Skip to content

Commit

Permalink
To support using shapely object to manipulate database geometry data. (
Browse files Browse the repository at this point in the history
…#75)

* To support using shapely obejct to manpulate database geometry data.

* Get rid of TYPE_CHECKING

* Add shapely geometry manpulate test
  • Loading branch information
wuwwen authored Nov 25, 2024
1 parent dda855e commit b4c4d9d
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 34 deletions.
1 change: 1 addition & 0 deletions .github/workflows/full_test_2024_1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install pytest
python -m pip install shapely
- name: Install mikepluspy
run: |
Expand Down
83 changes: 60 additions & 23 deletions mikeplus/datatableaccess.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,25 @@ def set_value(self, table_name, muid, column, value):
column name
value :
the value want to set
WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
Geometry can be set for the 'geometry' field of geometry based tables. e.g. Node and Link
Two types of data format are supported. One is wkt which is string format, another is shapely geometry object.
- WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
- shapely object is accept for geometry field. Please install shapely package first.
The supported geometry types are Point, LineString and Polygon
"""
if column.lower() == "geometry":
geom = GeoAPIHelper.GetIGeometryFromWKT(value)
wkt = None
if isinstance(value, str):
wkt = value
else:
shapely = self._get_shapely()
wkt = shapely.to_wkt(value)
geom = GeoAPIHelper.GetIGeometryFromWKT(wkt)
geomTable = IMuGeomTable(self._datatables[table_name])
geomTable.UpdateGeomByCommand(muid, geom)
else:
Expand All @@ -222,22 +232,32 @@ def set_values(self, table_name, muid, values):
muid
values : array
field values want to set
WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
Geometry can be set for the 'geometry' field of geometry based tables. e.g. Node and Link
Two types of data format are supported. One is wkt which is string format, another is shapely geometry object.
- WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
- shapely object is accept for geometry field. Please install shapely package first.
The supported geometry types are Point, LineString and Polygon
"""
value_dict = Dictionary[String, Object]()
for col in values:
if col.lower() == "geometry":
wkt = values[col]
geom_val = values[col]
wkt = None
if isinstance(geom_val, str):
wkt = geom_val
else:
shapely = self._get_shapely()
wkt = shapely.to_wkt(geom_val)
geom = GeoAPIHelper.GetIGeometryFromWKT(wkt)
geomTable = IMuGeomTable(self._datatables[table_name])
geomTable.UpdateGeomByCommand(muid, geom)
continue
value_dict[col] = values[col]
else:
value_dict[col] = values[col]
self._datatables[table_name].SetValuesByCommand(muid, value_dict)

def insert(self, table_name, muid, values=None):
Expand All @@ -251,19 +271,29 @@ def insert(self, table_name, muid, values=None):
muid
values : array, optional
the values want to insert, by default None
WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
Geometry can be set for the 'geometry' field of geometry based tables. e.g. Node and Link
Two types of data format are supported. One is wkt which is string format, another is shapely geometry object.
- WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.
Multiple geometry is not supported.
WTK example for point, line and polygon
- POINT (30 10)
- LINESTRING (30 10, 10 30, 40 40)
- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))
- shapely object is accept for geometry field. Please install shapely package first.
The supported geometry types are Point, LineString and Polygon
"""
value_dict = Dictionary[String, Object]()
geom = None
if values is not None:
for col in values:
if col.lower() == "geometry":
wkt = values[col]
wkt = None
geom_obj = values[col]
if isinstance(geom_obj, str):
wkt = values[col]
else:
shapely = self._get_shapely()
wkt = shapely.to_wkt(geom_obj)
geom = GeoAPIHelper.GetIGeometryFromWKT(wkt)
if isinstance(values[col], int):
value_dict[col] = System.Nullable[int](values[col])
Expand Down Expand Up @@ -324,6 +354,13 @@ def _create_datatables(self):
datatables = DataTableContainer(True)
return datatables

def _get_shapely(self):
shapely = sys.modules.get("shapely")
if shapely is None:
message = "This functionality requires installing the optional dependency shapely."
raise ImportError(message)
return shapely


class DataTableDemoAccess(DataTableAccess):
"""
Expand Down
70 changes: 59 additions & 11 deletions notebooks/DataTableAccessor.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@
"- Get link data for an exist link.\n",
"- Update node geometry.\n",
"\n",
"WTK (well-know-text) is accept for geometry field. It uses ISO 19162:2019 standard.\n",
"Multiple geometry is not supported.\n",
"WTK examples for point, line and polygon:\n",
"- POINT (30 10)\n",
"- LINESTRING (30 10, 10 30, 40 40)\n",
"- POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))\n"
"Both WTK and shapely geometry object are accept for geometry field.\n",
"\n",
"- WTK (well-know-text) is accepted for geometry field. You can use this format to insert, update and query data. It uses ISO 19162:2019 standard.\n",
" Multiple geometry is not supported.\n",
" WTK examples for point, line and polygon:\n",
" \n",
" - POINT (30 10)\n",
" - LINESTRING (30 10, 10 30, 40 40)\n",
" - POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))\n",
"\n",
"- Shapely object is accepted for inserting and updateing geometry data. But it's not supported yet for query geometry data. The return data type is\n",
" WTK format. Please make sure shapely package has been installed before using it.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "0666baf9",
"metadata": {},
"outputs": [],
Expand All @@ -37,7 +43,7 @@
" print(fields[i] + \":\" + str(values[i]))\n",
" i += 1\n",
" else:\n",
" print(\"There is no data of 'link_test'\")\n"
" print(\"There is no data of 'link_test'\")"
]
},
{
Expand Down Expand Up @@ -71,6 +77,12 @@
"data_access"
]
},
{
"cell_type": "markdown",
"id": "4f32cbe5",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 3,
Expand Down Expand Up @@ -104,7 +116,7 @@
" \"Description\": \"insertValues\",\n",
" \"geometry\": \"LINESTRING(3 4,10 50,20 25)\",\n",
"}\n",
"data_access.insert(\"msm_Link\", \"link_test\", values)\n"
"data_access.insert(\"msm_Link\", \"link_test\", values)"
]
},
{
Expand Down Expand Up @@ -172,7 +184,7 @@
"}\n",
"data_access.set_values(\"msm_Link\", \"link_test\", values)\n",
"values = data_access.get_field_values(\"msm_Link\", \"link_test\", fields)\n",
"print_field_values(fields, values)\n"
"print_field_values(fields, values)"
]
},
{
Expand Down Expand Up @@ -235,7 +247,7 @@
}
],
"source": [
"\"\"\"Insert node with geometry, and update node coordinate x and y\"\"\"\n",
"\"\"\"Insert node with geometry of wkt format, and update node coordinate x and y\"\"\"\n",
"values = {\"geometry\": \"POINT(6 10)\"}\n",
"data_access.insert(\"msm_Node\", \"node_test\", values)\n",
"fields = [\"GeomX\", \"GeomY\", \"geometry\"]\n",
Expand All @@ -255,6 +267,42 @@
{
"cell_type": "code",
"execution_count": 11,
"id": "d9fcd4f5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"link has been inserted, current data is:\n",
"geometry:LINESTRING (0 0, 10 10)\n",
"link geometry has been updated, current data is:\n",
"geometry:LINESTRING (10 10, 20 20)\n"
]
}
],
"source": [
"\"\"\"Insert line with geometry of shapely object, and update geometry with shapely object\"\"\"\n",
"from shapely.geometry import LineString\n",
"\n",
"line = LineString([(0, 0), (10, 10)])\n",
"values = {\"geometry\": line}\n",
"data_access.insert(\"msm_Link\", \"link_shp_test\", values)\n",
"fields = [\"geometry\"]\n",
"values = data_access.get_field_values(\"msm_Link\", \"link_shp_test\", fields)\n",
"print(\"link has been inserted, current data is:\")\n",
"print_field_values(fields, values)\n",
"line = LineString([(10, 10), (20, 20)])\n",
"data_access.set_value(\"msm_Link\", \"link_shp_test\", \"geometry\", line)\n",
"values = data_access.get_field_values(\"msm_Link\", \"link_shp_test\", fields)\n",
"print(\"link geometry has been updated, current data is:\")\n",
"print_field_values(fields, values)\n",
"data_access.delete(\"msm_Link\", \"link_shp_test\")\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f31060ad",
"metadata": {},
"outputs": [],
Expand Down
23 changes: 23 additions & 0 deletions tests/test_datatable.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,26 @@ def test_manipulate_data():
muids = data_access.get_muid_where("msm_Link", "MUID='link_test'")
assert len(muids) == 0
data_access.close_database()


def test_shapely_geometry():
from shapely.geometry import LineString

file_name = os.path.join("tests", "testdata", "Db", "Sirius", "Sirius.sqlite")
data_access = DataTableDemoAccess(file_name)
data_access.open_database()
muids = data_access.get_muid_where("msm_Link", "MUID='link_test'")
if len(muids) == 1:
data_access.delete("msm_Link", "link_test")
line = LineString([(0, 0), (10, 10)])
values = {"geometry": line}
data_access.insert("msm_Link", "link_shp_test", values)
fields = ["geometry"]
values = data_access.get_field_values("msm_Link", "link_shp_test", fields)
assert values[0] == "LINESTRING (0 0, 10 10)"
line = LineString([(10, 10), (20, 20)])
data_access.set_value("msm_Link", "link_shp_test", "geometry", line)
values = data_access.get_field_values("msm_Link", "link_shp_test", fields)
assert values[0] == "LINESTRING (10 10, 20 20)"
data_access.delete("msm_Link", "link_shp_test")
data_access.close_database()

0 comments on commit b4c4d9d

Please sign in to comment.