示例#1
0
        /// <summary>
        /// Obtains the geometry for spans along an alternate face attached to this leg.
        /// </summary>
        /// <param name="legStart">The position for the start of the leg.
        /// <param name="legEnd">The position for the end of the leg.</param>
        /// <param name="spans">Information for the spans coinciding with this leg.</param>
        /// <returns>The sections along this leg</returns>
        internal override ILineGeometry[] GetSpanSections(IPosition legStart, IPosition legEnd, SpanInfo[] spans)
        {
            var result = new ILineGeometry[spans.Length];

            Debug.Assert(AlternateFace != null);

            // Define the arc that corresponds to the complete leg (the circle should have been
            // already defined when we processed the primary face_.
            Debug.Assert(Circle != null);
            var arc = new CircularArcGeometry(Circle, legStart, legEnd, m_Metrics.IsClockwise);

            // Handle case where the leg is a cul-de-sac with no observed spans on the alternate face
            if (spans.Length == 1 && spans[0].ObservedDistance == null)
            {
                result[0] = arc;
                return(result);
            }

            // Get the required arc length (in meters on the ground)
            double len = arc.Length.Meters;

            // Get the observed arc length (in meters on the ground)
            double obs = AlternateFace.GetTotal();

            // Get the adjustment factor for stretching-compressing the observed distances.
            double factor = len / obs;

            // Define start of first arc.
            IPosition sPos = legStart;
            IPosition ePos = null;

            // Haven't got anywhere yet.
            double totobs = 0.0;

            // Figure out the location of each span
            for (int i = 0; i < result.Length; i++, sPos = ePos)
            {
                if (i == result.Length - 1)
                {
                    ePos = legEnd;
                }
                else
                {
                    // Add on the unscaled distance
                    totobs += spans[i].ObservedDistance.Meters;

                    // Scale to the required length for the overall leg
                    double elen = totobs * factor;

                    // Define the end position.
                    arc.GetPosition(new Length(elen), out ePos);
                }

                result[i] = new CircularArcGeometry(Circle, sPos, ePos, m_Metrics.IsClockwise);
            }

            return(result);
        }
示例#2
0
        internal override void Render(ISpatialDisplay display, IDrawStyle style)
        {
            // At scales larger than 1:1000, it may be advisable to draw an approximation (since
            // the drawing methods tend to reveal small non-existent glitches at larger scales)...

            // Draw an approximation of the curve (such that the chord-to-circumference
            // distance does not exceed 0.2mm at draw scale).

            /*
             * ILength tol = new Length(display.MapScale * 0.0002);
             * IPointGeometry[] pts = CircularArcGeometry.GetApproximation(this, tol);
             * new LineStringGeometry(pts).Render(display, style);
             */
            CircularArcGeometry.Render(this, display, style);
        }
示例#3
0
        internal void Draw() // was Paint
        {
            // Nothing to do if parallel points undefined.
            if (m_South == null || m_North == null)
            {
                return;
            }

            Debug.Assert(m_Line != null);
            ISpatialDisplay draw        = m_Cmd.ActiveDisplay;
            IDrawStyle      solidStyle  = EditingController.Current.Style(Color.Magenta);
            IDrawStyle      dottedStyle = new DottedStyle();

            ArcFeature arc = m_Line.GetArcBase();

            if (arc != null)
            {
                // The parallel portion is solid, while the remaining portion of the circle is dotted.
                CircularArcGeometry cg = new CircularArcGeometry(arc.Circle.Center, m_South, m_North, arc.IsClockwise);
                solidStyle.Render(draw, cg);
                cg.IsClockwise = !cg.IsClockwise;
                dottedStyle.Render(draw, cg);
            }
            else
            {
                // What's the bearing from the start to the end of the parallel?
                double bearing = Geom.BearingInRadians(m_South, m_North);

                // What's the max length of a diagonal crossing the entire screen?
                double maxdiag = m_Cmd.MaxDiagonal;

                // Project to a point below the southern end of the parallel, as
                // well as a point above the northern end.
                IPosition below = Geom.Polar(m_South, bearing + Constants.PI, maxdiag);
                IPosition above = Geom.Polar(m_North, bearing, maxdiag);

                LineSegmentGeometry.Render(below, m_South, draw, dottedStyle);
                LineSegmentGeometry.Render(m_South, m_North, draw, solidStyle);
                LineSegmentGeometry.Render(m_North, above, draw, dottedStyle);

                // If we have an offset point, draw it in green.
                if (m_Point != null)
                {
                    m_Point.Draw(draw, Color.Green);
                }
            }
        }
示例#4
0
        public void Render(ISpatialDisplay display, IDrawStyle style)
        {
            if (this.category == CadastralLineCategory.Radial)
            {
                style = new DottedStyle(style.LineColor);
            }

            if (m_Center == null)
            {
                style.Render(display, this.PositionArray);
            }
            else
            {
                // radius less than zero may represent a counter-clockwise direction
                bool isClockwise = (this.radius > 0.0);

                // Define a circular arc that is assumed to run clockwise.
                ICircleGeometry      circle = new CircleGeometry(m_Center.Geometry, Math.Abs(this.radius));
                ICircularArcGeometry arc    = new CircularArcGeometry(circle, m_From.Geometry, m_To.Geometry, isClockwise);

                // Assume clockwise, see what it looks like
                style.Render(display, arc);
            }

            /*
             * else
             * {
             * if (!this.arcLengthSpecified)
             *  throw new ApplicationException("Cannot determine arc direction");
             *
             * // Define a circular arc that is assumed to run clockwise.
             * CircleGeometry circle = new CircleGeometry(m_Center.Geometry, this.radius);
             * CircularArcGeometry arc = new CircularArcGeometry(circle, m_From.Geometry, m_To.Geometry, true);
             *
             * // Assume clockwise, see what it looks like
             * new DrawStyle(Color.Red).Render(display, arc);
             *
             * //double arcLength = arc.Length.Meters;
             * //double othLength = circle.Length.Meters;
             *
             * //// Get the arc length in meters (TODO: need to access file header to determine how to convert lengths)
             * //if (Math.Abs(othLength - this.arcLength) < Math.Abs(arcLength - this.arcLength))
             * //    arc.IsClockwise = false;
             * }
             */
        }
示例#5
0
        /// <summary>
        /// Gets the point on this line that is closest to a specified position.
        /// </summary>
        /// <param name="p">The position to search from.</param>
        /// <param name="tol">Maximum distance from line to the search position</param>
        /// <returns>The closest position (null if the line is further away than the specified
        /// max distance)</returns>
        internal override IPosition GetClosest(IPointGeometry p, ILength tol)
        {
            // Get the distance from the centre of the circle to the search point.
            IPointGeometry center = m_Circle.Center;
            double         dist   = Geom.Distance(center, p);

            // Return if the search point is beyond tolerance.
            double radius = m_Circle.Radius;
            double diff   = Math.Abs(dist - radius);

            if (diff > tol.Meters)
            {
                return(null);
            }

            // If the vertex lies in the curve sector, the closest position
            // is along the bearing from the centre through the search
            // position. Otherwise the closest position is the end of
            // the curve that's closest (given that it's within tolerance).

            if (CircularArcGeometry.IsInSector(this, p, 0.0))
            {
                double bearing = Geom.BearingInRadians(center, p);
                return(Geom.Polar(center, bearing, radius));
            }

            double d1 = Geom.DistanceSquared(p, BC);
            double d2 = Geom.DistanceSquared(p, EC);

            double t = tol.Meters;

            if (Math.Min(d1, d2) < (t * t))
            {
                if (d1 < d2)
                {
                    return(BC);
                }
                else
                {
                    return(EC);
                }
            }

            return(null);
        }
示例#6
0
        /// <summary>
        /// Obtains the geometry for spans along this leg.
        /// </summary>
        /// <param name="bc">The position for the start of the leg.
        /// <param name="bcBearing">The bearing on entry into the leg.</param>
        /// <param name="sfac">Scale factor to apply to distances.</param>
        /// <param name="spans">Information for the spans coinciding with this leg.</param>
        /// <returns>The sections along this leg</returns>
        internal override ILineGeometry[] GetSpanSections(IPosition bc, double bcBearing, double sfac, SpanInfo[] spans)
        {
            // Can't do anything if the leg radius isn't defined
            if (m_Metrics.ObservedRadius == null)
            {
                throw new InvalidOperationException("Cannot create sections for circular leg with undefined radius");
            }

            var result = new ILineGeometry[spans.Length];

            // Use supplied stuff to derive info on the center and EC.
            IPosition center;
            IPosition ec;
            double    bearingToBC;
            double    ecBearing;

            GetPositions(bc, bcBearing, sfac, out center, out bearingToBC, out ec, out ecBearing);

            // Define the underlying circle
            ICircleGeometry circle = new CircleGeometry(PointGeometry.Create(center), BasicGeom.Distance(center, bc));

            // Handle case where the leg is a cul-de-sac with no observed spans
            if (spans.Length == 1 && spans[0].ObservedDistance == null)
            {
                result[0] = new CircularArcGeometry(circle, bc, ec, m_Metrics.IsClockwise);
                return(result);
            }

            /// Initialize scaling factor for distances in cul-de-sacs (ratio of the length calculated from
            /// the CA & Radius, versus the observed distances that were actually specified). For curves that
            /// are not cul-de-sacs, this will be 1.0
            double culFactor = 1.0;

            if (m_Metrics.IsCulDeSac)
            {
                double obsv = PrimaryFace.GetTotal();
                if (obsv > MathConstants.TINY)
                {
                    culFactor = Length.Meters / obsv;
                }
            }

            IPosition sPos        = bc;
            IPosition ePos        = null;
            bool      isClockwise = m_Metrics.IsClockwise;
            double    radius      = RadiusInMeters;
            double    edist       = 0.0;

            for (int i = 0; i < result.Length; i++, sPos = ePos)
            {
                // Add on the unscaled distance
                edist += spans[i].ObservedDistance.Meters;

                // Get the angle subtended at the center of the circle. We use
                // unscaled values here, since the scale factors would cancel out.
                // However, we DO apply any cul-de-sac scaling factor, to account
                // for the fact that the distance may be inconsistent with the
                // curve length derived from the CA and radius. For example, it
                // is possible that the calculated curve length=200, although the
                // total of the observed spans is somehow only 100. In that case,
                // if the supplied distance is 50, we actually want to use a
                // value of 50 * (200/100) = 100.

                double angle = (edist * culFactor) / radius;

                // Get the bearing of the point with respect to the center of the circle.

                double bearing;

                if (isClockwise)
                {
                    bearing = bearingToBC + angle;
                }
                else
                {
                    bearing = bearingToBC - angle;
                }

                // Calculate the position using the scaled radius.
                ePos = Geom.Polar(center, bearing, radius * sfac);

                result[i] = new CircularArcGeometry(circle, sPos, ePos, isClockwise);
            }

            return(result);
        }
示例#7
0
        /// <summary>
        /// Draws the current state of the edit
        /// </summary>
        internal void Draw()
        {
            Debug.Assert(m_Line != null);
            ISpatialDisplay view = ActiveDisplay;

            // Figure out the positions for the ends of the parallel line (if any) ...

            // Assume we already know both terminals.
            IPosition start = m_Term1;
            IPosition end   = m_Term2;

            // If either one is undefined, but a dialog for it is active,
            // try to get the terminal from there instead.
            if (m_TermDial1 != null && start == null)
            {
                start = m_TermDial1.TerminalPosition;
            }

            if (m_TermDial2 != null && end == null)
            {
                end = m_TermDial2.TerminalPosition;
            }

            // If they weren't actually defined, use the parallel points instead.
            if (start == null)
            {
                start = m_Par1;
            }

            if (end == null)
            {
                end = m_Par2;
            }

            // If those weren't defined either, try to calculate them now.
            if (end == null && Calculate())
            {
                start = m_Par1;
                end   = m_Par2;
            }

            // Any offset point
            if (m_OffsetPoint != null)
            {
                m_OffsetPoint.Draw(view, Color.Green);
            }

            // Everything else should draw in usual command-style colour.
            IDrawStyle style       = EditingController.Current.Style(Color.Magenta);
            IDrawStyle dottedStyle = new DottedStyle();

            // If the reference line is a curve, get the curve info.
            ArcFeature arc = m_Line.GetArcBase();

            if (arc != null)
            {
                bool iscw = arc.IsClockwise;

                // Reverse the direction if necessary.
                if (m_IsReversed)
                {
                    iscw = !iscw;
                }

                // Draw the parallel line (the rest of the circle being dotted).
                if (start != null)
                {
                    CircularArcGeometry parArc = new CircularArcGeometry(arc.Circle, start, end, iscw);
                    style.Render(view, parArc);

                    parArc.IsClockwise = !parArc.IsClockwise;
                    dottedStyle.Render(view, parArc);
                }
            }
            else
            {
                // PARALLEL IS STRAIGHT

                // If we've got something, figure out positions for dotted portion.
                if (start != null)
                {
                    // What's the max length of a diagonal crossing the entire screen?
                    double maxdiag = this.MaxDiagonal;

                    // What's the bearing from the start to the end of the parallel?
                    double bearing = Geom.BearingInRadians(start, end);

                    // Project to a point before the start end of the parallel, as
                    // well as a point after the end.
                    IPosition before = Geom.Polar(start, bearing + Constants.PI, maxdiag);
                    IPosition after  = Geom.Polar(end, bearing, maxdiag);

                    LineSegmentGeometry.Render(before, start, view, dottedStyle);
                    LineSegmentGeometry.Render(start, end, view, style);
                    LineSegmentGeometry.Render(end, after, view, dottedStyle);
                }
            }

            // Draw terminal positions (if defined).

            if (m_Term1 != null)
            {
                style.Render(view, m_Term1);
            }

            if (m_Term2 != null)
            {
                style.Render(view, m_Term2);
            }

            // The terminal lines.

            if (m_TermLine1 != null)
            {
                m_TermLine1.Render(view, style);
            }

            if (m_TermLine2 != null)
            {
                m_TermLine2.Render(view, style);
            }

            // Do the active dialog last so their stuff draws on top.
            if (m_ParDial != null)
            {
                m_ParDial.Draw();
            }

            if (m_TermDial1 != null)
            {
                m_TermDial1.Draw();
            }

            if (m_TermDial2 != null)
            {
                m_TermDial2.Draw();
            }
        }
示例#8
0
 /// <summary>
 /// Loads a list of positions with data for this line.
 /// </summary>
 /// <param name="positions">The list to append to</param>
 /// <param name="reverse">Should the data be appended in reverse order?</param>
 /// <param name="wantFirst">Should the first position be appended? (last if <paramref name="reverse"/> is true)</param>
 /// <param name="arcTol">Tolerance for approximating circular arcs (the maximum chord-to-circumference distance).</param>
 internal override void AppendPositions(List <IPosition> positions, bool reverse, bool wantFirst, ILength arcTol)
 {
     IPointGeometry[] approx = CircularArcGeometry.GetApproximation(this, arcTol);
     MultiSegmentGeometry.AppendPositions(approx, positions, reverse, wantFirst);
 }
示例#9
0
        /// <summary>
        /// Cuts back a horizontal line segment to the closest intersection with this line.
        /// Used in point in polygon.
        /// </summary>
        /// <param name="s">Start of horizontal segment.</param>
        /// <param name="e">End of segment (will be modified if segment intersects this line)</param>
        /// <param name="status">Return code indicating whether an error has arisen (returned
        /// as 0 if no error).</param>
        /// <returns>True if the horizontal line was cut back.</returns>
        internal override bool GetCloser(IPointGeometry s, ref PointGeometry e, out uint status)
        {
            status = 0;

            // Get the window of the circle that this curve lies on.
            IWindow cwin = m_Circle.Extent;

            // Get a window for the horizontal segment.
            IWindow segwin = new Window(s, e);

            // Return if the windows don't overlap.
            if (!cwin.IsOverlap(segwin))
            {
                return(false);
            }

            // Return if the the segment is to the west of the circle's window.
            if (segwin.Max.X < cwin.Min.X)
            {
                return(false);
            }

            // Represent the horizontal segment in a class of its own
            HorizontalRay hseg = new HorizontalRay(s, e.X - s.X);

            if (!hseg.IsValid)
            {
                status = 1;
                return(false);
            }

            // Locate up to two intersections of the horizontal segment with the circle.
            IPosition x1 = null;
            IPosition x2 = null;
            uint      nx = hseg.Intersect(m_Circle, ref x1, ref x2);

            // Return if no intersections
            if (nx == 0)
            {
                return(false);
            }

            // Return if this arc curve is a complete circle.
            if (this.IsCircle)
            {
                return(false);
            }

            // Check whether the first intersection lies on this arc. If
            // so, update the end of segment, and return.
            if (CircularArcGeometry.IsInSector(this, x1, 0.0))
            {
                e = new PointGeometry(x1);
                return(true);
            }

            // If we got two intersections with the circle, check the
            // second intersection as well.
            if (nx == 2 && CircularArcGeometry.IsInSector(this, x2, 0.0))
            {
                e = new PointGeometry(x2);
                return(true);
            }

            return(false);
        }
示例#10
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)
 internal override ILength GetLength(IPosition asFarAs)
 {
     return(CircularArcGeometry.GetLength(this, asFarAs));
 }
示例#11
0
 /// <summary>
 /// Gets the position that is a specific distance from the start of this line.
 /// </summary>
 /// <param name="distance">The distance from the start of the line.</param>
 /// <param name="result">The position found</param>
 /// <returns>True if the distance is somewhere ON the line. False if the distance
 /// was less than zero, or more than the line length (in that case, the position
 /// found corresponds to the corresponding terminal point).</returns>
 internal override bool GetPosition(ILength distance, out IPosition result)
 {
     return(CircularArcGeometry.GetPosition(this, distance, out result));
 }
示例#12
0
 public override ILength Distance(IPosition point)
 {
     return(CircularArcGeometry.GetDistance(this, point));
 }
示例#13
0
        internal void Draw()
        {
            ISpatialDisplay display = m_Cmd.ActiveDisplay;

            // Draw the line we're extending in a special colour (any highlighting it
            // originally had should have been removed during LineExtensionControl_Load)
            if (m_ExtendLine != null)
            {
                m_ExtendLine.Draw(display, Color.DarkBlue);
            }

            // If we're doing an update, draw the original extension in grey.
            LineExtensionOperation pop = UpdateOp;

            if (pop != null)
            {
                LineFeature origLine = pop.NewLine;
                if (origLine != null)
                {
                    origLine.Draw(display, Color.Gray);
                }

                PointFeature origPoint = pop.NewPoint;
                if (origPoint != null)
                {
                    origPoint.Draw(display, Color.Gray);
                }
            }

            // Calculate the start and end points of the extension, initially
            // assuming that it's a straight line extension.
            IPosition start, end;

            if (LineExtensionUI.Calculate(m_ExtendLine, m_IsExtendFromEnd, m_Length, out start, out end))
            {
                // Draw the straight extension line
                IDrawStyle          style = (m_WantLine ? new DrawStyle(Color.Magenta) : new DottedStyle(Color.Magenta));
                LineSegmentGeometry seg   = new LineSegmentGeometry(start, end);
                seg.Render(display, style);
            }
            else
            {
                // Perhaps it's a circular arc ...

                IPosition center;
                bool      iscw;

                if (LineExtensionUI.Calculate(m_ExtendLine, m_IsExtendFromEnd, m_Length,
                                              out start, out end, out center, out iscw))
                {
                    // And draw the curve.
                    IDrawStyle          style = (m_WantLine ? new DrawStyle(Color.Magenta) : new DottedStyle(Color.Magenta));
                    IPointGeometry      c     = PointGeometry.Create(center);
                    CircularArcGeometry arc   = new CircularArcGeometry(c, start, end, iscw);
                    arc.Render(display, style);
                }
                else if (m_ExtendLine != null)
                {
                    // Get the position we're extending from.
                    end = (m_IsExtendFromEnd ? m_ExtendLine.EndPoint : m_ExtendLine.StartPoint);
                }
            }

            // If we actually got something, draw the end point.
            if (end != null)
            {
                IDrawStyle style = m_Cmd.Controller.DrawStyle;
                style.FillColor = Color.Magenta;
                style.Render(display, end);
            }
        }