Exemple #1
0
        /// <summary>
        /// Gets the position of a point on the circular leg.
        /// </summary>
        /// <param name="dist">The (unscaled) distance to the desired point.</param>
        /// <returns>The position.</returns>
        IPosition GetPoint(double dist, IPosition center, double radius, double culFactor, double bearingToBC, double sfac)
        {
            // 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 = (dist * culFactor) / radius;

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

            double bearing;

            if (m_Metrics.IsClockwise)
            {
                bearing = bearingToBC + angle;
            }
            else
            {
                bearing = bearingToBC - angle;
            }

            // Calculate the position using the scaled radius.
            return(Geom.Polar(center, bearing, radius * sfac));
        }
Exemple #2
0
        /// <summary>
        /// Gets the orientation point for a line. This is utilized to form
        /// network topology at the ends of a topological line.
        /// </summary>
        /// <param name="fromStart">True if the orientation from the start of the line is
        /// required. False to get the end orientation.</param>
        /// <param name="crvDist">Orientation distance for circular arcs (if a value of
        /// zero (or less) is specified, a "reasonable" orientation distance will be used -
        /// currently 5 metres on the ground).
        /// </param>
        /// <returns>The orientation point.</returns>
        internal override IPosition GetOrient(bool fromStart, double crvDist)
        {
            // Point to the BC or EC, depending on what we are orienting.
            IPosition loc = (fromStart ? Start : End);

            // Get the bearing of the location from the center of the circular arc
            IPointGeometry centre  = Circle.Center;
            double         bearing = Geom.BearingInRadians(centre, loc);

            // Get the distance to the orientation point. It should not be
            // any further than the length of the arc. We use a fixed
            // orientation distance of 5 metres on the ground for now.

            double dist;

            if (crvDist < Constants.TINY)
            {
                dist = Math.Min(5.0, Length.Meters);
            }
            else
            {
                dist = Math.Min(crvDist, Length.Meters);
            }

            // If we are coming from the end of the arc, use a negated
            // distance to get the direction right.
            if (!fromStart)
            {
                dist = -dist;
            }

            // Add the angle that subtends the orientation distance (or
            // subtract if the arc goes anti-clockwise).
            double radius = Circle.Radius;

            if (m_IsClockwise)
            {
                bearing += (dist / radius);
            }
            else
            {
                bearing -= (dist / radius);
            }

            // Figure out the orientation point from the new bearing.
            return(Geom.Polar(centre, bearing, radius));
        }
Exemple #3
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);
        }
Exemple #4
0
        private Feature ImportName(Ntx.Name name, Operation creator)
        {
            /*
             * // Get pointer to the applicable map theme
             * CeTheme theme(Name.GetTheme());
             * CeTheme* pTheme = theme.AddTheme();
             *
             * // Get pointer to the entity type.
             * GRAPHICSTYPE geom = ANNOTATION;
             * if ( Name.IsLabel() ) geom = POLYGON;
             * CeEntity* pEntity = AddEntity(Name.GetpFeatureCode(),pTheme,geom);
             */
            IEntity entity = GetEntityType(name, SpatialType.Text);

            // Get the text string
            string text = name.Text;

            // Get the position of the centre of the 1st character
            Ntx.Position pos     = name.Position(0);
            IPosition    vcentre = new Position(pos.Easting, pos.Northing);

            // Get text metrics
            float height   = name.Height;
            float spacing  = name.Spacing;
            float rotation = name.Rotation;

            // Calculate the top left corner of the first character using
            // the text metrics we just got ...

            // Get the width of the first character. For names that contain
            // only one character, the spacing we have will be zero, so in
            // that case, deduce the width of the character via the covering
            // rectangle.

            float charwidth = spacing;

            if (charwidth < Constants.TINY)
            {
                // Get the covering rectangle.
                Ntx.Position nw = name.NorthWest;
                Ntx.Position se = name.SouthEast;

                // And get the dimensions.
                double dx = se.Easting - nw.Easting;
                double dy = nw.Northing - se.Northing;

                // If the cover is screwed up, assume the width is 80% of the text height.
                if (dy < Constants.TINY)
                {
                    charwidth = (float)(height * 0.8);
                }
                else
                {
                    charwidth = (float)(height * (dx / dy));
                }
            }

            // Define the bearing from bottom to top of the text.
            double vbear = (double)rotation;

            // Get position directly above the centre of the 1st char.
            IPosition above = Geom.Polar(vcentre, vbear, 0.5 * (double)height);

            // Define the bearing from the point we just got to the
            // start of the text string.
            double hbear = vbear - Constants.PIDIV2;

            // Back up half a character to get the initial corner.
            PointGeometry topleft = new PointGeometry(Geom.Polar(above, hbear, 0.5 * (double)charwidth));

            IFont       font   = null;
            double      width  = (double)text.Length * charwidth;
            TextFeature result = null;

            if (name.IsLabel)
            {
                // Create key text
                string          keystr = name.Text;
                KeyTextGeometry kt     = new KeyTextGeometry(topleft, font, height, width, rotation);
                InternalIdValue id     = CadastralMapModel.Current.WorkingSession.AllocateNextId();
                result   = new TextFeature(creator, id, entity, kt);
                kt.Label = result;
                result.SetTopology(true);

                // Define the label's foreign ID and form a two-way association
                ForeignId fid = GetFeatureId(keystr);
                Debug.Assert(fid != null);
                fid.Add(result);

                // Remember the reference position of the label.
                Ntx.Position   xp = name.RefPosition;
                IPointGeometry pp = new PointGeometry(xp.Easting, xp.Northing);
                result.SetPolPosition(pp);
            }
            else
            {
                // Create a miscellaneous text label.
                MiscTextGeometry mt = new MiscTextGeometry(text, topleft, font, height, width, rotation);
                InternalIdValue  id = CadastralMapModel.Current.WorkingSession.AllocateNextId();
                result = new TextFeature(creator, id, entity, mt);
                result.SetTopology(false);
            }

            return(result);
        }
Exemple #5
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);
        }
Exemple #6
0
        /// <summary>
        /// Obtains annotation for this line.
        /// </summary>
        /// <param name="dist">The observed distance (if any).</param>
        /// <param name="drawObserved">Draw observed distance? Specify <c>false</c> for
        /// actual distance.</param>
        /// <returns>The annotation (null if it cannot be obtained)</returns>
        Annotation GetAnnotation(Distance dist, bool drawObserved)
        {
            // @devnote This function may not be that hot for curves that
            // are complete circles. At the moment though, I can't see why
            // we'd be drawing a distance alongside a circle.

            // Get the length of the arc
            double len = this.Length.Meters;

            // Get the string to output.
            string distr = GetDistance(len, dist, drawObserved);

            if (distr == null)
            {
                return(null);
            }

            // Get the mid-point of this arc.
            IPosition mid;

            this.GetPosition(new Length(len * 0.5), out mid);

            // Get the bearing from the center to the midpoint.
            IPosition center  = m_Circle.Center;
            double    bearing = BasicGeom.BearingInRadians(center, mid);

            // Get the height of the text, in meters on the ground.
            double grheight = EditingController.Current.LineAnnotationStyle.Height;

            // We will offset by 20% of the height (give a bit of space
            // between the text and the line).
            //double offset = grheight * 0.2;
            // ...looks fine with no offset (there is a space, but it's for descenders
            // that aren't there since we're dealing just with numbers).
            double offset = 0.0;

            // Get the rotation of the text.
            double rotation = bearing - MathConstants.PI;

            // If the midpoint is above the circle centre, we get upside-down
            // text so rotate it the other way. If we don't switch the
            // rotation, we need to make an extra shift, because the text
            // is aligned along its baseline.

            // This depends on whether the annotation is on the default
            // side or not.

            // Not sure about the following... (c.f. revised handling in SegmentGeometry)

            /*
             * if (mid.Y > center.Y)
             * {
             *  rotation += MathConstants.PI;
             *  if (isFlipped)
             *      offset = -0.9 * grheight;
             * }
             * else
             * {
             *  if (isFlipped)
             *      offset = -offset;
             *  else
             *      offset = 0.9 * grheight;	// 1.0 * grheight is too much
             * }
             */

            // ...try this instead

            if (mid.Y > center.Y)
            {
                rotation += MathConstants.PI;
            }
            else
            {
                offset = 1.3 * grheight; // push the text to the outer edge of the arc
            }
            if (dist != null && dist.IsAnnotationFlipped)
            {
                rotation += MathConstants.PI;

                // and may need to adjust offset...
            }

            // Project to the offset point.
            IPosition  p      = Geom.Polar(center, bearing, m_Circle.Radius + offset);
            Annotation result = new Annotation(distr, p, grheight, rotation);

            result.FontStyle = FontStyle.Italic;
            return(result);
        }
Exemple #7
0
        /// <summary>
        /// Adjusts the path (Helmert adjustment).
        /// </summary>
        /// <param name="dN">Misclosure in northing.</param>
        /// <param name="dE">Misclosure in easting.</param>
        /// <param name="precision">Precision denominator (zero if no adjustment needed).</param>
        /// <param name="length">Total observed length.</param>
        /// <param name="rotation">The clockwise rotation to apply (in radians).</param>
        /// <param name="sfac">The scaling factor to apply.</param>
        void Adjust(out double dN, out double dE, out double precision, out double length,
                    out double rotation, out double sfac)
        {
            dN   = dE = precision = length = rotation = 0.0;
            sfac = 1.0;

            // Initialize position to the start of the path, corresponding to the initial
            // un-adjusted end point.
            IPosition start  = m_From;
            IPosition gotend = new Position(m_From);

            // Initial bearing is due north.
            double bearing = 0.0;

            // Go through each leg, updating the end position, and getting
            // the total path length.
            foreach (Leg leg in m_Legs)
            {
                length += leg.Length.Meters;
                leg.Project(ref gotend, ref bearing, sfac);
            }

            // Get the bearing and distance of the end point we ended up with.
            double gotbear = Geom.BearingInRadians(m_From, gotend);
            double gotdist = Geom.Distance(m_From, gotend);

            // Get the bearing and distance we want.
            double wantbear = Geom.BearingInRadians(m_From, m_To);
            double wantdist = Geom.Distance(m_From, m_To);

            // Figure out the rotation.
            rotation = wantbear - gotbear;

            // Rotate the end point we got.
            gotend = Geom.Rotate(m_From, gotend, new RadianValue(rotation));

            // Calculate the line scale factor.
            double linefac = m_From.MapModel.SpatialSystem.GetLineScaleFactor(m_From, gotend);

            // Figure out where the rotated end point ends up when we apply the line scale factor.
            gotend = Geom.Polar(m_From, wantbear, gotdist * linefac);

            // What misclosure do we have?
            dN = gotend.Y - m_To.Y;
            dE = gotend.X - m_To.X;
            double delta = Math.Sqrt(dN * dN + dE * dE);

            // What's the precision denominator (use a value of 0 to denote an exact match).
            if (delta > MathConstants.TINY)
            {
                precision = wantdist / delta;
            }
            else
            {
                precision = 0.0;
            }

            // Figure out the scale factor for the adjustment (use a value of 0 if the start and end
            // points are coincident). The distances here have NOT been adjusted for the line scale factor.
            if (gotdist > MathConstants.TINY)
            {
                sfac = wantdist / gotdist;
            }
            else
            {
                sfac = 0.0;
            }

            // Remember the rotation and scaling factor
            m_IsAdjusted  = true;
            m_Rotation    = rotation;
            m_ScaleFactor = sfac;
            m_Precision   = precision;
        }