public Hyperbolic ( Geometry g, System.Numerics.Complex fixedPlus, double scale ) : void | ||
g | Geometry | |
fixedPlus | System.Numerics.Complex | |
scale | double | |
리턴 | void |
/// <summary> /// This will trim back the tile using an equidistant curve. /// It assumes the tile is at the origin. /// </summary> internal static void ShrinkTile( ref Tile tile, double shrinkFactor ) { // This code is not correct in non-Euclidean cases! // But it works reasonable well for small shrink factors. // For example, you can easily use this function to grow a hyperbolic tile beyond the disk. Mobius m = new Mobius(); m.Hyperbolic( tile.Geometry, new Vector3D(), shrinkFactor ); tile.Drawn.Transform( m ); return; /* // ZZZ // Wow, all the work I did below was subsumed by 4 code lines above! // I can't bring myself to delete it yet. switch( tile.Geometry ) { case Geometry.Spherical: { List<Tile> clipped = new List<Tile>(); clipped.Add( tile ); Polygon original = tile.Drawn.Clone(); foreach( Segment seg in original.Segments ) { Debug.Assert( seg.Type == SegmentType.Arc ); if( true ) { // Unproject to sphere. Vector3D p1 = Spherical2D.PlaneToSphere( seg.P1 ); Vector3D p2 = Spherical2D.PlaneToSphere( seg.P2 ); // Get the poles of the GC, and project them to the plane. Vector3D pole1, pole2; Spherical2D.GreatCirclePole( p1, p2, out pole1, out pole2 ); pole1 = Spherical2D.SphereToPlane( pole1 ); pole2 = Spherical2D.SphereToPlane( pole2 ); // Go hyperbolic, dude. double scale = 1.065; // ZZZ - needs to be configurable. Complex fixedPlus = pole1; Mobius hyperbolic = new Mobius(); hyperbolic.Hyperbolic( tile.Geometry, fixedPlus, scale ); Vector3D newP1 = hyperbolic.Apply( seg.P1 ); Vector3D newMid = hyperbolic.Apply( seg.Midpoint ); Vector3D newP2 = hyperbolic.Apply( seg.P2 ); Circle trimmingCircle = new Circle(); trimmingCircle.From3Points( newP1, newMid, newP2 ); Slicer.Clip( ref clipped, trimmingCircle, true ); } else { // I think this block has logic flaws, but strangely it seems to work, // so I'm leaving it in commented out for posterity. Vector3D p1 = seg.P1; Vector3D mid = seg.Midpoint; Vector3D p2 = seg.P2; //double offset = .1; double factor = .9; double f1 = Spherical2D.s2eNorm( (Spherical2D.e2sNorm( p1.Abs() ) * factor) ); double f2 = Spherical2D.s2eNorm( (Spherical2D.e2sNorm( mid.Abs() ) * factor) ); double f3 = Spherical2D.s2eNorm( (Spherical2D.e2sNorm( p2.Abs() ) * factor) ); p1.Normalize(); mid.Normalize(); p2.Normalize(); p1 *= f1; mid *= f2; p2 *= f3; Circle trimmingCircle = new Circle(); trimmingCircle.From3Points( p1, mid, p2 ); Slicer.Clip( ref clipped, trimmingCircle, true ); } } Debug.Assert( clipped.Count == 1 ); tile = clipped[0]; return; } case Geometry.Euclidean: { double scale = .95; Mobius hyperbolic = new Mobius(); hyperbolic.Hyperbolic( tile.Geometry, new Vector3D(), scale ); tile.Drawn.Transform( hyperbolic ); return; } case Geometry.Hyperbolic: { List<Tile> clipped = new List<Tile>(); clipped.Add( tile ); Circle infinity = new Circle(); infinity.Radius = 1.0; Polygon original = tile.Drawn.Clone(); foreach( Segment seg in original.Segments ) { Debug.Assert( seg.Type == SegmentType.Arc ); Circle segCircle = seg.GetCircle(); // Get the intersection points with the disk at infinity. Vector3D p1, p2; int count = Euclidean2D.IntersectionCircleCircle( infinity, segCircle, out p1, out p2 ); Debug.Assert( count == 2 ); Vector3D mid = seg.Midpoint; //mid *= 0.75; // ZZZ - needs to be configurable. double offset = .03; double f1 = DonHatch.h2eNorm( DonHatch.e2hNorm( mid.Abs() ) - offset ); mid.Normalize(); mid *= f1; Circle trimmingCircle = new Circle(); trimmingCircle.From3Points( p1, mid, p2 ); Slicer.Clip( ref clipped, trimmingCircle, false ); } Debug.Assert( clipped.Count == 1 ); tile = clipped[0]; return; } } */ }