3

I'm working on an algorithm which should check if two polygons, described by their vertex coordinates, are: one inside the other, are intersecting or are separated

image below describe this three cases: example

i'm thinking about how to do it but i'm not having any idea. Any suggestion?

TuoCuggino
  • 133
  • 3

3 Answers3

6

Using RegionIntersection and Area:

PolygonIntersectingQ[poly1_, poly2_] := Module[{m1, m2, area},
   {m1, m2} = MeshRegion[#, Polygon[Range@Length@#]] & /@ {poly1, poly2};
   area = Area@RegionIntersection[m1, m2];
   Switch[area,
    0, False,
    Area@m1, poly1,
    Area@m2, poly2,
    _, True]];

poly1 = {{-1, 0}, {0, 1}, {1, 3}, {1, 0}};
poly2 = {{-1, -0.5}, {2, 3}, {4, 2}};
PolygonIntersectingQ[poly1, poly2]

True

The function returns True if the polygons are intersecting, False if they are not intersecting and the inner polygon if one polygon is enclosed in the other.

paw
  • 5,650
  • 23
  • 31
5
R1 = Polygon[{{1, 0}, {1, 1}, {0, 0}}];
R2 = Polygon[{{0, 1}, {1/3, 1/2}, {0, 1/2}}];

Graphics[{R1, Red, R2}, Frame -> True]

enter image description here

Catenate @ Map[RegionMember[R1, #] &, List @@ R2] // MemberQ[#, True] &

False

R3 = Polygon[{{0, 1}, {3/4, 1/2}, {0, 1/2}}];

Graphics[{R1, Red, R3}, Frame -> True]

enter image description here

Catenate @ Map[RegionMember[R1, #] &, List @@ R3] // MemberQ[#, True] &

True

"Inside the other"

Catenate @ Map[RegionMember[R1, #] &, List @@ R1] // FreeQ[#, False] &

True

eldo
  • 67,911
  • 5
  • 60
  • 168
  • many thanks, should help – TuoCuggino Nov 09 '15 at 12:20
  • 2
    This is no general solution, your code fails for all cases where the first polygon doesn't have any of it's veritces inside the second polygon. Swapping R1 and R3 results in a wrong answer. Some cases can't be solved e.g. R1 = {{-1, 0}, {0, 1}, {1, 3}, {1, 0}}; R2 = {{-1, -0.5}, {2, 3}, {4, 2}}; – paw Nov 09 '15 at 18:18
3

using this: https://mathematica.stackexchange.com/a/51425/2079

segsegintersectionQ[lines_] := Module[{
   md = Subtract @@ (Plus @@ # & /@ lines), 
   sub = Subtract @@ # & /@ lines, det}, det = -Det[sub];
  TrueQ[And @@ (Abs[#] <= 1 & /@ #)] &@(Det[{#[[1]], md}]/
       det & /@ ({#, Reverse@#} &@sub))]; 

and this: https://mathematica.stackexchange.com/a/9408/2079

testpoint[poly_, pt_] := 
 Round[(Total@
       Mod[(# - RotateRight[#]) &@(ArcTan @@ (pt - #) & /@ poly), 
        2 Pi, -Pi]/2/Pi)] != 0

Which[  Or @@ Flatten@Outer[segsegintersectionQ[{##}] & ,
 Partition[Append[poly1, First@poly1], 2, 1],
 Partition[Append[poly2, First@poly2], 2, 1], 1] ,
                                True ,
  testpoint[poly1, poly2[[1]]], True,
  testpoint[poly2, poly1[[1]]], True]

I haven't tested but I suspect this will be faster than the Region approaches.

(You could use Or instead of Which if you don't need to separately treat the inside cases.)

george2079
  • 38,913
  • 1
  • 43
  • 110