public void Transform(Isometry i) { Hexagon.Transform(i); TestCircle.Transform(i); CircumCircle.Transform(i); Isometry *= i; }
public void Transform(Mobius m) { Hexagon.Transform(m); TestCircle.Transform(m); CircumCircle.Transform(m); Isometry *= new Isometry(m, null); }
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); }
/// <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); }
public Cell(Polygon boundary, CircleNE vertexCircle) { Boundary = boundary; VertexCircle = vertexCircle; Stickers = new List <Sticker>(); Isometry = new Isometry(); IndexOfMaster = -1; PickInfo = new PickInfo[] { }; }
public void Transform(Isometry i) { Boundary.Transform(i); foreach (Sticker s in Stickers) { s.Poly.Transform(i); } VertexCircle.Transform(i); }
/// <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; }
/// <summary> /// Called to reset us (needs to be done when the puzzle changes). /// </summary> public void Reset(Geometry g) { m_geometry = g; m_isometry = new Isometry(); m_rotation = 0; m_viewScale = 1.1f; m_viewLookFrom3D = new Vector3D(15, 15, 0); m_viewLookFrom4D = new Vector3D(0, 0, 7); m_up3D = new Vector3D(0, 0, 1); RotHandler4D.Current4dView = null; ProjectionDistance4D = 1.0; UpdateImageSpace(); }
/// <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); }
public void Recenter() { if (Closest == null || !Closest.IsSlave) { return; } // Isometry which will move center tile to closest. Isometry recenter = Closest.Isometry.Inverse(); // NOTE: This shouldn't be called multiple times before recalculating new center // so we safeguard against that by setting Closest to null after. m_isometry *= recenter; Closest = null; }
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(); }
/// <summary> /// Get a distribution of points on a sphere. /// The points are the vertices of a geodesic dome. /// </summary> private static Vector3D[] SpherePoints() { List <Vector3D> spherePoints = new List <Vector3D>(); TilingConfig config = new TilingConfig(3, 5); Tiling tiling = new Tiling(); tiling.GenerateInternal(config); Tile baseTile = tiling.Tiles.First(); Vector3D[] templateTextureCoords = TextureHelper.TextureCoords(baseTile.Boundary, Geometry.Spherical, doGeodesicDome: true); foreach (Tile tile in tiling.Tiles) { Isometry isom = new Isometry(); isom.CalculateFromTwoPolygons(baseTile, tile, Geometry.Spherical); Vector3D[] textureCoords = Isometry.TransformVertices(templateTextureCoords, isom.Inverse()); spherePoints.AddRange(textureCoords); } return(spherePoints.Select(p => H3Models.UHSToBall(p)).Distinct().ToArray()); }
public void Transform(Isometry i) { TransformInternal(i); }
/// <summary> /// Инициализирует новый экземпляр класса <see cref="PlanarCurve"/> с произвольным преобразованием. /// </summary> /// <param name="isometry"></param> protected PlanarCurve(Isometry isometry) { Isometry = isometry; }
/// <summary> /// Инициализирует новый экземпляр класса <see cref="PlanarCurve"/> с тождественным преобразованием. /// </summary> protected PlanarCurve() { Isometry = Isometry.Identity; }
public Tile() { Isometry = new Isometry(); EdgeIncidences = new List <Tile>(); VertexIndicences = new List <Tile>(); }
/// <summary> /// Инициализирует новый экземпляр класса <see cref="EllipticArcCurve"/> указанными параметрами. /// </summary> /// <param name="a">Полуось параллельная оси X.</param> /// <param name="b">Полуось параллельная оси Y.</param> /// <param name="angleStart">Угол (в радианах), который измеряется против часовой стрелки, начиная от оси X и заканчивая начальной точкой дуги.</param> /// <param name="angleSweep">Угол (в радианах), который измеряется против часовой стрелки, начиная от значения параметра <see cref="AngleStart"/> и заканчивая конечной точкой дуги.</param> /// <param name="isometry">Конгруэнтное преобразование трехмерного евклидова пространства.</param> public EllipticArcCurve(double a, double b, double angleStart, double angleSweep, Isometry isometry) : base(isometry) { if (a <= 0 || b <= 0) { throw new ArgumentException("Аргументы a и b, задающие полуоси эллипса должны быть больше нуля."); } A = a; B = b; AngleStart = angleStart; AngleSweep = angleSweep; if (a.Equals(b)) { _paramStart = angleStart; _paramSweep = angleSweep; } else { var sinStart = Sin(AngleStart); var cosStart = Cos(AngleStart); var angleStop = angleStart + angleSweep; var sinStop = Sin(angleStop); var cosStop = Cos(angleStop); _paramStart = Atan2(A * sinStart, B * cosStart); var paramStop = Atan2(A * sinStop, B * cosStop); if (AngleSweep * paramStop < 0) { paramStop -= Sign(paramStop) * Math.Tau; } var turns = Truncate(AngleSweep / Math.Tau); paramStop += turns * Math.Tau; _paramSweep = paramStop - _paramStart; } }
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(); }
public override void Transform(Isometry i) { base.Transform(i); CenterNE = i.Apply(CenterNE); }
public Pants() { Hexagon = new Polygon(); Isometry = new Isometry(); }
public void Transform(Isometry i) { Boundary.Transform(i); //Drawn.Transform( i ); VertexCircle.Transform(i); }
/// <summary> /// Инициализирует новый экземпляр класса <see cref="EllipticArcCurve"/> указанными параметрами. /// </summary> /// <param name="radius">Радиус дуги.</param> /// <param name="angleSweep">Угол (в радианах), который измеряется против часовой стрелки, начиная от оси X и заканчивая конечной точкой дуги.</param> /// <param name="isometry">Конгруэнтное преобразование трехмерного евклидова пространства.</param> public EllipticArcCurve(double radius, double angleSweep, Isometry isometry) : this(radius, radius, 0, angleSweep, isometry) { }