Skip to content

Commit

Permalink
Fix processing of unspecified 'proj', 'geodesic', 'evenOdd' parameter…
Browse files Browse the repository at this point in the history
…s in ee.Geometry constructors.

PiperOrigin-RevId: 708375802
  • Loading branch information
Google Earth Engine Authors committed Jan 9, 2025
1 parent af6914c commit 5b8e9a3
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 42 deletions.
62 changes: 32 additions & 30 deletions python/ee/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,18 +187,19 @@ def Point(
coords: A list of two [x,y] coordinates in the given projection.
proj: The projection of this geometry, or EPSG:4326 if unspecified.
*args: For convenience, varargs may be used when all arguments are
numbers. This allows creating EPSG:4326 points, e.g.,
ee.Geometry.Point(lng, lat).
numbers. This allows creating EPSG:4326 points, e.g.,
ee.Geometry.Point(lng, lat).
**kwargs: Keyword args that accept "lon" and "lat" for backward-
compatibility.
compatibility.
Returns:
An ee.Geometry describing a point.
"""
init = Geometry._parseArgs(
'Point', 1,
Geometry._GetSpecifiedArgs((coords, proj) + args, ('lon', 'lat'),
**kwargs))
'Point',
1,
Geometry._GetArgs((coords, proj) + args, ('lon', 'lat'), **kwargs),
)
if not isinstance(init, computedobject.ComputedObject):
xy = init['coordinates']
if not isinstance(xy, (list, tuple)) or len(xy) != 2:
Expand Down Expand Up @@ -226,7 +227,7 @@ def MultiPoint(coords=_UNSPECIFIED, proj=_UNSPECIFIED, *args) -> Geometry:
Returns:
An ee.Geometry describing a MultiPoint.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj) + args)
all_args = Geometry._GetArgs((coords, proj) + args)
return Geometry(Geometry._parseArgs('MultiPoint', 2, all_args))

# pylint: disable=keyword-arg-before-vararg
Expand Down Expand Up @@ -270,10 +271,14 @@ def Rectangle(
An ee.Geometry describing a rectangular polygon.
"""
init = Geometry._parseArgs(
'Rectangle', 2,
Geometry._GetSpecifiedArgs(
'Rectangle',
2,
Geometry._GetArgs(
(coords, proj, geodesic, evenOdd) + args,
('xlo', 'ylo', 'xhi', 'yhi'), **kwargs))
('xlo', 'ylo', 'xhi', 'yhi'),
**kwargs,
),
)
if not isinstance(init, computedobject.ComputedObject):
# GeoJSON does not have a Rectangle type, so expand to a Polygon.
xy = init['coordinates']
Expand Down Expand Up @@ -419,8 +424,7 @@ def LineString(
Returns:
An ee.Geometry describing a LineString.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj, geodesic, maxError) +
args)
all_args = Geometry._GetArgs((coords, proj, geodesic, maxError) + args)
return Geometry(Geometry._parseArgs('LineString', 2, all_args))

# pylint: disable=keyword-arg-before-vararg
Expand Down Expand Up @@ -459,8 +463,7 @@ def LinearRing(
Returns:
A dictionary representing a GeoJSON LinearRing.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj, geodesic, maxError) +
args)
all_args = Geometry._GetArgs((coords, proj, geodesic, maxError) + args)
return Geometry(Geometry._parseArgs('LinearRing', 2, all_args))

# pylint: disable=keyword-arg-before-vararg
Expand Down Expand Up @@ -500,8 +503,7 @@ def MultiLineString(
Returns:
An ee.Geometry describing a MultiLineString.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj, geodesic, maxError) +
args)
all_args = Geometry._GetArgs((coords, proj, geodesic, maxError) + args)
return Geometry(Geometry._parseArgs('MultiLineString', 3, all_args))

# pylint: disable=keyword-arg-before-vararg
Expand Down Expand Up @@ -544,8 +546,9 @@ def Polygon(
Returns:
An ee.Geometry describing a polygon.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj, geodesic, maxError,
evenOdd) + args)
all_args = Geometry._GetArgs(
(coords, proj, geodesic, maxError, evenOdd) + args
)
return Geometry(Geometry._parseArgs('Polygon', 3, all_args))

# pylint: disable=keyword-arg-before-vararg
Expand Down Expand Up @@ -590,8 +593,10 @@ def MultiPolygon(
Returns:
An ee.Geometry describing a MultiPolygon.
"""
all_args = Geometry._GetSpecifiedArgs((coords, proj, geodesic, maxError,
evenOdd) + args)

all_args = Geometry._GetArgs(
(coords, proj, geodesic, maxError, evenOdd) + args
)
return Geometry(Geometry._parseArgs('MultiPolygon', 4, all_args))

@_utils.accept_opt_prefix('opt_encoder')
Expand Down Expand Up @@ -766,16 +771,16 @@ def _parseArgs(ctor_name: str, depth: int, args: Any) -> Dict[str, Any]:
keys.append('maxError')
keys.append('evenOdd')

if all(ee_types.isNumber(i) for i in args):
if all(ee_types.isNumber(i) or i == _UNSPECIFIED for i in args):
# All numbers, so convert them to a true array.
result['coordinates'] = args
result['coordinates'] = [i for i in args if i != _UNSPECIFIED]
else:
# Parse parameters by position.
if len(args) > len(keys):
raise ee_exception.EEException(
'Geometry constructor given extra arguments.')
for key, arg in zip(keys, args):
if arg is not None:
if arg is not None and arg != _UNSPECIFIED:
result[key] = arg

# Standardize the coordinates and test if they are simple enough for
Expand Down Expand Up @@ -865,17 +870,14 @@ def _fixDepth(depth: int, coords: Any) -> Any:
return coords

@staticmethod
def _GetSpecifiedArgs(
args, keywords: Tuple[str, ...] = (), **kwargs
) -> List[Any]:
"""Returns args, filtering out _UNSPECIFIED and checking for keywords."""
def _GetArgs(args, keywords: Tuple[str, ...] = (), **kwargs) -> List[Any]:
"""Returns all args, specified or not, checking for keywords."""
args = list(args)
if keywords:
args = list(args)
for i, keyword in enumerate(keywords):
if keyword in kwargs:
assert args[i] is _UNSPECIFIED
args[i] = kwargs[keyword]
return [i for i in args if i != _UNSPECIFIED]
return args

@staticmethod
def name() -> str:
Expand Down
18 changes: 6 additions & 12 deletions python/ee/tests/geometry_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,8 @@ def testLineString_kwargs(self):

geometry = ee.Geometry.LineString(coords, geodesic=True)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(True)},
{'coordinates': ee.List(coords), 'geodesic': True},
geometry.args,
)

Expand Down Expand Up @@ -246,9 +245,8 @@ def testLinearRing_kwargs(self):

geometry = ee.Geometry.LinearRing(coords, geodesic=geodesic)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(geodesic)},
{'coordinates': ee.List(coords), 'geodesic': geodesic},
geometry.args,
)

Expand Down Expand Up @@ -300,9 +298,8 @@ def testMultiLineString_kwargs(self):

geometry = ee.Geometry.MultiLineString(coords, geodesic=geodesic)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(geodesic)},
{'coordinates': ee.List(coords), 'geodesic': geodesic},
geometry.args,
)

Expand Down Expand Up @@ -409,9 +406,8 @@ def testMultiPolygon_kwargs(self):

geometry = ee.Geometry.MultiPolygon(coords, geodesic=geodesic)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(geodesic)},
{'coordinates': ee.List(coords), 'geodesic': geodesic},
geometry.args,
)

Expand Down Expand Up @@ -518,9 +514,8 @@ def testPolygon_kwargs(self):

geometry = ee.Geometry.Polygon(coords, geodesic=geodesic)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(geodesic)},
{'coordinates': ee.List(coords), 'geodesic': geodesic},
geometry.args,
)

Expand Down Expand Up @@ -582,9 +577,8 @@ def testRectangle_kwargs(self):

geometry = ee.Geometry.Rectangle(coords, geodesic=geodesic)
self.assertEqual(func, geometry.func)
# TODO: Should be geodesic=True, not crs.
self.assertEqual(
{'coordinates': ee.List(coords), 'crs': ee.Projection(geodesic)},
{'coordinates': ee.List(coords), 'geodesic': geodesic},
geometry.args,
)

Expand Down

0 comments on commit 5b8e9a3

Please sign in to comment.