Polygons with holes?
Hi there,
i am currently trying to convert geojsons to svg to be able to print them in a webapplication.
The Problem i am facing is that Polygon does not support holes (https://docs.thi.ng/umbrella/geom/#md:shape-types)
what i do is to is basically this:
export const geoJsonToSvg = (
polygons: (UnitPolygonFeature | IPolygonGeoJson)[],
width?: number,
height?: number
) => {
const polys = geoJsonToPolygons(polygons);
return polygonToSvg(polys, bbox);
};
const geoJsonToPolygons = (
polygons: (UnitPolygonFeature | IPolygonGeoJson)[]
) => {
const polygonTree = polygons.map((p) => {
return p.geometry.coordinates.reduce((acc: (Polygon | Circle)[], l) => {
const poly = polygon(l.map((v) => [v[0], v[1]]));
acc.push(poly);
return acc;
}, []);
});
return flattenTree<Polygon | Circle>(polygonTree);
};
const polygonToSvg = (
polys: (Polygon | Circle | Point | Path | any)[],
bbox?: number[][]
) => {
const doc = svg(
{
width: 100,
height: 100,
viewBox: `${bbox}`,
},
["defs", {}, ...getPatterns(), ...getPatternMasks(bbox)]
);
for (let i = 0; i < polys.length; i++) {
if (Object.prototype.hasOwnProperty.call(polys[i], "toHiccup")) {
doc.push(polys[i].toHiccup());
} else {
doc.push(polys[i]);
}
}
const svgParsed = asSvg(doc);
return svgParsed;
};
this kind of works, but returns all holes from the geojson as additional polygons, overlaying the others.
How can i turn these polygons into holes?
Thanks a lot!!
Hi @pcace - polygons with holes are currently still unsupported (sadly!), because most of the operations in the geom package are relying on a single boundary representation and also because, personally, I had only rare use for them. However, I've got some old implementation which I've been meaning to re-integrate and at least add support for those operators which make sense. Technically, the best way for that will be to define a separate type of polygon, rather than complicating the existing setup. Let me think about this for a few days & I will report back ASAP...
@pcace Just FYI, posted an update: https://mastodon.thi.ng/@toxi/112383330661412657
@postspectacular Thank you so much!!!
@pcace Just released v7.0.0 with support for polygons with holes and paths with holes (or multiple curves in general). Please see full changelog here:
https://github.com/thi-ng/umbrella/blob/develop/packages/geom/CHANGELOG.md#700-2024-05-08
Most of the polymorphic geom operators also support these new/updated shape types, but please let me know if you run into any problems...
The addition of complexPolygon() and flip() is very exciting!
I tried and worked nicely but I had a TypeScript error.
Is there any way to get around this issue?
That is an issue I currently have no real solution for, other than having to manually cast the result of some of these functions, like so:
// add type-only import
import { type Polygon } from "@thi.ng/geom";
const combined = complexPolygon(poly1, [<Polygon>flip(poly2)]));
// or via the different syntax:
const combined = complexPolygon(poly1, [flip(poly2) as Polygon]));
This is part of the https://en.wikipedia.org/wiki/Expression_problem (esp. in typed languages) and I've been trying a few approaches to improve that, but none of them are truly "watertight" and/or as extensible as these polymorphic functions are intended to be... e.g. if had a custom shape type defined yourself, you can add an implementation for it via e.g. flip.add("myshapeid", (shape) => { ... }). You can do that for almost all of the thi.ng/geom functions... but that flexibility comes at a price, i.e. only a generic return type...
I appreciate your suggestion. 🙏
@cdaein Hehe... and I'm already working on #467, so far so good, but I already can see a bunch of more complex stuff on the horizon...
Closing this since complete, new release next week! :)