예제 #1
0
 public CircularArcGeometry(ICircularArcGeometry g)
 {
     m_Circle      = g.Circle;
     m_BC          = g.BC;
     m_EC          = g.EC;
     m_IsClockwise = g.IsClockwise;
 }
예제 #2
0
 public CircularArcGeometry(ICircleGeometry circle, IPosition bc, IPosition ec, bool isClockwise)
 {
     m_Circle      = circle;
     m_BC          = PositionGeometry.Create(bc);
     m_EC          = PositionGeometry.Create(ec);
     m_IsClockwise = isClockwise;
 }
 public CircularArcGeometry(ICircleGeometry circle, IPosition bc, IPosition ec, bool isClockwise)
 {
     m_Circle = circle;
     m_BC = PositionGeometry.Create(bc);
     m_EC = PositionGeometry.Create(ec);
     m_IsClockwise = isClockwise;
 }
 public CircularArcGeometry(ICircleGeometry circle, IPointGeometry bc, IPointGeometry ec, bool isClockwise)
 {
     m_Circle = circle;
     m_BC = bc;
     m_EC = ec;
     m_IsClockwise = isClockwise;
 }
예제 #5
0
 public CircularArcGeometry(ICircleGeometry circle, IPointGeometry bc, IPointGeometry ec, bool isClockwise)
 {
     m_Circle      = circle;
     m_BC          = bc;
     m_EC          = ec;
     m_IsClockwise = isClockwise;
 }
예제 #6
0
        /// <summary>
        /// Gets the exact positions for the BC or EC. The "exact" positions are obtained
        /// by projecting the stored BC/EC to a position that is exactly consistent with the
        /// definition of the underlying circle. Typically, the shifts will be less than 1
        /// micron on the ground.
        /// </summary>
        /// <param name="pos">The position to project (either the BC or EC)</param>
        /// <returns>The position on the circle</returns>
        IPosition GetCirclePosition(IPosition pos)
        {
            // Get the deltas of the position with respect to the centre of the circle.
            ICircleGeometry c    = Circle;
            double          cx   = c.Center.X;
            double          cy   = c.Center.Y;
            double          dx   = pos.X - cx;
            double          dy   = pos.Y - cy;
            double          dist = Math.Sqrt(dx * dx + dy * dy);

            // Return the centre if the position is coincident with the centre.
            if (dist < Constants.TINY)
            {
                return(c.Center);
            }

            // Get the factor for projecting the position.
            double factor = c.Radius / dist;

            // Figure out the position on the circle.
            double x = cx + dx * factor;
            double y = cy + dy * factor;

            return(new Position(x, y));
        }
예제 #7
0
        public static IWindow GetExtent(ICircleGeometry g)
        {
            double xc = g.Center.X;
            double yc = g.Center.Y;
            double r  = g.Radius;

            return(new Window(xc - r, yc - r, xc + r, yc + r));
        }
예제 #8
0
        /// <summary>
        /// Draws a circular arc
        /// </summary>
        /// <param name="display">The display to draw to</param>
        /// <param name="arc">The circular arc</param>
        public void Render(ISpatialDisplay display, IClockwiseCircularArcGeometry arc)
        {
            ICircleGeometry circle     = arc.Circle;
            IWindow         extent     = CircleGeometry.GetExtent(circle);
            float           topLeftX   = display.EastingToDisplay(extent.Min.X);
            float           topLeftY   = display.NorthingToDisplay(extent.Max.Y);
            float           size       = 2.0f * display.LengthToDisplay(circle.Radius);
            float           startAngle = (float)(arc.StartBearingInRadians * MathConstants.RADTODEG - 90.0);
            float           sweepAngle = (float)(arc.SweepAngleInRadians * MathConstants.RADTODEG);

            display.Graphics.DrawArc(m_Pen, topLeftX, topLeftY, size, size, startAngle, sweepAngle);
        }
예제 #9
0
        // If the specified position isn't actually on the arc, the length is to the
        // position when it's projected onto the arc (i.e. the perpendicular position)
        public static ILength GetLength(ICircularArcGeometry g, IPosition asFarAs)
        {
            ICircleGeometry circle = g.Circle;
            double          radius = circle.Radius;

            if (asFarAs == null)
            {
                // If the BC coincides with the EC, it's possible the arc has zero
                // length. As a matter of convention, counter-clockwise arcs will
                // be regarded as having a length of zero in that case. Meanwhile,
                // clockwise arcs will have a length that corresponds to the complete
                // circumference of the circle.

                if (g.BC.IsCoincident(g.EC))
                {
                    if (g.IsClockwise)
                    {
                        return(CircleGeometry.GetLength(circle));
                    }
                    else
                    {
                        return(Backsight.Length.Zero);
                    }
                }

                return(new Length(radius * g.SweepAngleInRadians));
            }

            // Express the position of the BC in a local coordinate system.
            IPosition  c  = circle.Center;
            QuadVertex bc = new QuadVertex(c, g.BC, radius);

            // Calculate the clockwise angle to the desired point.
            QuadVertex to  = new QuadVertex(c, asFarAs, radius);
            double     ang = to.BearingInRadians - bc.BearingInRadians;

            if (ang < 0.0)
            {
                ang += MathConstants.PIMUL2;
            }

            // If the curve is actually anti-clockwise, take the complement.
            if (!g.IsClockwise)
            {
                ang = MathConstants.PIMUL2 - ang;
            }

            return(new Length(radius * ang));
        }
예제 #10
0
        /// <summary>
        /// Calculates the position on a circle that is closest to the specified position
        /// (i.e. takes the supplied position and drop a perpendicular to the circle).
        /// </summary>
        /// <param name="g">The circle of interest</param>
        /// <param name="p">The position to process</param>
        /// <returns>The position on the circle closest to the supplied position. Null
        /// if the supplied position coincides with the center of the circle.</returns>
        public static IPosition GetClosestPosition(ICircleGeometry g, IPosition p)
        {
            // Get the deltas of the supplied position with respect to the circle center
            IPosition c    = g.Center;
            double    dx   = p.X - c.X;
            double    dy   = p.Y - c.Y;
            double    dist = Math.Sqrt(dx * dx + dy * dy);

            // No result if it's too close to the center.
            if (dist < MathConstants.TINY)
            {
                return(null);
            }

            // Get the factor for projecting the position.
            double factor = g.Radius / dist;

            // Figure out the position on the circle.
            return(new Position(c.X + dx * factor, c.Y + dy * factor));
        }
예제 #11
0
 /// <summary>
 /// Do a pair of circles coincide?
 /// </summary>
 /// <param name="a">The first circle</param>
 /// <param name="b">The second circle</param>
 /// <param name="radiusTol">The tolerance for a radius match, in meters on the ground</param>
 /// <returns>True if the two circles have the same center point, and the same radius (within
 /// the specified tolerance)</returns>
 public static bool IsCoincident(ICircleGeometry a, ICircleGeometry b, double radiusTol)
 {
     return(a.Center.IsCoincident(b.Center) &&
            Math.Abs(a.Radius - b.Radius) < radiusTol);
 }
예제 #12
0
        /// <summary>
        /// Intersects this direction with a circle. This may lead to 0, 1, or 2 intersections.
        /// If 2 intersections are found, the first intersection is defined as the one that is
        /// closer to the origin of the direction object.
        /// </summary>
        /// <param name="circle">The circle to intersect with.</param>
        /// <param name="x1">The 1st intersection (if any). Returned as null if no intersection.</param>
        /// <param name="x2">The 2nd intersection (if any). Returned as null if no intersection.</param>
        /// <returns>The number of intersections found.</returns>
        internal uint Intersect(ICircleGeometry circle, out IPosition x1, out IPosition x2)
        {
            // Initialize both intersections.
            x1 = x2 = null;

            // Get the origin of the direction & its bearing.
            IPosition start   = this.StartPosition;
            double    bearing = this.Bearing.Radians;

            // Get the centre of the circle & its radius.
            IPosition center = circle.Center;
            double    radius = circle.Radius;

            // The equation of each line is given in parametric form as:
            //
            //		x = xo + f * r
            //		y = yo + g * r
            //
            // where	xo,yo is the from point
            // and		f = sin(bearing)
            // and		g = cos(bearing)
            // and		r is the position ratio

            double g    = Math.Cos(bearing);
            double f    = Math.Sin(bearing);
            double fsq  = f * f;
            double gsq  = g * g;
            double fgsq = fsq + gsq;

            if (fgsq < Double.Epsilon)   // Should be impossible
            {
                return(0);
            }

            double startx = start.X;
            double starty = start.Y;
            double dx     = center.X - startx;
            double dy     = center.Y - starty;
            double fygx   = f * dy - g * dx;
            double root   = radius * radius * fgsq - fygx * fygx;

            // Check for no intersection.
            if (root < -Constants.TINY)
            {
                return(0);
            }

            // Check for tangential intersection (but don't count a
            // tangent if it precedes the start of the direction line).

            double fxgy = f * dx + g * dy;
            double prat;

            if (root < Constants.TINY)
            {
                prat = fxgy / fgsq;
                if (prat < 0.0)
                {
                    return(0);
                }
                x1 = new Position(startx + f * prat, starty + g * prat);
                return(1);
            }

            // We have two intersections, but one or both of them could
            // precede the start of the direction line.

            root = Math.Sqrt(root);
            double fginv = 1.0 / fgsq;
            double prat1 = (fxgy - root) * fginv;
            double prat2 = (fxgy + root) * fginv;

            // No intersections if both are prior to start of direction.
            if (prat1 < 0.0 && prat2 < 0.0)
            {
                return(0);
            }

            // If both intersections are valid ...
            prat = Math.Min(prat1, prat2);
            if (prat >= 0.0)
            {
                x1   = new Position(startx + f * prat, starty + g * prat);
                prat = Math.Max(prat1, prat2);
                x2   = new Position(startx + f * prat, starty + g * prat);
                return(2);
            }

            // So only one is valid ...
            prat = Math.Max(prat1, prat2);
            x1   = new Position(startx + f * prat, starty + g * prat);
            return(1);
        }
예제 #13
0
        /// <summary>
        /// Intersects 2 clockwise arcs that coincide with the perimeter of a circle.
        /// </summary>
        /// <param name="xsect">Intersection results.</param>
        /// <param name="circle">The circle the arcs coincide with</param>
        /// <param name="bc1">BC for 1st arc.</param>
        /// <param name="ec1">EC for 1st arc.</param>
        /// <param name="bc2">BC for 2nd arc.</param>
        /// <param name="ec2">EC for 2nd arc.</param>
        /// <returns>The number of intersections (0, 1, or 2). If non-zero, the intersections
        /// will be grazes.</returns>
        static uint ArcIntersect( IntersectionResult xsect
            , ICircleGeometry circle
            , IPointGeometry bc1
            , IPointGeometry ec1
            , IPointGeometry bc2
            , IPointGeometry ec2)
        {
            // Define the start of the clockwise arc as a reference line,
            // and get the clockwise angle to it's EC.
            Turn reft = new Turn(circle.Center, bc1);
            double sector = reft.GetAngleInRadians(ec1);

            // Where do the BC and EC of the 2nd curve fall with respect
            // to the 1st curve's arc sector?
            double bcang = reft.GetAngleInRadians(bc2);
            double ecang = reft.GetAngleInRadians(ec2);

            if (bcang<sector)
            {
                if (ecang<bcang)
                {
                    xsect.Append(bc2, ec1);
                    xsect.Append(bc1, ec2);
                    return 2;
                }

                if (ecang<sector)
                    xsect.Append(bc2, ec2);
                else
                    xsect.Append(bc2, ec1);

                return 1;
            }

            // The BC of the 2nd curve falls beyond the sector of the 1st ...
            // so we can't have any graze if the EC is even further on.
            if (ecang>bcang)
                return 0;

            // One graze ...

            if (ecang<sector)
                xsect.Append(bc1, ec2);
            else
                xsect.Append(bc1, ec1);

            return 1;
        }
예제 #14
0
        internal static uint Intersect(IntersectionResult results, ICircleGeometry a, ICircleGeometry b)
        {
            IPointGeometry centre1 = a.Center;
            IPointGeometry centre2 = b.Center;
            double radius1 = a.Radius;
            double radius2 = b.Radius;

            // The following looks pretty similar to Geom.IntersectCircles (some tolerance values are
            // a bit more relaxed here).

            // Pull out the XY's for the 2 centres.
            double xc1 = centre1.X;
            double yc1 = centre1.Y;
            double xc2 = centre2.X;
            double yc2 = centre2.Y;

            // Get distance (squared) between the 2 centres.
            double dx = xc2 - xc1;
            double dy = yc2 - yc1;
            double distsq = dx*dx + dy*dy;

            //	If the two circles have the same centre, check whether
            //	the radii match (if so, we have an overlap case).

            if (distsq < Constants.TINY)
            {
                if (Math.Abs(radius1-radius2) < Constants.XYRES)
                {
                    double xi = xc1;
                    double yi = yc1 + radius1;
                    results.Append(xi, yi, xi, yi);
                    return 1;
                }
                else
                    return 0;
            }

            // We'll need the radii squared
            double rsq1 = radius1 * radius1;
            double rsq2 = radius2 * radius2;

            // Now some mathematical magic I got out a book.
            double delrsq = rsq2 - rsq1;
            double sumrsq = rsq1 + rsq2;
            double root = 2.0*sumrsq*distsq - distsq*distsq - delrsq*delrsq;

            //	Check for no intersection.
            if (root < Constants.TINY)
                return 0;

            // We have at least one intersection.
            double dstinv = 0.5 / distsq;
            double scl = 0.5 - delrsq*dstinv;
            double x = dx*scl + xc1;
            double y = dy*scl + yc1;

            //	Is it tangential?
            if (root < Constants.TINY)
            {
                results.Append(x, y, 0.0);
                return 1;
            }

            // Figure out 2 intersections.
            root = dstinv * Math.Sqrt(root);
            double xfac = dx*root;
            double yfac = dy*root;

            results.Append(x-yfac, y+xfac, 0.0);
            results.Append(x+yfac, y-xfac, 0.0);
            return 2;
        }
예제 #15
0
        /// <summary>
        /// Intersect two circles. If there are two intersections,
        /// they are arranged so that the one with the lowest bearing comes first.
        /// </summary>
        /// <param name="a">The 1st circle</param>
        /// <param name="b">The 2nd circle</param>
        /// <param name="x1">The 1st intersection (if any).</param>
        /// <param name="x2">The 2nd intersection (if any).</param>
        /// <returns>The number of intersections found.</returns>
        internal static uint Intersect(ICircleGeometry a, ICircleGeometry b, out IPosition x1, out IPosition x2)
        {
            // Get the intersections (if any).
            uint nx = Geom.IntersectCircles(a.Center, a.Radius, b.Center, b.Radius, out x1, out x2);

            // Return if 0 or 1 intersection.
            if (nx<2)
                return nx;

            // Arrange the intersections so that the one with the lowest bearing comes first.
            QuadVertex q1x1 = new QuadVertex(a.Center, x1);
            QuadVertex q1x2 = new QuadVertex(a.Center, x2);
            QuadVertex q2x1 = new QuadVertex(b.Center, x1);
            QuadVertex q2x2 = new QuadVertex(b.Center, x2);

            double b1x1 = q1x1.BearingInRadians;
            double b1x2 = q1x2.BearingInRadians;
            double b2x1 = q2x1.BearingInRadians;
            double b2x2 = q2x2.BearingInRadians;

            // Switch if the min bearing to the 2nd intersection is actually
            // less than the min bearing to the 1st intersection.

            if (Math.Min(b1x2, b2x2) < Math.Min(b1x1, b2x1))
            {
                IPosition temp = x1;
                x1 = x2;
                x2 = temp;
            }

            return 2;
        }
예제 #16
0
 internal static uint Intersect(IntersectionResult result, ILineSegmentGeometry seg, ICircleGeometry circle)
 {
     return Intersect(result, seg.Start, seg.End, circle.Center, circle.Radius);
 }
예제 #17
0
 internal override uint IntersectCircle(IntersectionResult results, ICircleGeometry circle)
 {
     return(Make().IntersectCircle(results, circle));
 }
예제 #18
0
        /// <summary>
        /// Calculates the position on a circle that is closest to the specified position
        /// (i.e. takes the supplied position and drop a perpendicular to the circle).
        /// </summary>
        /// <param name="g">The circle of interest</param>
        /// <param name="p">The position to process</param>
        /// <returns>The position on the circle closest to the supplied position. Null
        /// if the supplied position coincides with the center of the circle.</returns>
        public static IPosition GetClosestPosition(ICircleGeometry g, IPosition p)
        {
            // Get the deltas of the supplied position with respect to the circle center
            IPosition c = g.Center;
            double dx = p.X - c.X;
            double dy = p.Y - c.Y;
            double dist = Math.Sqrt(dx*dx + dy*dy);

            // No result if it's too close to the center.
            if (dist<MathConstants.TINY)
                return null;

            // Get the factor for projecting the position.
            double factor = g.Radius/dist;

            // Figure out the position on the circle.
            return new Position(c.X + dx*factor, c.Y + dy*factor);
        }
예제 #19
0
 public static ILength Distance(ICircleGeometry g, IPosition p)
 {
     double d = BasicGeom.Distance(g.Center, p);
     return new Length(Math.Abs(d - g.Radius));
 }
예제 #20
0
 abstract internal uint IntersectCircle(IntersectionResult results, ICircleGeometry circle);
예제 #21
0
 public CircularArcGeometry(ICircularArcGeometry g)
 {
     m_Circle = g.Circle;
     m_BC = g.BC;
     m_EC = g.EC;
     m_IsClockwise = g.IsClockwise;
 }
예제 #22
0
        /// <summary>
        /// Intersects this direction with a circle. This may lead to 0, 1, or 2 intersections.
        /// If 2 intersections are found, the first intersection is defined as the one that is
        /// closer to the origin of the direction object.
        /// </summary>
        /// <param name="circle">The circle to intersect with.</param>
        /// <param name="x1">The 1st intersection (if any). Returned as null if no intersection.</param>
        /// <param name="x2">The 2nd intersection (if any). Returned as null if no intersection.</param>
        /// <returns>The number of intersections found.</returns>
        internal uint Intersect(ICircleGeometry circle, out IPosition x1, out IPosition x2)
        {
            // Initialize both intersections.
            x1 = x2 = null;

            // Get the origin of the direction & its bearing.
            IPosition start = this.StartPosition;
            double bearing = this.Bearing.Radians;

            // Get the centre of the circle & its radius.
            IPosition center = circle.Center;
            double radius = circle.Radius;

            // The equation of each line is given in parametric form as:
            //
            //		x = xo + f * r
            //		y = yo + g * r
            //
            // where	xo,yo is the from point
            // and		f = sin(bearing)
            // and		g = cos(bearing)
            // and		r is the position ratio

            double g = Math.Cos(bearing);
            double f = Math.Sin(bearing);
            double fsq = f*f;
            double gsq = g*g;
            double fgsq = fsq + gsq;

            if (fgsq<Double.Epsilon) // Should be impossible
                return 0;

            double startx = start.X;
            double starty = start.Y;
            double dx = center.X - startx;
            double dy = center.Y - starty;
            double fygx = f*dy - g*dx;
            double root = radius*radius*fgsq - fygx*fygx;

            // Check for no intersection.
            if (root < -Constants.TINY )
                return 0;

            // Check for tangential intersection (but don't count a
            // tangent if it precedes the start of the direction line).

            double fxgy = f*dx + g*dy;
            double prat;

            if (root < Constants.TINY)
            {
                prat = fxgy/fgsq;
                if (prat<0.0)
                    return 0;
                x1 = new Position(startx + f*prat, starty + g*prat);
                return 1;
            }

            // We have two intersections, but one or both of them could
            // precede the start of the direction line.

            root = Math.Sqrt(root);
            double fginv = 1.0/fgsq;
            double prat1 = (fxgy - root)*fginv;
            double prat2 = (fxgy + root)*fginv;

            // No intersections if both are prior to start of direction.
            if (prat1<0.0 && prat2<0.0)
                return 0;

            // If both intersections are valid ...
            prat = Math.Min(prat1,prat2);
            if (prat>=0.0)
            {
                x1 = new Position(startx + f*prat, starty + g*prat);
                prat = Math.Max(prat1,prat2);
                x2 = new Position(startx + f*prat, starty + g*prat);
                return 2;
            }

            // So only one is valid ...
            prat = Math.Max(prat1,prat2);
            x1 = new Position(startx + f*prat, starty + g*prat);
            return 1;
        }
예제 #23
0
 public static void Render(ICircleGeometry g, ISpatialDisplay display, IDrawStyle style)
 {
     style.Render(display, g.Center, g.Radius);
 }
예제 #24
0
 public static IWindow GetExtent(ICircleGeometry g)
 {
     double xc = g.Center.X;
     double yc = g.Center.Y;
     double r = g.Radius;
     return new Window(xc-r, yc-r, xc+r, yc+r);
 }
예제 #25
0
        /// <summary>
        /// Intersects a circle with a clockwise arc
        /// </summary>
        /// <param name="results"></param>
        /// <param name="c"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="arcCircle"></param>
        /// <returns></returns>
        static uint Intersect(IntersectionResult xsect, ICircleGeometry c, IPointGeometry start, IPointGeometry end, ICircleGeometry arcCircle)
        {
            // If the circles are IDENTICAL, we've got a graze.
            if (CircleGeometry.IsCoincident(c, arcCircle, Constants.XYRES))
            {
                xsect.Append(start, end);
                return 1;

            }

            // Intersect the 2 circles.
            IPosition x1, x2;
            uint nx = Intersect(c, arcCircle, out x1, out x2);

            // Return if no intersection.
            if (nx==0)
                return 0;

            // Remember the intersection(s) if they fall in the
            // curve's sector. Use a tolerance which is based on
            // the circle with the smaller radius (=> bigger angular
            // tolerance).

            IPointGeometry centre;
            double minrad;

            if (c.Radius < arcCircle.Radius)
            {
                minrad = c.Radius;
                centre = c.Center;
            }
            else
            {
                minrad = arcCircle.Radius;
                centre = arcCircle.Center;
            }

            //	const FLOAT8 angtol = XYTOL/minrad;
            //	const FLOAT8 angtol = 0.00002/minrad;	// 20 microns
            double angtol = 0.002/minrad;		// 2mm

            if (nx==1)
            {
                IPointGeometry loc = PointGeometry.Create(x1);
                if (Geom.IsInSector(loc, centre, start, end, angtol))
                {
                    xsect.Append(loc);
                    return 1;
                }

                return 0;
            }
            else
            {
                // Two intersections. They are valid if they fall within the curve's sector.
                IPointGeometry loc1 = PointGeometry.Create(x1);
                IPointGeometry loc2 = PointGeometry.Create(x2);
                uint nok=0;

                if (Geom.IsInSector(loc1, centre, start, end, angtol))
                {
                    xsect.Append(loc1);
                    nok++;
                }

                if (Geom.IsInSector(loc2, centre, start, end, angtol))
                {
                    xsect.Append(loc2);
                    nok++;
                }

                return nok;
            }
        }
예제 #26
0
 /// <summary>
 /// Calculates the perimeter length of a circle.
 /// </summary>
 /// <param name="g">The circle of interest</param>
 /// <returns>The perimeter length of the circle.</returns>
 public static ILength GetLength(ICircleGeometry g)
 {
     return new Length(g.Radius * MathConstants.PIMUL2);
 }
예제 #27
0
        internal static uint Intersect(IntersectionResult results, IMultiSegmentGeometry line, ICircleGeometry circle)
        {
            uint nx=0;

            IPointGeometry[] segs = line.Data;
            IPointGeometry c = circle.Center;
            double r = circle.Radius;

            for (int i=1; i<segs.Length; i++)
                nx += Intersect(results, segs[i-1], segs[i], c, r);

            return nx;
        }
예제 #28
0
 /// <summary>
 /// Do a pair of circles coincide?
 /// </summary>
 /// <param name="a">The first circle</param>
 /// <param name="b">The second circle</param>
 /// <param name="radiusTol">The tolerance for a radius match, in meters on the ground</param>
 /// <returns>True if the two circles have the same center point, and the same radius (within
 /// the specified tolerance)</returns>
 public static bool IsCoincident(ICircleGeometry a, ICircleGeometry b, double radiusTol)
 {
     return (a.Center.IsCoincident(b.Center) &&
             Math.Abs(a.Radius - b.Radius)<radiusTol);
 }
예제 #29
0
 internal static uint Intersect(IntersectionResult results, ICircularArcGeometry a, ICircleGeometry b)
 {
     if (CircularArcGeometry.IsCircle(a))
         return Intersect(results, a.Circle, b);
     else
         return Intersect(results, b, a.First, a.Second, a.Circle);
 }
예제 #30
0
 public static void Render(ICircleGeometry g, ISpatialDisplay display, IDrawStyle style)
 {
     style.Render(display, g.Center, g.Radius);
 }
예제 #31
0
        /// <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;
        }
예제 #32
0
 public CircleGeometry(ICircleGeometry g)
 {
     m_Center = g.Center;
     m_Radius = g.Radius;
 }
예제 #33
0
        /// <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;
        }
예제 #34
0
 internal override uint IntersectCircle(IntersectionResult results, ICircleGeometry that)
 {
     return IntersectionHelper.Intersect(results, (ILineSegmentGeometry)this, that);
 }
예제 #35
0
        public static ILength Distance(ICircleGeometry g, IPosition p)
        {
            double d = BasicGeom.Distance(g.Center, p);

            return(new Length(Math.Abs(d - g.Radius)));
        }
예제 #36
0
 internal override uint IntersectCircle(IntersectionResult results, ICircleGeometry that)
 {
     return(IntersectionHelper.Intersect(results, (ICircularArcGeometry)this, that));
 }
예제 #37
0
 /// <summary>
 /// Calculates the perimeter length of a circle.
 /// </summary>
 /// <param name="g">The circle of interest</param>
 /// <returns>The perimeter length of the circle.</returns>
 public static ILength GetLength(ICircleGeometry g)
 {
     return(new Length(g.Radius * MathConstants.PIMUL2));
 }
예제 #38
0
 internal override uint IntersectCircle(IntersectionResult results, ICircleGeometry circle)
 {
     return Make().IntersectCircle(results, circle);
 }
예제 #39
0
 public CircleGeometry(ICircleGeometry g)
 {
     m_Center = g.Center;
     m_Radius = g.Radius;
 }
예제 #40
0
        /// <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;
        }
예제 #41
0
 internal abstract uint IntersectCircle(IntersectionResult results, ICircleGeometry circle);
예제 #42
0
        /// <summary>
        /// Gets the position that is a specific distance from the start of a circular arc.
        /// </summary>
        /// <param name="g">The geometry for the circular arc</param>
        /// <param name="distance">The distance from the start of the arc.</param>
        /// <param name="result">The position found</param>
        /// <returns>True if the distance is somewhere ON the arc. False if the distance
        /// was less than zero, or more than the arc length (in that case, the position
        /// found corresponds to the corresponding terminal point).</returns>
        public static bool GetPosition(ICircularArcGeometry g, ILength distance, out IPosition result)
        {
            // Allow 1 micron tolerance
            const double TOL = 0.000001;

            // Check for invalid distances.
            double d = distance.Meters;

            if (d < 0.0)
            {
                result = g.BC;
                return(false);
            }

            double clen = g.Length.Meters; // Arc length

            if (d > (clen + TOL))
            {
                result = g.EC;
                return(false);
            }

            // Check for limiting values (if you don't do this, minute
            // roundoff at the BC & EC can lead to spurious locations).
            // (although it's possible to use TINY here, use 1 micron
            // instead, since we can't represent position any better
            // than that).

            if (d < TOL)
            {
                result = g.BC;
                return(true);
            }

            if (Math.Abs(d - clen) < TOL)
            {
                result = g.EC;
                return(true);
            }

            // Get the bearing of the BC
            ICircleGeometry circle  = g.Circle;
            IPosition       c       = circle.Center;
            double          radius  = circle.Radius;
            double          bearing = BasicGeom.BearingInRadians(c, g.BC);

            // Add the angle that subtends the required distance (or
            // subtract if the curve goes anti-clockwise).
            if (g.IsClockwise)
            {
                bearing += (d / radius);
            }
            else
            {
                bearing -= (d / radius);
            }

            // Figure out the required point from the new bearing.
            result = BasicGeom.Polar(c, bearing, radius);
            return(true);
        }