public static Polygon CreateEuclidean(int n, Vector3D p1, Vector3D p2, Vector3D normal) { List <Vector3D> polyPoints = new List <Vector3D>(); double centralAngle = 2 * Math.PI / n; Vector3D direction = p2 - p1; direction.RotateAboutAxis(normal, Math.PI / 2); direction.Normalize(); double dist = ((p2 - p1).Abs() / 2) / Math.Tan(Math.PI / n); Vector3D center = p1 + (p2 - p1) / 2 + direction * dist; for (int i = 0; i < n; i++) { Vector3D v = p1 - center; v.RotateAboutAxis(normal, centralAngle * i); v += center; polyPoints.Add(v); } Polygon poly = new Polygon(); poly.CreateEuclidean(polyPoints.ToArray()); return(poly); }
/// <summary> /// Returns the cotangent of the specified angle. /// Returns <see cref="double.NegativeInfinity" /> if angle is a multiple of +π or +2π. /// Returns <see cref="double.PositiveInfinity" /> if 0 or angle is a multiple of -π or -2π. /// </summary> /// <param name="radians">The angle in radians.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Double.</returns> public static double Cot(double radians, double tolerance = Numbers.ZeroTolerance) { if (NMath.Abs(radians).IsZeroSign()) { return(double.PositiveInfinity); } if (radians.IsEqualTo(Numbers.Pi, tolerance)) { return(double.NegativeInfinity); } // 180 deg if (radians.IsEqualTo(Numbers.TwoPi, tolerance)) { return(double.NegativeInfinity); } // 360 deg if (radians.IsEqualTo(-Numbers.Pi, tolerance)) { return(double.PositiveInfinity); } // -180 deg if (radians.IsEqualTo(-Numbers.TwoPi, tolerance)) { return(double.PositiveInfinity); } // -360 deg return(1d / NMath.Tan(radians)); }
/// <summary> /// Calculates distance/bearing between two geographic locations on Rhumb line (loxodrome) /// </summary> /// <param name="origin">origin location in geographic degrees</param> /// <param name="destination">destination location in geographic degrees</param> /// <param name="radius">radius of a geographic sphere, in kilometers</param> /// <remarks>radius defaults to Earth's mean radius</remarks> public static GeoRhumb GetRhumb(GeoPoint origin, GeoPoint destination, double radius = GeoGlobal.Earths.Radius) { origin = origin.ToRadians(); destination = destination.ToRadians(); var dLat = (destination.Latitude - origin.Latitude); var dLon = (destination.Longitude - origin.Longitude); var tDestination = Math.Tan(Math.PI / 4 + destination.Latitude / 2); var tOrigin = Math.Tan(Math.PI / 4 + origin.Latitude / 2); var dPhi = Math.Log(tDestination / tOrigin); // E-W line gives dPhi=0 var q = (IsFinite(dLat / dPhi)) ? dLat / dPhi : Math.Cos(origin.Latitude); // if dLon over 180° take shorter Rhumb across anti-meridian: if (Math.Abs(dLon) > Math.PI) { dLon = dLon > 0 ? -(2 * Math.PI - dLon) : (2 * Math.PI + dLon); } var distance = Math.Sqrt(dLat * dLat + q * q * dLon * dLon) * radius; var bearing = Math.Atan2(dLon, dPhi); return(new GeoRhumb { Distance = distance, Bearing = bearing.ToDegreesNormalized() }); }
/// <summary> /// Handles the calculation for cotangent. /// </summary> /// <param name="x">A double to be evaluated.</param> /// <returns>Return the cotangent of an angle specified in radians.</returns> public static double Cotangent(double x) { if (MathObj.Tan(x) == 0) { return(-2); } return(1 / MathObj.Tan(x)); }
public static MyLodStrategyPreprocessor Perform() { const float REFERENCE_HORIZONTAL_FOV = 70; const float REFERENCE_RESOLUTION_HEIGHT = 1080; float fovCoefficient = (float)(Math.Tan(MyRender11.Environment.Matrices.FovH / 2) / Math.Tan(MathHelper.ToRadians(REFERENCE_HORIZONTAL_FOV) / 2)); float resolutionCoefficient = REFERENCE_RESOLUTION_HEIGHT / (float)MyRender11.ViewportResolution.Y; return(new MyLodStrategyPreprocessor(fovCoefficient * resolutionCoefficient)); }
/// <summary> /// Assumes we are in the UHS model. /// Normal to the input sphere means we are along an arc orthogonal to that sphere. /// </summary> private static System.Tuple <Vector3D, Vector3D> Thicken(Vector3D v, Sphere normal) { if (Tolerance.Zero(v.Z)) { Sphere s = SphereFuncUHS(v); Vector3D direction = v - normal.Center; direction.Normalize(); direction *= s.Radius; return(new System.Tuple <Vector3D, Vector3D>(v + direction, v - direction)); } else { // We need to get the circle orthogonal to "normal" and z=0 and passing through v. // v is on normal. Vector3D z = new Vector3D(0, 0, -1); Vector3D hypot = normal.Center - v; double angle = hypot.AngleTo(z); double d2 = v.Z / Math.Tan(angle); Vector3D cen = v; cen.Z = 0; Vector3D direction = cen - normal.Center; direction.Normalize(); direction *= d2; cen += direction; double rad = v.Dist(cen); Vector3D n = direction; n.Normalize(); n.RotateXY(Math.PI / 2); // Sphere with non-euclidean center v; Sphere s = SphereFuncUHS(v); // Two points where this sphere intersects circle. var result = s.Intersection(new Circle3D() { Center = cen, Radius = rad, Normal = n }); // Our artificial thickening can cause this when s is too big relative to the circle. // In this case, we are very close to the boundary, so we can do a different calc. if (result == null) { direction = v - normal.Center; direction.Normalize(); direction *= s.Radius; result = new System.Tuple <Vector3D, Vector3D>(v + direction, v - direction); } return(result); } }
public static Matrix3x2 CreateSkew(float radiansX, float radiansY) { Matrix3x2 result; float xTan = (float)SM.Tan(radiansX); float yTan = (float)SM.Tan(radiansY); result.M11 = 1.0f; result.M12 = yTan; result.M21 = xTan; result.M22 = 1.0f; result.M31 = 0.0f; result.M32 = 0.0f; return(result); }
/// <summary> /// NOTE: Not general, and assumes some things we know about this problem domain, /// e.g. that c1 and c2 live on the same sphere of radius 1, and have two intersection points. /// </summary> public static void IntersectionCircleCircle(Vector3D sphereCenter, Circle3D c1, Circle3D c2, out Vector3D i1, out Vector3D i2) { // Spherical analogue of our flat circle-circle intersection. // Spherical pythagorean theorem for sphere where r=1: cos(hypt) = cos(A)*cos(B) Circle3D clone1 = c1.Clone(), clone2 = c2.Clone(); //clone1.Center -= sphereCenter; //clone2.Center -= sphereCenter; // Great circle (denoted by normal vector), and distance between the centers. Vector3D gc = clone2.Normal.Cross(clone1.Normal); double d = clone2.Normal.AngleTo(clone1.Normal); double r1 = clone1.Normal.AngleTo(clone1.PointOnCircle); double r2 = clone2.Normal.AngleTo(clone2.PointOnCircle); // Calculate distances we need. So ugly! // http://www.wolframalpha.com/input/?i=cos%28r1%29%2Fcos%28r2%29+%3D+cos%28x%29%2Fcos%28d-x%29%2C+solve+for+x double t1 = Math.Pow(Math.Tan(d / 2), 2); double t2 = Math.Cos(r1) / Math.Cos(r2); double t3 = Math.Sqrt((t1 + 1) * (t1 * t2 * t2 + 2 * t1 * t2 + t1 + t2 * t2 - 2 * t2 + 1)) - 2 * t1 * t2; double x = 2 * Math.Atan(t3 / (t1 * t2 + t1 - t2 + 1)); double y = Math.Acos(Math.Cos(r1) / Math.Cos(x)); i1 = clone1.Normal; i1.RotateAboutAxis(gc, x); i2 = i1; // Perpendicular to gc through i1. Vector3D gc2 = i1.Cross(gc); i1.RotateAboutAxis(gc2, y); i2.RotateAboutAxis(gc2, -y); i1 += sphereCenter; i2 += sphereCenter; /* * // It would be nice to do the spherical analogue of circle-circle intersections, like here: * // http://mathworld.wolfram.com/Circle-CircleIntersection.html * // But I don't want to jump down that rabbit hole and am going to sacrifice some speed to use * // my existing euclidean function. * * // Stereographic projection to the plane. XXX - Crap, circles may become lines, and this isn't being handled well. * Circle3D c1Plane = H3Models.BallToUHS( clone1 ); * Circle3D c2Plane = H3Models.BallToUHS( clone2 ); * if( 2 != Euclidean2D.IntersectionCircleCircle( c1Plane.ToFlatCircle(), c2Plane.ToFlatCircle(), out i1, out i2 ) ) * throw new System.Exception( "Expected two intersection points" ); * i1 = H3Models.UHSToBall( i1 ); i1 += sphereCenter; * i2 = H3Models.UHSToBall( i2 ); i2 += sphereCenter; */ }
/// <summary> /// Returns the tangent of the specified angle. /// Returns <see cref="double.NegativeInfinity" /> if angle is a multiple of -π/2 or -(3/2)*π. /// Returns <see cref="double.PositiveInfinity" /> if angle is a multiple of +π/2 or +(3/2)*π. /// </summary> /// <param name="radians">The angle in radians.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>System.Double.</returns> public static double Tan(double radians, double tolerance = Numbers.ZeroTolerance) { if (radians.IsEqualTo(Numbers.PiOver2, tolerance) || radians.IsEqualTo(3 * Numbers.PiOver2, tolerance)) { return(double.PositiveInfinity); } // 90 deg if (radians.IsEqualTo(-Numbers.PiOver2, tolerance) || radians.IsEqualTo(-3 * Numbers.PiOver2, tolerance)) { return(double.NegativeInfinity); } // -90 deg return(NMath.Tan(radians)); }
public static Matrix3x2 CreateSkew(float radiansX, float radiansY, Vector2 centerPoint) { Matrix3x2 result; float xTan = (float)SM.Tan(radiansX); float yTan = (float)SM.Tan(radiansY); float tx = -centerPoint.Y * xTan; float ty = -centerPoint.X * yTan; result.M11 = 1.0f; result.M12 = yTan; result.M21 = xTan; result.M22 = 1.0f; result.M31 = tx; result.M32 = ty; return(result); }
public Camera(Vec3 p_lookFrom, Vec3 p_lookAt, Vec3 p_upVector, double p_verticalFieldOfView, double p_aspectRatio, double p_aperture, double p_focalLength) { ApertureRadius = p_aperture / 2; var theta = p_verticalFieldOfView * Math.PI / 180; var halfHeight = Math.Tan(theta / 2); var halfWidth = p_aspectRatio * halfHeight; Origin = p_lookFrom; W = Vec3.GetUnitVector(p_lookFrom - p_lookAt); U = Vec3.GetUnitVector(Vec3.GetCrossProduct(p_upVector, W)); V = Vec3.GetCrossProduct(W, U); LowerLeftCorner = Origin - halfWidth * p_focalLength * U - halfHeight * p_focalLength * V - p_focalLength * W; HorizontalSize = 2 * halfWidth * p_focalLength * U; VerticalSize = 2 * halfHeight * p_focalLength * V; }
/// <summary> /// Helper to project points from S3 -> S2, then add an associated curve. /// </summary> private static void ProjectAndAddS3Points(Shapeways mesh, Vector3D[] pointsS3, bool shrink) { // Project to S3, then to R3. List <Vector3D> projected = new List <Vector3D>(); foreach (Vector3D v in pointsS3) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe(1.0); // Pull R3 into a smaller open disk. if (shrink) { double mag = Math.Atan(c.Abs()); c.Normalize(); c *= mag; } projected.Add(c); } System.Func <Vector3D, double> sizeFunc = v => { // Constant thickness. // return 0.08; double sphericalThickness = 0.002; double abs = v.Abs(); if (shrink) { abs = Math.Tan(abs); // The unshrunk abs. } // The thickness at this vector location. double result = Spherical2D.s2eNorm(Spherical2D.e2sNorm(abs) + sphericalThickness) - abs; if (shrink) { result *= Math.Atan(abs) / abs; // shrink it back down. } return(result); }; mesh.AddCurve(projected.ToArray(), sizeFunc); }
// Cotangent public static double Cotan(double x) { return(1 / MathObj.Tan(x)); }
public static double Tan(object self, double x) { return(SM.Tan(x)); }
public static float Tan(float rad) { return((float)SMath.Tan(rad)); }
public static double Tan(object self, [DefaultProtocol] double x) { return(SM.Tan(x)); }
private static int Math_Tan(ILuaState lua) { lua.PushNumber(Math.Tan(lua.L_CheckNumber(1))); return(1); }
s2eNorm(double sNorm) { //if( double.IsNaN( sNorm ) ) // return 1.0; return(Math.Tan(.5 * sNorm)); }
public void CreateRegular(int numSides, int q) { int p = numSides; Segments.Clear(); List <Vector3D> points = new List <Vector3D>(); Geometry g = Geometry2D.GetGeometry(p, q); double circumRadius = Geometry2D.GetNormalizedCircumRadius(p, q); double angle = 0; for (int i = 0; i < p; i++) { Vector3D point = new Vector3D(); point.X = (circumRadius * Math.Cos(angle)); point.Y = (circumRadius * Math.Sin(angle)); points.Add(point); angle += Utils.DegreesToRadians(360.0 / p); } // Turn this into segments. for (int i = 0; i < points.Count; i++) { int idx1 = i; int idx2 = i == points.Count - 1 ? 0 : i + 1; Segment newSegment = new Segment(); newSegment.P1 = points[idx1]; newSegment.P2 = points[idx2]; if (g != Geometry.Euclidean) { newSegment.Type = SegmentType.Arc; if (2 == p) { // Our magic formula below breaks down for digons. double factor = Math.Tan(Math.PI / 6); newSegment.Center = newSegment.P1.X > 0 ? new Vector3D(0, -circumRadius, 0) * factor : new Vector3D(0, circumRadius, 0) * factor; } else { // Our segments are arcs in Non-Euclidean geometries. // Magically, the same formula turned out to work for both. // (Maybe this is because the Poincare Disc model of the // hyperbolic plane is stereographic projection as well). double piq = q == -1 ? 0 : Math.PI / q; // Handle q infinite. double t1 = Math.PI / p; double t2 = Math.PI / 2 - piq - t1; double factor = (Math.Tan(t1) / Math.Tan(t2) + 1) / 2; newSegment.Center = (newSegment.P1 + newSegment.P2) * factor; } newSegment.Clockwise = Geometry.Spherical == g ? false : true; } // XXX - Make this configurable? // This is the color of cell boundary lines. //newSegment.m_color = CColor( 1, 1, 0, 1 ); Segments.Add(newSegment); } }