I have a self-intersecting / winding polygon (see in green on picture below). I'd like to get the outer shell (by only keeping the edges that are on the outside of the polygon / removing any inside edges) and therefore end up with a well-defined polygon without any holes inside (see solution in yellow on picture).
How could I do this? Convex/concave hulls won't do because they will take some ground outside the polygon.
I'm using turf-js, so any solution using that would be ideal, but happy to use other libraries / write an algorithm for scratch if not possible.
Related
Creating a map similar to the one found here:
https://www.plantmaps.com/interactive-california-2012-usda-plant-zone-hardiness-map.php
Have all the data needed.
Create polygons around each one without distance inbetween. No overlapping or similar.
Drawing it all by hand on geojson.io, seems impossible.
I want to create polygons around each [point] and make sure there is no distance between them.
What you're describing here is a tessellation. Depending on your data, you might opt for a regular tessellation (i.e. creating a grid of squares or hexagons, paying a modicum of attention to the units of your coordinate system) or the well-known-among-GIS-people Voronoi tessellation. Note that a Voronoi tessellation created over a regular grid of points will result in a regular grid of polygons.
There are plenty of tools for Voronoi tessellations. For javascript and GeoJSON, my tool of choice would be turf.js's voronoi module.
Here are some things to consider:
creating polygon from a point is simple enough. For example you use the point as the center of a regular polygon and devide 2PI by the number of sides and step through the points to create the polygon. But, what is the radius? That depends on the projection you are using. I happen to use OpenLayers and really like this map control. It's default projection it EPSG:3857. So, the coordinates are already in meters - so easy. But if your points are in long/lat then you have to do some math. it may be easier to transform to a different projection temporarily. An opensource library that is really nice for gis calculations if you need one is Turf.
You mentioned also about having non-overlapping polygons? Well, in this case you will have a lot of gaps if you use regular polygons. To have non-overlapping polygons with, as you put it no distance between them is an interesting constraint. Now you are dealing with different shaped polygons. And an algorithm for handling that is pretty intense. I know that MapInfo GIS has a feature for adjusting polygons to be non-overlapping. But, in a JavaScript environment with GeoJSON, you are probably talking about server side logic for this.
That map you are looking at looks like it is using Leaflet with svg overlays.
I want to make a shape (an XP bar) to always be ordered at the top of all shapes drawn.
How would this be possible, (I also use p5.js too, if that helps.) other than drawing it last (which I cannot do in my situation).
You've got two main options:
Option one: Draw it last. This is the easiest way to do it. If you "cannot" do it this way for some reason, that sounds like you need to refactor your code then.
Option two: Use 3D coordinates to draw it with a Z coordinate that's closer to the user. Most drawing functions can take 3D coordinates instead of 2D coordinates. This should work, but it's more complicated than just drawing it last.
I have an svg element composed of many different path objects, each of which represents one U.S state.
http://jsfiddle.net/jGjZ2/
I would like to merge the east territory (gold) into a single path object with no visible divisions.
The end result should look like this (ignore the inaccuracies):
I am using D3.
There is no GeoJSON or TopoJSON data - the map is svg directly embedded in html (see jsfiddle).
Thanks a lot!
Assuming you can ignore the stated restriction of manipulating an existing SVG image (which seems like an arbitrary restriction given the ready availability of cartographic boundaries in more easy-to-manipulate formats…), you can use topojson.mesh to merge multiple polygons. Though, note this approach has a few limitations as described in this example:
Another simple approach is to just draw the highlighted polygons twice: once with a thick black stroke and no fill, and a second time on top with orange fill and no stroke. This achieves the same effect without any need for topological manipulation:
I suppose if you really had to, you could reach into the SVG element and do the same thing by extracting the vector data, but it will be easier if you start from clean data.
I am writing code that will build an oriented bounding box (obb) tree for a (not necessarily convex) polygon in 2 dimensions.
So far, I'm able to find the area-minimal obb of a polygon by finding its convex hull and using rotating calipers on the hull.
The picture below is an example of this. The yellow-filled polygon with red lines and red points depicts the original polygon. The convex hull is shown in blue with black lines and the obb is shown as purple lines.
(Edit) As requested: Interactive Version - tested only in chrome
Now I want to extend my code to build an OBB tree, instead of just an OBB. This means I have to cut the polygon, and compute new OBBs for each half of the polygon.
The recommended way to do this seems to be to cut the polygon by cutting the OBB in half. But if I cut the obb through the middle in either of its axes it looks like I would have to create new vertices on the polygon (otherwise how do I find the convex hull of that partition?).
Is there a way to avoid adding vertices like this?
If not, what is the easiest way to do it (with respect to implementation difficulty)? What is the most runtime-efficient way?
Here's an example of a concave polygon that we want to create an OBB tree for:
In order to split it into a new set of concave polygons, we can simply cut our current polygon by cutting the bounding box down the middle and adding new 'intersection' vertices as appropriate:
:
This can be done in O(vertices) time because we can simply iterate through all of the edges, and add an intersection vertex if the edge crosses the red splitting line.
The polygon can then be divided in terms of these intersection vertices to get a new set of smaller (but still possibly concave) polygons. There will be at least two such polygons (one per side of the red line) but there may be more. In this next picture, the new polygons have been colored for emphasis:
Recursively computing the oriented bounding boxes for these smaller polygons gives the desired result. For example, here are the boxes from recursion depth 2:
Hopefully this is clear enough to help someone who's struggling the same way I was!
I'm not really sure this is what you need without further context, but here goes...
Subdividing a concave polygon into a set of convex polygons
In my comment above I suggested recursively subdividing the concave polygon in order to obtain a set of convex polygons instead. One (common) approach is the following:
If the polygon is convex, stop. (add the polygon to an array, I suppose)
Select an unmarked edge of the polygon. Mark the edge.
Split the polygon across the edge (actually: the infinite line coinciding with the edge).
Recursively repeat this algorithm for both result polygons (if non-empty).
Note: This is exactly how a BSP tree is built. Except in the algorithm above we're not building tree nodes and storing polygons in them. Maybe a BSP-only solution would be a solution to your problem as well (instead of using OBBs).
Testing a polygon for convexity (step 1)
For each edge, classify each vertex as on, in front or behind the edge. All vertices should be on or in front of the edge. If not (at least 1 vertex behind the edge), the polygon is concave. For details on the 'classifying' part, see my answer to a different question, which does this as well.
The rest
Once you have the list of convex sub-polygons, you could generate OBBs for them as you've done in your original post. You would not have an OBB tree though...
With the subdividing, you are adding vertices (a concern in your question). Depending on your application you may not need to use the subdivided polygons though: If you were to use a BSP tree and only needed simple collision you'd just traverse the tree and do some point/edge classifications and not deal with any polygon vertices.
Anyway, not really sure what to recommend further since I don't know what you want your application to do, but hopefully this is of some help.
Edit: I just realized that maybe this is what you want to do: Build a BSP tree and generate OBBs for each node, from root to leaf nodes. So the root node OBB would contain the entire concave polygon, and leaf nodes only convex sub-polygons. I remember the original Doom engine does something similar (except with axis-aligned BBs).
This Pentagon example shows holes can be added inside a Polygon: http://code.google.com/p/gmaps-samples-v3/source/browse/trunk/poly/pentagon.html?r=40
I would like to add a hole inside a circle.
Currently I am mimicking this by making a circle shape polygon and putting inner and outer bounds and it is working fine, however the code is extremely long seeing as the map has ~15 circles in it.
Any help would be much appreciated
Thanks!
I didn't find anything for the Circle class, but someone has figured out a function that will reduce your code size. It does the same thing you are doing, creating polygons shaped like a circle.
http://www.geocodezip.com/v3_polygon_example_donut.html
The function drawCircle(point, radius, dir) uses dir to distinguish positive space and holes. You have to alternate them to create holes.