예제 #1
0
        /// <summary>
        /// Allow a hyperbolic transformation using an absolute offset.
        /// offset is specified in the respective geometry.
        /// </summary>
        public void Hyperbolic2(Geometry g, Complex fixedPlus, Complex point, double offset)
        {
            // To the origin.
            Mobius m = new Mobius();

            m.Isometry(g, 0, fixedPlus * -1);
            double eRadius = m.Apply(point).Magnitude;

            double scale = 1;

            switch (g)
            {
            case Geometry.Spherical:
                double sRadius = Spherical2D.e2sNorm(eRadius);
                sRadius += offset;
                scale    = Spherical2D.s2eNorm(sRadius) / eRadius;
                break;

            case Geometry.Euclidean:
                scale = (eRadius + offset) / eRadius;
                break;

            case Geometry.Hyperbolic:
                double hRadius = DonHatch.e2hNorm(eRadius);
                hRadius += offset;
                scale    = DonHatch.h2eNorm(hRadius) / eRadius;
                break;
            }

            Hyperbolic(g, fixedPlus, scale);
        }
예제 #2
0
        public void AnimationSections(Settings config)
        {
            HoneycombDef imageData = new HoneycombDef(config.P, config.Q, config.R);
            int          p = imageData.P, q = imageData.Q, r = imageData.R;

            string filename = imageData.FormatFilename();

            Sphere[] mirrors = SimplexCalcs.Mirrors(p, q, r);
            double   bounds  = 1.0;          //config.UhsBoundary.Bounds;

            bounds = 9.0;

            // Calculate the color scale.
            int size = 200;

            CoxeterImages.Settings settings = new CoxeterImages.Settings()
            {
                Honeycomb = imageData,
                Width     = size,
                Height    = size,
                Bounds    = bounds,
                Mirrors   = mirrors,
                FileName  = imageData.FormatFilename(),
            };

            CoxeterImages imageCalculator = new CoxeterImages();

            //imageCalculator.AutoCalcScale( settings );
            if (settings.ColorScaling < 1)
            {
                settings.ColorScaling = 15;
            }
            settings.ColorScaling = 11;

            Program.Log("\nGenerating sections...");
            size              = 500;
            settings.Width    = size;
            settings.Height   = size;
            settings.FileName = filename;

            double max = Spherical2D.e2sNorm(15);
            double min = Spherical2D.e2sNorm(1.0 / 15);

            DonHatch.e2hNorm(max);
            int    numSteps = 1800;          // 1 minute
            double step     = (max - min) / numSteps;

            for (int i = 0; i < 1; i++)
            {
                Program.Log("\nSection " + i);
                imageCalculator.m_z = 1.0 / 0.5;
                Spherical2D.s2eNorm(min + step * i);
                DonHatch.h2eNorm(step * i);
                settings.FileName = string.Format("533_{0:D4}.png", i);
                imageCalculator.GenImage(settings);
            }
        }
예제 #3
0
        /// <summary>
        /// Equally subdivides a segment with a startpoint at the origin, in the respective geometry.
        /// </summary>
        private static Vector3D[] SubdivideRadialInGeometry(Segment radial, int divisions, Geometry g)
        {
            List <Vector3D> result = new List <Vector3D>();

            if (radial.Type != SegmentType.Line)
            {
                Debug.Assert(false);
                return(result.ToArray());
            }

            switch (g)
            {
            case Geometry.Spherical:
            {
                double eLength   = radial.Length;
                double sLength   = Spherical2D.e2sNorm(eLength);
                double divLength = sLength / divisions;

                for (int i = 0; i <= divisions; i++)
                {
                    double temp = Spherical2D.s2eNorm(divLength * i);
                    result.Add(radial.P2 * temp / eLength);
                }

                break;
            }

            case Geometry.Euclidean:
                return(radial.Subdivide(divisions));

            case Geometry.Hyperbolic:
            {
                double eLength   = radial.Length;
                double hLength   = DonHatch.e2hNorm(eLength);
                double divLength = hLength / divisions;

                for (int i = 0; i <= divisions; i++)
                {
                    double temp = DonHatch.h2eNorm(divLength * i);
                    result.Add(radial.P2 * temp / eLength);
                }

                break;
            }
            }

            return(result.ToArray());
        }
예제 #4
0
        static public double OffsetInModel(Tiler.Settings settings, double p = 0, double q = 0, double r = 1)
        {
            double off = OffsetInSpace(settings, p, q, r);

            switch (settings.Geometry)
            {
            case Geometry.Spherical:
                off = Spherical2D.s2eNorm(off);
                break;

            case Geometry.Hyperbolic:
                off = DonHatch.h2eNorm(off);
                break;
            }
            return(off);
        }
예제 #5
0
        /// <summary>
        /// Calculate the 4 points defining the fundamental geodesic quadrilateral.
        /// </summary>
        private static Vector3D[] Verts(int m, int k)
        {
            double dist1 = Math.PI / (m + 1);
            double dist2 = Math.PI / (k + 1);

            Vector3D p4 = new Vector3D(1, 0);

            p4.RotateXY(dist2);

            return(new Vector3D[]
            {
                new Vector3D(),
                new Vector3D(1, 0),
                new Vector3D(0, 0, Spherical2D.s2eNorm(dist1)),
                p4
            });
        }
예제 #6
0
        public static Sphere GeodesicOffset(Sphere s, double offset, bool ball = true)
        {
            Sphere offsetSphere;

            if (ball)
            {
                // Geodesic offset (ball).

                {                       // Hyperbolic honeycomb
                    double mag = s.Center.Abs() - s.Radius;
                    mag = s.IsPlane ? DonHatch.h2eNorm(offset) :
                          DonHatch.h2eNorm(DonHatch.e2hNorm(mag) - offset);

                    Vector3D closestPointToOrigin = s.IsPlane ? s.Normal : s.Center;
                    closestPointToOrigin.Normalize();
                    closestPointToOrigin *= mag;
                    offsetSphere          = H3Models.Ball.OrthogonalSphereInterior(closestPointToOrigin);

                    // There are multiple ultraparallel spheres.
                    // This experiments with picking others.
                    Mobius m = new Mobius();
                    m.Isometry(Geometry.Hyperbolic, 0, new Vector3D(0, -0.2));
                    //H3Models.TransformInBall2( offsetSphere, m );
                }

                {                       // Spherical honeycomb
                                        //offset *= -1;
                    double mag = -s.Center.Abs() + s.Radius;
                    Spherical2D.s2eNorm(Spherical2D.e2sNorm(mag) + offset);

                    offsetSphere         = s.Clone();
                    offsetSphere.Radius += offset * 10;
                }
            }
            else
            {
                // Geodesic offset (UHS).
                // XXX - not scaled right.
                offsetSphere         = s.Clone();
                offsetSphere.Radius += offset;
            }

            return(offsetSphere);
        }
예제 #7
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();
                }
            }
        }