Skip to content

Commit

Permalink
add coordinates class
Browse files Browse the repository at this point in the history
  • Loading branch information
cleder committed May 1, 2024
1 parent eb1667a commit b7bdb78
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 28 deletions.
2 changes: 1 addition & 1 deletion fastkml/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"name={self.name!r}, "
f"type={self.type!r}, "
f"type={self.type}, "
f"display_name={self.display_name!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down
120 changes: 114 additions & 6 deletions fastkml/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from typing import List
from typing import Optional
from typing import Sequence
from typing import Tuple
from typing import Union
from typing import cast

Expand All @@ -30,11 +31,13 @@
from pygeoif.factories import shape
from pygeoif.types import GeoCollectionType
from pygeoif.types import GeoType
from pygeoif.types import LineType
from pygeoif.types import Point2D
from pygeoif.types import Point3D

from fastkml import config
from fastkml.base import _BaseObject
from fastkml.base import _XMLObject
from fastkml.enums import AltitudeMode
from fastkml.enums import Verbosity
from fastkml.exceptions import KMLParseError
Expand All @@ -44,6 +47,7 @@
from fastkml.helpers import subelement_bool_kwarg
from fastkml.helpers import subelement_enum_kwarg
from fastkml.registry import RegistryItem
from fastkml.registry import known_types
from fastkml.registry import registry
from fastkml.types import Element

Expand Down Expand Up @@ -71,6 +75,110 @@
AnyGeometryType = Union[GeometryType, MultiGeometryType]


def coordinates_subelement(
obj: _XMLObject,
*,
element: Element,
attr_name: str,
node_name: str,
precision: Optional[int],
verbosity: Optional[Verbosity],
) -> None:
"""
Set the value of an attribute from a subelement with a text node.
Args:
----
obj (_XMLObject): The object from which to retrieve the attribute value.
element (Element): The parent element to add the subelement to.
attr_name (str): The name of the attribute to retrieve the value from.
node_name (str): The name of the subelement to create.
precision (Optional[int]): The precision of the attribute value.
verbosity (Optional[Verbosity]): The verbosity level.
Returns:
-------
None
"""
if getattr(obj, attr_name, None):
p = precision if precision is not None else 6
coordinates = getattr(obj, attr_name)
if len(coordinates[0]) == 2:
tuples = (f"{c[0]:.{p}f},{c[1]:.{p}f}" for c in coordinates)
elif len(coordinates[0]) == 3:
tuples = (f"{c[0]:.{p}f},{c[1]:.{p}f},{c[2]:.{p}f}" for c in coordinates)
else:
msg = f"Invalid dimensions in coordinates '{coordinates}'"
raise KMLWriteError(msg)
element.text = " ".join(tuples)


def subelement_coordinates_kwarg(
*,
element: Element,
ns: str,
name_spaces: Dict[str, str],
node_name: str,
kwarg: str,
classes: Tuple[known_types, ...],
strict: bool,
) -> Dict[str, LineType]:
# Clean up badly formatted tuples by stripping
# space following commas.
try:
latlons = re.sub(r", +", ",", element.text.strip()).split()
except AttributeError:
return {}
try:
return {
kwarg: [ # type: ignore[dict-item]
tuple(float(c) for c in latlon.split(",")) for latlon in latlons
],
}
except ValueError as error:
handle_invalid_geometry_error(
error=error,
element=element,
strict=strict,
)
return {}


class Coordinates(_XMLObject):

def __init__(
self,
*,
ns: Optional[str] = None,
name_spaces: Optional[Dict[str, str]] = None,
coords: Optional[LineType],
**kwargs: Any,
):
super().__init__(ns=ns, name_spaces=name_spaces, **kwargs)
self.coords = coords if coords else []

def __bool__(self) -> bool:
return bool(self.coords)

@classmethod
def get_tag_name(cls) -> str:
"""Return the tag name."""
return cls.__name__.lower()


registry.register(
Coordinates,
item=RegistryItem(
classes=(LineType,), # type: ignore[arg-type]
attr_name="coords",
node_name="coordinates",
get_kwarg=subelement_coordinates_kwarg,
set_element=coordinates_subelement,
),
)


def handle_invalid_geometry_error(
*,
error: Exception,
Expand Down Expand Up @@ -155,7 +263,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -331,7 +439,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -409,7 +517,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -482,7 +590,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -544,7 +652,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -724,7 +832,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down
4 changes: 2 additions & 2 deletions fastkml/gx.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"track_items={self.track_items!r}, "
f"**kwargs={self._get_splat()!r},"
Expand Down Expand Up @@ -402,7 +402,7 @@ def __repr__(self) -> str:
f"target_id={self.target_id!r}, "
f"extrude={self.extrude!r}, "
f"tessellate={self.tessellate!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"geometry={self.geometry!r}, "
f"tracks={self.tracks!r}, "
f"interpolate={self.interpolate!r}, "
Expand Down
4 changes: 2 additions & 2 deletions fastkml/links.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"href={self.href!r}, "
f"refresh_mode={self.refresh_mode!r}, "
f"refresh_mode={self.refresh_mode}, "
f"refresh_interval={self.refresh_interval!r}, "
f"view_refresh_mode={self.view_refresh_mode!r}, "
f"view_refresh_mode={self.view_refresh_mode}, "
f"view_refresh_time={self.view_refresh_time!r}, "
f"view_bound_scale={self.view_bound_scale!r}, "
f"view_format={self.view_format!r}, "
Expand Down
6 changes: 3 additions & 3 deletions fastkml/overlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ def __repr__(self) -> str:
f"tile_size={self.tile_size!r}, "
f"max_width={self.max_width!r}, "
f"max_height={self.max_height!r}, "
f"grid_origin={self.grid_origin!r}, "
f"grid_origin={self.grid_origin}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down Expand Up @@ -612,7 +612,7 @@ def __repr__(self) -> str:
f"view_volume={self.view_volume!r}, "
f"image_pyramid={self.image_pyramid!r}, "
f"point={self.point!r}, "
f"shape={self.shape!r}, "
f"shape={self.shape}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down Expand Up @@ -917,7 +917,7 @@ def __repr__(self) -> str:
f"draw_order={self.draw_order!r}, "
f"icon={self.icon!r}, "
f"altitude={self.altitude!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"lat_lon_box={self.lat_lon_box!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down
18 changes: 9 additions & 9 deletions fastkml/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"color={self.color!r}, "
f"color_mode={self.color_mode!r}, "
f"color_mode={self.color_mode}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down Expand Up @@ -264,8 +264,8 @@ def __repr__(self) -> str:
f"name_spaces={self.name_spaces!r}, "
f"x={self.x!r}, "
f"y={self.y!r}, "
f"xunits={self.xunits!r}, "
f"yunits={self.yunits!r}, "
f"xunits={self.xunits}, "
f"yunits={self.yunits}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down Expand Up @@ -380,7 +380,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"color={self.color!r}, "
f"color_mode={self.color_mode!r}, "
f"color_mode={self.color_mode}, "
f"scale={self.scale!r}, "
f"heading={self.heading!r}, "
f"icon={self.icon!r}, "
Expand Down Expand Up @@ -478,7 +478,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"color={self.color!r}, "
f"color_mode={self.color_mode!r}, "
f"color_mode={self.color_mode}, "
f"width={self.width!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -550,7 +550,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"color={self.color!r}, "
f"color_mode={self.color_mode!r}, "
f"color_mode={self.color_mode}, "
f"fill={self.fill!r}, "
f"outline={self.outline!r}, "
f"**kwargs={self._get_splat()!r},"
Expand Down Expand Up @@ -626,7 +626,7 @@ def __repr__(self) -> str:
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"color={self.color!r}, "
f"color_mode={self.color_mode!r}, "
f"color_mode={self.color_mode}, "
f"scale={self.scale!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -742,7 +742,7 @@ def __repr__(self) -> str:
f"bg_color={self.bg_color!r}, "
f"text_color={self.text_color!r}, "
f"text={self.text!r}, "
f"display_mode={self.display_mode!r}, "
f"display_mode={self.display_mode}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down Expand Up @@ -917,7 +917,7 @@ def __repr__(self) -> str:
f"name_spaces={self.name_spaces!r}, "
f"id={self.id!r}, "
f"target_id={self.target_id!r}, "
f"key={self.key!r}, "
f"key={self.key}, "
f"style={self.style!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down
2 changes: 1 addition & 1 deletion fastkml/times.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def __repr__(self) -> str:
return (
f"{self.__class__.__module__}.{self.__class__.__name__}("
f"dt={self.dt!r}, "
f"resolution={self.resolution!r}, "
f"resolution={self.resolution}, "
")"
)

Expand Down
8 changes: 4 additions & 4 deletions fastkml/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def __repr__(self) -> str:
f"altitude={self.altitude!r}, "
f"heading={self.heading!r}, "
f"tilt={self.tilt!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"time_primitive={self.times!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -279,7 +279,7 @@ def __repr__(self) -> str:
f"heading={self.heading!r}, "
f"tilt={self.tilt!r}, "
f"roll={self.roll!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"time_primitive={self.times!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -349,7 +349,7 @@ def __repr__(self) -> str:
f"heading={self.heading!r}, "
f"tilt={self.tilt!r}, "
f"range={self.range!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"time_primitive={self.times!r}, "
f"**kwargs={self._get_splat()!r},"
")"
Expand Down Expand Up @@ -419,7 +419,7 @@ def __repr__(self) -> str:
f"west={self.west!r}, "
f"min_altitude={self.min_altitude!r}, "
f"max_altitude={self.max_altitude!r}, "
f"altitude_mode={self.altitude_mode!r}, "
f"altitude_mode={self.altitude_mode}, "
f"**kwargs={self._get_splat()!r},"
")"
)
Expand Down
Loading

0 comments on commit b7bdb78

Please sign in to comment.