// Input argument: the center of the projection public GnomonicProjection(Dictionary <String, double> parameters) : base(parameters) { _center = SpatialUtil.SphericalRadToCartesian(InputLatitude("latitude1", 90), InputLongitude("longitude1", 360)); // This projection is designed for numerical computations rather than cartography. // The choice of coordinate basis for the tangent plane - which affects the // orientation of the projection in the xy plane - is optimized for accuracy rather // than good looks. The first basis vector is obtained by dropping the smallest coordinate, // switching the other two, and flipping the sign of one of them. The second one is // obtained by cross product. double[] center = { _center.X, _center.Y, _center.Z }; var vector = new double[3]; var k = GetMinEntry(center); var j = (k + 2) % 3; var i = (j + 2) % 3; vector[i] = -center[j]; vector[j] = center[i]; vector[k] = 0; _xAxis = new Vector3(vector[0], vector[1], vector[2]).Unitize(); _yAxis = _center.CrossProduct(_xAxis); }
protected internal override void Unproject(double x, double y, out double latitude, out double longitude) { var vector = _center + _xAxis * x + _yAxis * y; latitude = SpatialUtil.Latitude(vector); longitude = SpatialUtil.Longitude(vector); }
/// <summary> /// Calculates the offset distance. /// </summary> /// <param name="offset">The offset.</param> /// <param name="offsetBearing"></param> /// <param name="offsetAngle"></param> private static double CalculateOffsetDistance(double offset, double offsetBearing, double offsetAngle) { // offset / (SIN(RADIANS(((OffsetBearing - OffsetAngleLeft) + 360) % 360))) var denominator = (Math.Sin(SpatialUtil.ToRadians(((offsetBearing - offsetAngle) + 360) % 360))); return(offset / denominator); }
public static double InputLong(double longDeg, double max, string name) { if (double.IsNaN(longDeg) || longDeg < -max || longDeg > max) { throw new ArgumentOutOfRangeException(nameof(longDeg), string.Format(CultureInfo.InvariantCulture, Resource.InputLongitudeIsOutOfRange, longDeg, max)); } return(NormalizeLongitudeRad(SpatialUtil.ToRadians(longDeg))); }
public static double InputLat(double latDeg, double max, string name) { if (double.IsNaN(latDeg) || latDeg < -max || latDeg > max) { throw new ArgumentOutOfRangeException(name, string.Format(CultureInfo.InvariantCulture, Resource.InputLatitudeIsOutOfRange, latDeg, max)); } return(Clamp(Math.PI / 2, SpatialUtil.ToRadians(latDeg))); }
/// <summary> /// Gets the second point radian. /// </summary> /// <param name="nextPoint">The next point.</param> /// <param name="middlePoint">The middle point.</param> /// <returns></returns> private double GetSecondPointRadian(LRSPoint nextPoint, LRSPoint middlePoint) { var atan = GetAtanInDegree(middlePoint, nextPoint); atan = 90 - atan; atan = atan <= 0 ? 360 + atan : atan; return(SpatialUtil.ToRadians(180 - atan)); }
/// <summary> /// Gets the first point radian. /// </summary> /// <param name="previousPoint">The previous point.</param> /// <param name="middlePoint">The middle point.</param> /// <returns></returns> private double GetFirstPointRadian(LRSPoint previousPoint, LRSPoint middlePoint) { var atan = GetAtanInDegree(middlePoint, previousPoint); atan = 90 - atan; atan = atan <= 0 ? 360 + atan : atan; return(SpatialUtil.ToRadians(360 - atan)); }
public static AffineTransform Rotate(double angleDeg) { var angle = SpatialUtil.ToRadians(angleDeg); var transform = new AffineTransform { _ax = Math.Cos(angle), _ay = Math.Sin(angle) }; transform._bx = -transform._ay; transform._by = transform._ax; return(transform); }
/// <summary> /// Gets the parallel point. /// </summary> /// <returns>Point parallel to the current point.</returns> private LRSPoint GetParallelPoint() { var newX = X + (OffsetDistance * Math.Cos(SpatialUtil.ToRadians(90 - _offsetAngle))); var newY = Y + (OffsetDistance * Math.Sin(SpatialUtil.ToRadians(90 - _offsetAngle))); return(new LRSPoint( newX, newY, null, M, _srid )); }
public void AddLine(double latitude, double longitude, double?z, double?m) { // Transforming from geodetic coordinates to a unit vector. var endPoint = SpatialUtil.SphericalDegToCartesian(latitude, longitude); var angle = endPoint.Angle(_startPoint); if (angle > MinAngle) { // _startPoint and endPoint are the unit vectors that correspond to the input // start and end points. In their 3D space we operate in a local coordinate system // where _startPoint is the x axis and the xy plane contains endPoint. Every // point is now generated from the previous one by a fixed rotation in the local // xy plane, and converted back to geodetic coordinates. // Construct the local z and y axes. var zAxis = (_startPoint + endPoint).CrossProduct(_startPoint - endPoint).Unitize(); var yAxis = (_startPoint).CrossProduct(zAxis); // Calculating how many points we need. var count = Convert.ToInt32(Math.Ceiling(angle / SpatialUtil.ToRadians(_angle))); // Scaling the angle so that points are equally placed. var exactAngle = angle / count; var cosine = Math.Cos(exactAngle); var sine = Math.Sin(exactAngle); // Setting the first x and y points in our local coordinate system. var x = cosine; var y = sine; for (var i = 0; i < count - 1; i++) { var newPoint = (_startPoint * x + yAxis * y).Unitize(); // Adding the point. _sink.AddLine(SpatialUtil.LatitudeDeg(newPoint), SpatialUtil.LongitudeDeg(newPoint), null, null); // Rotating to get next point. var r = x * cosine - y * sine; y = x * sine + y * cosine; x = r; } } _sink.AddLine(latitude, longitude, z, m); // Remembering last point we added. _startPoint = endPoint; }
protected internal override void Project(double latitude, double longitude, out double x, out double y) { var vector = SpatialUtil.SphericalRadToCartesian(latitude, longitude); var r = vector * _center; if (r < _tolerance) { throw new ArgumentOutOfRangeException(nameof(latitude), "Input point is too far away from the center of projection."); } vector = vector / r; x = vector * _xAxis; y = vector * _yAxis; }
private static GameEffectWorldMethod CreateMethod_SpawnMinionThrow(string actorDefId, int level, float range, float amount) { return(delegate(EffectContext context) { Actor sourceActor = context.sourceActor; WeaponBody sourceWeapon = context.sourceWeapon; if (!LazySingletonBehavior <NetworkManager> .Instance.IsSimulationServer) { return; } SpawnMinions spawnMinions = sourceWeapon as SpawnMinions; for (int i = 0; i < (int)amount; i++) { Vector3 zero = Vector3.zero; Quaternion rotation = sourceActor.Rotation; if (!SpatialUtil.TryFindRandomSpotCircle(context.hitPoint, context.Radius, range, sourceActor.Height, out zero)) { Debug.Log("Couln't find valid spawn spot"); } else { LazySingletonBehavior <ActorManager> .Instance.Spawn(actorDefId, level, Actor.Faction.Player, /*context.hitPoint*/ zero, /*context.hitRot*/ rotation, delegate(Actor actor) { if (spawnMinions != null && spawnMinions.minionPrefab != null) { GameObject gameObject = spawnMinions.minionPrefab.Spawn(actor.transform); Minion component = gameObject.GetComponent <Minion>(); if (component != null) { spawnMinions.AttachMinion(component); } } Debug.Log(string.Concat(new object[] { "Spawned ", actor.DebugName, " at ", actor.transform.position }), actor); }); } } }); }
/// <summary> /// Gets the deviation angle of 3 points. /// </summary> /// <param name="pointA">The point a.</param> /// <param name="pointO">The point o.</param> /// <param name="pointB">The point b.</param> /// <param name="isNegativeOffset">if set to <c>true</c> [is negative offset].</param> /// <returns></returns> private double GetAOBAngle(LRSPoint pointA, LRSPoint pointO, LRSPoint pointB, bool isNegativeOffset) { const double angleCorrection = Math.PI / 2; const double angleConversion = 2 * Math.PI; var atanAo = pointA.GetAtanInRadian(pointO) + angleCorrection; var atanBo = pointB.GetAtanInRadian(pointO) + angleCorrection; // angle conversion atanAo = SpatialUtil.ToDegrees(atanAo <= 0 ? angleConversion + atanAo : atanAo); atanBo = SpatialUtil.ToDegrees(atanBo <= 0 ? angleConversion + atanBo : atanBo); var deviationAngle = 360 - (atanAo > atanBo ? 360 - (atanAo - atanBo) : atanBo - atanAo); // for positive offset; offset curve will be to the left of input geom; // so for positive deviation angle the computed angle should be subtracted from 360 // for negative offset; offset curve will be to the right of input geom return(isNegativeOffset ? deviationAngle : 360 - deviationAngle); }
// Angle in degrees between vectors a and b. public double AngleInDegrees(Vector3 a) { return(SpatialUtil.ToDegrees(Angle(a))); }
/// <summary> /// Gets the atan2 in degrees. /// This does angle correct when atan2 value is negative /// </summary> /// <param name="point1">The point1.</param> /// <param name="point2">The point2.</param> /// <returns>Atan2 in degrees</returns> private double GetAtanInDegree(LRSPoint point1, LRSPoint point2) { var atan = point1.GetAtanInRadian(point2); return(SpatialUtil.ToDegrees(atan <= 0 ? (2 * Math.PI) + atan : atan)); }
/// <summary> /// Find the point that is the given distance from the start point in the direction of the end point. /// The distance must be less than the distance between these two points. /// </summary> /// <param name="start">Start Geography Point</param> /// <param name="end">End Geography Point</param> /// <param name="distance">Distance at which the point to be located</param> /// <returns></returns> public static SqlGeography InterpolateBetweenGeog(SqlGeography start, SqlGeography end, double distance) { // We need to check a few prerequisite. // We only operate on points. if (!start.IsPoint() || !end.IsPoint()) { throw new ArgumentException(ErrorMessage.PointCompatible); } // The SRIDs also have to match var srid = start.STSrid.Value; if (srid != end.STSrid.Value) { throw new ArgumentException(ErrorMessage.SRIDCompatible); } // Finally, the distance has to fall between these points. var length = start.STDistance(end).Value; if (distance > length) { throw new ArgumentException(ErrorMessage.DistanceMustBeBetweenTwoPoints); } if (distance < 0) { throw new ArgumentException(ErrorMessage.DistanceMustBePositive); } // We'll just do this by binary search---surely this could be more efficient, // but this is relatively easy. // // Note that we can't just take the take the linear combination of end vectors because we // aren't working on a sphere. // We are going to do our binary search using 3D Cartesian values, however var startCart = SpatialUtil.GeographicToCartesian(start); var endCart = SpatialUtil.GeographicToCartesian(end); SqlGeography current; double currentDistance; // Keep refining until we slip below the THRESHOLD value. do { var currentCart = (startCart + endCart) / 2; current = SpatialUtil.CartesianToGeographic(currentCart, srid); currentDistance = start.STDistance(current).Value; if (distance <= currentDistance) { endCart = currentCart; } else { startCart = currentCart; } } while (Math.Abs(currentDistance - distance) > Constants.Tolerance); return(current); }
public void BeginFigure(double latitude, double longitude, double?z, double?m) { // Starting the figure, remembering the vector that corresponds to the first point. _startPoint = SpatialUtil.SphericalDegToCartesian(latitude, longitude); _sink.BeginFigure(latitude, longitude, z, m); }
/// <summary> /// Calculates the offset bearing. /// </summary> /// <param name="nextPoint">The next point.</param> private double CalculateOffsetBearing(LRSPoint nextPoint) { _angle = SpatialUtil.ToDegrees(GetAtanInRadian(nextPoint)); return((90 - _angle + 360) % 360); }