Example #1
0
        /// <summary>
        /// Checks if a position is coincident with a line segment
        /// </summary>
        /// <param name="p">The position to test</param>
        /// <param name="start">The start of the segment.</param>
        /// <param name="end">The end of the segment.</param>
        /// <param name="tolsq">The tolerance (squared) to use. Default is XYTOLSQ.</param>
        /// <returns>True if the test position lies somewhere along the segment.</returns>
        public static bool IsCoincidentWith(IPointGeometry p, IPointGeometry start, IPointGeometry end, double tolsq)
        {
            // Check whether there is exact coincidence at either end.
            if (p.IsCoincident(start) || p.IsCoincident(end))
            {
                return(true);
            }

            // Get the distance squared of a perpendicular dropped from
            // the test position to the segment (or the closest end if the
            // perpendicular does not fall ON the segment).
            return(BasicGeom.DistanceSquared(p.X, p.Y, start.X, start.Y, end.X, end.Y) < tolsq);
        }
Example #2
0
        /// <summary>
        /// Checks whether any intersections occur at positions that do not coincide
        /// with the end points of a line.
        /// </summary>
        /// <param name="line">The line to check. This should be the same line that
        /// was supplied to the <c>IntersectionFinder</c> constructor that created THIS results
        /// object (doing otherwise doesn't make any sense).</param>
        /// <returns>TRUE if any intersection does not coincide with the end points
        /// of the specified line.</returns>
        internal bool IsSplitOn(ILineGeometry line)
        {
            // Get the locations of the line end points.
            IPointGeometry start = line.Start;
            IPointGeometry end   = line.End;

            // Go through each intersection, looking for one that does
            // not correspond to the line ends.

            foreach (IntersectionData d in m_Data)
            {
                IPointGeometry loc1 = new PointGeometry(d.P1);
                if (!start.IsCoincident(loc1) && !end.IsCoincident(loc1))
                {
                    return(true);
                }

                if (d.IsGraze)
                {
                    /*
                     * Huh? This was the original, but it always ended up returning true.
                     *
                     *          IPointGeometry loc2 = PointGeometry.New(d.P2);
                     * if (!start.IsCoincident(loc2) && !end.IsCoincident(loc2))
                     *  return true;
                     *
                     * return true;
                     */
                    return(true);
                }
            }

            return(false);
        }
Example #3
0
        /// <summary>
        /// Returns the context code for a simple intersection with a line.
        /// </summary>
        /// <param name="loc">The location of the intersection.</param>
        /// <param name="line">The line to compare with.</param>
        /// <returns>The context code.</returns>
        static IntersectionType GetContext(IPointGeometry loc, ILineGeometry line)
        {
            IntersectionType context = 0;

            if (loc.IsCoincident(line.Start))
            {
                context |= IntersectionType.TouchStart;
            }

            if (loc.IsCoincident(line.End))
            {
                context |= IntersectionType.TouchEnd;
            }

            if (context == 0)
            {
                context = IntersectionType.TouchOther;
            }

            return(context);
        }
Example #4
0
        /// <summary>
        /// Constructor for a grazing intersection. If the supplied positions are
        /// actually closer than the coordinate resolution (1 micron), a simple
        /// intersection will be defined.
        /// </summary>
        /// <param name="p1">The 1st intersection.</param>
        /// <param name="p2">The 2nd intersection.</param>
        IntersectionData(IPointGeometry p1, IPointGeometry p2)
        {
            m_X1 = p1;
            if (!p1.IsCoincident(p2))
            {
                m_X2 = p2;
            }

            m_SortValue = 0.0;
            m_Context1  = 0;
            m_Context2  = 0;
        }
Example #5
0
        /// <summary>
        /// Determines which side of a divider a horizontal line segment lies on.
        /// Used in point in polygon.
        /// </summary>
        /// <param name="id">The divider to process</param>
        /// <param name="s">Start of horizontal segment.</param>
        /// <param name="e">End of segment.</param>
        /// <param name="od">The divider the side refers to. This usually refers to
        /// the supplied divider, but may refer to another divider in a situation where the
        /// horizontal segment passes directly through one end of <paramref name="d"/>.</param>
        /// <returns>Side.Left if the line is to the left of the divider, Side.Right
        /// if line to the right, Side.On if the end of the line is coincident with
        /// the divider, Side.Unknown if an error arose.</returns>
        /// <remarks>
        /// Rather than passing in 2 PointGeometry objects, it would be better to pass
        /// in a HorizontalRay object, since 2 arbitrary positions are not guaranteed
        /// to be horizontal.
        /// </remarks>
        internal static Side GetSide(IDivider id, IPointGeometry s, IPointGeometry e, out IDivider od)
        {
            // If the end of the horizontal segment hits the start or
            // the end of the specified divider, we have a situation where the divider
            // may not be the divider which is adjacent to the segment. In
            // that case, use special code to determine the side code.
            // Otherwise just convert the supplied divider into a line, and get the
            // side code by looking for a vertex which has a different
            // northing from that of the horizontal segment.

            Debug.Assert(s.Easting.Microns <= e.Easting.Microns);
            double d = e.Easting.Meters - s.Easting.Meters;
            Debug.Assert(d>=0.0);
            HorizontalRay hseg = new HorizontalRay(s, d);

            if (e.IsCoincident(id.From) || e.IsCoincident(id.To)) // e both times!
                return hseg.GetSide(id, e.IsCoincident(id.From), out od);
            else
            {
                od = id;
                return od.LineGeometry.GetSide(hseg);
            }
        }
Example #6
0
        /// <summary>
        /// Executes the move operation.
        /// </summary>
        /// <param name="to">The revised position of the reference point.</param>
        internal void Execute(PointGeometry to)
        {
            // Remember the old and new positions.
            IPointGeometry txtPos = m_Label.Position;
            IPointGeometry polPos = m_Label.GetPolPosition();

            if (txtPos.IsCoincident(polPos))
            {
                m_OldPosition = null;
            }
            else
            {
                m_OldPosition = PointGeometry.Create(polPos);
            }

            m_NewPosition = to;

            // Move the reference position (and rework any enclosing polygon)
            m_Label.SetPolPosition(m_NewPosition);

            // Peform standard completion steps
            Complete();
        }
Example #7
0
        internal override void MouseMove(IPosition p)
        {
            PointFeature      oldCurrentPoint = m_CurrentPoint;
            CadastralMapModel map             = CadastralMapModel.Current;
            EditingController ec   = EditingController.Current;
            ILength           size = new Length(ec.Project.Settings.PointHeight * 0.5);

            m_CurrentPoint = (map.QueryClosest(p, size, SpatialType.Point) as PointFeature);

            if (m_Start == null)
            {
                // If the mouse is over a different point, ensure the old point is erased
                if (oldCurrentPoint != null && !Object.ReferenceEquals(oldCurrentPoint, m_CurrentPoint))
                {
                    ErasePainting();
                }

                return;
            }

            if (m_CurrentPoint == null)
            {
                m_End = PointGeometry.Create(p);
            }
            else
            {
                m_End = m_CurrentPoint;
            }

            if (m_End.IsCoincident(m_Start))
            {
                m_End = null;
                return;
            }

            ErasePainting();
        }
        /// <summary>
        /// Intersects a line segment with a clockwise arc, where at least one end of the
        /// segment exactly coincides with one end of the arc.
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="bc">The start of the clockwise arc.</param>
        /// <param name="ec">The end of the clockwise arc.</param>
        /// <param name="circle">The circle on which the arc lies.</param>
        /// <param name="xend">The end of the segment that coincides with one end of the arc.</param>
        /// <param name="othend">The other end of the segment (may or may not coincide
        /// with one end of the arc).</param>
        /// <returns>The number of intersections (either 1 or 2).</returns>
        static uint EndIntersect( IntersectionResult xsect
            , IPointGeometry bc
            , IPointGeometry ec
            , ICircleGeometry circle
            , IPointGeometry xend
            , IPointGeometry othend)
        {
            // If the other end is INSIDE the circle, the matching end
            // location is the one and only intersection. Allow a tolerance
            // that is consistent with the resolution of data (3 microns).
            IPointGeometry centre = circle.Center;
            double radius = circle.Radius;
            double minrad = (radius-Constants.XYTOL);
            double minrsq = (minrad*minrad);
            double othdsq = Geom.DistanceSquared(othend, centre);

            if (othdsq < minrsq)
            {
                xsect.Append(xend);
                return 1;
            }

            // If the other end of the segment also coincides with either
            // end of the curve, the segment is a chord of the circle that
            // the curve lies on. However, if it's REAL close, we need to
            // return it as a graze ...

            if (othend.IsCoincident(bc) || othend.IsCoincident(ec))
            {
                // Get the midpoint of the chord.
                IPosition midseg = Position.CreateMidpoint(xend, othend);

                // If the distance from the centre of the circle to the
                // midpoint is REAL close to the curve, we've got a graze.

                if (Geom.DistanceSquared(midseg, centre) > minrsq)
                {
                    xsect.Append(xend, othend);
                    return 1;
                }

                // Two distinct intersections.
                xsect.Append(xend);
                xsect.Append(othend);
                return 2;
            }

            // If the other end is within tolerance of the circle, project
            // it to the circle and see if it's within the curve's sector.
            // If not, it's not really an intersect.

            double maxrad = (radius+Constants.XYTOL);
            double maxrsq = (maxrad*maxrad);

            if ( othdsq < maxrsq )
            {
                // Check if the angle to the other end is prior to the EC.
                // If not, it's somewhere off the curve.
                Turn reft = new Turn(centre, bc);
                if (reft.GetAngleInRadians(othend) > reft.GetAngleInRadians(ec))
                {
                    xsect.Append(xend);
                    return 1;
                }

                // And, like above, see if the segment grazes or not ...

                // Get the midpoint of the chord.
                IPosition midseg = Position.CreateMidpoint(xend, othend);

                // If the distance from the centre of the circle to the
                // midpoint is REAL close to the curve, we've got a graze.

                if (Geom.DistanceSquared(midseg, centre) > minrsq)
                {
                    xsect.Append(xend, othend);
                    return 1;
                }

                // Two distinct intersections.
                xsect.Append(xend);
                xsect.Append(othend);
                return 2;
            }

            // That leaves us with the other end lying somewhere clearly
            // outside the circle. However, we could still have a graze.

            // Make sure the BC/EC are EXACTLY coincident with the circle (they
            // may have been rounded off if the curve has been intersected
            // with a location that's within tolerance of the circle).

            IPosition trueBC, trueEC;
            Position.GetCirclePosition(bc, centre, radius, out trueBC);
            Position.GetCirclePosition(ec, centre, radius, out trueEC);

            // As well as the end of the segment that meets the curve.
            IPosition trueXend = (xend.IsCoincident(bc) ? trueBC : trueEC);

            // Intersect the segment with the complete circle (this does
            // NOT return an intersection at the other end, even if it is
            // really close ... we took care of that above).

            // The intersection must lie ON the segment (not sure about this though).

            IPosition othvtx = othend;
            IPosition x1, x2;
            bool isTangent;
            uint nx = Geom.IntersectCircle(centre, radius, trueXend, othvtx, out x1, out x2, out isTangent, true);

            // If we got NOTHING, that's unexpected, since one end exactly coincides
            // with the circle. In that case, just return the matching end (NOT
            // projected to the true position).
            if (nx==0)
            {
                xsect.Append(xend);
                return 1;
            }

            // If we got 2 intersections, pick the one that's further away than the matching end.
            if (nx==2 && Geom.DistanceSquared(x2, trueXend) > Geom.DistanceSquared(x1, trueXend))
                x1 = x2;

            // That leaves us with ONE intersection with the circle ... now
            // confirm that it actually intersects the arc!

            Turn refbc = new Turn(centre, trueBC);
            double eangle = refbc.GetAngleInRadians(trueEC);
            double xangle = refbc.GetAngleInRadians(x1);

            if (xangle > eangle)
            {
                xsect.Append(xend);
                return 1;
            }

            // Get the midpoint of the segment that connects the intersection to the true end.
            IPosition midx = Position.CreateMidpoint(trueXend, x1);

            // If the midpoint does NOT graze the circle, we've got 2 distinct intersections.
            // 25-NOV-99: Be realistic about it (avoid meaningless sliver polygons that are
            // less than 0.1mm wide on the ground).

            // if ( midx.DistanceSquared(centre) < minrsq ) {
            double rdiff = Geom.Distance(midx, centre) - radius;
            if (Math.Abs(rdiff) > 0.0001)
            {
                xsect.Append(xend);
                xsect.Append(x1);
                return 2;
            }

            // We've got a graze, but possibly one that can be ignored(!). To
            // understand the reasoning here, bear in mind that lines get cut
            // only so that network topology can be formed. To do that, 2
            // orientation points are obtained for the lines incident on xend.
            // For the segment, the orientation point is the other end of the
            // segment. For the curve, it's a position 5 metres along the
            // curve (or the total curve length if it's not that long). So
            // if the graze is closer than the point that will be used to
            // get the orientation point, we can ignore the graze, since it
            // does not provide any useful info.

            // Given that it's a graze, assume that it's ok to work out
            // the arc distance as if it was straight.
            double dsqx = Geom.DistanceSquared(trueXend, x1);

            // If it's closer than 4m (allow some leeway, seeing how we've
            // just done an approximation), ignore the intersection. If it's
            // actually between 4 and 5 metres, it shouldn't do any harm
            // to make a split there (although it's kind of redundant).
            if (dsqx < 16.0)
            {
                xsect.Append(xend);
                return 1;
            }

            // It's a graze.
            //CeVertex vxend(xend);	// wants a vertex
            xsect.Append(xend, x1);
            return 1;
        }
        /// <summary>
        /// Intersects this segment with another segment, where at least one end of the
        /// segment exactly coincides with one end of the other segment. 
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="start">The start of the other segment.</param>
        /// <param name="end">The end of the other segment.</param>
        /// <param name="xend">The end of THIS segment that coincides with one end
        /// of the other one (the geometry for either m_Start or m_End).</param>
        /// <param name="othend">The other end of THIS segment (may or may not coincide
        /// with one end of the other segment).</param>
        /// <returns>The number of intersections (always 1).</returns>
        static uint EndIntersect( IntersectionResult xsect
            , IPointGeometry start
            , IPointGeometry end
            , IPointGeometry xend
            , IPointGeometry othend)
        {
            // If the other end of this segment coincides with either end
            // of the other segment, we've got a total graze.
            if (othend.IsCoincident(start) || othend.IsCoincident(end))
            {
                xsect.Append(start, end);
                return 1;
            }

            // Get the locations that define the longer segment, together
            // with the location that is different from the exactly matching end.

            IPointGeometry startLong;
            IPointGeometry endLong;
            IPointGeometry test;

            if (Geom.DistanceSquared(xend, othend) < Geom.DistanceSquared(start, end))
            {
                test = othend;
                startLong = start;
                endLong = end;
            }
            else
            {
                startLong = xend;
                endLong = othend;

                if (xend.IsCoincident(start))
                    test = end;
                else
                    test = start;
            }

            // If it is coincident (to within the resolution) AND the
            // position ratio of the perpendicular point is ON this
            // segment, it's a graze.

            double tolsq = (Constants.XYRES * Constants.XYRES);

            if (PointGeometry.IsCoincidentWith(test, startLong, endLong, tolsq))
            {
                double prat = Geom.GetPositionRatio(test.X
                                                   , test.Y
                                                   , startLong.X
                                                   , startLong.Y
                                                   , endLong.X
                                                   , endLong.Y);

                if (prat>0.0 && prat<1.0)
                {
                    xsect.Append(xend, test);
                    return 1;
                }
            }

            // ONE intersection at the end that exactly matches.
            xsect.Append(xend);
            return 1;
        }
        /// <summary>
        /// Intersects a pair of clockwise arcs that sit on the same circle, and where ONE of
        /// the end points exactly matches.
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="circle">The circle the arcs coincide with</param>
        /// <param name="bc1">The BC of the 1st arc</param>
        /// <param name="ec1">The EC of the 1st arc</param>
        /// <param name="bc2">The BC of the 2nd arc -- the matching end</param>
        /// <param name="ec2">The EC of the 2nd arc</param>
        /// <param name="isStartMatch">Specify <c>true</c> if <paramref name="bc2"/> matches an end
        /// point of the 1st arc. Specify <c>false</c> if <paramref name="ec2"/> matches an end
        /// point of the 1st arc.</param>
        /// <returns>The number of intersections (always 1).</returns>
        static uint ArcEndIntersect( IntersectionResult xsect
            , ICircleGeometry circle
            , IPointGeometry bc1
            , IPointGeometry ec1
            , IPointGeometry bc2
            , IPointGeometry ec2
            , bool isStartMatch)
        {
            bool bmatch = bc1.IsCoincident(bc2);
            bool ematch = ec1.IsCoincident(ec2);

            // If the two curves share the same BC or same EC
            if (bmatch || ematch)
            {
                // We've got some sort of graze ...

                // Check for total graze.
                if (bmatch && ematch)
                    xsect.Append(bc1, ec1);
                else
                {
                    // We've therefore got a partial graze.

                    // If the length of this arc is longer than the other one, the graze is over the
                    // length of the other one, and vice versa. Since the two curves share the same
                    // radius and direction, the comparison just involves a comparison of the clockwise
                    // angles subtended by the arcs.

                    IPointGeometry centre = circle.Center;
                    double ang1 = new Turn(centre, bc1).GetAngleInRadians(ec1);
                    double ang2 = new Turn(centre, bc2).GetAngleInRadians(ec2);
                    bool isThisGraze = (ang1 < ang2);

                    if (isThisGraze)
                        xsect.Append(bc1, ec1);
                    else
                        xsect.Append(bc2, ec2);
                }
            }
            else
            {
                // The only intersection is at the common end.
                if (bc1.IsCoincident(bc2) || ec1.IsCoincident(bc2))
                    xsect.Append(bc2);
                else
                    xsect.Append(ec2);
            }

            return 1;
        }
        internal static uint Intersect( IntersectionResult results
            , IPointGeometry a
            , IPointGeometry b
            , IPointGeometry p
            , IPointGeometry q)
        {
            // 04-APR-2003: This isn't supposed to happen, but if we've somehow
            // got a null segment, it NEVER intersects anything.
            if (a.IsCoincident(b))
                return 0;

            // If the segment EXACTLY meets either end of the other segment,
            // it gets handled seperately.
            if (a.IsCoincident(p) || a.IsCoincident(q))
                return EndIntersect(results, p, q, a, b);

            if (b.IsCoincident(p) || b.IsCoincident(q))
                return EndIntersect(results, p, q, b, a);

            // Return if the windows don't overlap.
            Window winab = new Window(a, b);
            Window winpq = new Window(p, q);
            if (!winab.IsOverlap(winpq))
                return 0;

            // Check whether this line is completely coincident with the other one.
            // double tolsq = Constants.XYTOLSQ;
            double tolsq = (Constants.XYRES*Constants.XYRES);

            uint xcase = 0;
            if (PointGeometry.IsCoincidentWith(a, p, q, tolsq))
                xcase |= 0x08;
            if (PointGeometry.IsCoincidentWith(b, p, q, tolsq))
                xcase |= 0x04;

            if (xcase==12) // bits 1100
            {
                results.Append(a, b);
                return 1;
            }

            // Check the end points of the other line to this one.
            if (PointGeometry.IsCoincidentWith(p, a, b, tolsq))
                xcase |= 0x02;
            if (PointGeometry.IsCoincidentWith(q, a, b, tolsq))
                xcase |= 0x01;

            // Return intersections. Note that in cases 3,7,11, the intersections
            // are not necessarily ordered with respect to THIS segment.

            switch (xcase)
            {
                case 0:
                    {
                        // Try to get a simple intersection. Do not accept
                        // virtual intersections, since they should have been
                        // trapped via the calculation of the xcase.

                        double xi, yi;
                        int xcode = Geom.CalcIntersect(a.X, a.Y, b.X, b.Y, p.X, p.Y, q.X, q.Y, out xi, out yi, true);

                        if (xcode < 0)
                        {
                            results.Append(xi, yi, 0.0);
                            return 1;
                        }

                        return 0;
                    }

                case 1:
                    {
                        results.Append(q);
                        return 1;
                    }

                case 2:
                    {
                        results.Append(p);
                        return 1;
                    }

                case 3:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

                case 4:
                    {
                        results.Append(b);
                        return 1;
                    }

                case 5:
                    {
                        results.Append(q, b);
                        return 1;
                    }

                case 6:
                    {
                        results.Append(p, b);
                        return 1;
                    }

                case 7:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

                case 8:
                    {
                        results.Append(a);
                        return 1;
                    }

                case 9:
                    {
                        results.Append(a, q);
                        return 1;
                    }

                case 10:
                    {
                        results.Append(a, p);
                        return 1;
                    }

                case 11:
                    {
                        results.Append(p, q);	// order?
                        return 1;
                    }

            } // end switch

            throw new Exception("LineSegmentFeature.Intersect - Unexpected case");
        }
        /// <summary>
        /// Intersects a line segment with the data describing a clockwise curve.
        /// </summary>
        /// <param name="result">The intersection results.</param>
        /// <param name="a">The start of the line segment</param>
        /// <param name="b">The end of the line segment</param>
        /// <param name="start">The start of the clockwise arc.</param>
        /// <param name="end">The end of the clockwise arc.</param>
        /// <param name="circle">The circle on which the arc lies.</param>
        /// <returns></returns>
        static uint Intersect( IntersectionResult result
            , IPointGeometry a
            , IPointGeometry b
            , IPointGeometry start
            , IPointGeometry end
            , ICircleGeometry circle)
        {
            // If the segment exactly meets either end of the curve, it gets handled seperately.
            if (a.IsCoincident(start) || a.IsCoincident(end))
                return EndIntersect(result, start, end, circle, a, b);

            if (b.IsCoincident(start) || b.IsCoincident(end))
                return EndIntersect(result, start, end, circle, b, a);

            // Get circle definition.
            IPointGeometry centre = circle.Center;
            double radius = circle.Radius;

            // Get up to 2 intersections with the circle.
            IPosition x1, x2;
            bool isGraze;
            uint nx = GetXCircle(a, b, centre, radius, out x1, out x2, out isGraze);

            // Return if no intersections with the circle.
            if (nx==0)
                return 0;

            // If an intersection is really close to the end of an arc, force it to be there.
            if (Geom.DistanceSquared(start, x1) < Constants.XYTOLSQ)
                x1 = start;
            else if (Geom.DistanceSquared(end, x1) < Constants.XYTOLSQ)
                x1 = end;

            if (nx==2)
            {
                if (Geom.DistanceSquared(start, x2) < Constants.XYTOLSQ)
                    x2 = start;
                else if (Geom.DistanceSquared(end, x2) < Constants.XYTOLSQ)
                    x2 = end;
            }

            // Determine whether the intersections fall within the sector
            // that's defined by the clockwise curve (grazes need a bit
            // more handling, so do that after we see how to do the non-
            // grazing case.

            if ( !isGraze )
            {
                PointGeometry xloc1 = PointGeometry.Create(x1);
                double lintol = Constants.XYTOL / radius;

                // If we only got one intersect, and it's out of sector, that's us done.
                if (nx==1)
                {
                    if (!BasicGeom.IsInSector(xloc1, centre, start, end, lintol))
                        return 0;

                    result.Append(x1);
                    return 1;
                }

                // Two intersections with the circle ...

                if (BasicGeom.IsInSector(xloc1, centre, start, end, lintol))
                    result.Append(x1);
                else
                    nx--;

                PointGeometry xloc2 = PointGeometry.Create(x2);

                if (BasicGeom.IsInSector(xloc2, centre, start, end, lintol))
                    result.Append(x2);
                else
                    nx--;

                return nx;
            }

            // That leaves us with the case where this segment grazes the
            // circle. GetXCircle is always supposed to return nx==2 in that
            // case (they're also supposed to be arranged in the same
            // direction as this segment).
            Debug.Assert(nx==2);

            // Get the clockwise angle subtended by the circular arc. Add
            // on a tiny bit to cover numerical comparison problems.
            Turn reft = new Turn(centre, start);
            double maxangle = reft.GetAngleInRadians(end) + Constants.TINY;

            // Get the clockwise angles to both intersections.
            double a1 = reft.GetAngleInRadians(x1);
            double a2 = reft.GetAngleInRadians(x2);

            // No graze if both are beyond the arc sector.
            if (a1>maxangle && a2>maxangle)
                return 0;

            // If both intersects are within sector, the only thing to watch
            // out for is a case where the graze apparently occupies more
            // than half a circle. In that case, we've actually got 2 grazes.

            if (a1<maxangle &&  a2<maxangle)
            {
                if (a2>a1 && (a2-a1)>Constants.PI)
                {
                    result.Append(x1, start);
                    result.Append(end, x2);
                    return 2;
                }

                if (a1>a2 && (a1-a2)>Constants.PI)
                {
                    result.Append(start, x2);
                    result.Append(x1, end);
                    return 2;
                }

                // So it's just a regular graze.
                result.Append(x1, x2);
                return 1;
            }

            // That's covered the cases where both intersects are either
            // both in sector, or both out. Return the intersection that's
            // in sector as a simple intersection (NOT a graze).

            // This is a cop-out. We should really try to figure out which
            // portion of the curve is grazing, but the logic for doing so
            // is surprisingly complex, being subject to a variety of special
            // cases. By returning the intersect as a simple intersect, I'm
            // hoping it covers most cases.

            if (a1 < maxangle)
                result.Append(x1);
            else
                result.Append(x2);

            return 1;
        }
Example #13
0
        /// <summary>
        /// Checks if a position is coincident with a line segment
        /// </summary>
        /// <param name="p">The position to test</param>
        /// <param name="start">The start of the segment.</param>
        /// <param name="end">The end of the segment.</param>
        /// <param name="tolsq">The tolerance (squared) to use. Default is XYTOLSQ.</param>
        /// <returns>True if the test position lies somewhere along the segment.</returns>
        public static bool IsCoincidentWith(IPointGeometry p, IPointGeometry start, IPointGeometry end, double tolsq)
        {
            // Check whether there is exact coincidence at either end.
            if (p.IsCoincident(start) || p.IsCoincident(end))
                return true;

            // Get the distance squared of a perpendicular dropped from
            // the test position to the segment (or the closest end if the
            // perpendicular does not fall ON the segment).
            return (BasicGeom.DistanceSquared(p.X, p.Y, start.X, start.Y, end.X, end.Y) < tolsq);
        }