Example #1
0
        /// <summary>
        /// Attempts to make a distance out of this observation and a from-point.
        /// </summary>
        /// <param name="from">The point the distance was measured from.</param>
        /// <returns>
        /// The distance, in metres on the ground. If a distance cannot be deduced,
        /// this will be 0.0. NOTE: may actually be a distance on the mapping plane if this
        /// observation is an offset point. The caller needs to check.</returns>
        /// <devnote>
        /// This function was written to assist in the implementation of the
        /// Intersect Direction & Distance command, which allows a distance to be specified
        /// using an offset point. Since offsets and distance object do not inherit from some
        /// place where we could define a pure virtual, this function exists to make explicit
        /// checks on the sort of distance we have (I don't want to define stubs for all the
        /// other objects which won't be able to return a distance). Re-arranging the class
        /// hierarchy would be better.
        /// </devnote>
        internal ILength GetDistance(PointFeature from)
        {
            // It's easy if the observation is a distance object.
            Distance dist = (this as Distance);

            if (dist != null)
            {
                return(dist);
            }

            // Can't do anything if the from point is undefined.
            if (from == null)
            {
                return(Length.Zero);
            }

            // See if we have an offset point. If so, the distance is the
            // distance from the from-point to the offset-point.
            OffsetPoint offset = (OffsetPoint)this;

            if (offset == null)
            {
                return(Length.Zero);
            }

            return(new Length(Geom.Distance(offset.Point, from)));
        }
Example #2
0
 /// <summary>
 /// Calculates the distance from the start of this line to a specific position (on the map projection)
 /// </summary>
 /// <param name="asFarAs">Position on the line that you want the length to. Specify
 /// null for the length of the whole line.</param>
 /// <returns>The length. Less than zero if a position was specified and it is
 /// not on the line.</returns>
 internal override ILength GetLength(IPosition asFarAs)
 {
     if (asFarAs == null)
     {
         return(Length);
     }
     else
     {
         // assume it's on the line
         return(new Length(Geom.Distance(Start, asFarAs)));
     }
 }
Example #3
0
        /// <summary>
        /// Delegate that's called whenever the index finds a line with an extent that
        /// overlaps the query window.
        /// </summary>
        /// <param name="item">The item to process (expected to be some sort of <c>IFeature</c>)</param>
        /// <returns>True (always), meaning the query should continue.</returns>
        private bool OnQueryHit(ISpatialObject item)
        {
            if (item is Circle)
            {
                // Confirm the circle is truly within tolerance
                Circle c    = (item as Circle);
                double rad  = c.Radius;
                double dist = Geom.Distance(c.Center, m_Position);
                if (Math.Abs(rad - dist) < m_Tolerance)
                {
                    m_Result.Add(c);
                }
            }

            return(true);
        }
Example #4
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);
        }
Example #5
0
        /// <summary>
        /// Obtains the geometry for spans along an alternate face attached to this leg.
        /// </summary>
        /// <param name="start">The position for the start of the leg.
        /// <param name="end">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 start, IPosition end, SpanInfo[] spans)
        {
            Debug.Assert(AlternateFace != null);

            // Get the desired length (in meters on the ground)
            double len = Geom.Distance(start, end);

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

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

            // Get the bearing of the line.
            double bearing = Geom.BearingInRadians(start, end);

            return(GetSpanSections(start, bearing, factor, spans));
        }
        static bool GetPosition(IPosition[] line, double d, out IPosition result)
        {
            if (line.Length < 2)
            {
                throw new Exception("Line contains fewer than 2 positions");
            }

            // Check for invalid distance
            if (d < 0.0)
            {
                result = line[0];
                return(false);
            }

            double walked = 0.0;        // Distance walked so far

            // Loop through the segments until we get to a distance that
            // exceeds the required distance.
            for (int i = 1; i < line.Length; i++)
            {
                // Update total length walked to end of segment
                double seglen = Geom.Distance(line[i - 1], line[i]);
                walked += seglen;

                // If the accumulated distance exceeds the required distance,
                // the point we want is somewhere in the current segment.
                if (walked >= d)
                {
                    double ratio = (walked - d) / seglen;

                    // Check whether the ratio yields a length that matches segment length to within
                    // the order of the data precision (1 micron). If so, return the start of the segment.
                    // If you don't do this, minute shifts occur when points are inserted into the
                    // multisegment. This means that if you repeat the GetPosition call with the SAME distance,
                    // you may actually get a point that is fractionally different from the initially returned
                    // point.

                    if ((seglen - ratio * seglen) < 0.000002)
                    {
                        result = line[i - 1];
                    }
                    else
                    {
                        // Make damn sure!

                        double xs   = line[i - 1].X;
                        double ys   = line[i - 1].Y;
                        double xe   = line[i].X;
                        double ye   = line[i].Y;
                        double dx   = xe - xs;
                        double dy   = ye - ys;
                        double xres = xe - ratio * dx;
                        double yres = ye - ratio * dy;

                        if (Math.Abs(xres - xe) < 0.000002 && Math.Abs(yres - ye) < 0.000002)
                        {
                            result = line[i];
                        }
                        else
                        {
                            result = new Position(xres, yres);
                        }
                    }

                    return(true);
                }
            }

            // Got to the end, so the distance is too much
            result = line[line.Length - 1];
            return(false);
        }
Example #7
0
        void CheckPts(string ptsFileName, CadastralMapModel mm)
        {
            if (!File.Exists(ptsFileName))
            {
                return;
            }

            var badList = new List <CheckData>();

            foreach (string s in File.ReadAllLines(ptsFileName))
            {
                string[] items = s.Split(',');
                uint     id    = UInt32.Parse(items[0]);
                double   x     = Double.Parse(items[1]);
                double   y     = Double.Parse(items[2]);
                Position a     = new Position(x, y);

                PointFeature p = mm.Find <PointFeature>(new InternalIdValue(id));

                if (p != null)
                {
                    double delta = Geom.Distance(a, p);
                    if (delta > 0.001)
                    {
                        badList.Add(new CheckData()
                        {
                            Point = p, Delta = delta
                        });
                    }
                }
            }

            // Obtain the calculation sequence
            Operation[] calcs     = mm.GetCalculationSequence();
            var         editOrder = new Dictionary <uint, uint>();

            for (int i = 0; i < calcs.Length; i++)
            {
                editOrder.Add(calcs[i].EditSequence, (uint)i);
            }

            foreach (CheckData cd in badList)
            {
                cd.CalculationOrder = editOrder[cd.Point.Creator.EditSequence];
            }

            badList.Sort((A, B) => A.CalculationOrder.CompareTo(B.CalculationOrder));

            using (StreamWriter sw = File.CreateText(ptsFileName + ".check"))
            {
                // Dump out the calc order
                //foreach (Operation op in calcs)
                //    sw.WriteLine(String.Format("Edit={0} Order={1} Type={2}", op.EditSequence, editOrder[op.EditSequence], op.EditId));

                sw.WriteLine("Number of points>0.001 = " + badList.Count);
                foreach (CheckData cd in badList)
                {
                    sw.WriteLine(String.Format("Order={0} Id={1}  Delta={2:0.000}",
                                               cd.CalculationOrder, cd.Point.InternalId.ItemSequence, cd.Delta));
                }
            }
        }
Example #8
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;
        }