private static bool HandleRatioEquation(KnownMeasurementsAggregator known, SegmentRatioEquation theEq) { double topLeft = known.GetSegmentLength(theEq.lhs.smallerSegment); double bottomLeft = known.GetSegmentLength(theEq.lhs.largerSegment); double topRight = known.GetSegmentLength(theEq.rhs.smallerSegment); double bottomRight = known.GetSegmentLength(theEq.rhs.largerSegment); int unknown = 0; if (topLeft <= 0) { unknown++; } if (bottomLeft <= 0) { unknown++; } if (topRight <= 0) { unknown++; } if (bottomRight <= 0) { unknown++; } if (unknown != 1) { return(false); } if (topLeft <= 0) { return(known.AddSegmentLength(theEq.lhs.smallerSegment, (topRight / bottomRight) * bottomLeft)); } else if (bottomLeft <= 0) { return(known.AddSegmentLength(theEq.lhs.largerSegment, topLeft * (bottomRight / topRight))); } else if (topRight <= 0) { return(known.AddSegmentLength(theEq.rhs.smallerSegment, (topLeft / bottomLeft) * bottomRight)); } else if (bottomRight <= 0) { return(known.AddSegmentLength(theEq.rhs.largerSegment, topRight * (bottomLeft / topLeft))); } else { return(false); } }
// // In order for two triangles to be congruent, we require the following: // Triangle(A, B, C), Triangle(D, E, F), // SegmentRatio(Segment(A, B), Segment(D, E)), // SegmentRatio(Segment(A, C), Segment(D, F)), // SegmentRatio(Segment(B, C), Segment(E, F)) -> Congruent(Triangle(A, B, C), Triangle(D, E, F)), // Congruent(Angles(A, B, C), Angle(D, E, F)), // Congruent(Angles(C, A, B), Angle(F, D, E)), // Congruent(Angles(B, C, A), Angle(E, F, D)), // // Note: we need to figure out the proper order of the sides to guarantee congruence // public static List <EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.SSS_SIMILARITY; // The list of new grounded clauses if they are deduced List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); // If this is a new segment, check for congruent triangles with this new piece of information if (clause is SegmentRatioEquation) { SegmentRatioEquation newEq = clause as SegmentRatioEquation; // Check all combinations of triangles to see if they are congruent // This congruence must include the new segment congruence for (int i = 0; i < candidateTriangles.Count; i++) { for (int j = i + 1; j < candidateTriangles.Count; j++) { foreach (SegmentRatioEquation oldEq in candidateSegmentEquations) { newGrounded.AddRange(CheckForSSS(candidateTriangles[i], candidateTriangles[j], newEq, oldEq)); } } } // Add this segment to the list of possible clauses to unify later candidateSegmentEquations.Add(newEq); } // If this is a new triangle, check for triangles which may be congruent to this new triangle else if (clause is Triangle) { Triangle newTriangle = clause as Triangle; foreach (Triangle oldTriangle in candidateTriangles) { for (int m = 0; m < candidateSegmentEquations.Count - 1; m++) { for (int n = m + 1; n < candidateSegmentEquations.Count; n++) { newGrounded.AddRange(CheckForSSS(newTriangle, oldTriangle, candidateSegmentEquations[m], candidateSegmentEquations[n])); } } } // Add this triangle to the list of possible clauses to unify later candidateTriangles.Add(newTriangle); } return(newGrounded); }
// // In order for two triangles to be Similar, we require the following: // Triangle(A, B, C), Triangle(D, E, F), // Proportional(Segment(A, B), Segment(D, E)), // Congruent(Angle(A, B, C), Angle(D, E, F)), // Proportional(Segment(B, C), Segment(E, F)) -> Similar(Triangle(A, B, C), Triangle(D, E, F)), // Proportional(Segment(A, C), Angle(D, F)), // Congruent(Angle(C, A, B), Angle(F, D, E)), // Congruent(Angle(B, C, A), Angle(E, F, D)) // // Note: we need to figure out the proper order of the sides to guarantee similarity // public static List <EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.SAS_SIMILARITY; // The list of new grounded clauses if they are deduced List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); // If this is a new segment, check for Similar triangles with this new piece of information if (clause is SegmentRatioEquation) { SegmentRatioEquation newProp = clause as SegmentRatioEquation; // Check all combinations of triangles to see if they are Similar // This congruence must include the new segment congruence for (int i = 0; i < candidateTriangles.Count - 1; i++) { for (int j = i + 1; j < candidateTriangles.Count; j++) { foreach (CongruentAngles cas in candidateCongruentAngles) { newGrounded.AddRange(CollectAndCheckSAS(candidateTriangles[i], candidateTriangles[j], cas, newProp)); } } } // Add this segment to the list of possible clauses to unify later candidatePropSegmentEquations.Add(newProp); } else if (clause is CongruentAngles) { CongruentAngles newCas = clause as CongruentAngles; // Check all combinations of triangles to see if they are Similar // This congruence must include the new segment congruence for (int i = 0; i < candidateTriangles.Count - 1; i++) { for (int j = i + 1; j < candidateTriangles.Count; j++) { foreach (SegmentRatioEquation eq in candidatePropSegmentEquations) { newGrounded.AddRange(CollectAndCheckSAS(candidateTriangles[i], candidateTriangles[j], newCas, eq)); } } } // Add this segment to the list of possible clauses to unify later candidateCongruentAngles.Add(newCas); } // If this is a new triangle, check for triangles which may be Similar to this new triangle else if (clause is Triangle) { Triangle newTriangle = clause as Triangle; foreach (Triangle oldTriangle in candidateTriangles) { foreach (CongruentAngles cas in candidateCongruentAngles) { foreach (SegmentRatioEquation eq in candidatePropSegmentEquations) { newGrounded.AddRange(CollectAndCheckSAS(newTriangle, oldTriangle, cas, eq)); } } } // Add this triangle to the list of possible clauses to unify later candidateTriangles.Add(newTriangle); } return(newGrounded); }
// // // private static List <EdgeAggregator> CollectAndCheckSAS(Triangle ct1, Triangle ct2, CongruentAngles cas, SegmentRatioEquation sre) { List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); // Proportions must actually equate //if (!pss1.ProportionallyEquals(pss2)) return newGrounded; //// The smaller and larger segments of the proportionality must be distinct, respectively. //if (!pss1.IsDistinctFrom(pss2)) return newGrounded; // The proportional relationships need to link the given triangles if (!cas.LinksTriangles(ct1, ct2)) { return(newGrounded); } if (!sre.LinksTriangles(ct1, ct2)) { return(newGrounded); } //if (!pss1.LinksTriangles(ct1, ct2)) return newGrounded; //if (!pss2.LinksTriangles(ct1, ct2)) return newGrounded; // The smaller segments must belong to one triangle, same for larger segments. //if (!(ct1.HasSegment(pss1.smallerSegment) && ct1.HasSegment(pss2.smallerSegment) && // ct2.HasSegment(pss1.largerSegment) && ct2.HasSegment(pss2.largerSegment)) && // !(ct2.HasSegment(pss1.smallerSegment) && ct2.HasSegment(pss2.smallerSegment) && // ct1.HasSegment(pss1.largerSegment) && ct1.HasSegment(pss2.largerSegment))) // return newGrounded; KeyValuePair <Segment, Segment> segsTri1 = sre.GetSegments(ct1); KeyValuePair <Segment, Segment> segsTri2 = sre.GetSegments(ct2); //Segment seg1Tri1 = ct1.GetSegment(pss1); //Segment seg2Tri1 = ct1.GetSegment(pss2); //Segment seg1Tri2 = ct2.GetSegment(pss1); //Segment seg2Tri2 = ct2.GetSegment(pss2); // Avoid redundant segments, if they arise if (segsTri1.Key.StructurallyEquals(segsTri1.Value)) { return(newGrounded); } if (segsTri2.Key.StructurallyEquals(segsTri2.Value)) { return(newGrounded); } //if (seg1Tri1.StructurallyEquals(seg2Tri1)) return newGrounded; //if (seg1Tri2.StructurallyEquals(seg2Tri2)) return newGrounded; Angle angleTri1 = ct1.AngleBelongs(cas); Angle angleTri2 = ct2.AngleBelongs(cas); // Check both triangles if this is the included angle; if it is, we have SAS if (!angleTri1.IsIncludedAngle(segsTri1.Key, segsTri1.Value)) { return(newGrounded); } if (!angleTri2.IsIncludedAngle(segsTri2.Key, segsTri2.Value)) { return(newGrounded); } // // Generate Similar Triangles // Point vertex1 = angleTri1.GetVertex(); Point vertex2 = angleTri2.GetVertex(); // Construct a list of pairs to return; this is the correspondence from triangle 1 to triangle 2 List <KeyValuePair <Point, Point> > pairs = new List <KeyValuePair <Point, Point> >(); // The vertices of the angles correspond pairs.Add(new KeyValuePair <Point, Point>(vertex1, vertex2)); // For the segments, look at the congruences and select accordingly pairs.Add(new KeyValuePair <Point, Point>(segsTri1.Key.OtherPoint(vertex1), segsTri2.Key.OtherPoint(vertex2))); pairs.Add(new KeyValuePair <Point, Point>(segsTri1.Value.OtherPoint(vertex1), segsTri2.Value.OtherPoint(vertex2))); List <GroundedClause> simTriAntecedent = new List <GroundedClause>(); simTriAntecedent.Add(ct1); simTriAntecedent.Add(ct2); simTriAntecedent.Add(cas); simTriAntecedent.Add(sre); newGrounded.AddRange(GenerateCorrespondingParts(pairs, simTriAntecedent, annotation)); return(newGrounded); }
// // Of all the congruent segment pairs, choose a subset of 3. Exhaustively check all; if they work, return the set. // private static List <EdgeAggregator> CheckForSSS(Triangle ct1, Triangle ct2, SegmentRatioEquation sre1, SegmentRatioEquation sre2) { List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); // // The proportional relationships need to link the given triangles // if (!sre1.LinksTriangles(ct1, ct2)) { return(newGrounded); } if (!sre2.LinksTriangles(ct1, ct2)) { return(newGrounded); } // // Both equations must share a fraction (ratio) // if (!sre1.SharesRatio(sre2)) { return(newGrounded); } // // Collect all of the applicable segments // SegmentRatio shared = sre1.GetSharedRatio(sre2); SegmentRatio other1 = sre1.GetOtherRatio(shared); SegmentRatio other2 = sre2.GetOtherRatio(shared); Segment seg1Tri1 = ct1.GetSegment(shared); Segment seg2Tri1 = ct1.GetSegment(other1); Segment seg3Tri1 = ct1.GetSegment(other2); if (seg1Tri1 == null || seg2Tri1 == null || seg3Tri1 == null) { return(newGrounded); } Segment seg1Tri2 = ct2.GetSegment(shared); Segment seg2Tri2 = ct2.GetSegment(other1); Segment seg3Tri2 = ct2.GetSegment(other2); if (seg1Tri2 == null || seg2Tri2 == null || seg3Tri2 == null) { return(newGrounded); } // Avoid redundant segments, if they arise if (seg1Tri1.StructurallyEquals(seg2Tri1) || seg1Tri1.StructurallyEquals(seg3Tri1) || seg2Tri1.StructurallyEquals(seg3Tri1)) { return(newGrounded); } if (seg1Tri2.StructurallyEquals(seg2Tri2) || seg1Tri2.StructurallyEquals(seg3Tri2) || seg2Tri2.StructurallyEquals(seg3Tri2)) { return(newGrounded); } // // Collect the corresponding points // List <KeyValuePair <Point, Point> > pointPairs = new List <KeyValuePair <Point, Point> >(); pointPairs.Add(new KeyValuePair <Point, Point>(seg1Tri1.SharedVertex(seg2Tri1), seg1Tri2.SharedVertex(seg2Tri2))); pointPairs.Add(new KeyValuePair <Point, Point>(seg1Tri1.SharedVertex(seg3Tri1), seg1Tri2.SharedVertex(seg3Tri2))); pointPairs.Add(new KeyValuePair <Point, Point>(seg2Tri1.SharedVertex(seg3Tri1), seg2Tri2.SharedVertex(seg3Tri2))); List <GroundedClause> simTriAntecedent = new List <GroundedClause>(); simTriAntecedent.Add(ct1); simTriAntecedent.Add(ct2); simTriAntecedent.Add(sre1); simTriAntecedent.Add(sre2); newGrounded.AddRange(SASSimilarity.GenerateCorrespondingParts(pointPairs, simTriAntecedent, annotation)); return(newGrounded); }