Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        /// <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));
        }
Ejemplo n.º 3
0
        /// <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()
            });
        }
Ejemplo n.º 4
0
 /// <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));
 }
Ejemplo n.º 5
0
        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));
        }
Ejemplo n.º 6
0
        /// <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);
            }
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        /// <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;
             */
        }
Ejemplo n.º 9
0
        /// <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));
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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;
        }
Ejemplo n.º 12
0
        /// <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);
        }
Ejemplo n.º 13
0
 // Cotangent
 public static double Cotan(double x)
 {
     return(1 / MathObj.Tan(x));
 }
Ejemplo n.º 14
0
 public static double Tan(object self, double x)
 {
     return(SM.Tan(x));
 }
Ejemplo n.º 15
0
 public static float Tan(float rad)
 {
     return((float)SMath.Tan(rad));
 }
Ejemplo n.º 16
0
 public static double Tan(object self, [DefaultProtocol] double x)
 {
     return(SM.Tan(x));
 }
Ejemplo n.º 17
0
 private static int Math_Tan(ILuaState lua)
 {
     lua.PushNumber(Math.Tan(lua.L_CheckNumber(1)));
     return(1);
 }
Ejemplo n.º 18
0
 s2eNorm(double sNorm)
 {
     //if( double.IsNaN( sNorm ) )
     //	return 1.0;
     return(Math.Tan(.5 * sNorm));
 }
Ejemplo n.º 19
0
        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);
            }
        }