コード例 #1
0
        /// <summary>
        /// Checks whether a location falls in the sector lying between the BC and EC
        /// of a circular arc. The only condition is that the location has an appropriate
        /// bearing with respect to the bearings of the BC & EC (i.e. the location does not
        /// necessarily lie ON the arc).
        /// </summary>
        /// <param name="pos">The position to check</param>
        /// <param name="lintol">Linear tolerance, in meters on the ground (locations that are
        /// beyond the BC or EC by up to this much will also be regarded as "in-sector").</param>
        /// <returns>True if position falls in the sector defined by this arc</returns>
        public static bool IsInSector(ICircularArcGeometry g, IPosition pos, double lintol)
        {
            // If the arc is a complete circle, it's ALWAYS in sector.
            if (IsCircle(g))
            {
                return(true);
            }

            // Express the curve's start & end points in local system,
            // ordered clockwise.
            IPointGeometry start = g.First;
            IPointGeometry end   = g.Second;

            // Get the centre of the circular arc.
            IPosition centre = g.Circle.Center;

            // If we have a linear tolerance, figure out the angular equivalent.
            if (lintol > MathConstants.TINY)
            {
                double angtol = lintol / g.Circle.Radius;
                return(BasicGeom.IsInSector(pos, centre, start, end, angtol));
            }
            else
            {
                return(BasicGeom.IsInSector(pos, centre, start, end, 0.0));
            }
        }
コード例 #2
0
 public CircularArcGeometry(ICircularArcGeometry g)
 {
     m_Circle      = g.Circle;
     m_BC          = g.BC;
     m_EC          = g.EC;
     m_IsClockwise = g.IsClockwise;
 }
コード例 #3
0
        /// <summary>
        /// Generates an approximation of a circular arc.
        /// </summary>
        /// <param name="tol">The maximum chord-to-circumference distance.</param>
        /// <returns></returns>
        public static IPointGeometry[] GetApproximation(ICircularArcGeometry g, ILength tol)
        {
            // Get info about the circle the curve lies on.
            IPosition center = g.Circle.Center;
            double    radius = g.Circle.Radius;

            // Determine the change in bearing which will satisfy the specified tolerance
            // (if no tolerance has been specified, arbitrarily use a tolerance of 1mm on the ground).
            double tolm  = (tol.Meters > Double.Epsilon ? tol.Meters : 0.001);
            double dbear = Math.Acos((radius - tolm) / radius);

            IPointGeometry start = g.BC;
            IPointGeometry end   = g.EC;
            bool           iscw  = g.IsClockwise;

            // Get the total angle subtended by the curve.
            Turn   reft   = new Turn(center, start);
            double totang = reft.GetAngleInRadians(end); // clockwise

            if (!iscw)
            {
                totang = MathConstants.PIMUL2 - totang;
            }

            // Figure out how many positions we'll generate
            int nv = (int)(totang / dbear); // truncate

            Debug.Assert(nv >= 0);

            // Handle special case of very short arc.
            if (nv == 0)
            {
                return new IPointGeometry[] { start, end }
            }
            ;

            // Sign the delta-bearing the right way.
            if (!iscw)
            {
                dbear = -dbear;
            }

            // Get the initial bearing to the first position along the curve.
            double curbear = reft.BearingInRadians + dbear;

            // Append positions along the length of the curve.
            List <IPointGeometry> result = new List <IPointGeometry>(nv);

            result.Add(start);

            for (int i = 0; i < nv; i++, curbear += dbear)
            {
                IPosition p = BasicGeom.Polar(center, curbear, radius);
                result.Add(PositionGeometry.Create(p));
            }

            result.Add(end);
            return(result.ToArray());
        }
コード例 #4
0
        public static double GetSweepAngleInRadians(ICircularArcGeometry g)
        {
            IPosition f = g.First;
            IPosition s = g.Second;
            Turn      t = new Turn(g.Circle.Center, f);

            return(t.GetAngleInRadians(s));
        }
コード例 #5
0
        internal InverseArcDistanceForm()
        {
            InitializeComponent();
            color1Button.BackColor = InverseColors[0];
            color2Button.BackColor = InverseColors[1];

            m_Point1             = m_Point2 = null;
            m_Cir1               = m_Cir2 = m_CommCir = null;
            m_WantShort          = true;
            m_CurrentDistanceArc = null;
        }
コード例 #6
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));
        }
コード例 #7
0
        static double MinDistanceSquared(ICircularArcGeometry g, IPosition p)
        {
            // If the position lies in the arc sector, the minimum distance
            // is given by the distance to the circle. Otherwise the minimum
            // distance is the distance to the closest end of the arc.

            if (IsInSector(g, p, 0.0))
            {
                double dist   = BasicGeom.Distance(p, g.Circle.Center);
                double radius = g.Circle.Radius;
                return((dist - radius) * (dist - radius));
            }
            else
            {
                double d1 = BasicGeom.DistanceSquared(p, g.BC);
                double d2 = BasicGeom.DistanceSquared(p, g.EC);
                return(Math.Min(d1, d2));
            }
        }
コード例 #8
0
        internal virtual void ShowResult()
        {
            // If we have two points, get the distance between them,
            // format the result, and display it.
            if (m_Point1 != null && m_Point2 != null && m_CommCir != null)
            {
                // It's conceivable that the two points share more than
                // one common circle. For now, just pick off the first
                // common circle and use that.
                Circle circle = m_CommCir[0];

                // Get the centre of the circle.
                IPosition c = circle.Center;

                // Get the clockwise angle from point 1 to point 2.
                Turn   reft  = new Turn(c, m_Point1);
                double angle = reft.GetAngleInRadians(m_Point2);
                bool   iscw  = true;

                // Make sure the angle is consistent with whether we want
                // the short or the long arc distance.
                bool isshort = (angle < Constants.PI);
                if (isshort != m_WantShort)
                {
                    angle = Constants.PIMUL2 - angle;
                    iscw  = false;
                }

                // Get the arc distance and display it.
                double metric = angle * circle.Radius;
                distanceTextBox.Text = Format(metric, m_Point1, m_Point2);

                // Remember the geometry that corresponds to the displayed distance (this
                // will be drawn when the controller periodically calls the Draw method).
                m_CurrentDistanceArc = new CircularArcGeometry(circle, m_Point1, m_Point2, iscw);
            }
            else
            {
                distanceTextBox.Text = "<no distance>";
                m_CurrentDistanceArc = null;
            }
        }
コード例 #9
0
 internal static uint Intersect(IntersectionResult result, ILineSegmentGeometry seg, ICircularArcGeometry arc)
 {
     if (CircularArcGeometry.IsCircle(arc))
         return Intersect(result, seg, arc.Circle);
     else
         return Intersect(result, seg.Start, seg.End, arc.First, arc.Second, arc.Circle);
 }
コード例 #10
0
        /// <summary>
        /// Intersects a pair of circular arcs.
        /// </summary>
        /// <param name="results">Where to stick the results</param>
        /// <param name="a">The first arc</param>
        /// <param name="b">The second arc</param>
        /// <returns></returns>
        internal static uint Intersect(IntersectionResult results, ICircularArcGeometry ab, ICircularArcGeometry pq)
        {
            // Special handling if the two arcs share the same circle
            if (CircleGeometry.IsCoincident(ab.Circle, pq.Circle, Constants.XYRES))
                return ArcIntersect(results, ab, pq);

            // Arcs that meet exactly end to end get handled seperately.
            IPointGeometry a = ab.First;
            IPointGeometry b = ab.Second;
            IPointGeometry p = pq.First;
            IPointGeometry q = pq.Second;

            if (a.IsCoincident(p) || a.IsCoincident(q))
                return EndIntersect(results, ab, pq, true);

            if (b.IsCoincident(p) || b.IsCoincident(q))
                return EndIntersect(results, ab, pq, false);

            // Intersect the circle for the two arcs
            IPosition x1, x2;
            uint nx = Intersect(ab.Circle, pq.Circle, out x1, out x2);

            // Return if the circles don't intersect.
            if (nx==0)
                return 0;

            // Remember the intersection(s) if they fall in BOTH curve sectors.

            IPointGeometry thiscen = ab.Circle.Center;
            IPointGeometry othrcen = pq.Circle.Center;

            if (nx==1)
            {
                // If we got 1 intersection, it may be VERY close to the end
                // points. Make sure we also consider the precise check made up top.
                // Otherwise check if the intersection is in both sectors.

                IPointGeometry loc = PointGeometry.Create(x1); // rounded to nearest micron

                if (Geom.IsInSector(loc, thiscen, a, b, 0.0) &&
                    Geom.IsInSector(loc, othrcen, p, q, 0.0))
                {
                    results.Append(loc);
                    return 1;
                }

                return 0;
            }
            else
            {
                // Two intersections. They are valid if they fall within the arc's sector.
                // Again, make sure we consider any precise end-point check made above.

                uint nok=0;
                IPointGeometry loc1 = PointGeometry.Create(x1);
                IPointGeometry loc2 = PointGeometry.Create(x2);

                if (Geom.IsInSector(loc1, thiscen, a, b, 0.0) &&
                    Geom.IsInSector(loc1, othrcen, p, q, 0.0))
                {
                    results.Append(loc1);
                    nok++;
                }

                if (Geom.IsInSector(loc2, thiscen, a, b, 0.0) &&
                    Geom.IsInSector(loc2, othrcen, p, q, 0.0))
                {
                    results.Append(loc2);
                    nok++;
                }

                return nok;
            }
        }
コード例 #11
0
 internal uint IntersectArc(ICircularArcGeometry arc)
 {
     return m_IntersectedObject.LineGeometry.IntersectArc(this, arc);
 }
コード例 #12
0
ファイル: ArcGeometry.cs プロジェクト: 15831944/backsight
 internal override uint IntersectArc(IntersectionResult results, ICircularArcGeometry that)
 {
     return(IntersectionHelper.Intersect(results, that, (ICircularArcGeometry)this));
 }
コード例 #13
0
        public static IWindow GetExtent(ICircularArcGeometry g)
        {
            // If the curve is a complete circle, just define it the easy way.
            if (g.BC.IsCoincident(g.EC))
            {
                return(CircleGeometry.GetExtent(g.Circle));
            }

            IPosition bcp    = g.BC;
            IPosition ecp    = g.EC;
            IPosition centre = g.Circle.Center;

            // Initialize the window with the start location.
            Window win = new Window(bcp);

            // Expand using the end location
            win.Union(ecp);

            // If the curve is completely within one quadrant, we're done.
            QuadVertex bc = new QuadVertex(centre, bcp);
            QuadVertex ec = new QuadVertex(centre, ecp);

            Quadrant qbc = bc.Quadrant;
            Quadrant qec = ec.Quadrant;

            if (qbc == qec)
            {
                if (g.IsClockwise)
                {
                    if (bc.GetTanAngle() < ec.GetTanAngle())
                    {
                        return(win);
                    }
                }
                else
                {
                    if (ec.GetTanAngle() < bc.GetTanAngle())
                    {
                        return(win);
                    }
                }
            }

            // Get the window of the circle
            IWindow circle = CircleGeometry.GetExtent(g.Circle);

            // If the curve is anticlockwise, switch the quadrants for BC & EC
            if (!g.IsClockwise)
            {
                Quadrant temp = qbc;
                qbc = qec;
                qec = temp;
            }

            // Expand the window, depending on which quadrants the start &
            // end points fall in. The lack of breaks in the inner switches
            // is intentional (e.g. if start & end both fall in Quadrant.NorthEast,
            // the window we want is the complete circle, having checked above
            // for the case where the arc is JUST in Quadrant.NorthEast).

            // Define do-nothing values for the Union's below
            double wx = win.Min.X;
            double wy = win.Min.Y;

            if (qbc == Quadrant.NE)
            {
                switch (qec)
                {
                case Quadrant.NE:
                    win.Union(wx, circle.Max.Y);
                    goto case Quadrant.NW;

                case Quadrant.NW:
                    win.Union(circle.Min.X, wy);
                    goto case Quadrant.SW;

                case Quadrant.SW:
                    win.Union(wx, circle.Min.Y);
                    goto case Quadrant.SE;

                case Quadrant.SE:
                    win.Union(circle.Max.X, wy);
                    break;
                }
            }
            else if (qbc == Quadrant.SE)
            {
                switch (qec)
                {
                case Quadrant.SE:
                    win.Union(circle.Max.X, wy);
                    goto case Quadrant.NE;

                case Quadrant.NE:
                    win.Union(wx, circle.Max.Y);
                    goto case Quadrant.NW;

                case Quadrant.NW:
                    win.Union(circle.Min.X, wy);
                    goto case Quadrant.SW;

                case Quadrant.SW:
                    win.Union(wx, circle.Min.Y);
                    break;
                }
            }
            else if (qbc == Quadrant.SW)
            {
                switch (qec)
                {
                case Quadrant.SW:
                    win.Union(wx, circle.Min.Y);
                    goto case Quadrant.SE;

                case Quadrant.SE:
                    win.Union(circle.Max.X, wy);
                    goto case Quadrant.NE;

                case Quadrant.NE:
                    win.Union(wx, circle.Max.Y);
                    goto case Quadrant.NW;

                case Quadrant.NW:
                    win.Union(circle.Min.X, wy);
                    break;
                }
            }
            else if (qbc == Quadrant.NW)
            {
                switch (qec)
                {
                case Quadrant.NW:
                    win.Union(circle.Min.X, wy);
                    goto case Quadrant.SW;

                case Quadrant.SW:
                    win.Union(wx, circle.Min.Y);
                    goto case Quadrant.SE;

                case Quadrant.SE:
                    win.Union(circle.Max.X, wy);
                    goto case Quadrant.NE;

                case Quadrant.NE:
                    win.Union(wx, circle.Max.Y);
                    break;
                }
            }

            return(win);
        }
コード例 #14
0
 abstract internal uint IntersectArc(IntersectionResult results, ICircularArcGeometry arc);
コード例 #15
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);
        }
コード例 #16
0
 /// <summary>
 /// The second position of an arc, when reckoned clockwise.
 /// </summary>
 public static IPointGeometry GetSecondPosition(ICircularArcGeometry g)
 {
     return (g.IsClockwise ? g.EC : g.BC);
 }
コード例 #17
0
        static uint ArcIntersect(IntersectionResult results, ICircularArcGeometry ab, ICircularArcGeometry pq)
        {
            // Arcs that meet exactly end to end get handled seperately.
            IPointGeometry a = ab.First;
            IPointGeometry b = ab.Second;
            IPointGeometry p = pq.First;
            IPointGeometry q = pq.Second;

            if (a.IsCoincident(p) || a.IsCoincident(q))
                //return ArcEndIntersect(results, pq.Circle, p, q, a, b);
                return ArcEndIntersect(results, pq.Circle, p, q, a, b, true);

            if (b.IsCoincident(p) || b.IsCoincident(q))
                //return ArcEndIntersect(results, pq.Circle, p, q, b, a);
                return ArcEndIntersect(results, pq.Circle, p, q, a, b, false);

            return ArcIntersect(results, pq.Circle, p, q, a, b);
        }
コード例 #18
0
 /// <summary>
 /// The second position of an arc, when reckoned clockwise.
 /// </summary>
 public static IPointGeometry GetSecondPosition(ICircularArcGeometry g)
 {
     return(g.IsClockwise ? g.EC : g.BC);
 }
コード例 #19
0
 public static ILength GetDistance(ICircularArcGeometry g, IPosition p)
 {
     return(new Length(Math.Sqrt(MinDistanceSquared(g, p))));
 }
コード例 #20
0
 public static double GetStartBearingInRadians(ICircularArcGeometry g)
 {
     return(BasicGeom.BearingInRadians(g.Circle.Center, g.First));
 }
コード例 #21
0
 /// <summary>
 /// Does a circular arc represent a complete circle (with a
 /// BC that's coincident with the EC).
 /// </summary>
 public static bool IsCircle(ICircularArcGeometry g)
 {
     return(g.BC.IsCoincident(g.EC));
 }
コード例 #22
0
 public static double GetSweepAngleInRadians(ICircularArcGeometry g)
 {
     IPosition f = g.First;
     IPosition s = g.Second;
     Turn t = new Turn(g.Circle.Center, f);
     return t.GetAngleInRadians(s);
 }
コード例 #23
0
        /// <summary>
        /// Checks whether a location falls in the sector lying between the BC and EC
        /// of a circular arc. The only condition is that the location has an appropriate
        /// bearing with respect to the bearings of the BC & EC (i.e. the location does not
        /// necessarily lie ON the arc).
        /// </summary>
        /// <param name="pos">The position to check</param>
        /// <param name="lintol">Linear tolerance, in meters on the ground (locations that are
        /// beyond the BC or EC by up to this much will also be regarded as "in-sector").</param>
        /// <returns>True if position falls in the sector defined by this arc</returns>
        public static bool IsInSector(ICircularArcGeometry g, IPosition pos, double lintol)
        {
            // If the arc is a complete circle, it's ALWAYS in sector.
            if (IsCircle(g))
                return true;

            // Express the curve's start & end points in local system,
            // ordered clockwise.
            IPointGeometry start = g.First;
            IPointGeometry end = g.Second;

            // Get the centre of the circular arc.
            IPosition centre = g.Circle.Center;

            // If we have a linear tolerance, figure out the angular equivalent.
            if (lintol > MathConstants.TINY)
            {
                double angtol = lintol/g.Circle.Radius;
                return BasicGeom.IsInSector(pos, centre, start, end, angtol);
            }
            else
                return BasicGeom.IsInSector(pos, centre, start, end, 0.0);
        }
コード例 #24
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;
        }
コード例 #25
0
        static double MinDistanceSquared(ICircularArcGeometry g, IPosition p)
        {
            // If the position lies in the arc sector, the minimum distance
            // is given by the distance to the circle. Otherwise the minimum
            // distance is the distance to the closest end of the arc.

            if (IsInSector(g, p, 0.0))
            {
                double dist = BasicGeom.Distance(p, g.Circle.Center);
                double radius = g.Circle.Radius;
                return (dist-radius)*(dist-radius);
            }
            else
            {
                double d1 = BasicGeom.DistanceSquared(p, g.BC);
                double d2 = BasicGeom.DistanceSquared(p, g.EC);
                return Math.Min(d1, d2);
            }
        }
コード例 #26
0
 public static double GetStartBearingInRadians(ICircularArcGeometry g)
 {
     return BasicGeom.BearingInRadians(g.Circle.Center, g.First);
 }
コード例 #27
0
 public static void Render(ICircularArcGeometry g, ISpatialDisplay display, IDrawStyle style)
 {
     style.Render(display, (IClockwiseCircularArcGeometry)g);
 }
コード例 #28
0
 /// <summary>
 /// Does a circular arc represent a complete circle (with a
 /// BC that's coincident with the EC).
 /// </summary>
 public static bool IsCircle(ICircularArcGeometry g)
 {
     return g.BC.IsCoincident(g.EC);
 }
コード例 #29
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);
        }
コード例 #30
0
 public static void Render(ICircularArcGeometry g, ISpatialDisplay display, IDrawStyle style)
 {
     style.Render(display, (IClockwiseCircularArcGeometry)g);
 }
コード例 #31
0
        /// <summary>
        /// Defines links for this face. A prior call to <c>SetLine</c> is required.
        /// </summary>
        /// <param name="prev">The preceding face (after it has been processed via a call to
        /// <c>SetLine</c>, Must refer to the same polygon as this face.</param>
        /// <returns>The links (the number of array elements will equal the value that came
        /// back from the <c>SetLine</c> call)</returns>
        internal PolygonLink[] CreateLinks(PolygonFace prev)
        {
            Debug.Assert(m_Polygon != null);
            Debug.Assert(m_Divider != null);
            Debug.Assert(prev.Divider != null);
            Debug.Assert(Object.ReferenceEquals(prev.Polygon, m_Polygon));

            // Try to obtain a point feature at the beginning of this face.
            ISpatialIndex index      = CadastralMapModel.Current.Index;
            PointFeature  beginPoint = new FindPointQuery(index, m_Begin).Result;

            // If the polygon to the left of the this face? (if so, curve-related
            // things may need to be reversed below)
            bool isPolLeft = (m_Divider.Left == m_Polygon);

            // Default geometric info we need to define
            bool   isCurveEnd = false;
            bool   isRadial   = false;
            double bearing    = 0.0;
            double angle      = 0.0;

            // Is the position at the beginning of this face the start
            // or end of a circular arc (points between 2 curves (on
            // compound curve) are NOT considered to be curve ends). Note
            // that the line could either be a CircularArc, or a topological
            // section based on a circular arc.

            ICircularArcGeometry prevArc = (prev.Divider.LineGeometry as ICircularArcGeometry);
            ICircularArcGeometry thisArc = (m_Divider.LineGeometry as ICircularArcGeometry);
            bool isPrevCurve             = (prevArc != null);
            bool isThisCurve             = (thisArc != null);

            isCurveEnd = (isPrevCurve != isThisCurve);

            // If we are dealing with a point between two curves try to
            // set the curve parameters and, if successful, we will treat
            // the point as a radial point.

            if (isPrevCurve && isThisCurve)
            {
                isRadial = true;

                // Get the curve parameters...

                IPosition prevcen = prevArc.Circle.Center;
                double    prevrad = prevArc.Circle.Radius;

                IPosition thiscen = thisArc.Circle.Center;
                double    thisrad = thisArc.Circle.Radius;

                // We only need to know the sense for one of the arcs
                bool iscw = thisArc.IsClockwise;

                // If the 2 curves do not have the same centre and radius,
                // see if they are really close (to the nearest centimeter
                // on the ground). In that case, use the average values for
                // the 2 curves. If they really are different curves, don't
                // treat this as a radial curve point -- treat it as a
                // curve end instead.

                IPosition centre = null;            // The centre to actually use

                if (!(prevcen == thiscen && Math.Abs(prevrad - thisrad) < Constants.TINY))
                {
                    double xc1 = prevcen.X;
                    double yc1 = prevcen.Y;
                    double xc2 = thiscen.X;
                    double yc2 = thiscen.Y;
                    double dxc = xc2 - xc1;
                    double dyc = yc2 - yc1;

                    if (Math.Abs(dxc) < 0.01 &&
                        Math.Abs(dyc) < 0.01 &&
                        Math.Abs(prevrad - thisrad) < 0.01)
                    {
                        // Close enough
                        centre = new Position(xc1 + dxc * 0.5, yc1 + dyc * 0.5);
                    }
                    else
                    {
                        isRadial   = false;
                        isCurveEnd = true;
                    }
                }
                else
                {
                    centre = prevcen;
                }

                // If the centre and radius were the same (or close enough),
                // define the radial bearing from the centre of the circle.
                // If the polygon is actually on the other side, reverse the
                // bearing so that it's directed INTO the polygon.

                if (isRadial)
                {
                    Debug.Assert(centre != null);
                    bearing = Geom.BearingInRadians(centre, m_Begin);
                    angle   = 0.0;
                    if (iscw != isPolLeft)
                    {
                        bearing += Constants.PI;
                    }
                }
            }

            // If we're not dealing with a radial curve (or we have curves that
            // don't appear to be radial)
            if (!isRadial)
            {
                // Get the clockwise angle from the last position of the
                // preceding face to the first position after the start
                // of this face. Since info is held in a clockwise cycle
                // around the polygon, this will always give us the exterior
                // angle.
                Turn reference = new Turn(m_Begin, prev.TailReference);
                angle = reference.GetAngleInRadians(this.HeadReference);

                // Define the bearing to use for projecting the point. It's
                // in the middle of the angle, but projected into the polygon.
                bearing = reference.BearingInRadians + angle * 0.5 + Constants.PI;
            }

            // Initialize the link at the start of the face
            List <PolygonLink> links = new List <PolygonLink>();
            PolygonLink        link  = new PolygonLink(beginPoint, isCurveEnd, isRadial, bearing, angle);

            links.Add(link);

            // Initialize links for any extra points
            if (m_ExtraPoints != null)
            {
                // Intermediate points can never be curve ends
                isCurveEnd = false;

                // If the face is a curve, they're radial points
                isRadial = isThisCurve;

                // Note any curve info
                double    radius;
                IPosition centre = null;
                bool      iscw   = false;

                if (isRadial)
                {
                    Debug.Assert(m_Divider.Line.LineGeometry is ICircularArcGeometry);
                    ICircularArcGeometry arc = (m_Divider.Line.LineGeometry as ICircularArcGeometry);
                    centre = arc.Circle.Center;
                    radius = arc.Circle.Radius;
                    iscw   = arc.IsClockwise;
                    angle  = 0.0;
                }

                for (uint i = 0; i < m_ExtraPoints.Length; i++)
                {
                    //IPointGeometry loc = m_ExtraPoints[i].Geometry;
                    PointFeature loc = m_ExtraPoints[i];

                    // Figure out the orientation bearing for the point
                    if (isRadial)
                    {
                        Debug.Assert(centre != null);
                        bearing = Geom.BearingInRadians(centre, loc);
                        if (iscw != isPolLeft)
                        {
                            bearing += Constants.PI;
                        }
                    }
                    else
                    {
                        // Get the exterior clockwise angle

                        IPointGeometry back;
                        IPointGeometry fore;

                        if (i == 0)
                        {
                            back = m_Begin;
                        }
                        else
                        {
                            back = m_ExtraPoints[i - 1].Geometry;
                        }

                        if (i == (m_ExtraPoints.Length - 1))
                        {
                            fore = m_End;
                        }
                        else
                        {
                            fore = m_ExtraPoints[i + 1].Geometry;
                        }


                        Turn reference = new Turn(loc, back);
                        angle = reference.GetAngleInRadians(fore);

                        // Define the bearing to use for projecting the point. It's
                        // in the middle of the angle, but projected into the polygon.
                        bearing = reference.BearingInRadians + angle * 0.5 + Constants.PI;
                    }

                    link = new PolygonLink(m_ExtraPoints[i], isCurveEnd, isRadial, bearing, angle);
                    links.Add(link);
                }
            }

            return(links.ToArray());
        }
コード例 #32
0
 public CircularArcGeometry(ICircularArcGeometry g)
 {
     m_Circle = g.Circle;
     m_BC = g.BC;
     m_EC = g.EC;
     m_IsClockwise = g.IsClockwise;
 }
コード例 #33
0
 internal override uint IntersectArc(IntersectionResult results, ICircularArcGeometry arc)
 {
     return(Make().IntersectArc(results, arc));
 }
コード例 #34
0
 internal override uint IntersectArc(IntersectionResult results, ICircularArcGeometry that)
 {
     return IntersectionHelper.Intersect(results, (ILineSegmentGeometry)this, that);
 }
コード例 #35
0
        internal virtual void ShowResult()
        {
            // If we have two points, get the distance between them,
            // format the result, and display it.
            if (m_Point1!=null && m_Point2!=null && m_CommCir!=null)
            {
                // It's conceivable that the two points share more than
                // one common circle. For now, just pick off the first
                // common circle and use that.
                Circle circle = m_CommCir[0];

                // Get the centre of the circle.
                IPosition c = circle.Center;

                // Get the clockwise angle from point 1 to point 2.
                Turn reft = new Turn(c, m_Point1);
                double angle = reft.GetAngleInRadians(m_Point2);
                bool iscw = true;

                // Make sure the angle is consistent with whether we want
                // the short or the long arc distance.
                bool isshort = (angle < Constants.PI);
                if (isshort != m_WantShort)
                {
                    angle = Constants.PIMUL2 - angle;
                    iscw = false;
                }

                // Get the arc distance and display it.
                double metric = angle * circle.Radius;
                distanceTextBox.Text = Format(metric, m_Point1, m_Point2);

                // Remember the geometry that corresponds to the displayed distance (this
                // will be drawn when the controller periodically calls the Draw method).
                m_CurrentDistanceArc = new CircularArcGeometry(circle, m_Point1, m_Point2, iscw);
            }
            else
            {
                distanceTextBox.Text = "<no distance>";
                m_CurrentDistanceArc = null;
            }
        }
コード例 #36
0
 internal uint IntersectArc(ICircularArcGeometry arc)
 {
     return(m_IntersectedObject.LineGeometry.IntersectArc(this, arc));
 }
コード例 #37
0
        internal InverseArcDistanceForm()
        {
            InitializeComponent();
            color1Button.BackColor = InverseColors[0];
            color2Button.BackColor = InverseColors[1];

            m_Point1 = m_Point2 = null;
            m_Cir1 = m_Cir2 = m_CommCir = null;
            m_WantShort = true;
            m_CurrentDistanceArc = null;
        }
コード例 #38
0
 internal override uint IntersectArc(IntersectionResult results, ICircularArcGeometry arc)
 {
     return Make().IntersectArc(results, arc);
 }
コード例 #39
0
        /// <summary>
        /// Generates an approximation of a circular arc.
        /// </summary>
        /// <param name="tol">The maximum chord-to-circumference distance.</param>
        /// <returns></returns>
        public static IPointGeometry[] GetApproximation(ICircularArcGeometry g, ILength tol)
        {
            // Get info about the circle the curve lies on.
            IPosition center = g.Circle.Center;
            double radius = g.Circle.Radius;

            // Determine the change in bearing which will satisfy the specified tolerance
            // (if no tolerance has been specified, arbitrarily use a tolerance of 1mm on the ground).
            double tolm = (tol.Meters > Double.Epsilon ? tol.Meters : 0.001);
            double dbear = Math.Acos((radius-tolm)/radius);

            IPointGeometry start = g.BC;
            IPointGeometry end = g.EC;
            bool iscw = g.IsClockwise;

            // Get the total angle subtended by the curve.
            Turn reft = new Turn(center, start);
            double totang = reft.GetAngleInRadians(end); // clockwise
            if (!iscw)
                totang = MathConstants.PIMUL2 - totang;

            // Figure out how many positions we'll generate
            int nv = (int)(totang/dbear); // truncate
            Debug.Assert(nv>=0);

            // Handle special case of very short arc.
            if (nv==0)
                return new IPointGeometry[] { start, end };

            // Sign the delta-bearing the right way.
            if (!iscw)
                dbear = -dbear;

            // Get the initial bearing to the first position along the curve.
            double curbear = reft.BearingInRadians + dbear;

            // Append positions along the length of the curve.
            List<IPointGeometry> result = new List<IPointGeometry>(nv);
            result.Add(start);

            for (int i=0; i<nv; i++, curbear+=dbear)
            {
                IPosition p = BasicGeom.Polar(center, curbear, radius);
                result.Add(PositionGeometry.Create(p));
            }

            result.Add(end);
            return result.ToArray();
        }
コード例 #40
0
        internal static uint Intersect(IntersectionResult results, IMultiSegmentGeometry line, ICircularArcGeometry arc)
        {
            uint nx=0;

            IPointGeometry[] segs = line.Data;
            IPointGeometry f = arc.First;
            IPointGeometry s = arc.Second;
            ICircleGeometry circle = arc.Circle;

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

            return nx;
        }
コード例 #41
0
 public static ILength GetDistance(ICircularArcGeometry g, IPosition p)
 {
     return new Length(Math.Sqrt(MinDistanceSquared(g, p)));
 }
コード例 #42
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);
 }
コード例 #43
0
        public static IWindow GetExtent(ICircularArcGeometry g)
        {
            // If the curve is a complete circle, just define it the easy way.
            if (g.BC.IsCoincident(g.EC))
                return CircleGeometry.GetExtent(g.Circle);

            IPosition bcp = g.BC;
            IPosition ecp = g.EC;
            IPosition centre = g.Circle.Center;

            // Initialize the window with the start location.
            Window win = new Window(bcp);

            // Expand using the end location
            win.Union(ecp);

            // If the curve is completely within one quadrant, we're done.
            QuadVertex bc = new QuadVertex(centre, bcp);
            QuadVertex ec = new QuadVertex(centre, ecp);

            Quadrant qbc = bc.Quadrant;
            Quadrant qec = ec.Quadrant;

            if (qbc == qec)
            {
                if (g.IsClockwise)
                {
                    if (bc.GetTanAngle() < ec.GetTanAngle())
                        return win;
                }
                else
                {
                    if (ec.GetTanAngle() < bc.GetTanAngle())
                        return win;
                }
            }

            // Get the window of the circle
            IWindow circle = CircleGeometry.GetExtent(g.Circle);

            // If the curve is anticlockwise, switch the quadrants for BC & EC
            if (!g.IsClockwise)
            {
                Quadrant temp = qbc;
                qbc = qec;
                qec = temp;
            }

            // Expand the window, depending on which quadrants the start &
            // end points fall in. The lack of breaks in the inner switches
            // is intentional (e.g. if start & end both fall in Quadrant.NorthEast,
            // the window we want is the complete circle, having checked above
            // for the case where the arc is JUST in Quadrant.NorthEast).

            // Define do-nothing values for the Union's below
            double wx = win.Min.X;
            double wy = win.Min.Y;

            if (qbc==Quadrant.NE)
            {
                switch (qec)
                {
                    case Quadrant.NE:
                        win.Union(wx, circle.Max.Y);
                        goto case Quadrant.NW;
                    case Quadrant.NW:
                        win.Union(circle.Min.X, wy);
                        goto case Quadrant.SW;
                    case Quadrant.SW:
                        win.Union(wx, circle.Min.Y);
                        goto case Quadrant.SE;
                    case Quadrant.SE:
                        win.Union(circle.Max.X, wy);
                        break;
                }
            }
            else if (qbc==Quadrant.SE)
            {
                switch (qec)
                {
                    case Quadrant.SE:
                        win.Union(circle.Max.X, wy);
                        goto case Quadrant.NE;
                    case Quadrant.NE:
                        win.Union(wx, circle.Max.Y);
                        goto case Quadrant.NW;
                    case Quadrant.NW:
                        win.Union(circle.Min.X, wy);
                        goto case Quadrant.SW;
                    case Quadrant.SW:
                        win.Union(wx, circle.Min.Y);
                        break;
                }
            }
            else if (qbc==Quadrant.SW)
            {
                switch (qec)
                {
                    case Quadrant.SW:
                        win.Union(wx, circle.Min.Y);
                        goto case Quadrant.SE;
                    case Quadrant.SE:
                        win.Union(circle.Max.X, wy);
                        goto case Quadrant.NE;
                    case Quadrant.NE:
                        win.Union(wx, circle.Max.Y);
                        goto case Quadrant.NW;
                    case Quadrant.NW:
                        win.Union(circle.Min.X, wy);
                        break;
                }
            }
            else if (qbc==Quadrant.NW)
            {
                switch (qec)
                {
                    case Quadrant.NW:
                        win.Union(circle.Min.X, wy);
                        goto case Quadrant.SW;
                    case Quadrant.SW:
                        win.Union(wx, circle.Min.Y);
                        goto case Quadrant.SE;
                    case Quadrant.SE:
                        win.Union(circle.Max.X, wy);
                        goto case Quadrant.NE;
                    case Quadrant.NE:
                        win.Union(wx, circle.Max.Y);
                        break;
                }
            }

            return win;
        }
コード例 #44
0
        /// <summary>
        /// Intersects a pair of clockwise arcs, where one of the ends exactly coincides with the
        /// other arc. The two arcs are assumed to sit on different circles.
        /// </summary>
        /// <param name="xsect">The intersection results.</param>
        /// <param name="bc">The start of the other arc.</param>
        /// <param name="ec">The end of the other arc.</param>
        /// <param name="circle">The circle that the other arc sits on.</param>
        /// <param name="xend">The end of THIS arc that coincides with one end of the other one.</param>
        /// <param name="othend">The other end of THIS arc (may or may not coincide with one end of
        /// the other arc).</param>
        /// <param name="xCircle">The circle for THIS arc</param>
        /// <returns>The number of intersections (1 or 2).</returns>
        static uint EndIntersect( IntersectionResult xsect
            , ICircularArcGeometry ab
            , ICircularArcGeometry pq
            , bool isFirstEndCoincident)
        {
            IPointGeometry bc = pq.First;
            IPointGeometry ec = pq.Second;
            ICircleGeometry circle = pq.Circle;
            IPointGeometry xend = (isFirstEndCoincident ? ab.First : ab.Second);
            IPointGeometry othend = (isFirstEndCoincident ? ab.Second : ab.First);
            ICircleGeometry xCircle = ab.Circle;

            // The two curves sit on different circles, so do a precise intersection of the circles.
            IPointGeometry c1 = xCircle.Center;
            IPointGeometry c2 = circle.Center;
            double r1 = xCircle.Radius;
            double r2 = circle.Radius;
            IPosition x1, x2;
            uint nx = Geom.IntersectCircles(c1, r1, c2, r2, out x1, out x2);

            // If we didn't get ANY intersections, that's a bit unusual
            // seeing how one of the ends matches. However, it's possible
            // due to roundoff of the end locations. So in that case, just
            // return a single intersection at the matching end.
            if (nx==0)
            {
                xsect.Append(xend);
                return 1;
            }

            // @devnote If we got 1 intersection (i.e. the 2 circles just
            // touch), you might be tempted to think that it must be close
            // to the matching end location. That is NOT the case if the
            // circles are big.

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

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

            // Does it fall in the sector defined by the clockwise curve?

            IPointGeometry centre = c2;
            Turn reft = new Turn(centre, bc);
            double eangle = reft.GetAngleInRadians(ec);
            double xangle = reft.GetAngleInRadians(x1);
            if (xangle > eangle)
            {
                xsect.Append(xend);
                return 1;
            }

            // Does it fall in the sector defined by this curve (NO tolerance allowed).
            PointGeometry xloc = PointGeometry.Create(x1);
            bool isxthis = Geom.IsInSector(xloc, c1, ab.First, ab.Second, 0.0);
            if (!isxthis)
            {
                xsect.Append(xend);
                return 1;
            }

            // Get the midpoint of the segment that connects the intersection to the matching end.
            IPosition midx = Position.CreateMidpoint(xend, 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). Also,
            // the old way used 'centre' which may refer to r1 OR r2, so
            // you would have got the correct result only half of the time!
            // if ( fabs(midx.Distance(centre) - r1) > XYTOL ) {

            double rdiff = Geom.Distance(midx, c1) - r1;
            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 curves, 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(xend, 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.
            xsect.Append(xend, x1);
            return 1;
        }
コード例 #45
0
 internal abstract uint IntersectArc(IntersectionResult results, ICircularArcGeometry arc);