Skip to content

Commit

Permalink
Fix handling of interior rings
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscorn committed Apr 4, 2023
1 parent 116e8f3 commit f1cb875
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 19 deletions.
9 changes: 6 additions & 3 deletions mojxml_plugin/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,17 @@ def processAlgorithm(self, parameters, context, feedback):
if feedback.isCanceled():
return {}

# Get the exterior ring of the polygon
# Get the exterior ring and interior rings of the polygon
json_geom = src_feat["geometry"]
json_coords = json_geom["coordinates"]
exterior = json_coords[0][0]

# Create a MultiPolygon feature
geom = QgsMultiPolygon()
geom.addGeometry(QgsPolygon(QgsLineString(exterior)))
exterior = json_coords[0][0]
polygon = QgsPolygon(QgsLineString(exterior))
for interior in json_coords[0][1:]:
polygon.addInteriorRing(QgsLineString(interior))
geom.addGeometry(polygon)
feat = QgsFeature()
feat.setGeometry(geom)
feat.setFields(fields, initAttributes=True)
Expand Down
2 changes: 1 addition & 1 deletion mojxml_plugin/metadata.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[general]
name=MOJXML Loader
version=0.1.1
version=0.2.0
qgisMinimumVersion=3.0
description=This plugin is made for Japanese users. It converts Japanese "MOJ Map XML" (land registration polygon data) into geospatial formats. 法務省登記所備付地図データ(地図XML)の変換や読み込みを行います。
author=MIERUNE Inc.
Expand Down
37 changes: 22 additions & 15 deletions mojxml_plugin/mojxml/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ParseOptions:


class Feature(TypedDict):
"""GeoJSON Feature"""
"""GeoJSON-like feature representation"""

type: str
geometry: Dict[str, list]
Expand Down Expand Up @@ -95,7 +95,6 @@ def _parse_curves(

curve_id = curve.attrib["id"]
assert x is not None and y is not None
assert curve_id not in curves

curves[curve_id] = (x, y)

Expand All @@ -107,23 +106,32 @@ def _parse_surfaces(
) -> Dict[str, Surface]:
surfaces: Dict[str, Surface] = {}
for surface in spatial_elem.iterfind("./zmn:GM_Surface", _NS):
assert surface.find(".//zmn:GM_SurfaceBoundary.exterior", _NS) is not None
polygons = surface.findall("./zmn:GM_Surface.patch/zmn:GM_Polygon", _NS)
assert len(polygons) == 1
polygon = polygons[0]

surface_id = surface.attrib["id"]
surface_curves: list[tuple[float, float]] = []
for cc in polygon.iterfind(".//zmn:GM_CompositeCurve.generator", _NS):
rings: list[list[tuple[float, float]]] = []

exterior = polygon.find(".//zmn:GM_SurfaceBoundary.exterior", _NS)
ring: list[tuple[float, float]] = []
for cc in exterior.find(".//zmn:GM_Ring", _NS):
curve_id = cc.attrib["idref"]
assert curve_id in curves
assert surface_id not in surface_curves
surface_curves.append(curves[curve_id])
ring.append(curves[curve_id])
ring.append(ring[0])
rings.append(ring)

for interior in polygon.iterfind(".//zmn:GM_SurfaceBoundary.interior", _NS):
ring: list[tuple[float, float]] = []
for cc in interior.find(".//zmn:GM_Ring", _NS):
curve_id = cc.attrib["idref"]
assert curve_id in curves
ring.append(curves[curve_id])
ring.append(ring[0])
rings.append(ring)

assert surface_id not in surfaces
assert len(surface_curves) > 0, surface_id
surface_curves.append(surface_curves[0])
surfaces[surface_id] = [[surface_curves]]
surfaces[surface_id] = [rings]

return surfaces

Expand Down Expand Up @@ -189,18 +197,16 @@ def parse_raw(content: bytes, options: ParseOptions) -> List[Feature]:
"""Parse raw XML content and get a list of features."""
doc = et.fromstring(content, None)

# 基本情報を取得
base_props = _parse_base_properties(doc)
# このファイルの座標参照系を取得する
source_crs = CRS_MAP[doc.find("./座標系", _NS).text]

if (not options.include_arbitrary_crs) and source_crs is None:
return []

spatial_elem = doc.find("./空間属性", _NS)
points = _parse_points(spatial_elem)
curves = _parse_curves(spatial_elem, points)

# 平面直交座標系を WGS84 に変換する
# 平面直角座標系を WGS84 に変換する
if source_crs is not None:
transformer = pyproj.Transformer.from_crs(
source_crs, "epsg:4326", always_xy=True
Expand Down Expand Up @@ -245,6 +251,7 @@ def parse_raw(content: bytes, options: ParseOptions) -> List[Feature]:
)

# XMLのルート要素にある属性情報をFeatureのプロパティに追加する
base_props = _parse_base_properties(doc)
for feature in features:
feature["properties"].update(base_props)

Expand Down

0 comments on commit f1cb875

Please sign in to comment.