23

Yesterday I was looking to check if a point was inside a polygon and found this great script: https://github.com/tparkin/Google-Maps-Point-in-Polygon

But today at work I was told that our client needs to check if one polygon is inside another polygon. I am wondering if is there a formula where I can take, let's say, two coordinates (instead of one to check a point), and from those two coordinates generate a rectangle and check if that rectangle is inside a polygon.

I don't know if I'm asking a stupid question (a teacher in highschool used to say "there are no stupid questions, there is only fools who don't ask"), but if you don't understand me totally but just a bit, I'd be grateful if you just tell me where to start.

moinudin
  • 134,091
  • 45
  • 190
  • 216
chuysbz
  • 1,262
  • 6
  • 18
  • 47
  • 3
    Check if all points of polygon A are inside polygon B –  Jan 28 '11 at 22:50
  • I would first check to see if corners of the bounding box of one polygon are inside the other; that will be a fast test. After that, though, follow @M28's advice and check every point of one polygon inside the other. – Phrogz Jan 28 '11 at 22:52
  • 2
    @M28 Checking just the vertex points doesn't work. If B is not convex, then you have (many) cases where all of A vertices are in B, but a portion of A still crosses outside of B. – payne Jan 29 '11 at 14:19
  • @payne True, but he said he would only use rectangles –  Jan 29 '11 at 18:41
  • 2
    @M28: he said he's checking to see if a rectangle is inside a polygon. Consider a polygon that's a star-like shape: all the corners of the rectangle could be inside the star, but portions of the rectangle could lie outside the star. – payne Jan 29 '11 at 18:43
  • @payne Yep, Now I noticed that he said a rectangle inside a polygon. –  Jan 29 '11 at 18:45

5 Answers5

38

Perform line intersection tests for each pair of lines, one from each polygon. If no pairs of lines intersect and one of the line end-points of polygon A is inside polygon B, then A is entirely inside B.

The above works for any type of polygon. If the polygons are convex, you can skip the line intersection tests and just test that all line end-points of A are inside B.

If really necessary, you can speed up the line intersection tests using the sweep line algorithm.

moinudin
  • 134,091
  • 45
  • 190
  • 216
  • 1
    If there are no line intersections, then wouldn't you only need to check one point? – sdleihssirhc Jan 28 '11 at 22:55
  • That would do it. Very slow algorithm though, isn't it? O(n!) I think. – brian-d Jan 28 '11 at 23:01
  • @Hops O(NM) where A has N sides, B has M. You can speed it up if necessary, but since OP mentions one of the polygons is a rectangle I don't see the point since it makes the solution a lot more complex. I've edited in how to do this. – moinudin Jan 28 '11 at 23:05
  • 1
    Gah. Brain fart on my side. That's what I get for trying to think this through on a Friday afternoon. Sides... not points. For some reason I was thinking you'd have to check every possible line in the polygon... not the lines actually making up the polygon. Been one of those days, thanks for setting me straight :) – brian-d Jan 28 '11 at 23:11
  • If there's no intersection, they could also be near each-other. They don't have to contain one another. – Yochai Timmer Jan 29 '11 at 13:30
  • @Yochai That's why you test if one of the polygon's points is insider the other polygon. – moinudin Jan 29 '11 at 14:58
  • @marcog: what if one polygon is sharing some of its vertices with another and is just touching it? In that case if you chose a wrong (=shared) vertex for testing, you'd come with a wrong conclusion that one polygon is actually inside the other. – Igor Brejc Nov 16 '12 at 09:40
  • @IgorBrejc: I can imagine vertices to share (have identical) coordinates (coincide). What does it mean for polygons to _share vertices_? – greybeard Dec 06 '16 at 17:09
  • In some applications polygons can have holes. In that case the above algorithm would need to be adapted. Also, depending on the application, you should be careful about numerical precision when computing intersections of degenerate cases (e.g point on line). – Pablo H May 10 '17 at 00:49
  • This algorithm works only for polygons with no holes in any polygon and only for one polygon being truly inside the other. A polygon that shares edges ([example](https://gist.github.com/kelunik/7ac6602bf546da84dd96e360fae48f14)) isn't detected correctly and requires all points of one polygon to be inside the other (in case there are any overlapping edges) as far as I can tell. – kelunik Feb 20 '18 at 10:17
2

First check that one of the corner points in the polygon is inside the other polygon using the script. Then check if any of the lines in the polygon crosses any of the lines in the other polygon. If they don't, the polygon is inside the other polygon.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Nope. That would only work for rectangles or squares. – NickG Oct 20 '22 at 14:03
  • 1
    @NickG: I don't see where you get that limitation from. If one point of a polygon is inside the other, and no lines of the polygon crosses outside the other, then the entire polygon is clearly inside the other. – Guffa Oct 28 '22 at 10:39
  • Yeah I think I misread it - sorry :) – NickG Oct 28 '22 at 15:21
0

Maybe this part of the code can help you:

package com.polygons;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;

/**
 * Utility to Manipulate Polygons
 * 
 * @author fernando.hernandez
 *
 */

public class PolygonUtils {

    /**
     * Check if  polygon2 is inside polygon to polygon1
     * @param polygon1 polygon that contains other 
     * @param polygon2 polygon that is inner to other
     * @return true if polygon2 is inner to polygon1
     */
    public boolean isInsidePolygon(Polygon polygon1, Polygon polygon2){
        //all points in inner Polygon should be contained in polygon
        int[] xpoints = polygon2.xpoints;
        int[] ypoints = polygon2.ypoints;
        boolean result =  true;
        for (int i = 0, j = 0; i < polygon2.npoints ; i++,j++) {
             result = polygon1.contains(new Point(xpoints[i], ypoints[j]));
             if(!result) break;   
        }
        return result;
    }
}
Marko Letic
  • 2,460
  • 2
  • 28
  • 34
zeta
  • 39
  • 4
  • 4
    This only works for convex outer shapes. Concave outer shapes can contain all the points of the inner shape, but have overlapping edges. – thelastshadow Aug 24 '15 at 09:09
0

I had to find a similar solution. Here is what i have so far :

  1. First i fetched all the level 1 polygon coordinates in an array[pol1cords[cord1,cord2...],pol2cords[cord1,cord2...],..]
  2. Then fetched all the level 3 polygons and plotted them
  3. Then for each level 1 polygon, i checked if each of the polygon coordinates was inside the plotted level 3 coordinate with google.maps.geometry.poly.containsLocation(latLng, pol)
  4. If it returned true counter would go up
  5. At last if the counter was equal to the length of that array, the result would be true(the level 1 polygon is inside the level3 polygon).

My algorithm looks something like this:

""Zone(level 3)->District(level 2)->VDC(level 1)"" vdcs = getVDCs(); -> gives vdcs in an array which has name, id and polygon coordinates zones = getZones(); ->gives zones in an array which has name, id and polygon coordinates

foreach(zones as zone){
    drawPolygon(zone[coordinates]);
    foreach(vdcs as vdc){
        foreach(vdc[coordinates] as coordinate){
            result = checkLocation(zone, coordinate);
            if(result) counter++;
        }
        if(counter = vdc[coordinates].length){writeConsole(vdc_id+"true in"+zone_id)}
    }
}
Marko Letic
  • 2,460
  • 2
  • 28
  • 34
0

Is the polygon convex? Because, if it is, you could just run the "point in polygon" script for both "corners" of your "rectangle." If both corners are in, and the polygon has no "curves" inward, then wouldn't the whole rectangle be in?

sdleihssirhc
  • 42,000
  • 6
  • 53
  • 67