Beispiel #1
0
        /// <summary>
        /// Draws the path on the specified display
        /// </summary>
        /// <param name="display">The display to draw to</param>
        internal void Render(ISpatialDisplay display)
        {
            EnsureAdjusted();

            // Do nothing if the scale factor is undefined.
            if (Math.Abs(m_ScaleFactor) < MathConstants.TINY)
            {
                return;
            }

            // Initialize position to the start of the path.
            IPosition gotend = new Position(m_From);

            // Initial bearing is whatever the rotation is.
            double bearing = m_Rotation;

            for (int i = 0; i < m_Legs.Length; i++)
            {
                Leg leg = m_Legs[i];

                // Include any angle specified at the start of the leg
                StraightLeg sLeg = (leg as StraightLeg);
                if (sLeg != null)
                {
                    bearing = sLeg.AddStartAngle(bearing);
                }

                // Determine exit bearing for circular leg (do it now, in case an extra leg complicates matters below)
                double      exitBearing = bearing;
                CircularLeg cLeg        = (leg as CircularLeg);
                if (cLeg != null)
                {
                    exitBearing = cLeg.GetExitBearing(gotend, bearing, m_ScaleFactor);
                }

                // Obtain geometry for each span and draw
                SpanInfo[]      spans    = leg.PrimaryFace.Spans;
                ILineGeometry[] sections = leg.GetSpanSections(gotend, bearing, m_ScaleFactor, spans);
                DrawSpans(display, spans, sections);

                // If we're dealing with the first face of a staggered leg, process the second face
                if (leg.AlternateFace != null)
                {
                    spans    = leg.AlternateFace.Spans;
                    sections = leg.GetSpanSections(gotend, bearing, m_ScaleFactor, spans);
                    DrawSpans(display, spans, sections);
                }

                // Get to the end of the leg
                gotend  = sections[sections.Length - 1].End;
                bearing = exitBearing;
            }

            // Re-draw the terminal points to ensure that their color is on top.
            DrawEnds(display);
        }
Beispiel #2
0
        /// <summary>
        /// Creates spatial features (points and lines) for this leg. The created
        /// features don't have any geometry.
        /// </summary>
        /// <param name="ff">The factory for creating new spatial features</param>
        /// <param name="startPoint">The point (if any) at the start of this leg. May be
        /// null in a situation where the preceding leg ended with an "omit point" directive.</param>
        /// <param name="lastPoint">The point that should be used for the very end
        /// of the leg (specify null if a point should be created at the end of the leg).</param>
        internal void CreateFeatures(FeatureFactory ff, PointFeature startPoint, PointFeature lastPoint)
        {
            // If we're dealing with a circular arc, create the underlying circle (and a
            // center point). The radius of the circle is undefined at this stage, but the
            // circle must be present so that created arcs can be cross-referenced to it.

            // Note that it is conceivable that the center point will end up coinciding with
            // another point in the map (it could even coincide with another circular leg in
            // the same connection path).

            CircularLeg cLeg = (this as CircularLeg);

            if (cLeg != null)
            {
                cLeg.CreateCircle(ff, this.ItemSequence.ToString());
            }

            m_FirstSide.CreateFeatures(ff, startPoint, lastPoint);

            // Should the end of an alternate face share the end point of the primary face??
            if (m_OtherSide != null)
            {
                // If the leg is right at the end of a connection path, the alternate face needs to
                // end at the specified point. Otherwise use the point that was created at the end
                // of the primary face (in unusual cases, it's possible that no point was created
                // there - in that case, the alternate face will create the end point).

                PointFeature endLegPoint = lastPoint;
                if (endLegPoint == null)
                {
                    endLegPoint = m_FirstSide.GetEndPoint(ff.Creator);
                }

                m_OtherSide.CreateFeatures(ff, startPoint, endLegPoint);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Creates a circular leg.
        /// </summary>
        /// <param name="items">Array of path items.</param>
        /// <param name="si">Index to the item where the leg data starts.</param>
        /// <param name="nexti">Index of the item where the next leg starts.</param>
        /// <returns>The new leg.</returns>
        static CircularLeg CreateCircularLeg(PathItem[] items, int si, out int nexti)
        {
            // Confirm that the first item refers to the BC.
            if (items[si].ItemType != PathItemType.BC)
                throw new Exception("PathParser.CreateCircularLeg - Not starting at BC");

            // The BC has to be followed by at least 3 items: angle, radius
            // and EC (add an extra 1 to account for 0-based indexing).
            if (items.Length < si + 4)
                throw new Exception("PathParser.CreateCircularLeg - Insufficient curve data");

            double bangle = 0.0;		// Angle at BC
            double cangle = 0.0;		// Central angle
            double eangle = 0.0;		// Angle at EC
            bool twoangles = false;	    // True if bangle & eangle are both defined.
            bool clockwise = true;		// True if curve is clockwise
            int irad = 0;				// Index of the radius item
            bool cul = false;			// True if cul-de-sac case

            // Point to item following the BC.
            nexti = si + 1;
            PathItemType type = items[nexti].ItemType;

            // If the angle following the BC is a central angle
            if (type == PathItemType.CentralAngle)
            {
                // We have a cul-de-sac
                cul = true;

                // Get the central angle.
                cangle = items[nexti].Value;
                nexti++;
            }
            else if (type == PathItemType.BcAngle)
            {
                // Get the entry angle.
                bangle = items[nexti].Value;
                nexti++;

                // Does an exit angle follow?
                if (items[nexti].ItemType == PathItemType.EcAngle)
                {
                    eangle = items[nexti].Value;
                    twoangles = true;
                    nexti++;
                }
            }
            else
            {
                // The field after the BC HAS to be an angle.
                throw new ApplicationException("Angle does not follow BC");
            }

            // Must be followed by radius.
            if (items[nexti].ItemType != PathItemType.Radius)
                throw new ApplicationException("Radius does not follow angle");

            // Get the radius
            Distance radius = items[nexti].GetDistance();
            irad = nexti;
            nexti++;

            // The item after the radius indicates whether the curve is counterclockwise.
            if (items[nexti].ItemType == PathItemType.CounterClockwise)
            {
                nexti++;
                clockwise = false;
            }

            // Get the leg ID.
            int legnum = items[si].LegNumber;

            // How many distances have we got?
            int ndist = 0;
            for (; nexti < items.Length && items[nexti].LegNumber == legnum; nexti++)
            {
                if (items[nexti].IsDistance)
                    ndist++;
            }

            // Create the leg.
            CircularLeg leg = new CircularLeg(radius, clockwise, ndist);
            CircularLegMetrics metrics = leg.Metrics;

            // Set the entry angle or the central angle, depending on what we have.
            if (cul)
                metrics.SetCentralAngle(cangle);
            else
                metrics.SetEntryAngle(bangle);

            // Assign second angle if we have one.
            if (twoangles)
                metrics.SetExitAngle(eangle);

            // Assign each distance, starting one after the radius.
            ndist = 0;
            for (int i = irad + 1; i < nexti; i++)
            {
                Distance dist = items[i].GetDistance();
                if (dist != null)
                {
                    // See if there is a qualifier after the distance
                    LegItemFlag qual = LegItemFlag.Null;
                    if (i + 1 < nexti)
                    {
                        PathItemType nexttype = items[i + 1].ItemType;
                        if (nexttype == PathItemType.MissConnect)
                            qual = LegItemFlag.MissConnect;
                        if (nexttype == PathItemType.OmitPoint)
                            qual = LegItemFlag.OmitPoint;
                    }

                    leg.PrimaryFace.SetDistance(dist, ndist, qual);
                    ndist++;
                }
            }

            // Return the new leg.
            return leg;
        }
Beispiel #4
0
        /// <summary>
        /// Creates a circular leg.
        /// </summary>
        /// <param name="items">Array of path items.</param>
        /// <param name="si">Index to the item where the leg data starts.</param>
        /// <param name="nexti">Index of the item where the next leg starts.</param>
        /// <returns>The new leg.</returns>
        static CircularLeg CreateCircularLeg(PathItem[] items, int si, out int nexti)
        {
            // Confirm that the first item refers to the BC.
            if (items[si].ItemType != PathItemType.BC)
            {
                throw new Exception("PathParser.CreateCircularLeg - Not starting at BC");
            }

            // The BC has to be followed by at least 3 items: angle, radius
            // and EC (add an extra 1 to account for 0-based indexing).
            if (items.Length < si + 4)
            {
                throw new Exception("PathParser.CreateCircularLeg - Insufficient curve data");
            }

            double bangle    = 0.0;         // Angle at BC
            double cangle    = 0.0;         // Central angle
            double eangle    = 0.0;         // Angle at EC
            bool   twoangles = false;       // True if bangle & eangle are both defined.
            bool   clockwise = true;        // True if curve is clockwise
            int    irad      = 0;           // Index of the radius item
            bool   cul       = false;       // True if cul-de-sac case

            // Point to item following the BC.
            nexti = si + 1;
            PathItemType type = items[nexti].ItemType;

            // If the angle following the BC is a central angle
            if (type == PathItemType.CentralAngle)
            {
                // We have a cul-de-sac
                cul = true;

                // Get the central angle.
                cangle = items[nexti].Value;
                nexti++;
            }
            else if (type == PathItemType.BcAngle)
            {
                // Get the entry angle.
                bangle = items[nexti].Value;
                nexti++;

                // Does an exit angle follow?
                if (items[nexti].ItemType == PathItemType.EcAngle)
                {
                    eangle    = items[nexti].Value;
                    twoangles = true;
                    nexti++;
                }
            }
            else
            {
                // The field after the BC HAS to be an angle.
                throw new ApplicationException("Angle does not follow BC");
            }

            // Must be followed by radius.
            if (items[nexti].ItemType != PathItemType.Radius)
            {
                throw new ApplicationException("Radius does not follow angle");
            }

            // Get the radius
            Distance radius = items[nexti].GetDistance();

            irad = nexti;
            nexti++;

            // The item after the radius indicates whether the curve is counterclockwise.
            if (items[nexti].ItemType == PathItemType.CounterClockwise)
            {
                nexti++;
                clockwise = false;
            }

            // Get the leg ID.
            int legnum = items[si].LegNumber;

            // How many distances have we got?
            int ndist = 0;

            for (; nexti < items.Length && items[nexti].LegNumber == legnum; nexti++)
            {
                if (items[nexti].IsDistance)
                {
                    ndist++;
                }
            }

            // Create the leg.
            CircularLeg        leg     = new CircularLeg(radius, clockwise, ndist);
            CircularLegMetrics metrics = leg.Metrics;

            // Set the entry angle or the central angle, depending on what we have.
            if (cul)
            {
                metrics.SetCentralAngle(cangle);
            }
            else
            {
                metrics.SetEntryAngle(bangle);
            }

            // Assign second angle if we have one.
            if (twoangles)
            {
                metrics.SetExitAngle(eangle);
            }

            // Assign each distance, starting one after the radius.
            ndist = 0;
            for (int i = irad + 1; i < nexti; i++)
            {
                Distance dist = items[i].GetDistance();
                if (dist != null)
                {
                    // See if there is a qualifier after the distance
                    LegItemFlag qual = LegItemFlag.Null;
                    if (i + 1 < nexti)
                    {
                        PathItemType nexttype = items[i + 1].ItemType;
                        if (nexttype == PathItemType.MissConnect)
                        {
                            qual = LegItemFlag.MissConnect;
                        }
                        if (nexttype == PathItemType.OmitPoint)
                        {
                            qual = LegItemFlag.OmitPoint;
                        }
                    }

                    leg.PrimaryFace.SetDistance(dist, ndist, qual);
                    ndist++;
                }
            }

            // Return the new leg.
            return(leg);
        }