public Point2DList(Point2DList l) { int numPoints = l.Count; for (int i = 0; i < numPoints; ++i) { mPoints.Add(l[i]); } mBoundingBox.Set(l.BoundingBox); mEpsilon = l.Epsilon; mWindingOrder = l.WindingOrder; }
public virtual void AddRange(Point2DList l) { AddRange(l.mPoints.GetEnumerator(), l.WindingOrder); }
public void MergeParallelEdges(double tolerance) { if (Count <= 3) { return; } bool[] mergeMe = new bool[Count]; int newNVertices = Count; for (int i = 0; i < Count; ++i) { int lower = (i == 0) ? (Count - 1) : (i - 1); int middle = i; int upper = (i == Count - 1) ? (0) : (i + 1); double dx0 = this[middle].X - this[lower].X; double dy0 = this[middle].Y - this[lower].Y; double dx1 = this[upper].Y - this[middle].X; double dy1 = this[upper].Y - this[middle].Y; double norm0 = Math.Sqrt(dx0 * dx0 + dy0 * dy0); double norm1 = Math.Sqrt(dx1 * dx1 + dy1 * dy1); if (!(norm0 > 0.0 && norm1 > 0.0) && newNVertices > 3) { mergeMe[i] = true; --newNVertices; } dx0 /= norm0; dy0 /= norm0; dx1 /= norm1; dy1 /= norm1; double cross = dx0 * dy1 - dx1 * dy0; double dot = dx0 * dx1 + dy0 * dy1; if (Math.Abs(cross) < tolerance && dot > 0 && newNVertices > 3) { mergeMe[i] = true; --newNVertices; } else { mergeMe[i] = false; } } if (newNVertices == Count || newNVertices == 0) { return; } int currIndex = 0; Point2DList oldVertices = new Point2DList(this); Clear(); for (int i = 0; i < oldVertices.Count; ++i) { if (mergeMe[i] || newNVertices == 0 || currIndex == newNVertices) { continue; } if (currIndex >= newNVertices) { throw new Exception("Point2DList::MergeParallelEdges - currIndex[ " + currIndex.ToString() + "] >= newNVertices[" + newNVertices + "]"); } mPoints.Add(oldVertices[i]); mBoundingBox.AddPoint(oldVertices[i]); ++currIndex; } mWindingOrder = CalculateWindingOrder(); mEpsilon = CalculateEpsilon(); }
public PolygonError CheckPolygon() { PolygonError error = PolygonError.None; if (Count < 3 || Count > Point2DList.kMaxPolygonVertices) { error |= PolygonError.NotEnoughVertices; return(error); } if (IsDegenerate()) { error |= PolygonError.Degenerate; } if (!IsSimple()) { error |= PolygonError.NotSimple; } if (GetArea() < MathUtil.EPSILON) { error |= PolygonError.AreaTooSmall; } if ((error & PolygonError.NotSimple) != PolygonError.NotSimple) { bool bReversed = false; WindingOrderType expectedWindingOrder = WindingOrderType.CCW; WindingOrderType reverseWindingOrder = WindingOrderType.CW; if (WindingOrder == reverseWindingOrder) { WindingOrder = expectedWindingOrder; bReversed = true; } Point2D[] normals = new Point2D[Count]; Point2DList vertices = new Point2DList(Count); for (int i = 0; i < Count; ++i) { vertices.Add(new Point2D(this[i].X, this[i].Y)); int i1 = i; int i2 = NextIndex(i); Point2D edge = new Point2D(this[i2].X - this[i1].X, this[i2].Y - this[i1].Y); normals[i] = Point2D.Perpendicular(edge, 1.0); normals[i].Normalize(); } for (int i = 0; i < Count; ++i) { int iminus = PreviousIndex(i); double cross = Point2D.Cross(normals[iminus], normals[i]); cross = MathUtil.Clamp(cross, -1.0f, 1.0f); float angle = (float)Math.Asin(cross); if (Math.Abs(angle) <= Point2DList.kAngularSlop) { error |= PolygonError.SidesTooCloseToParallel; break; } } if (bReversed) { WindingOrder = reverseWindingOrder; } } return(error); }