Ejemplo n.º 1
0
        private static Vector3D[] CalcViaProjections(Vector3D p1, Vector3D p2, Vector3D p3, int divisions, Geometry g)
        {
            Vector3D h1 = Sterographic.PlaneToHyperboloid(p1);
            Vector3D h2 = Sterographic.PlaneToHyperboloid(p2);
            Vector3D h3 = Sterographic.PlaneToHyperboloid(p3);

            List <Vector3D> temp = new List <Vector3D>();
            Segment         seg1 = Segment.Line(h1, h2);
            Segment         seg2 = Segment.Line(h3, h2);

            Vector3D[] s1 = seg1.Subdivide(divisions);
            Vector3D[] s2 = seg2.Subdivide(divisions);
            for (int i = 0; i < divisions; i++)
            {
                Segment seg = Segment.Line(s1[i], s2[i]);
                temp.AddRange(seg.Subdivide(divisions - i));
            }
            temp.Add(h2);

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

            foreach (Vector3D v in temp)
            {
                Vector3D copy = v;
                Sterographic.NormalizeToHyperboloid(ref copy);
                result.Add(Sterographic.HyperboloidToPlane(copy));
            }
            return(result.ToArray());
        }
Ejemplo n.º 2
0
        public static void Experiment()
        {
            TilingConfig config = new TilingConfig(4, 3);
            Tiling       tiling = new Tiling();

            tiling.Generate(config);

            HashSet <H3.Cell.Edge> completed = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer());

            string fileName = "hopf.pov";

            using (StreamWriter sw = File.CreateText(fileName))
            {
                Tile[] tiles = tiling.Tiles.ToArray();
                //foreach( Tile t in tiling.Tiles )
                foreach (Tile t in new Tile[] { tiles[0] })
                {
                    foreach (Segment seg in t.Boundary.Segments)
                    {
                        H3.Cell.Edge e = new H3.Cell.Edge(seg.P1, seg.P2);
                        if (completed.Contains(e))
                        {
                            continue;
                        }

                        HopfLink(sw,
                                 Sterographic.PlaneToSphereSafe(e.Start),
                                 Sterographic.PlaneToSphereSafe(e.End), anti: false);
                        completed.Add(e);
                    }
                }
            }
        }
Ejemplo n.º 3
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)));
        }
Ejemplo n.º 4
0
        public int GetHashCode(Vector3D v)
        {
            Vector3D t = m_stereo ? Sterographic.R3toS3(v) : v;

            t = new Vector3D(Math.Abs(t.X), Math.Abs(t.Y), Math.Abs(t.Z), Math.Abs(t.W));
            return(t.GetHashCode());
        }
Ejemplo n.º 5
0
        public static GreatSphere[] CalcSpheres(Sphere[] simplex, Vector3D[] poles)
        {
            HashSet <Vector3D> completedPoles = new HashSet <Vector3D>(poles, new AntipodeEqualityComparer(stereo: true));

            ReflectSpheresRecursive(simplex, completedPoles.ToArray(), completedPoles);
            return(completedPoles.Select(p => new GreatSphere(Sterographic.R3toS3(p))).ToArray());
        }
Ejemplo n.º 6
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());
            }
Ejemplo n.º 7
0
 public void R3toS3()
 {
     for (int i = 0; i < Verts.Length; i++)
     {
         Verts[i] = Sterographic.R3toS3(Verts[i]);
     }
 }
Ejemplo n.º 8
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);
 }
Ejemplo n.º 9
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);
 }
Ejemplo n.º 10
0
        private static Vector3D Halfway(Vector3D v1, Vector3D v2)
        {
            Vector3D v1_ = Sterographic.PlaneToSphereSafe(v1);
            Vector3D v2_ = Sterographic.PlaneToSphereSafe(v2);

            Vector3D result = (v1_ + v2_) / 2;

            result.Normalize();
            return(Sterographic.SphereToPlane(result));
        }
Ejemplo n.º 11
0
        // https://plus.google.com/u/0/117663015413546257905/posts/BnCEkdNiTZ2
        public static void TwinDodecs()
        {
            Tiling       tiling = new Tiling();
            TilingConfig config = new TilingConfig(5, 3);

            tiling.GenerateInternal(config, Polytope.Projection.VertexCentered);                // Vertex-centered makes infinities tricky

            Dodec dodec = new Dodec();

            foreach (Tile tile in tiling.Tiles)
            {
                foreach (Segment seg in tile.Boundary.Segments)
                {
                    Vector3D p1 = seg.P1, p2 = seg.P2;
                    if (Infinity.IsInfinite(p1))
                    {
                        p1 = Infinity.InfinityVector;
                    }
                    if (Infinity.IsInfinite(p2))
                    {
                        p2 = Infinity.InfinityVector;
                    }

                    dodec.Verts.Add(p1);
                    dodec.Verts.Add(p2);
                    dodec.Midpoints.Add(Halfway(p1, p2));
                }
            }

            // Now recursively add more vertices.
            HashSet <Vector3D> allVerts = new HashSet <Vector3D>();

            foreach (Vector3D v in dodec.Verts)
            {
                allVerts.Add(v);
            }
            RecurseTwins(allVerts, dodec, 0);

            using (StreamWriter sw = File.CreateText("dual_dodecs_points_sphere.pov"))
            {
                foreach (Vector3D vert in allVerts)
                {
                    Vector3D onSphere = Sterographic.PlaneToSphereSafe(vert);
                    sw.WriteLine(PovRay.Sphere(new Sphere()
                    {
                        Center = onSphere, Radius = 0.01
                    }));

                    //if( !Infinity.IsInfinite( vert ) )
                    //	sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = 0.01 } ) );
                }
            }
        }
Ejemplo n.º 12
0
        public static Vector3D[] CalcViaProjections(Vector3D p1, Vector3D p2, Vector3D p3, int divisions, Geometry g)
        {
            if (g == Geometry.Euclidean)
            {
                throw new System.NotImplementedException();
            }

            Vector3D h1 = new Vector3D(), h2 = new Vector3D(), h3 = new Vector3D();

            if (g == Geometry.Hyperbolic)
            {
                h1 = Sterographic.PlaneToHyperboloid(p1);
                h2 = Sterographic.PlaneToHyperboloid(p2);
                h3 = Sterographic.PlaneToHyperboloid(p3);
            }
            else if (g == Geometry.Spherical)
            {
                h1 = Sterographic.PlaneToSphereSafe(p1);
                h2 = Sterographic.PlaneToSphereSafe(p2);
                h3 = Sterographic.PlaneToSphereSafe(p3);
            }

            List <Vector3D> temp = new List <Vector3D>();
            Segment         seg1 = Segment.Line(h1, h2);
            Segment         seg2 = Segment.Line(h3, h2);

            Vector3D[] s1 = seg1.Subdivide(divisions);
            Vector3D[] s2 = seg2.Subdivide(divisions);
            for (int i = 0; i < divisions; i++)
            {
                Segment seg = Segment.Line(s1[i], s2[i]);
                temp.AddRange(seg.Subdivide(divisions - i));
            }
            temp.Add(h2);

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

            foreach (Vector3D v in temp)
            {
                Vector3D copy = v;
                if (g == Geometry.Hyperbolic)
                {
                    Sterographic.NormalizeToHyperboloid(ref copy);
                    result.Add(Sterographic.HyperboloidToPlane(copy));
                }
                else if (g == Geometry.Spherical)
                {
                    copy.Normalize();
                    result.Add(Sterographic.SphereToPlane(copy));
                }
            }
            return(result.ToArray());
        }
Ejemplo n.º 13
0
        public static Vector3D Centroid(Geometry g, Vector3D[] conformalVerts)
        {
            if (g == Geometry.Euclidean)
            {
                Vector3D result = new Vector3D();
                foreach (Vector3D v in conformalVerts)
                {
                    result += v;
                }
                return(result / conformalVerts.Length);
            }

            Vector3D[] verts = conformalVerts.Select(v =>
            {
                switch (g)
                {
                case Geometry.Spherical:
                    return(Sterographic.PlaneToSphereSafe(v));

                case Geometry.Hyperbolic:
                    return(Sterographic.PlaneToHyperboloid(v));
                }

                throw new System.ArgumentException();
            }).ToArray();

            // https://math.stackexchange.com/a/2173370/300001
            Vector3D sum = new Vector3D();

            for (int i = 0; i < verts.Length; i++)
            {
                sum += verts[i];
            }
            Vector3D centroid = sum / Math.Sqrt(DotInGeometry(g, sum, sum));

            NormalizeInGeometry(g, ref centroid);

            switch (g)
            {
            case Geometry.Spherical:
                return(Sterographic.SphereToPlane(centroid));

            case Geometry.Hyperbolic:
                return(Sterographic.HyperboloidToPlane(centroid));
            }

            throw new System.ArgumentException();
        }
Ejemplo n.º 14
0
        public static void NormalizeInGeometry(Geometry g, ref Vector3D v)
        {
            switch (g)
            {
            case Geometry.Spherical:
                v.Normalize();
                break;

            case Geometry.Euclidean:
                throw new System.NotImplementedException();

            case Geometry.Hyperbolic:
                Sterographic.NormalizeToHyperboloid(ref v);
                break;
            }
        }
Ejemplo n.º 15
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);
            }
        }
Ejemplo n.º 16
0
        public bool Equals(Vector3D v1, Vector3D v2)
        {
            if (v1 == v2)
            {
                return(true);
            }

            Vector3D t1 = m_stereo ? Sterographic.R3toS3(v1) : v1;
            Vector3D t2 = m_stereo ? Sterographic.R3toS3(v2) : v2;

            if (t1 == t2 * -1)
            {
                return(true);
            }

            return(false);
        }
Ejemplo n.º 17
0
        private static void ProjectAndSave(List <Circle3D> circlesOnUnitSphere)
        {
            List <Circle3D> projected = new List <Circle3D>();

            foreach (Circle3D c in circlesOnUnitSphere)
            {
                Vector3D[] pp = c.RepresentativePoints.Select(p => Sterographic.SphereToPlane(p)).ToArray();

                Circle3D cProj = new Circle3D(pp[0], pp[1], pp[2]);
                if (Infinity.IsInfinite(cProj.Radius))
                {
                    continue;
                }
                cProj.Color = c.Color;
                projected.Add(cProj);
            }

            SaveToBmp(projected);
        }
Ejemplo n.º 18
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));
        }
Ejemplo n.º 19
0
        private static H3.Cell.Edge[] Cull120Cell(H3.Cell.Edge[] edges)
        {
            Func <Vector3D, bool> passes = new Func <Vector3D, bool>(v =>
            {
                //return
                //	Math.Pow( v.Z, 2 ) < 0.13 &&
                //	Math.Pow( v.W, 2 ) < 0.13;
                return(Tolerance.Equal(v.W, 0.0));
            });

            H3.Cell.Edge[] result = edges.Where(e =>
            {
                Vector3D start = Sterographic.R3toS3(e.Start);
                Vector3D end   = Sterographic.R3toS3(e.End);
                return(passes(start) && passes(end));
            }).ToArray();

            // Now cull valence-2 edges.
            //result = CullValence2Edges( result );

            return(result);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Calculates our pole from a stereographically projected sphere.
        /// Assume the input sphere is a geodesic sphere in the conformal model.
        /// </summary>
        public static GreatSphere FromSphere(Sphere s)
        {
            if (s.Center.IsOrigin)
            {
                return(new GreatSphere(new Vector3D(0, 0, 0, 1)));
            }

            if (s.IsPlane)
            {
                // If we are a plane, the pole is is on the unit sphere.
                Vector3D pole = s.Normal;
                pole.Normalize();
                return(new GreatSphere(Sterographic.R3toS3(pole)));
            }

            Vector3D v1 = Sterographic.R3toS3(s.Center + new Vector3D(s.Radius, 0, 0, 0));
            Vector3D v2 = Sterographic.R3toS3(s.Center + new Vector3D(0, s.Radius, 0, 0));
            Vector3D v3 = Sterographic.R3toS3(s.Center + new Vector3D(0, 0, s.Radius, 0));

            Vector3D o = Orthogonal(v1, v2, v3);

            return(new GreatSphere(o));
        }
Ejemplo n.º 21
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());
            }
        }
Ejemplo n.º 22
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();*/
        }
Ejemplo n.º 23
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");
            }
        }
Ejemplo n.º 24
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");
        }
Ejemplo n.º 25
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 );
        }
Ejemplo n.º 26
0
        private static void SpecialCase333()
        {
            /*
             *      HashSet<Vector3D> verts = new HashSet<Vector3D>();
             *      foreach( H3.Cell.Edge e in edges )
             *      {
             *              verts.Add( e.Start );
             *              verts.Add( e.End );
             *      }
             *
             *      /// We need to be smart such that the radius does not change too much at each step,
             *      /// and are going to do that by adding multiple edges.
             *      double upperTest = 35.25; // dist where rad ~300
             *
             *      System.Func<double, double> locationAtRad = rad =>
             *      {
             *              double min = 0;
             *              double max = upperTest;
             *              double current = upperTest / 2;
             *              double searchOffset = ( max - min ) / 4;
             *
             *              Vector3D cen;
             *              double radTest;
             *              H3Models.Ball.DupinCyclideSphere( verts.First() * current, .07 / 2, g, out cen, out radTest );
             *
             *              // iterate to it.
             *              double diff = Math.Abs( rad - radTest );
             *              int iterations = 1000;
             *              for( int i = 0; i < iterations; i++ )
             *              {
             *                      double t1, t2;
             *                      H3Models.Ball.DupinCyclideSphere( verts.First() * ( current + searchOffset ), .07 / 2, g, out cen, out t1 );
             *                      H3Models.Ball.DupinCyclideSphere( verts.First() * ( current - searchOffset ), .07 / 2, g, out cen, out t2 );
             *                      double d1 = Math.Abs( rad - t1 );
             *                      double d2 = Math.Abs( rad - t2 );
             *                      if( d1 == Math.Min( Math.Min( diff, d1 ), d2 ) )
             *                      {
             *                              diff = d1;
             *                              current += searchOffset;
             *                      }
             *                      if( d2 == Math.Min( Math.Min( diff, d1 ), d2 ) )
             *                      {
             *                              diff = d2;
             *                              current -= searchOffset;
             *                      }
             *
             *                      if( Tolerance.Equal( diff, 0.0, .0001 ) )
             *                              return current;
             *
             *                      searchOffset /= 2;
             *              }
             *
             *              throw new System.Exception();
             *      };
             *
             *      List<H3.Cell.Edge> toAdd = new List<H3.Cell.Edge>();
             *      foreach( Vector3D v in verts )
             *      {
             *              //toAdd.Add( new H3.Cell.Edge( v, v * 49 ) );
             *              //toAdd.Add( new H3.Cell.Edge( v * 45, v * 48.5 ) );	// need a lot of resolution here.
             *              toAdd.Add( new H3.Cell.Edge( v, v * 35.25 ) );
             *
             *              double maxRad = 300;
             *              double changePerEdge = 5;
             *              double last = 1.0;
             *              for( double rad = changePerEdge; rad < maxRad; rad += changePerEdge )
             *              {
             *                      double loc = locationAtRad( rad );
             *                      //toAdd.Add( new H3.Cell.Edge( v * last, v * loc ) );
             *                      last = loc;
             *              }
             *      }
             *      toAdd.AddRange( edges );
             *      edges = toAdd.ToArray();
             */

            // Sphere sweeps just not working - We need to add in clipped tori here.
            //Vector3D s3 = Sterographic.R3toS3( new Vector3D( 0.7 / 2, 0, 0 ) );
            Vector3D s3 = Sterographic.R3toS3(new Vector3D());

            s3 += new Vector3D();

            // r2 is major radius of torus.
            // r2 - r1 is minor radius of torus
            double   r1 = .07 / 2;
            double   r2;
            Vector3D cen;
            double   arbitrary = 0.25;

            H3Models.Ball.DupinCyclideSphere(new Vector3D(arbitrary, 0, 0), r1, Geometry.Spherical, out cen, out r2);
            double y   = cen.Abs();
            double rad = (r2 * r2 - r1 * r1 - y * y) / (2 * r1 - 2 * r2);
            double x   = rad + r1;

            System.Diagnostics.Trace.WriteLine(x);
        }