private static void ConnectIntersections(SplitVertex start, SplitVertex end, List<SplitVertex> intersections, bool? direction, List<SplitVertex> polygon) { int index1 = intersections.IndexOf(start); int index2 = intersections.IndexOf(end); if (Math.Abs(index1 - index2) == 1) return; // int step = index2 > index1 ? 1 : -1; // index2 -= step; // index1 += step; // // for (; index2 != index1; index2 -= step) // { // var cornerDirection = intersections[index2].GetDirection (intersections[index2].GetNextIntersection ()); // if (cornerDirection != direction && cornerDirection != null) // { // do // { // polygon.Add (end); // end = end.Next; // } while (!end.IsIntersect); // polygon.Add (end); // } // } SplitVertex stop; if (index2 > index1) { end = intersections [index2 - 1]; stop = intersections [index1 + 1]; } else { end = intersections [index2 + 1]; stop = intersections [index1 - 1]; } while(end != stop) { //connect vertex when encounter concave intersection if (end.IsIntersect) { var cornerDirection = end.GetDirection (end.GetNextIntersection ()); if (cornerDirection != direction && cornerDirection != null) { double cp1 = SplitVertex.CrossProduct (intersections [0], intersections [intersections.Count - 1], start.Next); double cp2 = SplitVertex.CrossProduct (intersections [0], intersections [intersections.Count - 1], end.Next); if (cp1 * cp2 > 0) { do { polygon.Add (end); end = end.Next; } while (!end.IsIntersect); polygon.Add (end); var ind = intersections.IndexOf(end); if (index2 > index1) ind--; else ind++; if(end != stop) end = intersections[ind]; } else end = end.Next; } else end = end.Next; } else end = end.Next; } }
public static List<List<SplitVertex>> Split(SplitVertex polygon, Point p1, Point p2) { var ins = new List<SplitVertex>(); //phase 1 get all intersection SplitVertex current = polygon; do { var next = current.Next; var cross = Line.IntersectWithSegment(p1, p2, current.ToPoint(), next.ToPoint()); if (cross.HasValue) { var iv = cross.Value.ToSplitVertex(); iv.IsIntersect = true; iv.Next = next; iv.Previous = current; next.Previous = iv; current.Next = iv; if (ins.Count == 0) ins.Add(iv); else { int j = 0; for (; j<ins.Count && (cross.Value.X > ins[j].X || (cross.Value.X == ins[j].X && cross.Value.Y >ins[j].Y)); j++); if(j == ins.Count) ins.Add(iv); else ins.Insert(j, iv); } } current = next; } while (current != polygon); var result = new List<List<SplitVertex>>(); if (ins.Count == 0) { result.Add(polygon.ToList()); return result; } //phase 2 current = ins[0]; bool? direction = polygon.GetDirection(); do { //create new polygon when encouter convex intersection if(current.IsIntersect && current.GetDirection(current.GetNextIntersection()) == direction) { var fi = current; var sp = new List<SplitVertex>(); result.Add(sp); do { sp.Add(current); current = current.Next; } while (!current.IsIntersect); sp.Add(current); ConnectIntersections(fi,current,ins,direction,sp); } else current = current.Next; } while (current != ins[0]); return result; }
public bool? GetDirection(SplitVertex end) { double signedArea = 0; SplitVertex v = this; do { signedArea += (v.X * v.Next.Y - v.Next.X * v.Y); v = v.Next; } while (v != end); signedArea += (end.X * Y - X * end.Y); if (signedArea == 0) return null; return signedArea > 0; }
public static double CrossProduct(SplitVertex v1,SplitVertex v2,SplitVertex v3) { return (v2.X - v1.X) * (v3.Y - v2.Y) - (v2.Y - v1.Y) * (v3.X - v2.X); }