This seems non-trivial (it gets asked quite a lot on various forums), but I absolutely need this as a building block for a more complex algorithm.
Input: 2 polygons (A and B) in 2D, given as a list of edges [(x0, y0, x1, y2), ...] each. The points are represented by pairs of doubles. I do not know if they are given clockwise, counter-clockwise or in any direction at all. I do know that they are not necessarily convex.
Output: 3 polygons representing A, B and the intersecting polygon AB. Either of which may be an empty (?) polygon, e.g. null.
Hint for optimization: These polygons represent room and floor boundaries. So the room boundary will normally fully intersect with the floor boundary, unless it belongs to another floor on the same plane (argh!).
I'm kind of hoping someone has already done this in c# and will let me use their strategy/code, as what I have found so far on this problem is rather daunting.
EDIT: So it seems I'm not entirely chicken for feiling faint at the prospect of doing this. I would like to restate the desired output here, as this is a special case and might make computation simpler:
Output: First polygon minus all the intersecting bits, intersection polygons (plural is ok). I'm not really interested in the second polygon, just its intersection with the first.
EDIT2: I am currently using the GPC (General Polygon Clipper) library that makes this really easy!
Arash Partow's FastGEO library contains implementations of many interesting algorithms in computational geometry. Polygon intersection is one of them. It's written in Pascal, but it's only implementing math so it's pretty readable. Note that you will certainly need to preprocess your edges a little, to get them into clockwise or counterclockwise order.
ETA: But really, the best way to do this is to not do this. Find another way to approach your problem that doesn't involve arbitrary polygon intersections.
If you are programming in .NET Framework, you may want to take a look at SqlGeometry class available in .NET assemblies shipped as Microsoft SQL Server System CLR Types
The SqlGeometry class provides STIntersection method
SqlGeometry g1 = SqlGeometry.Parse("POLYGON ((...))");
SqlGeometry g2 = SqlGeometry.Parse("POLYGON ((...))");
SqlGeometry intersection = g1.STIntersection(g2);
What I think you should do
Do not attempt to do this yourself if you can possibly help it. Instead, use one of the many available polygon intersection algorithms that already exist.
I was strongly considering the following codebase on the strength of their demonstration code and the fact that they mentioned their handling of most/all of the weird cases. You would need to donate an amount (of you/your company's choice) if you use it commercially, but it's worth it to get a robust version of this kind of code.
http://www.cs.man.ac.uk/~toby/gpc/
What I actually did was to use a polygon-intersection algorithm that is part of the Java2D libraries. You can possibly find something similar in MS's own C# libraries to use.
There are other options out there as well; look for "polygon clipper" or "polygon clipping", since the same basic algorithms that handle polygon intersection also tend to be usable for the general clipping cases.
Once you actually have a polygon clipping library, you just need to subtract polygon B from polygon A to get your first piece of output, and intersect polygons A and B to get your second piece of output.
How to roll your own, for the hopelessly masochistic
When I was considering rolling my own, I found the Weiler-Atherton algorithm to have the most potential for general polygon-cutting. I used the following as a reference:
http://cs1.bradley.edu/public/jcm/weileratherton.html
http://en.wikipedia.org/wiki/Weiler-Atherton
The details, as they say, are too dense to include here, but I have no doubt that you'll be able to find references on Weiler-Atherton for years to come. Essentially, you split all the points into those that are entering the final polygon or exiting the final polygon, then you form a graph out of all the points, and then walk the graph in the appropriate directions in order to extract all the polygon pieces you want. By changing the way you define and treat the "entering" and "exiting" polygons, you can achieve several possible polygon intersections (AND, OR, XOR, etc.).
It's actually fairly implementable, but like with any computational geometry code, the devil is in the degeneracies.
You may also want to have a look at the NetTopologySuite or even try importing it into Sql server 2008 & it's spatial tools.
Clipper is an open source freeware polygon clipping library (written in Delphi and C++) that does exactly what you're asking - http://sourceforge.net/projects/polyclipping/
In my testing, Clipper is both significantly faster and far less prone to error than GPC (see more detailed comparisons here - http://www.angusj.com/delphi/clipper.php#features). Also, while there's source code for both Delphi and C++, the Clipper library also includes a compiled DLL to make it very easy to use the clipping functions in other (Windows) languages too.
A polygon is fully described by an ordered list of points (P1, P2, ..., Pn). The edges are (P1 - P2), (P2 - P3), ..., (Pn - P1). If you have two polygons A and B which overlaps, there will be a point An (from the list on points describing polygon A) which lies within the area surrounded by polygon B or vice versa (a point of B lies in A). If no such point is found, then the polygons does not overlap. If such a point is found (i.e. Ai) check the adjacent points of the polygon A(i-1) and A(i+1). Repeat until you find a point outside the area or all points are checked (then the first polygon lies completly within the second polygon). If you found a point outside then you can calculate the crossing point. Find the corresponding edge of polygon B and follow it with resersed roles = now check if the points of polygon B lie within polygon A. This way you can build a list of points which describe the overlapping polygon. If needed you should check if the polygons are identical, (P1, P2, P3) === (P2, P3, P1).
This is just an idea and there maybe better ways. If you find a working and tested solution I would recommend that you use it...
narozed
Try to use GIS tools for that, such as ArcObjects, TopologySuite, GEOS, OGR, etc. I'm not sure if all of these distributions are availuable to .net, but they all do the same.
This academic paper explains how to do this.
If you dare to take a look to other people's GPL C++ code, you can see how do they do it in Inkscape:
http://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/head:/src/2geom/shape.cpp (line 126)
Related
I have 3D point clouds and want to reconstruct the surface. I tried various techniques in Meshlab to find the algorithm that best suits my specific kind of cloud.
The poisson surface reconstruction is very promising, but it does not preserve the original point position. After reconstruction and measuring at specific positions in the cloud it turned out that the measurements are off by a factor of over 1.5 compared to measurements on the object in the real world.
The ball pivoting algorithm is better. It preserved the position of the points and the measurements were also within the expected range. However this algorithm is patented in the USA so I can't use it for a commercial project.
After researching other algorithms, I did not find any that preserve the point position like ball pivoting which could be used in a commercial environment. Do you know algorithms that fulfill these two criteria and which I could try with my point cloud to see if they work well before implementing them?
Any help would be appreciated.
For interpolating surface reconstruction (that keeps the datapoints), two algorithms perform reasonably well (crust and co-cone).
Crust algorithm:
The idea is to first compute the Voronoi diagram of the pointset, then select from the Voronoi vertices the ones that are a good approximation of the medial axis (called the poles), then compute the 3D Delaunay triangulation of the input points + the poles, and finally extract the triangles that connect three input points in a tetrahedron where the fourth vertex is a pole.
More references:
http://web.cs.ucdavis.edu/~amenta/pubs/crust.pdf
http://web.mit.edu/manoli/crust/www/crust.html
plus: quite simple to implement, some theoretical guarantees if input data is a good sampling
minus: requires to compute two Delaunay triangulations
Co-cone algorithm:
The idea is to compute the Voronoi diagram of the pointset, and then in each Voronoi cell compute a good approximation of the normal to the surface (as the vector that connect the poles, i.e. the two Voronoi vertices furthest away from the datapoint). Then in each Voronoi cell one considers the complement of a cone (co-cone) centered on the datapoint and having the normal as an axis. If three co-cones have a non-empty intersection with a Voronoi edge, then the three datapoints are connected with a triangle. Note that the co-cone objects do not need to be constructed explicitely (just angles need to be compared in order to test whether there is an intersection).
More references:
http://web.cse.ohio-state.edu/~tamaldey/surfrecon.htm
Plus: requires a single Delaunay triangulation (compared to 2 for the Crust), some theoretical guarantees if the input data is a "good sampling"
Minus: a little bit more complicated than the crust (but worth the effort I think)
Some final words:
These algorithms construct a good (i.e. manifold) surface if the point set realises a good sampling (i.e. density proportional to thickness and curvature, something called "local feature size" = distance to medial axis). In practice, the input data does not satisfy this condition, therefore the output of the method will be a "soup of triangles" that will be mostly OK but that will require some post-processing to fix some local defects.
Edit 03/21/16 You may also try my own algorithm (Co3Ne), implemented in my software library Geogram (http://alice.loria.fr/software/geogram/doc/html/index.html) and my software Graphite (http://alice.loria.fr/software/graphite/doc/html/). Graphite can be downloaded there: http://gforge.inria.fr/frs/?group_id=1465 (both portable source code and Windows64 executable). It is a form of Co-cone with various optimizations and parallel implementation.
I am getting coordinates - lat/lon and I want to check if these coordinates are in the continental United States or not. Is there a easy way to do it in C#? I can convert the coordinates into MGRS or UTM.
Thanks!
Oh wow, they have it just for you:
http://econym.org.uk/gmap/states.xml
All the coords of the US states!
Build up a polygon and apply any polygon-contains-point algorithm.
The classic algorithm is ray-casting, and its even pretty simple. Let me know if you have any trouble with it.
Now, you have two options:
Use the data to build a polygon for each state, and check a point with each one of them. If none match, it is not in the US.
However, there is a problem with that approach - I don't know how the data was gathered, but its possible that there are very little gaps between states, or even slight overlaps. So if you only care if its generally in the US or not, I suggest the second approach:
Use the data to build a polygon for each state, and an algorithm to combine those polygons to one (like union). Save that polygon and use that as with the 1st approach.
I wonder if there's any described algorithm that can convert isochrones into approximate area to show a range of some feature (in my problem this feature is a road network).
Example. I have something like on the image beneath:
It's a simple network (where I can arrive from the start point in X minutes or going Y kilometers). I have information of all the nodes and links. Now I need to create an isochrone map that show an approximate range where I can arrive.
Problems:
Convex hull - sucks because of too general approximation,
I can create buffors on roads - so I will get some polygon that shows range, but I will also have the holes by roads that connect into circles.
What I need to obtain is something like this:
I've found some potentially useful information HERE, but there are only some ideas how it could be done. If anyone has any concept, please, help me to solve my problem.
Interesting problem, to get better answers you might want to define exactly what will this area that shows the range (isochrone map) be used for? For example is it illustrative? If you define what kind of approximation you want it could help you solve the problem.
Now here are some ideas.
1) Find all the cycles in the graph (see link), then eliminate edges that are shared between two cycles. Finally take the convex hull of the remaining cycles, this together with all the roads, so that the outliers that do not form cycles are included, will give a good approximation for an isochrome map.
2) A simpler solution is to define a thickness around each point of every road, this thickness should be inversely proportional to how long it takes to arrive at that point from the starting point. I.e. the longer it takes to arrive at the point the less thick. You can then scale the thickness of all points until all wholes are filled, and then you will have an approximate isochrome map. One possible way of implementing this is to run an algorithm that takes all possible routes simultaneously from the starting point, branching off at every new intersection, while tracking how long it took to arrive at each point. During its execution, at every instant of time all previously discovered route should be thickened. At the end you can scale this thickness so as to fill all wholes.
Hopefully this will be of some help. Good luck.
I have solved the problem (it's not so fast and robust, but has to be enough for now).
I generated my possible routes using A* (A-Star) algorithm.
I used #Artur Gower's idea from point one to eliminate cycles and simplify my geometry.
Later I decided to generate 2 types of gemetries (1st - like on the image, 2nd - simple buffers):
1st one:
3. Then I have removed the rest of unnecessary points using Douglas-Peucker algorithm (very fast!).
4. In the end I used Concave Hull algorithm (aka Alpha-Shapes or Non-Convex Hull).
2nd one:
3. Apply a buffer to the existing geometry and take the exterior ring (JTS library made that really easier:)).
Is there any simple (or not) algorithm that is capable of creating polygons from closed path?
Assume w have following path:
0,0; 2,0, 2,1; 1,1;
1,2; 2,2; 2,3; 0,3;
I need to be able to create polygon indexes for OpenGL vertex buffer. Language I'm using is C#.
Someone suggested me Convex Hull, but it's not the thing I'm looking for, cause I have a shape already. I know that this could be a trivial issue, but seriously, I can't find any description or something to point mi in the right direction.
Edit:
Answer 1 suggest to select a point and connect it to other not connected points, this works fine for presented in answer shape but it will not work for shape i posted, shape above looks like this:
Converting to triangles is either easy or hard, depending on what your requirements are and how well you want to do it.
If your polygon is convex, the easiest way is to use GL_TRIANGLES with the indicies
0, 1, 2, 0, 2, 3, 0, 3, 4, ...
It will look like this:
The situation for concave is more work. An algorithm that also works for concave polygons (not ones with holes!) is the Ear-clipping method, described on wikipedia (there is more on that page.)
Things get really interesting when you want a "good" triangulation: avoid skinny or small triangles, reduce number of triangles etc., and then you can trade off quality for speed. I won't go into any advanced algorithms here; searching for polygon triangulation on Google will get you lots of info.
As for normals, if your polygon is planar (it most likely "should" be) then take two non co-incident edges and cross product them (there are two normals and you probably only want one: you need to choose the order in which you cross product (clockwise or anticlockwise) based on the right hand rule.
I have 2D world maps that are basically Mercator-Like projections, (If you walk west long enough you end up east of where you started)
Question I have: Can you use A* for computing paths on these types of maps as well?
I can't think of any reason why you couldn't (I'm thinking that you would simply represent the edge map nodes such that the North, South, East, Wed, "border" nodes simply connected to the opposite side).
Thanks in advance, if anyone has seen something like this before or can give me a few hints I would appreciate it.
Pathfinding algorithms don't really care about global topology of the map. The only tricky part is to get a good estimator for A* but using the 3D distance should be ok if your map is indeed a surface in a 3d space and step cost is step length.
Your map can have all sort of strange "connections" (including for example knotted bridges) and this will not be a problem if you implement A* correctly.
I can't imagine why a Mercator-Like projections would cause a problem for A*, as long as your heuristic function approximates distances correctly. I think something along the below function should work fine
float heuristic(point from, point to, size mapsize) {
float x = from.x - to.x;
if (abs(x) > mapsize.x/2)
x = mapsize.x - x;
float y = from.y - to.y;
if (abs(y) > mapsize.y/2)
y = mapsize.y - y;
return sqrt(x*x+y*y);
}
Edited: I realize know I was misled by the non-graph theoretical) use of the word edge (where the question title strongly suggested a graph algorithm question :))
Why do you suppose there are no edges? There are many logical discrete locations that you could model, and limited connections between (i.e. not where a wall is :)). There you go: you have your edges.
What you probably mean is that you don't want to represent your edges in data (which you don't have to, but still there are the logical edges that connect locations/points.)
That said:
you ask whether someone has seen things like this before. I vaguely recall seeing something relevant to this in Knuths Dancing Links article (DLX) which is an implementation technique for A* algorithms.
http://en.wikipedia.org/wiki/Dancing_Links
original publication [PDF]
The article specifically treats states as 'cells' (in a grid) with east/west/north/south links. It's been a long time so I don't quite recall how you would map (no pun intended) your problem on that algorithm.
The dance steps. One good way to implement algorithm X is to represent each 1 in the
matrix A as a data object x with five fields L[x]; R[x]; U [x]; D[x]; C[x]. Rows of the matrix
are doubly linked as circular lists via the L and R fields ("left" and "right"); columns are
doubly linked as circular lists via the U and D fields ("up" and "down"). Each column
list also includes a special data object called its list header.