Ejemplo n.º 1
0
        private static List <Vector3D[]> BasePointsTiling()
        {
            TilingConfig config = new TilingConfig(3, 7, maxTiles: 100);
            Tiling       tiling = new Tiling();

            tiling.Generate(config);

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

            int numPerSeg = 25;
            List <Vector3D[]> basePoints = new List <Vector3D[]>();

            foreach (Tile t in tiling.Tiles)
            {
                foreach (Segment s in t.Boundary.Segments)
                {
                    H3.Cell.Edge e = new H3.Cell.Edge(s.P1, s.P2);
                    if (finished.Contains(e))
                    {
                        continue;
                    }
                    finished.Add(e);

                    Vector3D[] points = s.Subdivide(numPerSeg).Select(p =>
                    {
                        p = new Vector3D(p.X, 0, p.Y);
                        return(H3Models.BallToUHS(p));
                    }).ToArray();
                    basePoints.Add(points);
                }
            }

            return(basePoints);
        }
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
        private static bool EdgeOk(Edge edge, Settings s)
        {
            if (s.G == Geometry.Spherical)
            {
                return(true);
            }

            double thresh = s.Threshold;

            switch (s.ThreshType)
            {
            case EdgeThreshType.Length:

                // This will also work for ideal edges.
                return(edge.Start.Dist(edge.End) > thresh);

            case EdgeThreshType.Radial:

                return
                    (edge.Start.Abs() < thresh &&
                     edge.End.Abs() < thresh);
            }

            return(false);
        }
Ejemplo n.º 4
0
        private static List <H3.Cell.Edge> CopyAndProject(List <H3.Cell.Edge> regionEdges, Tiling tiling, double scale, Vector3D offset)
        {
            HashSet <H3.Cell.Edge> newEdges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer());
            //foreach( Tile tile in tiling.Tiles )	// Needed for doing full ball (rather than just half of it)
            Tile tile = tiling.Tiles.First();

            {
                foreach (H3.Cell.Edge edge in regionEdges)
                {
                    // Translation
                    // The isometry is necessary for the 363, but seems to mess up 636
                    Vector3D start = tile.Isometry.Apply(edge.Start) + offset;
                    Vector3D end   = tile.Isometry.Apply(edge.End) + offset;
                    //Vector3D start = edge.Start + tile.Center + offset;
                    //Vector3D end = edge.End + tile.Center + offset;

                    // Scaling
                    start *= scale;
                    end   *= scale;

                    // Projections
                    start = H3Models.UHSToBall(start);
                    end   = H3Models.UHSToBall(end);

                    H3.Cell.Edge transformed = new H3.Cell.Edge(start, end);
                    if (EdgeOkBall(transformed))
                    {
                        newEdges.Add(transformed);
                    }
                }
            }

            return(newEdges.ToList());
        }
Ejemplo n.º 5
0
        public static Vector3D EdgeToPlane(Geometry g, H3.Cell.Edge edge)
        {
            if (g != Geometry.Hyperbolic)
            {
                throw new System.NotImplementedException();
            }

            Vector3D b1, b2;

            H3Models.Ball.GeodesicIdealEndpoints(edge.Start, edge.End, out b1, out b2);
            if (((b2 + b1) / 2).IsOrigin)
            {
                Vector3D lineNormal = b2 - b1;
                lineNormal.RotateXY(Math.PI / 2);
                lineNormal.Normalize();
                return(new Vector3D(lineNormal.X, lineNormal.Y, lineNormal.Z, 0));
            }

            Vector3D center, normal;
            double   radius, angleTot;

            H3Models.Ball.Geodesic(edge.Start, edge.End, out center, out radius, out normal, out angleTot);

            Vector3D closest = H3Models.Ball.ClosestToOrigin(new Circle3D()
            {
                Center = center, Radius = radius, Normal = normal
            });
            Vector3D closestKlein = HyperbolicModels.PoincareToKlein(closest);

            center.Normalize();
            return(new Vector3D(center.X, center.Y, center.Z, closestKlein.Abs()));
        }
Ejemplo n.º 6
0
        public static void Cell633()
        {
            TilingConfig config = new TilingConfig(6, 3, maxTiles: 20000);
            Tiling       tiling = new Tiling();

            tiling.GenerateInternal(config, Polytope.Projection.VertexCentered);

            double edgeLength = Honeycomb.EdgeLength(6, 3, 3);

            double z      = 0.25;
            double offset = H3Models.UHS.ToEHorizontal(edgeLength, z);
            double scale  = offset / tiling.Tiles.First().Boundary.Segments.First().Length;

            foreach (Tile tile in tiling.Tiles)
            {
                tile.Transform(Mobius.Scale(scale));
            }

            Vector3D dummy;
            double   radius;

            H3Models.UHS.Geodesic(new Vector3D(0, 0, z), new Vector3D(scale, 0, z), out dummy, out radius);
            Vector3D midradius = H3Models.UHSToBall(new Vector3D(0, 0, radius));
            double   temp      = midradius.Z;
            double   temp2     = (1 - temp) / 2;
            double   temp3     = temp + temp2;
            double   temp4     = temp3;

            Vector3D circumradius = H3Models.UHSToBall(new Vector3D(0, 0, z));

            temp  = circumradius.Z;
            temp2 = (1 - temp) / 2;
            temp3 = temp + temp2;
            temp4 = temp3;

            // Checking

            /*
             * Vector3D test = new Vector3D( offset, 0, z );
             * test = H3Models.UHSToBall( test );
             * double edgeLength2 = DonHatch.e2hNorm( test.Abs() );
             * edgeLength2 += 0;
             */

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

            foreach (Tile tile in tiling.Tiles)
            {
                foreach (Segment seg in tile.Boundary.Segments)
                {
                    H3.Cell.Edge edge = new H3.Cell.Edge(
                        H3Models.UHSToBall(seg.P1 + new Vector3D(0, 0, z)),
                        H3Models.UHSToBall(seg.P2 + new Vector3D(0, 0, z)));
                    edges.Add(edge);
                }
            }

            PovRay.WriteH3Edges(new PovRay.Parameters(), edges.ToArray(), "edges.pov");
        }
Ejemplo n.º 7
0
        private static bool EdgeOkUHS(H3.Cell.Edge edge, Circle region)
        {
            if (Tolerance.GreaterThan(edge.Start.Abs(), region.Radius) ||
                Tolerance.GreaterThan(edge.End.Abs(), region.Radius))
            {
                return(false);
            }

            return(EdgeOk(edge, m_params.UhsCutoff));
        }
Ejemplo n.º 8
0
        H3.Cell.Edge Transform(H3.Cell.Edge edge, double t)
        {
            if (edge == null)
            {
                return(edge);
            }

            H3.Cell.Edge result = new H3.Cell.Edge(Transform(edge.Start, t), Transform(edge.End, t));
            result.Color = edge.Color;
            return(result);
        }
Ejemplo n.º 9
0
        void AddRow(Mesh mesh, H3.Cell.Edge edge1, H3.Cell.Edge edge2)
        {
            int div = 60;               // Has to be the same for all edges?

            if (edge1 == null && edge2 == null)
            {
                return;
            }

            System.Func <Vector3D, Vector3D, int, Vector3D[]> geoPoints = null;
            if (Ball)
            {
                geoPoints = H3Models.Ball.GeodesicPoints;
            }
            else
            {
                geoPoints = H3Models.UHS.GeodesicPoints;
            }

            if (edge1 == null || edge2 == null)
            {
                H3.Cell.Edge e = edge1 == null ? edge2 : edge1;
                if (e.Start == e.End)
                {
                    return;
                }

                Vector3D[] verts = geoPoints(e.Start, e.End, div);
                Vector3D   center, dummy;
                double     radius, dummyD;
                if (Ball)
                {
                    H3Models.Ball.Geodesic(e.Start, e.End, out center, out radius, out dummy, out dummyD);
                }
                else
                {
                    H3Models.UHS.Geodesic(e.Start, e.End, out center, out radius, out dummy, out dummyD);
                }
                for (int i = 0; i < verts.Length - 1; i++)
                {
                    mesh.Triangles.Add(new Mesh.Triangle(verts[i], verts[i + 1], center));                              // Radius will be small, so reasonable.
                }

                return;
            }

            Vector3D[] verts1 = geoPoints(edge1.Start, edge1.End, div);
            Vector3D[] verts2 = geoPoints(edge2.Start, edge2.End, div);
            for (int i = 0; i < verts1.Length - 1; i++)
            {
                mesh.Triangles.Add(new Mesh.Triangle(verts1[i], verts1[i + 1], verts2[i]));
                mesh.Triangles.Add(new Mesh.Triangle(verts2[i], verts1[i + 1], verts2[i + 1]));
            }
        }
Ejemplo n.º 10
0
 void CalcFibers(Vector3D[] basePoints, List <H3.Cell.Edge> fibers, double t)
 {
     foreach (Vector3D v in basePoints)
     {
         H3.Cell.Edge e = CalcFiberFromBase(v);
         if (e != null)
         {
             e.Color = Color(Transform(H3Models.UHSToBall(v), t));
         }
         fibers.Add(Transform(e, t));
     }
 }
Ejemplo n.º 11
0
        public static void Cell633()
        {
            TilingConfig config = new TilingConfig( 6, 3, maxTiles: 20000 );
            Tiling tiling = new Tiling();
            tiling.GenerateInternal( config, Polytope.Projection.VertexCentered );

            double edgeLength = Honeycomb.EdgeLength( 6, 3, 3 );

            double z = 0.25;
            double offset = H3Models.UHS.ToEHorizontal( edgeLength, z );
            double scale = offset / tiling.Tiles.First().Boundary.Segments.First().Length;
            foreach( Tile tile in tiling.Tiles )
                tile.Transform( Mobius.Scale( scale ) );

            Vector3D dummy;
            double radius;
            H3Models.UHS.Geodesic( new Vector3D( 0, 0, z ), new Vector3D( scale, 0, z ), out dummy, out radius );
            Vector3D midradius = H3Models.UHSToBall( new Vector3D( 0, 0, radius ) );
            double temp = midradius.Z;
            double temp2 = ( 1 - temp ) / 2;
            double temp3 = temp + temp2;
            double temp4 = temp3;

            Vector3D circumradius = H3Models.UHSToBall( new Vector3D( 0, 0, z ) );
            temp = circumradius.Z;
            temp2 = ( 1 - temp ) / 2;
            temp3 = temp + temp2;
            temp4 = temp3;

            // Checking
            /*
            Vector3D test = new Vector3D( offset, 0, z );
            test = H3Models.UHSToBall( test );
            double edgeLength2 = DonHatch.e2hNorm( test.Abs() );
            edgeLength2 += 0;
            */

            HashSet<H3.Cell.Edge> edges = new HashSet<H3.Cell.Edge>();
            foreach( Tile tile in tiling.Tiles )
                foreach( Segment seg in tile.Boundary.Segments )
                {
                    H3.Cell.Edge edge = new H3.Cell.Edge(
                        H3Models.UHSToBall( seg.P1 + new Vector3D( 0, 0, z ) ),
                        H3Models.UHSToBall( seg.P2 + new Vector3D( 0, 0, z ) ) );
                    edges.Add( edge );
                }

            PovRay.WriteH3Edges( new PovRay.Parameters(), edges.ToArray(), "edges.pov" );
        }
Ejemplo n.º 12
0
        private static string H3Edge(Parameters parameters, H3.Cell.Edge edge)
        {
            Vector3D v1 = edge.Start, v2 = edge.End;

            Vector3D[] points = null;
            Func <Vector3D, Sphere> sizeFunc = v => new Sphere()
            {
                Center = v, Radius = H3Models.SizeFuncConst(v, parameters.Scale)
            };

            if (parameters.Halfspace)
            {
                points = H3Models.UHS.GeodesicPoints(v1, v2);
                if (!parameters.ThinEdges)
                {
                    sizeFunc = v =>
                    {
                        // XXX, inexact
                        return(new Sphere()
                        {
                            Center = v, Radius = H3Models.UHS.SizeFunc(v, parameters.AngularThickness)
                        });
                    }
                }
                ;
            }
            else
            {
                points = H3Models.Ball.GeodesicPoints(v1, v2);
                if (!parameters.ThinEdges)
                {
                    sizeFunc = v =>
                    {
                        Vector3D c;
                        double   r;
                        H3Models.Ball.DupinCyclideSphere(v, parameters.AngularThickness / 2, out c, out r);
                        return(new Sphere()
                        {
                            Center = c, Radius = r
                        });
                        //return new Sphere() { Center = v, Radius = H3Models.Ball.SizeFunc( v, parameters.AngularThickness ) }; // inexact
                    }
                }
                ;
            }

            return(H3EdgeSphereSweep(points, sizeFunc));
        }
Ejemplo n.º 13
0
        private static H3.Cell.Facet GenFacet(Geometry g, int mirror1, int mirror2, Simplex simplex, Vector3D startingPoint)
        {
            List <Sphere> mirrors = new List <Sphere>();

            mirrors.Add(simplex.Facets[mirror1]);
            mirrors.Add(simplex.Facets[mirror2]);

            List <H3.Cell.Edge> startingEdges = new List <H3.Cell.Edge>();
            Vector3D            reflected     = simplex.ReflectInFacet(startingPoint, mirror1);

            startingEdges.Add(new H3.Cell.Edge(startingPoint, reflected));
            reflected = simplex.ReflectInFacet(startingPoint, mirror2);
            startingEdges.Add(new H3.Cell.Edge(startingPoint, reflected));
            startingEdges.RemoveAll(e => e.Start == e.End);
            if (startingEdges.Count == 0)
            {
                return(null);
            }

            H3.Cell.Edge[] completedEdges = Recurse.CalcEdges(mirrors.ToArray(), startingEdges.ToArray(), new Recurse.Settings()
            {
                G = g
            });
            if (completedEdges.Length == 1)
            {
                return(null);
            }

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

            H3.Cell.Edge edge    = completedEdges.First();
            Vector3D     start   = edge.Start;
            Vector3D     current = edge.End;

            facetVerts.Add(edge.End);
            while (current != start)
            {
                edge    = completedEdges.First(e => e != edge && (e.Start == current || e.End == current));
                current = edge.Start == current ? edge.End : edge.Start;
                facetVerts.Add(current);
            }

            return(new H3.Cell.Facet(facetVerts.ToArray()));
        }
Ejemplo n.º 14
0
        public static void Polarity()
        {
            TilingConfig config = new TilingConfig(3, 7, 50);
            Tiling       tiling = new Tiling();

            tiling.GenerateInternal(config);

            List <Vector3D>     points = new List <Vector3D>();
            List <H3.Cell.Edge> edges  = new List <H3.Cell.Edge>();

            foreach (Polygon p in tiling.Tiles.Select(t => t.Boundary))
            {
                foreach (Segment s in p.Segments)
                {
                    foreach (Vector3D v in s.Subdivide(25))
                    {
                        Vector3D     klein = HyperbolicModels.PoincareToKlein(v);
                        H3.Cell.Edge e     = Dual(klein);
                        points.Add(klein);
                        edges.Add(e);
                    }
                }
            }

            using (StreamWriter sw = File.CreateText("polarity.pov"))
            {
                double rad = 0.01;
                foreach (Vector3D vert in points)
                {
                    sw.WriteLine(PovRay.Sphere(new Sphere()
                    {
                        Center = vert, Radius = rad
                    }));
                }
                foreach (H3.Cell.Edge edge in edges)
                {
                    sw.WriteLine(PovRay.Cylinder(edge.Start, edge.End, rad / 2));
                }
            }
        }
Ejemplo n.º 15
0
        private static void ThinMesh(H3.Cell.Edge[] edges, System.Func <H3.Cell.Edge, Vector3D[]> divider,
                                     out Mesh thinMesh, out List <Vector3D[]> boundaryPoints)
        {
            thinMesh = new Mesh();

            boundaryPoints = new List <Vector3D[]>();
            List <Vector3D> starts = new List <Vector3D>();
            List <Vector3D> ends   = new List <Vector3D>();

            for (int i = 0; i < edges.Length - 1; i++)
            {
                int          idx1 = i;
                int          idx2 = i + 1;
                H3.Cell.Edge e1   = edges[idx1];
                H3.Cell.Edge e2   = edges[idx2];

                Vector3D[] points1 = divider(e1);
                Vector3D[] points2 = divider(e2);

                thinMesh.AddBand(points1, points2, close: false);

                starts.Add(e1.Start);
                ends.Add(e1.End);
                if (idx1 == 0)
                {
                    boundaryPoints.Add(points1);
                }
                if (idx2 == edges.Length - 1)
                {
                    boundaryPoints.Add(points2);
                    starts.Add(e2.Start);
                    ends.Add(e2.End);
                }
            }
            starts.Reverse();
            boundaryPoints.Add(starts.ToArray());
            boundaryPoints.Add(ends.ToArray());
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Helper to do one step of reflections.
        /// Returns a new list of region edges.
        /// </summary>
        private static List <H3.Cell.Edge> DoOneStep(List <H3.Cell.Edge> regionEdges, Tiling tiling, Circle region)
        {
            HashSet <H3.Cell.Edge> newEdges = new HashSet <H3.Cell.Edge>(new H3.Cell.EdgeEqualityComparer());

            foreach (Tile tile in tiling.Tiles)
            {
                foreach (H3.Cell.Edge edge in regionEdges)
                {
                    H3.Cell.Edge toAdd = null;
                    if (!Tolerance.Zero(tile.Center.Abs()))
                    {
                        // Translate
                        // The isometry is necessary for the 363, but seems to mess up 636
                        Vector3D start = tile.Isometry.Apply(edge.Start);
                        Vector3D end   = tile.Isometry.Apply(edge.End);
                        //Vector3D start = edge.Start + tile.Center;
                        //Vector3D end = edge.End + tile.Center;

                        // Reflect
                        start = region.ReflectPoint(start);
                        end   = region.ReflectPoint(end);

                        toAdd = new H3.Cell.Edge(start, end);
                    }
                    else
                    {
                        toAdd = edge;
                    }

                    if (EdgeOkUHS(toAdd, region))
                    {
                        newEdges.Add(toAdd);
                    }
                }
            }

            return(newEdges.ToList());
        }
Ejemplo n.º 17
0
        private static void AddEuclideanEdge(Shapeways mesh, HashSet <H3.Cell.Edge> completed, Vector3D start, Vector3D end)
        {
            H3.Cell.Edge edge = new H3.Cell.Edge(start, end);
            if (completed.Contains(edge))
            {
                return;
            }

            Shapeways tempMesh = new Shapeways();
            Segment   seg      = Segment.Line(start, end);

            int div = 20 - (int)(start.Abs() * 4);

            if (div < 1)
            {
                div = 1;
            }

            tempMesh.AddCurve(seg.Subdivide(div), .05);
            Transform(tempMesh.Mesh);

            mesh.Mesh.Triangles.AddRange(tempMesh.Mesh.Triangles);
            completed.Add(edge);
        }
Ejemplo n.º 18
0
        private static List<H3.Cell.Edge> CopyAndProject( List<H3.Cell.Edge> regionEdges, Tiling tiling, double scale, Vector3D offset )
        {
            HashSet<H3.Cell.Edge> newEdges = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() );
            //foreach( Tile tile in tiling.Tiles )	// Needed for doing full ball (rather than just half of it)
            Tile tile = tiling.Tiles.First();
            {
                foreach( H3.Cell.Edge edge in regionEdges )
                {
                    // Translation
                    // The isometry is necessary for the 363, but seems to mess up 636
                    Vector3D start = tile.Isometry.Apply( edge.Start ) + offset;
                    Vector3D end = tile.Isometry.Apply( edge.End ) + offset;
                    //Vector3D start = edge.Start + tile.Center + offset;
                    //Vector3D end = edge.End + tile.Center + offset;

                    // Scaling
                    start *= scale;
                    end *= scale;

                    // Projections
                    start = H3Models.UHSToBall( start );
                    end = H3Models.UHSToBall( end );

                    H3.Cell.Edge transformed = new H3.Cell.Edge( start, end );
                    if( EdgeOkBall( transformed ) )
                        newEdges.Add( transformed );
                }
            }

            return newEdges.ToList();
        }
Ejemplo n.º 19
0
 private static bool EdgeOk(H3.Cell.Edge edge, double cutoff)
 {
     return(edge.Start.Dist(edge.End) > cutoff);
 }
Ejemplo n.º 20
0
 private static bool EdgeOkBall(H3.Cell.Edge edge)
 {
     return(EdgeOk(edge, m_params.BallCutoff));
 }
Ejemplo n.º 21
0
        /// <summary>
        /// Helper to do one step of reflections.
        /// Returns a new list of region edges.
        /// </summary>
        private static List<H3.Cell.Edge> DoOneStep( List<H3.Cell.Edge> regionEdges, Tiling tiling, Circle region )
        {
            HashSet<H3.Cell.Edge> newEdges = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() );
            foreach( Tile tile in tiling.Tiles )
            {
                foreach( H3.Cell.Edge edge in regionEdges )
                {
                    H3.Cell.Edge toAdd = null;
                    if( !Tolerance.Zero( tile.Center.Abs() ) )
                    {
                        // Translate
                        // The isometry is necessary for the 363, but seems to mess up 636
                        Vector3D start = tile.Isometry.Apply( edge.Start );
                        Vector3D end = tile.Isometry.Apply( edge.End );
                        //Vector3D start = edge.Start + tile.Center;
                        //Vector3D end = edge.End + tile.Center;

                        // Reflect
                        start = region.ReflectPoint( start );
                        end = region.ReflectPoint( end );

                        toAdd = new H3.Cell.Edge( start, end );
                    }
                    else
                        toAdd = edge;

                    if( EdgeOkUHS( toAdd, region ) )
                        newEdges.Add( toAdd );
                }
            }

            return newEdges.ToList();
        }
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
        /// <summary>
        /// Create an STL file for a cell.
        /// Currently only works for cells with both hyperideal vertices and cells.
        /// </summary>
        public static void HoneycombHyperidealLegs(HoneycombDef def, int lod, Dictionary <Vector3D, H3.Cell> complete)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            m_div = TextureHelper.SetLevels(lod);

            bool ball = false;

            Sphere[]       simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: ball);
            H3.Cell.Edge[] edges;
            if (ball)
            {
                edges = SimplexCalcs.SimplexEdgesBall(p, q, r);
            }
            else
            {
                edges = SimplexCalcs.SimplexEdgesUHS(p, q, r);
            }

            // Two edges of one simplex facet.
            H3.Cell.Edge e1 = edges[2];
            H3.Cell.Edge e2 = edges[3];
            Vector3D[]   points1, points2;
            if (ball)
            {
                points1 = H3Models.Ball.GeodesicPoints(e1.Start, e1.End, 2 * m_div);
                points2 = H3Models.Ball.GeodesicPoints(e2.Start, e2.End, 2 * m_div);
            }
            else
            {
                points1 = H3Models.UHS.GeodesicPoints(e1.Start, e1.End, 2 * m_div);
                points2 = H3Models.UHS.GeodesicPoints(e2.Start, e2.End, 2 * m_div);
            }

            Sphere cellSphere   = simplex[0];
            Sphere vertexSphere = simplex[3];

            // Because one vertex the facet triangle is hyperideal, it will actually look like a square.
            List <Vector3D[]> allPoints = new List <Vector3D[]>();

            for (int i = 0; i < points1.Length; i++)
            {
                Vector3D p1 = points1[i];
                Vector3D p2 = points2[i];

                Vector3D[] arcPoints;
                if (i == points1.Length - 1)
                //if( false )
                {
                    // NOTE: This arc is not generally geodesic!
                    // Or is it?
                    arcPoints = ball ?
                                H3Models.Ball.GeodesicPoints(p1, p2, m_div) :
                                H3Models.UHS.GeodesicPoints(p1, p2, m_div);

                    /*Circle3D arc = cellSphere.Intersection( vertexSphere );
                     * double angleTot = (p1 - arc.Center).AngleTo( p2 - arc.Center );
                     * arcPoints = Shapeways.CalcArcPoints( arc.Center, arc.Radius, p1, arc.Normal, -angleTot, div );*/
                }
                else
                {
                    Circle3D c        = Circle3D.FromCenterAnd2Points(cellSphere.Center, p1, p2);
                    double   angleTot = (p1 - c.Center).AngleTo(p2 - c.Center);
                    arcPoints = Shapeways.CalcArcPoints(cellSphere.Center, cellSphere.Radius, p1, c.Normal, -angleTot, m_div);
                }
                //Vector3D[] arcPoints = new Vector3D[] { p1, p2 };
                allPoints.Add(arcPoints);
            }

            // Create the triangles for the patch.
            Mesh mesh = new Mesh();

            for (int i = 0; i < allPoints.Count - 1; i++)
            {
                Vector3D[] arc1 = allPoints[i];
                Vector3D[] arc2 = allPoints[i + 1];

                for (int j = 0; j < arc1.Length - 1; j++)
                {
                    // Points of (i,j) box;
                    Vector3D p1 = arc1[j];
                    Vector3D p2 = arc2[j];
                    Vector3D p3 = arc1[j + 1];
                    Vector3D p4 = arc2[j + 1];

                    Mesh.Triangle tri1 = new Mesh.Triangle(p1, p2, p3);
                    Mesh.Triangle tri2 = new Mesh.Triangle(p2, p4, p3);

                    // We need to thicken after reflecting around, otherwise we can't apply a min thickness.

                    /*Sphere normal = cellSphere;
                     * Mesh.Triangle[] thickened1 = Thicken( tri1, normal );
                     * Mesh.Triangle[] thickened2 = Thicken( tri2, normal );
                     * mesh.Triangles.AddRange( thickened1 );
                     * mesh.Triangles.AddRange( thickened2 );*/

                    mesh.Triangles.Add(tri1);
                    mesh.Triangles.Add(tri2);
                }
            }

            // AuxPoints will be used for multiple things.
            // - The first two points are for an an that will fill the gap where there is a missing face.
            // - We'll also store the points for the 4 edges of our fundamental triangle.
            List <Vector3D> auxPoints = new List <Vector3D>();
            {
                var             edge1 = allPoints.First();
                var             edge2 = allPoints.Last();
                List <Vector3D> edge3 = new List <Vector3D>(), edge4 = new List <Vector3D>();
                for (int i = 0; i < allPoints.Count; i++)
                {
                    edge3.Add(allPoints[i][0]);
                    edge4.Add(allPoints[i][allPoints[i].Length - 1]);
                }
                edge4.Reverse();

                auxPoints.Add(e1.Start);
                auxPoints.Add(e1.End);
                auxPoints.AddRange(edge1.Reverse());
                auxPoints.AddRange(edge2);
                auxPoints.AddRange(edge3);
                auxPoints.AddRange(edge4);
            }

            Vector3D cen = HoneycombPaper.InteriorPointBall;

            /* Reorientation code.  Move this elsewhere.
             *
             * // Face centered orientation.
             * bool faceCentered = false;
             * if( faceCentered )
             *      SimplexCalcs.PrepForFacetCentering( p, q, simplex, ref cen );
             *
             * Mobius mUHS = SimplexCalcs.FCOrientMobius( p, q );
             * Mobius mBall = HoneycombPaper.FCOrientMobius( H3Models.UHSToBall( cellSphere ) );
             *
             * simplex = simplex.Select( s =>
             * {
             *      s = H3Models.UHSToBall( s );
             *      //H3Models.TransformInBall2( s, mBall );
             *      return s;
             * } ).ToArray();
             *
             *
             * {
             *      for( int i = 0; i < mesh.Triangles.Count; i++ )
             *      {
             *              Mesh.Triangle tri = mesh.Triangles[i];
             *
             *              if( faceCentered )
             *              {
             *                      tri.a = mUHS.ApplyToQuaternion( tri.a );
             *                      tri.b = mUHS.ApplyToQuaternion( tri.b );
             *                      tri.c = mUHS.ApplyToQuaternion( tri.c );
             *              }
             *
             *              tri.a = H3Models.UHSToBall( tri.a );
             *              tri.b = H3Models.UHSToBall( tri.b );
             *              tri.c = H3Models.UHSToBall( tri.c );
             *
             *              if( faceCentered )
             *              {
             *                      tri.a = H3Models.TransformHelper( tri.a, mBall );
             *                      tri.b = H3Models.TransformHelper( tri.b, mBall );
             *                      tri.c = H3Models.TransformHelper( tri.c, mBall );
             *              }
             *              mesh.Triangles[i] = tri;
             *      }
             *
             *      if( faceCentered )
             *              cen = H3Models.TransformHelper( cen, mBall );
             * }
             */

            // Now we need to reflect around this fundamental patch.
            H3.Cell[] simplices = GenCell(simplex, mesh, cen, auxPoints.ToArray(), ball);

            // Existing cells take precedence.
            foreach (H3.Cell c in simplices)
            {
                Vector3D t = c.Center;
                H3.Cell  dummy;
                if (!complete.TryGetValue(t, out dummy))
                {
                    complete[t] = c;
                }
            }
        }
Ejemplo n.º 24
0
        private static void ReflectEdgesRecursive( Sphere[] simplex, Edge[] edges, Settings settings,
			HashSet<Edge> completedEdges )
        {
            if( 0 == edges.Length )
                return;

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

            foreach( Edge edge in edges )
            //foreach( Sphere mirror in simplex )
            for( int m=0; m<simplex.Length; m++ )
            {
                Sphere mirror = simplex[m];

                if( completedEdges.Count > settings.MaxEdges )
                    throw new System.Exception( "Maxing out edges - will result in uneven filling." );

                Vector3D r1 = mirror.ReflectPoint( edge.Start );
                Vector3D r2 = mirror.ReflectPoint( edge.End );

                Edge newEdge = new Edge( r1, r2 );
                newEdge.CopyDepthsFrom( edge );
                if( !EdgeOk( newEdge, settings ) )
                    continue;

                // This tracks reflections across the cell facets.
                newEdge.Depths[m]++;

                // Edge color.
                // Make the threshold length black, or the background color.
                double percentWhite = ( r1.Dist( r2 ) - settings.Threshold ) / 0.015;
                if( percentWhite < 0 )
                    percentWhite = 0;
                if( percentWhite > 1 )
                    percentWhite = 1;
                //newEdge.Color = new Vector3D( percentWhite, percentWhite, percentWhite );
                newEdge.Color = m_background;
                newEdge.Color.Z = 0.1 + 0.9 * percentWhite;

                if( completedEdges.Add( newEdge ) )
                {
                    // Haven't seen this edge yet, so
                    // we'll need to recurse on it.
                    newEdges.Add( newEdge );
                }
            }

            ReflectEdgesRecursive( simplex, newEdges.ToArray(), settings, completedEdges );
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Attempts to calculate approx 1.3M edges when the threshold is a minimum edge length.
        /// This is required for honeycombs with ideal or ultra-ideal cells
        /// </summary>
        public static Edge[] CalcEdgesSmart2( Sphere[] simplex, Edge[] edges )
        {
            Settings s = new Settings();

            // I found that log(1/thresh)/log(count) was relatively constant,
            // so we'll extrapolate that to get close to the right number of edges.
            double OneOverThresh = 60;
            s.Threshold = 1 / OneOverThresh;
            Edge[] result = CalcEdges( simplex, edges, s );
            int count1 = result.Length;

            OneOverThresh = 80;
            s.Threshold = 1 / OneOverThresh;
            result = CalcEdges( simplex, edges, s );
            int count2 = result.Length;

            double slope = ( Math.Log( count2 ) - Math.Log( count1 ) ) / ( Math.Log( 80 ) - Math.Log( 60 ) );

            // Why 1.3M?  We'll get 650k after we half this.
            double desiredCount = 2e6;
            //double desiredCount = 3e4;	// For testing
            double logDesiredCount = Math.Log( desiredCount );
            double temp = Math.Log( 80 ) + ( logDesiredCount - Math.Log( count2 ) ) / slope;

            s.Threshold = 1 / Math.Exp( temp );
            return CalcEdges( simplex, edges, s );
        }
Ejemplo n.º 26
0
        private static void HoneycombFiniteVertexFig(HoneycombDef def, int lod, Dictionary <Vector3D, H3.Cell> complete)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            double   scale = 1.0;
            Vector3D vUHS  = H3Models.BallToUHS(SimplexCalcs.VertexPointBall(p, q, r));

            if (Geometry2D.GetGeometry(q, r) != Geometry.Hyperbolic)                // Vertex-centered if possible
            {
                scale = 1.0 / vUHS.Z;
            }
            System.Func <Vector3D, Vector3D> trans = v =>
            {
                v  = H3Models.BallToUHS(v);
                v *= scale;
                v  = H3Models.UHSToBall(v);
                return(v);
            };

            bool ball = true;

            Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: ball);
            simplex = simplex.Select(s =>
            {
                s = H3Models.BallToUHS(s);
                Sphere.ScaleSphere(s, scale);
                s = H3Models.UHSToBall(s);
                return(s);
            }).ToArray();
            H3.Cell.Edge[] edges = SimplexCalcs.SimplexEdgesBall(p, q, r);

            // Two edges of the simplex facet.
            // NOTE: This contruction only works for material triangles, and matches the construction in the TextureHelper.
            m_div = TextureHelper.SetLevels(lod);
            int[]           elementIndices = TextureHelper.TextureElements(1, lod);
            List <Vector3D> points         = new List <Vector3D>();

            H3.Cell.Edge e1 = edges[2];
            H3.Cell.Edge e2 = edges[3];
            Vector3D     p1 = trans(e1.Start), p2 = trans(e1.End), p3 = trans(e2.End);

            Vector3D[] points1 = H3Models.Ball.GeodesicPoints(p2, p1, m_div);
            Vector3D[] points2 = H3Models.Ball.GeodesicPoints(p3, p1, m_div);
            for (int i = 0; i < m_div; i++)
            {
                points.AddRange(H3Models.Ball.GeodesicPoints(points1[i], points2[i], m_div - i));
            }
            points.Add(p1);

            Mesh mesh = new Mesh();

            for (int i = 0; i < elementIndices.Length / 3; i++)
            {
                int      idx1 = i * 3;
                int      idx2 = i * 3 + 1;
                int      idx3 = i * 3 + 2;
                Vector3D v1   = points[elementIndices[idx1]];
                Vector3D v2   = points[elementIndices[idx2]];
                Vector3D v3   = points[elementIndices[idx3]];
                mesh.Triangles.Add(new Mesh.Triangle(v1, v2, v3));
            }

            // AuxPoints will be used for multiple things.
            // - The first is a definition point for a face, so we can check for duplicates.
            // - We'll also store the points for the 3 edges of our fundamental triangle.
            List <Vector3D> auxPoints = new List <Vector3D>();
            {
                auxPoints.Add((p1 + p2 + p3) / 3);
                auxPoints.AddRange(points1);
                auxPoints.AddRange(points2.Reverse());
                auxPoints.AddRange(H3Models.Ball.GeodesicPoints(points2[0], points1[0], m_div));
            }

            Vector3D cen = HoneycombPaper.InteriorPointBall;

            H3.Cell[] simplices = GenCell(simplex, mesh, cen, auxPoints.ToArray(), ball);

            // Existing cells take precedence.
            foreach (H3.Cell c in simplices)
            {
                Vector3D t = c.AuxPoints[0];
                H3.Cell  dummy;
                if (!complete.TryGetValue(t, out dummy))
                {
                    complete[t] = c;
                }
            }
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Returns the 6 simplex edges in the UHS model.
        /// </summary>
        public static H3.Cell.Edge[] SimplexEdgesUHS( int p, int q, int r )
        {
            // Only implemented for honeycombs with both hyperideal edges/vertices right now.
            if( !( Geometry2D.GetGeometry( p, q ) == Geometry.Hyperbolic &&
                    Geometry2D.GetGeometry( q, r ) == Geometry.Hyperbolic ) )
                throw new System.NotImplementedException();

            Sphere[] simplex = SimplexCalcs.Mirrors( p, q, r, moveToBall: false );

            Circle[] circles = simplex.Select( s => H3Models.UHS.IdealCircle( s ) ).ToArray();

            Vector3D[] defPoints = new Vector3D[6];
            Vector3D dummy;
            Euclidean2D.IntersectionLineCircle( circles[1].P1, circles[1].P2, circles[0], out defPoints[0], out dummy );
            Euclidean2D.IntersectionLineCircle( circles[2].P1, circles[2].P2, circles[0], out defPoints[1], out dummy );
            Euclidean2D.IntersectionLineCircle( circles[1].P1, circles[1].P2, circles[3], out defPoints[2], out dummy );
            Euclidean2D.IntersectionLineCircle( circles[2].P1, circles[2].P2, circles[3], out defPoints[3], out dummy );

            Circle3D c = simplex[0].Intersection( simplex[3] );

            Vector3D normal = c.Normal;
            normal.RotateXY( Math.PI / 2 );
            Vector3D intersection;
            double height, off;

            Euclidean2D.IntersectionLineLine( c.Center, c.Center + normal, circles[1].P1, circles[1].P2, out intersection );
            off = ( intersection - c.Center ).Abs();
            height = Math.Sqrt( c.Radius * c.Radius - off * off );
            intersection.Z = height;
            defPoints[4] = intersection;

            Euclidean2D.IntersectionLineLine( c.Center, c.Center + normal, circles[2].P1, circles[2].P2, out intersection );
            off = ( intersection - c.Center ).Abs();
            height = Math.Sqrt( c.Radius * c.Radius - off * off );
            intersection.Z = height;
            defPoints[5] = intersection;

            bool order = false;
            H3.Cell.Edge[] edges = new H3.Cell.Edge[]
            {
                new H3.Cell.Edge( new Vector3D(), new Vector3D( 0, 0, 10 ) ),
                new H3.Cell.Edge( defPoints[4], defPoints[5], order ),
                new H3.Cell.Edge( defPoints[0], defPoints[4], order ),
                new H3.Cell.Edge( defPoints[1], defPoints[5], order ),
                new H3.Cell.Edge( defPoints[2], defPoints[4], order ),
                new H3.Cell.Edge( defPoints[3], defPoints[5], order ),
            };

            return edges;
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Returns the 6 simplex edges in the UHS model.
        /// </summary>
        public static H3.Cell.Edge[] SimplexEdgesUHS(int p, int q, int r)
        {
            // Only implemented for honeycombs with hyperideal cells right now.
            if (!(Geometry2D.GetGeometry(p, q) == Geometry.Hyperbolic))
            {
                throw new System.NotImplementedException();
            }

            Sphere[] simplex = SimplexCalcs.Mirrors(p, q, r, moveToBall: false);

            Circle[] circles = simplex.Select(s => H3Models.UHS.IdealCircle(s)).ToArray();

            Vector3D[] defPoints = new Vector3D[6];
            Vector3D   dummy;

            Euclidean2D.IntersectionLineCircle(circles[1].P1, circles[1].P2, circles[0], out defPoints[0], out dummy);
            Euclidean2D.IntersectionLineCircle(circles[2].P1, circles[2].P2, circles[0], out defPoints[1], out dummy);
            Euclidean2D.IntersectionLineCircle(circles[1].P1, circles[1].P2, circles[3], out defPoints[2], out dummy);
            Euclidean2D.IntersectionLineCircle(circles[2].P1, circles[2].P2, circles[3], out defPoints[3], out dummy);

            Circle3D c = simplex[0].Intersection(simplex[3]);

            Vector3D normal = c.Normal;

            normal.RotateXY(Math.PI / 2);
            Vector3D intersection;
            double   height, off;

            Euclidean2D.IntersectionLineLine(c.Center, c.Center + normal, circles[1].P1, circles[1].P2, out intersection);
            off            = (intersection - c.Center).Abs();
            height         = Math.Sqrt(c.Radius * c.Radius - off * off);
            intersection.Z = height;
            defPoints[4]   = intersection;

            Euclidean2D.IntersectionLineLine(c.Center, c.Center + normal, circles[2].P1, circles[2].P2, out intersection);
            off            = (intersection - c.Center).Abs();
            height         = Math.Sqrt(c.Radius * c.Radius - off * off);
            intersection.Z = height;
            defPoints[5]   = intersection;

            // Hyperideal vertex too?
            bool order = false;

            H3.Cell.Edge[] edges = null;
            if (Geometry2D.GetGeometry(q, r) == Geometry.Hyperbolic)
            {
                edges = new H3.Cell.Edge[]
                {
                    new H3.Cell.Edge(new Vector3D(), new Vector3D(0, 0, 10)),
                    new H3.Cell.Edge(defPoints[4], defPoints[5], order),
                    new H3.Cell.Edge(defPoints[0], defPoints[4], order),
                    new H3.Cell.Edge(defPoints[1], defPoints[5], order),
                    new H3.Cell.Edge(defPoints[2], defPoints[4], order),
                    new H3.Cell.Edge(defPoints[3], defPoints[5], order),
                };
            }
            else
            {
                Vector3D vPointUHS = H3Models.BallToUHS(VertexPointBall(p, q, r));
                defPoints[0] = defPoints[1] = vPointUHS;
                edges        = new H3.Cell.Edge[]
                {
                    new H3.Cell.Edge(vPointUHS, new Vector3D(0, 0, 10)),
                    new H3.Cell.Edge(defPoints[4], defPoints[5], order),
                    new H3.Cell.Edge(defPoints[0], defPoints[4], order),
                    new H3.Cell.Edge(defPoints[1], defPoints[5], order),
                    new H3.Cell.Edge(defPoints[2], defPoints[4], order),
                    new H3.Cell.Edge(defPoints[3], defPoints[5], order),
                };
            }

            return(edges);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Wendy's 77
        /// </summary>
        public static void Wendy(Simplex simplex, H3.Cell.Edge[] edges)
        {
            H3.Cell startingCell = null;

            Vector3D start = startingCell.Verts.First();

            Func <Vector3D, Vector3D> findAntipode = input =>
            {
                Vector3D antipode = new Vector3D();
                double   max      = double.MinValue;
                foreach (Vector3D v in startingCell.Verts)
                {
                    double d = H3Models.Ball.HDist(v, input);
                    if (d > max)
                    {
                        max      = d;
                        antipode = v;
                    }
                }
                return(antipode);
            };

            H3.Cell.Edge[] diagonals = new H3.Cell.Edge[] { new H3.Cell.Edge(start, findAntipode(start)) };
            diagonals = Recurse.CalcEdges(simplex.Facets, diagonals, new Recurse.Settings()
            {
                Threshold = 0.9983
            });

            // diagonals includes too much at this point (it includes all icosahedra diagonals, but we only want one diagonal from each cell).
            // We need to begin at 4 start points, and branch out from each to find the ones we want.

            var vertsToDiagonals = FindConnectedEdges(diagonals);
            var connectedEdges   = FindConnectedEdges(edges);

            // Get all edges (not diagonals) connected to start.
            List <H3.Cell.Edge> connectedToStart    = connectedEdges[start];
            Vector3D            startOpp            = connectedToStart[0].Opp(start);
            List <H3.Cell.Edge> connectedToStartOpp = connectedEdges[startOpp];

            // We need to pick 4 of these edges, arranged in a tetrahedron for our starting points.
            List <Vector3D> startingPoints = new List <Vector3D>();

            List <double> distances = new List <double>();

            // View1
            //startingPoints.Add( start );
            //foreach( Vector3D v in connectedToStartOpp.Select( e => e.Opp( startOpp ) ) )
            //	distances.Add( H3Models.Ball.HDist( startingPoints.First(), v ) );
            //startingPoints.Add( connectedToStartOpp[10].Opp( startOpp ) );
            //startingPoints.Add( connectedToStartOpp[13].Opp( startOpp ) );
            //startingPoints.Add( connectedToStartOpp[14].Opp( startOpp ) );

            // View2
            startingPoints.Add(startOpp);
            foreach (Vector3D v in connectedToStart.Select(e => e.Opp(start)))
            {
                distances.Add(H3Models.Ball.HDist(startingPoints.First(), v));
            }
            startingPoints.Add(connectedToStart[10].Opp(start));
            startingPoints.Add(connectedToStart[13].Opp(start));
            startingPoints.Add(connectedToStart[14].Opp(start));

            distances.Clear();
            distances.Add(H3Models.Ball.HDist(startingPoints[1], startingPoints[2]));
            distances.Add(H3Models.Ball.HDist(startingPoints[1], startingPoints[3]));
            distances.Add(H3Models.Ball.HDist(startingPoints[2], startingPoints[3]));
            distances.Add(H3Models.Ball.HDist(startingPoints[0], startingPoints[1]));
            distances.Add(H3Models.Ball.HDist(startingPoints[0], startingPoints[2]));
            distances.Add(H3Models.Ball.HDist(startingPoints[0], startingPoints[3]));
            double dist = 3.097167;

            Func <Vector3D[], H3.Cell.Edge[]> RemoveVerts = starting =>
            {
                List <H3.Cell.Edge> keepers      = new List <H3.Cell.Edge>();
                HashSet <Vector3D>  removedVerts = new HashSet <Vector3D>();
                Recurse.BranchAlongVerts(starting.ToArray(), vertsToDiagonals, removedVerts);
                foreach (H3.Cell.Edge e in edges)
                {
                    if (removedVerts.Contains(e.Start) || removedVerts.Contains(e.End))
                    {
                        continue;
                    }
                    keepers.Add(e);
                }
                return(keepers.ToArray());
            };

            edges = RemoveVerts(startingPoints.ToArray());

            bool done = false;

            while (!done)
            {
                done = true;
                var newConnectedEdges = FindConnectedEdges(edges);
                foreach (Vector3D v in newConnectedEdges.Keys)
                {
                    List <H3.Cell.Edge> oldEdgeList = connectedEdges[v];
                    List <H3.Cell.Edge> newEdgeList = newConnectedEdges[v];

                    // Only work edges that were full originally.
                    if (oldEdgeList.Count != 20)
                    {
                        continue;
                    }

                    // We need at least two to find the rest.
                    int newCount = newEdgeList.Count;
                    if (newCount > 16 && newCount < 19)
                    {
                        List <H3.Cell.Edge> removed = oldEdgeList.Except(newEdgeList, new H3.Cell.EdgeEqualityComparer()).ToList();

                        H3.Cell.Edge[] toTrim = newEdgeList.FindAll(e =>
                        {
                            foreach (H3.Cell.Edge alreadyRemoved in removed)
                            {
                                double d = H3Models.Ball.HDist(alreadyRemoved.Opp(v), e.Opp(v));
                                if (!Tolerance.Equal(dist, d, 0.00001))
                                {
                                    return(false);
                                }
                            }

                            return(true);
                        }).ToArray();

                        edges = RemoveVerts(toTrim.Select(e => e.Opp(v)).ToArray());
                        done  = false;
                    }

                    if (newCount == 20)
                    {
                        done = false;
                    }
                }
            }
        }
Ejemplo n.º 30
0
        private static string Edge(Parameters parameters, Geometry g, H3.Cell.Edge edge)
        {
            Vector3D v1 = edge.Start, v2 = edge.End;

            Vector3D[] points = null;
            Func <Vector3D, Sphere> sizeFunc = v => new Sphere()
            {
                Center = v, Radius = H3Models.SizeFuncConst(v, parameters.Scale)
            };

            //double minRad = 0.0005;
            double minRad = 0.0004;

            //double minRad = 0.0017;

            // STL
            //minRad = 0.8 / 100;

            if (parameters.Halfspace)
            {
                //v1 = H3Models.BallToUHS( v1 );
                //v2 = H3Models.BallToUHS( v2 );

                points = H3Models.UHS.GeodesicPoints(v1, v2);
                if (!parameters.ThinEdges)
                {
                    sizeFunc = v =>
                    {
                        // XXX, inexact
                        return(new Sphere()
                        {
                            Center = v, Radius = Math.Max(H3Models.UHS.SizeFunc(v, parameters.AngularThickness), minRad)
                        });
                    }
                }
                ;
            }
            else
            {
                if (g == Geometry.Hyperbolic)
                {
                    points = H3Models.Ball.GeodesicPoints(v1, v2, edge.Color.Z);
                }
                else if (g == Geometry.Spherical)
                {
                    points = S3.GeodesicPoints(v1, v2);
                    //points = points.Select( p => { p.Normalize(); return p; } ).ToArray();
                }
                else
                {
                    //points = new Vector3D[] { v1, v2 };
                    List <Vector3D> interpolated = new List <Vector3D>();
                    int             count        = 20;
                    for (int i = 0; i <= count; i++)
                    {
                        interpolated.Add(v1 + (v2 - v1) * ((double)i / count));
                    }
                    points = interpolated.ToArray();
                }

                if (!parameters.ThinEdges)
                {
                    sizeFunc = v =>
                    {
                        Vector3D c;
                        double   r;
                        H3Models.Ball.DupinCyclideSphere(v, parameters.AngularThickness / 2, g, out c, out r);
                        return(new Sphere()
                        {
                            Center = c, Radius = Math.Max(r, minRad)
                        });
                    }
                }
                ;
            }

            //if( g == Geometry.Euclidean )
            //	return EdgeCylinder( points, sizeFunc );

            return(EdgeSphereSweep(points, sizeFunc, edge.Color));
        }
Ejemplo n.º 31
0
        /// <summary>
        /// This generates a honeycomb by reflecting in 4 mirrors of the fundamental simplex.
        /// </summary>
        public static void OneHoneycombNew( HoneycombDef imageData )
        {
            int p = imageData.P;
            int q = imageData.Q;
            int r = imageData.R;

            double thickness = 0.1;
            double thicknessSpherical = Spherical2D.s2eNorm( thickness );
            double thicknessHyperbolic = R3.Math.DonHatch.h2eNorm( thickness );
            double threshold = 1;

            H3.Cell.Edge[] edges = null;
            H3.Cell[] cellsToHighlight = null;
            Sphere[] simplex = null;
            Vector3D vertex = new Vector3D();

            Geometry g = Util.GetGeometry( p, q, r );
            if( g == Geometry.Spherical )
            {
                thickness = thicknessSpherical /*.07 for 333*/  /* 0.05for 433*/  /*.025 for 533,335*/;
                threshold = 10000;

                simplex = SimplexCalcs.MirrorsSpherical( p, q, r );
                vertex = SimplexCalcs.VertexSpherical( p, q, r );

                // Ugly special casing for 333, since it has a vertex project to infinity.
                if( p == 3 && q == 3 && r == 3 )
                    SpecialCase333();
            }
            else if( g == Geometry.Euclidean )
            {
                thickness = thickness / 2;
                threshold = 5/*20*/;

                SimplexCalcs.CalcEScale();
                simplex = SimplexCalcs.MirrorsEuclidean();
                Vector3D[] verts = SimplexCalcs.VertsEuclidean();
                vertex = verts[2];
            }
            else
            {
                thickness = thicknessHyperbolic;
                threshold = 0.01;

                simplex = SimplexCalcs.Mirrors( p, q, r );
                Vector3D[] verts = SimplexCalcs.VertsBall( p, q, r );
                vertex = verts[2];

                //Vector3D[] simplexVerts = SimplexCalcs.VertsBall( p, q, r );
                //H3.Cell.Edge edge = new H3.Cell.Edge( simplexVerts[2], simplexVerts[3] );
                //H3.Cell.Edge edge = SimplexCalcs.HoneycombEdgeBall( p, q, r );
                //H3.Cell.Edge[] startingEdges = new H3.Cell.Edge[] { edge };

                //H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2( simplex, startingEdges );

                // Vertex Centered.
                bool vertexCentered = false;
                if( vertexCentered )
                {
                    Vector3D v = SimplexCalcs.VertexPointBall( p, q, r );
                    v = H3Models.BallToUHS( v );
                    double scale = 1.0 / v.Abs();
                    edges = edges.Select( e =>
                        {
                            Vector3D start = H3Models.UHSToBall( H3Models.BallToUHS( e.Start ) * scale );
                            Vector3D end = H3Models.UHSToBall( H3Models.BallToUHS( e.End ) * scale );
                            return new H3.Cell.Edge( start, end );
                        } ).ToArray();
                }

                // Code to show endpoints of 535
                /*using( StreamWriter sw = File.CreateText( "535_points.pov" ) )
                {
                    HashSet<Vector3D> verts = new HashSet<Vector3D>();
                    foreach( H3.Cell.Edge e in edges )
                    {
                        verts.Add( Sterographic.SphereToPlane( e.Start ) );
                        verts.Add( Sterographic.SphereToPlane( e.End ) );
                    }

                    foreach( Vector3D vert in verts )
                        if( !Infinity.IsInfinite( vert ) )
                            sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = 0.01 } ) );
                }*/
            }

            // Recurse
            bool dual = false;
            {
                H3.Cell.Edge[] startingEdges = null;
                if( dual )
                    startingEdges = new H3.Cell.Edge[] { SimplexCalcs.DualEdgeBall( simplex ) };
                else
                    startingEdges = new H3.Cell.Edge[] { SimplexCalcs.HoneycombEdgeBall( simplex, vertex ) };

                edges = Recurse.CalcEdges( simplex, startingEdges, new Recurse.Settings() { G = g, Threshold = threshold } );

                //CullHalfOfEdges( ref edges );

                // No need to cull edges in spherical case.
                // This was just to generate some images for 350-cell paper.
                //edges = Cull120Cell( edges );

                Simplex tet = new Simplex();
                tet.Facets = simplex;

                if( dual )
                {
                    H3.Cell.Edge[] oneDualCell = edges.Where( e => e.Depths[2] == 0 ).ToArray();
                    simplex = simplex.Skip( 1 ).ToArray();
                    edges = Recurse.CalcEdges( simplex, oneDualCell, new Recurse.Settings() { G = g, Threshold = threshold } );

                    int[] polyMirrors = new int[] { 0, 1, 3 };
                    H3.Cell startingCell = PolyhedronToHighlight( g, polyMirrors, tet, new Vector3D() );
                    cellsToHighlight = Recurse.CalcCells( simplex, new H3.Cell[] { startingCell } );
                    //cellsToHighlight = new H3.Cell[] { startingCell };
                    //cellsToHighlight = cellsToHighlight.Skip( 7 ).ToArray();
                }
                else
                {
                    int[] polyMirrors = new int[] { 1, 2, 3 };
                    H3.Cell startingCell = PolyhedronToHighlight( g, polyMirrors, tet, vertex );
                    //cellsToHighlight = Recurse.CalcCells( simplex, new H3.Cell[] { startingCell } );
                    cellsToHighlight = new H3.Cell[] { startingCell };
                }

                // Include just one cell?
                bool includeOne = false;
                if( includeOne )
                {
                    edges = edges.Where( e => e.Depths[0] == 0 ).ToArray();
                    //cellsToHighlight = cellsToHighlight.Where( c => c.Depths[0] == 0 ).ToArray();
                }
            }

            // Write the file
            bool pov = false;
            if( pov )
            {
                string filename = string.Format( "{0}{1}{2}.pov", p, q, r );
                PovRay.WriteEdges( new PovRay.Parameters() { AngularThickness = thickness }, g, edges,
                    filename, append: false );
                //File.Delete( filename );
                //PovRay.AppendFacets( cellsToHighlight, filename );

                HashSet<Vector3D> verts = new HashSet<Vector3D>();
                foreach( H3.Cell.Edge e in edges )
                {
                    verts.Add( e.Start );
                    verts.Add( e.End );
                }
                foreach( Vector3D v in verts )
                {
                    Vector3D t = v;
                    t.Normalize();
                    t *= 0.9;
                    System.Diagnostics.Trace.WriteLine( string.Format( "light_source {{ <{0},{1},{2}> White*.2 }}", t.X, t.Y, t.Z ) );
                }

                /*
                // Include the standard pov stuff, so we can batch this.
                string fileName = imageData.FormatFilename( string.Empty );
                using( StreamWriter sw = File.CreateText( fileName + ".pov" ) )
                {
                    sw.WriteLine( "#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\paper\\H3.pov\"" );
                }

                bool dummy = true;	// Doesn't matter for Pov-Ray, just Shapeways meshes.
                H3.SaveToFile( fileName, edges, dummy, append: true );
                */
            }
            else
            {
                if( g == Geometry.Spherical )
                {
                    edges = edges.Where( e => e.Start.Valid() && e.End.Valid() && !Infinity.IsInfinite( e.Start ) && !Infinity.IsInfinite( e.End ) ).ToArray();
                    S3.EdgesToStl( edges );
                }
                else
                    throw new System.NotImplementedException();
            }
        }
Ejemplo n.º 32
0
 public static Edge[] CalcEdges( Sphere[] simplex, Edge[] edges, Settings settings )
 {
     HashSet<Edge> completedEdges = new HashSet<Edge>( edges, new H3.Cell.EdgeEqualityComparer() );
     ReflectEdgesRecursive( simplex, completedEdges.ToArray(), settings, completedEdges );
     return completedEdges.ToArray();
 }
Ejemplo n.º 33
0
        private static bool EdgeOk( Edge edge, Settings s )
        {
            if( s.G == Geometry.Spherical )
                return true;

            double thresh = s.Threshold;

            bool useEdgeLength = s.G == Geometry.Hyperbolic;
            if( useEdgeLength )
            {
                // This will also work for ideal edges.
                return edge.Start.Dist( edge.End ) > thresh;
            }
            else
            {
                return
                    edge.Start.Abs() < thresh &&
                    edge.End.Abs() < thresh;
            }
        }
Ejemplo n.º 34
0
        /// <summary>
        /// Wendy's 77
        /// </summary>
        public static void Wendy( Simplex simplex, H3.Cell.Edge[] edges )
        {
            H3.Cell startingCell = null;

            Vector3D start = startingCell.Verts.First();

            Func<Vector3D, Vector3D> findAntipode = input =>
            {
                Vector3D antipode = new Vector3D();
                double max = double.MinValue;
                foreach( Vector3D v in startingCell.Verts )
                {
                    double d = H3Models.Ball.HDist( v, input );
                    if( d > max )
                    {
                        max = d;
                        antipode = v;
                    }
                }
                return antipode;
            };

            H3.Cell.Edge[] diagonals = new H3.Cell.Edge[] { new H3.Cell.Edge( start, findAntipode( start ) ) };
            diagonals = Recurse.CalcEdges( simplex.Facets, diagonals, new Recurse.Settings() { Threshold = 0.9983 } );

            // diagonals includes too much at this point (it includes all icosahedra diagonals, but we only want one diagonal from each cell).
            // We need to begin at 4 start points, and branch out from each to find the ones we want.

            var vertsToDiagonals = FindConnectedEdges( diagonals );
            var connectedEdges = FindConnectedEdges( edges );

            // Get all edges (not diagonals) connected to start.
            List<H3.Cell.Edge> connectedToStart = connectedEdges[start];
            Vector3D startOpp = connectedToStart[0].Opp( start );
            List<H3.Cell.Edge> connectedToStartOpp = connectedEdges[startOpp];

            // We need to pick 4 of these edges, arranged in a tetrahedron for our starting points.
            List<Vector3D> startingPoints = new List<Vector3D>();

            List<double> distances = new List<double>();

            // View1
            //startingPoints.Add( start );
            //foreach( Vector3D v in connectedToStartOpp.Select( e => e.Opp( startOpp ) ) )
            //	distances.Add( H3Models.Ball.HDist( startingPoints.First(), v ) );
            //startingPoints.Add( connectedToStartOpp[10].Opp( startOpp ) );
            //startingPoints.Add( connectedToStartOpp[13].Opp( startOpp ) );
            //startingPoints.Add( connectedToStartOpp[14].Opp( startOpp ) );

            // View2
            startingPoints.Add( startOpp );
            foreach( Vector3D v in connectedToStart.Select( e => e.Opp( start ) ) )
                distances.Add( H3Models.Ball.HDist( startingPoints.First(), v ) );
            startingPoints.Add( connectedToStart[10].Opp( start ) );
            startingPoints.Add( connectedToStart[13].Opp( start ) );
            startingPoints.Add( connectedToStart[14].Opp( start ) );

            distances.Clear();
            distances.Add( H3Models.Ball.HDist( startingPoints[1], startingPoints[2] ) );
            distances.Add( H3Models.Ball.HDist( startingPoints[1], startingPoints[3] ) );
            distances.Add( H3Models.Ball.HDist( startingPoints[2], startingPoints[3] ) );
            distances.Add( H3Models.Ball.HDist( startingPoints[0], startingPoints[1] ) );
            distances.Add( H3Models.Ball.HDist( startingPoints[0], startingPoints[2] ) );
            distances.Add( H3Models.Ball.HDist( startingPoints[0], startingPoints[3] ) );
            double dist = 3.097167;

            Func<Vector3D[], H3.Cell.Edge[]> RemoveVerts = starting =>
            {
                List<H3.Cell.Edge> keepers = new List<H3.Cell.Edge>();
                HashSet<Vector3D> removedVerts = new HashSet<Vector3D>();
                Recurse.BranchAlongVerts( starting.ToArray(), vertsToDiagonals, removedVerts );
                foreach( H3.Cell.Edge e in edges )
                {
                    if( removedVerts.Contains( e.Start ) || removedVerts.Contains( e.End ) )
                        continue;
                    keepers.Add( e );
                }
                return keepers.ToArray();
            };

            edges = RemoveVerts( startingPoints.ToArray() );

            bool done = false;
            while( !done )
            {
                done = true;
                var newConnectedEdges = FindConnectedEdges( edges );
                foreach( Vector3D v in newConnectedEdges.Keys )
                {
                    List<H3.Cell.Edge> oldEdgeList = connectedEdges[v];
                    List<H3.Cell.Edge> newEdgeList = newConnectedEdges[v];

                    // Only work edges that were full originally.
                    if( oldEdgeList.Count != 20 )
                        continue;

                    // We need at least two to find the rest.
                    int newCount = newEdgeList.Count;
                    if( newCount > 16 && newCount < 19 )
                    {
                        List<H3.Cell.Edge> removed = oldEdgeList.Except( newEdgeList, new H3.Cell.EdgeEqualityComparer() ).ToList();

                        H3.Cell.Edge[] toTrim = newEdgeList.FindAll( e =>
                        {
                            foreach( H3.Cell.Edge alreadyRemoved in removed )
                            {
                                double d = H3Models.Ball.HDist( alreadyRemoved.Opp( v ), e.Opp( v ) );
                                if( !Tolerance.Equal( dist, d, 0.00001 ) )
                                    return false;
                            }

                            return true;
                        } ).ToArray();

                        edges = RemoveVerts( toTrim.Select( e => e.Opp( v ) ).ToArray() );
                        done = false;
                    }

                    if( newCount == 20 )
                        done = false;
                }
            }
        }
Ejemplo n.º 35
0
 public static Edge[] CalcEdges( Sphere[] simplex, Edge[] edges )
 {
     Settings settings = new Settings();
     return CalcEdges( simplex, edges, settings );
 }
Ejemplo n.º 36
0
        private static void ReflectEdgesRecursive(Sphere[] simplex, Edge[] edges, Settings settings,
                                                  HashSet <Edge> completedEdges)
        {
            if (0 == edges.Length)
            {
                return;
            }

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

            foreach (Edge edge in edges)
            {
                //foreach( Sphere mirror in simplex )
                for (int m = 0; m < simplex.Length; m++)
                {
                    Sphere mirror = simplex[m];

                    if (completedEdges.Count > settings.MaxEdges)
                    {
                        throw new System.Exception("Maxing out edges - will result in uneven filling.");
                    }

                    Vector3D r1 = mirror.ReflectPoint(edge.Start);
                    Vector3D r2 = mirror.ReflectPoint(edge.End);

                    Edge newEdge = new Edge(r1, r2);
                    newEdge.CopyDepthsFrom(edge);
                    if (!EdgeOk(newEdge, settings))
                    {
                        continue;
                    }

                    // This tracks reflections across the cell facets.
                    newEdge.Depths[m]++;

                    // Edge color.
                    // This also controls resolution of the edges, and can have a big effect on file size.
                    // Make the threshold cutoff black, or the background color.
                    double percentWhite = 1;
                    if (settings.ThreshType == EdgeThreshType.Length)
                    {
                        percentWhite = (r1.Dist(r2) - settings.Threshold) / 0.015;
                    }
                    else
                    {
                        double closestToOrigin = Math.Min(r1.Abs(), r2.Abs());                          // Mainly ranges from 0 to 1
                        if (closestToOrigin < 0.9)
                        {
                            percentWhite = 1.0;
                        }
                        else
                        {
                            percentWhite = 1.0 - Math.Pow(closestToOrigin - 0.9, 1.3) / 0.1;
                        }
                    }
                    if (percentWhite < 0)
                    {
                        percentWhite = 0;
                    }
                    if (percentWhite > 1)
                    {
                        percentWhite = 1;
                    }
                    //newEdge.Color = new Vector3D( percentWhite, percentWhite, percentWhite );
                    newEdge.Color   = m_background;
                    newEdge.Color.Z = 0.1 + 0.9 * percentWhite;

                    if (completedEdges.Add(newEdge))
                    {
                        // Haven't seen this edge yet, so
                        // we'll need to recurse on it.
                        newEdges.Add(newEdge);
                    }
                }
            }

            ReflectEdgesRecursive(simplex, newEdges.ToArray(), settings, completedEdges);
        }
Ejemplo n.º 37
0
        /// <summary>
        /// Attempts to calculate approx 1.3M edges when the threshold is a distance from origin in the ball model.
        /// This works for honeycombs with finite cells.
        /// </summary>
        public static Edge[] CalcEdgesSmart( Sphere[] simplex, Edge[] edges )
        {
            Settings s = new Settings();

            // The number of cells increase exponentially with hyperbolic distance,
            // so linear on a log scale.
            // We'll do to test runs to get the line, then run at the extrapolated value.
            double hDist = 5;
            s.Threshold = DonHatch.h2eNorm( hDist );
            Edge[] result = CalcEdges( simplex, edges, s );
            int count1 = result.Length;

            hDist = 5.5;
            s.Threshold = DonHatch.h2eNorm( hDist );
            result = CalcEdges( simplex, edges, s );
            int count2 = result.Length;

            double slope = ( Math.Log( count2 ) - Math.Log( count1 ) ) / 0.5;

            // Why 1.3M?  We'll get 650k after we half this.
            double desiredCount = 1.0e4;		// for testing
            //double desiredCount = 1.3e6;
            //double desiredCount = 0.4e6;	// Mid-range
            double logDesiredCount = Math.Log( desiredCount );
            hDist = 5.5 + ( logDesiredCount - Math.Log( count2 ) ) / slope;

            s.Threshold = DonHatch.h2eNorm( hDist );
            return CalcEdges( simplex, edges, s );
        }
Ejemplo n.º 38
0
        /// <summary>
        /// This generates a honeycomb by reflecting in 4 mirrors of the fundamental simplex.
        /// This "new" method is now old.
        /// </summary>
        public static void OneHoneycombNew(HoneycombDef imageData)
        {
            int p = imageData.P;
            int q = imageData.Q;
            int r = imageData.R;

            double thickness           = 0.05;
            double thicknessSpherical  = Spherical2D.s2eNorm(thickness);
            double thicknessHyperbolic = R3.Math.DonHatch.h2eNorm(thickness);
            double threshold           = 1;

            H3.Cell.Edge[] edges            = null;
            H3.Cell[]      cellsToHighlight = null;
            Sphere[]       simplex          = null;
            Vector3D       vertex           = new Vector3D();

            Geometry g = Util.GetGeometry(p, q, r);

            if (g == Geometry.Spherical)
            {
                thickness = thicknessSpherical /*.07 for 333*/  /* 0.05for 433*/  /*.025 for 533,335*/;
                threshold = 10000;

                simplex = SimplexCalcs.MirrorsSpherical(p, q, r);
                vertex  = SimplexCalcs.VertexSpherical(p, q, r);

                // Ugly special casing for 333, since it has a vertex project to infinity.
                if (p == 3 && q == 3 && r == 3)
                {
                    SpecialCase333();
                }
            }
            else if (g == Geometry.Euclidean)
            {
                thickness = thickness / 2;
                threshold = 1 /*20*/;

                //SimplexCalcs.CalcEScale();
                simplex = SimplexCalcs.MirrorsEuclidean();
                Vector3D[] verts = SimplexCalcs.VertsEuclidean();
                vertex = verts[2];
            }
            else
            {
                thickness = thicknessHyperbolic;
                threshold = 0.01;

                simplex = SimplexCalcs.Mirrors(p, q, r);
                Vector3D[] verts = SimplexCalcs.VertsBall(p, q, r);
                vertex = verts[2];

                //Vector3D[] simplexVerts = SimplexCalcs.VertsBall( p, q, r );
                //H3.Cell.Edge edge = new H3.Cell.Edge( simplexVerts[2], simplexVerts[3] );
                //H3.Cell.Edge edge = SimplexCalcs.HoneycombEdgeBall( p, q, r );
                //H3.Cell.Edge[] startingEdges = new H3.Cell.Edge[] { edge };

                //H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2( simplex, startingEdges );

                // Vertex Centered.
                bool vertexCentered = false;
                if (vertexCentered)
                {
                    Vector3D v = SimplexCalcs.VertexPointBall(p, q, r);
                    v = H3Models.BallToUHS(v);
                    double scale = 1.0 / v.Abs();
                    edges = edges.Select(e =>
                    {
                        Vector3D start = H3Models.UHSToBall(H3Models.BallToUHS(e.Start) * scale);
                        Vector3D end   = H3Models.UHSToBall(H3Models.BallToUHS(e.End) * scale);
                        return(new H3.Cell.Edge(start, end));
                    }).ToArray();
                }

                // Code to show endpoints of 535

                /*using( StreamWriter sw = File.CreateText( "535_points.pov" ) )
                 * {
                 *      HashSet<Vector3D> verts = new HashSet<Vector3D>();
                 *      foreach( H3.Cell.Edge e in edges )
                 *      {
                 *              verts.Add( Sterographic.SphereToPlane( e.Start ) );
                 *              verts.Add( Sterographic.SphereToPlane( e.End ) );
                 *      }
                 *
                 *      foreach( Vector3D vert in verts )
                 *              if( !Infinity.IsInfinite( vert ) )
                 *                      sw.WriteLine( PovRay.Sphere( new Sphere() { Center = vert, Radius = 0.01 } ) );
                 * }*/
            }

            // Recurse
            bool dual = false;
            {
                H3.Cell.Edge[] startingEdges = null;
                if (dual)
                {
                    startingEdges = new H3.Cell.Edge[] { SimplexCalcs.DualEdgeBall(simplex) }
                }
                ;
                else
                {
                    //startingEdges = new H3.Cell.Edge[] { SimplexCalcs.HoneycombEdgeBall( simplex, vertex ) };
                    Vector3D[] verts  = SimplexCalcs.VertsEuclidean();
                    Vector3D   v1     = verts[0] + 2 * verts[2];             // adjacent cube center
                    Vector3D   corner = verts[3];

                    startingEdges = new H3.Cell.Edge[] { new H3.Cell.Edge(v1, corner) };
                }

                edges = Recurse.CalcEdges(simplex, startingEdges, new Recurse.Settings()
                {
                    G = g, Threshold = threshold
                });

                edges = edges.Where(e =>
                {
                    int sum = e.Depths.Count(d => d == 0);
                    return(true);
                }).ToArray();

                //CullHalfOfEdges( ref edges );

                // No need to cull edges in spherical case.
                // This was just to generate some images for 350-cell paper.
                //edges = Cull120Cell( edges );

                Simplex tet = new Simplex();
                tet.Facets = simplex;

                if (dual)
                {
                    H3.Cell.Edge[] oneDualCell = edges.Where(e => e.Depths[2] == 0).ToArray();
                    simplex = simplex.Skip(1).ToArray();
                    edges   = Recurse.CalcEdges(simplex, oneDualCell, new Recurse.Settings()
                    {
                        G = g, Threshold = threshold
                    });

                    int[]   polyMirrors  = new int[] { 0, 1, 3 };
                    H3.Cell startingCell = HoneycombGen.PolyhedronToHighlight(g, polyMirrors, tet, new Vector3D());
                    cellsToHighlight = Recurse.CalcCells(simplex, new H3.Cell[] { startingCell });
                    //cellsToHighlight = new H3.Cell[] { startingCell };
                    //cellsToHighlight = cellsToHighlight.Skip( 7 ).ToArray();
                }
                else
                {
                    int[]   polyMirrors  = new int[] { 1, 2, 3 };
                    H3.Cell startingCell = HoneycombGen.PolyhedronToHighlight(g, polyMirrors, tet, vertex);
                    //cellsToHighlight = Recurse.CalcCells( simplex, new H3.Cell[] { startingCell } );
                    cellsToHighlight = new H3.Cell[] { startingCell };
                }

                // Include just one cell?
                bool includeOne = false;
                if (includeOne)
                {
                    edges = edges.Where(e => e.Depths[0] == 0).ToArray();
                    //cellsToHighlight = cellsToHighlight.Where( c => c.Depths[0] == 0 ).ToArray();
                }
            }

            // Rotate
            bool rotate = false;

            if (rotate)
            {
                CompoundOfFive24Cells(ref edges);
            }

            // Write the file
            bool pov = true;

            if (pov)
            {
                string filename = string.Format("{0}{1}{2}.pov", p, q, r);
                PovRay.WriteEdges(new PovRay.Parameters()
                {
                    AngularThickness = thickness
                }, g, edges,
                                  filename, append: false);
                //File.Delete( filename );
                //PovRay.AppendFacets( cellsToHighlight, filename );

                HashSet <Vector3D> verts = new HashSet <Vector3D>();
                foreach (H3.Cell.Edge e in edges)
                {
                    verts.Add(e.Start);
                    verts.Add(e.End);
                }

                /*foreach( Vector3D v in verts )
                 * {
                 *      Vector3D t = v;
                 *      t.Normalize();
                 *      t *= 0.9;
                 *      System.Diagnostics.Trace.WriteLine( string.Format( "light_source {{ <{0},{1},{2}> White*.2 }}", t.X, t.Y, t.Z ) );
                 * }*/


                /*
                 * // Include the standard pov stuff, so we can batch this.
                 * string fileName = imageData.FormatFilename( string.Empty );
                 * using( StreamWriter sw = File.CreateText( fileName + ".pov" ) )
                 * {
                 *      sw.WriteLine( "#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\paper\\H3.pov\"" );
                 * }
                 *
                 * bool dummy = true;	// Doesn't matter for Pov-Ray, just Shapeways meshes.
                 * H3.SaveToFile( fileName, edges, dummy, append: true );
                 */
            }
            else
            {
                if (g == Geometry.Spherical)
                {
                    edges = edges.Where(e => e.Start.Valid() && e.End.Valid() && !Infinity.IsInfinite(e.Start) && !Infinity.IsInfinite(e.End)).ToArray();
                    S3.EdgesToStl(edges);
                }
                else
                {
                    throw new System.NotImplementedException();
                }
            }
        }