Skip to content

Commit

Permalink
Bug: Add support for Point shape to geometric_to_pixel (#48)
Browse files Browse the repository at this point in the history
add geographic_point_to_pixel
  • Loading branch information
mackenzie-grimes-noaa authored Jan 22, 2024
1 parent bb4da5e commit c14d187
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 31 deletions.
6 changes: 3 additions & 3 deletions python/idsse_common/idsse/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ def round_half_away(number: Scalar, precision: int = 0) -> Scalar:
is_less_than_half = abs(factored_number - math.trunc(factored_number)) < 0.5

rounded_number = (
_round_toward_zero(factored_number) if is_less_than_half
else _round_away_from_zero(factored_number)
) / factor
_round_toward_zero(factored_number) if is_less_than_half
else _round_away_from_zero(factored_number)
) / factor
return int(rounded_number) if precision == 0 else float(rounded_number)


Expand Down
71 changes: 47 additions & 24 deletions python/idsse_common/idsse/common/vectaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@


def rasterize(
geometry: str | Geometry,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
geometry: str | Geometry,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
) -> tuple[numpy.array]:
"""Takes a geographic geometry (specified with lon/lat) and determines all the
associated pixels in the translated space (as specified by grid_proj).
Expand Down Expand Up @@ -74,9 +74,9 @@ def rasterize(


def rasterize_point(
point: str | Coord | Point,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
point: str | Coord | Point,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
) -> tuple[numpy.array]:
"""Takes a geographic Point (specified with lon/lat) and determines the
associated pixel in the translated space (as specified by grid_proj).
Expand Down Expand Up @@ -111,9 +111,9 @@ def rasterize_point(


def rasterize_linestring(
linestring: str | Sequence[Coord] | LineString,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
linestring: str | Sequence[Coord] | LineString,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
) -> tuple[numpy.array]:
"""Takes a geographic LineString (specified with lon/lat) and determines all the
associated pixels in the translated space (as specified by grid_proj).
Expand Down Expand Up @@ -168,9 +168,9 @@ def rasterize_linestring(


def rasterize_polygon(
polygon: str | Sequence[Coords] | Polygon,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
polygon: str | Sequence[Coords] | Polygon,
grid_proj: GridProj | None = None,
rounding: RoundingMethod = RoundingMethod.FLOOR
) -> tuple[numpy.array]:
"""Takes a geographic Polygon (specified with lon/lat) and determines all the
associated pixels in the translated space (as specified by grid_proj).
Expand Down Expand Up @@ -228,6 +228,8 @@ def geographic_to_pixel(
Geometry: Shapely geometry of the same type as input geometry with vertices
defined by x,y pixels
"""
if isinstance(geo, Point):
return geographic_point_to_pixel(geo, grid_proj, rounding)
if isinstance(geo, LineString):
return geographic_linestring_to_pixel(geo, grid_proj, rounding)
if isinstance(geo, Polygon):
Expand All @@ -239,10 +241,34 @@ def geographic_to_pixel(
raise ValueError(f'Passed geometry is type:{type(geo)}, which is not of supported types')


def geographic_point_to_pixel(
point: Point,
grid_proj: GridProj,
rounding: RoundingMethod = None
) -> Point:
"""Map a Point specified in lat/lon space to geometry specified in pixel space
Args:
point (Point): Shapely geometry with vertices defined by lon,lat
grid_proj (GridProj): Projection plus pixel resolution
rounding (RoundingMethod, optional): One of None, 'floor', 'round'. Defaults to None.
Raises:
ValueError: If geometry is not a Point
Returns:
Point: Shapely Point with vertices defined by x,y pixels
"""
if not isinstance(point, Point):
raise ValueError(f'Geometry must be a Point but is a {type(point)}')

coords = grid_proj.map_geo_to_pixel(*list(zip(*point.coords)), rounding)
return Point(coords)


def geographic_linestring_to_pixel(
linestring: LineString | Sequence[Coord],
grid_proj: GridProj,
rounding: RoundingMethod | None = None
linestring: LineString | Sequence[Coord],
grid_proj: GridProj,
rounding: RoundingMethod | None = None
) -> LineString:
"""Map a LineString specified in lat/lon space to geometry specified in pixel space
Expand All @@ -263,17 +289,15 @@ def geographic_linestring_to_pixel(
else:
raise TypeError(f'Geometry must be a LineString but is a {type(linestring)}')

# coords = [grid_proj.map_geo_to_pixel(*ll, rounding) for ll in line_string.coords]
coords = list(zip(*grid_proj.map_geo_to_pixel(*list(zip(*coords)), rounding)))

pixel_linestring = LineString(coords)
return pixel_linestring
return LineString(coords)


def geographic_polygon_to_pixel(
poly: Polygon | Sequence[Coords],
grid_proj: GridProj,
rounding: RoundingMethod | None = None
poly: Polygon | Sequence[Coords],
grid_proj: GridProj,
rounding: RoundingMethod | None = None
) -> Polygon:
"""Map a Polygon specified in lat/lon space to geometry specified in pixel space
Expand Down Expand Up @@ -301,8 +325,7 @@ def geographic_polygon_to_pixel(
interiors = [list(zip(*grid_proj.map_geo_to_pixel(*list(zip(*interior.coords)), rounding)))
for interior in interiors]

pixel_poly = Polygon(exterior, holes=interiors)
return pixel_poly
return Polygon(exterior, holes=interiors)


def pixels_for_linestring(linestring: LineString) -> tuple[numpy.array]:
Expand Down Expand Up @@ -345,7 +368,7 @@ def _make_numpy(points: Sequence[Pixel]) -> tuple[numpy.ndarray]:
Returns:
Tuple[numpy.ndarray]: Same coordinates but restructured
"""
return tuple(numpy.array(dim_coord, dtype=numpy.int64) for dim_coord in map(list, zip(*points)))
return tuple(numpy.array(dim_coord, dtype=numpy.int64) for dim_coord in tuple(zip(*points)))


def _pixels_for_linestring(
Expand Down
24 changes: 20 additions & 4 deletions python/idsse_common/test/test_vectaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from idsse.common.grid_proj import GridProj
from idsse.common.vectaster import (geographic_to_pixel,
geographic_linestring_to_pixel,
geographic_point_to_pixel,
geographic_polygon_to_pixel,
from_wkt,
rasterize,
Expand All @@ -37,6 +38,14 @@ def grid_proj() -> GridProj:


# test
def test_geographic_point_to_pixel(grid_proj: GridProj):
point = from_wkt('POINT (-105 40)')
pixel_point = from_wkt('POINT (941.5576426719887 778.2701810387533)')
result = geographic_point_to_pixel(point, grid_proj)

assert result == pixel_point


def test_geographic_linestring_to_pixel(grid_proj: GridProj):
linestring = from_wkt('LINESTRING (-100 30, -110 40, -120 50)')
pixel_linestring = from_wkt('LINESTRING (1099.1941683923565 324.546444238068,'
Expand Down Expand Up @@ -64,18 +73,25 @@ def test_geographic_polygon_to_pixel(grid_proj: GridProj):


def test_geographic_to_pixel(monkeypatch: MonkeyPatch, grid_proj: GridProj):
point = from_wkt('POINT (-105 40)')
line_string = from_wkt('LINESTRING (-105 40, -110 40, -110 50)')
polygon = from_wkt('POLYGON ((-105 40, -110 40, -110 50, -105 50, -105 40))')

point_mock = Mock()
line_string_mock = Mock()
polygon_mock = Mock()
monkeypatch.setattr('idsse.common.vectaster.geographic_point_to_pixel', point_mock)
monkeypatch.setattr('idsse.common.vectaster.geographic_linestring_to_pixel', line_string_mock)
monkeypatch.setattr('idsse.common.vectaster.geographic_polygon_to_pixel', polygon_mock)

geographic_to_pixel(line_string, grid_proj)
line_string_mock.assert_called_once()
geographic_to_pixel(polygon, grid_proj)
polygon_mock.assert_called_once()
_ = geographic_to_pixel(point, grid_proj)
point_mock.assert_called_once_with(point, grid_proj, None)

_ = geographic_to_pixel(line_string, grid_proj)
line_string_mock.assert_called_once_with(line_string, grid_proj, None)

_ = geographic_to_pixel(polygon, grid_proj)
polygon_mock.assert_called_once_with(polygon, grid_proj, None)


def test_rasterize_point(grid_proj: GridProj):
Expand Down

0 comments on commit c14d187

Please sign in to comment.