Пример #1
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()));
        }
Пример #2
0
        private static void CreateCellPovRay(HoneycombDef def, string filename, double t = 0)
        {
            int p = def.P;
            int q = def.Q;
            int r = def.R;

            //Vector3D trans = new Vector3D( 1.0/3, 0 ) * (2 + 2 * Math.Sin( Math.PI / 6 )) * t;
            //double scale = 1.8;
            Vector3D trans = new Vector3D();
            double   scale = 1.0;

            Vector3D[] sVerts = null;               // SimplexCalcs.VertsBall( p, q, r );

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

            // Just did this for everything.  Non-general position working better and will make all heads consistent.
            scale = 2.0;

            if (Geometry2D.GetGeometry(q, r) != Geometry.Hyperbolic)                // Vertex-centered if possible
            {
                scale = 1.0 / vUHS.Z;
            }
            //else if( Geometry2D.GetGeometry( p, q ) == Geometry.Hyperbolic ) // Make the biggest head somewhat smaller.
            //	scale = 2.0;

            Vector3D cen = InteriorPointBall;

            /*var kleinVerts = sVerts.Select( v => HyperbolicModels.PoincareToKlein( v ) );
             * Vector3D avg = new Vector3D();
             * foreach( Vector3D v in kleinVerts )
             *      avg += v;
             * avg /= kleinVerts.Count();
             * Vector3D cen = HyperbolicModels.KleinToPoincare( avg );*/
            cen  = H3Models.BallToUHS(cen);
            cen += trans;
            //cen *= scale;
            cen = H3Models.UHSToBall(cen);

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

            // Apply transformations.
            simplex = simplex.Select(s =>
            {
                Sphere.TranslateSphere(s, trans);
                Sphere.ScaleSphere(s, scale);
                return(H3Models.UHSToBall(s));
            }).ToArray();

            for (int i = 0; i < 4; i++)
            {
                if (simplex[i].IsPointInside(cen))
                {
                    simplex[i].Invert = true;
                }
            }

            Sphere[] simplexForColorScale = SimplexCalcs.Mirrors(p, q, r, moveToBall: true);
            CoxeterImages.Settings temp   = AutoCalcScale(def, simplexForColorScale);
            int maxDepth = (int)temp.ColorScaling;
            //Random rand = new Random( p+q+r );
            //int randOffset = rand.Next( maxDepth );

            bool ball = true;
            bool dual = false;

            H3.Cell[] simplicesFinal = GenCell(simplex, null, cen, ball, dual);

            using (StreamWriter sw = File.CreateText(filename))                 // We need to reuse this StreamWriter (vs. calling AppendSimplex) for performance.
            {
                sw.WriteLine("#include \"hyper_ball.pov\"");

                //int[] include = new int[] { 0, 1, 2, 3 };
                int[] include = new int[] { 0 };
                if (dual)
                {
                    include = new int[] { 3 }
                }
                ;

                // Output the facets.
                foreach (H3.Cell cell in simplicesFinal)
                {
                    Sphere[] facets = cell.Facets.Select(f => f.Sphere).ToArray();
                    if (m_toKlein)
                    {
                        facets = facets.Select(s => H3Models.BallToKlein(s)).ToArray();
                    }

                    int   depth = cell.Depths[0] + 1;
                    Color c     = Coloring.ColorAlongHexagon(maxDepth, depth);
                    if (cell.Depths.Sum() % 2 == 0)
                    {
                        c = Coloring.Inverse(c);
                    }
                    PovRay.AddSimplex(sw, facets, cell.Center, include, filename, Coloring.ToVec(c));
                }

                /*include = new int[] { 1, 2, 3 };
                 * foreach( H3.Cell cell in simplicesFinal )
                 * {
                 *      Sphere[] facets = cell.Facets.Select( f => f.Sphere ).ToArray();
                 *      Color c = Color.Red;
                 *      Vector3D cv = Coloring.ToVec( c );
                 *      cv.W = 0.9;
                 *      PovRay.AddSimplex( sw, facets, cell.Center, include, filename, cv );
                 * }*/
            }

            // Output the edges/verts.
            bool includeEdges = false;

            if (includeEdges)
            {
                sVerts = sVerts.Select(v =>
                {
                    v  = H3Models.BallToUHS(v);
                    v += trans;
                    v *= scale;
                    return(H3Models.UHSToBall(v));
                }).ToArray();

                H3.Cell.Edge[] edges = Recurse.CalcEdges(simplex.Skip(1).ToArray(),
                                                         new H3.Cell.Edge[] { new H3.Cell.Edge(sVerts[2], sVerts[3], order: false) },
                                                         new Recurse.Settings()
                {
                    Threshold = 0.01
                });
                PovRay.WriteH3Edges(new PovRay.Parameters {
                    AngularThickness = 0.01
                }, edges, filename, append: true);

                HashSet <Vector3D> verts = new HashSet <Vector3D>();
                foreach (H3.Cell.Edge e in edges)
                {
                    verts.Add(e.End);
                }
                PovRay.WriteVerts(new PovRay.Parameters {
                    AngularThickness = 0.02
                }, Geometry.Hyperbolic, verts.ToArray(), filename, append: true);
            }
        }
Пример #3
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;
                    }
                }
            }
        }
Пример #4
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();
                }
            }
        }