Example #1
1
 public static H3.Cell[] CalcCells2( Sphere[] mirrors, H3.Cell[] cells, Settings settings )
 {
     HashSet<Vector3D> completedCellIds = new HashSet<Vector3D>( cells.Select( c => c.ID ).ToArray() );
     List<H3.Cell> completedCells = new List<H3.Cell>( cells );
     ReflectCellsRecursive2( mirrors, cells, settings, completedCells, completedCellIds );
     return completedCells.ToArray();
 }
Example #2
0
        public static void GenImage()
        {
            int size = 1000;
            Bitmap image = new Bitmap( size, size );
            ImageSpace i = new ImageSpace( size, size );
            double b = 1.1;
            i.XMin = -b; i.XMax = b;
            i.YMin = -b; i.YMax = b;

            Vector3D cen = HoneycombPaper.CellCenBall;
            cen = H3Models.BallToUHS( cen );
            Sphere[] simplex = Simplex( ref cen );

            Sphere inSphere = InSphere( simplex );

            using( Graphics g = Graphics.FromImage( image ) )
            foreach( int[] reflections in AllCells() )
            {
                Sphere clone = inSphere.Clone();
                foreach( int r in reflections )
                    clone.Reflect( simplex[r] );

                Sphere ball = new Sphere();
                Circle3D inSphereIdealBall = ball.Intersection( clone );
                Circle3D inSphereIdealUHS = H3Models.BallToUHS( inSphereIdealBall );
                Circle inSphereIdeal = new Circle { Center = inSphereIdealUHS.Center, Radius = inSphereIdealUHS.Radius };

                using( Brush brush = new SolidBrush( Color.Blue ) )
                    DrawUtils.DrawFilledCircle( inSphereIdeal, g, i, brush );
            }

            image.Save( "threefifty.png", ImageFormat.Png );
        }
Example #3
0
        private static void ReflectEdgesRecursive( Sphere[] mirrors, Quad[] quads, 
			List<Quad> allQuads, HashSet<Vector3D> completed )
        {
            if( 0 == quads.Length )
                return;

            List<Quad> newQuads = new List<Quad>();

            foreach( Quad quad in quads )
            //foreach( Sphere mirror in mirrors )
            {
                Sphere mirror = mirrors[3];
                Quad newQuad = quad.Clone();

                for( int i = 0; i < newQuad.Verts.Length; i++ )
                    newQuad.Verts[i] = mirror.ReflectPoint( newQuad.Verts[i] );

                if( completed.Add( newQuad.ID ) )
                {
                    // Haven't seen this yet, so
                    // we'll need to recurse on it.
                    allQuads.Add( newQuad );
                    newQuads.Add( newQuad );
                }
            }

            //ReflectEdgesRecursive( mirrors, newQuads.ToArray(), allQuads, completed );
        }
Example #4
0
 public static void AppendSimplex( Sphere[] facets, Vector3D interiorPoint, int[] include, string fileName )
 {
     using( StreamWriter sw = File.AppendText( fileName ) )
     {
         sw.WriteLine( SimplexFacets( facets, interiorPoint, include ) );
     }
 }
Example #5
0
 /// <summary>
 /// Append facets to the end of an existing povray file.
 /// </summary>
 public static void AppendFacets( Sphere[] facets, string fileName )
 {
     using( StreamWriter sw = File.AppendText( fileName ) )
     {
         foreach( Sphere sphere in facets )
             sw.WriteLine( H3Facet( sphere ) );
     }
 }
Example #6
0
 /// <summary>
 /// A version for the fundamental simplex.
 /// </summary>
 public static void CreateSimplex( Sphere[] facets, string fileName )
 {
     using( StreamWriter sw = File.CreateText( fileName ) )
     {
         Vector3D dummy = new Vector3D();
         sw.WriteLine( SimplexFacets( facets, dummy, new int[] { 0, 1, 2, 3 } ) );
     }
 }
Example #7
0
 private static Quad[] CalcQuads( Sphere[] mirrors, Quad start )
 {
     List<Quad> allQuads = new List<Quad>();
     allQuads.Add( start );
     HashSet<Vector3D> completed = new HashSet<Vector3D>( new Vector3D[] { start.ID } );
     ReflectEdgesRecursive( mirrors, new Quad[] { start }, allQuads, completed );
     return allQuads.ToArray();
 }
Example #8
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();
        }
Example #9
0
        private static string SimplexFacets( Sphere[] facets, Vector3D interiorPoint, int[] include )
        {
            StringBuilder sb = new StringBuilder();

            foreach( int idx in include )
            {
                Sphere facet = facets[idx];

                bool invert = CheckForInvert( facet, interiorPoint );
                sb.Append( string.Format( "{0} material {{ sphereMat2 }} clipped_by {{ ball }}",
                    FormatSphereNoMaterial( facet, invert, false ) ) );

                Sphere[] others = facets.Except( new Sphere[] { facet } ).ToArray();
                foreach( Sphere otherFacet in others )
                {
                    invert = CheckForInvert( otherFacet, interiorPoint );
                    sb.Append( string.Format( " clipped_by {{ {0} }}", FormatSphereNoMaterial( otherFacet, invert ) ) );
                }

                sb.Append( " }" );
            }

            return sb.ToString();
        }
Example #10
0
 public static Sphere Plane( Vector3D offset, Vector3D normal )
 {
     Sphere result = new Sphere();
     result.Center = normal;
     result.Offset = offset;
     result.Radius = double.PositiveInfinity;
     return result;
 }
Example #11
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();
 }
Example #12
0
        public static void RotateSphere( Sphere s, Vector3D axis, double rotation )
        {
            if( s.IsPlane )
            {
                Vector3D o = s.Offset;
                o.RotateAboutAxis( axis, rotation );
                s.Offset = o;
            }

            Vector3D c = s.Center;
            c.RotateAboutAxis( axis, rotation );
            s.Center = c;
        }
Example #13
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 );
        }
Example #14
0
        private static void ReflectCellsRecursive( Sphere[] simplex, H3.Cell[] cells, Settings settings,
			List<H3.Cell> completedCells, HashSet<Vector3D> completedCellIds )
        {
            if( 0 == cells.Length )
                return;

            List<H3.Cell> newCells = new List<H3.Cell>();

            foreach( H3.Cell cell in cells )
            //foreach( Sphere mirror in simplex )
            for( int m=0; m<simplex.Length; m++ )
            {
                Sphere mirror = simplex[m];
                //if( m == 2 )
                //	continue;

                //if( completedCellIds.Count > 1000 )
                //	return;

                //if( completedCellIds.Count > settings.MaxEdges/5 )
                if( completedCellIds.Count > settings.MaxEdges / 20 )
                    throw new System.Exception( "Maxing out cells - will result in uneven filling." );

                H3.Cell newCell = cell.Clone();
                newCell.Reflect( mirror );
                if( !CellOk( newCell, settings ) )
                    continue;

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

                if( completedCellIds.Add( newCell.ID ) )
                {
                    // Haven't seen this cell yet, so
                    // we'll need to recurse on it.
                    newCells.Add( newCell );
                    completedCells.Add( newCell );
                }
            }

            ReflectCellsRecursive( simplex, newCells.ToArray(), settings, completedCells, completedCellIds );
        }
Example #15
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 );
        }
Example #16
0
        public static void ScaleSphere( Sphere s, double factor )
        {
            if( s.IsPlane )
                s.Offset *= factor;

            s.Center *= factor;
            s.Radius *= factor;
        }
Example #17
0
        /// <summary>
        /// Finds the intersection (a circle) between us and another sphere.
        /// Returns null if sphere centers are coincident or no intersection exists.
        /// Does not currently work for planes.
        /// </summary>
        public Circle3D Intersection( Sphere s )
        {
            if( this.IsPlane || s.IsPlane )
                throw new System.NotImplementedException();

            double r = s.Radius;
            double R = this.Radius;

            Vector3D diff = this.Center - s.Center;
            double d = diff.Abs();
            if( Tolerance.Zero( d ) || d > r + R )
                return null;

            double x = ( d*d + r*r - R*R ) / ( 2*d );
            double y = Math.Sqrt( r*r - x*x );

            Circle3D result = new Circle3D();
            diff.Normalize();
            result.Normal = diff;
            result.Center = s.Center + diff * x;
            result.Radius = y;
            return result;
        }
Example #18
0
        /// <summary>
        /// Reflect ourselves about another sphere.
        /// </summary>
        public void Reflect( Sphere sphere )
        {
            // An interior point used to calculate whether we get inverted.
            Vector3D interiorPoint;
            if( IsPlane )
            {
                Debug.Assert( !this.Normal.IsOrigin );
                interiorPoint = -this.Normal;
            }
            else
            {
                // We don't want it to be the center, because that will reflect to infinity.
                interiorPoint = ( this.Center + new Vector3D( this.Radius / 2, 0 ) );
            }
            if( Invert )
                interiorPoint = ReflectPoint( interiorPoint );
            Debug.Assert( IsPointInside( interiorPoint ) );
            interiorPoint = sphere.ReflectPoint( interiorPoint );
            Debug.Assert( !interiorPoint.DNE );

            if( this.Equals( sphere ) )
            {
                if( IsPlane )
                {
                    //this.Center = -this.Center;	// Same as inverting, but we need to do it this way because of Pov-Ray
                    this.Invert = !this.Invert;
                }
                else
                    this.Invert = !this.Invert;

                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // Both planes?
            if( IsPlane && sphere.IsPlane )
            {
                // XXX - not general, but I know the planes I'll be dealing with go through the origin.
                //if( !sphere.Offset.IsOrigin )
                //	throw new System.NotImplementedException();

                /*Vector3D p1 = this.Normal.Cross( sphere.Normal );
                if( !p1.Normalize() )
                {
                    this.Center *= -1;
                    return;
                }

                Vector3D p2 = p1.Cross( this.Normal );
                p2.Normalize();
                p1 = sphere.ReflectPoint( p1 );
                p2 = sphere.ReflectPoint( p2 );
                Vector3D newNormal = p2.Cross( p1 );
                if( !newNormal.Normalize() )
                    throw new System.Exception( "Reflection impl" );
                this.Center = newNormal;*/

                // Reflect the normal relative to the plane (conjugate with sphere.Offset).
                Vector3D newNormal = this.Normal + sphere.Offset;
                newNormal = sphere.ReflectPoint( newNormal );
                newNormal -= sphere.Offset;
                newNormal.Normalize();
                this.Center = newNormal;

                // Calc the new offset (so far we have considered planes through origin).
                this.Offset = sphere.ReflectPoint( this.Offset );

                //Debug.Assert( Offset.IsOrigin );	// XXX - should handle more generality.
                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // We are a plane and reflecting in a sphere.
            if( IsPlane )
            {
                // Think of 2D case here (circle and line)...
                Vector3D projected  = Euclidean3D.ProjectOntoPlane( this.Normal, this.Offset, sphere.Center );
                Vector3D p = sphere.ReflectPoint( projected );
                if( Infinity.IsInfinite( p ) )
                {
                    // This can happen if we go through sphere.Center.
                    // This reflection does not change our orientation (does not invert us).
                    return;
                }

                Center = sphere.Center + ( p - sphere.Center ) / 2;
                Radius = Center.Dist( sphere.Center );

                // Did this invert us?
                if( !this.IsPointInside( interiorPoint ) )
                    Invert = !Invert;

                return;
            }

            // Is mirror a plane?
            if( sphere.IsPlane )
            {
                Vector3D projected = Euclidean3D.ProjectOntoPlane( sphere.Normal, sphere.Offset, Center );
                Vector3D diff = Center - projected;
                Center -= 2 * diff;
                // Radius remains unchanged.
                // NOTE: This does not invert us.
                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            //
            // Now sphere reflecting in a sphere.
            //

            // Reflecting to a plane?
            if( IsPointOn( sphere.Center ) )
            {
                // Concentric spheres?
                if( Center == sphere.Center )
                    throw new System.Exception();

                // Center
                Vector3D center = Center - sphere.Center;

                // Offset
                Vector3D direction = center;
                direction.Normalize();
                Vector3D offset = direction * Radius * 2;
                offset = sphere.ReflectPoint( offset );

                // We are a line now.
                Center = center;
                //Offset = offset;	// Not working??  Caused issues in old generation code for 435.
                Radius = double.PositiveInfinity;

                // Did this invert us?
                if( !this.IsPointInside( interiorPoint ) )
                    this.Invert = !this.Invert;

                Debug.Assert( this.IsPointInside( interiorPoint ) );
                return;
            }

            // XXX - Could try to share code below with Circle class.
            // NOTE: We can't just reflect the center.
            //		 See http://mathworld.wolfram.com/Inversion.html
            double a = Radius;
            double k = sphere.Radius;
            Vector3D v = Center - sphere.Center;
            double s = k * k / ( v.MagSquared() - a * a );
            Center = sphere.Center + v * s;
            Radius = Math.Abs( s ) * a;

            // Did this invert us?
            if( !this.IsPointInside( interiorPoint ) )
                Invert = !Invert;
        }
Example #19
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" );
            }
        }
Example #20
0
        private static Sphere InSphere( Sphere[] simplex )
        {
            // The point centered on a face is the closest point of the cell mirror to the origin.
            Vector3D facePoint = simplex[0].ProjectToSurface( new Vector3D() );

            // Reflect it to get 3 more points on our insphere.
            Vector3D reflected1 = simplex[2].ReflectPoint( facePoint );
            Vector3D reflected2 = simplex[1].ReflectPoint( reflected1 );
            Vector3D reflected3 = simplex[3].ReflectPoint( reflected2 );
            Sphere inSphere = Sphere.From4Points( facePoint, reflected1, reflected2, reflected3 );
            return inSphere;
        }
Example #21
0
        /// <summary>
        /// This generates a polyhedron using recursion.  It needs to be finite 
        /// (There are not any other breakouts of the recursion, other than all facets having been generated.)
        /// </summary>
        public static void GenPolyhedron( Sphere[] mirrors, H3.Cell.Facet[] facets,
			List<H3.Cell.Facet> completedFacets, HashSet<Vector3D> completedFacetIds )
        {
            if( 0 == facets.Length )
                return;

            List<H3.Cell.Facet> newFacets = new List<H3.Cell.Facet>();

            foreach( H3.Cell.Facet facet in facets )
                foreach( Sphere mirror in mirrors )
            {
                H3.Cell.Facet newFacet = facet.Clone();
                newFacet.Reflect( mirror );
                if( completedFacetIds.Add( newFacet.ID ) )
                {
                    // Haven't seen this facet yet, so
                    // we'll need to recurse on it.
                    newFacets.Add( newFacet );
                    completedFacets.Add( newFacet );
                }
            }

            GenPolyhedron( mirrors, newFacets.ToArray(), completedFacets, completedFacetIds );
        }
Example #22
0
 public static string Sphere( Sphere sphere )
 {
     return string.Format( "sphere {{ {0}, {1:G6} material {{ sphereMat }} }}",
             FormatVec( sphere.Center ), sphere.Radius );
     //return string.Format( "sphere {{ {0}, rad material {{ sphereMat }} }}",
     //	FormatVec( sphere.Center ) );
 }
Example #23
0
        private static void ReflectCellsRecursive2( Sphere[] simplex, H3.Cell[] cells, Settings settings,
			List<H3.Cell> completedCells, HashSet<Vector3D> completedCellIds )
        {
            if( 0 == cells.Length )
                return;

            List<H3.Cell> newCells = new List<H3.Cell>();

            foreach( H3.Cell cell in cells )
            //foreach( Sphere mirror in simplex )
            for( int m = 0; m < simplex.Length; m++ )
            {
                Sphere mirror = simplex[m];
                if( completedCellIds.Count > 250000 )
                    return;

                H3.Cell newCell = cell.Clone();
                newCell.Reflect( mirror );
                //if( !CellOk( newCell, settings ) )
                bool cellOk = true;
                foreach( H3.Cell.Facet f in cell.Facets )
                    if( f.Sphere.Radius < 0.002 )
                        cellOk = false;
                if( !cellOk )
                    continue;

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

                if( completedCellIds.Add( newCell.ID ) )
                {
                    // Haven't seen this cell yet, so
                    // we'll need to recurse on it.
                    newCells.Add( newCell );
                    completedCells.Add( newCell );
                }
            }

            ReflectCellsRecursive2( simplex, newCells.ToArray(), settings, completedCells, completedCellIds );
        }
Example #24
0
        private static bool CheckForInvert( Sphere facet, Vector3D point )
        {
            System.Diagnostics.Debug.Assert( !facet.IsPointInside( point ) );
            if( !facet.IsPlane )
            {
                bool invert = !facet.Invert;

                // This check doesn't seem like it should be here.
                //if( facet.IsPointInside( point ) )
                //	invert = !invert;

                return invert;
            }
            else
            {
                return !facet.Invert;
            }
        }
Example #25
0
 /////////////////////////////////////////////////////////
 // Hacking around.  I should remove this or make CalcCells() configurable enough to deal with more cases.
 public static H3.Cell[] CalcCells2( Sphere[] mirrors, H3.Cell[] cells )
 {
     Settings settings = new Settings();
     return CalcCells2( mirrors, cells, settings );
 }
Example #26
0
 private static string FormatSphereNoMaterial( Sphere sphere, bool invert, bool includeClosingBracket = true )
 {
     if( sphere.IsPlane )
     {
         Vector3D offsetOnNormal = Euclidean2D.ProjectOntoLine( sphere.Offset, new Vector3D(), sphere.Normal );
         double offset = offsetOnNormal.Abs();
         if( offsetOnNormal.Dot( sphere.Normal ) < 0 )
             offset *= -1;
         return string.Format( "plane {{ {0}, {1:G6}{2} {3}",
             FormatVec( sphere.Normal ), offset, invert ? " inverse" : string.Empty,
             includeClosingBracket ? "}" : string.Empty );
     }
     else
     {
         return string.Format( "sphere {{ {0}, {1:G6}{2} {3}",
             FormatVec( sphere.Center ), sphere.Radius, invert ? " inverse" : string.Empty,
             includeClosingBracket ? "}" : string.Empty );
     }
 }
Example #27
0
 public static Edge[] CalcEdges( Sphere[] simplex, Edge[] edges )
 {
     Settings settings = new Settings();
     return CalcEdges( simplex, edges, settings );
 }
Example #28
0
 private static string H3Facet( Sphere sphere )
 {
     if( sphere.IsPlane )
     {
         Vector3D offsetOnNormal = Euclidean2D.ProjectOntoLine( sphere.Offset, new Vector3D(), sphere.Normal );
         return string.Format( "plane {{ {0}, {1:G6} material {{ sphereMat }} clipped_by {{ ball }} }}",
             FormatVec( sphere.Normal ), offsetOnNormal.Abs() );
     }
     else
     {
         return string.Format( "sphere {{ {0}, {1:G6} material {{ sphereMat }} clipped_by {{ ball }} }}",
             FormatVec( sphere.Center ), sphere.Radius );
     }
 }
Example #29
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 );
        }
Example #30
0
            /// <summary>
            /// Find the sphere defined by 3 points on the unit sphere, and orthogonal to the unit sphere.
            /// Returns null if points are not on the unit sphere.
            /// </summary>
            public static Sphere OrthogonalSphere( Vector3D b1, Vector3D b2, Vector3D b3 )
            {
                Sphere unitSphere = new Sphere();
                if( !unitSphere.IsPointOn( b1 ) ||
                    !unitSphere.IsPointOn( b2 ) ||
                    !unitSphere.IsPointOn( b3 ) )
                    return null;

                Circle3D c = new Circle3D( b1, b2, b3 );

                // Same impl as orthogonal circles now.
                Vector3D center;
                double radius;
                OrthogonalCircle( b1, b1 + ( c.Center - b1 ) * 2, out center, out radius );

                Sphere sphere = new Sphere();
                if( Infinity.IsInfinite( radius ) )
                {
                    // Have the center act as a normal.
                    sphere.Center = c.Normal;
                    sphere.Radius = double.PositiveInfinity;
                }
                else
                {
                    sphere.Center = center;
                    sphere.Radius = radius;
                }
                return sphere;
            }