////////////////////////////////////////////////////////////////////////////////////// // This method takes in present position (LatLongClass) and range/bearing from the // present position. It returns a new position (LatLongClass) // // Distance is IN // Azimuth in degrees public static LatLongClass CalculateNewPosition(LatLongClass PresentPosition, double Distance, double Azimuth) { LatLongClass NewPosition = new LatLongClass(); // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set Lincoln Memorial coordinates GlobalCoordinates Present_Pos; Present_Pos = new GlobalCoordinates(new Angle(PresentPosition.GetLatLongDecimal().LatitudeDecimal), new Angle(PresentPosition.GetLatLongDecimal().LongitudeDecimal)); // now, plug the result into to direct solution GlobalCoordinates dest; Angle endBearing = new Angle(); double Distance_In_Meeters = (Distance * NMtoKM * 1000.0); dest = geoCalc.CalculateEndingGlobalCoordinates(reference, Present_Pos, Azimuth, Distance_In_Meeters, out endBearing); NewPosition.SetPosition(new LatLongDecimal(dest.Latitude.Degrees, dest.Longitude.Degrees)); return NewPosition; }
public void AssignFunctions(LocalTerrain lt, FunctionMathCalculator fmc, GlobalCoordinates globalMinThresholdC, GlobalCoordinates globalMaxThresholdC) { this.lt = lt; this.fmc = fmc; this.globalMinThresholdC = globalMinThresholdC; this.globalMaxThresholdC = globalMaxThresholdC; }
public bool IsDefined(int x, int z, GlobalCoordinates gc) { if (GetLocalValue(x, z, gc) == 666) return false; else return true; }
/// <summary> /// Calculate the destination if we start at: /// Lincoln Memorial in Washington, D.C --> 38.8892N, 77.04978W /// and travel at /// 51.7679 degrees for 6179.016136 kilometers /// /// WGS84 reference ellipsoid /// </summary> static void TwoDimensionalDirectCalculation() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set Lincoln Memorial coordinates GlobalCoordinates lincolnMemorial; lincolnMemorial = new GlobalCoordinates( new Angle(38.88922), new Angle(-77.04978) ); // set the direction and distance Angle startBearing = new Angle(51.7679); double distance = 6179016.13586; // find the destination Angle endBearing; GlobalCoordinates dest = geoCalc.CalculateEndingGlobalCoordinates(reference, lincolnMemorial, startBearing, distance, out endBearing); Console.WriteLine("Travel from Lincoln Memorial at 51.767921 deg for 6179.016 km"); Console.Write(" Destination: {0:0.0000}{1}", dest.Latitude.Degrees, (dest.Latitude > 0) ? "N" : "S" ); Console.WriteLine(", {0:0.0000}{1}", dest.Longitude.Degrees, (dest.Longitude > 0) ? "E" : "W"); Console.WriteLine(" End Bearing: {0:0.00} degrees", endBearing.Degrees); }
public void TestAntiPodal1() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set position 1 GlobalCoordinates p1; p1 = new GlobalCoordinates(10, 80.6); // set position 2 GlobalCoordinates p2; p2 = new GlobalCoordinates(-10, -100); // calculate the geodetic measurement GeodeticCurve geoCurve; geoCurve = geoCalc.CalculateGeodeticCurve(reference, p1, p2); Assert.AreEqual(19970718.422432076, geoCurve.EllipsoidalDistance, 0.001); Assert.AreEqual(90.0004877491174, geoCurve.Azimuth.Degrees, 0.0000001); Assert.AreEqual(270.0004877491174, geoCurve.ReverseAzimuth.Degrees, 0.0000001); }
/// <summary> /// Calculate the two-dimensional path from /// Lincoln Memorial in Washington, D.C --> 38.8892N, 77.04978W /// to /// Eiffel Tower in Paris --> 48.85889N, 2.29583E /// using /// WGS84 reference ellipsoid /// </summary> static void TwoDimensionalInverseCalculation() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set Lincoln Memorial coordinates GlobalCoordinates lincolnMemorial; lincolnMemorial = new GlobalCoordinates( new Angle(38.88922), new Angle(-77.04978) ); // set Eiffel Tower coordinates GlobalCoordinates eiffelTower; eiffelTower = new GlobalCoordinates( new Angle(48.85889), new Angle(2.29583) ); // calculate the geodetic curve GeodeticCurve geoCurve = geoCalc.CalculateGeodeticCurve(reference, lincolnMemorial, eiffelTower); double ellipseKilometers = geoCurve.EllipsoidalDistance / 1000.0; double ellipseMiles = ellipseKilometers * 0.621371192; Console.WriteLine("2-D path from Lincoln Memorial to Eiffel Tower using WGS84"); Console.WriteLine(" Ellipsoidal Distance: {0:0.00} kilometers ({1:0.00} miles)", ellipseKilometers, ellipseMiles); Console.WriteLine(" Azimuth: {0:0.00} degrees", geoCurve.Azimuth.Degrees); Console.WriteLine(" Reverse Azimuth: {0:0.00} degrees", geoCurve.ReverseAzimuth.Degrees); }
/// <summary> /// returns filter value on given global coordiantes (0 if not defined) /// gc = global filter space /// </summary> public float GetGlobalValue(int x, int z, GlobalCoordinates gc) { float value = gc.GetValue(x, z); if (value != 666) return value; else return 0; }
public void AssignFunctions(LocalTerrain lt, FunctionMathCalculator fmc, GlobalCoordinates globalFilterMedianC, FunctionTerrainManager functionTerrainManager) { this.lt = lt; this.fmc = fmc; this.globalFilterMedianC = globalFilterMedianC; ftm = functionTerrainManager; }
/// <summary> /// apply filter to given heightmap /// </summary> public void FilterMapInRegion(GlobalCoordinates map, Area region, float epsilon) { int x_min = region.botLeft.x; int z_min = region.botLeft.z; int x_max = region.topRight.x; int z_max = region.topRight.z; int area = 1; GlobalCoordinates mapTmp = new GlobalCoordinates(100); for (int x = x_min; x < x_max; x++) { for (int z = z_min; z < z_max; z++) { if (map.IsDefined(x, z)) { float average = 0; int neighboursCount = 0; for (int _x = x - area; _x <= x + area; _x++) { for (int _z = z - area; _z <= z + area; _z++) { if (map.IsDefined(_x, _z)) { average += map.GetValue(_x, _z, 0); neighboursCount++; } } } if (neighboursCount != 0) average /= neighboursCount; else average = 666; if (average != 666) { float height = map.GetValue(x, z); if (height < average - epsilon) fg.SetGlobalValue(x, z, (average + epsilon), true, mapTmp); else if (height > average + epsilon) fg.SetGlobalValue(x, z, (average - epsilon), true, mapTmp); } } } } for (int x = x_min; x < x_max; x++) { for (int z = z_min; z < z_max; z++) { if(mapTmp.IsDefined(x, z)) map.SetValue(x, z, mapTmp.GetValue(x, z)); } } }
public static GeodeticMeasurement CalculateDistance(double lat1, double lon1, double lat2, double lon2) { GlobalCoordinates p1 = new GlobalCoordinates(new Angle(lat1), new Angle(lon1)); GlobalCoordinates p2 = new GlobalCoordinates(new Angle(lat2), new Angle(lon2)); GeodeticCalculator gc = new GeodeticCalculator(); GlobalPosition gp1 = new GlobalPosition(p1); GlobalPosition gp2 = new GlobalPosition(p2); GeodeticMeasurement gm = gc.CalculateGeodeticMeasurement(Ellipsoid.WGS84, gp1, gp2); return gm; }
public PatchManager(int patchSize) { this.patchSize = patchSize; rMin = new GlobalCoordinates(100); rMax = new GlobalCoordinates(100); noise = new GlobalCoordinates(100); patchLevel = new GlobalCoordinates(100);//-1 = random,0=low,1=medium,2=high gm = new GridManager(new Vector3(0, 0, 0), patchSize, patchSize); SetPatchOrder(PatchOrder.LMH); }
public void AssignFunctions(GlobalCoordinates globalTerrainC, TerrainGenerator terrainGenerator, FilterGenerator filterGenerator, RiverGenerator riverGenerator, ErosionGenerator erosionGenerator) { this.globalTerrainC = globalTerrainC; tg = terrainGenerator; fg = filterGenerator; rg = riverGenerator; eg = erosionGenerator; lm.AssignFunctions(tg, fg, rg, eg); }
private void DoGeodaeticCalculations () { DataRow RootRow = MapDataWrapper.Instance.GetMapKachelRootImageRow (TypenName, RootKachelName); GeodeticCalculator GeoCalc = new GeodeticCalculator(); Ellipsoid ReferenceModell = Ellipsoid.WGS84; GlobalCoordinates TopLeftStart = new GlobalCoordinates (new Angle(Convert.ToDouble(RootRow["TopY"])), new Angle(Convert.ToDouble(RootRow["LeftX"]))); GlobalCoordinates TopRightEnd = new GlobalCoordinates (new Angle(Convert.ToDouble(RootRow["TopY"])), new Angle(Convert.ToDouble(RootRow["RightX"]))); GlobalCoordinates BottomLeftStart = new GlobalCoordinates (new Angle(Convert.ToDouble(RootRow["BottomY"])), new Angle(Convert.ToDouble(RootRow["LeftX"]))); GlobalCoordinates BottomRightEnd = new GlobalCoordinates (new Angle(Convert.ToDouble(RootRow["BottomY"])), new Angle(Convert.ToDouble(RootRow["RightX"]))); GeodeticCurve TopCurve = GeoCalc.CalculateGeodeticCurve(ReferenceModell, TopLeftStart, TopRightEnd); double TopMeters = TopCurve.EllipsoidalDistance; GeodeticCurve BottomCurve = GeoCalc.CalculateGeodeticCurve(ReferenceModell, BottomLeftStart, BottomRightEnd); double BottomMeters = BottomCurve.EllipsoidalDistance; GeodeticCurve LeftCurve = GeoCalc.CalculateGeodeticCurve(ReferenceModell, BottomLeftStart, TopLeftStart); double LeftMeters = LeftCurve.EllipsoidalDistance; GeodeticCurve RightCurve = GeoCalc.CalculateGeodeticCurve(ReferenceModell, BottomRightEnd, TopRightEnd); double RightMeters = RightCurve.EllipsoidalDistance; LeftToRightDistance = (TopMeters + BottomMeters) / 2.0; BottomToTopDistance = (LeftMeters + RightMeters) / 2.0; LeftMeasure = new Point (Convert.ToDouble(RootRow["LeftX"]), Convert.ToDouble(RootRow["TopY"])); TopMeasure = new Point (Convert.ToDouble(RootRow["LeftX"]), Convert.ToDouble(RootRow["TopY"])); RightMeasure = new Point (Convert.ToDouble(RootRow["RightX"]), Convert.ToDouble(RootRow["BottomY"])); BottomMeasure = new Point (Convert.ToDouble(RootRow["RightX"]), Convert.ToDouble(RootRow["BottomY"])); double MaxDrawingAreaAspectRatio = MaxDrawingWidth / MaxDrawingHeight; double RootKachelAspectRatio = LeftToRightDistance / BottomToTopDistance; if (RootKachelAspectRatio >= MaxDrawingAreaAspectRatio) { FullDrawingWidth = MaxDrawingWidth; FullDrawingHeight = FullDrawingWidth / RootKachelAspectRatio; } else { FullDrawingHeight = MaxDrawingHeight; FullDrawingWidth = FullDrawingHeight * RootKachelAspectRatio; } }
public RiverInfo(RiverGenerator rg) { riverPath = new List<Vertex>(); //reachTop = false; //reachRight = false; //reachBot = false; //reachLeft = false; fd = rg.fd; frp = rg.frp; ftm = rg.ftm; fmc = rg.fmc; reachedSides = new List<Direction>(); shape = RiverShape.atan; lowestPoint = new Vertex(666, 666, 666); globalRiverC = new GlobalCoordinates(100); }
public FilterGenerator(int quadrantSize, LocalTerrain localTerrain) { globalFilterMountainC = new GlobalCoordinates(100); globalFilterAverageC = new GlobalCoordinates(100); globalFilterMedianC = new GlobalCoordinates(100); globalFilterSpikeC = new GlobalCoordinates(100); globalFilterGaussianC = new GlobalCoordinates(100); globalFilterMinThresholdC = new GlobalCoordinates(100); globalFilterMaxThresholdC = new GlobalCoordinates(100); lt = localTerrain; localCoordinates = lt.localTerrainC; mf = new MountainFilter(this); af = new AverageFilter(this); mdf = new MedianFilter(this); sf = new SpikeFilter(this); gf = new GaussianFilter(this); tf = new ThresholdFilter(this); }
public void CanonicalizeLatitude() { Angle latitude = new Angle(30); Angle longitude = new Angle(20); GlobalCoordinates coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, latitude); Assert.AreEqual(coords.Longitude, longitude); latitude = new Angle(100); coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, new Angle(80)); Assert.AreEqual(coords.Longitude, new Angle(-160)); latitude = new Angle(-100); coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, new Angle(-80)); Assert.AreEqual(coords.Longitude, new Angle(-160)); latitude = new Angle(200); coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, new Angle(-20)); Assert.AreEqual(coords.Longitude, new Angle(-160)); latitude = new Angle(280); coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, new Angle(-80)); Assert.AreEqual(coords.Longitude, longitude); latitude = new Angle(-200); coords = new GlobalCoordinates(latitude, longitude); Assert.AreEqual(coords.Latitude, new Angle(20)); Assert.AreEqual(coords.Longitude, new Angle(-160)); latitude = new Angle(100); longitude = new Angle(1000); coords = new GlobalCoordinates(latitude, longitude); coords.Longitude = 0.0; coords.Latitude = -359.0; Assert.IsTrue(Math.Abs(coords.Latitude.Degrees - 1.0) < 1e-6); }
public void CornerCaseForLatitude() { Angle latitude = new Angle(100); Angle longitude = new Angle(1000); GlobalCoordinates coords = new GlobalCoordinates(latitude, longitude); coords.Longitude = 0.0; coords.Latitude = -360.0; Assert.IsTrue(Math.Abs(coords.Latitude.Degrees - 0) < 1e-6); Assert.IsTrue(Math.Abs(coords.Longitude.Degrees - 0) < 1e-6); coords = new GlobalCoordinates(latitude, longitude); coords.Longitude = 180.0; coords.Latitude = -360.0; Assert.IsTrue(Math.Abs(coords.Latitude.Degrees - 0) < 1e-6); Assert.IsTrue(Math.Abs(coords.Longitude.Degrees - 180) < 1e-6); coords.Longitude = 0.0; coords.Latitude = 100.0; coords.Latitude = -360.0; Assert.IsTrue(Math.Abs(coords.Latitude.Degrees - 0) < 1e-6); Assert.IsTrue(Math.Abs(coords.Longitude.Degrees - 180) < 1e-6); }
float T = 0.1f; //delta time #endregion Fields #region Constructors public HydraulicErosion(ErosionGenerator erosionGenerator) { eg = erosionGenerator; lm = eg.lt.lm; hydraulicErosionMap = new GlobalCoordinates(100); sedimentMap = new GlobalCoordinates(100); waterMap = new GlobalCoordinates(100); stepMap = new GlobalCoordinates(100); //inflowMap = new GlobalCoordinates(100); outflowTop = new GlobalCoordinates(100); outflowRight = new GlobalCoordinates(100); outflowBot = new GlobalCoordinates(100); outflowLeft = new GlobalCoordinates(100); velocityX = new GlobalCoordinates(100); velocityZ = new GlobalCoordinates(100); erosionEffect = new HashSet<Vertex>(); outflowField = new HashSet<Vertex>(); noWater = new HashSet<Vertex>(); }
public void TestCalculateGeodeticCurve() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set Lincoln Memorial coordinates GlobalCoordinates lincolnMemorial; lincolnMemorial = new GlobalCoordinates(38.88922, -77.04978); // set Eiffel Tower coordinates GlobalCoordinates eiffelTower; eiffelTower = new GlobalCoordinates(48.85889, 2.29583); // calculate the geodetic curve GeodeticCurve geoCurve = geoCalc.CalculateGeodeticCurve(reference, lincolnMemorial, eiffelTower); Assert.AreEqual(6179016.136, geoCurve.EllipsoidalDistance, 0.001); Assert.AreEqual(51.76792142, geoCurve.Azimuth.Degrees, 0.0000001); Assert.AreEqual(291.75529334, geoCurve.ReverseAzimuth.Degrees, 0.0000001); }
public void TestPoleCrossing() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set Lincoln Memorial coordinates GlobalCoordinates lincolnMemorial; lincolnMemorial = new GlobalCoordinates(new Angle(38.88922), new Angle(-77.04978)); // set a bearing of 1.0deg (almost straight up) and a distance Angle startBearing = new Angle(1.0); double distance = 6179016.13586; // set the expected destination GlobalCoordinates expected; expected = new GlobalCoordinates(new Angle(85.60006433), new Angle(92.17243943)); // calculate the ending global coordinates Angle endBearing; GlobalCoordinates dest = geoCalc.CalculateEndingGlobalCoordinates(reference, lincolnMemorial, startBearing, distance, out endBearing); Assert.AreEqual(expected.Latitude.Degrees, dest.Latitude.Degrees, 0.0000001); Assert.AreEqual(expected.Longitude.Degrees, dest.Longitude.Degrees, 0.0000001); }
/// <summary> /// sets height to global terrain /// maps given local coordinates on global /// </summary> /// <param name="x"></param> /// <param name="z"></param> public void SetLocalValue(int x, int z, float height, bool overwrite, GlobalCoordinates gc) { if (!overwrite && IsDefined(x, z, gc)) return; gc.SetValue(x + (int)center.x - terrainWidth / 2, z + (int)center.z - terrainHeight / 2, height, overwrite); }
/// <summary> /// Convert a latitude/longitude coordinate to a Euclidian coordinate on a flat map /// </summary> /// <param name="coordinates">The latitude/longitude coordinates in degrees</param> /// <returns>The euclidian coordinates of that point</returns> public abstract EuclidianCoordinate ToEuclidian(GlobalCoordinates coordinates);
/// <summary> /// Get the Mercator scale factor for the given point /// </summary> /// <param name="point">The point</param> /// <returns>The scale factor</returns> public abstract double ScaleFactor(GlobalCoordinates point);
/// <summary> /// Calculate the geodetic curve between two points on a specified reference ellipsoid. /// This is the solution to the inverse geodetic problem. /// </summary> /// <param name="start">starting coordinates</param> /// <param name="end">ending coordinates</param> /// <returns>The geodetic curve information to get from start to end</returns> public GeodeticCurve CalculateGeodeticCurve( GlobalCoordinates start, GlobalCoordinates end) { // // All equation numbers refer back to Vincenty's publication: // See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf // // get constants var majorAxis = ReferenceGlobe.SemiMajorAxis; var minorAxis = ReferenceGlobe.SemiMinorAxis; var flattening = ReferenceGlobe.Flattening; // get parameters as radians var phi1 = start.Latitude.Radians; var lambda1 = start.Longitude.Radians; var phi2 = end.Latitude.Radians; var lambda2 = end.Longitude.Radians; // calculations var a2 = majorAxis * majorAxis; var b2 = minorAxis * minorAxis; var squaredRatio = (a2 - b2) / b2; var omega = lambda2 - lambda1; var tanphi1 = Math.Tan(phi1); var tanU1 = (1.0 - flattening) * tanphi1; var u1 = Math.Atan(tanU1); var sinU1 = Math.Sin(u1); var cosU1 = Math.Cos(u1); var tanphi2 = Math.Tan(phi2); var tanU2 = (1.0 - flattening) * tanphi2; var u2 = Math.Atan(tanU2); var sinU2 = Math.Sin(u2); var cosU2 = Math.Cos(u2); var sinU1SinU2 = sinU1 * sinU2; var cosU1SinU2 = cosU1 * sinU2; var sinU1CosU2 = sinU1 * cosU2; var cosU1CosU2 = cosU1 * cosU2; // eq. 13 var lambda = omega; // intermediates we'll need to compute 's' var a = 0.0; var sigma = 0.0; var deltasigma = 0.0; var converged = false; for (var i = 0; i < 20; i++) { var lambda0 = lambda; var sinlambda = Math.Sin(lambda); var coslambda = Math.Cos(lambda); // eq. 14 var sin2Sigma = cosU2 * sinlambda * cosU2 * sinlambda + Math.Pow(cosU1SinU2 - sinU1CosU2 * coslambda, 2.0); var sinsigma = Math.Sqrt(sin2Sigma); // eq. 15 var cossigma = sinU1SinU2 + cosU1CosU2 * coslambda; // eq. 16 sigma = Math.Atan2(sinsigma, cossigma); // eq. 17 Careful! sin2sigma might be almost 0! var sinalpha = sin2Sigma.IsZero() ? 0.0 : cosU1CosU2 * sinlambda / sinsigma; var alpha = Math.Asin(sinalpha); var cosalpha = Math.Cos(alpha); var cos2Alpha = cosalpha * cosalpha; // eq. 18 Careful! cos2alpha might be almost 0! var cos2Sigmam = cos2Alpha.IsZero() ? 0.0 : cossigma - 2 * sinU1SinU2 / cos2Alpha; var u3 = cos2Alpha * squaredRatio; var cos2Sigmam2 = cos2Sigmam * cos2Sigmam; // eq. 3 a = 1.0 + u3 / 16384 * (4096 + u3 * (-768 + u3 * (320 - 175 * u3))); // eq. 4 var b = u3 / 1024 * (256 + u3 * (-128 + u3 * (74 - 47 * u3))); // eq. 6 deltasigma = b * sinsigma * (cos2Sigmam + b / 4 * (cossigma * (-1 + 2 * cos2Sigmam2) - b / 6 * cos2Sigmam * (-3 + 4 * sin2Sigma) * (-3 + 4 * cos2Sigmam2))); // eq. 10 var c = flattening / 16 * cos2Alpha * (4 + flattening * (4 - 3 * cos2Alpha)); // eq. 11 (modified) lambda = omega + (1 - c) * flattening * sinalpha * (sigma + c * sinsigma * (cos2Sigmam + c * cossigma * (-1 + 2 * cos2Sigmam2))); // see how much improvement we got var change = Math.Abs((lambda - lambda0) / lambda); if (i > 1 && change < Precision) { converged = true; break; } } // eq. 19 var s = minorAxis * a * (sigma - deltasigma); Angle alpha1; // didn't converge? must be N/S if (!converged) { if (phi1 > phi2) { alpha1 = Angle.Angle180; } else if (phi1 < phi2) { alpha1 = Angle.Zero; } else { alpha1 = new Angle(double.NaN); } } // else, it converged, so do the math else { alpha1 = new Angle(); // eq. 20 var radians = Math.Atan2(cosU2 * Math.Sin(lambda), cosU1SinU2 - sinU1CosU2 * Math.Cos(lambda)); if (radians.IsNegative()) { radians += TwoPi; } alpha1.Radians = radians; } if (alpha1 >= 360.0) { alpha1 -= 360.0; } return(new GeodeticCurve(this, s, alpha1)); }
/// <summary> /// Calculate the geodetic curve between two points on a specified reference ellipsoid. /// This is the solution to the inverse geodetic problem. /// </summary> /// <param name="ellipsoid">reference ellipsoid to use</param> /// <param name="start">starting coordinates</param> /// <param name="end">ending coordinates </param> /// <returns></returns> public GeodeticCurve CalculateGeodeticCurve(Ellipsoid ellipsoid, GlobalCoordinates start, GlobalCoordinates end) { // // All equation numbers refer back to Vincenty's publication: // See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf // // get constants double a = ellipsoid.SemiMajorAxis; double b = ellipsoid.SemiMinorAxis; double f = ellipsoid.Flattening; // get parameters as radians double phi1 = start.Latitude.Radians; double lambda1 = start.Longitude.Radians; double phi2 = end.Latitude.Radians; double lambda2 = end.Longitude.Radians; // calculations double a2 = a * a; double b2 = b * b; double a2b2b2 = (a2 - b2) / b2; double omega = lambda2 - lambda1; double tanphi1 = Math.Tan(phi1); double tanU1 = (1.0 - f) * tanphi1; double U1 = Math.Atan(tanU1); double sinU1 = Math.Sin(U1); double cosU1 = Math.Cos(U1); double tanphi2 = Math.Tan(phi2); double tanU2 = (1.0 - f) * tanphi2; double U2 = Math.Atan(tanU2); double sinU2 = Math.Sin(U2); double cosU2 = Math.Cos(U2); double sinU1sinU2 = sinU1 * sinU2; double cosU1sinU2 = cosU1 * sinU2; double sinU1cosU2 = sinU1 * cosU2; double cosU1cosU2 = cosU1 * cosU2; // eq. 13 double lambda = omega; // intermediates we'll need to compute 's' double A = 0.0; double B = 0.0; double sigma = 0.0; double deltasigma = 0.0; double lambda0; bool converged = false; for (int i = 0; i < 20; i++) { lambda0 = lambda; double sinlambda = Math.Sin(lambda); double coslambda = Math.Cos(lambda); // eq. 14 double sin2sigma = (cosU2 * sinlambda * cosU2 * sinlambda) + Math.Pow(cosU1sinU2 - sinU1cosU2 * coslambda, 2.0); double sinsigma = Math.Sqrt(sin2sigma); // eq. 15 double cossigma = sinU1sinU2 + (cosU1cosU2 * coslambda); // eq. 16 sigma = Math.Atan2(sinsigma, cossigma); // eq. 17 Careful! sin2sigma might be almost 0! double sinalpha = (sin2sigma == 0) ? 0.0 : cosU1cosU2 * sinlambda / sinsigma; double alpha = Math.Asin(sinalpha); double cosalpha = Math.Cos(alpha); double cos2alpha = cosalpha * cosalpha; // eq. 18 Careful! cos2alpha might be almost 0! double cos2sigmam = cos2alpha == 0.0 ? 0.0 : cossigma - 2 * sinU1sinU2 / cos2alpha; double u2 = cos2alpha * a2b2b2; double cos2sigmam2 = cos2sigmam * cos2sigmam; // eq. 3 A = 1.0 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175 * u2))); // eq. 4 B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47 * u2))); // eq. 6 deltasigma = B * sinsigma * (cos2sigmam + B / 4 * (cossigma * (-1 + 2 * cos2sigmam2) - B / 6 * cos2sigmam * (-3 + 4 * sin2sigma) * (-3 + 4 * cos2sigmam2))); // eq. 10 double C = f / 16 * cos2alpha * (4 + f * (4 - 3 * cos2alpha)); // eq. 11 (modified) lambda = omega + (1 - C) * f * sinalpha * (sigma + C * sinsigma * (cos2sigmam + C * cossigma * (-1 + 2 * cos2sigmam2))); // see how much improvement we got double change = Math.Abs((lambda - lambda0) / lambda); if ((i > 1) && (change < 0.0000000000001)) { converged = true; break; } } // eq. 19 double s = b * A * (sigma - deltasigma); Angle alpha1; Angle alpha2; // didn't converge? must be N/S if (!converged) { if (phi1 > phi2) { alpha1 = Angle.Angle180; alpha2 = Angle.Zero; } else if (phi1 < phi2) { alpha1 = Angle.Zero; alpha2 = Angle.Angle180; } else { alpha1 = new Angle(Double.NaN); alpha2 = new Angle(Double.NaN); } } // else, it converged, so do the math else { double radians; alpha1 = new Angle(); alpha2 = new Angle(); // eq. 20 radians = Math.Atan2(cosU2 * Math.Sin(lambda), (cosU1sinU2 - sinU1cosU2 * Math.Cos(lambda))); if (radians < 0.0) radians += TwoPi; alpha1.Radians = radians; // eq. 21 radians = Math.Atan2(cosU1 * Math.Sin(lambda), (-sinU1cosU2 + cosU1sinU2 * Math.Cos(lambda))) + Math.PI; if (radians < 0.0) radians += TwoPi; alpha2.Radians = radians; } if (alpha1 >= 360.0) alpha1 -= 360.0; if (alpha2 >= 360.0) alpha2 -= 360.0; return new GeodeticCurve(s, alpha1, alpha2); }
public Point(GlobalCoordinates _coordinate, double?_height) { coordinate = new GlobalCoordinates(_coordinate.Latitude, _coordinate.Longitude); height = _height; }
public Point(double lat, double lon, double?_height) { coordinate = new GlobalCoordinates(new Angle(lat), new Angle(lon)); height = _height; }
/// <summary> /// Compute the meridian convergence for a location /// </summary> /// <param name="point">The location defined by latitude/longitude</param> /// <returns>The meridian convergence</returns> public Angle MeridianConvergence(GlobalCoordinates point) { _ = ToUtmCoordinates(point, out _, out var meridianConvergence); return(Angle.RadToDeg(meridianConvergence)); }
public Point() { coordinate = new GlobalCoordinates(); height = null; }
/// <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> public double EuclidianDistance(GlobalCoordinates point1, GlobalCoordinates point2) { return(EuclidianDistance(ToEuclidian(point1), ToEuclidian(point2))); }
/// <summary> /// Convert a latitude/longitude coordinate to a Euclidian coordinate on a flat map /// </summary> /// <param name="coordinates">The latitude/longitude coordinates in degrees</param> /// <returns>The euclidian coordinates of that point</returns> public override EuclidianCoordinate ToEuclidian(GlobalCoordinates coordinates) { return(ToUtmCoordinates(coordinates, out _, out _)); }
private static GeoCoordinate ToGeoCoordinate(this GlobalCoordinates globalCoordinates) { return(new GeoCoordinate(globalCoordinates.Latitude.Degrees, globalCoordinates.Longitude.Degrees)); }
public void TestConstructor3() { var loc = new GlobalCoordinates(utm.MaxLatitude + 1.0, 0); Assert.ThrowsException <ArgumentOutOfRangeException>(() => new UtmGrid(utm, loc)); }
/// <summary> /// sets filter value /// all filters should operate on global space /// gc = global filter space /// </summary> public void SetGlobalValue(int x, int z, float value, bool overwrite, GlobalCoordinates gc) { gc.SetValue(x, z, value, overwrite); }
/// <summary> /// Calculate the destination and final bearing after traveling a specified /// distance, and a specified starting bearing, for an initial location. /// This is the solution to the direct geodetic problem. /// </summary> /// <param name="start">starting location</param> /// <param name="startBearing">starting bearing (degrees)</param> /// <param name="distance">distance to travel (meters)</param> /// <param name="endBearing">bearing at destination (degrees)</param> /// <returns>The coordinates of the final location of the traveling</returns> /// <exception cref="ArgumentOutOfRangeException"></exception> public GlobalCoordinates CalculateEndingGlobalCoordinates( GlobalCoordinates start, Angle startBearing, double distance, out Angle endBearing) { var majorAxis = ReferenceGlobe.SemiMajorAxis; var minorAxis = ReferenceGlobe.SemiMinorAxis; var aSquared = majorAxis * majorAxis; var bSquared = minorAxis * minorAxis; var flattening = ReferenceGlobe.Flattening; var phi1 = start.Latitude.Radians; var alpha1 = startBearing.Radians; var cosAlpha1 = Math.Cos(alpha1); var sinAlpha1 = Math.Sin(alpha1); var s = distance; var tanU1 = (1.0 - flattening) * Math.Tan(phi1); var cosU1 = 1.0 / Math.Sqrt(1.0 + tanU1 * tanU1); var sinU1 = tanU1 * cosU1; if (Math.Sign(distance) < 0) { throw new ArgumentOutOfRangeException(Properties.Resources.NEGATIVE_DISTANCE); } // eq. 1 var sigma1 = Math.Atan2(tanU1, cosAlpha1); // eq. 2 var sinAlpha = cosU1 * sinAlpha1; var sin2Alpha = sinAlpha * sinAlpha; var cos2Alpha = 1 - sin2Alpha; var uSquared = cos2Alpha * (aSquared - bSquared) / bSquared; // eq. 3 var a = 1 + uSquared / 16384 * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared))); // eq. 4 var b = uSquared / 1024 * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared))); // iterate until there is a negligible change in sigma double sinSigma; double sigmaM2; double cosSigmaM2; double cos2SigmaM2; var sOverbA = s / (minorAxis * a); var sigma = sOverbA; var prevSigma = sOverbA; for (; ;) { // eq. 5 sigmaM2 = 2.0 * sigma1 + sigma; cosSigmaM2 = Math.Cos(sigmaM2); cos2SigmaM2 = cosSigmaM2 * cosSigmaM2; sinSigma = Math.Sin(sigma); var cosSignma = Math.Cos(sigma); // eq. 6 var deltaSigma = b * sinSigma * (cosSigmaM2 + b / 4.0 * (cosSignma * (-1 + 2 * cos2SigmaM2) - b / 6.0 * cosSigmaM2 * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM2))); // eq. 7 sigma = sOverbA + deltaSigma; // break after converging to tolerance if (sigma.IsApproximatelyEqual(prevSigma, Precision)) { break; } prevSigma = sigma; } sigmaM2 = 2.0 * sigma1 + sigma; cosSigmaM2 = Math.Cos(sigmaM2); cos2SigmaM2 = cosSigmaM2 * cosSigmaM2; var cosSigma = Math.Cos(sigma); sinSigma = Math.Sin(sigma); // eq. 8 var phi2 = Math.Atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1, (1.0 - flattening) * Math.Sqrt(sin2Alpha + Math.Pow(sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1, 2.0))); // eq. 9 // This fixes the pole crossing defect spotted by Matt Feemster. When a path // passes a pole and essentially crosses a line of latitude twice - once in // each direction - the longitude calculation got messed up. Using Atan2 // instead of Atan fixes the defect. The change is in the next 3 lines. //double tanLambda = sinSigma * sinAlpha1 / (cosU1 * cosSigma - sinU1*sinSigma*cosAlpha1); //double lambda = Math.Atan(tanLambda); var lambda = Math.Atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1); // eq. 10 var c = flattening / 16 * cos2Alpha * (4 + flattening * (4 - 3 * cos2Alpha)); // eq. 11 var l = lambda - (1 - c) * flattening * sinAlpha * (sigma + c * sinSigma * (cosSigmaM2 + c * cosSigma * (-1 + 2 * cos2SigmaM2))); // eq. 12 var alpha2 = Math.Atan2(sinAlpha, -sinU1 * sinSigma + cosU1 * cosSigma * cosAlpha1); // build result var latitude = new Angle(); var longitude = new Angle(); latitude.Radians = phi2; longitude.Radians = start.Longitude.Radians + l; endBearing = Angle.Zero; endBearing.Radians = alpha2; return(new GlobalCoordinates(latitude, longitude)); }
public void TestConstructor3() { var loc = new GlobalCoordinates(utm.MaxLatitude + 1.0, 0); var g = new UtmGrid(utm, loc); }
/// <summary> /// Calculate the destination after traveling a specified distance, and a /// specified starting bearing, for an initial location. This is the /// solution to the direct geodetic problem. /// </summary> /// <param name="ellipsoid">reference ellipsoid to use</param> /// <param name="start">starting location</param> /// <param name="startBearing">starting bearing (degrees)</param> /// <param name="distance">distance to travel (meters)</param> /// <returns></returns> public GlobalCoordinates CalculateEndingGlobalCoordinates(Ellipsoid ellipsoid, GlobalCoordinates start, Angle startBearing, double distance) { Angle endBearing = new Angle(); return CalculateEndingGlobalCoordinates(ellipsoid, start, startBearing, distance, out endBearing); }
public void TestAntiPodal2() { // instantiate the calculator GeodeticCalculator geoCalc = new GeodeticCalculator(); // select a reference elllipsoid Ellipsoid reference = Ellipsoid.WGS84; // set position 1 GlobalCoordinates p1; p1 = new GlobalCoordinates(11, 80); // set position 2 GlobalCoordinates p2; p2 = new GlobalCoordinates(-10, -100); // calculate the geodetic measurement GeodeticCurve geoCurve; geoCurve = geoCalc.CalculateGeodeticCurve(reference, p1, p2); Assert.AreEqual(19893320.272061437, geoCurve.EllipsoidalDistance, 0.001); Assert.AreEqual(360.0, geoCurve.Azimuth.Degrees, 0.0000001); Assert.AreEqual(0.0, geoCurve.ReverseAzimuth.Degrees, 0.0000001); }
/// <summary> /// Calculate the destination and final bearing after traveling a specified /// distance, and a specified starting bearing, for an initial location. /// This is the solution to the direct geodetic problem. /// </summary> /// <param name="ellipsoid">reference ellipsoid to use</param> /// <param name="start">starting location</param> /// <param name="startBearing">starting bearing (degrees)</param> /// <param name="distance">distance to travel (meters)</param> /// <param name="endBearing">bearing at destination (degrees)</param> /// <returns></returns> public GlobalCoordinates CalculateEndingGlobalCoordinates(Ellipsoid ellipsoid, GlobalCoordinates start, Angle startBearing, double distance, out Angle endBearing) { double a = ellipsoid.SemiMajorAxis; double b = ellipsoid.SemiMinorAxis; double aSquared = a * a; double bSquared = b * b; double f = ellipsoid.Flattening; double phi1 = start.Latitude.Radians; double alpha1 = startBearing.Radians; double cosAlpha1 = Math.Cos(alpha1); double sinAlpha1 = Math.Sin(alpha1); double s = distance; double tanU1 = (1.0 - f) * Math.Tan(phi1); double cosU1 = 1.0 / Math.Sqrt(1.0 + tanU1 * tanU1); double sinU1 = tanU1 * cosU1; // eq. 1 double sigma1 = Math.Atan2(tanU1, cosAlpha1); // eq. 2 double sinAlpha = cosU1 * sinAlpha1; double sin2Alpha = sinAlpha * sinAlpha; double cos2Alpha = 1 - sin2Alpha; double uSquared = cos2Alpha * (aSquared - bSquared) / bSquared; // eq. 3 double A = 1 + (uSquared / 16384) * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared))); // eq. 4 double B = (uSquared / 1024) * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared))); // iterate until there is a negligible change in sigma double deltaSigma; double sOverbA = s / (b * A); double sigma = sOverbA; double sinSigma; double prevSigma = sOverbA; double sigmaM2; double cosSigmaM2; double cos2SigmaM2; for (; ; ) { // eq. 5 sigmaM2 = 2.0 * sigma1 + sigma; cosSigmaM2 = Math.Cos(sigmaM2); cos2SigmaM2 = cosSigmaM2 * cosSigmaM2; sinSigma = Math.Sin(sigma); double cosSignma = Math.Cos(sigma); // eq. 6 deltaSigma = B * sinSigma * (cosSigmaM2 + (B / 4.0) * (cosSignma * (-1 + 2 * cos2SigmaM2) - (B / 6.0) * cosSigmaM2 * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM2))); // eq. 7 sigma = sOverbA + deltaSigma; // break after converging to tolerance if (Math.Abs(sigma - prevSigma) < 0.0000000000001) break; prevSigma = sigma; } sigmaM2 = 2.0 * sigma1 + sigma; cosSigmaM2 = Math.Cos(sigmaM2); cos2SigmaM2 = cosSigmaM2 * cosSigmaM2; double cosSigma = Math.Cos(sigma); sinSigma = Math.Sin(sigma); // eq. 8 double phi2 = Math.Atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1, (1.0 - f) * Math.Sqrt(sin2Alpha + Math.Pow(sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1, 2.0))); // eq. 9 // This fixes the pole crossing defect spotted by Matt Feemster. When a path // passes a pole and essentially crosses a line of latitude twice - once in // each direction - the longitude calculation got messed up. Using Atan2 // instead of Atan fixes the defect. The change is in the next 3 lines. //double tanLambda = sinSigma * sinAlpha1 / (cosU1 * cosSigma - sinU1*sinSigma*cosAlpha1); //double lambda = Math.Atan(tanLambda); double lambda = Math.Atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1); // eq. 10 double C = (f / 16) * cos2Alpha * (4 + f * (4 - 3 * cos2Alpha)); // eq. 11 double L = lambda - (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cosSigmaM2 + C * cosSigma * (-1 + 2 * cos2SigmaM2))); // eq. 12 double alpha2 = Math.Atan2(sinAlpha, -sinU1 * sinSigma + cosU1 * cosSigma * cosAlpha1); // build result Angle latitude = new Angle(); Angle longitude = new Angle(); latitude.Radians = phi2; longitude.Radians = start.Longitude.Radians + L; endBearing = new Angle(); endBearing.Radians = alpha2; return new GlobalCoordinates(latitude, longitude); }
/// <summary> /// returns filter value on given local coordiantes (0 if not defined) /// localFilter = filter type /// </summary> public float GetLocalValue(int x, int z, GlobalCoordinates gc) { float value = localCoordinates.GetLocalValue(x, z, gc); if (value != 666) return value; else return 0; }
public void AssignFunctions(LocalTerrain lt, FunctionMathCalculator fmc, GlobalCoordinates globalFilterGaussianC) { this.lt = lt; this.fmc = fmc; this.globalFilterGaussianC = globalFilterGaussianC; }
public GlobalTerrain(int quadrantSize) { globalTerrainC = new GlobalCoordinates(quadrantSize); }
/// <summary> /// Get the Mercator scale factor for the given point /// </summary> /// <param name="point">The point</param> /// <returns>The scale factor</returns> public override double ScaleFactor(GlobalCoordinates point) { _ = ToUtmCoordinates(point, out var scaleFactor, out _); return(scaleFactor); }
/// <summary> /// maps given local coordinates to global /// returns value on given coordinates /// 666 if not defined /// </summary> public float GetLocalValue(int x, int z, GlobalCoordinates gc) { //Debug.Log("getting " + x + "," + z); //Debug.Log("= " + (x + (int)center.x - terrainWidth) + "," + (z + (int)center.z - terrainHeight / 2)); return gc.GetValue(x + (int)center.x - terrainWidth / 2, z + (int)center.z - terrainHeight / 2); }