// Gets the distance between two points. private double Dist(Vector3D p1, Vector3D p2) { switch (this.Metric) { case Metric.Spherical: { // ZZZ - Is it too expensive to build up a mobius every time? // I wonder if there is a better way. Mobius m = new Mobius(); m.Isometry(Geometry.Spherical, 0, -p1); Vector3D temp = m.Apply(p2); return(Spherical2D.e2sNorm(temp.Abs())); } case Metric.Euclidean: { return((p2 - p1).Abs()); } case Metric.Hyperbolic: { // ZZZ - Is it too expensive to build up a mobius every time? // I wonder if there is a better way. Mobius m = new Mobius(); m.Isometry(Geometry.Hyperbolic, 0, -p1); Vector3D temp = m.Apply(p2); return(DonHatch.e2hNorm(temp.Abs())); } } throw new System.NotImplementedException(); }
/// <summary> /// A correct implementation of shrink tile. /// hmmmm, is "scaling" even well defined in non-E geometries? Am I really looking for an equidistant curve? /// Sadly, even if I figure out what is best, I fear changing out usage of the incorrect one below in MagicTile, /// because of the possibility of breaking existing puzzles. /// </summary> internal static void ShrinkTileCorrect(ref Tile tile, double shrinkFactor) { System.Func <Vector3D, double, Vector3D> scaleFunc = null; switch (tile.Geometry) { case Geometry.Euclidean: { scaleFunc = (v, s) => v * s; break; } case Geometry.Spherical: { scaleFunc = (v, s) => { // Move to spherical norm, scale, then move back to euclidean. double scale = Spherical2D.s2eNorm((Spherical2D.e2sNorm(v.Abs()) * s)); v.Normalize(); return(v * scale); }; break; } case Geometry.Hyperbolic: { throw new System.NotImplementedException(); } } }
/// <summary> /// Helper to project points from S3 -> S2, then add an associated curve. /// </summary> private static void ProjectAndAddS3Points(Shapeways mesh, Vector3D[] pointsS3, bool shrink) { // Project to S3, then to R3. List <Vector3D> projected = new List <Vector3D>(); foreach (Vector3D v in pointsS3) { v.Normalize(); Vector3D c = v.ProjectTo3DSafe(1.0); // Pull R3 into a smaller open disk. if (shrink) { double mag = Math.Atan(c.Abs()); c.Normalize(); c *= mag; } projected.Add(c); } System.Func <Vector3D, double> sizeFunc = v => { // Constant thickness. // return 0.08; double sphericalThickness = 0.002; double abs = v.Abs(); if (shrink) { abs = Math.Tan(abs); // The unshrunk abs. } // The thickness at this vector location. double result = Spherical2D.s2eNorm(Spherical2D.e2sNorm(abs) + sphericalThickness) - abs; if (shrink) { result *= Math.Atan(abs) / abs; // shrink it back down. } return(result); }; mesh.AddCurve(projected.ToArray(), sizeFunc); }