/// <summary> /// Helper to construct some points we need for calculating simplex facets for a {p,q,r} honeycomb. /// </summary> private static void TilePoints(int p, int q, out Vector3D p1, out Vector3D p2, out Vector3D p3, out Segment seg) { if (Infinite(p) && Infinite(q) /*&& FiniteOrInfinite( r )*/) { p1 = new Vector3D(1, 0, 0); p2 = new Vector3D(0, Math.Sqrt(2) - 1); p3 = Vector3D.DneVector(); Circle3D arcCircle; H3Models.Ball.OrthogonalCircleInterior(p2, p1, out arcCircle); seg = Segment.Arc(p1, p2, arcCircle.Center, clockwise: true); } else { Segment[] baseTileSegments; if (Infinite(q)) { baseTileSegments = BaseTileSegments(p, q); // Can't use dual here. } else { baseTileSegments = BaseTileSegments(q, p); // Intentionally using dual. } seg = baseTileSegments.First(); p1 = seg.P1; p2 = seg.Midpoint; p3 = p2; p3.RotateXY(-Math.PI / 2); } }
/// <summary> /// Helper to return the smaller spliced arc. /// </summary> private static Segment SmallerSplicedArc(Circle c, List <IntersectionPoint> iPoints, ref int pair, bool increment, ref int nextSegIndex) { IntersectionPoint iPoint1, iPoint2; GetPairPoints(iPoints, pair, increment, out iPoint1, out iPoint2); Vector3D p1 = iPoint1.Location; Vector3D p2 = iPoint2.Location; nextSegIndex = iPoint2.Index; Segment newSeg = Segment.Arc(p1, p2, c.Center, clockwise: true); if (newSeg.Angle > System.Math.PI) { newSeg.Clockwise = false; } pair++; if (pair == iPoints.Count / 2) { pair = 0; } return(newSeg); }
public static Polygon Heart() { Polygon newPoly = new Polygon(); double size = 0.12; double angle = -3 * Math.PI / 2; Vector3D p1 = new Vector3D(0, -1.5 * size); Vector3D p2 = new Vector3D(-size, 0); Vector3D p3 = new Vector3D(-size / 2, size); Vector3D p4 = new Vector3D(0, size / 2); Vector3D p5 = new Vector3D(size / 2, size); Vector3D p6 = new Vector3D(size, 0); p1.RotateXY(angle); p2.RotateXY(angle); p3.RotateXY(angle); p4.RotateXY(angle); p5.RotateXY(angle); p6.RotateXY(angle); newPoly.Segments.Add(Segment.Line(p1, p2)); newPoly.Segments.Add(Segment.Arc(p2, p3, p4)); newPoly.Segments.Add(Segment.Arc(p4, p5, p6)); newPoly.Segments.Add(Segment.Line(p6, p1)); return(newPoly); }
/// <summary> /// Slicing function used for earthquake puzzles. /// c should be geodesic (orthogonal to the disk boundary). /// </summary> public static void SlicePolygonWithHyperbolicGeodesic(Polygon p, CircleNE c, double thickness, out List <Polygon> output) { Geometry g = Geometry.Hyperbolic; Segment seg = null; if (c.IsLine) { Vector3D p1, p2; Euclidean2D.IntersectionLineCircle(c.P1, c.P2, new Circle(), out p1, out p2); seg = Segment.Line(p1, p2); } else { // Setup the two slicing circles. // These are cuts equidistant from the passed in geodesic. Vector3D closestToOrigin = H3Models.Ball.ClosestToOrigin(new Circle3D() { Center = c.Center, Radius = c.Radius, Normal = new Vector3D(0, 0, 1) }); Vector3D p1, p2; Euclidean2D.IntersectionCircleCircle(c, new Circle(), out p1, out p2); seg = Segment.Arc(p1, closestToOrigin, p2); } Circle c1 = H3Models.Ball.EquidistantOffset(g, seg, thickness / 2); Circle c2 = H3Models.Ball.EquidistantOffset(g, seg, -thickness / 2); CircleNE c1NE = c.Clone(), c2NE = c.Clone(); c1NE.Center = c1.Center; c2NE.Center = c2.Center; c1NE.Radius = c1.Radius; c2NE.Radius = c2.Radius; SlicePolygonHelper(p, c1NE, c2NE, out output); }
/// <summary> /// Euclidean scale us relative to some center point. /// NOTE: Currently only works for line segments. /// </summary> public void Scale(Vector3D center, double factor) { Translate(-center); if (this.Type == SegmentType.Line) { this.P1 *= factor; this.P2 *= factor; } else if (this.Type == SegmentType.Arc) { Vector3D p1 = this.P1; Vector3D p2 = this.P2; Vector3D mid = this.Midpoint; p1 *= factor; p2 *= factor; mid *= factor; Segment temp = Segment.Arc(p1, mid, p2); this.P1 = p1; this.P2 = p2; this.Center = temp.Center; } Translate(center); }