Beispiel #1
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 #2
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 #3
0
        /// <summary>
        /// Adds the specified item before the specified existing node in the list.
        /// </summary>
        /// <param name="node">Existing node before which new item will be inserted</param>
        /// <param name="item">New item to be inserted</param>
        /// <exception cref="ArgumentNullException"><paramref name="node"/> is NULL</exception>
        /// <exception cref="InvalidOperationException"><paramref name="node"/> doesn't belongs to list</exception>
        public CircularLinkedListNode <T> AddBefore(CircularLinkedListNode <T> node, T item)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            // ensuring the supplied node belongs to this list
            CircularLinkedListNode <T> temp = FindNode(head, node.Value);

            if (temp != node)
            {
                throw new InvalidOperationException("Node doesn't belongs to this list");
            }

            CircularLinkedListNode <T> newNode = new CircularLinkedListNode <T>(item);

            node.Previous.Next = newNode;
            newNode.Previous   = node.Previous;
            newNode.Next       = node;
            node.Previous      = newNode;

            // if the node adding is head node, then repointing head node
            if (node == head)
            {
                head = newNode;
            }

            ++count;

            return(newNode);
        }
Beispiel #4
0
 private void AddFirstItem(T item)
 {
     head          = new CircularLinkedListNode <T>(item);
     tail          = head;
     head.Next     = tail;
     head.Previous = tail;
 }
Beispiel #5
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 #6
0
        /// <summary>
        /// Removes the first occurance of the supplied item
        /// </summary>
        /// <param name="item">Item to be removed</param>
        /// <returns>TRUE if removed, else FALSE</returns>
        public bool Remove(T item)
        {
            // finding the first occurance of this item
            CircularLinkedListNode <T> nodeToRemove = Find(item);

            if (nodeToRemove != null)
            {
                return(RemoveNode(nodeToRemove));
            }

            return(false);
        }
Beispiel #7
0
        /// <summary>
        /// Adds the new item before the specified existing item in the list.
        /// </summary>
        /// <param name="existingItem">Existing item before which new item will be added</param>
        /// <param name="newItem">New item to be added to the list</param>
        /// <exception cref="ArgumentException"><paramref name="existingItem"/> doesn't exist in the list</exception>
        public void AddBefore(T existingItem, T newItem)
        {
            // finding a node for the existing item
            CircularLinkedListNode <T> node = Find(existingItem);

            if (node == null)
            {
                throw new ArgumentException("existingItem doesn't exist in the list");
            }

            AddBefore(node, newItem);
        }
Beispiel #8
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 #9
0
        /// <summary>
        /// Gets a reverse enumerator
        /// </summary>
        /// <returns></returns>
        public IEnumerator <T> GetReverseEnumerator()
        {
            CircularLinkedListNode <T> current = tail;

            if (current != null)
            {
                do
                {
                    yield return(current.Value);

                    current = current.Previous;
                } while (current != tail);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Gets a forward enumerator
        /// </summary>
        /// <returns></returns>
        public IEnumerator <T> GetEnumerator()
        {
            CircularLinkedListNode <T> current = head;

            if (current != null)
            {
                do
                {
                    yield return(current.Value);

                    current = current.Next;
                } while (current != head);
            }
        }
Beispiel #11
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 #12
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 #13
0
        private CircularLinkedListNode <T> FindNode(CircularLinkedListNode <T> node, T valueToCompare)
        {
            CircularLinkedListNode <T> result = null;

            if (comparer.Equals(node.Value, valueToCompare))
            {
                result = node;
            }
            else if (result == null && node.Next != head)
            {
                result = FindNode(node.Next, valueToCompare);
            }

            return(result);
        }
Beispiel #14
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 #15
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 #16
0
 /// <summary>
 /// Adds item to the last
 /// </summary>
 /// <param name="item">Item to be added</param>
 public void AddFirst(T item)
 {
     if (head == null)
     {
         AddFirstItem(item);
     }
     else
     {
         CircularLinkedListNode <T> newNode = new CircularLinkedListNode <T>(item);
         head.Previous    = newNode;
         newNode.Previous = tail;
         newNode.Next     = head;
         tail.Next        = newNode;
         head             = newNode;
     }
     ++count;
 }
Beispiel #17
0
        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)));
        }
Beispiel #18
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 #19
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 #20
0
 /// <summary>
 /// Add a new item to the end of the list
 /// </summary>
 /// <param name="item">Item to be added</param>
 public void AddLast(T item)
 {
     // if head is null, then this will be the first item
     if (head == null)
     {
         AddFirstItem(item);
     }
     else
     {
         CircularLinkedListNode <T> newNode = new CircularLinkedListNode <T>(item);
         tail.Next        = newNode;
         newNode.Next     = head;
         newNode.Previous = tail;
         tail             = newNode;
         head.Previous    = tail;
     }
     ++count;
 }
Beispiel #21
0
        /// <summary>
        /// Gets the item at the current index
        /// </summary>
        /// <param name="index">Zero-based index</param>
        /// <exception cref="ArgumentOutOfRangeException">index is out of range</exception>
        public CircularLinkedListNode <T> this[int index]
        {
            get
            {
                if (index >= count || index < 0)
                {
                    throw new ArgumentOutOfRangeException("index");
                }
                else
                {
                    CircularLinkedListNode <T> node = head;
                    for (int i = 0; i < index; i++)
                    {
                        node = node.Next;
                    }

                    return(node);
                }
            }
        }
Beispiel #22
0
        private bool RemoveNode(CircularLinkedListNode <T> nodeToRemove)
        {
            CircularLinkedListNode <T> previous = nodeToRemove.Previous;

            previous.Next = nodeToRemove.Next;
            nodeToRemove.Next.Previous = nodeToRemove.Previous;

            // if this is head, we need to update the head reference
            if (head == nodeToRemove)
            {
                head = nodeToRemove.Next;
            }
            else if (tail == nodeToRemove)
            {
                tail = tail.Previous;
            }

            --count;
            return(true);
        }
Beispiel #23
0
        public void CopyTo(T[] array, int arrayIndex)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }

            if (arrayIndex < 0 || arrayIndex > array.Length)
            {
                throw new ArgumentOutOfRangeException("arrayIndex");
            }

            CircularLinkedListNode <T> node = head;

            do
            {
                array[arrayIndex++] = node.Value;
                node = node.Next;
            } while (node != head);
        }
Beispiel #24
0
        /// <summary>
        /// Finds the supplied item and returns a node which contains item. Returns NULL if item not found
        /// </summary>
        /// <param name="item">Item to search</param>
        /// <returns><see cref="CircularLinkedListNode&lt;T&gt;"/> instance or NULL</returns>
        public CircularLinkedListNode <T> Find(T item)
        {
            CircularLinkedListNode <T> node = FindNode(head, item);

            return(node);
        }
Beispiel #25
0
 /// <summary>
 /// Clears the list
 /// </summary>
 public void Clear()
 {
     head  = null;
     tail  = null;
     count = 0;
 }
Beispiel #26
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);
        }