Beispiel #1
0
        public bool Normalize()
        {
            bool normalized = true;
            CircularLinkedList <UV>     points = GetPoints();
            CircularLinkedListNode <UV> node   = points.Head;

            do
            {
                UV p0 = node.Previous.Value;
                UV p1 = node.Value;
                UV p2 = node.Next.Value;

                double angle = VectorManipulator.CalculatesAngle(p0, p1, p2);
                if (AlmostEqual(angle, Math.PI, 0.01) || AlmostEqual(angle, 0, 0.01))
                {
                    points.Remove(p1);
                    normalized = false;
                }
                node = node.Next;
            } while (node != points.Head);

            curveArray = CreateCurveArrayFromPoints(points);

            if (!normalized)
            {
                Normalize();
            }

            return(normalized);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        /// <summary>
        /// Get all notches in a list of ordered points that represent the vertices of
        /// a polygon. A notch is a point that the reflex angle in internal.
        /// </summary>
        /// <param name="points">
        /// The poitns in the LinkedList must be ordered in clockwise order.
        /// </param>
        /// <returns>
        /// Returns a List with the notches.
        /// </returns>
        private List <UV> GetNotches(CircularLinkedList <UV> points)
        {
            List <UV> notches = new List <UV>();

            if (points.Count < 5)
            {
                return(notches);
            }

            CircularLinkedListNode <UV> node = points.Head;

            do
            {
                UV     p0    = node.Value;
                UV     p1    = node.Next.Value;
                UV     p2    = node.Next.Next.Value;
                double angle = VectorManipulator.CalculatesAngle(p0, p1, p2);
                if (angle > Math.PI)
                {
                    notches.Add(p1);
                }

                node = node.Next;
            } while (node != points.Head);

            return(notches);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <summary>
        /// Create a sub group of the linkedList that starts with node 'first' and ends with node 'last'.
        /// </summary>
        /// <param name="first"></param>
        /// <param name="last"></param>
        /// <returns>
        /// Returns the vertives of the new polygon.
        /// </returns>
        private CircularLinkedList <UV> CreatePolygonBetweenVertices(CircularLinkedListNode <UV> first, CircularLinkedListNode <UV> last)
        {
            CircularLinkedList <UV>     polygon = new CircularLinkedList <UV>();
            CircularLinkedListNode <UV> node    = first;

            do
            {
                polygon.AddLast(node.Value);
                node = node.Next;
            } while (node != last);
            polygon.AddLast(node.Value);
            return(polygon);
        }
Beispiel #7
0
        private UV CalculatePolygonCentroid(CircularLinkedList <UV> vertices)
        {
            CircularLinkedListNode <UV> node = vertices.Head;
            UV sum = UV.Zero;

            do
            {
                UV vertex = node.Value;
                sum += vertex;
                node = node.Next;
            } while (node != vertices.Head);
            sum /= vertices.Count;
            return(sum);
        }
Beispiel #8
0
        /// <summary>
        /// Eliminates a notch by creating a new line between the notch and an edge of the polygon.
        /// </summary>
        /// <param name="notch">Coordinates of the notch.</param>
        /// <param name="curveArray">The polygon.</param>
        /// <param name="points">The vertices of the polygon.</param>
        /// <param name="preferredOrientation">The method will try to make a cut that is parallel to this vector.</param>
        /// <param name="cutLine">The line that cut the polygon.</param>
        /// <returns>
        /// Returns the list of the CurveArrays.
        /// </returns>
        private List <CurveArray> EliminateNotch(UV notch, CurveArray curveArray, CircularLinkedList <UV> points, XYZ preferredOrientation, out Line cutLine)
        {
            XYZ  notche3D = VectorManipulator.TransformUVinXYZ(notch);
            Line line1    = Line.CreateUnbound(notche3D, preferredOrientation);

            XYZ  otherOrientation = new XYZ(preferredOrientation.Y, preferredOrientation.X, 0);
            Line line2            = Line.CreateUnbound(notche3D, otherOrientation);

            CircularLinkedListNode <UV> notchNode = FindPoint(points, notch);

            // get the posible curves for the new point
            CurveArray posibleCurves = new CurveArray();

            foreach (Curve curve in curveArray)
            {
                if (PosibleCurve(curve, notchNode))
                {
                    posibleCurves.Append(curve);
                }
            }

            // iterate for each possible curve, and if
            // a intersection is found, the point will
            // added in the linked list
            CircularLinkedListNode <UV> newNode;

            newNode = FindNewNode(ref points, line1, posibleCurves, notch);

            if (newNode == null)
            {
                newNode = FindNewNode(ref points, line2, posibleCurves, notch);
            }

            // generates the 2 new polygons
            CircularLinkedList <UV> polygonA = CreatePolygonBetweenVertices(newNode, notchNode);
            CircularLinkedList <UV> polygonB = CreatePolygonBetweenVertices(notchNode, newNode);

            // creates the curves
            List <CurveArray> list = new List <CurveArray>
            {
                CreateCurveArrayFromPoints(polygonA),
                CreateCurveArrayFromPoints(polygonB)
            };

            // returns the cutLine
            cutLine = Line.CreateBound(notche3D, VectorManipulator.TransformUVinXYZ(newNode.Value));

            return(list);
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #10
0
        /// <summary>
        /// Creates a Curve Array given the Boundary Segments.
        /// </summary>
        /// <param name="offset">
        /// A positive value that represents the offset that the curve array will have in a direction.
        /// If this value is 0, the user may not pass an offsetVector.
        /// <returns>
        /// Returns the offseted Curve Array.
        /// </returns>
        public CurveArray CreateOffsetedCurveArray(double offset, List <Line> unchangedLines)
        {
            if (offset < 0 || curveArray.Size < 3)
            {
                return(null);
            }

            Normalize();
            CircularLinkedList <UV> points         = GetPoints();
            CircularLinkedList <UV> offsetedPoints = OffsetPolygon(points, offset, unchangedLines);

            CircularLinkedList <UV> linkedOffsetedPoints = new CircularLinkedList <UV>(offsetedPoints);
            CurveArray offsetedCurveArray = CreateCurveArrayFromPoints(linkedOffsetedPoints);

            return(offsetedCurveArray);
        }
Beispiel #11
0
        /// <summary>
        /// Searches for a point in the LinkedList
        /// </summary>
        /// <returns>
        /// Returns the node.
        /// </returns>
        private static CircularLinkedListNode <UV> FindPoint(CircularLinkedList <UV> points, UV key)
        {
            CircularLinkedListNode <UV> node = points.Head;

            do
            {
                UV point = node.Value;
                if (point.IsAlmostEqualTo(key, 0.01))
                {
                    return(node);
                }

                node = node.Next;
            } while (node != points.Head);
            return(null);
        }
Beispiel #12
0
        private static CircularLinkedListNode <UV> AddPointBetween(CircularLinkedList <UV> points, UV p0, UV p1, UV newPoint)
        {
            CircularLinkedListNode <UV> p0Node = FindPoint(points, p0);
            CircularLinkedListNode <UV> p1Node = FindPoint(points, p1);

            if (p0Node.Next.Equals(p1Node))
            {
                return(points.AddAfter(p0Node, newPoint));
            }

            if (p1Node.Next.Equals(p0Node))
            {
                return(points.AddAfter(p1Node, newPoint));
            }

            throw new ArgumentException("The points are not sequential.");
        }
Beispiel #13
0
        /// <summary>
        /// Create a CurveArray given its vertices.
        /// </summary>
        public CurveArray CreateCurveArrayFromPoints(CircularLinkedList <UV> points)
        {
            CurveArray curveArray            = new CurveArray();
            CircularLinkedListNode <UV> node = points.Head;
            Line line;

            do
            {
                // for the cases that the 2 lines are colinear
                if (!node.Value.IsAlmostEqualTo(node.Next.Value))
                {
                    line = Line.CreateBound(VectorManipulator.TransformUVinXYZ(node.Value), VectorManipulator.TransformUVinXYZ(node.Next.Value));
                    curveArray.Append(line);
                }
                node = node.Next;
            } while (node != points.Head);
            return(curveArray);
        }
Beispiel #14
0
        /// <summary>
        /// Decompose a non convex perimiter into its convex components. There is no
        /// garantee that it will be the mininum number of convex polygons. All the
        /// angles of the perimeter must be a multiple of PI/2 radians.
        /// </summary>
        /// <returns>
        /// Returns a List of CurveArrays that represents the convex compenents.
        /// </returns>
        public List <CurveArray> GetConvexPerimeters(XYZ preferredOrientation, List <Line> cutLines)
        {
            CircularLinkedList <UV> points = GetPoints();
            List <UV>         notches      = GetNotches(points);
            List <CurveArray> perimeters   = new List <CurveArray>();

            if (notches.Count == 0)
            {
                perimeters.Add(curveArray);
                return(perimeters);
            }

            List <CurveArray> result = EliminateNotch(notches[0], curveArray, points, preferredOrientation, out Line line);

            cutLines.Add(line);
            foreach (CurveArray array in result)
            {
                Polygon p = new Polygon(array);
                perimeters.AddRange(p.GetConvexPerimeters(preferredOrientation, cutLines));
            }

            perimeters.Sort(new SortingDescendingArea());
            return(perimeters);
        }
Beispiel #15
0
        /// <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);
        }