Skip to content

Commit

Permalink
v0.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
xyluo25 committed Mar 3, 2024
1 parent 56e84a5 commit 94f9cb7
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 102 deletions.
2 changes: 1 addition & 1 deletion pyufunc/pkg_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


# **** Package Info **** #
pkg_version = "0.2.1"
pkg_version = "0.2.2"
pkg_name = "pyufunc"
pkg_author = "Mr. Xiangyong Luo, Dr. Xuesong Simon Zhou"
pkg_email = "luoxiangyong01@gmail.com, xzhou74@asu.edu"
Expand Down
2 changes: 0 additions & 2 deletions pyufunc/util_geo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
calc_distance_on_unit_sphere,
find_closest_point,
get_coordinates_from_geom,
find_closest_points,
find_k_nearest_points,
)

Expand All @@ -22,6 +21,5 @@
'calc_distance_on_unit_sphere',
'find_closest_point',
'get_coordinates_from_geom',
'find_closest_points',
'find_k_nearest_points',
"gmns_geo"]
111 changes: 18 additions & 93 deletions pyufunc/util_geo/_geo_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,103 +261,18 @@ def get_coordinates_from_geom(geom_obj: Union[Point, MultiPoint, LineString, Mul

@requires("shapely")
@func_running_time
def find_closest_points(pts: Union[Point, MultiPoint, LineString, MultiLineString,
Polygon, MultiPolygon, GeometryCollection],
geom_obj: Union[Point, MultiPoint, LineString, MultiLineString,
Polygon, MultiPolygon, GeometryCollection],
radius: float,
k_closest: int = 0) -> dict:
"""Find the closest points from a list of points to a geometry object (points) within a given radius.
Note:
This is equivalent to function: find_k_nearest_points.
Args:
pts (shapely.geometry): the list of points to start with
geom_obj (shapely.geometry): the geometry object to be projected to
radius (float): search radius for each target point. Unit in meters.
k_closest (int): k closest points for each starting point within the radius constraint.
If k_closest is 0, return all points within the radius. Defaults to 0.
Returns:
dict: the closest points for each point within the radius constraint
Example:
>>> from shapely.geometry import Point, MultiPoint
>>> pts = MultiPoint([(1, 1), (2, 2), (3, 3)])
>>> geom = Point(1, 1)
>>> find_closest_points(pts, geom, 2)
{POINT (1 1): [POINT (1 1), POINT (2 2): [POINT (1 1)], POINT (3 3): []}
>>> find_closest_points(pts, geom, 1, k_closest=2)
{POINT (1 1): [POINT (1 1), POINT (2 2): [POINT (1 1)], POINT (3 3): []}
"""

# import required modules
from shapely.geometry import (Point, MultiPoint, LineString, MultiLineString,
Polygon, MultiPolygon, GeometryCollection)

# TDD: Test-Driven Development, check data types of input arguments
typing_set = (Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection)
assert isinstance(pts, typing_set), (
"The input pts should be a shapely.geometry.base.BaseGeometry object.")
assert isinstance(geom_obj, typing_set), (
"The input pts should be a shapely.geometry.base.BaseGeometry object. object.")
assert isinstance(radius, (float, int)), "The input radius should be a float, int, or None object."
assert isinstance(k_closest, int), "The input k_closest should be an int object."

if k_closest < 0:
raise ValueError("The input k_closest should be a non-negative integer.")

# get the coordinates of the starting point / points
pts_coords = get_coordinates_from_geom(pts)

# create a buffer for each starting point with the given radius in meters
pts_coords_buffer = [Polygon(create_circle_at_point_with_radius(coord, radius)["coordinates"])
for coord in pts_coords]

# get the coordinates of the geometry object and create a multipoint object for the geometry object
geom_pts_coords = get_coordinates_from_geom(geom_obj)
geom_pts = MultiPoint(geom_pts_coords)

# find the closest points for each starting point within the buffer
closest_points = {}

for coord, pt_buffer in zip(pts_coords, pts_coords_buffer):
# find the intersection between the buffer and the geometry object
intersected_pts = pt_buffer.intersection(geom_pts)

# coord point
pt = Point(coord)

if intersected_pts.is_empty:
closest_points[pt] = []
elif isinstance(intersected_pts, Point):
closest_points[pt] = [intersected_pts]
else:
closest_points[pt] = sorted(intersected_pts.geoms, key=functools.partial(calc_distance_on_unit_sphere, pt))

if k_closest > 0:
closest_points = {k: v[:k_closest] for k, v in closest_points.items()}

return closest_points


@requires("shapely")
def find_k_nearest_points(pts: Union[Point, MultiPoint, LineString, MultiLineString,
Polygon, MultiPolygon, GeometryCollection],
geom_obj: Union[Point, MultiPoint, LineString, MultiLineString,
Polygon, MultiPolygon, GeometryCollection],
radius: float,
k_nearest: int = 0) -> dict:
"""Find the k nearest points from a list of points to a geometry object (points) within a given radius.
Note:
This is equivalent to function: find_closest_points.
Args:
pts (shapely.geometry): the list of points to start with
geom_obj (shapely.geometry): the geometry object to be projected to
radius (float): search radius for each target point. Unit in meters.
radius (float): search radius for each target point, must be greater than 0. Unit in meters.
k_nearest (int, optional): the k nearest points within radius. If it's 0, return all points within the radius.
Defaults to 0.
Expand All @@ -378,26 +293,35 @@ def find_k_nearest_points(pts: Union[Point, MultiPoint, LineString, MultiLineStr
"The input pts should be a shapely.geometry.base.BaseGeometry object.")
assert isinstance(geom_obj, typing_set), (
"The input pts should be a shapely.geometry.base.BaseGeometry object. object.")
assert isinstance(radius, (float, int)), "The input radius should be a float, int, or None object."
assert isinstance(radius, (float, int)), "The input radius should be a float, int object."
assert isinstance(k_nearest, int), "The input k_nearest should be an int object."

if k_nearest < 0:
raise ValueError("The input k_nearest should be a non-negative integer.")

if radius <= 0:
raise ValueError("The input radius should be a positive number.")

# get the coordinates of the starting point / points
pts_coords = get_coordinates_from_geom(pts)

# create a buffer for each starting point with the given radius in meters
pts_coords_buffer = [Polygon(create_circle_at_point_with_radius(coord, radius)["coordinates"])
for coord in pts_coords]

# get the coordinates of the geometry object and create a multipoint object for the geometry object
geom_pts_coords = get_coordinates_from_geom(geom_obj)
geom_pts = MultiPoint(geom_pts_coords)

# find the closest points for each starting point within the buffer
# create empty dictionary to store the closest points for each starting point
closest_points = {}

# for radius > 0, crate a buffer for each starting point with the given radius in meters
# print out unit of radius
print(f" Radius unit: {radius} meters")

# create a buffer for each starting point with the given radius in meters
pts_coords_buffer = [Polygon(
create_circle_at_point_with_radius(coord, radius)["coordinates"])
for coord in pts_coords]

# find the closest points for each starting point within the buffer
for coord, pt_buffer in zip(pts_coords, pts_coords_buffer):
# find the intersection between the buffer and the geometry object
intersected_pts = pt_buffer.intersection(geom_pts)
Expand All @@ -410,7 +334,8 @@ def find_k_nearest_points(pts: Union[Point, MultiPoint, LineString, MultiLineStr
elif isinstance(intersected_pts, Point):
closest_points[pt] = [intersected_pts]
else:
closest_points[pt] = sorted(intersected_pts.geoms, key=functools.partial(calc_distance_on_unit_sphere, pt))
closest_points[pt] = sorted(intersected_pts.geoms,
key=functools.partial(calc_distance_on_unit_sphere, pt))

if k_nearest > 0:
closest_points = {k: v[:k_nearest] for k, v in closest_points.items()}
Expand Down
5 changes: 2 additions & 3 deletions utility_function_by_category.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Note: we may not update available functions in time, please run code below to ch
pyufunc.show_util_func_by_category()
```

Available utility functions in pyUFunc (53):
Available utility functions in pyUFunc (52):

- util_common:
- show_docstring_headers
Expand Down Expand Up @@ -45,7 +45,6 @@ Available utility functions in pyUFunc (53):
- calc_distance_on_unit_sphere
- find_closest_point
- get_coordinates_from_geom
- find_closest_points
- find_k_nearest_points
- gmns_geo

Expand Down Expand Up @@ -74,11 +73,11 @@ Available utility functions in pyUFunc (53):

- pkg_utils:
- import_package
- requires
- func_running_time
- func_time
- get_user_defined_func
- is_user_defined_func
- is_module_importable
- requires
- show_util_func_by_category
- show_util_func_by_keyword
5 changes: 2 additions & 3 deletions utility_function_by_keyword.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ Note: we may not update available functions in time, please run code below to ch
pyufunc.show_util_func_by_keyword()
```

Available utility functions in pyUFunc (53):
Available utility functions in pyUFunc (52):

- non-keywords:
- gmns_geo
- path2linux
- path2uniform
- import_package
- requires
- func_running_time
- func_time
- requires

- show:
- show_docstring_headers
Expand Down Expand Up @@ -57,7 +57,6 @@ Available utility functions in pyUFunc (53):

- find:
- find_closest_point
- find_closest_points
- find_k_nearest_points

- calc:
Expand Down

0 comments on commit 94f9cb7

Please sign in to comment.