Skip to content

Commit

Permalink
Merge pull request #41 from pyturf/refactor_invariant
Browse files Browse the repository at this point in the history
Add get geometry type function
  • Loading branch information
diogomatoschaves committed Jul 16, 2020
2 parents 98152b6 + 1c19d7b commit 96a7492
Show file tree
Hide file tree
Showing 30 changed files with 816 additions and 114 deletions.
6 changes: 6 additions & 0 deletions docs/source/modules/meta.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ Get geometry from features
--------------------------

.. autofunction:: turf.invariant.get_geometry_from_features


Get geometry type from features
-------------------------------

.. autofunction:: turf.invariant.get_geometry_type
46 changes: 24 additions & 22 deletions turf/boolean_point_in_polygon/_boolean_point_in_polygon.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from typing import Sequence, Union, Dict

from turf.helpers import Feature
from turf.invariant import get_coords_from_features, get_geometry_from_features
from turf.invariant import (
get_coords_from_features,
get_geometry_from_features,
get_geometry_type,
)
from turf.bbox import bbox as bounding_box
from turf.utils.error_codes import error_code_messages
from turf.utils.exceptions import InvalidInput
Expand Down Expand Up @@ -31,7 +35,6 @@ def boolean_point_in_polygon(
the point is inside the polygon otherwise False.
:return: True if the Point is inside the Polygon; False otherwise
"""

if not isinstance(options, dict):
options = {}

Expand All @@ -40,39 +43,38 @@ def boolean_point_in_polygon(
point_coords = get_coords_from_features(point, ["Point"])
polygon_coords = get_coords_from_features(polygon, valid_polygons)

try:
polygon_geom_type = get_geometry_from_features(polygon, valid_polygons).get(
"type"
)
if not polygon_geom_type:
raise AttributeError
except AttributeError:
raise InvalidInput(error_code_messages["InvalidGeometry"](valid_polygons))
geometry_type = get_geometry_type(polygon, valid_polygons)

bbox = bounding_box(polygon)

if not in_bbox(point_coords, bbox):
return False

if polygon_geom_type == "Polygon":
if isinstance(geometry_type, str):
geometry_type = [geometry_type]
polygon_coords = [polygon_coords]

inside_polygon = False

for polygon in polygon_coords:
# check if it is in the outer ring first
if in_ring(point_coords, polygon[0], ignore_boundary):
in_hole = False
for geo_type, poly_coords in zip(geometry_type, polygon_coords):

if geo_type == "Polygon":
poly_coords = [poly_coords]

for polygon in poly_coords:
# check if it is in the outer ring first
if in_ring(point_coords, polygon[0], ignore_boundary):
in_hole = False

for ring in polygon[1:]:
if in_ring(point_coords, ring, not ignore_boundary):
in_hole = True
for ring in polygon[1:]:
if in_ring(point_coords, ring, not ignore_boundary):
in_hole = True

if not in_hole:
inside_polygon = True
if not in_hole:
inside_polygon = True

if inside_polygon:
break
if inside_polygon:
break

return inside_polygon

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def test_boolean_point_in_polygon_boundary(self, boundary, poly, points):
),
pytest.param(
point([0, 1]),
[[[0, 1], [1, 2], [2, 3], [0, 1]]],
[[0, 1], [1, 2], [2, 3], [0, 1]],
error_code_messages["InvalidGeometry"](allowed_types_polygon),
id="InvalidGeometry-input_must_have_a_geometry",
),
Expand Down
1 change: 1 addition & 0 deletions turf/invariant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
get_coords_from_features,
get_coords_from_geometry,
get_geometry_from_features,
get_geometry_type,
)
118 changes: 116 additions & 2 deletions turf/invariant/_invariant.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Sequence, Callable, Set, List, Union
from typing import Any, Sequence, Callable, Set, List, Tuple, Union

from turf.helpers import (
Feature,
Expand All @@ -24,6 +24,14 @@
"Polygon",
"MultiPolygon",
]
allowed_features_default = (
Point,
MultiPoint,
LineString,
MultiLineString,
Polygon,
MultiPolygon,
)


def _process_list_input(
Expand All @@ -41,7 +49,6 @@ def _process_list_input(
:param raise_exception: if an exception should be raised or if it should be silent
:return: list with extracted coords
"""

dim = get_input_dimensions(input_value)

allowed_dimensions = {dimensions.get(type_, None) for type_ in allowed_types}
Expand Down Expand Up @@ -173,6 +180,113 @@ def get_geometry_from_features(features: Any, allowed_types: Sequence = None) ->
raise InvalidInput(error_code_messages["InvalidGeometry"](allowed_types))


def get_geometry_type(
features: Any, allowed_types: Sequence = None
) -> Union[str, Tuple[str]]:
"""
Gets the Geometry type from Features. Features must be a GeoJSON,
a Feature object, FeatureCollection a Dictionary, List or a Tuple, otherwise it raises an exception.
:param features: Any input value(s)
:param allowed_types: allowed Feature types
:return: str if one extracted geometry_type else tuple
"""
if not allowed_types:
allowed_features = [allowed_features_default, allowed_types_default]

else:

allowed_features = [
tuple(
[
feature
for feature in allowed_features_default
if feature.__name__ in allowed_types
]
),
allowed_types,
]

features = get_geometry_from_features(features, allowed_features[1])

if isinstance(features, (dict, *allowed_features[0])):

geometry_type = _get_geometry_type_from_feature(features, allowed_features)

elif isinstance(features, (list, tuple)):

geometry_type = _get_geometry_type_from_list(features, allowed_features)

else:
raise InvalidInput(error_code_messages["InvalidGeometry"](allowed_features[1]))

if len(geometry_type) == 1:
geometry_type = geometry_type[0]

return geometry_type


def _get_geometry_type_from_feature(
features: Any, allowed_features: List[Union[Tuple, Sequence]]
) -> str:
"""
Gets the Geometry type from a Features. Features must be a GeoJSON,
a Feature object, FeatureCollection or a Dictionary, otherwise it raises an exception.
:param features: Any input value(s) except a list
:return: tuple with extracted geometry types
"""
geometry_type = features.get("type", None)

if geometry_type not in allowed_features[1]:
raise InvalidInput(error_code_messages["InvalidGeometry"](allowed_features[1]))

return geometry_type


def _get_geometry_type_from_list(
features: List, allowed_features: List[Union[Tuple, Sequence]]
) -> Tuple[str]:
"""
Gets the Geometry type from a List, otherwise it raises an exception.
:param features: input feature as a list
:return: tuple with extracted geometry types
"""
geometry_type = tuple()

n_dim = get_input_dimensions(features)

if n_dim == 1 and all(
isinstance(el, (dict, *allowed_features[0])) for el in features
):
return tuple(
map(
lambda geom: _get_geometry_type_from_feature(geom, allowed_features),
features,
)
)

elif all(isinstance(el, (list, tuple, int, float)) for el in features):

feature_type = [
k for k, v in dimensions.items() if v == n_dim and k in allowed_features[1]
]
if len(feature_type) == 1:

geometry_type += (feature_type[0],)

else:
raise InvalidInput(
error_code_messages["InvalidGeometry"](allowed_features[1])
)

else:
raise InvalidInput(error_code_messages["InvalidGeometry"](allowed_features[1]))

return geometry_type


def get_coords_from_features(features: Any, allowed_types: Sequence = None) -> List:
"""
Retrieves coords from Features. Features must be a GeoJSON,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@
}
}
]
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
]
}
}]
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
]
}
}]
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@
]
}
}]
]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
4.833351373672485,
45.760809294695534
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
4.8331475257873535,
45.760296567821456
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
4.833984374999999,
45.76073818687033
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
4.834005832672119,
45.76022171678877
]
}
},
{
"type": "Feature",
"properties": {"allowed_types": ["LineString"]},
"geometry": {
"type": "LineString",
"coordinates": [
[
4.86020565032959,
45.76884015325622
],
[
4.85994815826416,
45.749558161214516
]
]
}
}
]

0 comments on commit 96a7492

Please sign in to comment.