MapPoints() public method

This transform will map z1 to Zero, z2 to One, and z3 to Infinity. http://en.wikipedia.org/wiki/Mobius_transformation#Mapping_first_to_0.2C_1.2C_.E2.88.9E If one of the zi is ∞, then the proper formula is obtained by first dividing all entries by zi and then taking the limit zi → ∞
public MapPoints ( System.Numerics.Complex z1, System.Numerics.Complex z2, System.Numerics.Complex z3 ) : void
z1 System.Numerics.Complex
z2 System.Numerics.Complex
z3 System.Numerics.Complex
return void
コード例 #1
0
ファイル: Mobius.cs プロジェクト: remuladgryta/MagicTile
        /// <summary>
        /// This transform will map the z points to the respective w points.
        /// </summary>
        public void MapPoints(Complex z1, Complex z2, Complex z3, Complex w1, Complex w2, Complex w3)
        {
            Mobius m1 = new Mobius(), m2 = new Mobius();

            m1.MapPoints(z1, z2, z3);
            m2.MapPoints(w1, w2, w3);
            this = m2.Inverse() * m1;
        }
コード例 #2
0
ファイル: Isometry.cs プロジェクト: remuladgryta/MagicTile
        private void CalculateFromTwoPolygonsInternal(Polygon home, Polygon boundary, CircleNE homeVertexCircle, Geometry g)
        {
            // ZZZ - We have to use the boundary, but that can be projected to infinity for some of the spherical tilings.
            //		 Trying to use the Drawn tile produced weird (yet interesting) results.
            Polygon poly1 = boundary;
            Polygon poly2 = home;

            if (poly1.Segments.Count < 3 ||
                poly2.Segments.Count < 3)                       // Poor poor digons.
            {
                Debug.Assert(false);
                return;
            }

            // Same?
            Vector3D p1 = poly1.Segments[0].P1, p2 = poly1.Segments[1].P1, p3 = poly1.Segments[2].P1;
            Vector3D w1 = poly2.Segments[0].P1, w2 = poly2.Segments[1].P1, w3 = poly2.Segments[2].P1;

            if (p1 == w1 && p2 == w2 && p3 == w3)
            {
                this.Mobius = Mobius.Identity();
                return;
            }

            Mobius m = new Mobius();

            m.MapPoints(p1, p2, p3, w1, w2, w3);
            this.Mobius = m;

            // Worry about reflections as well.
            if (g == Geometry.Spherical)
            {
                // If inverted matches the orientation, we need a reflection.
                bool inverted = poly1.IsInverted;
                if (!(inverted ^ poly1.Orientation))
                {
                    this.Reflection = homeVertexCircle;
                }
            }
            else
            {
                if (!poly1.Orientation)
                {
                    this.Reflection = homeVertexCircle;
                }
            }

            // Some testing.
            Vector3D test = this.Apply(boundary.Center);

            if (test != home.Center)
            {
                // ZZZ: What is happening here is that the mobius can project a point to infinity before the reflection brings it back to the origin.
                //		It hasn't been much of a problem in practice yet, but will probably need fixing at some point.
                //Trace.WriteLine( "oh no!" );
            }
        }
コード例 #3
0
ファイル: Isometry.cs プロジェクト: remuladgryta/MagicTile
        /// <summary>
        /// Does a circle inversion in an arbitrary, generalized circle.
        /// IOW, the three points may be collinear, in which case we are talking about a reflection.
        /// </summary>
        private void CacheCircleInversion(Complex c1, Complex c2, Complex c3)
        {
            Mobius toUnitCircle = new Mobius();

            toUnitCircle.MapPoints(
                c1, c2, c3,
                new Complex(1, 0),
                new Complex(-1, 0),
                new Complex(0, 1));

            m_cache1 = toUnitCircle;
            m_cache2 = m_cache1.Inverse();
        }
コード例 #4
0
ファイル: Isometry.cs プロジェクト: remuladgryta/MagicTile
        /// <summary>
        /// Composition operator.
        /// </summary>>
        public static Isometry operator *(Isometry i1, Isometry i2)
        {
            // ZZZ - Probably a better way.
            // We'll just apply both isometries to a canonical set of points,
            // Then calc which isometry makes that.

            Complex p1 = new Complex(1, 0);
            Complex p2 = new Complex(-1, 0);
            Complex p3 = new Complex(0, 1);
            Complex w1 = p1, w2 = p2, w3 = p3;

            // Compose (apply in reverse order).
            w1 = i2.Apply(w1);
            w2 = i2.Apply(w2);
            w3 = i2.Apply(w3);
            w1 = i1.Apply(w1);
            w2 = i1.Apply(w2);
            w3 = i1.Apply(w3);

            Mobius m = new Mobius();

            m.MapPoints(p1, p2, p3, w1, w2, w3);

            Isometry result = new Isometry();

            result.Mobius = m;

            // Need to reflect at end?
            bool r1 = i1.Reflection != null;
            bool r2 = i2.Reflection != null;

            if (r1 ^ r2)                // One and only one reflection.
            {
                result.Reflection = new Circle(
                    Vector3D.FromComplex(w1),
                    Vector3D.FromComplex(w2),
                    Vector3D.FromComplex(w3));
            }

            return(result);
        }
コード例 #5
0
ファイル: Mobius.cs プロジェクト: roice3/Honeycombs
 /// <summary>
 /// This transform will map the z points to the respective w points.
 /// </summary>
 public void MapPoints( Complex z1, Complex z2, Complex z3, Complex w1, Complex w2, Complex w3 )
 {
     Mobius m1 = new Mobius(), m2 = new Mobius();
     m1.MapPoints( z1, z2, z3 );
     m2.MapPoints( w1, w2, w3 );
     this =  m2.Inverse() * m1;
 }
コード例 #6
0
ファイル: Mesh.cs プロジェクト: roice3/Honeycombs
        private static void AddSymmetryTriangles( Mesh mesh, Tiling tiling, Polygon boundary )
        {
            // Assume template centered at the origin.
            Polygon template = tiling.Tiles.First().Boundary;
            List<Triangle> templateTris = new List<Triangle>();
            foreach( Segment seg in template.Segments )
            {
                int num = 1 + (int)(seg.Length * m_divisions);

                Vector3D a = new Vector3D();
                Vector3D b = seg.P1;
                Vector3D c = seg.Midpoint;
                Vector3D centroid = ( a + b + c ) / 3;

                Polygon poly = new Polygon();
                Segment segA = Segment.Line( new Vector3D(), seg.P1 );
                Segment segB = seg.Clone();
                segB.P2 = seg.Midpoint;
                Segment segC = Segment.Line( seg.Midpoint, new Vector3D() );
                poly.Segments.Add( segA );
                poly.Segments.Add( segB );
                poly.Segments.Add( segC );

                Vector3D[] coords = TextureHelper.TextureCoords( poly, Geometry.Hyperbolic );
                int[] elements = TextureHelper.TextureElements( 3, LOD: 3 );
                for( int i = 0; i < elements.Length / 3; i++ )
                {
                    int idx1 = i * 3;
                    int idx2 = i * 3 + 1;
                    int idx3 = i * 3 + 2;
                    Vector3D v1 = coords[elements[idx1]];
                    Vector3D v2 = coords[elements[idx2]];
                    Vector3D v3 = coords[elements[idx3]];
                    templateTris.Add( new Triangle( v1, v2, v3 ) );
                }

                /*

                // Need to shrink a little, so we won't
                // get intersections among neighboring faces.
                a = Shrink( a, centroid );
                b = Shrink( b, centroid );
                c = Shrink( c, centroid );

                Vector3D[] list = seg.Subdivide( num * 2 );
                list[0] = b;
                list[list.Length / 2] = c;
                for( int i = 0; i < list.Length / 2; i++ )
                    templateTris.Add( new Triangle( centroid, list[i], list[i + 1] ) );

                for( int i = num - 1; i >= 0; i-- )
                    templateTris.Add( new Triangle( centroid, a + (c - a) * (i + 1) / num, a + (c - a) * i / num ) );

                for( int i = 0; i < num; i++ )
                    templateTris.Add( new Triangle( centroid, a + (b - a) * i / num, a + (b - a) * (i + 1) / num ) );
                */
            }

            foreach( Tile tile in tiling.Tiles )
            {
                Vector3D a = tile.Boundary.Segments[0].P1;
                Vector3D b = tile.Boundary.Segments[1].P1;
                Vector3D c = tile.Boundary.Segments[2].P1;

                Mobius m = new Mobius();
                if( tile.Isometry.Reflected )
                    m.MapPoints( template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, c, b, a );
                else
                    m.MapPoints( template.Segments[0].P1, template.Segments[1].P1, template.Segments[2].P1, a, b, c );

                foreach( Triangle tri in templateTris )
                {
                    Triangle transformed = new Triangle(
                        m.Apply( tri.a ),
                        m.Apply( tri.b ),
                        m.Apply( tri.c ) );
                    CheckAndAdd( mesh, transformed, boundary );
                }
            }
        }
コード例 #7
0
ファイル: Isometry.cs プロジェクト: roice3/Honeycombs
        /// <summary>
        /// Composition operator.
        /// </summary>>
        public static Isometry operator *( Isometry i1, Isometry i2 )
        {
            // ZZZ - Probably a better way.
            // We'll just apply both isometries to a canonical set of points,
            // Then calc which isometry makes that.

            Complex p1 = new Complex( 1, 0 );
            Complex p2 = new Complex( -1, 0 );
            Complex p3 = new Complex( 0, 1 );
            Complex w1 = p1, w2 = p2, w3 = p3;

            // Compose (apply in reverse order).
            w1 = i2.Apply( w1 );
            w2 = i2.Apply( w2 );
            w3 = i2.Apply( w3 );
            w1 = i1.Apply( w1 );
            w2 = i1.Apply( w2 );
            w3 = i1.Apply( w3 );

            Mobius m = new Mobius();
            m.MapPoints( p1, p2, p3, w1, w2, w3 );

            Isometry result = new Isometry();
            result.Mobius = m;

            // Need to reflect at end?
            bool r1 = i1.Reflection != null;
            bool r2 = i2.Reflection != null;
            if( r1 ^ r2 )	// One and only one reflection.
            {
                result.Reflection = new Circle(
                    Vector3D.FromComplex( w1 ),
                    Vector3D.FromComplex( w2 ),
                    Vector3D.FromComplex( w3 ) );
            }

            return result;
        }
コード例 #8
0
ファイル: Isometry.cs プロジェクト: roice3/Honeycombs
        private void CalculateFromTwoPolygonsInternal( Polygon home, Polygon boundary, CircleNE homeVertexCircle, Geometry g )
        {
            // ZZZ - We have to use the boundary, but that can be projected to infinity for some of the spherical tilings.
            //		 Trying to use the Drawn tile produced weird (yet interesting) results.
            Polygon poly1 = boundary;
            Polygon poly2 = home;

            if( poly1.Segments.Count < 3 ||
                poly2.Segments.Count < 3 )	// Poor poor digons.
            {
                Debug.Assert( false );
                return;
            }

            // Same?
            Vector3D p1 = poly1.Segments[0].P1, p2 = poly1.Segments[1].P1, p3 = poly1.Segments[2].P1;
            Vector3D w1 = poly2.Segments[0].P1, w2 = poly2.Segments[1].P1, w3 = poly2.Segments[2].P1;
            if( p1 == w1 && p2 == w2 && p3 == w3 )
            {
                this.Mobius = Mobius.Identity();
                return;
            }

            Mobius m = new Mobius();
            m.MapPoints( p1, p2, p3, w1, w2, w3 );
            this.Mobius = m;

            // Worry about reflections as well.
            if( g == Geometry.Spherical )
            {
                // If inverted matches the orientation, we need a reflection.
                bool inverted = poly1.IsInverted;
                if( !(inverted ^ poly1.Orientation) )
                    this.Reflection = homeVertexCircle;
            }
            else
            {
                if( !poly1.Orientation )
                    this.Reflection = homeVertexCircle;
            }

            // Some testing.
            Vector3D test = this.Apply( boundary.Center );
            if( test != home.Center )
            {
                // ZZZ: What is happening here is that the mobius can project a point to infinity before the reflection brings it back to the origin.
                //		It hasn't been much of a problem in practice yet, but will probably need fixing at some point.
                //Trace.WriteLine( "oh no!" );
            }
        }
コード例 #9
0
ファイル: Isometry.cs プロジェクト: roice3/Honeycombs
        /// <summary>
        /// Does a circle inversion in an arbitrary, generalized circle.
        /// IOW, the three points may be collinear, in which case we are talking about a reflection.
        /// </summary>
        private void CacheCircleInversion( Complex c1, Complex c2, Complex c3 )
        {
            Mobius toUnitCircle = new Mobius();
            toUnitCircle.MapPoints(
                c1, c2, c3,
                new Complex( 1, 0 ),
                new Complex( -1, 0 ),
                new Complex( 0, 1 ) );

            m_cache1 = toUnitCircle;
            m_cache2 = m_cache1.Inverse();
        }
コード例 #10
0
ファイル: CoxeterImages.cs プロジェクト: roice3/Honeycombs
        /// <summary>
        /// Using this to move the view around in interesting ways.
        /// </summary>
        private Vector3D ApplyTransformation( Vector3D v, double t = 0.0 )
        {
            //v.RotateXY( Math.PI / 4 + 0.01 );
            bool applyNone = true;
            if( applyNone )
                return v;

            Mobius m0 = new Mobius(), m1 = new Mobius(), m2 = new Mobius(), m3 = new Mobius();
            Sphere unitSphere = new Sphere();

            // self-similar scale for 437
            //v*= 4.259171776329806;

            double s = 6.5;
            v *= s;
            v += new Vector3D( s/3, -s/3 );
            v = unitSphere.ReflectPoint( v );
            v.RotateXY( Math.PI/6 );
            //v /= 3;
            //v.RotateXY( Math.PI );
            //v.RotateXY( Math.PI/2 );
            return v;

            //v.Y = v.Y / Math.Cos( Math.PI / 6 );	// 637 repeatable
            //return v;

            // 12,12,12
            m0.Isometry( Geometry.Hyperbolic, 0, new Complex( .0, .0 ) );
            m1 = Mobius.Identity();
            m2 = Mobius.Identity();
            m3 = Mobius.Identity();
            v = (m0 * m1 * m2 * m3).Apply( v );
            return v;

            // i64
            m0.Isometry( Geometry.Hyperbolic, 0, new Complex( .5, .5 ) );
            m1.UpperHalfPlane();
            m2 = Mobius.Scale( 1.333333 );
            m3.Isometry( Geometry.Euclidean, 0, new Vector3D( 0, -1.1 ) );
            v = (m1 * m2 * m3).Apply( v );
            return v;

            // 464
            // NOTE: Also, don't apply rotations during simplex generation.
            m1.UpperHalfPlane();
            m2 = Mobius.Scale( 1.3 );
            m3.Isometry( Geometry.Euclidean, 0, new Vector3D( 1.55, -1.1 ) );
            v = ( m1 * m2 * m3 ).Apply( v );
            return v;

            // iii
            m1.Isometry( Geometry.Hyperbolic, 0, new Complex( 0, Math.Sqrt( 2 ) - 1 ) );
            m2.Isometry( Geometry.Euclidean, -Math.PI / 4, 0 );
            m3 = Mobius.Scale( 5 );
            //v = ( m1 * m2 * m3 ).Apply( v );

            // Vertical Line
            /*v = unitSphere.ReflectPoint( v );
            m1.MapPoints( new Vector3D(-1,0), new Vector3D(), new Vector3D( 1, 0 ) );
            m2 = Mobius.Scale( .5 );
            v = (m1*m2).Apply( v ); */

            /*
            m1 = Mobius.Scale( 0.175 );
            v = unitSphere.ReflectPoint( v );
            v = m1.Apply( v );
             * */

            // Inversion
            //v = unitSphere.ReflectPoint( v );
            //return v;

            /*Mobius m1 = new Mobius(), m2 = new Mobius(), m3 = new Mobius();
            m1.Isometry( Geometry.Spherical, 0, new Complex( 0, 1 ) );
            m2.Isometry( Geometry.Euclidean, 0, new Complex( 0, -1 ) );
            m3 = Mobius.Scale( 0.5 );
            v = (m1 * m3 * m2).Apply( v );*/

            //Mobius m = new Mobius();
            //m.Isometry( Geometry.Hyperbolic, 0, new Complex( -0.88, 0 ) );
            //m.Isometry( Geometry.Hyperbolic, 0, new Complex( 0, Math.Sqrt(2) - 1 ) );
            //m = Mobius.Scale( 0.17 );
            //m.Isometry( Geometry.Spherical, 0, new Complex( 0, 3.0 ) );
            //v = m.Apply( v );

            // 63i, 73i
            m1 = Mobius.Scale( 6.0 ); // Scale {3,i} to unit disk.
            m1 = Mobius.Scale( 1.0 / 0.14062592996431983 ); // 73i	(constant is abs of midpoint of {3,7} tiling, if we want to calc later for other tilings).
            m2.MapPoints( Infinity.InfinityVector, new Vector3D( 1, 0 ), new Vector3D() ); // swap interior/exterior
            m3.UpperHalfPlane();
            v *= 2.9;

            // iii
            /*m1.MapPoints( new Vector3D(), new Vector3D(1,0), new Vector3D( Math.Sqrt( 2 ) - 1, 0 ) );
            m2.Isometry( Geometry.Euclidean, -Math.PI / 4, 0 );
            m3 = Mobius.Scale( 0.75 );*/

            Mobius m = m3 * m2 * m1;
            v = m.Inverse().Apply( v );	// Strange that we have to do inverse here.

            return v;
        }