How to intersect two polygons?

23,510

Solution 1

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.

Solution 2

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.

Solution 3

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);

Solution 4

You may also want to have a look at the NetTopologySuite or even try importing it into Sql server 2008 & it's spatial tools.

Solution 5

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.

Share:
23,510
darkAsPitch
Author by

darkAsPitch

I am an software developer that is not afraid to get his hands dirty... I done time in Visual Basic and never complained. PHP? Sure. I can write beautiful code in any language. But Python really rocks my boat. And c# I like too. I tend to collect a lot of different tools and am especially fond of those that work well together - as opposed to technologies that tend to create silos with NIHS. As I mature as a software developer, I have found that my passion for the craft grows while at the same time my willingness to participate in flame wars shrinks. Let's just get it done. And make the user happy.

Updated on October 13, 2020

Comments

  • darkAsPitch
    darkAsPitch over 3 years

    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!