示例#1
0
        public static void HopfOrbit()
        {
            List <Vector3D> s2Points = new List <Vector3D>();

            for (double theta = Math.PI * .1; theta <= Math.PI * .9; theta += Math.PI * .2)
            {
                for (double lon = -Math.PI; lon <= Math.PI; lon += Math.PI / 10)
                {
                    s2Points.Add(SphericalCoords.SphericalToCartesian(new Vector3D(1.0, theta, lon)));
                }
            }

            using (StreamWriter sw = File.CreateText(@".\out.pov"))
            {
                System.Func <Vector3D, Sphere> sizeFunc = v => new Sphere()
                {
                    Center = v, Radius = 0.01
                };
                foreach (Vector3D s2Point in s2Points)
                {
                    Vector3D[] circlePoints = OneHopfCircle(s2Point);

                    //for( int i = 0; i < circlePoints.Length; i++ )
                    //	circlePoints[i] = circlePoints[i].ProjectTo3DSafe( 1.0 );

                    // Note: effectively orthogonal projects here because EdgeSphereSweep doesn't write W coord.
                    string circleString = PovRay.EdgeSphereSweep(circlePoints, sizeFunc);
                    sw.WriteLine(circleString);
                }
            }
        }
    public static Vector3 GetVecWithoutYRot(Vector3 coords)
    {
        SphericalCoords sphCoords = CartesianToSpherical(coords);

        sphCoords.theta = 0;
        return(sphCoords.ToCartesian());
    }
示例#3
0
        public static Vector3D SinusoidalToStereo(Vector3D v)
        {
            double   lat       = Math.PI / 2 * (1 - v.Y);
            Vector3D spherical = new Vector3D(1, lat, Math.PI * v.X / Math.Cos(lat - Math.PI / 2));
            Vector3D onBall    = SphericalCoords.SphericalToCartesian(spherical);

            return(Sterographic.SphereToPlane(onBall));
        }
    public static Vector3 SphericalToCartesian(SphericalCoords coords)
    {
        float rSinPhi = coords.radius * Mathf.Sin(coords.phi);
        float x       = rSinPhi * Mathf.Cos(coords.theta);
        float y       = coords.radius * Mathf.Cos(coords.phi);
        float z       = rSinPhi * Mathf.Sin(coords.theta);

        return(new Vector3(x, y, z));
    }
示例#5
0
        /// <summary>
        /// 2-dimensional function.
        /// http://archive.bridgesmathart.org/2013/bridges2013-217.pdf
        /// </summary>
        public static Vector3D MercatorToStereo(Vector3D v)
        {
            v *= Math.PI;               // Input is [-1,1]
            double   lat         = 2 * Math.Atan(Math.Exp(v.Y)) - Math.PI / 2;
            double   inclination = lat + Math.PI / 2;
            Vector3D spherical   = new Vector3D(1, inclination, v.X);
            Vector3D onBall      = SphericalCoords.SphericalToCartesian(spherical);

            return(Sterographic.SphereToPlane(onBall));
        }
示例#6
0
        public static Vector3D EquirectangularToStereo(Vector3D v)
        {
            // http://mathworld.wolfram.com/EquirectangularProjection.html
            // y is the latitude
            // x is the longitude
            // Assume inputs go from -1 to 1.
            Vector3D spherical = new Vector3D(1, Math.PI / 2 * (1 - v.Y), v.X * Math.PI);
            Vector3D onBall    = SphericalCoords.SphericalToCartesian(spherical);

            return(Sterographic.SphereToPlane(onBall));
        }
示例#7
0
        /// <summary>
        /// https://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection
        /// </summary>
        private static double EqualAreaToStereo(double dist)
        {
            if (dist > 1)
            {
                throw new System.ArgumentException();
            }

            // We have dist normalized between 0 and 1, so this formula is slightly
            // different than on Wikipedia, where dist ranges up to 2.
            Vector3D v = new Vector3D(1, 2 * Math.Acos(dist), 0);

            v = Sterographic.SphereToPlane(SphericalCoords.SphericalToCartesian(v));
            return(v.Abs());
        }
示例#8
0
        public static void GenPolyhedron()
        {
            Tiling tiling;
            int    p = 3;
            int    q = 6;

            GetAssociatedTiling(p, q, 5000, out tiling);

            double overallScale = 12.5;                 // 2.5 cm = 1 in diameter

            Shapeways mesh = new Shapeways();

            foreach (Tile tile in tiling.Tiles)
            {
                foreach (Segment seg in tile.Boundary.Segments)
                {
                    double tilingScale = 0.75;
                    seg.Scale(new Vector3D(), tilingScale);

                    Vector3D v1 = Sterographic.PlaneToSphereSafe(seg.P1);
                    Vector3D v2 = Sterographic.PlaneToSphereSafe(seg.P2);
                    //if( v1.Dist( v2 ) < 0.01 )
                    //	continue;
                    if (SphericalCoords.CartesianToSpherical(v1).Y < Math.PI / 12 &&
                        SphericalCoords.CartesianToSpherical(v2).Y < Math.PI / 12)
                    {
                        continue;
                    }

                    double dist      = v1.Dist(v2);
                    int    divisions = 2 + (int)(dist * 20);

                    Vector3D[] points = seg.Subdivide(divisions);
                    points = points.Select(v => Sterographic.PlaneToSphereSafe(v)).ToArray();
                    mesh.AddCurve(points, v => SizeFunc(v, overallScale));
                }
            }

            mesh.Mesh.Scale(overallScale);

            string outputFileName = @"d:\temp\" + p + q + ".stl";

            STL.SaveMeshToSTL(mesh.Mesh, outputFileName);
        }
示例#9
0
        private static double SizeFunc(Vector3D v, double overallScale)
        {
            //return .6 / 2 / overallScale;

            // Silver min wall is 0.6
            // Silver min wire is 0.8 (supported) or 1.0 (unsupported).

            double min = 0.55 / 2;
            double max = 1.5 / 2;

            // for caps
            //double min = 0.71 / 2;
            //double max = 0.5 / 2;	// 36
            //double max = 0.35 / 2; // 63

            Vector3D s      = SphericalCoords.CartesianToSpherical(v);
            double   angle  = s.Y / Math.PI;                    // angle 0 to 1
            double   result = min + (max - min) * angle;

            return(result / overallScale);
        }
示例#10
0
        public static void RLD_Surface()
        {
            RLD_outputs outputs;
            Mesh        mesh = new Mesh();

            SurfaceInternal(out outputs);
            double scale = m_params.Scale;

            // Now add in all the catenoids.
            double mInc = Math.PI * 2 / m_params.M;

            for (int k = 1; k < outputs.x_i.Length; k++)
            {
                for (int m = 0; m < m_params.M; m++)
                {
                    Vector3D loc = SphericalCoords.SphericalToCartesian(new Vector3D(1, Math.PI / 2 - outputs.x_i[k], m * mInc));
                    mesh.Append(Catenoid(scale, loc, outputs.phi_i[k], outputs.t_i[k]));
                }
            }

            PovRay.WriteMesh(mesh, "RLD.pov");
        }
示例#11
0
        /// <summary>
        /// This allows us to change the model we have on the plane.
        /// We usually want UHS, but for Pov-Ray mapping these images to a sphere, we need to have it be an equirectangular projection
        /// NOTE: The bounds should be set to 1.0 for this to work! v.X and v.Y must be in-between -1 and 1. (also, don't rotate simplex mirrors, for POV-Ray anyway)
        /// </summary>
        private Vector3D PlaneModelToBall(Vector3D v, double t = 0.0)
        {
            bool equirectangular = false;

            if (!equirectangular)
            {
                // Normal UHS (sterographic projection).
                return(H3Models.UHSToBall(v));
            }
            else
            {
                // If you want output to have twice the width.
                double xScale = 2;
                v.X /= xScale;

                // http://mathworld.wolfram.com/EquirectangularProjection.html
                // y is the latitude
                // x is the longitude
                // Assume inputs go from -1 to 1.
                Vector3D spherical = new Vector3D(1, Math.PI / 2 * (1 - v.Y), v.X * Math.PI);
                Vector3D onBall    = SphericalCoords.SphericalToCartesian(spherical);
                return(ApplyTransformationToSphere(onBall, t));
            }
        }
示例#12
0
    private void FillKNNTrees(KNNBone rootBone, bool ignoreRotation, bool bothHandsInFeatureVec, string headBoneName, string rHandBoneName, string lHandBoneName, float slidingWindowSizeInMS, float slidingWindowOffsetInMS, float pollingRate, List <int> lHandTreeNodes, List <int> rHandTreeNodes, List <float[]> lHandTreePoints, List <float[]> rHandTreePoints)
    {
        float sourceFrameTime     = bvhParser.frameTime;
        float targetFrameTime     = 1.0f / pollingRate;
        float totalTime           = bvhParser.frames * sourceFrameTime;
        int   totalNewFrames      = (int)(totalTime / targetFrameTime);
        float slidingWindowOffset = slidingWindowOffsetInMS / 1000.0f;
        float slidingWindowSize   = slidingWindowSizeInMS / 1000.0f;

        int totalWindows     = (int)((totalTime - (slidingWindowSize)) / (slidingWindowOffset));
        int framesPerWindow  = (int)((slidingWindowSize) / targetFrameTime);
        int nrOfFeatures     = bothHandsInFeatureVec ? 18 : 9;
        int featureVecLength = nrOfFeatures * framesPerWindow;

        setToFrame(0, true, true, true);

        for (int currentWindow = 0; currentWindow < totalWindows; currentWindow++)
        {
            float[] lHandPoints = new float[featureVecLength];
            float[] rHandPoints = new float[featureVecLength];

            for (int currFrame = 0; currFrame < framesPerWindow; currFrame++)
            {
                float startTime   = slidingWindowOffset * (float)currentWindow;
                float sourceFrame = getSourceFrameFromTargetTime(sourceFrameTime, startTime + (float)currFrame * targetFrameTime);
                setToFrame(sourceFrame, true, true, true);
                Vector3 rHandPosition = root.Find(rHandBoneName).position;
                Vector3 lHandPosition = root.Find(lHandBoneName).position;

                if (sourceFrame >= 1.0f)
                {
                    setToFrame(sourceFrame - 1.0f, true, true, true);
                }

                Vector3 prevRHandPosition = root.Find(rHandBoneName).position;
                Vector3 prevLHandPosition = root.Find(lHandBoneName).position;

                if (sourceFrame >= 2.0f)
                {
                    setToFrame(sourceFrame - 2.0f, true, true, true);
                }

                Vector3 prevPrevRHandPosition = root.Find(rHandBoneName).position;
                Vector3 prevPrevLHandPosition = root.Find(lHandBoneName).position;

                Vector3 lHandVelocity = (lHandPosition - prevLHandPosition) / sourceFrameTime;
                Vector3 rHandVelocity = (rHandPosition - prevRHandPosition) / sourceFrameTime;

                Vector3 prevLHandVelocity = (prevLHandPosition - prevPrevLHandPosition) / sourceFrameTime;
                Vector3 prevRHandVelocity = (prevRHandPosition - prevPrevRHandPosition) / sourceFrameTime;

                Vector3 lHandAcceleration = (lHandVelocity - prevLHandVelocity) / sourceFrameTime;
                Vector3 rHandAcceleration = (rHandVelocity - prevRHandVelocity) / sourceFrameTime;

                if (ignoreRotation)
                {
                    SphericalCoords rHandSpPosition = SphericalCoords.CartesianToSpherical(rHandPosition);
                    SphericalCoords lHandSpPosition = SphericalCoords.CartesianToSpherical(lHandPosition);

                    float rHandAngle = rHandSpPosition.theta * Mathf.Rad2Deg;
                    float lHandAngle = lHandSpPosition.theta * Mathf.Rad2Deg;

                    //rotate velocity and acceleration angle around "theta"
                    lHandVelocity = Quaternion.AngleAxis(lHandAngle, Vector3.up) * lHandVelocity;
                    rHandVelocity = Quaternion.AngleAxis(rHandAngle, Vector3.up) * rHandVelocity;

                    lHandAcceleration = Quaternion.AngleAxis(lHandAngle, Vector3.up) * lHandAcceleration;
                    rHandAcceleration = Quaternion.AngleAxis(rHandAngle, Vector3.up) * rHandAcceleration;

                    rHandSpPosition.theta = 0;
                    lHandSpPosition.theta = 0;

                    rHandPosition = rHandSpPosition.ToCartesian();
                    lHandPosition = lHandSpPosition.ToCartesian();
                }


                int pointOffset = currFrame * nrOfFeatures;
                lHandPoints[pointOffset]     = lHandPosition.x;
                lHandPoints[pointOffset + 1] = lHandPosition.y;
                lHandPoints[pointOffset + 2] = lHandPosition.z;

                lHandPoints[pointOffset + 3] = lHandVelocity.x;
                lHandPoints[pointOffset + 4] = lHandVelocity.y;
                lHandPoints[pointOffset + 5] = lHandVelocity.z;

                lHandPoints[pointOffset + 6] = lHandAcceleration.x;
                lHandPoints[pointOffset + 7] = lHandAcceleration.y;
                lHandPoints[pointOffset + 8] = lHandAcceleration.z;

                rHandPoints[pointOffset]     = rHandPosition.x;
                rHandPoints[pointOffset + 1] = rHandPosition.y;
                rHandPoints[pointOffset + 2] = rHandPosition.z;

                rHandPoints[pointOffset + 3] = rHandVelocity.x;
                rHandPoints[pointOffset + 4] = rHandVelocity.y;
                rHandPoints[pointOffset + 5] = rHandVelocity.z;

                rHandPoints[pointOffset + 6] = rHandAcceleration.x;
                rHandPoints[pointOffset + 7] = rHandAcceleration.y;
                rHandPoints[pointOffset + 8] = rHandAcceleration.z;

                if (bothHandsInFeatureVec)
                {
                    lHandPoints[pointOffset + 9]  = rHandPosition.x;
                    lHandPoints[pointOffset + 10] = rHandPosition.y;
                    lHandPoints[pointOffset + 11] = rHandPosition.z;

                    lHandPoints[pointOffset + 12] = rHandVelocity.x;
                    lHandPoints[pointOffset + 13] = rHandVelocity.y;
                    lHandPoints[pointOffset + 14] = rHandVelocity.z;

                    lHandPoints[pointOffset + 15] = rHandAcceleration.x;
                    lHandPoints[pointOffset + 16] = rHandAcceleration.y;
                    lHandPoints[pointOffset + 17] = rHandAcceleration.z;

                    rHandPoints[pointOffset + 9]  = lHandPosition.x;
                    rHandPoints[pointOffset + 10] = lHandPosition.y;
                    rHandPoints[pointOffset + 11] = lHandPosition.z;

                    rHandPoints[pointOffset + 12] = lHandVelocity.x;
                    rHandPoints[pointOffset + 13] = lHandVelocity.y;
                    rHandPoints[pointOffset + 14] = lHandVelocity.z;

                    rHandPoints[pointOffset + 15] = lHandAcceleration.x;
                    rHandPoints[pointOffset + 16] = lHandAcceleration.y;
                    rHandPoints[pointOffset + 17] = lHandAcceleration.z;
                }
            }
            int lastPositionSourceIndex = (int)((currentWindow * slidingWindowOffset + slidingWindowSize) / sourceFrameTime);

            setToFrame(lastPositionSourceIndex, true, true, true);
            rootBone.AddRotationsFromTransform(root);

            lHandTreePoints.Add(lHandPoints); lHandTreeNodes.Add(lHandTreeNodes.Count);
            rHandTreePoints.Add(rHandPoints); rHandTreeNodes.Add(rHandTreeNodes.Count);
        }
    }
示例#13
0
        public static void CatenoidBasedSurface()
        {
            RLD_outputs outputs;

            SurfaceInternal(out outputs);
            double scale = m_params.Scale;

            // Map a point for a given k/m from the hemihypersphere to the complex plane.
            // You can also pass in -1 for k to get a point on the equator of the hemihypersphere.
            double mInc = Math.PI * 2 / m_params.M;
            Func <RLD_outputs, int, int, Vector3D> onPlane = (o, k, m) =>
            {
                double theta = k == -1 ? 0 : outputs.x_i[k];
                theta += Math.PI / 2;
                return
                    (Sterographic.SphereToPlane(
                         SphericalCoords.SphericalToCartesian(
                             new Vector3D(1, theta, m * mInc)
                             )
                         ));
            };

            // Setup texture coords on fundamental triangle.
            // We'll use a fundamental triangle in the southern hemisphere,
            // with stereographically projected coords at (0,0), (1,0), and CCW on the unit circle depending on M.
            Polygon p = new Polygon();

            p.Segments.Add(Segment.Line(new Vector3D(), new Vector3D(1, 0)));
            p.Segments.Add(Segment.Arc(new Vector3D(1, 0), onPlane(outputs, 1, 1), onPlane(outputs, -1, 1)));
            p.Segments.Add(Segment.Line(onPlane(outputs, -1, 1), new Vector3D()));
            int levels = 9;

            TextureHelper.SetLevels(levels);
            Vector3D[] coords         = TextureHelper.TextureCoords(p, Geometry.Spherical, doGeodesicDome: true);
            int[]      elementIndices = TextureHelper.TextureElements(1, levels);

            // Setup a nearTree for the catenoid locations (on the plane).
            NearTree nearTree = new NearTree(Metric.Spherical);

            for (int k = 1; k < outputs.x_i.Length; k++)
            {
                for (int m = 0; m <= 1; m++)
                {
                    Vector3D loc = onPlane(outputs, k, m);
                    nearTree.InsertObject(new NearTreeObject()
                    {
                        ID = k, Location = loc
                    });
                }
            }

            // Given a point on the plane, find the nearest catenoid center and calculate the height of the surface based on that.
            // This also calculates the locking of the point.
            Func <Vector3D, Tuple <double, Vector3D, Vector3D> > heightAndLocking = coord =>
            {
                NearTreeObject closest;
                if (!nearTree.FindNearestNeighbor(out closest, coord, double.MaxValue))
                {
                    throw new System.Exception();
                }

                Vector3D locked = new Vector3D();
                if (p.Segments[0].IsPointOn(coord) ||
                    p.Segments[2].IsPointOn(coord))
                {
                    locked = new Vector3D(1, 1, 0, 0);
                }
                //if( p.Segments[1].IsPointOn( v ) )		// Not working right for some reason, but line below will work.
                if (Tolerance.Equal(coord.Abs(), 1))
                {
                    locked = new Vector3D(1, 1, 1, 0);
                }

                Vector3D vSphere = Sterographic.PlaneToSphere(coord);
                Vector3D cSphere = Sterographic.PlaneToSphere(closest.Location);
                double   dist    = vSphere.AngleTo(cSphere);

                int    k          = (int)closest.ID;
                double waist      = outputs.t_i[k];
                double rld_height = outputs.phi_i[k];

                double h      = waist * 3.5 * 2;                                        // height where catenoid will meet rld_height.
                double factor = scale * rld_height * 2 / h;                             // Artifical scaling so we can see things.
                dist /= factor;

                double z = double.NaN;
                if (dist >= waist)
                {
                    z = waist * DonHatch.acosh(dist / waist);
                }
                else if (dist >= 0.7 * waist)
                {
                    z = 0;

                    // Move the coord to the thinnest waist circle.
                    Mobius m = new Mobius();
                    m.Hyperbolic(Geometry.Spherical, coord.ToComplex(), waist / dist);
                    coord = m.Apply(coord);
                }

                if (dist < waist * 20)
                {
                    locked = new Vector3D(1, 1, 1, 1);
                }

                return(new Tuple <double, Vector3D, Vector3D>(z * factor, locked, coord));
            };

            // Calculate all the coordinates.
            Vector3D[] locks = new Vector3D[coords.Length];
            for (int i = 0; i < coords.Length; i++)
            {
                Vector3D coord = coords[i];
                var      hl    = heightAndLocking(coord);
                locks[i]  = hl.Item2;
                coord     = hl.Item3;
                coords[i] = Normal(Sterographic.PlaneToSphere(coord), (double)hl.Item1);
            }

            // Relax it.
            Relax(coords, elementIndices, locks);

            Mesh   mesh = new Mesh();
            Sphere s    = new Sphere();

            for (int i = 0; i < elementIndices.Length; i += 3)
            {
                Vector3D a = coords[elementIndices[i]];
                Vector3D b = coords[elementIndices[i + 1]];
                Vector3D c = coords[elementIndices[i + 2]];
                if (a.DNE || b.DNE || c.DNE)
                {
                    continue;
                }

                for (int m = 0; m <= 0; m++)
                {
                    mesh.Triangles.Add(new Mesh.Triangle(a, b, c));
                    mesh.Triangles.Add(new Mesh.Triangle(
                                           s.ReflectPoint(a),
                                           s.ReflectPoint(b),
                                           s.ReflectPoint(c)));
                    a.RotateXY(mInc);
                    b.RotateXY(mInc);
                    c.RotateXY(mInc);
                }
            }

            PovRay.WriteMesh(mesh, "RLD.pov");
        }
示例#14
0
 /// <summary>
 /// Converts to cartesian coordinates.
 /// </summary>
 public Vector3 ToCartesian()
 {
     return(SphericalCoords.SphericalToCartesian(this));
 }
示例#15
0
    public void SetSkeletonFromHandPos(KDTree <float, int> tree, LinkedList <FeatureItem> features, string handName, int k)
    {
        float[]   featureVec    = new float[featureVectorLength];
        Transform headTransform = rootBone.transform.Find("LowerBack/Spine/Spine1/Neck/Neck1/Head");
        Transform neckTransform = rootBone.transform.Find("LowerBack/Spine/Spine1/Neck/Neck1/Head");

        rootBone.transform.position -= headTransform.position;

        float handTargetSpPositionAngle = SphericalCoords.GetYRotFromVec(features.Last().position) * Mathf.Rad2Deg;

        var currFeatureContainer = features.Last;

        Debug.Assert(featureVectorLength % 9 == 0);
        for (int i = 0; i < featureVectorLength / 9; i++)
        {
            FeatureItem currFeatureItem = currFeatureContainer.Value;

            Vector3 handPos = currFeatureItem.position;
            Vector3 handVel = currFeatureItem.velocity;
            Vector3 handAcc = currFeatureItem.acceleration;

            if (ignoreRotation)
            {
                float handYRotValue = SphericalCoords.GetYRotFromVec(handPos) * Mathf.Rad2Deg;

                SphericalCoords sphCoords = SphericalCoords.CartesianToSpherical(handPos);
                sphCoords.theta = 0;
                Vector3 outVec = sphCoords.ToCartesian();

                handPos = Quaternion.AngleAxis(handYRotValue, Vector3.up) * handPos;
                handVel = Quaternion.AngleAxis(handYRotValue, Vector3.up) * handVel;
                handAcc = Quaternion.AngleAxis(handYRotValue, Vector3.up) * handAcc;
            }

            int startIndex = 9 * i;
            featureVec[startIndex]     = handPos.x;
            featureVec[startIndex + 1] = handPos.y;
            featureVec[startIndex + 2] = handPos.z;

            featureVec[startIndex + 3] = handVel.x;
            featureVec[startIndex + 4] = handVel.y;
            featureVec[startIndex + 5] = handVel.z;

            featureVec[startIndex + 6] = handAcc.x;
            featureVec[startIndex + 7] = handAcc.y;
            featureVec[startIndex + 8] = handAcc.z;

            if (currFeatureContainer.Previous != null)
            {
                currFeatureContainer = currFeatureContainer.Previous;
            }
        }

        Tuple <float[], int>[] poseIndices = tree.NearestNeighbors(featureVec, k);

        int index = poseIndices[0].Item2;

        RotationIndex[] rotations = new RotationIndex[poseIndices.Length];

        for (int i = 0; i < poseIndices.Length; i++)
        {
            double        distance = Metrics.WeightedL2Norm(poseIndices[i].Item1, featureVec);
            RotationIndex currIdx  = new RotationIndex(poseIndices[i].Item2, (float)(1.0 / distance));
            rotations[i] = currIdx;
        }

        rootBone.SetToRotations(rotations);
        //rootBone.SetToRotation(index);

        Transform       handTransform                = rootBone.transform.Find(handName);
        SphericalCoords handTransformSpPosition      = SphericalCoords.CartesianToSpherical(handTransform.position - headTransform.position);
        float           handTransformSpPositionAngle = handTransformSpPosition.theta * Mathf.Rad2Deg;

        rootBone.transform.localRotation *= Quaternion.Euler(0, -handTargetSpPositionAngle + handTransformSpPositionAngle, 0);
    }