Beispiel #1
0
        /// <summary>
        /// Helper to do a geodesic pan.
        /// </summary>
        private void GeodesicPan(Vector3D p1, Vector3D p2)
        {
            Mobius   pan     = new Mobius();
            Isometry inverse = m_isometry.Inverse();

            p1 = inverse.Apply(p1);
            p2 = inverse.Apply(p2);
            pan.Geodesic(m_geometry, p1, p2);
            m_isometry.Mobius *= pan;
        }
Beispiel #2
0
        /// <summary>
        /// Transforms us into a new macro based on a different click location.
        /// </summary>
        public Macro Transform(Cell clickedCell, Vector3D clickedPoint, Puzzle puzzle, bool mouseMotionReflected)
        {
            Macro m = this.CloneAllButTwists();

            m.SetupMobius(clickedCell, clickedPoint, puzzle, mouseMotionReflected);

            // Did we have an odd number of view reflections?
            bool viewReflected = this.ViewReflected ^ m.ViewReflected;

            Isometry iso1 = new Isometry(m.Mobius, null);
            Isometry iso2 = new Isometry(this.Mobius, null);

            if (viewReflected)
            {
                iso1 = Isometry.ReflectX() * iso1;
            }
            Isometry combined = iso1.Inverse() * iso2;

            foreach (SingleTwist t in this.m_twists)
            {
                // Find the transformed twist data.
                // NOTE: We choose the one which will be closest to the origin after transformation,
                //		 which hopefully won't lead to performance problems.
                //		 I initially just used the first TwistDataForStateCalcs list item,
                //		 but that led to issues because sometimes it would get transformed
                //		 to very near the disk boundary. We'd have run out of cells to
                //		 find the correct closest, and the transformed macros got all messed up.
                TwistData tdOriginal = t.IdentifiedTwistData.TwistDataForStateCalcs
                                       .OrderBy(td => combined.Apply(td.Center).MagSquared())
                                       .First();
                Vector3D  newCenter = combined.Apply(tdOriginal.Center);
                TwistData tdNew     = puzzle.ClosestTwistingCircles(newCenter);

                SingleTwist tClone = t.Clone();
                tClone.IdentifiedTwistData = tdNew.IdentifiedTwistData;

                // If the reverse state of our transformed twist
                // has changed, we may need to reverse the new twist.
                bool reverse = tdOriginal.Reverse ^ tdNew.Reverse;
                if (reverse ^ viewReflected)                    // NOTE: Very similar to code in Renderer.
                {
                    tClone.ReverseTwist();
                }

                m.m_twists.Add(tClone);
            }

            return(m);
        }
Beispiel #3
0
        private static Isometry SetupIsometry(Cell clickedCell, Vector3D clickedPoint, Puzzle puzzle)
        {
            int      p            = puzzle.Config.P;
            Geometry g            = puzzle.Config.Geometry;
            Isometry cellIsometry = clickedCell.Isometry.Clone();

            // Take out reflections.
            // ZZZ - Figuring out how to deal with these reflected isometries was a bit painful to figure out.
            //		 I wish I had just taken more care to not have any cell isometries with reflections.
            //		 Maybe I can rework that to be different at some point.
            if (cellIsometry.Reflection != null)
            {
                cellIsometry = Isometry.ReflectX() * cellIsometry;
            }

            // Round to nearest vertex.
            Vector3D centered         = cellIsometry.Apply(clickedPoint);
            double   angle            = Euclidean2D.AngleToCounterClock(centered, new Vector3D(1, 0));
            double   angleFromZeroToP = p * angle / (2 * Math.PI);

            angleFromZeroToP = Math.Round(angleFromZeroToP, 0);
            if (p == (int)angleFromZeroToP)
            {
                angleFromZeroToP = 0;
            }
            angle = 2 * Math.PI * angleFromZeroToP / p;

            // This will take vertex to canonical position.
            Mobius rotation = new Mobius();

            rotation.Isometry(g, angle, new Complex());
            Isometry rotIsometry = new Isometry(rotation, null);

            return(rotIsometry * cellIsometry);
        }
Beispiel #4
0
 /// <summary>
 /// Apply an isometry to us.
 /// </summary>
 public void Transform(Isometry isometry)
 {
     foreach (Segment s in this.Segments)
     {
         s.Transform(isometry);
     }
     Center = isometry.Apply(Center);
 }
Beispiel #5
0
        public static void DrawPolygonSolid(Polygon p, Isometry isometry, Color color)
        {
            GL.Color3(color);
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.Begin(BeginMode.TriangleFan);
            {
                Vector3D center = isometry.Apply(p.Center);
                GL.Vertex2(center.X, center.Y);

                Vector3D[] edgePoints = p.EdgePoints;
                for (int i = 0; i < edgePoints.Length; i++)
                {
                    Vector3D draw = isometry.Apply(edgePoints[i]);
                    GL.Vertex2(draw.X, draw.Y);
                }
            }
            GL.End();
        }
Beispiel #6
0
        public static void DrawElements(HyperbolicModel model, Vector3D[] textureCoords, Vector3D[] textureVerts, int[] elements,
                                        Isometry mouseIsometry, double textureScale)
        {
            ////////////////////// ZZZ - Use VBOs
            GL.Begin(BeginMode.Triangles);
            {
                double factor  = textureScale;
                int    skipped = 0;

                for (int i = 0; i < elements.Length; i++)
                {
                    int idx = elements[i];

                    // In Poincare model.
                    GL.TexCoord2((textureCoords[idx].X * factor + 1) / 2, (textureCoords[idx].Y * factor + 1) / 2);
                    Complex transformed = textureVerts[idx].ToComplex();
                    if (mouseIsometry != null)
                    {
                        transformed = mouseIsometry.Apply(transformed);
                    }

                    switch (model)
                    {
                    case HyperbolicModel.Poincare:
                    {
                        Vertex(transformed);
                        break;
                    }

                    case HyperbolicModel.Klein:
                    {
                        Vector3D temp = Vector3D.FromComplex(transformed);
                        Vertex(PoincareToKlein(temp));
                        break;
                    }

                    case HyperbolicModel.Pseudosphere:
                    {
                        Mobius m = new Mobius();
                        m.UpperHalfPlane();
                        Complex u   = m.Apply(transformed);
                        double  x   = u.Real;
                        double  y   = u.Imaginary;
                        double  max = 1 * System.Math.PI;
                        double  min = -1 * System.Math.PI;
                        if (0 == i % 3 && (x < min - 1 || x > max + 1 || y < 0))
                        {
                            skipped = 1;
                            continue;
                        }

                        if (skipped > 0 && skipped < 3)
                        {
                            skipped++;
                            continue;
                        }

                        skipped = 0;

                        GL.TexCoord2((textureCoords[idx].X * factor + 1) / 2, (textureCoords[idx].Y * factor + 1) / 2);

                        // Pseudosphere
                        Func <double, Complex> tractrix = new Func <double, Complex>(
                            (t) =>
                            {
                                return(new Complex(t - Math.Tanh(t), 1.0 / Math.Cosh(t)));
                            });

                        //Vector3D temp1 = Vector3D.FromComplex( u );
                        if (x < min)
                        {
                            x = min;
                        }
                        if (x > max)
                        {
                            x = max;
                        }
                        if (y < 1)
                        {
                            y = 1;
                        }
                        Vector3D temp1 = new Vector3D(x, y);

                        double   logy  = Math.Log(temp1.Y);
                        Complex  tract = tractrix(logy);
                        Vector3D temp2 = new Vector3D(
                            Math.Cos(temp1.X) * tract.Imaginary,
                            Math.Sin(temp1.X) * tract.Imaginary,
                            tract.Real);

                        GL.Vertex3(temp2.X, temp2.Y, temp2.Z);

                        //temp1 = m.Inverse().Apply( temp1 );
                        //GL.Vertex3( temp1.X, temp1.Y, temp1.Z );
                        //Vertex( temp1 );

                        break;
                    }

                    case HyperbolicModel.Hyperboloid:
                    {
                        Vector3D hyper = Sterographic.PlaneToHyperboloid(Vector3D.FromComplex(transformed));                                                    // Hyperboloid
                        GL.Vertex3(hyper.X, hyper.Y, hyper.Z);
                        break;
                    }

                    default:
                    {
                        System.Diagnostics.Debug.Assert(false);
                        break;
                    }
                    }

                    /* // PETALS
                     * int petals = 7;
                     * double newMag = transformed.Magnitude * ( 1 + 0.5 * Math.Sin( transformed.Phase * petals ) );
                     * double newPhase = transformed.Phase + ( -0.2 * newMag * Math.Pow( Math.Sin( newMag * 3 ), 1 ) * Math.Cos( transformed.Phase * petals ) );
                     * transformed = Complex.FromPolarCoordinates( newMag, newPhase );
                     *
                     * Vertex( transformed );
                     * */

                    //double mag = System.Math.Pow( transformed.Magnitude, 3 ) / transformed.Magnitude;				// nice
                    //double mag = System.Math.Pow( transformed.Magnitude - 3, 2 ) + .0;							// looks spherical

                    //double mag = transformed.Magnitude + 0.1* System.Math.Sin( transformed.Magnitude * 15 );		// Fun warping (20 is cool too)
                    //Vertex( transformed * mag );

                    /*double xmag = 1;
                     * double ymag = transformed.Imaginary + 0.1 * System.Math.Sin( transformed.Imaginary * 15 );
                     * xmag = System.Math.Abs( xmag );
                     * ymag = System.Math.Abs( ymag );
                     * Vertex( new Complex( transformed.Real * xmag, transformed.Imaginary * ymag ) );	*/

                    //Vertex( 2 / System.Math.PI * Complex.Log( ( 1 + transformed ) / ( 1 - transformed ) ) );		// Band model
                    //Vertex( Complex.Pow( transformed, 3 ) / transformed.Magnitude );								// Spikey

                    // Spiral
                    //Complex band = 2 / System.Math.PI * Complex.Log( ( 1 + transformed ) / ( 1 - transformed ) );
                    //band = new Complex( band.Real, band.Imaginary + 0.3 * System.Math.Sin( band.Real * 2 ) );
                    //band = new Complex( band.Real * .5, band.Imaginary );
                    //band += new Complex( 0, .5 );
                    //Vertex( band );

                    /*
                     * double x = band.Real;
                     * double y = band.Imaginary;
                     *
                     * double r = System.Math.Exp( x );
                     * double theta = 3*( x + y/1.75 ); */
                    //Vertex( new Complex( r * System.Math.Sin( theta ), r * System.Math.Cos( theta ) ) );			// Spiral
                }
            }
            GL.End();
        }
Beispiel #7
0
 public override void Transform(Isometry i)
 {
     base.Transform(i);
     CenterNE = i.Apply(CenterNE);
 }