public ConvexPolygon(Point[] points) { if (points.Length < 3) { throw new ArgumentException("Too few points (" + points.Length + "). There should be at least 3 points to make a polygon"); } // Checking convexity double sign_value = Vector.CrossProduct( (Vector)points[0] - (Vector)points[points.Length - 1], (Vector)points[1] - (Vector)points[points.Length - 1]); double sign_value2 = Vector.CrossProduct( (Vector)points[points.Length - 1] - (Vector)points[points.Length - 2], (Vector)points[0] - (Vector)points[points.Length - 2]); if (Math.Sign(sign_value) * Math.Sign(sign_value2) < 0) throw new PolygonNotConvexException("Polygon isn't convex"); for (int i = 0; i < points.Length - 2; i++) { double sign_value_i = Vector.CrossProduct( (Vector)points[i + 1] - (Vector)points[i], (Vector)points[i + 2] - (Vector)points[i]); if (Math.Sign(sign_value) * Math.Sign(sign_value_i) < 0) throw new PolygonNotConvexException("Polygon isn't convex"); } // Sorting points clockwise if (sign_value > 0) mVertex = points; else { mVertex = new Point[points.Length]; for (int i = 0; i < points.Length; i++) { mVertex[i] = points[points.Length - 1 - i]; } } // Constructing sides mSides = new Segment[mVertex.Length]; mSides[mVertex.Length - 1] = new Segment(mVertex[mVertex.Length - 1], mVertex[0]); for (int i = 0; i < mVertex.Length - 1; i++) mSides[i] = new Segment(mVertex[i], mVertex[i + 1]); // Calculating bounding box mXMin = mVertex[0].X; mXMax = mVertex[0].X; mYMin = mVertex[0].Y; mYMax = mVertex[0].Y; for (int i = 1; i < mVertex.Length; i++) { if (mXMin > mVertex[i].X) mXMin = mVertex[i].X; if (mYMin > mVertex[i].Y) mYMin = mVertex[i].Y; if (mXMax < mVertex[i].X) mXMax = mVertex[i].X; if (mYMax < mVertex[i].Y) mYMax = mVertex[i].Y; } }
public static Point GetCrossing(Segment s1, Segment s2) { // Algorithmic equality if (s1 == s2) throw new SelfCrossingException("Trying to find selfcrossing"); // TODO: Add rough estimation here (i.e. rectangle estimation) if (s1._Crossings.ContainsKey(s2)) return s1._Crossings[s2]; // TODO: Check integrity // Parallelism and zero-length Vector AB1 = new Vector(s1._B.X - s1._A.X, s1._B.Y - s1._A.Y); Vector AB2 = new Vector(s2._B.X - s2._A.X, s2._B.Y - s2._A.Y); double D = Vector.CrossProduct(AB2, AB1); if (Math.Abs(D) == 0) return null; if (s1._A == s2._A || s1._A == s2._B) return s1._A; if (s1._B == s2._A || s1._B == s2._B) return s1._B; // Calculating crossing between lines double m = Vector.CrossProduct((Vector)s1._A, AB1); double n = Vector.CrossProduct((Vector)s2._A, AB2); double x = (m * AB2.X - n * AB1.X) / D; double y = (m * AB2.Y - n * AB1.Y) / D; // Checking if an endpoint of one segment is contained by other if (s1._A.X == x && s1._A.Y == y) return s1._A; if (s1._B.X == x && s1._B.Y == y) return s1._B; if (s2._A.X == x && s2._A.Y == y) return s2._A; if (s2._B.X == x && s2._B.Y == y) return s2._B; // Checking if the crossing point is in both segments Vector AC1 = new Vector(x - s1._A.X, y - s1._A.Y); Vector BC1 = new Vector(x - s1._B.X, y - s1._B.Y); if ((AB1 * AC1) * (-AB1 * BC1) < 0) return null; Vector AC2 = new Vector(x - s2._A.X, y - s2._A.Y); Vector BC2 = new Vector(x - s2._B.X, y - s2._B.Y); if ((AB2 * AC2) * (-AB2 * BC2) < 0) return null; // Adding the point to crossing dictionaries Point crs = new Point(x, y); s1._Crossings.Add(s2, crs); s2._Crossings.Add(s1, crs); return crs; }
public int IndexOfSide(Segment side) { for (int i = 0; i < mSides.Length; i++) if (mSides[i] == side) return i; return -1; }
public bool HasCrossing(Point crossing, out Segment mySide, out Segment other) { mySide = null; other = null; for (int i = 0; i < mSides.Length; i++) { Segment res = mSides[i].HasCrossing(crossing); if (res != null) { mySide = mSides[i]; other = res; return true; } } return false; }