public Kite(Segment left, Segment right, Segment top, Segment bottom, bool tlDiag = false, bool brDiag = false, Intersection inter = null) : base(left, right, top, bottom) { if (Utilities.CompareValues(left.Length, top.Length) && Utilities.CompareValues(right.Length, bottom.Length)) { pairASegment1 = left; pairASegment2 = top; pairBSegment1 = right; pairBSegment2 = bottom; } else if (Utilities.CompareValues(left.Length, bottom.Length) && Utilities.CompareValues(right.Length, top.Length)) { pairASegment1 = left; pairASegment2 = bottom; pairBSegment1 = right; pairBSegment2 = top; } else { throw new ArgumentException("Quadrilateral does not define a kite; no two adjacent sides are equal lengths: " + this); } //Set the diagonal and intersection values if (!tlDiag) this.SetTopLeftDiagonalInValid(); if (!brDiag) this.SetBottomRightDiagonalInValid(); this.SetIntersection(inter); }
public Square(Segment left, Segment right, Segment top, Segment bottom, bool tlDiag = false, bool brDiag = false, Intersection inter = null) : base(left, right, top, bottom) { if (!Utilities.CompareValues(topLeftAngle.measure, 90)) { throw new ArgumentException("Quadrilateral is not a Square; angle does not measure 90^o: " + topLeftAngle); } if (!Utilities.CompareValues(topRightAngle.measure, 90)) { throw new ArgumentException("Quadrilateral is not a Square; angle does not measure 90^o: " + topRightAngle); } if (!Utilities.CompareValues(bottomLeftAngle.measure, 90)) { throw new ArgumentException("Quadrilateral is not a Square; angle does not measure 90^o: " + bottomLeftAngle); } if (!Utilities.CompareValues(bottomRightAngle.measure, 90)) { throw new ArgumentException("Quadrilateral is not a Square; angle does not measure 90^o: " + bottomRightAngle); } //Set the diagonal and intersection values if (!tlDiag) this.SetTopLeftDiagonalInValid(); if (!brDiag) this.SetBottomRightDiagonalInValid(); this.SetIntersection(inter); }
// // If a common segment exists (a transversal that cuts across both intersections), return that common segment // public Segment CommonSegment(Intersection thatInter) { if (lhs.StructurallyEquals(thatInter.lhs) || lhs.IsCollinearWith(thatInter.lhs)) return lhs; if (lhs.StructurallyEquals(thatInter.rhs) || lhs.IsCollinearWith(thatInter.rhs)) return lhs; if (rhs.StructurallyEquals(thatInter.lhs) || rhs.IsCollinearWith(thatInter.lhs)) return rhs; if (rhs.StructurallyEquals(thatInter.rhs) || rhs.IsCollinearWith(thatInter.rhs)) return rhs; return null; }
public Perpendicular(Intersection inter) : base(inter.intersect, inter.lhs, inter.rhs) { // Check if truly perpendicular if (lhs.CoordinatePerpendicular(rhs) == null) { throw new ArgumentException("Intersection is not perpendicular: " + inter.ToString()); } originalInter = inter; }
// // Chair Corresponding // // | | | // |_____|____ leftInter |_________ tipOfT // | | | // | | | // off tipOfT // // bottomInter private static List<EdgeAggregator> InstantiateChairIntersection(Parallel parallel, Intersection inter1, Point off, Intersection inter2, Point bottomTip) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); Segment transversal = inter1.AcquireTransversal(inter2); Point tipOfT1 = inter1.CreatesTShape(); Point tipOfT2 = inter2.CreatesTShape(); Point leftTip = null; Intersection leftInter = null; Intersection bottomInter = null; if (transversal.PointLiesOn(tipOfT1)) { leftInter = inter1; bottomInter = inter2; leftTip = tipOfT1; } // thatInter is leftInter else if (transversal.PointLiesOn(tipOfT2)) { leftInter = inter2; bottomInter = inter1; leftTip = tipOfT2; } // // Generate the new congruence // List<CongruentAngles> newAngleRelations = new List<CongruentAngles>(); // CTA: Hack fix to alleviate exception thrown from improper congruent constructions. GeometricCongruentAngles gca = null; try { gca = new GeometricCongruentAngles(new Angle(leftTip, bottomInter.intersect, bottomTip), new Angle(bottomInter.intersect, leftInter.intersect, off)); } catch (Exception e) { if (Utilities.DEBUG) System.Diagnostics.Debug.WriteLine(e.ToString()); return newGrounded; } newAngleRelations.Add(gca); return MakeRelations(newAngleRelations, parallel, inter1, inter2); }
public Rectangle(Segment a, Segment b, Segment c, Segment d, bool tlDiag = false, bool brDiag = false, Intersection inter = null) : base(a, b, c, d) { foreach (Angle angle in angles) { if (!Utilities.CompareValues(angle.measure, 90)) { throw new ArgumentException("Quadrilateral is not a Rectangle; angle does not measure 90^o: " + angle); } } //Set the diagonal and intersection values if (!tlDiag) this.SetTopLeftDiagonalInValid(); if (!brDiag) this.SetBottomRightDiagonalInValid(); this.SetIntersection(inter); }
// // Returns the exact transversal between the intersections // public Segment AcquireTransversal(Intersection thatInter) { // The two intersections should not be at the same vertex if (intersect.Equals(thatInter.intersect)) return null; Segment common = CommonSegment(thatInter); if (common == null) return null; // A legitimate transversal must belong to both intersections (is a subsegment of one of the lines) Segment transversal = new Segment(this.intersect, thatInter.intersect); Segment thisTransversal = this.GetCollinearSegment(transversal); Segment thatTransversal = thatInter.GetCollinearSegment(transversal); if (!thisTransversal.HasSubSegment(transversal)) return null; if (!thatTransversal.HasSubSegment(transversal)) return null; return transversal; }
private static List<EdgeAggregator> CheckAndGenerateCongruentAdjacentImplyPerpendicular(Intersection intersection, CongruentAngles conAngles) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The given angles must belong to the intersection. That is, the vertex must align and all rays must overlay the intersection. if (!intersection.InducesBothAngles(conAngles)) return newGrounded; // // Now we have perpendicular scenario // Strengthened streng = new Strengthened(intersection, new Perpendicular(intersection)); // Construct hyperedge List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(intersection); antecedent.Add(conAngles); newGrounded.Add(new EdgeAggregator(antecedent, streng, annotation)); return newGrounded; }
//TODO: Need to find a way to determine the validity of diagonals, and to find the intersection if both diagonals are valid //These values are determined for base quadrilaterals by the Implied Component Calculator in the UI parser, but are never //computed for the specialized quads public Rhombus(Segment left, Segment right, Segment top, Segment bottom, bool tlDiag = false, bool brDiag = false, Intersection inter = null) : base(left, right, top, bottom) { if (!Utilities.CompareValues(top.Length, left.Length)) { throw new ArgumentException("Quadrilateral is not a Rhombus; sides are not equal length: " + top + " " + left); } if (!Utilities.CompareValues(top.Length, right.Length)) { throw new ArgumentException("Quadrilateral is not a Rhombus; sides are not equal length: " + top + " " + right); } if (!Utilities.CompareValues(top.Length, bottom.Length)) { throw new ArgumentException("Quadrilateral is not a Rhombus; sides are not equal length: " + top + " " + bottom); } //Set the diagonal and intersection values if (!tlDiag) this.SetTopLeftDiagonalInValid(); if (!brDiag) this.SetBottomRightDiagonalInValid(); this.SetIntersection(inter); }
public static List<GenericInstantiator.EdgeAggregator> GeneratePerpendicularBisector(GroundedClause tri, AngleBisector ab, Intersection inter) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); IsoscelesTriangle isoTri = (tri is Strengthened ? (tri as Strengthened).strengthened : tri) as IsoscelesTriangle; if (tri is EquilateralTriangle) { } // Does the Angle Bisector occur at the vertex angle (non-base angles) of the Isosceles triangle? try { if (!ab.angle.GetVertex().Equals(isoTri.GetVertexAngle().GetVertex())) return newGrounded; } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.ToString()); } // Is the intersection point between the endpoints of the base of the triangle? if (!Segment.Between(inter.intersect, isoTri.baseSegment.Point1, isoTri.baseSegment.Point2)) return newGrounded; // Does this intersection define this angle bisector situation? That is, the bisector and base must align with the intersection if (!inter.ImpliesRay(ab.bisector)) return newGrounded; if (!inter.HasSegment(isoTri.baseSegment)) return newGrounded; List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(tri); antecedent.Add(ab); antecedent.Add(inter); // PerpendicularBisector(M, Segment(M, C), Segment(A, B)) Strengthened newPerpB = new Strengthened(inter, new PerpendicularBisector(inter, ab.bisector)); newGrounded.Add(new EdgeAggregator(antecedent, newPerpB, annotation)); return newGrounded; }
// leftTop rightTop // | | // |_________| // | | // | | // leftBottom rightBottom // private static List<EdgeAggregator> GenerateH(Parallel parallel, Intersection crossingInterLeft, Intersection crossingInterRight) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); Segment transversal = crossingInterLeft.AcquireTransversal(crossingInterRight); // // Find tops and bottoms // Segment crossingLeftParallel = crossingInterLeft.OtherSegment(transversal); Segment crossingRightParallel = crossingInterRight.OtherSegment(transversal); // // Determine which points are on the same side of the transversal. // Segment testingCrossSegment = new Segment(crossingLeftParallel.Point1, crossingRightParallel.Point1); Point intersection = transversal.FindIntersection(testingCrossSegment); Point leftTop = crossingLeftParallel.Point1; Point leftBottom = crossingLeftParallel.Point2; Point rightTop = null; Point rightBottom = null; if (transversal.PointLiesOnAndBetweenEndpoints(intersection)) { rightTop = crossingRightParallel.Point2; rightBottom = crossingRightParallel.Point1; } else { rightTop = crossingRightParallel.Point1; rightBottom = crossingRightParallel.Point2; } // // Generate the new congruences // List<CongruentAngles> newAngleRelations = new List<CongruentAngles>(); GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(leftTop, crossingInterLeft.intersect, crossingInterRight.intersect), new Angle(rightBottom, crossingInterRight.intersect, crossingInterLeft.intersect)); newAngleRelations.Add(gca); gca = new GeometricCongruentAngles(new Angle(rightTop, crossingInterRight.intersect, crossingInterLeft.intersect), new Angle(leftBottom, crossingInterLeft.intersect, crossingInterRight.intersect)); newAngleRelations.Add(gca); return MakeRelations(newAngleRelations, parallel, crossingInterLeft, crossingInterRight); }
// offCross // | // leftCross ______|______ rightCross // | // leftStands _____|_____ rightStands // private static List<EdgeAggregator> GenerateFlying(Parallel parallel, Intersection inter1, Intersection inter2, Point offCross) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // // Determine which is the crossing intersection and which stands on the endpoints // Intersection crossingInter = null; Intersection standsInter = null; if (inter1.Crossing()) { crossingInter = inter1; standsInter = inter2; } else if (inter2.Crossing()) { crossingInter = inter2; standsInter = inter1; } // Determine the side of the crossing needed for the angle Segment transversal = inter1.AcquireTransversal(inter2); Segment parallelStands = standsInter.OtherSegment(transversal); Segment parallelCrossing = crossingInter.OtherSegment(transversal); // Determine point orientation in the plane Point leftStands = parallelStands.Point1; Point rightStands = parallelStands.Point2; Point leftCross = null; Point rightCross = null; Segment crossingTester = new Segment(leftStands, parallelCrossing.Point1); Point intersection = transversal.FindIntersection(crossingTester); if (transversal.PointLiesOnAndBetweenEndpoints(intersection)) { leftCross = parallelCrossing.Point2; rightCross = parallelCrossing.Point1; } else { leftCross = parallelCrossing.Point1; rightCross = parallelCrossing.Point2; } // // Generate the new congruence // List<CongruentAngles> newAngleRelations = new List<CongruentAngles>(); GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(rightCross, crossingInter.intersect, standsInter.intersect), new Angle(leftStands, standsInter.intersect, crossingInter.intersect)); newAngleRelations.Add(gca); gca = new GeometricCongruentAngles(new Angle(leftCross, crossingInter.intersect, standsInter.intersect), new Angle(rightStands, standsInter.intersect, crossingInter.intersect)); newAngleRelations.Add(gca); return MakeRelations(newAngleRelations, parallel, inter1, inter2); }
public SegmentBisector(Intersection b, Segment bisec) : base() { bisected = b; bisector = bisec; }
// 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)); }
// // Acquire all intersections from the maximal segment list // private void ConstructMaximalSegmentSegmentIntersections() { for (int s1 = 0; s1 < maximalSegments.Count - 1; s1++) { for (int s2 = s1 + 1; s2 < maximalSegments.Count; s2++) { // An intersection should not be between collinear segments if (!maximalSegments[s1].IsCollinearWith(maximalSegments[s2])) { // The point must be 'between' both segment endpoints Point numericInter = maximalSegments[s1].FindIntersection(maximalSegments[s2]); if (maximalSegments[s1].PointLiesOnAndBetweenEndpoints(numericInter) && maximalSegments[s2].PointLiesOnAndBetweenEndpoints(numericInter)) { // The actual point in the figure Point knownPt = GeometryTutorLib.Utilities.GetStructurally<Point>(allFigurePoints, numericInter); Intersection newInter = new Intersection(knownPt, maximalSegments[s1], maximalSegments[s2]); GeometryTutorLib.Utilities.AddStructurallyUnique<Intersection>(ssIntersections, newInter); } } } } }
public void SetIntersection(Intersection diag) { diagonalIntersection = diag; }
private static List<EdgeAggregator> MakeRelations(List<CongruentAngles> newAngleRelations, Parallel parallel, Intersection inter1, Intersection inter2) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(parallel); antecedent.Add(inter1); antecedent.Add(inter2); foreach (CongruentAngles newAngles in newAngleRelations) { newGrounded.Add(new EdgeAggregator(antecedent, newAngles, annotation)); } return newGrounded; }
// // 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)); }
// // Creates a Topped F-Shape // top // offLeft __________ offEnd <--- Stands on // | // |_____ off <--- Stands on // | // | // bottom // // Returns: <bottom, off> public KeyValuePair <Intersection, Point> CreatesToppedFShape(Intersection thatInter) { KeyValuePair <Intersection, Point> nullPair = new KeyValuePair <Intersection, Point>(null, null); // A valid transversal is required for this shape if (!this.CreatesAValidTransversalWith(thatInter)) { return(nullPair); } // Avoid both standing on an endpoint OR crossing if (this.StandsOnEndpoint() || thatInter.StandsOnEndpoint()) { return(nullPair); } if (this.Crossing() || thatInter.Crossing()) { return(nullPair); } Segment transversal = this.AcquireTransversal(thatInter); Intersection standsOnTop = null; Intersection standsOnBottom = null; // Top has 2 points on the transversal; bottom has 3 Segment nonTransversalThis = this.OtherSegment(transversal); Segment nonTransversalThat = thatInter.OtherSegment(transversal); if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point1) || transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point2)) { // | // ____| <--- Stands on // | // |_____ off <--- Stands on // | // | if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) || transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2)) { return(nullPair); } standsOnBottom = this; standsOnTop = thatInter; } else if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) || transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2)) { standsOnBottom = this; standsOnTop = thatInter; } else { return(nullPair); } // Check that the bottom extends the transversal if (!standsOnBottom.GetCollinearSegment(transversal).HasStrictSubSegment(transversal)) { return(nullPair); } Point off = standsOnBottom.OtherSegment(transversal).OtherPoint(standsOnBottom.intersect); return(new KeyValuePair <Intersection, Point>(standsOnBottom, off)); }
// // Creates a basic S-Shape with standsOnEndpoints // // ______ offThat // | // offThis ______| // // Return <offThis, offThat> private static List<EdgeAggregator> GenerateSimpleS(Parallel parallel, Intersection inter1, Point offThis, Intersection inter2, Point offThat) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // // Generate the new congruence // List<CongruentAngles> newAngleRelations = new List<CongruentAngles>(); GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(offThat, inter2.intersect, inter1.intersect), new Angle(offThis, inter1.intersect, inter2.intersect)); newAngleRelations.Add(gca); return MakeRelations(newAngleRelations, parallel, inter1, inter2); }
// // A \ // \ B // \ / // O \/ X // /\ // / \ // C / D // // One Secant, One Tangent // Intersection(X, AD, BC), Tangent(Circle(O), BC) -> 2 * Angle(AXC) = MajorArc(AC) - MinorArc(AC) // public static List<EdgeAggregator> InstantiateOneSecantOneTangentTheorem(Intersection inter, Tangent tangent, GroundedClause original) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); CircleSegmentIntersection tan = tangent.intersection as CircleSegmentIntersection; // Is the tangent segment part of the intersection? if (!inter.HasSegment(tan.segment)) return newGrounded; // Acquire the chord that the intersection creates. Segment secant = inter.OtherSegment(tan.segment); Circle circle = tan.theCircle; Segment chord = circle.ContainsChord(secant); // Check if this segment never intersects the circle or doesn't create a chord. if (chord == null) return newGrounded; // // Get the near / far points out of the chord // Point closeChordPt = null; Point farChordPt = null; if (Segment.Between(chord.Point1, chord.Point2, inter.intersect)) { closeChordPt = chord.Point1; farChordPt = chord.Point2; } else { closeChordPt = chord.Point2; farChordPt = chord.Point1; } // // Acquire the arcs // // Get the close arc first which we know exactly how it is constructed AND that it's a minor arc. Arc closeArc = Arc.GetFigureMinorArc(circle, closeChordPt, tan.intersect); // The far arc MAY be a major arc; if it is, the first candidate arc will contain the close arc. Arc farArc = Arc.GetFigureMinorArc(circle, farChordPt, tan.intersect); if (farArc.HasMinorSubArc(closeArc)) { farArc = Arc.GetFigureMajorArc(circle, farChordPt, tan.intersect); } Angle theAngle = Angle.AcquireFigureAngle(new Angle(closeChordPt, inter.intersect, tan.intersect)); // // Construct the new relationship // NumericValue two = new NumericValue(2); GeometricAngleArcEquation gaaeq = new GeometricAngleArcEquation(new Multiplication(two, theAngle), new Subtraction(farArc, closeArc)); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(original); antecedent.Add(inter); antecedent.Add(closeArc); antecedent.Add(farArc); newGrounded.Add(new EdgeAggregator(antecedent, gaaeq, annotation)); return newGrounded; }
// // Creates a Topped F-Shape // top // oppSide __________ <--- Stands on // | // |_____ off <--- Stands on // | // | // bottom // // Returns: <bottom, off> private static List<EdgeAggregator> GenerateToppedFShape(Parallel parallel, Intersection inter1, Intersection inter2, Intersection bottom, Point off) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); Intersection top = inter1.Equals(bottom) ? inter2 : inter1; // Determine the side of the top intersection needed for the angle Segment transversal = inter1.AcquireTransversal(inter2); Segment parallelTop = top.OtherSegment(transversal); Segment parallelBottom = bottom.OtherSegment(transversal); Segment crossingTester = new Segment(off, parallelTop.Point1); Point intersection = transversal.FindIntersection(crossingTester); Point oppSide = transversal.PointLiesOnAndBetweenEndpoints(intersection) ? parallelTop.Point1 : parallelTop.Point2; // // Generate the new congruence // List<CongruentAngles> newAngleRelations = new List<CongruentAngles>(); GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(off, bottom.intersect, top.intersect), new Angle(oppSide, top.intersect, bottom.intersect)); newAngleRelations.Add(gca); return MakeRelations(newAngleRelations, parallel, inter1, inter2); }
// // A \ // \ B // \ / // O \/ X // /\ // / \ // C / D // // Two tangents: // Intersection(X, AD, BC), Tangent(Circle(O), BC), Tangent(Circle(O), AD) -> 2 * Angle(AXC) = MajorArc(AC) - MinorArc(AC) // public static List<EdgeAggregator> InstantiateTwoTangentsTheorem(Tangent tangent1, Tangent tangent2, Intersection inter, GroundedClause original1, GroundedClause original2) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); CircleSegmentIntersection tan1 = tangent1.intersection as CircleSegmentIntersection; CircleSegmentIntersection tan2 = tangent2.intersection as CircleSegmentIntersection; if (tan1.StructurallyEquals(tan2)) return newGrounded; // Do the tangents apply to the same circle? if (!tan1.theCircle.StructurallyEquals(tan2.theCircle)) return newGrounded; Circle circle = tan1.theCircle; // Do these tangents work with this intersection? if (!inter.HasSegment(tan1.segment) || !inter.HasSegment(tan2.segment)) return newGrounded; // Overkill? Do the tangents intersect at the same point as the intersection's intersect point? if (!tan1.segment.FindIntersection(tan2.segment).StructurallyEquals(inter.intersect)) return newGrounded; // // Get the arcs // Arc minorArc = new MinorArc(circle, tan1.intersect, tan2.intersect); Arc majorArc = new MajorArc(circle, tan1.intersect, tan2.intersect); Angle theAngle = new Angle(tan1.intersect, inter.intersect, tan2.intersect); // // Construct the new relationship // NumericValue two = new NumericValue(2); GeometricAngleArcEquation gaaeq = new GeometricAngleArcEquation(new Multiplication(two, theAngle), new Subtraction(majorArc, minorArc)); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(original1); antecedent.Add(original2); antecedent.Add(inter); antecedent.Add(majorArc); antecedent.Add(minorArc); newGrounded.Add(new EdgeAggregator(antecedent, gaaeq, annotation)); return newGrounded; }
private static List<EdgeAggregator> CheckAndGenerateParallelImplyAlternateInterior(Intersection inter1, Intersection inter2, Parallel parallel) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The two intersections should not be at the same vertex if (inter1.intersect.Equals(inter2.intersect)) return newGrounded; // Determine the transversal Segment transversal = inter1.AcquireTransversal(inter2); if (transversal == null) return newGrounded; // // Ensure the non-traversal segments align with the parallel segments // Segment parallel1 = inter1.OtherSegment(transversal); Segment parallel2 = inter2.OtherSegment(transversal); // The non-transversals should not be the same (coinciding) if (parallel1.IsCollinearWith(parallel2)) return newGrounded; Segment coincidingParallel1 = parallel.CoincidesWith(parallel1); Segment coincidingParallel2 = parallel.CoincidesWith(parallel2); // The pair of non-transversals needs to align exactly with the parallel pair of segments if (coincidingParallel1 == null || coincidingParallel2 == null) return newGrounded; // Both intersections should not be referring to an intersection point on the same parallel segment if (parallel.segment1.PointLiesOn(inter1.intersect) && parallel.segment1.PointLiesOn(inter2.intersect)) return newGrounded; if (parallel.segment2.PointLiesOn(inter1.intersect) && parallel.segment2.PointLiesOn(inter2.intersect)) return newGrounded; // The resultant candidate parallel segments shouldn't share any vertices if (coincidingParallel1.SharedVertex(coincidingParallel2) != null) return newGrounded; if (inter1.StandsOnEndpoint() && inter2.StandsOnEndpoint()) { // // Creates a basic S-Shape with standsOnEndpoints // // offThis ______ // | // offThat ______| // // Return <offThis, offThat> KeyValuePair<Point, Point> cShapePoints = inter1.CreatesBasicCShape(inter2); if (cShapePoints.Key != null && cShapePoints.Value != null) return newGrounded; // // Creates a basic S-Shape with standsOnEndpoints // // ______ offThat _______ // | \ // offThis ______| _____\ // // Return <offThis, offThat> KeyValuePair<Point, Point> sShapePoints = inter1.CreatesBasicSShape(inter2); if (sShapePoints.Key != null && sShapePoints.Value != null) { return GenerateSimpleS(parallel, inter1, sShapePoints.Key, inter2, sShapePoints.Value); } return newGrounded; } // _______/________ // / // / // ______/_______ // / if (inter1.Crossing() && inter2.Crossing()) return GenerateDualCrossings(parallel, inter1, inter2); // No alt int in this case: // Creates an F-Shape // top // _____ offEnd <--- Stands on Endpt // | // |_____ offStands <--- Stands on // | // | // bottom KeyValuePair<Point, Point> fShapePoints = inter1.CreatesFShape(inter2); if (fShapePoints.Key != null && fShapePoints.Value != null) return newGrounded; // Alt. Int if an H-Shape // // | | // |_____| // | | // | | // if (inter1.CreatesHShape(inter2)) return GenerateH(parallel, inter1, inter2); // Creates an S-Shape // // |______ // | // ______| // | // // Order of non-collinear points is order of intersections: <this, that> KeyValuePair<Point, Point> standardSShapePoints = inter1.CreatesStandardSShape(inter2); if (standardSShapePoints.Key != null && standardSShapePoints.Value != null) { return GenerateSimpleS(parallel, inter1, standardSShapePoints.Key, inter2, standardSShapePoints.Value); } // Corresponding if a flying-Shape // // | | // |_____|___ offCross // | | // | | // Point offCross = inter1.CreatesFlyingShapeWithCrossing(inter2); if (offCross != null) { return GenerateFlying(parallel, inter1, inter2, offCross); } // // Creates a shape like an extended t // offCross offCross // | | // _____|____ ______|______ // | | // |_____ offStands offStands _____| // // Returns <offStands, offCross> KeyValuePair<Point, Point> tShapePoints = inter1.CreatesCrossedTShape(inter2); if (tShapePoints.Key != null && tShapePoints.Value != null) { return GenerateCrossedT(parallel, inter1, inter2, tShapePoints.Key, tShapePoints.Value); } // // Creates a Topped F-Shape // top // offLeft __________ offEnd <--- Stands on // | // |_____ off <--- Stands on // | // | // bottom // // Returns: <bottom, off> KeyValuePair<Intersection, Point> toppedFShapePoints = inter1.CreatesToppedFShape(inter2); if (toppedFShapePoints.Key != null && toppedFShapePoints.Value != null) { return GenerateToppedFShape(parallel, inter1, inter2, toppedFShapePoints.Key, toppedFShapePoints.Value); } return newGrounded; }
// \ A // \ // \ // center: O / P // / // / B // // Tangent(Circle(O), Segment(B, P)), // Tangent(Circle(O), Segment(A, P)), // Intersection(AP, BP) -> Congruent(Segment(A, P), Segment(P, B)) // private static List<EdgeAggregator> InstantiateTheorem(Tangent tangent1, Tangent tangent2, Intersection inter, GroundedClause original1, GroundedClause original2) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // Do the tangents apply to the same circle? if (!tangent1.intersection.theCircle.StructurallyEquals(tangent2.intersection.theCircle)) return newGrounded; // Do the tangents have components the are part of the third intersection if (!inter.HasSegment((tangent1.intersection as CircleSegmentIntersection).segment)) return newGrounded; if (!inter.HasSegment((tangent2.intersection as CircleSegmentIntersection).segment)) return newGrounded; Segment segment1 = Segment.GetFigureSegment(inter.intersect, tangent1.intersection.intersect); Segment segment2 = Segment.GetFigureSegment(inter.intersect, tangent2.intersection.intersect); GeometricCongruentSegments gcs = new GeometricCongruentSegments(segment1, segment2); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(original1); antecedent.Add(original2); antecedent.Add(inter); newGrounded.Add(new EdgeAggregator(antecedent, gcs, annotation)); return newGrounded; }
// // Generate all covering intersection clauses; that is, generate maximal intersections (a subset of all intersections) // private void CalculateIntersections() { // // Iterate over all polygons // for (int sidesIndex = Polygon.MIN_POLY_INDEX; sidesIndex < Polygon.MAX_EXC_POLY_INDEX; sidesIndex++) { foreach (Polygon poly in polygons[sidesIndex]) { // // Add intersection clauses for all sides the polygon // List<Segment> sides = poly.orderedSides; for (int s1 = 0; s1 < sides.Count - 1; s1++) { for (int s2 = s1 + 1; s2 < sides.Count; s2++) { // The shared vertex must be a vertex of the polygon Point vertex = sides[s1].SharedVertex(sides[s2]); if (vertex != null && poly.points.Contains(vertex)) { GeometryTutorLib.Utilities.AddStructurallyUnique(ssIntersections, new Intersection(vertex, sides[s1], sides[s2])); } } } // // Handle quadrilateral diagonals // if (poly is Quadrilateral) { Quadrilateral quad = poly as Quadrilateral; if (GetMaximalProblemSegment(quad.bottomLeftTopRightDiagonal) == null) { quad.SetBottomRightDiagonalInValid(); } if (GetMaximalProblemSegment(quad.topLeftBottomRightDiagonal) == null) { quad.SetTopLeftDiagonalInValid(); } // If both diagonals exist in the figure, create an intersection and provide the quadrilateral with the intersection. if (quad.TopLeftDiagonalIsValid() && quad.BottomRightDiagonalIsValid()) { // The calculated intersection Point inter = quad.bottomLeftTopRightDiagonal.FindIntersection(quad.topLeftBottomRightDiagonal); // The actual point in the figure Point knownPt = GeometryTutorLib.Utilities.GetStructurally<Point>(allFigurePoints, inter); if (knownPt == null) { throw new Exception("Expected to find the point (did not):"); } Intersection diagInter = new Intersection(knownPt, quad.bottomLeftTopRightDiagonal, quad.topLeftBottomRightDiagonal); GeometryTutorLib.Utilities.AddStructurallyUnique<Intersection>(ssIntersections, diagInter); quad.SetIntersection(diagInter); } } } } CalculateMaximalMinimalSegments(); ConstructMaximalSegmentSegmentIntersections(); }
//public PerpendicularBisector(Point i, Segment l, Segment bisector, string just) : base(i, l, bisector, just) //{ // this.bisector = bisector; //} public PerpendicularBisector(Intersection inter, Segment bisector) : base(inter) { this.bisector = bisector; }
private static List<EdgeAggregator> CheckAndGenerateProportionality(Triangle tri, Intersection inter1, Intersection inter2, Parallel parallel) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The two intersections should not be at the same vertex if (inter1.intersect.Equals(inter2.intersect)) return newGrounded; // // Do these intersections share a segment? That is, do they share the transversal? // Segment transversal = inter1.AcquireTransversal(inter2); if (transversal == null) return newGrounded; // // Is the transversal a side of the triangle? It should not be. // if (tri.LiesOn(transversal)) return newGrounded; // // Determine if one parallel segment is a side of the triangle (which must occur) // Segment coinciding = tri.DoesParallelCoincideWith(parallel); if (coinciding == null) return newGrounded; // The transversal and common segment must be distinct if (coinciding.IsCollinearWith(transversal)) return newGrounded; // // Determine if the simplified transversal is within the parallel relationship. // Segment parallelTransversal = parallel.OtherSegment(coinciding); Segment simpleParallelTransversal = new Segment(inter1.intersect, inter2.intersect); if (!parallelTransversal.IsCollinearWith(simpleParallelTransversal)) return newGrounded; // A // /\ // / \ // / \ // off1 /------\ off2 // / \ // B /__________\ C // // Both intersections should create a T-shape. // Point off1 = inter1.CreatesTShape(); Point off2 = inter2.CreatesTShape(); if (off1 == null || off2 == null) return newGrounded; // Get the intersection segments which should coincide with the triangle sides KeyValuePair<Segment, Segment> otherSides = tri.OtherSides(coinciding); // The intersections may be outside this triangle if (otherSides.Key == null || otherSides.Value == null) return newGrounded; Segment side1 = inter1.OtherSegment(transversal); Segment side2 = inter2.OtherSegment(transversal); // Get the actual sides of the triangle Segment triangleSide1 = null; Segment triangleSide2 = null; if (side1.IsCollinearWith(otherSides.Key) && side2.IsCollinearWith(otherSides.Value)) { triangleSide1 = otherSides.Key; triangleSide2 = otherSides.Value; } else if (side1.IsCollinearWith(otherSides.Value) && side2.IsCollinearWith(otherSides.Key)) { triangleSide1 = otherSides.Value; triangleSide2 = otherSides.Key; } else return newGrounded; // Verify the opposing parts of the T are on the opposite sides of the triangle if (!triangleSide1.PointLiesOnAndExactlyBetweenEndpoints(off2)) return newGrounded; if (!triangleSide2.PointLiesOnAndExactlyBetweenEndpoints(off1)) return newGrounded; // // Construct the new proprtional relationship and resultant equation // Point sharedVertex = triangleSide1.SharedVertex(triangleSide2); SegmentRatio newProp1 = new SegmentRatio(new Segment(sharedVertex, off2), triangleSide1); SegmentRatio newProp2 = new SegmentRatio(new Segment(sharedVertex, off1), triangleSide2); GeometricSegmentRatioEquation newEq = new GeometricSegmentRatioEquation(newProp1, newProp2); // Construct hyperedge List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(tri); antecedent.Add(inter1); antecedent.Add(inter2); antecedent.Add(parallel); newGrounded.Add(new EdgeAggregator(antecedent, newEq, annotation)); return newGrounded; }
// // 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)); }
// // A \ // \ B // \ / // O \/ X // /\ // / \ // C / D // // Two Secants // Intersection(X, AD, BC) -> 2 * Angle(AXC) = MajorArc(AC) - MinorArc(AC) // public static List<EdgeAggregator> InstantiateTwoSecantsTheorem(Intersection inter, Circle circle) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // Is this intersection explicitly outside the circle? That is, the point of intersection exterior? if (!circle.PointIsExterior(inter.intersect)) return newGrounded; // // Get the chords // Segment chord1 = circle.ContainsChord(inter.lhs); Segment chord2 = circle.ContainsChord(inter.rhs); if (chord1 == null || chord2 == null) return newGrounded; Point closeChord1Pt = null; Point closeChord2Pt = null; Point farChord1Pt = null; Point farChord2Pt = null; if (Segment.Between(chord1.Point1, chord1.Point2, inter.intersect)) { closeChord1Pt = chord1.Point1; farChord1Pt = chord1.Point2; } else { closeChord1Pt = chord1.Point2; farChord1Pt = chord1.Point1; } if (Segment.Between(chord2.Point1, chord2.Point2, inter.intersect)) { closeChord2Pt = chord2.Point1; farChord2Pt = chord2.Point2; } else { closeChord2Pt = chord2.Point2; farChord2Pt = chord2.Point1; } // // Get the arcs // Arc closeArc = Arc.GetFigureMinorArc(circle, closeChord1Pt, closeChord2Pt); Arc farArc = Arc.GetFigureMinorArc(circle, farChord1Pt, farChord2Pt); Angle theAngle = Angle.AcquireFigureAngle(new Angle(closeChord1Pt, inter.intersect, closeChord2Pt)); // // Construct the new relationship // NumericValue two = new NumericValue(2); //GeometricAngleEquation gaeq = new GeometricAngleEquation(new Multiplication(two, theAngle), new Subtraction(farArc, closeArc)); GeometricAngleArcEquation gaaeq = new GeometricAngleArcEquation(new Multiplication(two, theAngle), new Subtraction(farArc, closeArc)); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(inter); antecedent.Add(circle); antecedent.Add(closeArc); antecedent.Add(farArc); newGrounded.Add(new EdgeAggregator(antecedent, gaaeq, annotation)); return newGrounded; }
private static List<GroundedClause> MakeAntecedent(Intersection inter, Angle angle1, Angle angle2) { List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(inter); antecedent.Add(angle1); antecedent.Add(angle2); return antecedent; }
private static List<EdgeAggregator> CheckAndGenerateCorrespondingAnglesImplyParallel(Intersection inter1, Intersection inter2, CongruentAngles conAngles) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The two intersections should not be at the same vertex if (inter1.intersect.Equals(inter2.intersect)) return newGrounded; Segment transversal = inter1.CommonSegment(inter2); if (transversal == null) return newGrounded; Angle angleI = inter1.GetInducedNonStraightAngle(conAngles); Angle angleJ = inter2.GetInducedNonStraightAngle(conAngles); // // Do we have valid intersections and congruent angle pairs // if (angleI == null || angleJ == null) return newGrounded; // // Check to see if they are, in fact, Corresponding Angles // Segment parallelCand1 = inter1.OtherSegment(transversal); Segment parallelCand2 = inter2.OtherSegment(transversal); // The resultant candidate parallel segments shouldn't share any vertices if (parallelCand1.SharedVertex(parallelCand2) != null) return newGrounded; // Numeric hack to discount any non-parallel segments if (!parallelCand1.IsParallelWith(parallelCand2)) return newGrounded; // A sanity check that the '4th' point does not lie on the other intersection (thus creating an obvious triangle and thus not parallel lines) Point fourthPoint1 = parallelCand1.OtherPoint(inter1.intersect); Point fourthPoint2 = parallelCand2.OtherPoint(inter2.intersect); if (fourthPoint1 != null && fourthPoint2 != null) { if (parallelCand1.PointLiesOn(fourthPoint2) || parallelCand2.PointLiesOn(fourthPoint1)) return newGrounded; } // Both angles should NOT be in the interioir OR the exterioir; a combination is needed. bool ang1Interior = angleI.OnInteriorOf(inter1, inter2); bool ang2Interior = angleJ.OnInteriorOf(inter1, inter2); if (ang1Interior && ang2Interior) return newGrounded; if (!ang1Interior && !ang2Interior) return newGrounded; // // Are these angles on the same side of the transversal? // // // Make a simple transversal from the two intersection points Segment simpleTransversal = new Segment(inter1.intersect, inter2.intersect); // Find the rays the lie on the transversal Segment rayNotOnTransversalI = angleI.OtherRayEquates(simpleTransversal); Segment rayNotOnTransversalJ = angleJ.OtherRayEquates(simpleTransversal); Point pointNotOnTransversalNorVertexI = rayNotOnTransversalI.OtherPoint(angleI.GetVertex()); Point pointNotOnTransversalNorVertexJ = rayNotOnTransversalJ.OtherPoint(angleJ.GetVertex()); // Create a segment from these two points so we can compare distances Segment crossing = new Segment(pointNotOnTransversalNorVertexI, pointNotOnTransversalNorVertexJ); // // Will this crossing segment actually intersect the real transversal in the middle of the two segments It should NOT. // Point intersection = transversal.FindIntersection(crossing); if (Segment.Between(intersection, inter1.intersect, inter2.intersect)) return newGrounded; // // Now we have an alternate interior scenario // GeometricParallel newParallel = new GeometricParallel(parallelCand1, parallelCand2); // Construct hyperedge List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(inter1); antecedent.Add(inter2); antecedent.Add(conAngles); newGrounded.Add(new EdgeAggregator(antecedent, newParallel, annotation)); return newGrounded; }
// A B // \ / // \ / // \/ // /\ X // / \ // / \ // C D // // Intersection(X, Segment(A, D), Segment(B, C)) -> Supplementary(Angle(A, X, B), Angle(B, X, D)) // Supplementary(Angle(B, X, D), Angle(D, X, C)) // Supplementary(Angle(D, X, C), Angle(C, X, A)) // Supplementary(Angle(C, X, A), Angle(A, X, B)) // public static List<EdgeAggregator> InstantiateToSupplementary(Intersection inter) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The situation looks like this: // | // | // |_______ // if (inter.StandsOnEndpoint()) return newGrounded; // The situation looks like this: // | // | // _____|_______ // if (inter.StandsOn()) { Point up = null; Point left = null; Point right = null; if (inter.lhs.HasPoint(inter.intersect)) { up = inter.lhs.OtherPoint(inter.intersect); left = inter.rhs.Point1; right = inter.rhs.Point2; } else { up = inter.rhs.OtherPoint(inter.intersect); left = inter.lhs.Point1; right = inter.lhs.Point2; } // Gets the single angle object from the original figure Angle newAngle1 = Angle.AcquireFigureAngle(new Angle(left, inter.intersect, up)); Angle newAngle2 = Angle.AcquireFigureAngle(new Angle(right, inter.intersect, up)); Supplementary supp = new Supplementary(newAngle1, newAngle2); supp.SetNotASourceNode(); supp.SetNotAGoalNode(); supp.SetClearDefinition(); newGrounded.Add(new EdgeAggregator(MakeAntecedent(inter, supp.angle1, supp.angle2), supp, annotation)); } // // The situation is standard and results in 4 supplementary relationships // else { Angle newAngle1 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point1, inter.intersect, inter.rhs.Point1)); Angle newAngle2 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point1, inter.intersect, inter.rhs.Point2)); Angle newAngle3 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point2, inter.intersect, inter.rhs.Point1)); Angle newAngle4 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point2, inter.intersect, inter.rhs.Point2)); List<Supplementary> newSupps = new List<Supplementary>(); newSupps.Add(new Supplementary(newAngle1, newAngle2)); newSupps.Add(new Supplementary(newAngle2, newAngle4)); newSupps.Add(new Supplementary(newAngle3, newAngle4)); newSupps.Add(new Supplementary(newAngle3, newAngle1)); foreach (Supplementary supp in newSupps) { supp.SetNotASourceNode(); supp.SetNotAGoalNode(); supp.SetClearDefinition(); newGrounded.Add(new EdgeAggregator(MakeAntecedent(inter, supp.angle1, supp.angle2), supp, annotation)); } } return newGrounded; }
//public PerpendicularBisector(Point i, Segment l, Segment bisector, string just) : base(i, l, bisector, just) //{ // this.bisector = bisector; //} public PerpendicularBisector(Intersection inter, Segment bisector) : base(inter) { this.bisector = bisector; }
// // A \ / B // \ / // \ / // O \/ X // /\ // / \ // C / \ D // // Intersection(Segment(AD), Segment(BC)) -> 2 * Angle(CXA) = Arc(A, C) + Arc(B, D), // 2 * Angle(BXD) = Arc(A, C) + Arc(B, D), // 2 * Angle(AXB) = Arc(A, B) + Arc(C, D), // 2 * Angle(CXD) = Arc(A, B) + Arc(C, D) // public static List<EdgeAggregator> InstantiateTheorem(Intersection inter, Circle circle) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // Is this intersection explicitly inside the circle? That is, the point of intersection interior? if (!circle.PointIsInterior(inter.intersect)) return newGrounded; // // Get the chords // Segment chord1 = circle.GetChord(inter.lhs); Segment chord2 = circle.GetChord(inter.rhs); if (chord1 == null || chord2 == null) return newGrounded; // // Group 1 // Arc arc1 = Arc.GetFigureMinorArc(circle, chord1.Point1, chord2.Point1); Angle angle1 = Angle.AcquireFigureAngle(new Angle(chord1.Point1, inter.intersect, chord2.Point1)); Arc oppArc1 = Arc.GetFigureMinorArc(circle, chord1.Point2, chord2.Point2); Angle oppAngle1 = Angle.AcquireFigureAngle(new Angle(chord1.Point2, inter.intersect, chord2.Point2)); // // Group 2 // Arc arc2 = Arc.GetFigureMinorArc(circle, chord1.Point1, chord2.Point2); Angle angle2 = Angle.AcquireFigureAngle(new Angle(chord1.Point1, inter.intersect, chord2.Point2)); Arc oppArc2 = Arc.GetFigureMinorArc(circle, chord1.Point2, chord2.Point1); Angle oppAngle2 = Angle.AcquireFigureAngle(new Angle(chord1.Point2, inter.intersect, chord2.Point1)); // // Construct each of the 4 equations. // NumericValue two = new NumericValue(2); GeometricAngleArcEquation gaeq1 = new GeometricAngleArcEquation(new Multiplication(two, angle1), new Addition(arc1, oppArc1)); GeometricAngleArcEquation gaeq2 = new GeometricAngleArcEquation(new Multiplication(two, oppAngle1), new Addition(arc1, oppArc1)); GeometricAngleArcEquation gaeq3 = new GeometricAngleArcEquation(new Multiplication(two, angle2), new Addition(arc2, oppArc2)); GeometricAngleArcEquation gaeq4 = new GeometricAngleArcEquation(new Multiplication(two, oppAngle2), new Addition(arc2, oppArc2)); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(inter); antecedent.Add(circle); newGrounded.Add(new EdgeAggregator(antecedent, gaeq1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, gaeq2, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, gaeq3, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, gaeq4, annotation)); return newGrounded; }