Example #1
0
            private double arcAngle;             // angle in radians

            internal Arc(Circle circle, ICoordinate p1, ICoordinate midPt, ICoordinate p2)
            {
                this.circle = circle;
                this.p1     = p1;
                this.p2     = p2;
                p1Angle     = circle.GetAngle(p1);
                // See if this arc covers the whole circle
                if (p1.Equals2D(p2))
                {
                    p2Angle  = TWO_PI + p1Angle;
                    arcAngle = TWO_PI;
                }
                else
                {
                    p2Angle = circle.GetAngle(p2);
                    double midPtAngle = circle.GetAngle(midPt);

                    // determine the direction
                    double ccDegrees = SubtractAngles(p1Angle,
                                                      midPtAngle)
                                       + SubtractAngles(midPtAngle, p2Angle);

                    if (ccDegrees < TWO_PI)
                    {
                        clockwise = false;
                        arcAngle  = ccDegrees;
                    }
                    else
                    {
                        clockwise = true;
                        arcAngle  = TWO_PI - ccDegrees;
                    }
                }
            }
        /// <summary>
        ///  Compares two <see cref="Coordinate" />s for their relative position along a segment
        /// lying in the specified <see cref="Octant" />.
        /// </summary>
        /// <param name="octant"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns>
        /// -1 if node0 occurs first, or
        ///  0 if the two nodes are equal, or
        ///  1 if node1 occurs first.
        /// </returns>
        public static int Compare(Octants octant, ICoordinate p0, ICoordinate p1)
        {
            // nodes can only be equal if their coordinates are equal
            if (p0.Equals2D(p1)) 
                return 0;

            int xSign = RelativeSign(p0.X, p1.X);
            int ySign = RelativeSign(p0.Y, p1.Y);

            switch (octant)
            {
                case Octants.Zero: 
                    return CompareValue(xSign, ySign);
                case Octants.One:
                    return CompareValue(ySign, xSign);
                case Octants.Two:
                    return CompareValue(ySign, -xSign);
                case Octants.Three:
                    return CompareValue(-xSign, ySign);
                case Octants.Four:
                    return CompareValue(-xSign, -ySign);
                case Octants.Five:
                    return CompareValue(-ySign, -xSign);
                case Octants.Six:
                    return CompareValue(-ySign, xSign);
                case Octants.Seven:
                    return CompareValue(xSign, -ySign);
            }

            Assert.ShouldNeverReachHere("invalid octant value: " + octant);
            return 0;
        }
Example #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SegmentNode"/> class.
 /// </summary>
 /// <param name="segString"></param>
 /// <param name="coord"></param>
 /// <param name="segmentIndex"></param>
 /// <param name="segmentOctant"></param>
 public SegmentNode(SegmentString segString, ICoordinate coord, int segmentIndex, Octants segmentOctant)
 {
     this.segString     = segString;
     this.Coordinate    = new Coordinate(coord);
     this.SegmentIndex  = segmentIndex;
     this.segmentOctant = segmentOctant;
     isInterior         = !coord.Equals2D(segString.GetCoordinate(segmentIndex));
 }
Example #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SegmentNode"/> class.
 /// </summary>
 /// <param name="segString"></param>
 /// <param name="coord"></param>
 /// <param name="segmentIndex"></param>
 /// <param name="segmentOctant"></param>
 public SegmentNode(SegmentString segString, ICoordinate coord, int segmentIndex, Octants segmentOctant)
 {
     this.segString = segString;
     this.Coordinate = new Coordinate(coord);
     this.SegmentIndex = segmentIndex;
     this.segmentOctant = segmentOctant;
     isInterior = !coord.Equals2D(segString.GetCoordinate(segmentIndex));
 }
Example #5
0
 /// <summary>
 /// Adds nodes for any collapsed edge pairs
 /// which are pre-existing in the vertex list.
 /// </summary>
 /// <param name="collapsedVertexIndexes"></param>
 private void FindCollapsesFromExistingVertices(IList collapsedVertexIndexes)
 {
     for (int i = 0; i < edge.Count - 2; i++)
     {
         ICoordinate p0 = edge.GetCoordinate(i);
         ICoordinate p1 = edge.GetCoordinate(i + 1);
         ICoordinate p2 = edge.GetCoordinate(i + 2);
         if (p0.Equals2D(p2))    // add base of collapse as node
         {
             collapsedVertexIndexes.Add(i + 1);
         }
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="snapPts"></param>
 /// <returns></returns>
 private ICoordinate FindSnapForVertex(ICoordinate pt, ICoordinate[] snapPts)
 {
     foreach (ICoordinate coord in snapPts)
     {
         // if point is already equal to a src pt, don't snap
         if (pt.Equals2D(coord))
         {
             return(null);
         }
         if (pt.Distance(coord) < snapTolerance)
         {
             return(coord);
         }
     }
     return(null);
 }
Example #7
0
 private Arc(Circle circle, ICoordinate p1, ICoordinate p2, bool isClockwise)
 {
     this.p1   = p1;
     this.p2   = p2;
     clockwise = isClockwise;
     p1Angle   = circle.GetAngle(p1);
     if (p1.Equals2D(p2))
     {
         p2Angle = TWO_PI + p1Angle;
     }
     else
     {
         p2Angle = circle.GetAngle(p2);
     }
     DetermineArcAngle();
 }
Example #8
0
        /// <summary>
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>
        /// -1 this SegmentNode is located before the argument location, or
        ///  0 this SegmentNode is at the argument location, or
        ///  1 this SegmentNode is located after the argument location.
        /// </returns>
        public int CompareTo(object obj)
        {
            SegmentNode other = (SegmentNode)obj;

            if (SegmentIndex < other.SegmentIndex)
            {
                return(-1);
            }
            if (SegmentIndex > other.SegmentIndex)
            {
                return(1);
            }
            if (Coordinate.Equals2D(other.Coordinate))
            {
                return(0);
            }
            return(SegmentPointComparator.Compare(segmentOctant, Coordinate, other.Coordinate));
        }
Example #9
0
            private void DetermineArcAngle()
            {
                double diff;

                if (p1.Equals2D(p2))
                {
                    diff = TWO_PI;
                }
                else if (clockwise)
                {
                    diff = p1Angle - p2Angle;
                }
                else
                {
                    diff = p2Angle - p1Angle;
                }
                arcAngle = NormalizeAngle(diff);
            }
Example #10
0
        /// <summary>
        ///  Compares two <see cref="Coordinate" />s for their relative position along a segment
        /// lying in the specified <see cref="Octant" />.
        /// </summary>
        /// <param name="octant"></param>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <returns>
        /// -1 if node0 occurs first, or
        ///  0 if the two nodes are equal, or
        ///  1 if node1 occurs first.
        /// </returns>
        public static int Compare(Octants octant, ICoordinate p0, ICoordinate p1)
        {
            // nodes can only be equal if their coordinates are equal
            if (p0.Equals2D(p1))
            {
                return(0);
            }

            int xSign = RelativeSign(p0.X, p1.X);
            int ySign = RelativeSign(p0.Y, p1.Y);

            switch (octant)
            {
            case Octants.Zero:
                return(CompareValue(xSign, ySign));

            case Octants.One:
                return(CompareValue(ySign, xSign));

            case Octants.Two:
                return(CompareValue(ySign, -xSign));

            case Octants.Three:
                return(CompareValue(-xSign, ySign));

            case Octants.Four:
                return(CompareValue(-xSign, -ySign));

            case Octants.Five:
                return(CompareValue(-ySign, -xSign));

            case Octants.Six:
                return(CompareValue(-ySign, xSign));

            case Octants.Seven:
                return(CompareValue(xSign, -ySign));
            }

            Assert.ShouldNeverReachHere("invalid octant value: " + octant);
            return(0);
        }
Example #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="intPt"></param>
        /// <param name="segmentIndex"></param>
        public void AddIntersection(ICoordinate intPt, int segmentIndex)
        {
            int normalizedSegmentIndex = segmentIndex;
            // normalize the intersection point location
            int nextSegIndex = normalizedSegmentIndex + 1;

            if (nextSegIndex < pts.Length)
            {
                ICoordinate nextPt = pts[nextSegIndex];

                // Normalize segment index if intPt falls on vertex
                // The check for point equality is 2D only - Z values are ignored
                if (intPt.Equals2D(nextPt))
                {
                    normalizedSegmentIndex = nextSegIndex;
                }
            }

            // Add the intersection point to edge intersection list.
            SegmentNode ei = nodeList.Add(intPt, normalizedSegmentIndex);
        }
Example #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="splitEdges"></param>
        private void CheckSplitEdgesCorrectness(IList splitEdges)
        {
            ICoordinate[] edgePts = edge.Coordinates;

            // check that first and last points of split edges are same as endpoints of edge
            SegmentString split0 = (SegmentString)splitEdges[0];
            ICoordinate   pt0    = split0.GetCoordinate(0);

            if (!pt0.Equals2D(edgePts[0]))
            {
                throw new Exception("bad split edge start point at " + pt0);
            }

            SegmentString splitn = (SegmentString)splitEdges[splitEdges.Count - 1];

            ICoordinate[] splitnPts = splitn.Coordinates;
            ICoordinate   ptn       = splitnPts[splitnPts.Length - 1];

            if (!ptn.Equals2D(edgePts[edgePts.Length - 1]))
            {
                throw new Exception("bad split edge end point at " + ptn);
            }
        }
Example #13
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="intPt"></param>
        /// <param name="segmentIndex"></param>
        public void AddIntersection(ICoordinate intPt, int segmentIndex)
        {
            var normalizedSegmentIndex = segmentIndex;
            // normalize the intersection point location
            var nextSegIndex = normalizedSegmentIndex + 1;
            if(nextSegIndex < pts.Length)
            {
                var nextPt = pts[nextSegIndex];
              
                // Normalize segment index if intPt falls on vertex
                // The check for point equality is 2D only - Z values are ignored
                if (intPt.Equals2D(nextPt))
                    normalizedSegmentIndex = nextSegIndex;                
            }

            // Add the intersection point to edge intersection list.
            var ei = nodeList.Add(intPt, normalizedSegmentIndex);
        }
Example #14
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="pt"></param>
 /// <param name="snapPts"></param>
 /// <returns></returns>
 private ICoordinate FindSnapForVertex(ICoordinate pt, ICoordinate[] snapPts)
 {
     foreach (ICoordinate coord in snapPts)
     {
         // if point is already equal to a src pt, don't snap
         if (pt.Equals2D(coord))
             return null;
         if (pt.Distance(coord) < snapTolerance)
             return coord;
     }
     return null;
 }
Example #15
0
        /// <summary>
        /// Computes whether a ring defined by an array of <see cref="Coordinate" />s is oriented counter-clockwise.
        /// The list of points is assumed to have the first and last points equal.
        /// This will handle coordinate lists which contain repeated points.
        /// This algorithm is only guaranteed to work with valid rings.
        /// If the ring is invalid (e.g. self-crosses or touches),
        /// the computed result may not be correct.
        /// </summary>>
        /// <param name="ring"></param>
        /// <returns></returns>
        public static bool IsCCW(ICoordinate[] ring)
        {
            // # of points without closing endpoint
            int nPts = ring.Length - 1;

            // find highest point
            ICoordinate hiPt    = ring[0];
            int         hiIndex = 0;

            for (int i = 1; i <= nPts; i++)
            {
                ICoordinate p = ring[i];
                if (p.Y > hiPt.Y)
                {
                    hiPt    = p;
                    hiIndex = i;
                }
            }

            // find distinct point before highest point
            int iPrev = hiIndex;

            do
            {
                iPrev = iPrev - 1;
                if (iPrev < 0)
                {
                    iPrev = nPts;
                }
            }while (ring[iPrev].Equals2D(hiPt) && iPrev != hiIndex);

            // find distinct point after highest point
            int iNext = hiIndex;

            do
            {
                iNext = (iNext + 1) % nPts;
            }while (ring[iNext].Equals2D(hiPt) && iNext != hiIndex);

            ICoordinate prev = ring[iPrev];
            ICoordinate next = ring[iNext];

            /*
             * This check catches cases where the ring contains an A-B-A configuration of points.
             * This can happen if the ring does not contain 3 distinct points
             * (including the case where the input array has fewer than 4 elements),
             * or it contains coincident line segments.
             */
            if (prev.Equals2D(hiPt) || next.Equals2D(hiPt) || prev.Equals2D(next))
            {
                return(false);
            }

            int disc = ComputeOrientation(prev, hiPt, next);

            /*
             *  If disc is exactly 0, lines are collinear.  There are two possible cases:
             *  (1) the lines lie along the x axis in opposite directions
             *  (2) the lines lie on top of one another
             *
             *  (1) is handled by checking if next is left of prev ==> CCW
             *  (2) will never happen if the ring is valid, so don't check for it
             *  (Might want to assert this)
             */
            bool isCCW = false;

            if (disc == 0)
            {
                // poly is CCW if prev x is right of next x
                isCCW = (prev.X > next.X);
            }
            else
            {
                // if area is positive, points are ordered CCW
                isCCW = (disc > 0);
            }
            return(isCCW);
        }
Example #16
0
            private double arcAngle; // angle in radians

            #endregion Fields

            #region Constructors

            internal Arc(Circle circle, ICoordinate p1, ICoordinate midPt, ICoordinate p2)
            {
                this.circle = circle;
                this.p1 = p1;
                this.p2 = p2;
                p1Angle = circle.GetAngle(p1);
                // See if this arc covers the whole circle
                if (p1.Equals2D(p2))
                {
                    p2Angle = TWO_PI + p1Angle;
                    arcAngle = TWO_PI;
                }
                else
                {
                    p2Angle = circle.GetAngle(p2);
                    double midPtAngle = circle.GetAngle(midPt);

                    // determine the direction
                    double ccDegrees = SubtractAngles(p1Angle,
                                                      midPtAngle)
                                       + SubtractAngles(midPtAngle, p2Angle);

                    if (ccDegrees < TWO_PI)
                    {
                        clockwise = false;
                        arcAngle = ccDegrees;
                    }
                    else
                    {
                        clockwise = true;
                        arcAngle = TWO_PI - ccDegrees;
                    }
                }
            }
Example #17
0
 private Arc(Circle circle, ICoordinate p1, ICoordinate p2, bool isClockwise)
 {
     this.p1 = p1;
     this.p2 = p2;
     clockwise = isClockwise;
     p1Angle = circle.GetAngle(p1);
     if (p1.Equals2D(p2))
     {
         p2Angle = TWO_PI + p1Angle;
     }
     else
     {
         p2Angle = circle.GetAngle(p2);
     }
     DetermineArcAngle();
 }