public bool Equals(IPolygon2D other) { var poly = other as Polygon2D; if (poly == null) { return(false); } if (VertexCount != poly.VertexCount) { return(false); } var vertices = Vertices.ToList(); var otherVertices = poly.Vertices.ToList(); for (var i = 0; i < VertexCount; i++) { if (!vertices[i].Equals(otherVertices[i])) { return(false); } } return(true); }
public ConvexHullTest() { m_vertices = new List <Vector2>() { new Vector2(0, 0), new Vector2(1, 1), new Vector2(0, 2), new Vector2(3, 2), new Vector2(2, -1), new Vector2(0, -1), new Vector2(-1, -2), new Vector2(-3, -1), new Vector2(-1, -0.5f), new Vector2(-4, 1), new Vector2(-2, 3), }; m_polygon = new Polygon2D(m_vertices); m_upperhull = new List <Vector2>() { m_vertices[9], m_vertices[10], m_vertices[3] }; m_lowerhull = new List <Vector2>() { m_vertices[9], m_vertices[7], m_vertices[6], m_vertices[4], m_vertices[3] }; m_hull = new Polygon2D(new List <Vector2>() { m_vertices[9], m_vertices[10], m_vertices[3], // upperhull m_vertices[4], m_vertices[6], m_vertices[7] // lowerhull }); }
public bool Equals(IPolygon2D other) { var poly = other as MultiPolygon2D; if (poly == null) { return(false); } if (Polygons.Count != poly.Polygons.Count) { return(false); } var polygons = Polygons.ToList(); var otherPolygons = poly.Polygons.ToList(); for (var i = 0; i < Polygons.Count; i++) { if (!polygons[i].Equals(otherPolygons[i])) { return(false); } } return(true); }
/// <summary> /// Checks to see if two polygons intersect /// </summary> /// <param name="a">The first polygon.</param> /// <param name="b">The second polygon.</param> /// <returns>True if the two polygons intersect. False otherwise.</returns> public static bool Intersects(IPolygon2D a, IPolygon2D b) { // See if this polygon's points are contained in the other polygon for (int i = 0; i < a.NumSides; i++) { if (b.Contains(a.Vertices[i])) { return(true); } } // See if this polygon contains the other polygon's points for (int i = 0; i < b.NumSides; i++) { if (a.Contains(b.Vertices[i])) { return(true); } } // See if any of the polygon edges intersect each other for (int i = 0; i < a.NumSides; i++) { Vector2 edgeStart = a.Vertices[i]; Vector2 edgeEnd = (i == a.NumSides - 1 ? a.Vertices[0] : a.Vertices[i + 1]); for (int j = 0; j < b.NumSides; j++) { Vector2 otherEdgeStart = a.Vertices[j]; Vector2 otherEdgeEnd = (j == a.NumSides - 1 ? a.Vertices[0] : a.Vertices[j + 1]); if (ShapeUtility.AreEdgesIntersecting(edgeStart, edgeEnd, otherEdgeStart, otherEdgeEnd)) { return(true); } } } return(false); }
public bool Equals(IPolygon2D other) { var poly = other as Polygon2DWithHoles; if (poly == null) { return(false); } if (!Outside.Equals(poly.Outside)) { return(false); } if (Holes.Count != poly.Holes.Count) { return(false); } var holes = Holes.ToList(); var otherHoles = poly.Holes.ToList(); for (var i = 0; i < holes.Count; i++) { if (!holes[i].Equals(otherHoles[i])) { return(false); } } return(true); }
/// <summary> /// Divide <c>ParabolicArcSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Region2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { var segment = source as ParabolicArcSegment2D; // The angle in degrees double totalAngle = segment.GetAngle(ref start); if (angle < Math.Abs(totalAngle) || this.numberOfTiles > 1) { int numberOfTiles = Math.Max((int)Math.Ceiling(Math.Abs(totalAngle) / angle), this.numberOfTiles); double deltaAngle = totalAngle / numberOfTiles; var mat = new Matrix(); mat.Rotate(deltaAngle); var t = segment.GetTangentOnSegment(ref start, 0); for (int i = 1; i < numberOfTiles; ++i) { t = mat.Transform(t); if (segment.CoordinatesFromTangent(ref start, t, out Point p)) { target.Add(p); } } } target.Add(segment.EndPoint); }
private static List <IntPoint> CreatePolygon(IPolygon2D polygon, bool counterClockwise) { if (polygon.IsCounterClockwise != counterClockwise) { polygon.Reverse(); } return(CreatePolygon(polygon)); }
protected static List <IntPoint> CreatePolygon(IPolygon2D polygon) { var count = polygon.Count; var cpolygon = new List <IntPoint>(count); for (int i = 0; i < count; ++i) { cpolygon.Add(new IntPoint((long)(polygon[i].X * ClipperScale), (long)(polygon[i].Y * ClipperScale))); } return(cpolygon); }
/// <summary> /// Calculates the average of all vertices on a polygon /// </summary> /// <param name="shape">The polygon.</param> /// <returns>The center point of the polygon.</returns> public static Vector2 CalculateCenterPoint(IPolygon2D shape) { Vector2 pointSum = VectorUtility.Zero; for (int i = 0; i < shape.NumSides; i++) { pointSum += shape.Vertices[i]; } Vector2 pointAverage = pointSum / shape.NumSides; return(pointAverage); }
/// <summary> /// Compare points of polygon with <paramref name="pattern"/>. /// </summary> /// <param name="pattern">Polygon to be compared with this instance.</param> /// <param name="tolerance">Tolerance used in comparison of coordinates</param> /// <returns>True if all points are equal.</returns> public bool EqualPoints(IPolygon2D pattern, double tolerance) { for (int i = 0, sz = this.Count; i < sz; i++) { Point left = this[i]; Point right = pattern[i]; if (!left.X.IsEqual(right.X, tolerance) || !left.Y.IsEqual(right.Y, tolerance)) { return(false); } } return(true); }
/// <summary> /// combine 2 convex hulls /// </summary> public static Polygon2D ComputeConvexHull(IPolygon2D polygon1, IPolygon2D polygon2) { //TODO: change to O(n) algorithm List <Vector2> vl = new List <Vector2>(); foreach (var v in polygon1.Vertices) { vl.Add(v); } foreach (var v in polygon2.Vertices) { vl.Add(v); } return(ComputeConvexHull(vl)); }
/// <summary> /// Calculates the vector pointing to the furthest vertex of the specified polygon if the polygon is centered at 0,0. /// </summary> /// <param name="shape">The polygon.</param> /// <returns>The vector pointing to the furthest vertex of the specified polygon if the polygon is centered at 0,0.</returns> public static Vector2 CalculateOuterRadius(IPolygon2D shape) { Vector2 max = VectorUtility.Zero; Vector2 vector; for (int i = 0; i < shape.NumSides; i++) { vector = shape.Vertices[i] - shape.Center; if (vector.Length() > max.Length()) { max = vector; } } return(max); }
/// <summary> /// Divide <c>LineSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Polygon2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { double length = source.GetLength(ref start); if (numberOfTiles > 1 || length > lengthOfTile) { int tiles = Math.Max(numberOfTiles, (int)Math.Ceiling(length / lengthOfTile)); LineSegment2D segment = source as LineSegment2D; Vector u = Point.Subtract(segment.EndPoint, start) / tiles; Point pt = start; for (int i = 1; i < tiles; ++i) { pt = Point.Add(pt, u); target.Add(pt); } } target.Add(source.EndPoint); }
public static IEnumerable <IPolyLine2D> BuildOffset(IPolygon2D polygon, double delta, JoinType joinType, EndType endType, double mitterLimit, double maxDiscretizationAngle = 5) { bool containsCircArc = false; var p = CreatePolygon(polygon); if (joinType == JoinType.jtRound || endType == EndType.etOpenRound) { containsCircArc = true; } var co = new ClipperOffset(mitterLimit); co.AddPath(p, joinType, endType); var solution = new List <List <IntPoint> >(); co.Execute(ref solution, delta * ClipperScale); foreach (var poly in solution) { yield return(CreatePolyline(poly, containsCircArc, maxDiscretizationAngle + 1)); } }
/// <summary> /// Discretize of <c>PolyLine2D</c> to <c>Polygon2D</c>. /// </summary> /// <param name="source">The <c>PolyLine2D</c> to discretization.</param> /// <param name="target">The <c>Polygon2D</c> as destination.</param> /// <param name="targetInxs">The <c>IList</c> as destination.</param> public void Discretize(IPolyLine2D source, ref IPolygon2D target, IList <int> targetInxs) { if (source == null) { return; } Point start = source.StartPoint; target.Add(start); int i = 0; int lastInx = 0; foreach (var segment in source.Segments) { SelectSegment2DDiscretizator(segment.GetType()).Discretize(start, segment, target); start = segment.EndPoint; if (targetInxs != null) { for (int j = lastInx; j < target.Count; j++) { targetInxs.Add(i); } lastInx = target.Count; } i++; } if (targetInxs != null) { if (source.IsClosed && (targetInxs.Count > 0)) { targetInxs[0] = targetInxs[targetInxs.Count - 1]; } } }
/// <summary> /// Divide <c>CircularArcSegment2D</c> on straight lines polygon. /// </summary> /// <param name="start">The start point of segment.</param> /// <param name="source">The segment to discretization.</param> /// <param name="target">The <c>Region2D</c> as target of discretization.</param> public void Discretize(Point start, ISegment2D source, IPolygon2D target) { CircularArcSegment2D segment = source as CircularArcSegment2D; // The angle in degrees double totalAngle = Math.Abs(segment.GetAngle(ref start)); if (angle < totalAngle || this.numberOfTiles > 1) { int numberOfTiles = Math.Max((int)Math.Ceiling(totalAngle / angle), this.numberOfTiles); double deltaAngle = totalAngle / numberOfTiles * segment.IsCounterClockwise(ref start); Matrix mat = new Matrix(); Point centre = segment.GetCentre(ref start); for (int i = 1; i < numberOfTiles; ++i) { mat.RotateAt(deltaAngle, centre.X, centre.Y); target.Add(mat.Transform(start)); } } target.Add(segment.EndPoint); }
internal static IPolyLine3D ConvertTo3D(IPolygon2D polygon2D, Func <double, double, IPoint3D> createPoint, IMatrix44 lcs = null) { if (polygon2D == null) { return(null); } var count = polygon2D.Count; if (count > 1) { var polyline3D = new PolyLine3D(); var beg = createPoint(polygon2D[0].X, polygon2D[0].Y); for (var i = 1; i < count; ++i) { var end = createPoint(polygon2D[i].X, polygon2D[i].Y); var seg = new LineSegment3D(beg, end); polyline3D.Add(seg); beg = end; } if (polygon2D.IsClosed) { polyline3D.Segments.Last().EndPoint = polyline3D.Segments.First().StartPoint; } if (lcs != null) { GeomOperation.TransformToGCS(lcs, polyline3D); } return(polyline3D); } return(null); }
/// <summary> /// Checks for intersection between a polygon and a circle. /// </summary> /// <param name="polygon">The circle.</param> /// <param name="circle">The polygon.</param> /// <returns>True if the two shapes intersect. False othwerise.</returns> public static bool Intersects(IPolygon2D polygon, ICircle2D circle) { // See if the closest point of each edge to the circle's center is inside the center Vector2 circleCenter = circle.Center; for (int i = 0; i < polygon.NumSides; i++) { Vector2 closestPointOfEdge = (i == polygon.NumSides - 1 ? ShapeUtility.CalculateClosestPointOnEdge(circleCenter, polygon.Vertices[i], polygon.Vertices[0]) : ShapeUtility.CalculateClosestPointOnEdge(circleCenter, polygon.Vertices[i], polygon.Vertices[i + 1])); if (circle.Contains(closestPointOfEdge)) { return(true); } } // See if this polygon contains the other circle if (polygon.Contains(circle.Center)) { return(true); } return(false); }
/// <summary> /// Triangulates this polygon using the two ears theorem. This is O(n^2). /// </summary> /// <remarks> /// Currently runs in O(n^2) time. /// TODO improve this to O(n log n) or O(n log log n). /// </remarks> /// <param name="polygon"></param> /// <param name="setTwinPointers"> whether the triangulation should set twin pointers </param> /// <returns>A list of clockwise triangles whose disjoint union is this polygon</returns> public static Triangulation Triangulate(IPolygon2D polygon, bool setTwinPointers = true) { // cannot yet triangulate non-simple polygons /* assume it to be, checks takes too long * if (!polygon.IsSimple()) * { * throw new ArgumentException("Polygon must be simple: " + polygon); * } */ if (polygon.VertexCount < 3) { return(new Triangulation()); } var T = TriangulateRecursive(polygon.Vertices.ToList()); if (setTwinPointers) { T.SetTwinPointers(); } return(T); }
public bool Intersects(IPolygon2D other) { return(ShapeUtility.Intersects(other, this)); }
/// <summary> /// Computes the lower hull of the given polygon /// </summary> /// <param name="polygon"></param> /// <returns></returns> public static List <Vector2> ComputeLowerHull(IPolygon2D polygon) { return(ComputeHull(polygon.Vertices, -1)); }
public override bool Intersects(IPolygon2D other) { return(ShapeUtility.Intersects(this, other)); }
public bool Equals(IPolygon2D other) { throw new NotImplementedException(); }
public void Add(IPolygon2D polygon, PolyType type) { var p = CreatePolygon(polygon); this.clipper.AddPath(p, type, polygon.IsClosed); }
public abstract bool Intersects(IPolygon2D other);
public static void DrawPolygon(this SpriteBatch spriteBatch, IPolygon2D polygon, Color color) { DrawPolygon(spriteBatch, polygon.Vertices, polygon.NumSides, color, Matrix.Identity); }
public static void DrawPolygon(this SpriteBatch spriteBatch, IPolygon2D polygon, Color color, Matrix transformFromWorldToCamera) { DrawPolygon(spriteBatch, polygon.Vertices, polygon.NumSides, color, transformFromWorldToCamera); }
/// <summary> /// Finds the closets point on the polygon to the specified point. /// </summary> /// <param name="point">The point to find the closest point to.</param> /// <param name="polygon">The polygon on which to find the closets point.</param> /// <returns>The point on the polygon that is closest to the specified point.</returns> public static Vector2 FindClosestPointOnPolygon(Vector2 point, IPolygon2D polygon) { return(FindClosestPointOnPolygon(point, polygon.Vertices, polygon.NumSides)); }
/// <summary> /// Checks to see whether the specified point lies in the specified complex polygon. Complex polygon here /// means that the polygon may contain convex vertices. /// </summary> /// <param name="point">The point to check containment for.</param> /// <param name="polygon">The polygon to check containment for.</param> /// <returns>True if the point lies within the polygon, false otherwise.</returns> public static bool ContainsForComplexPolygon(Vector2 point, IPolygon2D polygon) { return(ContainsForComplexPolygon(point, polygon.Vertices, polygon.NumSides)); }
/// <summary> /// Calculates the vector pointing to the nearest point on the polygon if the center is at 0,0. /// </summary> /// <param name="shape">The polygon.</param> /// <returns>The vector pointing to the nearest point on the polygon if the center is at 0,0.</returns> public static Vector2 CalculateInnerRadius(IPolygon2D shape) { return(shape.FindClosestPoint(shape.Center) - shape.Center); }