예제 #1
0
        /// <summary>
        /// This is like the GenCell method, but super hacked up for the Catacombs image with Henry.
        /// </summary>
        internal static void GenCellCatacombs( Sphere[] simplex, bool ball )
        {
            // We don't want to include the first mirror (which reflects across cells).
            Sphere[] mirrors = simplex.Skip( 1 ).ToArray();
            Sphere[] allMirrors = simplex.ToArray();

            // Simplices will be the "cells" in Recurse.CalcCells.
            H3.Cell.Facet[] simplexFacets = simplex.Select( m => new H3.Cell.Facet( m ) ).ToArray();

            // Offset cell boundary ever so slightly, to avoid artifacts of adjacent cells.
            Sphere toReflectLater = simplexFacets[0].Sphere.Clone();
            //simplexFacets[0].Sphere = CoxeterImages.GeodesicOffset( simplexFacets[0].Sphere, ball ? -1e-6 : 1e-7, ball );

            H3.Cell startingCell = new H3.Cell( simplexFacets );
            startingCell = startingCell.Clone();	// So our mirrors don't get munged after we reflect around later.
            Vector3D cen = new Vector3D( 0.05, 0.01, -0.05 );		//	373, 438
            //Vector3D cen = new Vector3D( 0.05, 0.01, 100 );		//	637
            //cen.RotateXY( Math.PI / 2 );	// only if we also rotate simplex mirrors.  XXX - make a setting.
            startingCell.Center = cen;
            H3.Cell[] simplices = Recurse.CalcCells( mirrors, new H3.Cell[] { startingCell }, new Recurse.Settings() { Ball = ball } );

            List<H3.Cell> simplicesFinal = new List<H3.Cell>();
            List<int[]> reflectionSets = new List<int[]>();
            // 1 reflects in x-axis
            // 3, 1 rotates right
            // 1, 3 rotates left

            reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 0, 1, 3 } );
            reflectionSets.Add( new int[] { 0, 3, 1, 2, 3, 1, 0, 3, 1, 2, 0, 3 } );

            // 2
            reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 1, 0, 3, 1, 3, 1, 3, 1, 2, 3, 1, 3, 2, 3, 1 } );
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 1, 0,		3, 1, 3, 1, 0,	3, 1, 3, 1, 3, 1, 2,	3, 1, 3, 2, 3, 1 } );

            // 3
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 1, 0, 3, 1, 3, 1, 0, 3, 1, 2 } );
            reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 0, 3, 1, 3, 1, 0, 2 } );
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 1, 0, 3, 1, 2 } );

            // 5
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 3, 1, 0, 1, 2, 3, 1 } );

            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 0, 2, 3, 1 } );
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 0, 3, 1, 3, 1, 3, 1, 2, 3, 1, 3, 1, 0, 1, 3 } );	// baby
            //reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 0, 3, 1, 3, 1, 3, 1, 2 } );	// maybe
            //reflectionSets.Add( new int[] { 0, 3, 1, 2, 3, 1, 0, 2, 1, 3 } );
            //reflectionSets.Add( new int[] { 0, 3, 1, 2, 3, 1, 0, 3, 1, 2 } );		// not great orientation
            // reflectionSets.Add( new int[] { 0, 3, 1, 3, 1, 2 } );	// big

            bool ceiling = true;
            if( ceiling )
                simplicesFinal = simplices.ToList();
            else
            {
                foreach( int[] set in reflectionSets )
                {
                    List<H3.Cell> copy = simplices.Select( s => s.Clone() ).ToList();
                    foreach( int r in set )
                    {
                        foreach( H3.Cell cell in copy )
                            cell.Reflect( allMirrors[r] );
                    }
                    simplicesFinal.AddRange( copy );
                }
            }

            /*
            // A second cell.
            //toReflectLater = simplices[45].Facets[0].Sphere.Clone();
            //toReflectLater = simplices.First( s => s.Depth == 2 ).Facets[0].Sphere.Clone();
            foreach( H3.Cell cell in simplices )
                cell.Reflect( toReflectLater );

            // A third cell.
            toReflectLater = simplices[40].Facets[0].Sphere.Clone();
            //toReflectLater = simplices.First( s => s.Depth == 4 ).Facets[0].Sphere.Clone();
            foreach( H3.Cell cell in simplices )
                cell.Reflect( toReflectLater );

            foreach( H3.Cell cell in simplices )
                cell.Depths = new int[4];
            List<H3.Cell> simplicesFinal = Recurse.CalcCells2( mirrors, simplices ).ToList();
            simplicesFinal = simplicesFinal.Where( s => s.Depths[0] % 3 == 1 && s.Depths[1] % 2 == 0 && s.Depths[2] % 2 == 1 ).ToList();
            */

            /*
            List<H3.Cell> simplicesFinal = new List<H3.Cell>();
            //for( int d = 0; d < 1; d+=2 )
            int d = 0;
            {
                //Sphere toReflect = simplices.First( s => s.Depth == d ).Facets[0].Sphere.Clone();
                //Sphere toReflect = simplices.Where( s => s.Depth == d ).Skip(1).Take(1).First().Facets[0].Sphere.Clone();
                List<H3.Cell> reflectionCells = simplices.Where( s => s.Depths[1] == d && s.Depths[0] % 2 == 0 ).Skip(0).Take(1).ToList();
                foreach( Sphere toReflect in reflectionCells.Select( c => c.Facets[0].Sphere.Clone() ) )
                {
                    List<H3.Cell> thisCell = new List<H3.Cell>();
                    foreach( H3.Cell cell in simplices )
                    {
                        H3.Cell clone = cell.Clone();
                        clone.Reflect( toReflect );
                        thisCell.Add( clone );
                    }

                    //Sphere toReflect2 = thisCell.First( s => s.Depth1 == d + 3 && s.Depth0 % 2 == 0 ).Facets[0].Sphere.Clone();
                    //List<H3.Cell> reflectionCellsTemp = simplices.Where( s => Math.Abs( s.Depths[1] - d ) == 2 && s.Depths[0] % 2 == 0 ).ToList();
                    List<H3.Cell> reflectionCellsTemp = simplices.Where( s => s.Depths[1] == 2 && s.Depths[1] == s.Depths[0] + s.Depths[2] ).ToList();
                    List<H3.Cell> reflectionCells2 = reflectionCellsTemp;//.Where( ( x, i ) => i % 3 == 0 ).ToList(); // .Skip( 5 ).Take( 5 ).ToList();
                    foreach( Sphere toReflect2 in reflectionCells2.Select( c => c.Facets[0].Sphere.Clone() ) )
                    //Sphere toReflect2 = toReflectLater;
                    {
                        foreach( H3.Cell cell in thisCell )
                        {
                            H3.Cell clone = cell.Clone();
                            clone.Reflect( toReflect2 );
                            simplicesFinal.Add( clone );
                        }
                    }
                }
            }*/

            int count = 0;
            foreach( H3.Cell cell in simplicesFinal )
            {
                count++;

                //if( count % 2 == 0 )
                //	continue;
                /*if( count < 1 )
                    continue;
                if( count > 30 )
                    return;
                 */
                //int[] include = new int[] { 0, 1, 2, 3 };
                int[] include = new int[] { 0 };
                PovRay.AppendSimplex( cell.Facets.Select( f => f.Sphere ).ToArray(), cell.Center, include, "cell.pov" );
            }
        }
예제 #2
0
        /// <summary>
        /// Used to generate a regular cell as a set of simplices and save to a Pov-ray file.
        /// This will work for non-finite cells.
        /// </summary>
        private static H3.Cell[] GenCell( Sphere[] simplex, Mesh mesh, Vector3D cen, bool ball, bool dual )
        {
            // We don't want to include the first mirror (which reflects across cells).
            Sphere[] mirrors = simplex.Skip( 1 ).ToArray();
            if( dual )
                mirrors = new Sphere[] { simplex[0], simplex[1], simplex[2] };
            Sphere[] allMirrors = simplex.ToArray();
            mirrors = simplex.ToArray();

            // Simplices will be the "cells" in Recurse.CalcCells.
            H3.Cell.Facet[] simplexFacets = simplex.Select( m => new H3.Cell.Facet( m ) ).ToArray();

            H3.Cell startingCell = new H3.Cell( simplexFacets );
            startingCell.Center = cen;
            startingCell.Mesh = mesh;

            //FCOrient( startingCell );

            startingCell = startingCell.Clone();	// So our mirrors don't get munged after we reflect around later.
            H3.Cell[] simplices = Recurse.CalcCells( mirrors, new H3.Cell[] { startingCell }, new Recurse.Settings() { Ball = ball } );
            //H3.Cell[] simplices = new H3.Cell[] { startingCell };

            // Layers.
            int layer = 0;
            return simplices.Where( s => s.Depths[0] <= layer /*&& s.Depths[0] == 3 && s.Depths[1] == 3*/ ).ToArray();
            //return simplices.ToArray();
        }
예제 #3
0
        private static H3.Cell[] GenTruss( Sphere[] simplex, Mesh mesh, Vector3D cen, bool ball )
        {
            // We don't want to include the first mirror (which reflects across cells).
            Sphere[] mirrors = simplex.Skip( 1 ).ToArray();
            Sphere[] allMirrors = simplex.ToArray();

            // Simplices will be the "cells" in Recurse.CalcCells.
            H3.Cell.Facet[] simplexFacets = simplex.Select( m => new H3.Cell.Facet( m ) ).ToArray();

            H3.Cell startingCell = new H3.Cell( simplexFacets );
            startingCell.Center = cen;

            //FCOrient( startingCell );
            //return null;

            startingCell = startingCell.Clone();	// So our mirrors don't get munged after we reflect around later.
            H3.Cell[] simplices = Recurse.CalcCells( mirrors, new H3.Cell[] { startingCell }, new Recurse.Settings() { Ball = ball } );
            //H3.Cell[] simplices = new H3.Cell[] { startingCell };

            // Subsets
            //return simplices.Where( s => s.Depths[0] == 1 ).ToArray();
            //return simplices.ToArray();

            List<H3.Cell> final = new List<H3.Cell>();
            final.AddRange( simplices );

            // Add in other truss cells.
            Recurse.Settings settings = new Recurse.Settings();
            foreach( int[] reflections in TrussReflections() )
            foreach( H3.Cell c in simplices )
            {
                H3.Cell clone = c.Clone();
                foreach( int r in reflections )
                    clone.Reflect( allMirrors[r] );
                if( Recurse.CellOk( clone, settings ) )
                    final.Add( clone );
            }

            return final.ToArray();
        }
예제 #4
0
        public static Sphere[] Mirrors( int p, int q, int r, ref Vector3D cellCenter, bool moveToBall = true, double scaling = -1 )
        {
            Geometry g = Util.GetGeometry( p, q, r );
            if( g == Geometry.Spherical )
                return SimplexCalcs.MirrorsSpherical( p, q, r );
            else if( g == Geometry.Euclidean )
                return SimplexCalcs.MirrorsEuclidean();

            // This is a rotation we'll apply to the mirrors at the end.
            // This is to try to make our image outputs have vertical bi-lateral symmetry and the most consistent in all cases.
            // NOTE: + is CW, not CCW. (Because the way I did things, our images have been reflected vertically, and I'm too lazy to go change this.)
            double rotation = Math.PI / 2;

            // Some construction points we need.
            Vector3D p1, p2, p3;
            Segment seg = null;
            TilePoints( p, q, out p1, out p2, out p3, out seg );

            //
            // Construct in UHS
            //

            Geometry cellGeometry = Geometry2D.GetGeometry( p, q );

            Vector3D center = new Vector3D();
            double radius = 0;
            if( cellGeometry == Geometry.Spherical )
            {
                // Finite or Infinite r

                // Spherical trig
                double halfSide = Geometry2D.GetTrianglePSide( q, p );
                double mag = Math.Sin( halfSide ) / Math.Cos( Util.PiOverNSafe( r ) );
                mag = Math.Asin( mag );

                // e.g. 43j
                //mag *= 0.95;

                // Move mag to p1.
                mag = Spherical2D.s2eNorm( mag );
                H3Models.Ball.DupinCyclideSphere( p1, mag, Geometry.Spherical, out center, out radius );
            }
            else if( cellGeometry == Geometry.Euclidean )
            {
                center = p1;
                radius = p1.Dist( p2 ) / Math.Cos( Util.PiOverNSafe( r ) );
            }
            else if( cellGeometry == Geometry.Hyperbolic )
            {
                if( Infinite( p ) && Infinite( q ) && FiniteOrInfinite( r ) )
                {
                    //double iiiCellRadius = 2 - Math.Sqrt( 2 );
                    //Circle3D iiiCircle = new Circle3D() { Center = new Vector3D( 1 - iiiCellRadius, 0, 0 ), Radius = iiiCellRadius };
                    //radius = iiiCellRadius;	// infinite r
                    //center = new Vector3D( 1 - radius, 0, 0 );

                    // For finite r, it was easier to calculate cell facet in a more symmetric position,
                    // then move into position with the other mirrors via a Mobius transformation.
                    double rTemp = 1 / ( Math.Cos( Util.PiOverNSafe( r ) ) + 1 );
                    Mobius m = new Mobius();
                    m.Isometry( Geometry.Hyperbolic, -Math.PI / 4, new Vector3D( 0, Math.Sqrt( 2 ) - 1 ) );
                    Vector3D c1 = m.Apply( new Vector3D( 1 - 2 * rTemp, 0, 0 ) );
                    Vector3D c2 = c1;
                    c2.Y *= -1;
                    Vector3D c3 = new Vector3D( 1, 0 );
                    Circle3D c = new Circle3D( c1, c2, c3 );

                    radius = c.Radius;
                    center = c.Center;
                }
                else if( Infinite( p ) && Finite( q ) && FiniteOrInfinite( r ) )
                {
                    // http://www.wolframalpha.com/input/?i=r%2Bx+%3D+1%2C+sin%28pi%2Fp%29+%3D+r%2Fx%2C+solve+for+r
                    // radius = 2 * Math.Sqrt( 3 ) - 3;	// Appolonian gasket wiki page
                    //radius = Math.Sin( Math.PI / q ) / ( Math.Sin( Math.PI / q ) + 1 );
                    //center = new Vector3D( 1 - radius, 0, 0 );

                    // For finite r, it was easier to calculate cell facet in a more symmetric position,
                    // then move into position with the other mirrors via a Mobius transformation.
                    double rTemp = 1 / ( Math.Cos( Util.PiOverNSafe( r ) ) + 1 );
                    Mobius m = new Mobius();
                    m.Isometry( Geometry.Hyperbolic, 0, p2 );
                    Vector3D findingAngle = m.Inverse().Apply( new Vector3D( 1, 0 ) );
                    double angle = Math.Atan2( findingAngle.Y, findingAngle.X );

                    m.Isometry( Geometry.Hyperbolic, angle, p2 );
                    Vector3D c1 = m.Apply( new Vector3D( 1 - 2 * rTemp, 0, 0 ) );
                    Vector3D c2 = c1;
                    c2.Y *= -1;
                    Vector3D c3 = new Vector3D( 1, 0 );
                    Circle3D c = new Circle3D( c1, c2, c3 );

                    radius = c.Radius;
                    center = c.Center;
                }
                else if( Finite( p ) && Infinite( q ) && FiniteOrInfinite( r ) )
                {
                    radius = p2.Abs(); // infinite r
                    radius = DonHatch.asinh( Math.Sinh( DonHatch.e2hNorm( p2.Abs() ) ) / Math.Cos( Util.PiOverNSafe( r ) ) );	// hyperbolic trig

                    // 4j3
                    //m_jOffset = radius * 0.02;
                    //radius += m_jOffset ;

                    radius = DonHatch.h2eNorm( radius );
                    center = new Vector3D();
                    rotation *= -1;
                }
                else if( /*Finite( p ) &&*/ Finite( q ) )
                {
                    // Infinite r
                    //double mag = Geometry2D.GetTrianglePSide( q, p );

                    // Finite or Infinite r
                    double halfSide = Geometry2D.GetTrianglePSide( q, p );
                    double mag = DonHatch.asinh( Math.Sinh( halfSide ) / Math.Cos( Util.PiOverNSafe( r ) ) );	// hyperbolic trig
                    H3Models.Ball.DupinCyclideSphere( p1, DonHatch.h2eNorm( mag ), out center, out radius );
                }
                else
                    throw new System.NotImplementedException();
            }
            Sphere cellBoundary = new Sphere()
            {
                Center = center,
                Radius = radius
            };

            Sphere[] interior = InteriorMirrors( p, q );
            Sphere[] surfaces = new Sphere[] { cellBoundary, interior[0], interior[1], interior[2] };

            // Apply rotations.
            bool applyRotations = true;
            if( applyRotations )
            {
                foreach( Sphere s in surfaces )
                    RotateSphere( s, rotation );
                p1.RotateXY( rotation );
            }

            // Apply scaling
            bool applyScaling = scaling != -1;
            if( applyScaling )
            {
                //double scale = 1.0/0.34390660467269524;
                //scale = 0.58643550768408892;
                foreach( Sphere s in surfaces )
                    Sphere.ScaleSphere( s, scaling );
            }

            bool facetCentered = false;
            if( facetCentered )
            {
                PrepForFacetCentering( p, q, surfaces, ref cellCenter );
            }

            // Move to ball if needed.
            Sphere[] result = surfaces.Select( s => moveToBall ? H3Models.UHSToBall( s ) : s ).ToArray();
            cellCenter = moveToBall ? H3Models.UHSToBall( cellCenter ) : cellCenter;

            return result;
        }