Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polygons with holes? #464

Open
pcace opened this issue Apr 30, 2024 · 8 comments
Open

Polygons with holes? #464

pcace opened this issue Apr 30, 2024 · 8 comments

Comments

@pcace
Copy link

pcace commented Apr 30, 2024

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!!

@postspectacular
Copy link
Member

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...

postspectacular added a commit that referenced this issue May 2, 2024
- add complexPolygon() factory fn
- add bounds() & centroid() impls
postspectacular added a commit that referenced this issue May 2, 2024
)

BREAKING CHANGE: update path related ctors & functions

- add `subPaths` argument for Path ctor/factory fn
- rename `Path.add()` => `Path.addSegments()`
- add `Path.addSubPaths()`
- update `Path.toHiccup()` to include sub-paths
- update `pathFromSvg()` to always return a single path only
  - sub-paths are included in main path now
- update impls for following ops to also process sub-paths:
  - bounds()
  - rotate()
  - scale()
  - simplify()
  - translate()
  - transform()
  - transformVertices()
postspectacular added a commit that referenced this issue May 3, 2024
- add implementations for:
  - arcLength()
  - area()
  - asPath()
  - closestPoint()
  - convexHull()
  - edges()
  - flip()
  - pointInside()
  - resample()
  - rotate()
  - scale()
  - simplify()
  - subdivCurve()
  - transform()
  - transformVertices()
  - translate()
  - vertices()
- add tests
postspectacular added a commit that referenced this issue May 3, 2024
…464)

BREAKING CHANGE: update asPolygon() to return array of polylines

- add/update impls for complexpoly & path to produce multiple results
- update other internal callsites
- update tests
@postspectacular
Copy link
Member

@pcace Just FYI, posted an update: https://mastodon.thi.ng/@toxi/112383330661412657

@pcace
Copy link
Author

pcace commented May 5, 2024

@postspectacular Thank you so much!!!

@postspectacular
Copy link
Member

@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...

@cdaein
Copy link

cdaein commented May 8, 2024

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?

Screenshot 2024-05-08 at 3 53 47 PM

@postspectacular
Copy link
Member

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...

@cdaein
Copy link

cdaein commented May 9, 2024

I appreciate your suggestion. 🙏

@postspectacular
Copy link
Member

@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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants