Skip to content

Commit f1cb875

Browse files
committed
Fix handling of interior rings
1 parent 116e8f3 commit f1cb875

File tree

3 files changed

+29
-19
lines changed

3 files changed

+29
-19
lines changed

mojxml_plugin/algorithm.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,17 @@ def processAlgorithm(self, parameters, context, feedback):
145145
if feedback.isCanceled():
146146
return {}
147147

148-
# Get the exterior ring of the polygon
148+
# Get the exterior ring and interior rings of the polygon
149149
json_geom = src_feat["geometry"]
150150
json_coords = json_geom["coordinates"]
151-
exterior = json_coords[0][0]
152151

153152
# Create a MultiPolygon feature
154153
geom = QgsMultiPolygon()
155-
geom.addGeometry(QgsPolygon(QgsLineString(exterior)))
154+
exterior = json_coords[0][0]
155+
polygon = QgsPolygon(QgsLineString(exterior))
156+
for interior in json_coords[0][1:]:
157+
polygon.addInteriorRing(QgsLineString(interior))
158+
geom.addGeometry(polygon)
156159
feat = QgsFeature()
157160
feat.setGeometry(geom)
158161
feat.setFields(fields, initAttributes=True)

mojxml_plugin/metadata.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[general]
22
name=MOJXML Loader
3-
version=0.1.1
3+
version=0.2.0
44
qgisMinimumVersion=3.0
55
description=This plugin is made for Japanese users. It converts Japanese "MOJ Map XML" (land registration polygon data) into geospatial formats. 法務省登記所備付地図データ(地図XML)の変換や読み込みを行います。
66
author=MIERUNE Inc.

mojxml_plugin/mojxml/parse.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ParseOptions:
2424

2525

2626
class Feature(TypedDict):
27-
"""GeoJSON Feature"""
27+
"""GeoJSON-like feature representation"""
2828

2929
type: str
3030
geometry: Dict[str, list]
@@ -95,7 +95,6 @@ def _parse_curves(
9595

9696
curve_id = curve.attrib["id"]
9797
assert x is not None and y is not None
98-
assert curve_id not in curves
9998

10099
curves[curve_id] = (x, y)
101100

@@ -107,23 +106,32 @@ def _parse_surfaces(
107106
) -> Dict[str, Surface]:
108107
surfaces: Dict[str, Surface] = {}
109108
for surface in spatial_elem.iterfind("./zmn:GM_Surface", _NS):
110-
assert surface.find(".//zmn:GM_SurfaceBoundary.exterior", _NS) is not None
111109
polygons = surface.findall("./zmn:GM_Surface.patch/zmn:GM_Polygon", _NS)
112110
assert len(polygons) == 1
113111
polygon = polygons[0]
114-
115112
surface_id = surface.attrib["id"]
116-
surface_curves: list[tuple[float, float]] = []
117-
for cc in polygon.iterfind(".//zmn:GM_CompositeCurve.generator", _NS):
113+
rings: list[list[tuple[float, float]]] = []
114+
115+
exterior = polygon.find(".//zmn:GM_SurfaceBoundary.exterior", _NS)
116+
ring: list[tuple[float, float]] = []
117+
for cc in exterior.find(".//zmn:GM_Ring", _NS):
118118
curve_id = cc.attrib["idref"]
119119
assert curve_id in curves
120-
assert surface_id not in surface_curves
121-
surface_curves.append(curves[curve_id])
120+
ring.append(curves[curve_id])
121+
ring.append(ring[0])
122+
rings.append(ring)
123+
124+
for interior in polygon.iterfind(".//zmn:GM_SurfaceBoundary.interior", _NS):
125+
ring: list[tuple[float, float]] = []
126+
for cc in interior.find(".//zmn:GM_Ring", _NS):
127+
curve_id = cc.attrib["idref"]
128+
assert curve_id in curves
129+
ring.append(curves[curve_id])
130+
ring.append(ring[0])
131+
rings.append(ring)
122132

123133
assert surface_id not in surfaces
124-
assert len(surface_curves) > 0, surface_id
125-
surface_curves.append(surface_curves[0])
126-
surfaces[surface_id] = [[surface_curves]]
134+
surfaces[surface_id] = [rings]
127135

128136
return surfaces
129137

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

192-
# 基本情報を取得
193-
base_props = _parse_base_properties(doc)
200+
# このファイルの座標参照系を取得する
194201
source_crs = CRS_MAP[doc.find("./座標系", _NS).text]
195-
196202
if (not options.include_arbitrary_crs) and source_crs is None:
197203
return []
198204

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

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

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

0 commit comments

Comments
 (0)