Skip to content

Commit bf8bfb8

Browse files
committed
handle polygons
1 parent 4cac4fe commit bf8bfb8

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

src/pages/upload/createOsmChangeFromPatchFile.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,57 @@ function geojsonToOsmGeometry(
149149
return [relation];
150150
}
151151

152-
// TODO: support other geometries
152+
// this logic is based on what RapiD uses:
153+
// https://github.com/facebookincubator/Rapid/blob/8a58b2/modules/services/esri_data.js#L103-L134
153154
case 'Polygon':
154155
case 'MultiPolygon': {
155-
return undefined;
156+
const nodes: OsmNode[] = [];
157+
const ways: { way: OsmWay; role: string }[] = [];
158+
159+
const groups =
160+
geom.type === 'Polygon' ? [geom.coordinates] : geom.coordinates;
161+
162+
for (const rings of groups) {
163+
for (const [index, ring] of rings.entries()) {
164+
const ringNodes = ring.map(coordToNode);
165+
if (ringNodes.length < 3) return [];
166+
167+
const first = ringNodes[0];
168+
const last = ringNodes.at(-1);
169+
if (first !== last) ringNodes.push(first); // sanity check, ensure rings are closed
170+
171+
const way: OsmWay = {
172+
...TEMPLATE_OSM_FEATURE,
173+
type: 'way',
174+
id: nextId.way--,
175+
nodes: ringNodes.map((n) => n.id),
176+
};
177+
nodes.push(...ringNodes);
178+
ways.push({ way, role: index === 0 ? 'outer' : 'inner' });
179+
}
180+
181+
if (groups.length === 1 && rings.length === 1) {
182+
// special case: only 1 ring, so we don't need a multipolygon,
183+
// we can just create a simple way and abort early.
184+
const way: OsmWay = { ...baseFeature, ...ways[0].way };
185+
return [way, ...nodes];
186+
}
187+
}
188+
189+
const relation: OsmRelation = {
190+
...baseFeature,
191+
tags: { type: 'multipolygon', ...baseFeature.tags },
192+
type: 'relation',
193+
id: nextId.relation--,
194+
members: ways.map(({ way, role }) => ({
195+
type: 'way',
196+
ref: way.id,
197+
role,
198+
})),
199+
};
200+
return [relation, ...ways.map((w) => w.way), ...nodes];
156201
}
202+
157203
default: {
158204
return undefined;
159205
}

0 commit comments

Comments
 (0)