ReflectInFacet() public method

public ReflectInFacet ( Vector3D v, int facet ) : Vector3D
v Vector3D
facet int
return Vector3D
Exemplo n.º 1
0
        private static void OneHoneycombGoursat( int[] active, string baseName, int baseHue )
        {
            CalcThickness( active );

            // Create the simplex.
            Simplex simplex = new Simplex();
            simplex.InitializeGoursat();

            // Map of labels for mirrors consistent with input scheme to Goursat function.
            // Map is from wikipedia labeling scheme to the indices our function generates.
            //
            // wiki == our index
            // 0100 == 0
            // 0001 == 1
            // 1000 == 2
            // 0010 == 3
            Func<int, int> mapMirror = i =>
            {
                switch( i )
                {
                    case 0: return 2;
                    case 1: return 0;
                    case 2: return 3;
                    case 3: return 1;
                }
                throw new System.ArgumentException();
            };

            // We need to set this up before converting the mirrors.
            string mirrorsString = ActiveMirrorsString( active );
            string suffix = "-" + mirrorsString;

            // Convert our active mirrors into the Goursat tet indices.
            int[] polyMirrors = new int[] { 1, 2, 3 };
            active = active.Select( i => mapMirror( i ) ).OrderBy( i => i ).ToArray();
            polyMirrors = polyMirrors.Select( i => mapMirror( i ) ).OrderBy( i => i ).ToArray();

            Vector3D startingPoint = IterateToStartingPoint( active, simplex );
            List<H3.Cell.Edge> startingEdges = new List<H3.Cell.Edge>();
            foreach( int a in active )
            {
                Vector3D reflected = simplex.ReflectInFacet( startingPoint, a );
                startingEdges.Add( new H3.Cell.Edge( startingPoint, reflected ) );
            }

            bool doEdges = true;
            bool doCells = false;

            // Generate the honeycomb.
            H3.Cell.Edge[] edges = null;
            if( doEdges )
                edges = Recurse.CalcEdgesSmart( simplex.Facets, startingEdges.ToArray() );

            // Highlighted cells.
            H3.Cell[] cellsToHighlight = null;
            if( doCells )
            {
                H3.Cell startingCell = PolyhedronToHighlight( Geometry.Hyperbolic, polyMirrors, simplex, startingPoint );
                cellsToHighlight = Recurse.CalcCells( simplex.Facets, new H3.Cell[] { startingCell } );
                //cellsToHighlight = new H3.Cell[] { startingCell };
            }

            // plugin Wendy's nonuniform calcs here...
            //Nonuniform.Wendy( simplex, edges );

            // Trim out half the edges (the ones we won't see in our Pov-Ray view).
            Vector3D lookFrom = new Vector3D( 1, 1, 1 ) * 0.7;
            Vector3D lookAt = new Vector3D( );	// pov-ray lookat
            double thresh = -.01;
            if( doEdges )
                edges = edges.Where( e => e.Start.Dot( lookAt ) > thresh || e.End.Dot( lookAt ) > thresh ).ToArray();
            //if( doCells )
            //	cellsToHighlight = cellsToHighlight.Where( c => c.Center.Dot( lookAt ) > thresh ).ToArray();	// I don't think this works right

            // Setup Pov-ray stuff.
            // We have 16 possible mirror states.  We'll calculate the hue by converting the binary state to decimal, and doubling.
            // So for a given family, the hue will range over 32 numbers.
            int hue = baseHue + 2 * Convert.ToInt32( mirrorsString, 2 );
            string fileName = baseName + suffix;
            using( StreamWriter sw = File.CreateText( fileName + ".pov" ) )
            {
                sw.WriteLine( string.Format( "#declare lookFrom = <{0},{1},{2}>;", lookFrom.X, lookFrom.Y, lookFrom.Z ) );
                sw.WriteLine( string.Format( "#declare lookAt = <{0},{1},{2}>;", lookAt.X, lookAt.Y, lookAt.Z ) );
                sw.WriteLine( "#include \"C:\\Users\\hrn\\Documents\\roice\\povray\\H3_uniform_faces\\H3_uniform_faces.pov\"" );
                //sw.WriteLine( string.Format( "background {{ CHSL2RGB( <{0}, 1, .3> ) }}", hue ) );
                //sw.WriteLine( string.Format( "background {{ rgb <.13,.37,.31> }}" ) );
                sw.WriteLine( string.Format( "background {{ rgb 1 }}" ) );
            }

            if( doEdges )
                H3.SaveToFile( fileName, edges, finite: true, append: true );
            if( doCells )
            {
                HashSet<H3.Cell.Edge> cellEdges = new HashSet<H3.Cell.Edge>( new H3.Cell.EdgeEqualityComparer() );
                foreach( H3.Cell cell in cellsToHighlight )
                    cell.AppendAllEdges( cellEdges );
                edges = cellEdges.ToArray();
                H3.SaveToFile( fileName, edges, finite: true, append: true );

                H3.AppendFacets( fileName, cellsToHighlight );
            }
        }
Exemplo n.º 2
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() );
        }
Exemplo n.º 3
0
        // CHEAT! (would be better to do a geometrical construction)
        // We are going to iterate to the starting point that will make all edge lengths the same.
        private static Vector3D IterateToStartingPoint( int[] activeMirrors, Simplex simplex )
        {
            if( activeMirrors.Length == 1 )
                return simplex.Verts[activeMirrors[0]];

            // We are minimizing the output of this function,
            // because we want all edge lengths to be as close as possible.
            // Input vector should be in the Ball Model.
            Func<Vector3D, double> diffFunc = v =>
            {
                List<double> lengths = new List<double>();
                for( int i = 0; i < activeMirrors.Length; i++ )
                {
                    Vector3D reflected = simplex.ReflectInFacet( v, activeMirrors[i] );
                    lengths.Add( H3Models.Ball.HDist( v, reflected ) );
                }

                double result = 0;
                double average = lengths.Average();
                foreach( double length in lengths )
                    result += Math.Abs( length - average );
                return result;
            };

            // So that we can leverage Euclidean barycentric coordinates, we will first convert our simplex to the Klein model.
            // We will need to take care to properly convert back to the Ball as needed.
            Vector3D[] kleinVerts = simplex.Verts.Select( v => HyperbolicModels.PoincareToKlein( v ) ).ToArray();

            // Normalizing barycentric coords amounts to making sure the 4 coords add to 1.
            Func<Vector3D, Vector3D> baryNormalize = b =>
            {
                return b / ( b.X + b.Y + b.Z + b.W );
            };

            // Bary Coords to Euclidean
            Func<Vector3D[], Vector3D, Vector3D> baryToEuclidean = ( kv, b ) =>
            {
                Vector3D result =
                    kv[0] * b.X + kv[1] * b.Y + kv[2] * b.Z + kv[3] * b.W;
                return result;
            };

            // Our starting barycentric coords (halfway between all active mirrors).
            Vector3D bary = new Vector3D();
            foreach( int a in activeMirrors )
                bary[a] = 0.5;
            bary = baryNormalize( bary );

            // For each iteration, we'll shrink this search offset.
            // NOTE: The starting offset and decrease factor I'm using don't guarantee convergence,
            // but it seems to be working pretty well (even when varying these parameters).
            //double searchOffset = 1.0 - bary[activeMirrors[0]];
            //double searchOffset = bary[activeMirrors[0]];
            double factor = 1.5;	// Adjusting this helps get some to converge, e.g. 4353-1111
            double searchOffset = bary[activeMirrors[0]] / factor;

            double min = double.MaxValue;
            int iterations = 1000;
            for( int i = 0; i < iterations; i++ )
            {
                min = diffFunc( HyperbolicModels.KleinToPoincare( baryToEuclidean( kleinVerts, bary ) ) );
                foreach( int a in activeMirrors )
                {
                    Vector3D baryTest1 = bary, baryTest2 = bary;
                    baryTest1[a] += searchOffset;
                    baryTest2[a] -= searchOffset;
                    baryTest1 = baryNormalize( baryTest1 );
                    baryTest2 = baryNormalize( baryTest2 );

                    double t1 = diffFunc( HyperbolicModels.KleinToPoincare( baryToEuclidean( kleinVerts, baryTest1 ) ) );
                    double t2 = diffFunc( HyperbolicModels.KleinToPoincare( baryToEuclidean( kleinVerts, baryTest2 ) ) );
                    if( t1 < min )
                    {
                        min = t1;
                        bary = baryTest1;
                    }
                    if( t2 < min )
                    {
                        min = t2;
                        bary = baryTest2;
                    }
                }

                if( Tolerance.Equal( min, 0.0, 1e-14 ) )
                {
                    System.Console.WriteLine( string.Format( "Converged in {0} iterations.", i ) );
                    break;
                }

                searchOffset /= factor;
            }

            if( !Tolerance.Equal( min, 0.0, 1e-14 ) )
            {
                System.Console.WriteLine( "Did not converge: " + min );

                // Be a little looser before thrown an exception.
                if( !Tolerance.Equal( min, 0.0, 1e-12 ) )
                {
                    System.Console.ReadKey( true );
                    //throw new System.Exception( "Boo. We did not converge." );
                    return Vector3D.DneVector();
                }
            }

            return HyperbolicModels.KleinToPoincare( baryToEuclidean( kleinVerts, bary ) );
        }
Exemplo n.º 4
0
        public static void Paracompact( HoneycombDef def, int[] active, int baseHue )
        {
            string baseName = BaseName( def );
            string mirrorsString = ActiveMirrorsString( active );
            string suffix = "-" + mirrorsString;
            string fileName = baseName + suffix;

            if( File.Exists( fileName + ".pov" ) )
            {
                Console.WriteLine( string.Format( "Skipping {0}", fileName ) );
                return;
            }

            Console.WriteLine( string.Format( "Building {0}", fileName ) );
            CalcThickness( active );

            // The wiki mirrors are labeled in the reverse of ours.
            Func<int, int> mapMirror = i => 3 - i;
            active = active.Select( i => mapMirror( i ) ).OrderBy( i => i ).ToArray();

            Simplex simplex = new Simplex();
            simplex.Facets = SimplexCalcs.Mirrors( def.P, def.Q, def.R );
            simplex.Verts = SimplexCalcs.VertsBall( def.P, def.Q, def.R );

            Vector3D startingPoint = IterateToStartingPoint( active, simplex );
            if( startingPoint.DNE )
                return;
            List<H3.Cell.Edge> startingEdges = new List<H3.Cell.Edge>();
            foreach( int a in active )
            {
                Vector3D reflected = simplex.ReflectInFacet( startingPoint, a );
                startingEdges.Add( new H3.Cell.Edge( startingPoint, reflected ) );
            }

            SetupBaseHue( fileName, mirrorsString, baseHue );
            Recurse.m_background = new Vector3D( baseHue, 1, .1 );

            H3.Cell.Edge[] edges = Recurse.CalcEdgesSmart2( simplex.Facets, startingEdges.ToArray() );
            H3.SaveToFile( fileName, edges, finite: true, append: true );
        }