예제 #1
0
        /// <summary>
        ///     Get the latitude/longitude coordinates from the euclidian coordinates
        /// </summary>
        /// <param name="xy">The euclidien coordinates</param>
        /// <returns>The latitude/longitude coordinates of that point</returns>
        public override GlobalCoordinates FromEuclidian(EuclidianCoordinate xy)
        {
            double scaleFactor;
            double meridianConvergence;

            return(FromEuclidian(xy, out scaleFactor, out meridianConvergence));
        }
예제 #2
0
        /// <summary>
        ///     Check whether another euclidian point belongs to the same projection
        /// </summary>
        /// <param name="other">The other point</param>
        /// <returns>True if they belong to the same projection, false otherwise</returns>
        public override bool IsSameProjection(EuclidianCoordinate other)
        {
            var utmOther = other as UtmCoordinate;

            if (null != utmOther)
            {
                return(utmOther.Grid.Equals(Grid));
            }
            return(false);
        }
예제 #3
0
        /// <summary>
        ///     Compute the euclidian distance to another point
        /// </summary>
        /// <param name="other">The other point</param>
        /// <returns>The distance</returns>
        /// <exception cref="ArgumentException">Raised if the two points don't belong to the same projection</exception>
        public override double DistanceTo(EuclidianCoordinate other)
        {
            var obj = other as UtmCoordinate;

            if (obj == null || !Grid.Equals(obj.Grid))
            {
                throw new ArgumentException();
            }
            return(base.DistanceTo(other));
        }
예제 #4
0
 /// <summary>
 ///     Compute the euclidian distance between two points given by rectangular coordinates
 ///     Please note, that due to scaling effects this might be quite different from the true
 ///     geodetic distance. To get a good approximation, you must divide this value by a
 ///     scale factor.
 /// </summary>
 /// <param name="point1">The first point</param>
 /// <param name="point2">The second point</param>
 /// <returns>The distance between the points</returns>
 /// <exception cref="ArgumentException">Raised if the two points don't belong to the same projection</exception>
 /// <exception cref="ArgumentNullException">Raised if one of the points is null</exception>
 public double EuclidianDistance(EuclidianCoordinate point1, EuclidianCoordinate point2)
 {
     if (point1 == null || point2 == null)
     {
         throw new ArgumentNullException();
     }
     if (!(point1.Projection.Equals(this) && point2.Projection.Equals(this)))
     {
         throw new ArgumentException(Properties.Resource.POINT_NOT_OWNED);
     }
     return(point1.DistanceTo(point2));
 }
        /// <summary>
        ///     Convert a XY position on a Mercator map into global coordinates
        /// </summary>
        /// <param name="xy">The xy position on the Mercator map</param>
        /// <returns>The global coordinates</returns>
        public GlobalCoordinates XyToGlobalCoordinates(double[] xy)
        {
            var e = new EuclidianCoordinate(this, xy);

            return(FromEuclidian(e));
        }
 /// <summary>
 ///     Get the latitude/longitude coordinates from the euclidian coordinates
 /// </summary>
 /// <param name="xy">The euclidien coordinates</param>
 /// <returns>The latitude/longitude coordinates of that point</returns>
 public override GlobalCoordinates FromEuclidian(EuclidianCoordinate xy)
 {
     return(new GlobalCoordinates(YToLatitude(xy.Y), XToLongitude(xy.X)));
 }
        /// <summary>
        ///     Compute a loxodromic path from start to end witha given number of points
        /// </summary>
        /// <param name="start">starting coordinates</param>
        /// <param name="end">ending coordinates</param>
        /// <param name="mercatorRhumbDistance">The distance of the two points on a Rhumb line on the Mercator projection</param>
        /// <param name="bearing">The constant course for the path</param>
        /// <param name="numberOfPoints">Number of points on the path (including start and end)</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the number of points is less than 2</exception>
        /// <returns>An array of points describing the loxodromic path from start to end</returns>
        public GlobalCoordinates[] CalculatePath(
            GlobalCoordinates start,
            GlobalCoordinates end,
            out double mercatorRhumbDistance,
            out Angle bearing,
            int numberOfPoints = 10)
        {
            mercatorRhumbDistance = 0;
            bearing = 0;
            if (numberOfPoints < 2)
            {
                throw new ArgumentOutOfRangeException(Properties.Resource.GEODETIC_PATH_MIN_2);
            }
            if (start == end || numberOfPoints == 2)
            {
                return new[] { start, end }
            }
            ;

            var cStart = ToEuclidian(start);
            var cEnd   = ToEuclidian(end);
            var dist   = EuclidianDistance(cStart, cEnd);
            var step   = dist / (numberOfPoints - 1);
            var dx     = (cEnd.X - cStart.X) / dist;
            var dy     = (cEnd.Y - cStart.Y) / dist;

            bearing         = 0;
            bearing.Radians = Math.Atan2(dx, dy);
            if (bearing < 0)
            {
                bearing += 360;
            }
            if (bearing == 90 || bearing == 270)
            {
                mercatorRhumbDistance = dist * ScaleFactor(start.Latitude.Degrees);
            }
            else
            {
                /*
                 * This is based on a paper published by Miljenko Petrović
                 * See: http://hrcak.srce.hr/file/24998
                 * */
                var e2 = ReferenceGlobe.Eccentricity * ReferenceGlobe.Eccentricity;
                mercatorRhumbDistance = ReferenceGlobe.SemiMajorAxis / Math.Cos(bearing.Radians) *
                                        (((1 - e2 / 4.0) * (end.Latitude - start.Latitude).Radians)
                                         -
                                         e2 * (Math.Sin(2 * end.Latitude.Radians)
                                               - Math.Sin(2 * start.Latitude.Radians)) * 3.0 / 8.0);
            }
            var result = new GlobalCoordinates[numberOfPoints];

            result[0] = start;
            result[numberOfPoints - 1] = end;
            for (var i = 1; i < numberOfPoints - 1; i++)
            {
                var point = new EuclidianCoordinate(this, cStart.X + i * dx * step, cStart.Y + i * dy * step);
                result[i] = FromEuclidian(point);
            }
            return(result);
        }
    }
예제 #8
0
 /// <summary>
 ///     Get the latitude/longitude coordinates from the euclidian coordinates
 /// </summary>
 /// <param name="xy">The euclidien coordinates</param>
 /// <returns>The latitude/longitude coordinates of that point</returns>
 public override GlobalCoordinates FromEuclidian(EuclidianCoordinate xy)
 {
     return(FromEuclidian(xy, out _, out _));
 }
예제 #9
0
        internal GlobalCoordinates FromEuclidian(
            EuclidianCoordinate xy,
            out double scaleFactor,
            out double meridianConvergence)
        {
            if (!(xy is UtmCoordinate point))
            {
                throw new ArgumentException(Properties.Resource.NO_UTM_COORDINATE);
            }
            var hemi = point.Grid.IsNorthern ? 1 : -1;

            var northingOffset = point.Grid.IsNorthern ? 0.0 : Southern_Northing_Offset;
            var chi            = (point.Y - northingOffset) / (MathConsts.K0 * _m.A);
            var eta            = (point.X - MathConsts.E0) / (MathConsts.K0 * _m.A);

            var sum = 0.0;

            for (var j = 1; j <= 3; j++)
            {
                sum += (_m.Beta[j - 1] * Math.Sin(2.0 * j * chi) * Math.Cosh(2.0 * j * eta));
            }
            var chitick = chi - sum;

            sum = 0.0;
            for (var j = 1; j <= 3; j++)
            {
                sum += (_m.Beta[j - 1] * Math.Cos(2.0 * j * chi) * Math.Sinh(2.0 * j * eta));
            }
            var etatick = eta - sum;

            sum = 0.0;
            for (var j = 1; j <= 3; j++)
            {
                sum += (2.0 * j * _m.Beta[j - 1] * Math.Cos(2.0 * j * chi) * Math.Cosh(2.0 * j * eta));
            }
            var sigmatick = 1.0 - sum;

            var tautick = 0.0;

            for (var j = 1; j <= 3; j++)
            {
                tautick += (2.0 * j * _m.Beta[j - 1] * Math.Sin(2.0 * j * chi) * Math.Sinh(2.0 * j * eta));
            }
            var xi = Math.Asin(Math.Sin(chitick) / Math.Cosh(etatick));

            var phi = xi;

            for (var j = 1; j <= 3; j++)
            {
                phi += (_m.Delta[j - 1] * Math.Sin(2.0 * j * xi));
            }

            var lambda0 = point.Grid.CenterMeridian.Radians;
            var lambda  = lambda0 + Math.Atan(Math.Sinh(etatick) / Math.Cos(chitick));
            var k       = ((MathConsts.K0 * _m.A) / ReferenceGlobe.SemiMajorAxis) *
                          Math.Sqrt(((Math.Pow(Math.Cos(chitick), 2.0) + Math.Pow(Math.Sinh(etatick), 2.0)) /
                                     (sigmatick * sigmatick + tautick * tautick)) *
                                    (1.0 + Math.Pow(((1.0 - _m.N) / (1.0 + _m.N)) * Math.Tan(phi), 2.0)));
            var gamma = Math.Atan((tautick + sigmatick * Math.Tan(chitick) * Math.Tanh(etatick)) /
                                  (sigmatick - tautick * Math.Tan(chitick) * Math.Tanh(etatick))) * hemi;

            scaleFactor         = k;
            meridianConvergence = gamma;
            return(new GlobalCoordinates(Angle.RadToDeg(phi), Angle.RadToDeg(lambda)));
        }
예제 #10
0
 /// <summary>
 ///     Get the latitude/longitude coordinates from the euclidian coordinates
 /// </summary>
 /// <param name="xy">The euclidien coordinates</param>
 /// <returns>The latitude/longitude coordinates of that point</returns>
 public abstract GlobalCoordinates FromEuclidian(EuclidianCoordinate xy);