-
Notifications
You must be signed in to change notification settings - Fork 4
Featureclasses #145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Featureclasses #145
Changes from all commits
e9ffed4
68d9b39
4120510
1c338b7
af83601
82058b8
b062d08
c1b1fae
42903a0
bca3b69
b033fc3
91570d6
dae9491
28ca429
90b8c5d
f2fae54
f120060
fa27e38
00a1c16
59ec916
e5a2fce
c3b55b1
79adb37
c54e401
d16fc8b
d7814fe
c90fdbc
5de49ac
f525470
e96e3eb
87a697c
944656f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,16 +6,19 @@ | |
|
|
||
| import json | ||
| import re | ||
| from datetime import datetime | ||
| from typing import cast, Any, Dict, List, Optional, Union | ||
|
|
||
| from geostructures.collections import FeatureCollection | ||
| from geostructures.structures import GeoPolygon, GeoPoint, GeoLineString | ||
| from geostructures.multistructures import MultiGeoPoint, MultiGeoPolygon, MultiGeoLineString | ||
| from geostructures.time import TimeInterval | ||
| from geostructures.typing import GeoShape, SimpleShape | ||
|
|
||
|
|
||
| _PARSER_MAP: Dict[str, SimpleShape] = { | ||
| 'POINT': GeoPoint, | ||
| 'POINTGEOMETRY': GeoPoint, | ||
| 'LINESTRING': GeoLineString, | ||
| 'POLYGON': GeoPolygon, | ||
| 'MULTIPOINT': MultiGeoPoint, | ||
|
|
@@ -24,6 +27,153 @@ | |
| } | ||
|
|
||
|
|
||
| def _get_datetime_pandas(start_time, end_time): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _PARSER_MAP not updated with new types that can show up |
||
| """ | ||
| Converts pandas Timestamps to Python datetime objects and returns a TimeInterval. | ||
|
|
||
| Args: | ||
| start_time (pd.Timestamp or None): The start time. | ||
| end_time (pd.Timestamp or None): The end time. | ||
|
|
||
| Returns: | ||
| TimeInterval: The time interval representing the start and end time. | ||
| """ | ||
| import pandas as pd | ||
| from geostructures.time import TimeInterval | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move TimeInterval to top imports |
||
|
|
||
| if pd.notnull(start_time) or pd.notnull(end_time): | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's take a quick re-look at this block. If start_time/end_time is not null but is also not a timestamp it could cause issues |
||
| if isinstance(start_time, pd.Timestamp): | ||
| start_time = start_time.to_pydatetime() | ||
|
|
||
| if isinstance(end_time, pd.Timestamp): | ||
| end_time = end_time.to_pydatetime() | ||
|
|
||
| return TimeInterval(start_time, end_time) | ||
|
|
||
|
|
||
| def parse_arcgis_featureclass( | ||
| row, | ||
| columns, | ||
| time_start_property: Optional[Union[str, 'datetime']] = None, | ||
| time_end_property: Optional[Union[str, 'datetime']] = None, | ||
| time_fmt: Optional[Union[str, List[str]]] = None, | ||
| ) -> GeoShape: | ||
| """ | ||
| Parses an ArcGIS feature class row into a geospatial structure. | ||
|
|
||
| Args: | ||
| row: | ||
| The row from an ArcGIS feature class, typically obtained using an arcgis GeoAccessor. | ||
|
|
||
| columns: | ||
| List of column names to extract attribute values from the row. | ||
|
|
||
| time_start_property: | ||
| Optional; the column name or datetime representing the start time. | ||
|
|
||
| time_end_property: | ||
| Optional; the column name or datetime representing the end time. | ||
|
|
||
| time_fmt: | ||
| Optional; the format or list of formats for parsing time strings. | ||
|
|
||
| Returns: | ||
| A geospatial object parsed from the feature class row, with attributes and time interval. | ||
|
|
||
| Raises: | ||
| ValueError: If the geometry type is not supported. | ||
| """ | ||
| geometry = row.SHAPE | ||
| geometry_type_str = type(geometry).__name__.upper() | ||
|
|
||
| if geometry_type_str not in _PARSER_MAP: | ||
| raise ValueError(f'Unsupported geometry type: {geometry_type_str}.') | ||
|
|
||
| parser = _PARSER_MAP[geometry_type_str] | ||
| properties = {col: getattr(row, col) for col in columns} | ||
| time_start_value, time_end_value = None, None | ||
| if time_start_property is not None: | ||
| time_start_value = getattr(row, time_start_property, None) | ||
|
|
||
| if time_end_property is not None: | ||
| time_end_value = getattr(row, time_end_property, None) | ||
|
|
||
| dt = None | ||
| if time_start_value and isinstance(time_start_value, str): | ||
| dt = TimeInterval.from_str(time_start_value, time_end_value, time_fmt) | ||
|
|
||
| elif time_start_value: | ||
| dt = TimeInterval(time_start_value, time_end_value) | ||
|
|
||
| return parser.from_featureclass( | ||
| geometry, | ||
| dt=dt, | ||
| properties=properties | ||
| ) | ||
|
|
||
|
|
||
| def parse_arcpy_featureclass( | ||
| row, | ||
| fields, | ||
| time_start_property: Optional[Union[str, 'datetime']] = None, | ||
| time_end_property: Optional[Union[str, 'datetime']] = None, | ||
| time_fmt: Optional[Union[str, List[str]]] = None, | ||
| ) -> GeoShape: | ||
| """ | ||
| Parses an ArcGIS feature class row into a geospatial structure. | ||
|
|
||
| Args: | ||
| row: The row from an ArcGIS feature class, typically obtained using an arcpy cursor. | ||
| fields: List of column names to extract attribute values from the row. | ||
| time_start_property: Optional; the column name or datetime representing the start time. | ||
| time_end_property: Optional; the column name or datetime representing the end time. | ||
| time_fmt: Optional; the format or list of formats for parsing time strings. | ||
|
|
||
| Returns: | ||
| A geospatial object parsed from the feature class row, with attributes and time interval. | ||
|
|
||
| Raises: | ||
| ValueError: If the geometry type is not supported. | ||
| """ | ||
| geometry_index = fields.index('SHAPE@') | ||
| time_start_index, time_end_index = None, None | ||
|
|
||
| if time_start_property in fields: | ||
| time_start_index = fields.index(time_start_property) | ||
|
|
||
| if time_end_property in fields: | ||
| time_end_index = fields.index(time_end_property) | ||
|
|
||
| geometry = row[geometry_index] | ||
| geometry_type_str = type(geometry).__name__.upper() | ||
|
|
||
| if geometry_type_str not in _PARSER_MAP: | ||
| raise ValueError(f'Unsupported geometry type: {geometry_type_str}.') | ||
|
|
||
| parser = _PARSER_MAP[geometry_type_str] | ||
| properties = dict(zip(fields, row)) | ||
| del properties['SHAPE@'] | ||
| time_start_value, time_end_value = None, None | ||
| if time_start_value is not None: | ||
| time_start_value = row[time_start_index] | ||
|
|
||
| if time_end_value is not None: | ||
| time_end_value = row[time_end_index] | ||
|
|
||
| dt = None | ||
| if time_start_value and isinstance(time_start_value, str): | ||
| dt = TimeInterval.from_str(time_start_value, time_end_value, time_fmt) | ||
|
|
||
| elif time_start_value: | ||
| dt = TimeInterval(time_start_value, time_end_value) | ||
|
|
||
| return parser.from_featureclass( | ||
| geometry, | ||
| dt=dt, | ||
| properties=properties | ||
| ) | ||
|
|
||
|
|
||
| def parse_fastkml( | ||
| kml, | ||
| _shapes: Optional[List[GeoShape]] = None, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a docstring