示例#1
0
            private H3.Cell.Edge[] GenEdgesInternal(Vector3D v1, Vector3D v2, Vector3D v3, Vector3D v4)
            {
                int div = 5;
                List <H3.Cell.Edge> result = new List <H3.Cell.Edge>();

                for (int i = 0; i <= div; i++)
                {
                    Vector3D start = v1 + (v2 - v1) * i / div;
                    Vector3D end   = v3 + (v4 - v3) * i / div;
                    start.Normalize();
                    end.Normalize();

                    start = Sterographic.S3toR3(start);
                    end   = Sterographic.S3toR3(end);

                    if (Infinity.IsInfinite(start))
                    {
                        start = end * 10;
                    }
                    if (Infinity.IsInfinite(end))
                    {
                        end = start * 10;
                    }

                    result.Add(new H3.Cell.Edge(start, end));
                }
                return(result.ToArray());
            }
示例#2
0
        /// <summary>
        /// Returns a stereographically sphere representing us.
        /// </summary>
        public Sphere ToSphere()
        {
            // Equatorial sphere?
            if (Pole == new Vector3D(0, 0, 0, 1))
            {
                return(new Sphere());
            }

            // A plane?
            Vector3D poleR3 = Sterographic.S3toR3(Pole);

            if (Tolerance.Equal(poleR3.Abs(), 1))
            {
                return(Sphere.Plane(poleR3));
            }

            // Get 4 points on the sphere.
            Vector3D e1 = new Vector3D(1, 0, 0, 0);
            Vector3D e2 = new Vector3D(0, 1, 0, 0);
            Vector3D e3 = new Vector3D(0, 0, 1, 0);
            Vector3D e4 = new Vector3D(0, 0, 0, 1);

            System.Func <Vector3D, Vector3D> one = v =>
            {
                v = Euclidean3D.ProjectOntoPlane(Pole, new Vector3D(), v);
                v.Normalize();
                return(Sterographic.S3toR3(v));
            };

            return(Sphere.From4Points(one(e1), one(e2), one(e3), one(e4)));
        }
示例#3
0
 private static Vector3D Transform2(Vector3D p, Matrix4D mat)
 {
     p.Normalize();
     p = mat.RotateVector(p);
     p = Sterographic.S3toR3(p);
     p = SphericalModels.StereoToEquidistant(p);
     return(p);
 }
示例#4
0
 private static Vector3D[] OneHopfCircleProjected(Vector3D s2Point, bool anti)
 {
     Vector3D[] circlePoints = S3.OneHopfCircle(s2Point, anti);
     for (int i = 0; i < circlePoints.Length; i++)
     {
         circlePoints[i] = Sterographic.S3toR3(circlePoints[i]);
     }
     return(circlePoints);
 }
示例#5
0
        public static void ElevenCell()
        {
            Graph g = new Graph();

            g.SetupCompleteGraph(11);

            GraphRelaxation relaxer = new GraphRelaxation();

            relaxer.Graph          = g;
            relaxer.NodeRepulsion  = 0.01;
            relaxer.EdgeAttraction = 0.0;
            relaxer.EdgeRepulsion  = 0.0;
            relaxer.Relax(20000);

            Vector3D northPole = new Vector3D(0, 0, 0, 1);

            H3.Cell.Edge[] edges = g.Edges.Select(e =>
            {
                Vector3D v1 = g.Nodes[e.V1].Position.ToVec3D();
                Vector3D v2 = g.Nodes[e.V2].Position.ToVec3D();
                //if( v1.Compare( northPole, .5 ) || v2.Compare( northPole, 0.5 ) )	// Cull edges near north pole.
                //	return null;
                v1 = Sterographic.S3toR3(v1);
                v2 = Sterographic.S3toR3(v2);
                return(new H3.Cell.Edge(v1, v2));
            }).ToArray();

            edges = edges.Where(e => e != null).ToArray();

            bool povray = false;

            if (povray)
            {
                string filename = "test.pov";
                System.IO.File.Delete(filename);
                using (StreamWriter sw = new StreamWriter(filename))
                    sw.WriteLine("#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\H3\\horosphere\\633.pov\"");

                PovRay.WriteEdges(new PovRay.Parameters {
                    AngularThickness = 0.03
                }, Geometry.Spherical, edges, filename, append: true);
            }
            else
            {
                S3.EdgesToStl(edges);
            }
        }
示例#6
0
        public static Circle3D GeodesicFrom2Points(Vector3D a, Vector3D b)
        {
            if (a == b || a == -b)
            {
                throw new System.Exception("Geodesic not unique");
            }

            System.Func <Vector3D, Circle3D> lineFunc = p =>
            {
                Circle3D circ = new Circle3D();
                circ.Radius = double.PositiveInfinity;
                p.Normalize();
                circ.Normal = p;                    // Hacky representation of a line.
                return(circ);
            };

            if (a.IsOrigin || b.IsOrigin)
            {
                Vector3D p = a.IsOrigin ? b : a;
                return(lineFunc(p));
            }

            double mag1 = a.Abs(), mag2 = b.Abs();

            if (Tolerance.Equal(mag1, 1) && Tolerance.Equal(mag2, 1))
            {
                return(new Circle3D(a, b, a * -1));
            }

            // The antipode in S^3 of a or b will give us a 3rd point.
            Vector3D antipode = Sterographic.S3toR3(Sterographic.R3toS3(a) * -1);

            // If the antipode is also an an antipode in R3, the points are colinear
            // (or they are on the equatorial 2-sphere, but that is checked above).
            if (a == antipode * -1)
            {
                return(lineFunc(a));
            }

            return(new Circle3D(a, b, antipode));
        }
示例#7
0
        private static void Relax(Vector3D[] coordsR3, int[] elementIndices, Vector3D[] locks)
        {
            int   dim = 4;
            Graph g   = new Graph();

            for (int i = 0; i < coordsR3.Length; i++)
            {
                Vector3D  v    = coordsR3[i];
                GraphNode node = new GraphNode(new VectorND(Sterographic.R3toS3(v)), new VectorND(dim));
                node.Lock = new VectorND(locks[i]);
                g.Nodes.Add(node);
            }

            for (int i = 0; i < elementIndices.Length; i += 3)
            {
                int a = elementIndices[i];
                int b = elementIndices[i + 1];
                int c = elementIndices[i + 2];
                g.AddEdge(new GraphEdge(a, b));
                g.AddEdge(new GraphEdge(b, c));
                g.AddEdge(new GraphEdge(c, a));
            }

            GraphRelaxation relaxer = new GraphRelaxation();

            relaxer.Graph          = g;
            relaxer.NodeRepulsion  = 0;
            relaxer.EdgeAttraction = 0.5;
            relaxer.EdgeRepulsion  = 0;
            relaxer.Relax(1000);

            for (int i = 0; i < coordsR3.Length; i++)
            {
                GraphNode node = g.Nodes[i];
                coordsR3[i] = Sterographic.S3toR3(node.Position.ToVec3D());
            }
        }
示例#8
0
        private static void CompoundOfFive24Cells(ref H3.Cell.Edge[] edges)
        {
            List <H3.Cell.Edge> allEdges = new List <H3.Cell.Edge>();

            Vector3D v600 = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 3, 5));
            Vector3D v24  = Sterographic.R3toS3(SimplexCalcs.VertexSpherical(3, 4, 3));

            Sphere[] mirrors600 = SimplexCalcs.MirrorsSpherical(3, 3, 5);

            double a24  = v24.AngleTo(Sterographic.R3toS3(new Vector3D()));
            double a600 = v600.AngleTo(Sterographic.R3toS3(new Vector3D()));

            Matrix4D m600  = Matrix4D.MatrixToRotateinCoordinatePlane(a600, 2, 3);
            Matrix4D m600_ = Matrix4D.MatrixToRotateinCoordinatePlane(-a600, 2, 3);
            Matrix4D m24   = Matrix4D.MatrixToRotateinCoordinatePlane(a24, 2, 3);
            Matrix4D m24_  = Matrix4D.MatrixToRotateinCoordinatePlane(-a24, 2, 3);

            double eLength = 2 * Math.PI / 10;                  // 600-cell edge length
            double a_id    = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 2));

            eLength = 1.0 / Math.Sin(2 * Math.PI / 5);                  // icosahedron edge length
            double a_i = Math.Asin(Math.Sin(eLength / 2) / Math.Sin(Math.PI / 3) * Math.Sin(Math.PI / 5));

            Func <Vector3D, Vector3D> rot600 = v =>
            {
                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);
                return(v);
            };

            Func <Vector3D, int, Vector3D> rotOne = (v, idx) =>
            {
                v = Sterographic.R3toS3(v);
                v = m24.RotateVector(v);
                v = Sterographic.S3toR3(v);
                v.RotateAboutAxis(new Vector3D(1, 0, 0), -a_id);

                // Vertex to cell center.
                v = Sterographic.R3toS3(v);
                v = m600_.RotateVector(v);
                v = Sterographic.S3toR3(v);

                List <int> reflections = new List <int>();
                if (idx == 0)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(1);
                    reflections.Add(2);
                }

                if (idx != 0)
                {
                    reflections.Add(3);
                }
                if (idx == 2)
                {
                    reflections.Add(1);
                    reflections.Add(2);
                }
                if (idx == 3)
                {
                    reflections.Add(2);
                    reflections.Add(1);
                }
                if (idx == 4)
                {
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(2);
                    reflections.Add(0);
                    reflections.Add(1);
                    reflections.Add(0);
                    reflections.Add(1);
                }

                foreach (int reflection in reflections)
                {
                    v = mirrors600[reflection].ReflectPoint(v);
                }

                v = Sterographic.R3toS3(v);
                v = m600.RotateVector(v);
                v = Sterographic.S3toR3(v);

                //v.RotateAboutAxis( new Vector3D( 0, 0, 1 ), Math.PI/3 );
                //v.RotateAboutAxis( new Vector3D( 1, 0, 0 ), -a_i*2 );
                v = Sterographic.R3toS3(v);
                //v = m24_.RotateVector( v );
                v = Sterographic.S3toR3(v);


                return(v);
            };

            for (int i = 0; i < 5; i++)
            {
                //if( i == 0 )
                //	continue;

                allEdges.AddRange(edges.Select(e =>
                {
                    H3.Cell.Edge newEdge = new H3.Cell.Edge(rotOne(e.Start, i), rotOne(e.End, i));
                    //H3.Cell.Edge newEdge = new H3.Cell.Edge( rot600( e.Start ), rot600( e.End ) );
                    switch (i)
                    {
                    case 0:
                        newEdge.Color = new Vector3D(1, 0, 0, 1);
                        //newEdge.Color = new Vector3D( 1, 1, 1, 0 );
                        break;

                    case 1:
                        newEdge.Color = new Vector3D(0, 1, 0, 2);
                        break;

                    case 2:
                        newEdge.Color = new Vector3D(0, 0, 1, 3);
                        break;

                    case 3:
                        newEdge.Color = new Vector3D(1, 0, 1, 4);
                        break;

                    case 4:
                        newEdge.Color = new Vector3D(0, 1, 1, 5);
                        break;
                    }
                    return(newEdge);
                }));
            }

            edges = allEdges.ToArray();

            //edges = edges.Where( e => Tolerance.Equal( 1, e.Start.Abs() ) || Tolerance.Equal( 1, e.End.Abs() ) ).ToArray();

            HashSet <Vector3D> uniqueVerts = new HashSet <Vector3D>();

            foreach (H3.Cell.Edge e in edges)
            {
                uniqueVerts.Add(e.Start);
                uniqueVerts.Add(e.End);
            }
            System.Diagnostics.Trace.WriteLine("Number of verts = " + uniqueVerts.Count);

            /*edges = edges.Where( e =>
             * {
             *      Vector3D v = Tolerance.Equal( 1, e.Start.Abs() ) ? e.End : e.Start;
             *      if( v.Abs() >= 0.8 || v.Abs() <= 0.7 )
             *              return false;
             *
             *      if( Tolerance.LessThanOrEqual( v.X, 0 ) || Tolerance.GreaterThanOrEqual( v.Y, 0 ) || Tolerance.GreaterThanOrEqual( v.Z, 0 ) )
             *              return false;
             *
             *      return true;
             * } ).ToArray();
             *
             * edges = edges.OrderBy( e => Tolerance.Equal( 1, e.Start.Abs() ) ? e.End.Abs() : e.Start.Abs() ).ToArray();*/
        }
示例#9
0
        public static void S3BiHelicoid()
        {
            double cutoff = 8.0;
            int    div    = 500;

            Matrix4D mat = Matrix4D.MatrixToRotateinCoordinatePlane(1 * Math.PI / 4, 0, 3);
            Mesh     m1  = S3Helicoid(div, mat, reciprocal: false);
            //m1.Triangles = m1.Triangles.Where( t => t.a.Abs() < cutoff && t.b.Abs() < cutoff && t.c.Abs() < cutoff ).ToList();

            Mesh m2 = S3Helicoid(div, mat, reciprocal: true);
            //m2.Triangles = m2.Triangles.Where( t => t.a.Abs() < cutoff && t.b.Abs() < cutoff && t.c.Abs() < cutoff ).ToList();

            Mesh m3 = new Mesh();

            System.Action <bool> addCore = recip =>
            {
                List <Vector3D> circlePoints = new List <Vector3D>();
                double          aOffset      = 2 * Math.PI / div;
                for (int i = 0; i <= div; i++)
                {
                    double x = Math.Sin(aOffset * i);
                    double y = Math.Cos(aOffset * i);
                    circlePoints.Add(recip ?
                                     new Vector3D(x, y) : new Vector3D(0, 0, x, y));
                }

                // partial transform to R3 here.
                circlePoints = circlePoints.Select(p =>
                {
                    p = mat.RotateVector(p);
                    p = Sterographic.S3toR3(p);
                    return(p);
                }).ToList();

                List <Vector3D> ePoints = new List <Vector3D>();
                List <double>   eRadii  = new List <double>();
                foreach (Vector3D pNE in circlePoints)
                {
                    Sphere sphere = SphereFuncBall(Geometry.Spherical, pNE, false);
                    ePoints.Add(sphere.Center);
                    eRadii.Add(sphere.Radius);
                }

                Shapeways shapeways = new Shapeways();
                shapeways.AddClosedCurve(ePoints.ToArray(), eRadii.ToArray());
                m3.Append(shapeways.Mesh);
            };
            addCore(false);
            addCore(true);
            for (int i = 0; i < m3.Triangles.Count; i++)
            {
                Mesh.Triangle t = m3.Triangles[i];
                m3.Triangles[i] = Transform(t, SphericalModels.StereoToEquidistant);
            }

            string filename = "helicoid.stl";

            File.Delete(filename);
            using (StreamWriter sw = File.AppendText(filename))
            {
                STL.AppendMeshToSTL(m1, sw);
                STL.AppendMeshToSTL(m2, sw);
                STL.AppendMeshToSTL(m3, sw);
            }

            //HelicoidHelper( thinMesh, boundaryPoints );
        }
示例#10
0
        public void Gen(int p, int q, int r)
        {
            Geometry g = Util.GetGeometry(p, q, r);

            if (g != Geometry.Spherical)
            {
                throw new System.Exception("Point group code only for spherical geometry.");
            }

            Simplex simplex = new Simplex();

            simplex.Facets = SimplexCalcs.Mirrors(p, q, r);
            Vector3D cen        = new Vector3D();
            Vector3D faceCenter = SimplexCalcs.FaceCenterSpherical(p, q, r);
            Vector3D edgeMid    = SimplexCalcs.EdgeMidpointSpherical(p, q, r);
            Vector3D vertex     = SimplexCalcs.VertexSpherical(p, q, r);

            List <Vector3D> startingPoles = new List <Vector3D>();

            startingPoles.Add(Sterographic.S3toR3(GreatSphere.FromSphere(simplex.Facets[0]).Pole));
            GreatSphere[] spheres = CalcSpheres(simplex.Facets, startingPoles.ToArray());

            string filename = "point_group.pov";

            using (StreamWriter sw = File.CreateText(filename))
            {
                //foreach( var greatSphere in spheres )
                //sw.WriteLine( PovRay.Sphere( greatSphere.ToSphere() ) );
            }

            /*
             * List<H3.Cell.Edge> startingEdges = new List<H3.Cell.Edge>();
             * startingEdges.Add( new H3.Cell.Edge( cen, faceCenter ) );
             * H3.Cell.Edge[] edges = Recurse.CalcEdges( simplex.Facets, startingEdges.ToArray(), new Recurse.Settings() { G = Geometry.Spherical, Threshold = 0.001 } );
             * //edges = edges.Where( e => !( Infinity.IsInfinite( e.Start ) || Infinity.IsInfinite( e.End ) ) ).ToArray();
             *
             * PovRay.WriteEdges( new PovRay.Parameters() { AngularThickness = 0.01 }, Geometry.Spherical, edges, filename, append: true );
             */

            double minRad = 0;
            double thick  = 0.005;

            System.Func <Vector3D, Sphere> sizeFunc = v =>
            {
                Vector3D c;
                double   rad;
                H3Models.Ball.DupinCyclideSphere(v, thick / 2, g, out c, out rad);
                return(new Sphere()
                {
                    Center = c, Radius = Math.Max(rad, minRad)
                });
            };

            // All geodesics
            List <Circle3D> startingCircles = new List <Circle3D>();

            startingCircles.Add(GeodesicFrom2Points(cen, edgeMid));
            Circle3D[] geodesics = CalcGeodesics(simplex.Facets, startingCircles.ToArray());

            Vector3D color = new Vector3D(0, 0, 1);

            using (StreamWriter sw = File.CreateText(filename))
            {
                Shapeways shapeways = new Shapeways();
                foreach (Circle3D geodesic in geodesics)
                {
                    Vector3D[] points;
                    if (Infinity.IsInfinite(geodesic.Radius))
                    {
                        double  cutoff = 15;
                        Segment seg    = Segment.Line(geodesic.Normal * cutoff, geodesic.Normal * -cutoff);
                        points = seg.Subdivide(42);
                    }
                    else
                    {
                        List <Vector3D> tempPoints = geodesic.Subdivide(150).ToList();
                        tempPoints.Add(tempPoints[0]);
                        tempPoints.Add(tempPoints[1]);
                        points = tempPoints.ToArray();
                    }

                    List <Vector3D> ePoints = new List <Vector3D>();
                    List <double>   eRadii  = new List <double>();
                    foreach (Vector3D pNE in points)
                    {
                        Sphere sphere = sizeFunc(pNE);
                        ePoints.Add(sphere.Center);
                        eRadii.Add(sphere.Radius);
                    }
                    shapeways.AddCurve(ePoints.ToArray(), eRadii.ToArray());

                    sw.WriteLine(PovRay.EdgeSphereSweep(points, sizeFunc, color));
                }

                STL.SaveMeshToSTL(shapeways.Mesh, "533.stl");
            }
        }