public List <CurveArray> DividePolygonInHalf(XYZ divisionDirection, out Line cutLine) { Normalize(); CircularLinkedList <UV> points = GetPoints(); List <CircularLinkedListNode <UV> > newPoints = new List <CircularLinkedListNode <UV> >(); UV centroid = CalculatePolygonCentroid(points); cutLine = Line.CreateUnbound(VectorManipulator.TransformUVinXYZ(centroid), divisionDirection); foreach (Curve curve in curveArray) { SetComparisonResult result = cutLine.Intersect(curve, out IntersectionResultArray resultArray); if (result == SetComparisonResult.Overlap) { UV newPoint = VectorManipulator.ProjectInPlaneXY(resultArray.get_Item(0).XYZPoint); XYZ p0 = curve.GetEndPoint(0); XYZ p1 = curve.GetEndPoint(1); newPoints.Add(AddPointBetween(points, VectorManipulator.ProjectInPlaneXY(p0), VectorManipulator.ProjectInPlaneXY(p1), newPoint)); } } CircularLinkedList <UV> newPolygon0 = CreatePolygonBetweenVertices(newPoints[0], newPoints[1]); CircularLinkedList <UV> newPolygon1 = CreatePolygonBetweenVertices(newPoints[1], newPoints[0]); List <CurveArray> dividedCurveArrays = new List <CurveArray> { CreateCurveArrayFromPoints(newPolygon0), CreateCurveArrayFromPoints(newPolygon1) }; cutLine = Line.CreateBound(VectorManipulator.TransformUVinXYZ(newPoints[0].Value), VectorManipulator.TransformUVinXYZ(newPoints[1].Value)); return(dividedCurveArrays); }
/// <summary> /// Add a new vertice in order in the list of vertices of the polygon given the IntersectionResultArray. /// </summary> /// <param name="points"></param> /// <param name="resultArray"></param> /// <param name="curve"></param> private static CircularLinkedListNode <UV> AddPointsInList(CircularLinkedList <UV> points, IntersectionResultArray resultArray, Curve curve) { UV p0 = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(0)); CircularLinkedListNode <UV> newNode = null; CircularLinkedListNode <UV> node = FindPoint(points, p0); IntersectionResultArrayIterator iterator = resultArray.ForwardIterator(); iterator.Reset(); while (iterator.MoveNext()) { IntersectionResult result = iterator.Current as IntersectionResult; UV intersectionPoint = VectorManipulator.ProjectInPlaneXY(result.XYZPoint); newNode = points.AddAfter(node, intersectionPoint); } if (newNode.Next.Value.IsAlmostEqualTo(newNode.Value)) { points.Remove(newNode.Next.Value); } else if (newNode.Previous.Value.IsAlmostEqualTo(newNode.Value)) { points.Remove(newNode.Previous.Value); } return(newNode); }
/// <summary> /// Get the vertices of the CurveArray /// </summary> /// <param name="curveArray"> /// The CurveArray must be closed. /// </param> /// <returns> /// Returns a Linked List of UV points ordered in clock wise order. /// </returns> private CircularLinkedList <UV> GetPoints() { CircularLinkedList <UV> points = new CircularLinkedList <UV>(); foreach (Curve curve in curveArray) { UV point2D = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(0)); points.AddLast(point2D); } return(points); }
/// <summary> /// Finds a point that /// </summary> /// <param name="points"></param> /// <param name="line1"></param> /// <param name="posibleCurves"></param> /// <returns></returns> private static CircularLinkedListNode <UV> FindNewNode(ref CircularLinkedList <UV> points, Line line, CurveArray posibleCurves, UV notch) { // iterate for each possible curve, and if // a intersection is found, the point will // be added in the linked list CircularLinkedListNode <UV> newNode = null; // get the closest point UV newPoint = null, previousPoint = null; double minDistance = double.MaxValue; foreach (Curve curve in posibleCurves) { SetComparisonResult intersection = curve.Intersect(line, out IntersectionResultArray resultArray); if (intersection == SetComparisonResult.Overlap) { IntersectionResultArrayIterator iterator = resultArray.ForwardIterator(); iterator.Reset(); while (iterator.MoveNext()) { IntersectionResult result = iterator.Current as IntersectionResult; UV point = VectorManipulator.ProjectInPlaneXY(result.XYZPoint); double distance = point.DistanceTo(notch); if (distance < minDistance) { minDistance = distance; newPoint = point; previousPoint = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(0)); } } } } // insert the new point in the list CircularLinkedListNode <UV> node = FindPoint(points, previousPoint); newNode = points.AddAfter(node, newPoint); if (newNode.Next.Value.IsAlmostEqualTo(newNode.Value)) { points.Remove(newNode.Next.Value); } else if (newNode.Previous.Value.IsAlmostEqualTo(newNode.Value)) { points.Remove(newNode.Previous.Value); } return(newNode); }
private bool PosibleCurve(Curve curve, CircularLinkedListNode <UV> pointNode) { // the curve cannot contain the 2 points after or before or the pointNode itself List <UV> forbiddenPoints = new List <UV> { pointNode.Value, pointNode.Previous.Value, pointNode.Previous.Previous.Value, pointNode.Next.Value, pointNode.Next.Next.Value }; UV p0 = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(0)); UV p1 = VectorManipulator.ProjectInPlaneXY(curve.GetEndPoint(1)); return(!(SearchForUVInList(forbiddenPoints, p0) && SearchForUVInList(forbiddenPoints, p1))); }
/// <summary> /// Offset a polygon in all directions, except the edge of this polygon that is equal to the unchangedLine parameter. /// </summary> /// <param name="vertices">A list of 2D coordinates that represents the vertices of the polygon. The list must be ordered counter-clockwise</param> /// <param name="offset">The offset value.</param> /// <param name="unchangedLine">If an edge of the polygon is collinear to this line, that edge will remain unchanged.</param> /// <returns>Returns a List of 2D coordinates that represents the offseted polygon.</returns> private static CircularLinkedList <UV> OffsetPolygon(CircularLinkedList <UV> vertices, double offset, List <Line> unchangedLines) { if (offset == 0) { return(vertices); } CircularLinkedList <UV> adjusted_points = new CircularLinkedList <UV>(); CircularLinkedListNode <UV> node = vertices.Head; do { //find the points before and after our target point. UV vertexI = node.Previous.Value; UV vertexJ = node.Value; UV vertexK = node.Next.Value; //the next step is to push out each point based on the position of its surrounding points and then //figure out the intersections of the pushed out points UV v1 = vertexJ - vertexI; UV v2 = vertexK - vertexJ; // verifies if one of the segments ij, ji, jk or kj is the unchangedLine if (unchangedLines != null) { foreach (Line l in unchangedLines) { UV p0 = VectorManipulator.ProjectInPlaneXY(l.GetEndPoint(0)); UV p1 = VectorManipulator.ProjectInPlaneXY(l.GetEndPoint(1)); if ((vertexI.IsAlmostEqualTo(p0) && vertexJ.IsAlmostEqualTo(p1)) || (vertexJ.IsAlmostEqualTo(p0) && vertexI.IsAlmostEqualTo(p1))) { v1 = UV.Zero; break; } if ((vertexJ.IsAlmostEqualTo(p0) && vertexK.IsAlmostEqualTo(p1)) || (vertexK.IsAlmostEqualTo(p0) && vertexJ.IsAlmostEqualTo(p1))) { v2 = UV.Zero; break; } } } v1 = v1.Normalize() * offset; v2 = v2.Normalize() * offset; // creates a shifted line that is parallel to the vector v1 UV n1 = new UV(-v1.V, v1.U); UV pij1 = vertexI + n1; UV pij2 = vertexJ + n1; Line line1 = Line.CreateBound(VectorManipulator.TransformUVinXYZ(pij1), VectorManipulator.TransformUVinXYZ(pij2)); line1.MakeUnbound(); // creates a shifted line that is parallel to the vector v2 UV n2 = new UV(-v2.V, v2.U); UV pjk1 = vertexJ + n2; UV pjk2 = vertexK + n2; Line line2 = Line.CreateBound(VectorManipulator.TransformUVinXYZ(pjk1), VectorManipulator.TransformUVinXYZ(pjk2)); line2.MakeUnbound(); //see where the shifted lines 1 and 2 intersect SetComparisonResult comparisonResult = line1.Intersect(line2, out IntersectionResultArray intersection); if (comparisonResult == SetComparisonResult.Overlap) { IntersectionResult result = intersection.get_Item(0); UV intersection_point = VectorManipulator.ProjectInPlaneXY(result.XYZPoint); //add the intersection as our adjusted vert point adjusted_points.AddLast(new UV(intersection_point.U, intersection_point.V)); } node = node.Next; } while (node != vertices.Head); return(adjusted_points); }