internal static void SetStandardBounds(Tiler.Settings settings) { // Default if not otherwise specified. double diskBounds = 1.01; settings.Bounds = diskBounds; switch (settings.Geometry) { case Geometry.Spherical: if (settings.SphericalModel == SphericalModel.Sterographic) { settings.Bounds = 6.5; } else if (settings.SphericalModel == SphericalModel.Equirectangular || settings.SphericalModel == SphericalModel.Mercator) { settings.Bounds = 1; } else if (settings.SphericalModel == SphericalModel.PeirceQuincuncial) { settings.Bounds = 4; } break; case Geometry.Euclidean: if (settings.EuclideanModel == EuclideanModel.Isometric || settings.EuclideanModel == EuclideanModel.Spiral || settings.EuclideanModel == EuclideanModel.Loxodromic) { settings.Bounds = 2; } break; case Geometry.Hyperbolic: if (settings.HyperbolicModel == HyperbolicModel.Orthographic || settings.HyperbolicModel == HyperbolicModel.InvertedPoincare) { settings.Bounds = 5; } else if (settings.HyperbolicModel == HyperbolicModel.Azimuthal_Equidistant) { settings.Bounds = 4; } else if (settings.HyperbolicModel == HyperbolicModel.Azimuthal_EqualArea) { settings.Bounds = 3; } else if (settings.HyperbolicModel == HyperbolicModel.Joukowsky) { settings.Bounds = 1.5; } break; } }
public static void SaveSettings(Tiler.Settings settings, string path) { XmlWriterSettings writerSettings = new XmlWriterSettings(); writerSettings.OmitXmlDeclaration = true; writerSettings.Indent = true; using (var writer = XmlWriter.Create(path, writerSettings)) { DataContractSerializer dcs = new DataContractSerializer(settings.GetType()); dcs.WriteObject(writer, settings); } }
private void GenImage(string mosaicDir, Tiler.Settings settings, int count) { string numString = count.ToString(); numString = numString.PadLeft(4, '0'); settings.FileName = Path.Combine(mosaicDir, "" + numString + ".png"); if (File.Exists(settings.FileName)) { return; } Program.MakeTiling(settings); }
static void TestCurrentQueue() { Test.IsTesting = true; string localWorkingDir = Persistence.WorkingDir; string testDir = Path.Combine(localWorkingDir, "queueTest"); DirectoryInfo di = new DirectoryInfo(testDir); foreach (FileInfo file in di.GetFiles()) { file.Delete(); } string workingDir = @"D:\GitHub\TilingBot\TilingBot\working"; workingDir = @"D:\TilingBot\working"; Persistence.WorkingDir = workingDir; string[] queue = File.ReadAllLines(Persistence.QueueFile); //string[] queue = Directory.GetFiles( Path.Combine( workingDir, "queue" ), "*.xml" ).Select( p => Path.GetFileNameWithoutExtension( p ) ).ToArray(); List <string> tweetStrings = new List <string>(); foreach (string qi in queue) { string fullPath = Path.Combine(Persistence.QueueDir, qi + ".xml"); Tiler.Settings settings = Persistence.LoadSettings(fullPath); StandardInputs(settings); string tweetString = Tweet.Format(settings); Console.WriteLine(tweetString + "\n"); tweetStrings.Add(tweetString); } File.WriteAllLines(Path.Combine(testDir, "tweetStrings.txt"), tweetStrings.ToArray()); foreach (string qi in queue) { m_timestamp = DateTime.Now; string fullPath = Path.Combine(Persistence.QueueDir, qi + ".xml"); Tiler.Settings settings = Persistence.LoadSettings(fullPath); StandardInputs(settings); settings.FileName = FormatFileName() + ".png"; string tweetString = Tweet.Format(settings); Console.WriteLine(tweetString + "\n"); tweetStrings.Add(tweetString); MakeTiling(settings); string imagePath = settings.FileName; string newPath = Path.Combine(testDir, imagePath); File.Move(imagePath, newPath); } }
private static string ShortDesc(Tiler.Settings settings) { string p = InfinitySafe(settings.P); string q = InfinitySafe(settings.Q); if (settings.IsRegularDual) { Utils.Swap(ref p, ref q); } string uniformDesc = UniformDesc(settings, false); return(string.Format("{0} {{{1},{2}}}", uniformDesc, p, q)); }
private static string UniformDesc(Tiler.Settings settings, bool addParenthesis = true) { var m = settings.Active; string uniformDesc = string.Empty; if (m.Length == 1) { if (m[0] == 0) { uniformDesc = "regular"; } else if (m[0] == 1) { uniformDesc = "rectified"; } else if (m[0] == 2) { // We'll handle duals by switching p and q in the description. uniformDesc = "regular"; } } else if (m.Length == 2) { int m1 = m[0], m2 = m[1]; if (m1 == 0 && m2 == 1) { uniformDesc = "truncated"; } else if (m1 == 1 && m2 == 2) { uniformDesc = "bitruncated"; } else if (m1 == 0 && m2 == 2) { uniformDesc = "cantellated"; } } else if (m.Length == 3) { uniformDesc = settings.IsSnub ? "snub" : "omnitruncated"; } if (addParenthesis && !string.IsNullOrEmpty(uniformDesc)) { uniformDesc = " (" + uniformDesc + ")"; } return(uniformDesc); }
public static string ArchiveToWorking(Tiler.Settings settings) { string imagePath = settings.FileName; string newPath = Path.Combine(Persistence.WorkingDir, imagePath); File.Move(imagePath, newPath); // Save settings for posterity. string settingsPath = FormatFileName() + ".xml"; settingsPath = Path.Combine(Persistence.WorkingDir, settingsPath); Persistence.SaveSettings(settings, settingsPath); return(newPath); }
static public double OffsetInModel(Tiler.Settings settings, double p = 0, double q = 0, double r = 1) { double off = OffsetInSpace(settings, p, q, r); switch (settings.Geometry) { case Geometry.Spherical: off = Spherical2D.s2eNorm(off); break; case Geometry.Hyperbolic: off = DonHatch.h2eNorm(off); break; } return(off); }
public static void RandomizeColors(Tiler.Settings settings, Random rand) { List <Color> colors = new List <Color>(); for (int i = 0; i < 5; i++) { colors.Add(RandColor(rand)); } settings.Colors = colors.ToArray(); settings.ColoringOption = RandIntWeighted(rand, new int[] { 10, 30, 10, 5 }); if (RandBool(rand)) { settings.ColoringData = new int[] { 1 } } ; }
internal static void StandardInputs(Tiler.Settings settings) { settings.Antialias = Test.IsTesting ? false : true; int size = Test.IsTesting ? 500 : 1200; settings.Width = size; settings.Height = size; // Set the standard bounds, if they aren't already set. if (settings.Bounds == 0) { SetStandardBounds(settings); } SetSpecialAspectRatios(settings); settings.Init(); }
internal static void RandomizeActive(Tiler.Settings settings, Random rand) { List <int> active = new List <int>(); if (RandBool(rand)) { active.Add(0); } if (RandBool(rand)) { active.Add(1); } if (RandBool(rand)) { active.Add(2); } if (active.Count == 0) { active.Add(0); } settings.Active = active.ToArray(); }
internal static Tiler.Settings GenSettings(bool tweeting) { Tiler.Settings settings = new Tiler.Settings(); RandomizeInputs(settings); Test.InputsTesting(ref settings); if (tweeting && !Test.IsTesting) { string next = Persistence.NextInQueue(); string queueDir = Persistence.QueueDir; string fullPath = Path.Combine(queueDir, next + ".xml"); if (File.Exists(fullPath)) { settings = Persistence.LoadSettings(fullPath); Persistence.Move(next, queueDir, Path.Combine(queueDir, "done")); } Persistence.PopQueue(); } settings.FileName = FormatFileName() + ".png"; StandardInputs(settings); return(settings); }
private static string SymmetryDesc(Tiler.Settings settings) { return(string.Format("[{0},{1}] #symmetry", InfinitySafe(settings.P), InfinitySafe(settings.Q))); }
static public Mobius OffsetMobius(Tiler.Settings settings, double p = 0, double q = 0, double r = 1) { double off = OffsetInModel(settings, p, q, r); return(Mobius.CreateFromIsometry(settings.Geometry, 0, new Complex(off, 0))); }
private static string ModelString(Tiler.Settings settings) { string model = string.Empty; string prefix = "the "; string postfix = " projection"; switch (settings.Geometry) { case Geometry.Spherical: { switch (settings.SphericalModel) { case SphericalModel.Sterographic: prefix = string.Empty; model = "stereographic"; break; case SphericalModel.Gnomonic: model = "gnomonic"; break; case SphericalModel.Azimuthal_Equidistant: model = "equidistant azimuthal"; break; case SphericalModel.Azimuthal_EqualArea: model = "equal area azimuthal"; break; case SphericalModel.Equirectangular: model = "equirectangular"; break; case SphericalModel.Mercator: model = "Mercator"; break; case SphericalModel.Orthographic: model = "orthographic"; break; case SphericalModel.Sinusoidal: model = "sinusoidal"; break; case SphericalModel.PeirceQuincuncial: model = "Peirce quincuncial"; break; } break; } case Geometry.Euclidean: { switch (settings.EuclideanModel) { case EuclideanModel.Isometric: model = "plane"; postfix = " model"; break; case EuclideanModel.Conformal: prefix = "a "; model = "conformal"; break; // These next two aren't well known and I should come up with better names. case EuclideanModel.Disk: prefix = "a "; model = "fisheye"; postfix = " view"; break; case EuclideanModel.UpperHalfPlane: prefix = "an "; model = "upper half plane"; break; case EuclideanModel.Spiral: prefix = "a "; model = "spiral"; break; case EuclideanModel.Loxodromic: prefix = "a "; model = "loxodromic"; break; } break; } case Geometry.Hyperbolic: { switch (settings.HyperbolicModel) { case HyperbolicModel.Poincare: model = "Poincaré disk"; postfix = " model"; break; case HyperbolicModel.Klein: model = "Klein"; postfix = " model"; break; case HyperbolicModel.UpperHalfPlane: model = "upper half plane"; postfix = " model"; break; case HyperbolicModel.Band: model = "band"; postfix = " model"; break; case HyperbolicModel.Orthographic: model = "orthographic"; break; case HyperbolicModel.Square: model = "conformal square"; break; case HyperbolicModel.InvertedPoincare: model = "inverted Poincaré disk"; break; case HyperbolicModel.Joukowsky: model = "Joukowsky"; break; case HyperbolicModel.Ring: model = "ring"; break; case HyperbolicModel.Azimuthal_Equidistant: model = "azimuthal equidistant"; break; case HyperbolicModel.Azimuthal_EqualArea: model = "azimuthal equal area"; break; case HyperbolicModel.Schwarz_Christoffel: prefix = postfix = string.Empty; string poly = PolygonString(settings.SchwarzChristoffelPolygon); model = $"a conformal {poly}"; break; } break; } } return(prefix + model + postfix); }
internal static void RandomModelAndMobius(Tiler.Settings settings, Random rand) { // Random model. switch (settings.Geometry) { case Geometry.Spherical: { int model = 1 + RandIntWeighted(rand, new int[] { 30, 20, 5, 15, 5, 20, 15, 15, 15 }); if (model == 2) { settings.SphericalModel = SphericalModel.Gnomonic; } if (model == 3) { settings.SphericalModel = SphericalModel.Azimuthal_Equidistant; } if (model == 4) { settings.SphericalModel = SphericalModel.Azimuthal_EqualArea; } if (model == 5) { settings.SphericalModel = SphericalModel.Equirectangular; } if (model == 6) { settings.SphericalModel = SphericalModel.Mercator; } if (model == 7) { settings.SphericalModel = SphericalModel.Orthographic; } if (model == 8) { settings.SphericalModel = SphericalModel.Sinusoidal; } if (model == 9) { settings.SphericalModel = SphericalModel.PeirceQuincuncial; } break; } case Geometry.Euclidean: { int model = 1 + RandIntWeighted(rand, new int[] { 30, 10, 10, 10, 10, 10 }); if (model == 2) { settings.EuclideanModel = EuclideanModel.Conformal; } if (model == 3) { settings.EuclideanModel = EuclideanModel.Disk; } if (model == 4) { settings.EuclideanModel = EuclideanModel.UpperHalfPlane; } if (model == 5) { settings.EuclideanModel = EuclideanModel.Spiral; } if (model == 6) { settings.EuclideanModel = EuclideanModel.Loxodromic; } break; } case Geometry.Hyperbolic: { int model = 1 + RandIntWeighted(rand, new int[] { 50, 30, 20, 40, 10, 30, 15, 15, 5, 20, 10 }); if (model == 2) { settings.HyperbolicModel = HyperbolicModel.Klein; } if (model == 3) { settings.HyperbolicModel = HyperbolicModel.UpperHalfPlane; } if (model == 4) { settings.HyperbolicModel = HyperbolicModel.Band; } if (model == 5) { settings.HyperbolicModel = HyperbolicModel.Orthographic; } if (model == 6) { settings.HyperbolicModel = HyperbolicModel.Square; } if (model == 7) { settings.HyperbolicModel = HyperbolicModel.InvertedPoincare; } if (model == 8) { settings.HyperbolicModel = HyperbolicModel.Joukowsky; } if (model == 9) { settings.HyperbolicModel = HyperbolicModel.Ring; } if (model == 10) { settings.HyperbolicModel = HyperbolicModel.Azimuthal_Equidistant; } if (model == 11) { settings.HyperbolicModel = HyperbolicModel.Azimuthal_EqualArea; } break; } } settings.Mobius = RandomMobius(settings, rand); }
public static string Format(Tiler.Settings settings) { string tilingType = string.Empty; switch (settings.Geometry) { case Geometry.Spherical: tilingType = "#Spherical"; break; case Geometry.Euclidean: tilingType = "#Euclidean"; break; case Geometry.Hyperbolic: tilingType = "#Hyperbolic"; break; } /* * From Tom Ruen... * For right angle domains, you might consider these names for tilings. * {p,q} = {p,q}_100 * t{p,q} = {p,q}_110 (truncated) * 2t{p,q} = t{p,q} = {p,q}_011 (dual truncated or bitruncated) * r{p,q} = {p,q}_010 (rectified) * rr{p,q} = {p,q}_101 (double-rectified or cantellated) * tr{p,q} = {p,q}_111 (Omnitruncated) * s{p,q} = htr{p,qP = h{p,q}_111 (snub) */ string centeringString = string.Empty; //CenteringString( settings ); string modelString = ModelString(settings); string additionalInfo = string.Empty; string link = string.Empty; if (settings.DualCompound) { additionalInfo = DualCompoundString(settings); } else if (settings.IsGeodesicDomeAnalogue) { additionalInfo = GeodesicString(settings); link = @"https://en.wikipedia.org/wiki/Geodesic_polyhedron"; } else if (settings.IsGoldberg) { additionalInfo = GoldbergString(settings); link = @"https://en.wikipedia.org/wiki/Goldberg_polyhedron"; } else if (settings.IsCatalanDual) { additionalInfo = CatalanDualString(settings); } else if (settings.CirclePacking) { additionalInfo = CirclePackingString(settings); } else { additionalInfo = Capitalize(ShortDesc(settings)) + "."; } // Consider adding links for projections as well. // https://en.wikipedia.org/wiki/Sinusoidal_projection if (settings.IsSnub && !settings.Dual) { link = @"https://en.wikipedia.org/wiki/Snub_(geometry)"; } if (!string.IsNullOrEmpty(link)) { link = " " + link; } return(string.Format("{0} #tiling shown{1} in {2}. {3}{4}", tilingType, centeringString, modelString, additionalInfo, link)); }
private static string CenteringString(Tiler.Settings settings) { // // We may not be able to describe this well in all cases, so typically we just return nothing. // if (settings.Geometry == Geometry.Spherical && settings.SphericalModel == SphericalModel.Mercator) { return(string.Empty); } if (settings.Geometry == Geometry.Euclidean && settings.EuclideanModel == EuclideanModel.UpperHalfPlane) { return(string.Empty); } if (settings.Geometry == Geometry.Hyperbolic && settings.HyperbolicModel == HyperbolicModel.UpperHalfPlane) { return(string.Empty); } if (settings.Centering == Tiler.Centering.General) { return(string.Empty); } string vertexCentered = " vertex-centered"; string edgeCentered = " edge-centered"; string tileCentered = " tile-centered"; if (settings.Centering == Tiler.Centering.Vertex) { return(vertexCentered); } if (settings.Active.Length == 1) { switch (settings.Active[0]) { case 0: { switch (settings.Centering) { case Tiler.Centering.Fundamental_Triangle_Vertex1: return(vertexCentered); case Tiler.Centering.Fundamental_Triangle_Vertex2: return(edgeCentered); case Tiler.Centering.Fundamental_Triangle_Vertex3: return(tileCentered); } break; } case 2: { switch (settings.Centering) { case Tiler.Centering.Fundamental_Triangle_Vertex1: return(tileCentered); case Tiler.Centering.Fundamental_Triangle_Vertex2: return(edgeCentered); case Tiler.Centering.Fundamental_Triangle_Vertex3: return(vertexCentered); } break; } } } return(string.Empty); }
private static string DualCompoundString(Tiler.Settings settings) { string symmetry = SymmetryDesc(settings); return(string.Format("Dual compound with {0}.", symmetry)); }
public static void Gen() { Tiler.Settings settings = Program.GenSettings(tweeting: false); //settings = Persistence.LoadSettings( Path.Combine( Persistence.WorkingDir, "2019-1-17_23-08-44.xml" ) ); settings = Persistence.LoadSettings(Path.Combine(Persistence.WorkingDir, "2019-3-18_21-49-38.xml")); // Make custom setting edits here. //settings.VertexWidth = 0.0; settings.P = 4; settings.Q = 8; settings.Centering = Tiler.Centering.Fundamental_Triangle_Vertex1; Mobius mOrig = settings.Mobius; Program.StandardInputs(settings); int numFrames = Test.IsTesting ? 20 : 180; Vector3D pStart = new Vector3D(); //Vector3D pEnd = new Vector3D( 0, OffsetInModel( settings, 2, 0, 0 ) ); Vector3D pEnd = new Vector3D(OffsetInModel(settings, 0, 2, 0), 0); //pEnd.RotateXY( Math.PI / settings.P ); //pEnd.RotateXY( Math.PI / 2 ); /*pStart = settings.Verts[0]; * pEnd = pStart; * pEnd.RotateXY( 2 * Math.PI / settings.P );*/ settings.Centering = Tiler.Centering.Fundamental_Triangle_Vertex2; Mobius t = settings.CenteringMobius(); //pStart = t.Apply( pStart ); //pEnd = t.Apply( pEnd ); Vector3D[] points = TextureHelper.SubdivideSegmentInGeometry(pStart, pEnd, numFrames, settings.Geometry); /* * // Array of Mobius transforms. * * System.Func<Vector3D, double, Vector3D> pointInDirAtDist = (dir, hDist) => * { * dir.Normalize(); * dir *= DonHatch.h2eNorm( hDist ); * return dir; * }; * * List<double> distancesSmoothed = new List<double>(); * List<double> anglesSmoothed = new List<double>(); * for( int i=0; i<numFrames; i++ ) * { * double frac = (double)i / numFrames; * double smoothedFrac = Util.Smoothed( frac, 1.0 ); * distancesSmoothed.Add( smoothedFrac * DonHatch.e2hNorm( pEnd.Abs() ) ); * anglesSmoothed.Add( smoothedFrac * Math.PI / 2 ); * } * Vector3D[] pointsSmoothed = distancesSmoothed.Select( d => pointInDirAtDist( pEnd, d ) ).ToArray(); * * // Build up a set of Mobius transformations. * Mobius trans = new Mobius(), rot = new Mobius(), runningStep = Mobius.Identity(); * trans.Geodesic( settings.Geometry, pStart.ToComplex(), pEnd.ToComplex() ); * rot.Isometry( Geometry.Euclidean, Math.PI / 2, new Complex() ); * List<Mobius> mList = new List<Mobius>(); * List<H3.Cell.Edge[]> globalEdges = new List<H3.Cell.Edge[]>(); * List<H3.Cell.Edge> completedEdges = new List<H3.Cell.Edge>(); * for( int s=0; s<=5; s++ ) * { * for( int i = 0; i < numFrames * 2; i++ ) * { * List<H3.Cell.Edge> frameEdges = new List<H3.Cell.Edge>(); * Mobius m = new Mobius(); * if( i < numFrames ) * { * Vector3D pCurrent = pointsSmoothed[i]; * m.Geodesic( settings.Geometry, pStart.ToComplex(), pCurrent.ToComplex() ); * mList.Add( runningStep * m ); * frameEdges.Add( new H3.Cell.Edge( runningStep.Apply( pStart ), runningStep.Apply( pCurrent ) ) ); * } * else * { * m.Isometry( Geometry.Euclidean, anglesSmoothed[i-numFrames], new Complex() ); * mList.Add( runningStep * trans * m ); * frameEdges.Add( new H3.Cell.Edge( runningStep.Apply( pStart ), runningStep.Apply( pEnd ) ) ); * } * frameEdges.AddRange( completedEdges ); * globalEdges.Add( frameEdges.ToArray() ); * } * completedEdges.Add( new H3.Cell.Edge( runningStep.Apply( pStart ), runningStep.Apply( pEnd ) ) ); * runningStep *= trans * rot; * } */ double ew = settings.EdgeWidth; for (int i = 0; i < numFrames; i++) { string numString = i.ToString(); numString = numString.PadLeft(3, '0'); settings.FileName = "frame" + numString + ".png"; Console.WriteLine(settings.FileName); double frac = (double)i / numFrames; // Setup the Mobius. Vector3D pCurrent = points[i]; Mobius m = Mobius.Identity(), mInitOff = Mobius.Identity(), mInitRot = Mobius.Identity(), mCentering = Mobius.Identity(), mModel = Mobius.Identity(); //mInitRot = Mobius.CreateFromIsometry( Geometry.Euclidean, frac * 2 * Math.PI, new Complex() ); //settings.Centering = Tiler.Centering.Fundamental_Triangle_Vertex2; //mCentering = settings.CenteringMobius(); double rot = frac * 2 * Math.PI / 2; settings.ImageRot = -rot; //mInitOff = OffsetMobius( settings ); mInitRot = Mobius.CreateFromIsometry(Geometry.Euclidean, -Math.PI / 4, new Complex()); //m.Isometry( settings.Geometry, Math.PI / 4, pCurrent.ToComplex() ); //m.Geodesic( settings.Geometry, pStart.ToComplex(), pCurrent.ToComplex() ); //m = mCentering * m * mCentering.Inverse(); // Rotation double xOff = OffsetInModel(settings, 0, 0, 1); m = RotAboutPoint(settings.Geometry, new Vector3D(0, 0), rot); //m = RotAboutPoint( settings.Geometry, new Vector3D( xOff, 0 ),/* -frac * Math.PI*/ -frac * 2 * Math.PI / settings.Q ); //m = LimitRot( settings, 0*Math.PI/4, 2*frac ); //m = RotAboutPoint( settings.Geometry, new Vector3D(0,0), frac * 2 * Math.PI / settings.P ); //m = mList[i]; settings.Anim = frac; // Util.Smoothed( frac, 1.0 ); // Change edge width. //double fact = 1 + settings.Anim * 20; //settings.EdgeWidth = ew * fact; //settings.GlobalEdges = globalEdges[i]; Console.WriteLine(Tweet.Format(settings) + "\n"); string newPath = Path.Combine(Persistence.AnimDir, settings.FileName); if (File.Exists(newPath)) { continue; } // Need to do this when animating where edges need recalc. settings.Init(); //mModel = RotAboutPoint( Geometry.Spherical, new Vector3D( 1, 0 ), 2 * Math.PI * frac ); //Mobius mZoom = Mobius.Scale( 1.0 / ( 1.0 - Util.Smoothed( 2*frac, 0.8 ) ) ); //mModel *= mZoom; // We will control the Mobius transformation ourself. // NOTE: Needs to be done after Init call above, or it will get clobbered. settings.Mobius = m * mCentering * mInitOff * mInitRot * mModel; settings.Centering = Tiler.Centering.General; //settings.Mobius = RotAboutPoint( settings, new Vector3D(), Math.PI / 6 ); Program.MakeTiling(settings); File.Delete(newPath); File.Move(settings.FileName, newPath); if (i == 0) { string settingsPath = Path.Combine(Persistence.AnimDir, "settings.xml"); Persistence.SaveSettings(settings, settingsPath); } } }
internal static void MakeTiling(Tiler.Settings settings) { Tiler tiler = new Tiler(); tiler.GenImage(settings); }