/// <summary>
        /// Implements the total order relation.
        /// The angle of edge a is greater than the angle of edge b,
        /// where the angle of an edge is the angle made by
        /// the first segment of the edge with the positive x-axis.
        /// When applied to a list of edges originating at the same point,
        /// this produces a CCW ordering of the edges around the point.
        /// Using the obvious algorithm of computing the angle is not robust,
        /// since the angle calculation is susceptible to roundoff error.
        /// </summary>
        /// <remarks>
        /// A robust algorithm is:
        /// 1. compare the quadrants the edge vectors lie in.
        /// If the quadrants are different,
        /// it is trivial to determine which edge has a greater angle.
        /// 2. If the vectors lie in the same quadrant, the
        /// <see cref="CGAlgorithms.ComputeOrientation"/> function
        /// can be used to determine the relative orientation of the vectors.
        /// </remarks>
        public int CompareAngularDirection(HalfEdge e)
        {
            double dx  = DeltaX;
            double dy  = DeltaY;
            double dx2 = e.DeltaX;
            double dy2 = e.DeltaY;

            // same vector
            if (dx == dx2 && dy == dy2)
            {
                return(0);
            }

            double quadrant  = QuadrantOp.Quadrant(dx, dy);
            double quadrant2 = QuadrantOp.Quadrant(dx2, dy2);

            // if the vectors are in different quadrants, determining the ordering is trivial
            if (quadrant > quadrant2)
            {
                return(1);
            }
            if (quadrant < quadrant2)
            {
                return(-1);
            }
            // vectors are in the same quadrant
            // Check relative orientation of direction vectors
            // this is > e if it is CCW of e
            return(CGAlgorithms.ComputeOrientation(e.Orig, e.Dest, Dest));
        }
Пример #2
0
        /// <summary>
        /// Finds the index of the last point in a monotone chain
        /// starting at a given point.
        /// Any repeated points (0-length segments) will be included
        /// in the monotone chain returned.
        /// </summary>
        /// <param name="pts">The coordinates</param>
        /// <param name="start">The start index</param>
        /// <returns>
        /// The index of the last point in the monotone chain starting at <c>start</c>.
        /// </returns>
        private static int FindChainEnd(Coordinate[] pts, int start)
        {
            int safeStart = start;

            // skip any zero-length segments at the start of the sequence
            // (since they cannot be used to establish a quadrant)
            while (safeStart < pts.Length - 1 && pts[safeStart].Equals2D(pts[safeStart + 1]))
            {
                safeStart++;
            }
            // check if there are NO non-zero-length segments
            if (safeStart >= pts.Length - 1)
            {
                return(pts.Length - 1);
            }
            // determine overall quadrant for chain (which is the starting quadrant)
            int chainQuad = QuadrantOp.Quadrant(pts[safeStart], pts[safeStart + 1]);
            int last      = start + 1;

            while (last < pts.Length)
            {
                // skip zero-length segments, but include them in the chain
                if (!pts[last - 1].Equals2D(pts[last]))
                {
                    // compute quadrant for next possible segment in chain
                    int quad = QuadrantOp.Quadrant(pts[last - 1], pts[last]);
                    if (quad != chainQuad)
                    {
                        break;
                    }
                }
                last++;
            }
            return(last - 1);
        }
Пример #3
0
        /// <summary>
        /// Constructs a DirectedEdge connecting the <c>from</c> node to the
        /// <c>to</c> node.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="directionPt">
        /// Specifies this DirectedEdge's direction (given by an imaginary
        /// line from the <c>from</c> node to <c>directionPt</c>).
        /// </param>
        /// <param name="edgeDirection">
        /// Whether this DirectedEdge's direction is the same as or
        /// opposite to that of the parent Edge (if any).
        /// </param>
        public DirectedEdge(Node from, Node to, Coordinate directionPt, bool edgeDirection)
        {
            this.from          = from;
            this.to            = to;
            this.EdgeDirection = edgeDirection;
            p0 = from.Coordinate;
            p1 = directionPt;
            double dx = p1.X - p0.X;
            double dy = p1.Y - p0.Y;

            _quadrant = QuadrantOp.Quadrant(dx, dy);
            _angle    = Math.Atan2(dy, dx);
        }
Пример #4
0
        private DirectedEdge _sym;  // optional

        #endregion

        /// <summary>
        /// Constructs a DirectedEdge connecting the <c>from</c> node to the
        /// <c>to</c> node.
        /// </summary>
        /// <param name="inFrom"></param>
        /// <param name="inTo"></param>
        /// <param name="directionPt">
        /// Specifies this DirectedEdge's direction (given by an imaginary
        /// line from the <c>from</c> node to <c>directionPt</c>).
        /// </param>
        /// <param name="inEdgeDirection">
        /// Whether this DirectedEdge's direction is the same as or
        /// opposite to that of the parent Edge (if any).
        /// </param>
        public DirectedEdge(Node inFrom, Node inTo, Coordinate directionPt, bool inEdgeDirection)
        {
            _from          = inFrom;
            _to            = inTo;
            _edgeDirection = inEdgeDirection;
            _p0            = _from.Coordinate;
            _p1            = directionPt;
            double dx = _p1.X - _p0.X;
            double dy = _p1.Y - _p0.Y;

            _quadrant = QuadrantOp.Quadrant(dx, dy);
            _angle    = Math.Atan2(dy, dx);
        }
Пример #5
0
        /// <returns>
        /// The index of the last point in the monotone chain.
        /// </returns>
        private static int FindChainEnd(IList <Coordinate> pts, int start)
        {
            // determine quadrant for chain
            int chainQuad = QuadrantOp.Quadrant(pts[start], pts[start + 1]);
            int last      = start + 1;

            while (last < pts.Count)
            {
                // compute quadrant for next possible segment in chain
                int quad = QuadrantOp.Quadrant(pts[last - 1], pts[last]);
                if (quad != chainQuad)
                {
                    break;
                }
                last++;
            }
            return(last - 1);
        }