// // Creates an S-Shape // // |______ // | // ______| // | // // Order of non-collinear points is order of intersections: <this, that> public KeyValuePair <Point, Point> CreatesStandardSShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } Point thisNonCollinear = this.CreatesTShape(); Point thatNonCollinear = thatInter.CreatesTShape(); if (thisNonCollinear == null || thatNonCollinear == null) { return(nullPair); } // // Verify that the shape is PI and not an S-shape; look for the intersection point NOT between the endpoints of the transversal // // The transversal should be valid Segment transversal = this.AcquireTransversal(thatInter); Point intersection = transversal.FindIntersection(new Segment(thisNonCollinear, thatNonCollinear)); // PI-shape if (!transversal.PointLiesOnAndBetweenEndpoints(intersection)) { return(nullPair); } // S-Shape return(new KeyValuePair <Point, Point>(thisNonCollinear, thatNonCollinear)); }
//Demonstrates: congruent chords have congruent arcs public Page306Theorem7_4_1(bool onoff, bool complete) : base(onoff, complete) { Point o = new Point("O", 0, 0); points.Add(o); Point r = new Point("R", -3, 4); points.Add(r); Point s = new Point("S", 2, Math.Sqrt(21)); points.Add(s); Point t = new Point("T", 2, -Math.Sqrt(21)); points.Add(t); Point u = new Point("U", -3, -4); points.Add(u); Segment rt = new Segment(r, t); Segment su = new Segment(s, u); Point v = rt.FindIntersection(su); points.Add(v); Segment rs = new Segment(r, s); segments.Add(rs); Segment ut = new Segment(u, t); segments.Add(ut); Circle c = new Circle(o, 5.0); circles.Add(c); parser = new LiveGeometry.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); given.Add(new GeometricCongruentSegments(rs, ut)); MinorArc a1 = (MinorArc)parser.Get(new MinorArc(c, r, s)); MinorArc a2 = (MinorArc)parser.Get(new MinorArc(c, t, u)); MajorArc ma1 = (MajorArc)parser.Get(new MajorArc(c, r, s)); MajorArc ma2 = (MajorArc)parser.Get(new MajorArc(c, t, u)); goals.Add(new GeometricCongruentArcs(a1, a2)); goals.Add(new GeometricCongruentArcs(ma1, ma2)); }
public static bool IntersectAtSamePoint(Segment seg1, Segment seg2, Segment seg3) { Point intersection1 = seg1.FindIntersection(seg3); Point intersection2 = seg2.FindIntersection(seg3); return(intersection1.Equals(intersection2)); }
// // Creates a Leaner-Shape (a bench you can sit on) // // top // |______ tipStands // | // tipEndpt ______| // // Returns <tipEndpoint, tipStands> public KeyValuePair <Point, Point> CreatesLeanerShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint()) { return(nullPair); } // // Determine which is the stands and which is the endpoint // Intersection endpointInter = null; Intersection standsInter = null; if (this.StandsOnEndpoint() && thatInter.StandsOn()) { endpointInter = this; standsInter = thatInter; } else if (thatInter.StandsOnEndpoint() && this.StandsOn()) { endpointInter = thatInter; standsInter = this; } else { return(nullPair); } // // Acquire Points // Point tipStands = standsInter.CreatesTShape(); Segment transversal = this.AcquireTransversal(thatInter); Segment parallelEndpoint = endpointInter.OtherSegment(transversal); Point tipEndpoint = parallelEndpoint.OtherPoint(endpointInter.intersect); // Determine sides Segment crossingTester = new Segment(tipEndpoint, tipStands); Point intersection = transversal.FindIntersection(crossingTester); // F-Shape if (!transversal.PointLiesOnAndBetweenEndpoints(intersection)) { return(nullPair); } // Desired Leaner shape return(new KeyValuePair <Point, Point>(tipEndpoint, tipStands)); }
//Demonstrates: ExteriorAngleHalfDifferenceInterceptedArcs : two secants public Test04(bool onoff, bool complete) : base(onoff, complete) { //Circle Point o = new Point("O", 0, 0); points.Add(o); Circle circleO = new Circle(o, 5.0); circles.Add(circleO); //Intersection point for two secants Point x = new Point("X", 0, 6); points.Add(x); //Secant intersection points for circle O Point a = new Point("A", -3, -4); points.Add(a); Point b = new Point("B", 3, -4); points.Add(b); Point c, d, trash; circleO.FindIntersection(new Segment(b, x), out c, out trash); if (b.StructurallyEquals(c)) c = trash; c = new Point("C", c.X, c.Y); points.Add(c); circleO.FindIntersection(new Segment(a, x), out d, out trash); if (a.StructurallyEquals(d)) d = trash; d = new Point("D", d.X, d.Y); points.Add(d); //Create point for another arc (Arc(CE)) of equal measure to (1/2)*(Arc(AB)-Arc(CD)) Point e = new Point("E", 3, 4); points.Add(e); //Should now be able to form segments for a central angle of equal measure to (1/2)*(Arc(AB)-Arc(CD)) Segment oc = new Segment(o, c); segments.Add(oc); Segment oe = new Segment(o, e); segments.Add(oe); //Label the intersection betweeen OE and BX Point i = oe.FindIntersection(new Segment(b, x)); i = new Point("I", i.X, i.Y); points.Add(i); List<Point> pnts = new List<Point>(); pnts.Add(a); pnts.Add(d); pnts.Add(x); collinear.Add(new Collinear(pnts)); pnts = new List<Point>(); pnts.Add(b); pnts.Add(i); pnts.Add(c); pnts.Add(x); collinear.Add(new Collinear(pnts)); parser = new GeometryTutorLib.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); MinorArc farMinor1 = (MinorArc)parser.Get(new MinorArc(circleO, a, b)); MinorArc closeMinor1 = (MinorArc)parser.Get(new MinorArc(circleO, c, d)); MinorArc centralAngleArc = (MinorArc)parser.Get(new MinorArc(circleO, c, e)); given.Add(new GeometricArcEquation(new Multiplication(new NumericValue(2), centralAngleArc), new Subtraction(farMinor1, closeMinor1))); goals.Add(new GeometricCongruentAngles((Angle)parser.Get(new Angle(a, x, b)), (Angle)parser.Get(new Angle(c, o, e)))); }
// // Creates a basic S-Shape with standsOnEndpoints // // offThis ______ // | // offThat ______| // // Return <offThis, offThat> public KeyValuePair <Point, Point> CreatesBasicCShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } if (!this.StandsOnEndpoint()) { return(nullPair); } if (!thatInter.StandsOnEndpoint()) { return(nullPair); } // // Determine offThis and offThat // Segment transversal = this.AcquireTransversal(thatInter); Segment parallelThis = this.OtherSegment(transversal); Segment parallelThat = thatInter.OtherSegment(transversal); Point offThis = transversal.PointLiesOnAndBetweenEndpoints(parallelThis.Point1) ? parallelThis.Point2 : parallelThis.Point1; Point offThat = transversal.PointLiesOnAndBetweenEndpoints(parallelThat.Point1) ? parallelThat.Point2 : parallelThat.Point1; // Avoid S-shape scenario Segment crossingTester = new Segment(offThis, offThat); Point intersection = transversal.FindIntersection(crossingTester); // We may have parallel crossingTester and transversal; that's ok if (crossingTester.IsParallelWith(transversal)) { return(new KeyValuePair <Point, Point>(offThis, offThat)); } // S-shape if (transversal.PointLiesOnAndBetweenEndpoints(intersection)) { return(nullPair); } // C-Shape return(new KeyValuePair <Point, Point>(offThis, offThat)); }
// // o // eoooooooo offStands // e //offEndpoint eeeeeee // o // Returns: <offEndpoint, offStands> public KeyValuePair <Point, Point> CreatesSimpleSShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } // Restrict to desired combination if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint()) { return(nullPair); } // // Determine which is the stands and which is the endpoint // Intersection endpointInter = null; Intersection standsInter = null; if (this.StandsOnEndpoint() && thatInter.StandsOn()) { endpointInter = this; standsInter = thatInter; } else if (thatInter.StandsOnEndpoint() && this.StandsOn()) { endpointInter = this; standsInter = thatInter; } else { return(nullPair); } // Determine S shape Point offStands = standsInter.CreatesTShape(); Segment transversal = this.AcquireTransversal(thatInter); Segment parallelEndpoint = endpointInter.OtherSegment(transversal); Point offEndpoint = parallelEndpoint.OtherPoint(endpointInter.intersect); Segment crossingTester = new Segment(offStands, offEndpoint); Point intersection = transversal.FindIntersection(crossingTester); return(transversal.PointLiesOnAndBetweenEndpoints(intersection) ? new KeyValuePair <Point, Point>(offEndpoint, offStands) : nullPair); }
public static Circle ConstructCircle(Point p1, Point p2, Point p3) { // // Find the center of the circle. // Segment chord1 = new Segment(p1, p2); Segment chord2 = new Segment(p2, p3); Segment perpBis1 = chord1.GetPerpendicular(chord1.Midpoint()); Segment perpBis2 = chord2.GetPerpendicular(chord2.Midpoint()); Point center = perpBis1.FindIntersection(perpBis2); // // Radius is the distance between the circle and any of the original points. // return(new Circle(center, Point.calcDistance(center, p1))); }
//Demonstrates: If two inscribed angles intercept the same arc, the angles are congruent public Test08(bool onoff, bool complete) : base(onoff, complete) { //Points for chord BAC Point a = new Point("A", -1, -System.Math.Sqrt(24)); points.Add(a); Point b = new Point("B", -3, 4); points.Add(b); Point c = new Point("C", 2, System.Math.Sqrt(21)); points.Add(c); //Points for angle BDC Point d = new Point("D", 3, -4); points.Add(d); //Lable the intersection between BD and AC Segment ac = new Segment(a, c); Segment db = new Segment(d, b); Point i = ac.FindIntersection(db); i = new Point("I", i.X, i.Y); points.Add(i); //Segments for both angles Segment ab = new Segment(a, b); segments.Add(ab); Segment dc = new Segment(d, c); segments.Add(dc); List<Point> pnts = new List<Point>(); pnts.Add(a); pnts.Add(i); pnts.Add(c); collinear.Add(new Collinear(pnts)); pnts = new List<Point>(); pnts.Add(d); pnts.Add(i); pnts.Add(b); collinear.Add(new Collinear(pnts)); //Circle Point o = new Point("O", 0, 0); points.Add(o); Circle circleO = new Circle(o, 5.0); circles.Add(circleO); parser = new GeometryTutorLib.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); goals.Add(new GeometricCongruentAngles((Angle)parser.Get(new Angle(b, a, c)), (Angle)parser.Get(new Angle(b, d, c)))); }
//Demonstrates: Measure of an angle formed by two chords that intersect inside a circle is equal to half the sum of the measures //of the intercepted arcs //To see use of theorem, need to turn off VERTICAL_ANGLES and RELATIONS_OF_CONGRUENT_ANGLES_ARE_CONGRUENT in JustificationSwitch public Test07(bool onoff, bool complete) : base(onoff, complete) { //Circle Point o = new Point("O", 0, 0); points.Add(o); Circle circleO = new Circle(o, 5.0); circles.Add(circleO); //Points for chord ab Point a = new Point("A", -3, 4); points.Add(a); Point b = new Point("B", 3, -4); points.Add(b); //Points for chord cd Point c = new Point("C", -3, -4); points.Add(c); Point d = new Point("D", 1, System.Math.Sqrt(24)); points.Add(d); //Find intersection point of ab and cd Segment ab = new Segment(a, b); Segment cd = new Segment(c, d); Point inter = ab.FindIntersection(cd); Point z = new Point("Z", inter.X, inter.Y); points.Add(z); List<Point> pnts = new List<Point>(); pnts.Add(a); pnts.Add(z); pnts.Add(b); collinear.Add(new Collinear(pnts)); pnts = new List<Point>(); pnts.Add(c); pnts.Add(z); pnts.Add(d); collinear.Add(new Collinear(pnts)); parser = new LiveGeometry.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); goals.Add(new GeometricCongruentAngles((Angle)parser.Get(new Angle(a, z, d)), (Angle)parser.Get(new Angle(c, z, b)))); goals.Add(new GeometricCongruentAngles((Angle)parser.Get(new Angle(a, z, c)), (Angle)parser.Get(new Angle(b, z, d)))); }
//Demonstrates: Congruent chords have congruent arcs (and converse); arc addition axiom public Page309Problem09(bool onoff, bool complete) : base(onoff, complete) { Point o = new Point("O", 0, 0); points.Add(o); Point r = new Point("R", -3, 4); points.Add(r); Point s = new Point("S", 2, Math.Sqrt(21)); points.Add(s); Point t = new Point("T", 2, -Math.Sqrt(21)); points.Add(t); Point u = new Point("U", -3, -4); points.Add(u); Segment rt = new Segment(r, t); Segment su = new Segment(s, u); Point v = rt.FindIntersection(su); points.Add(v); Segment rs = new Segment(r, s); segments.Add(rs); Segment ut = new Segment(u, t); segments.Add(ut); List<Point> pnts = new List<Point>(); pnts.Add(r); pnts.Add(v); pnts.Add(t); collinear.Add(new Collinear(pnts)); pnts = new List<Point>(); pnts.Add(s); pnts.Add(v); pnts.Add(u); collinear.Add(new Collinear(pnts)); Circle c = new Circle(o, 5.0); circles.Add(c); parser = new GeometryTutorLib.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); given.Add(new GeometricCongruentSegments((Segment)parser.Get(new Segment(r, s)), (Segment)parser.Get(new Segment(u, t)))); goals.Add(new GeometricCongruentSegments((Segment)parser.Get(new Segment(r, t)), (Segment)parser.Get(new Segment(u, s)))); }
//Demonstrates: Inscribed angle half measure of intercepted arc and transitive substitution public Test03(bool onoff, bool complete) : base(onoff, complete) { Point o = new Point("O", 0, 0); points.Add(o); Point r = new Point("R", -3, 4); points.Add(r); Point t = new Point("T", 3, 4); points.Add(t); Point v = new Point("V", -3, -4); points.Add(v); Point x = new Point("X", 0, -5); points.Add(x); Segment vr = new Segment(v, r); segments.Add(vr); Segment tx = new Segment(t, x); segments.Add(tx); Segment vt = new Segment(v, t); Segment rx = new Segment(r, x); Point i = vt.FindIntersection(rx); i = new Point("I", i.X, i.Y); points.Add(i); List<Point> pnts = new List<Point>(); pnts.Add(v); pnts.Add(i); pnts.Add(o); pnts.Add(t); collinear.Add(new Collinear(pnts)); pnts = new List<Point>(); pnts.Add(x); pnts.Add(i); pnts.Add(r); collinear.Add(new Collinear(pnts)); Circle c = new Circle(o, 5.0); circles.Add(c); parser = new GeometryTutorLib.TutorParser.HardCodedParserMain(points, collinear, segments, circles, onoff); goals.Add(new GeometricCongruentAngles((Angle)parser.Get(new Angle(i, v, r)), (Angle)parser.Get(new Angle(i, x, t)))); }
// // Creates an F-Shape // top // _____ offEnd <--- Stands on Endpt // | // |_____ offStands <--- Stands on // | // | // bottom // Order of non-collinear points is order of intersections: <this, that> public KeyValuePair <Point, Point> CreatesFShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } // Avoid both standing on an endpoint if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint()) { return(nullPair); } Intersection endpt = null; Intersection standsOn = null; if (this.StandsOnEndpoint() && thatInter.StandsOn()) { endpt = this; standsOn = thatInter; } else if (thatInter.StandsOnEndpoint() && this.StandsOn()) { endpt = thatInter; standsOn = this; } else { return(nullPair); } Segment transversal = this.AcquireTransversal(thatInter); Segment transversalStands = standsOn.GetCollinearSegment(transversal); // // Determine Top and bottom to avoid PI shape // Point top = null; Point bottom = null; if (Segment.Between(standsOn.intersect, transversalStands.Point1, endpt.intersect)) { bottom = transversalStands.Point1; top = transversalStands.Point2; } else { bottom = transversalStands.Point2; top = transversalStands.Point1; } // Avoid: ____ Although this shouldn't happen since both intersections do not stand on endpoints // ____| if (transversal.HasPoint(top) && transversal.HasPoint(bottom)) { return(nullPair); } // Also avoid Simple PI-Shape // if (!transversal.HasPoint(top) && !transversal.HasPoint(bottom)) { return(nullPair); } // Find the two points that make the points of the F Segment parallelEndPt = endpt.OtherSegment(transversal); Segment parallelStands = standsOn.OtherSegment(transversal); Point offEnd = transversal.PointLiesOn(parallelEndPt.Point1) ? parallelEndPt.Point2 : parallelEndPt.Point1; Point offStands = transversal.PointLiesOn(parallelStands.Point1) ? parallelStands.Point2 : parallelStands.Point1; // Check this is not a crazy F // _____ // | // ____| // | // | Point intersection = transversal.FindIntersection(new Segment(offEnd, offStands)); if (transversal.PointLiesOnAndBetweenEndpoints(intersection)) { return(nullPair); } // Return in the order of 'off' points: <this, that> return(this.Equals(endpt) ? new KeyValuePair <Point, Point>(offEnd, offStands) : new KeyValuePair <Point, Point>(offStands, offEnd)); }
public static bool IntersectAtSamePoint(Segment seg1, Segment seg2, Segment seg3) { Point intersection1 = seg1.FindIntersection(seg3); Point intersection2 = seg2.FindIntersection(seg3); return intersection1.Equals(intersection2); }
public static Quadrilateral GenerateQuadrilateral(Segment s1, Segment s2, Segment s3, Segment s4) { // ____ // | // |____ // Check a C shape of 3 segments; the 4th needs to be opposite Segment top; Segment bottom; Segment left = AcquireMiddleSegment(s1, s2, s3, out top, out bottom); // Check C for the top, bottom, and right sides if (left == null) { return(null); } Segment right = s4; Segment tempOut1, tempOut2; Segment rightMid = AcquireMiddleSegment(top, bottom, right, out tempOut1, out tempOut2); // The middle segment we acquired must match the 4th segment if (!right.StructurallyEquals(rightMid)) { return(null); } // // The top / bottom cannot cross; bowtie or hourglass shape // A valid quadrilateral will have the intersections outside of the quad, that is defined // by the order of the three points: intersection and two endpts of the side // Point intersection = top.FindIntersection(bottom); // Check for parallel lines, then in-betweenness if (intersection != null && !double.IsNaN(intersection.X) && !double.IsNaN(intersection.Y)) { if (Segment.Between(intersection, top.Point1, top.Point2)) { return(null); } if (Segment.Between(intersection, bottom.Point1, bottom.Point2)) { return(null); } } // The left / right cannot cross; bowtie or hourglass shape intersection = left.FindIntersection(right); // Check for parallel lines, then in-betweenness if (intersection != null && !double.IsNaN(intersection.X) && !double.IsNaN(intersection.Y)) { if (Segment.Between(intersection, left.Point1, left.Point2)) { return(null); } if (Segment.Between(intersection, right.Point1, right.Point2)) { return(null); } } // // Verify that we have 4 unique points; And not different shapes (like a star, or triangle with another segment) // List <Point> pts = new List <Point>(); pts.Add(left.SharedVertex(top)); pts.Add(left.SharedVertex(bottom)); pts.Add(right.SharedVertex(bottom)); pts.Add(right.SharedVertex(top)); for (int i = 0; i < pts.Count - 1; i++) { for (int j = i + 1; j < pts.Count; j++) { if (pts[i].StructurallyEquals(pts[j])) { return(null); } } } return(new Quadrilateral(left, right, top, bottom)); }
// // Creates a Chair // // | | | // |_____|____ leftInter |_________ tipOfT // | | | // | | | // off tipOfT // // bottomInter // // <leftInter, bottomInter> // Returns the legs of the chair in specific ordering: <off, bottomTip> public KeyValuePair <Point, Point> CreatesChairShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } // Both intersections must be standing on (and not endpoints) if (!this.StandsOn() || !thatInter.StandsOn()) { return(nullPair); } if (this.StandsOnEndpoint() || thatInter.StandsOnEndpoint()) { return(nullPair); } Point thisTipOfT = this.CreatesTShape(); Point thatTipOfT = thatInter.CreatesTShape(); Segment transversal = this.AcquireTransversal(thatInter); Intersection leftInter = null; Intersection bottomInter = null; // Avoid: // | // |______ // | | // | | // this is leftInter Point bottomTip = null; if (transversal.PointLiesOn(thisTipOfT)) { if (transversal.PointLiesOnAndBetweenEndpoints(thisTipOfT)) { return(nullPair); } leftInter = this; bottomInter = thatInter; bottomTip = thisTipOfT; } // thatInter is leftInter else if (transversal.PointLiesOn(thatTipOfT)) { if (transversal.PointLiesOnAndBetweenEndpoints(thatTipOfT)) { return(nullPair); } leftInter = thatInter; bottomInter = this; bottomTip = thisTipOfT; } // Otherwise, this indicates a PI-shaped scenario else { return(nullPair); } // // Returns the bottom of the legs of the chair // Segment parallelLeft = leftInter.OtherSegment(transversal); Segment crossingTester = new Segment(parallelLeft.Point1, bottomTip); Point intersection = transversal.FindIntersection(crossingTester); Point off = transversal.PointLiesOnAndBetweenEndpoints(intersection) ? parallelLeft.Point2 : parallelLeft.Point1; return(new KeyValuePair <Point, Point>(off, bottomTip)); }
public Intersection GetIntersection(GeometryTutorLib.ConcreteAST.Segment segment1, GeometryTutorLib.ConcreteAST.Segment segment2) { Point inter = (Point)Get(segment1.FindIntersection(segment2)); return((Intersection)Get(new Intersection(inter, segment1, segment2))); }
// top // o // offStands oooooooe // e //offEndpoint eeeeeee // o // bottom // Returns: <offEndpoint, offStands> public KeyValuePair <Point, Point> CreatesSimplePIShape(Intersection thatInter) { KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } // Restrict to desired combination if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint()) { return(nullPair); } // // Determine which is the stands and which is the endpoint // Intersection endpointInter = null; Intersection standsInter = null; if (this.StandsOnEndpoint() && thatInter.StandsOn()) { endpointInter = this; standsInter = thatInter; } else if (thatInter.StandsOnEndpoint() && this.StandsOn()) { endpointInter = this; standsInter = thatInter; } else { return(nullPair); } // // Avoid Some shapes // Segment transversal = this.AcquireTransversal(thatInter); Segment transversalStands = standsInter.GetCollinearSegment(transversal); Point top = null; Point bottom = null; if (Segment.Between(standsInter.intersect, transversalStands.Point1, endpointInter.intersect)) { top = transversalStands.Point1; bottom = transversalStands.Point2; } else { top = transversalStands.Point2; bottom = transversalStands.Point1; } // Avoid: ____ Although this shouldn't happen since both intersections do not stand on endpoints // ____| // // Also avoid Simple F-Shape // if (transversal.HasPoint(top) || transversal.HasPoint(bottom)) { return(nullPair); } // Determine S shape Point offStands = standsInter.CreatesTShape(); Segment parallelEndpoint = endpointInter.OtherSegment(transversal); Point offEndpoint = parallelEndpoint.OtherPoint(endpointInter.intersect); Segment crossingTester = new Segment(offStands, offEndpoint); Point intersection = transversal.FindIntersection(crossingTester); // S-shape // PI-Shape return(transversal.PointLiesOnAndBetweenEndpoints(intersection) ? nullPair : new KeyValuePair <Point, Point>(offEndpoint, offStands)); }
public List<Area_Based_Analyses.Atomizer.AtomicRegion> Atomize(List<Point> figurePoints) { List<Segment> constructedChords = new List<Segment>(); List<Segment> constructedRadii = new List<Segment>(); List<Point> imagPoints = new List<Point>(); List<Point> interPts = GetIntersectingPoints(); // // Construct the radii // switch (interPts.Count) { // If there are no points of interest, the circle is the atomic region. case 0: return Utilities.MakeList<AtomicRegion>(new ShapeAtomicRegion(this)); // If only 1 intersection point, create the diameter. case 1: Point opp = Utilities.AcquirePoint(figurePoints, this.OppositePoint(interPts[0])); constructedRadii.Add(new Segment(center, interPts[0])); constructedRadii.Add(new Segment(center, opp)); imagPoints.Add(opp); interPts.Add(opp); break; default: foreach (Point interPt in interPts) { constructedRadii.Add(new Segment(center, interPt)); } break; } // // Construct the chords // List<Segment> chords = new List<Segment>(); for (int p1 = 0; p1 < interPts.Count - 1; p1++) { for (int p2 = p1 + 1; p2 < interPts.Count; p2++) { Segment chord = new Segment(interPts[p1], interPts[p2]); if (!DefinesDiameter(chord)) constructedChords.Add(chord); } } // // Do any of the created segments result in imaginary intersection points. // foreach (Segment chord in constructedChords) { foreach (Segment radius in constructedRadii) { Point inter = Utilities.AcquireRestrictedPoint(figurePoints, chord.FindIntersection(radius), chord, radius); if (inter != null) { chord.AddCollinearPoint(inter); radius.AddCollinearPoint(inter); // if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter); Utilities.AddUnique<Point>(imagPoints, inter); } } } for (int c1 = 0; c1 < constructedChords.Count - 1; c1++) { for (int c2 = c1 + 1; c2 < constructedChords.Count; c2++) { Point inter = constructedChords[c1].FindIntersection(constructedChords[c2]); inter = Utilities.AcquireRestrictedPoint(figurePoints, inter, constructedChords[c1], constructedChords[c2]); if (inter != null) { constructedChords[c1].AddCollinearPoint(inter); constructedChords[c2].AddCollinearPoint(inter); //if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter); Utilities.AddUnique<Point>(imagPoints, inter); } } } // // Add all imaginary points to the list of figure points. // Utilities.AddUniqueList<Point>(figurePoints, imagPoints); // // Construct the Planar graph for atomic region identification. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(); // // Add all imaginary points, intersection points, and center. // foreach (Point pt in imagPoints) { graph.AddNode(pt); } foreach (Point pt in interPts) { graph.AddNode(pt); } graph.AddNode(this.center); // // Add all chords and radii as edges. // foreach (Segment chord in constructedChords) { for (int p = 0; p < chord.collinear.Count - 1; p++) { graph.AddUndirectedEdge(chord.collinear[p], chord.collinear[p + 1], new Segment(chord.collinear[p], chord.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } foreach (Segment radius in constructedRadii) { for (int p = 0; p < radius.collinear.Count - 1; p++) { graph.AddUndirectedEdge(radius.collinear[p], radius.collinear[p + 1], new Segment(radius.collinear[p], radius.collinear[p + 1]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT); } } // // Add all arcs // List<Point> arcPts = this.ConstructAllMidpoints(interPts); for (int p = 0; p < arcPts.Count; p++) { graph.AddNode(arcPts[p]); graph.AddNode(arcPts[(p + 1) % arcPts.Count]); graph.AddUndirectedEdge(arcPts[p], arcPts[(p + 1) % arcPts.Count], new Segment(arcPts[p], arcPts[(p + 1) % interPts.Count]).Length, Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC); } // // Convert the planar graph to atomic regions. // Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph); FacetCalculator atomFinder = new FacetCalculator(copy); List<Primitive> primitives = atomFinder.GetPrimitives(); List<AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, Utilities.MakeList<Circle>(this)); // // A filament may result in the creation of a major AND minor arc; both are not required. // Figure out which one to omit. // Multiple semi-circles may arise as well; omit if they can be broken into constituent elements. // List <AtomicRegion> trueAtoms = new List<AtomicRegion>(); for (int a1 = 0; a1 < atoms.Count; a1++) { bool trueAtom = true; for (int a2 = 0; a2 < atoms.Count; a2++) { if (a1 != a2) { if (atoms[a1].Contains(atoms[a2])) { trueAtom = false; break; } } } if (trueAtom) trueAtoms.Add(atoms[a1]); } atoms = trueAtoms; return trueAtoms; }
// // Determine if the segment passes through the circle (we know it is not a chord since they have been filtered). // private bool IsSecant(Segment segment, List<Point> figPoints, out Segment chord) { // Make it null and overwrite when necessary. chord = null; // Is the segment exterior to the circle, but intersects at an endpoint (and wasn't tangent). if (this.PointIsExterior(segment.Point1) && this.PointLiesOn(segment.Point2)) return false; if (this.PointIsExterior(segment.Point2) && this.PointLiesOn(segment.Point1)) return false; // Is one endpoint of the segment simply on the interior of the circle (so we have nothing)? if (this.PointIsInterior(segment.Point1) || this.PointIsInterior(segment.Point2)) return false; if (ContainsDiameter(segment)) { chord = ConstructChord(segment, this.center, this.radius, figPoints); // Add radii to the list. radii.Add(new Segment(this.center, chord.Point1)); radii.Add(new Segment(this.center, chord.Point2)); return true; } // Acquire the line perpendicular to the segment that passes through the center of the circle. Segment perpendicular = segment.GetPerpendicular(this.center); // Is this perpendicular segment a radius? If so, it's tangent, not a secant //if (Utilities.CompareValues(perpendicular.Length, this.radius)) return false; // Is the perpendicular a radius? Check if the intersection of the segment and the perpendicular is on the circle. If so, it's tangent Point intersection = segment.FindIntersection(perpendicular); if (this.PointLiesOn(intersection)) return false; //Adjust perpendicular segment to include intersection with segment perpendicular = new Segment(intersection, this.center); // Filter the fact that there are no intersections if (perpendicular.Length > this.radius) return false; // 1/2 chord length // _____ circPoint // | / // | / // perp.Length | / radius // | / // |/ // Determine the half-chord length via Pyhtagorean Theorem. double halfChordLength = Math.Sqrt(Math.Pow(this.radius, 2) - Math.Pow(perpendicular.Length, 2)); chord = ConstructChord(segment, perpendicular.OtherPoint(this.center), halfChordLength, figPoints); return true; }
// return the midpoint between these two on the circle. public Point Midpoint(Point a, Point b, Point sameSide) { Point midpt = Midpoint(a, b); Segment segment = new Segment(a, b); Segment other = new Segment(midpt, sameSide); Point intersection = segment.FindIntersection(other); if (Segment.Between(intersection, midpt, sameSide)) return this.OppositePoint(midpt); return midpt; }
// // Determine tangency of the given segment. // Indicate tangency by returning the segment which creates the 90^0 angle. // public Segment IsTangent(Segment segment) { // If the center and the segment points are collinear, this will not be a tangent. if (segment.PointLiesOn(this.center)) return null; // Acquire the line perpendicular to the segment that passes through the center of the circle. Segment perpendicular = segment.GetPerpendicular(this.center); // If the segment was found to pass through the center, it is not a tangent if (perpendicular.Equals(segment)) return null; // Is this perpendicular segment a radius? Check length //if (!Utilities.CompareValues(perpendicular.Length, this.radius)) return null; // Is the perpendicular a radius? Check that the intersection of the segment and the perpendicular is on the circle Point intersection = segment.FindIntersection(perpendicular); if (!this.PointLiesOn(intersection)) return null; // The intersection between the perpendicular and the segment must be within the endpoints of the segment. return segment.PointLiesOnAndBetweenEndpoints(intersection) ? perpendicular : null; }
// // This is a complex situation because we need to identify situations where circles intersect with the resultant regions: // (| (|) // ( | ( | ) // ( | ( | ) // ( | ( | ) // (| (|) // // Note: There will always be a chord because of our implied construction. // We are interested in only minor arcs of the given circles. // private List<Atomizer.AtomicRegion> ConvertToCircleCircle(Segment chord, List<Circle> circles, out Circle leftOuterCircle, out Circle rightOuterCircle) { List<Atomizer.AtomicRegion> regions = new List<Atomizer.AtomicRegion>(); leftOuterCircle = null; rightOuterCircle = null; // // Simple cases that require no special attention. // if (!circles.Any()) return null; if (circles.Count == 1) { leftOuterCircle = circles[0]; regions.AddRange(ConstructBasicLineCircleRegion(chord, circles[0])); return regions; } // All circles that are on each side of the chord List<Circle> leftSide = new List<Circle>(); List<Circle> rightSide = new List<Circle>(); // For now, assume max, one circle per side. // Construct a collinear list of points that includes all circle centers as well as the single intersection point between the chord and the line passing through all circle centers. // This orders the sides and provides implied sizes. Segment centerLine = new Segment(circles[0].center, circles[1].center); for (int c = 2; c < circles.Count; c++) { centerLine.AddCollinearPoint(circles[c].center); } // Find the intersection between the center-line and the chord; add that to the list. Point intersection = centerLine.FindIntersection(chord); centerLine.AddCollinearPoint(intersection); List<Point> collPoints = centerLine.collinear; int interIndex = collPoints.IndexOf(intersection); for (int i = 0; i < collPoints.Count; i++) { // find the circle based on center int c; for (c = 0; c < circles.Count; c++) { if (circles[c].center.StructurallyEquals(collPoints[i])) break; } // Add the circle in order if (i < interIndex) leftSide.Add(circles[c]); else if (i > interIndex) rightSide.Add(circles[c]); } // the outermost circle is first in the left list and last in the right list. if (leftSide.Any()) leftOuterCircle = leftSide[0]; if (rightSide.Any()) rightOuterCircle = rightSide[rightSide.Count - 1]; // // Main combining algorithm: // Assume: Increasing Arc sequence A \in A_1, A_2, ..., A_n and the single chord C // // Construct region B = (C, A_1) // For the increasing Arc sequence (k subscript) A_2, A_3, ..., A_n // B = Construct ((C, A_k) \ B) // // Alternatively: // Construct(C, A_1) // for each pair Construct (A_k, A_{k+1}) // // // Handle each side: left and right. // if (leftSide.Any()) regions.AddRange(ConstructBasicLineCircleRegion(chord, leftSide[leftSide.Count - 1])); for (int ell = 0; ell < leftSide.Count - 2; ell++) { regions.Add(ConstructBasicCircleCircleRegion(chord, leftSide[ell], leftSide[ell + 1])); } if (rightSide.Any()) regions.AddRange(ConstructBasicLineCircleRegion(chord, rightSide[0])); for (int r = 1; r < rightSide.Count - 1; r++) { regions.Add(ConstructBasicCircleCircleRegion(chord, rightSide[r], rightSide[r + 1])); } return regions; }