Exemplo n.º 1
0
        //       A              D
        //      /\             /\
        //     /  \           /  \
        //    /    \         /    \
        //   /______\       /______\
        //  B        C      E       F
        //
        // In order for two triangles to be congruent, we require the following:
        //    Triangle(A, B, C), Triangle(D, E, F),
        //    Congruent(Angle(A, B, C), Angle(D, E, F)),
        //    Congruent(Angle(A, C, B), Angle(D, F, E)) -> Congruent(Angle(B, A, C), Angle(E, D, F)),
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.TWO_PAIRS_CONGRUENT_ANGLES_IMPLY_THIRD_PAIR_CONGRUENT;

            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // Do we have a segment or triangle?
            if (!(c is CongruentAngles) && !(c is Triangle))
            {
                return(newGrounded);
            }

            if (c is CongruentAngles)
            {
                CongruentAngles newCas = c as CongruentAngles;

                // Reflexive relationships will not relate two distinct triangles
                if (newCas.IsReflexive())
                {
                    return(newGrounded);
                }

                // Check all combinations of triangles to see if they have congruent pairs
                // 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 oldCas in candidateCongruent)
                        {
                            newGrounded.AddRange(CheckAndGenerateThirdCongruentPair(candidateTriangles[i], candidateTriangles[j], newCas, oldCas));
                        }
                    }
                }

                candidateCongruent.Add(newCas);
            }
            else if (c is Triangle)
            {
                Triangle newTri = c as Triangle;

                // Check all combinations of triangles to see if they have congruent pairs
                // This congruence must include the new segment congruence
                for (int i = 0; i < candidateCongruent.Count - 1; i++)
                {
                    for (int j = i + 1; j < candidateCongruent.Count; j++)
                    {
                        foreach (Triangle oldTri in candidateTriangles)
                        {
                            newGrounded.AddRange(CheckAndGenerateThirdCongruentPair(newTri, oldTri, candidateCongruent[i], candidateCongruent[j]));
                        }
                    }
                }

                candidateTriangles.Add(newTri);
            }

            return(newGrounded);
        }
Exemplo n.º 2
0
        //
        // Construct the AngleBisector if we have
        //
        //      V---------------A
        //     / \
        //    /   \
        //   /     \
        //  B       C
        //
        // Congruent(Angle, A, V, C), Angle(C, V, B)),  Segment(V, C)) -> AngleBisector(Angle(A, V, B)
        //
        //
        private static List <EdgeAggregator> InstantiateToDef(CongruentAngles cas, Segment segment)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // Find the shared segment between the two angles; we know it is valid if we reach this point
            Segment shared = cas.AreAdjacent();

            // The bisector must align with the given segment
            if (!segment.IsCollinearWith(shared))
            {
                return(newGrounded);
            }

            // We need a true bisector in which the shared vertex of the angles in between the endpoints of this segment
            if (!segment.PointLiesOnAndBetweenEndpoints(cas.ca1.GetVertex()))
            {
                return(newGrounded);
            }

            //
            // Create the overall angle which is being bisected
            //
            Point   vertex        = cas.ca1.GetVertex();
            Segment newRay1       = cas.ca1.OtherRayEquates(shared);
            Segment newRay2       = cas.ca2.OtherRayEquates(shared);
            Angle   combinedAngle = new Angle(newRay1.OtherPoint(vertex), vertex, newRay2.OtherPoint(vertex));

            // Determine if the segment is a straight angle (we don't want an angle bisector here, we would want a segment bisector)
            if (newRay1.IsCollinearWith(newRay2))
            {
                return(newGrounded);
            }

            // The bisector cannot be of the form:
            //    \
            //     \
            //      V---------------A
            //     /
            //    /
            //   B
            if (!combinedAngle.IsOnInteriorExplicitly(segment.Point1) && !combinedAngle.IsOnInteriorExplicitly(segment.Point2))
            {
                return(newGrounded);
            }

            AngleBisector newAB = new AngleBisector(combinedAngle, segment);

            // For hypergraph
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(segment);
            antecedent.Add(cas);

            newGrounded.Add(new EdgeAggregator(antecedent, newAB, annotation));
            return(newGrounded);
        }
        //
        // Just generate the new triangle
        //
        private static EdgeAggregator GenerateCongruentSides(Triangle tri, CongruentAngles cas)
        {
            GeometricCongruentSegments newConSegs = new GeometricCongruentSegments(tri.OtherSide(cas.ca1), tri.OtherSide(cas.ca2));

            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(cas);
            antecedent.Add(tri);

            return(new EdgeAggregator(antecedent, newConSegs, annotation));
        }
        //
        // AnglePairRelation(Angle(1), Angle(2)),
        // AnglePairRelation(Angle(3), Angle(4)),
        // Congruent(Angle(2), Angle(4)) -> Congruent(Angle(1), Angle(3))
        //                                  AnglePairRelation(Angle(1), Angle(4)),
        //                                  AnglePairRelation(Angle(2), Angle(3)),
        //
        //         |   /
        //         |1 /
        //         | / 2
        //         |/____________________
        //         |   /
        //         |3 /
        //         | / 4
        //         |/____________________
        //
        //
        // AnglePairRelation(Angle(1), Angle(2)),
        // AnglePairRelation(Angle(3), Angle(4)),
        // Congruent(Angle(2), Angle(4)) -> Congruent(Angle(1), Angle(3))
        //                                  AnglePairRelation(Angle(1), Angle(4)),
        //                                  AnglePairRelation(Angle(2), Angle(3)),
        //
        //                      /              /
        //                     /              /
        //                 1  /              /\ 2
        //       ____________/              /__\__________________
        //                      /              /
        //                     /              /
        //                 3  /              /\ 4
        //       ____________/              /__\__________________
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            compAnnotation.active = EngineUIBridge.JustificationSwitch.RELATIONS_OF_CONGRUENT_ANGLES_ARE_CONGRUENT;
            suppAnnotation.active = EngineUIBridge.JustificationSwitch.RELATIONS_OF_CONGRUENT_ANGLES_ARE_CONGRUENT;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (!(c is CongruentAngles) && !(c is AnglePairRelation))
            {
                return(newGrounded);
            }

            if (c is CongruentAngles)
            {
                CongruentAngles cas = c as CongruentAngles;

                // We are not interested in reflexive relationships implying congruences or any complementary or supplementary relations.
                if (cas.IsReflexive())
                {
                    return(newGrounded);
                }

                for (int i = 0; i < candRelation.Count - 1; i++)
                {
                    for (int j = i + 1; j < candRelation.Count; j++)
                    {
                        newGrounded.AddRange(IndirectRelations(cas, candRelation[i], candRelation[j]));
                    }
                }

                candCongruentAngles.Add(cas);
            }
            else if (c is AnglePairRelation)
            {
                AnglePairRelation newRelation = c as AnglePairRelation;

                foreach (AnglePairRelation relation in candRelation)
                {
                    newGrounded.AddRange(DirectRelations(relation, newRelation));

                    foreach (CongruentAngles cas in candCongruentAngles)
                    {
                        newGrounded.AddRange(IndirectRelations(cas, relation, newRelation));
                    }
                }

                candRelation.Add(newRelation);
            }

            return(newGrounded);
        }
Exemplo n.º 5
0
        //
        // Intersection(M, Segment(A,B), Segment(C, D)),
        // Intersection(N, Segment(A,B), Segment(E, F)),
        // Congruent(Angle(A, N, F), Angle(A, M, D)) -> Parallel(Segment(C, D), Segment(E, F))
        //
        //                                            B
        //                                           /
        //                              C-----------/-----------D
        //                                         / M
        //                                        /
        //                             E---------/-----------F
        //                                      / N
        //                                     A
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_CORRESPONDING_ANGLES_IMPLY_PARALLEL;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (!(c is CongruentAngles) && !(c is Intersection))
            {
                return(newGrounded);
            }

            if (c is CongruentAngles)
            {
                CongruentAngles conAngles = c as CongruentAngles;

                if (conAngles.IsReflexive())
                {
                    return(newGrounded);
                }

                // Find two candidate lines cut by the same transversal
                for (int i = 0; i < candIntersection.Count - 1; i++)
                {
                    for (int j = i + 1; j < candIntersection.Count; j++)
                    {
                        newGrounded.AddRange(CheckAndGenerateCorrespondingAnglesImplyParallel(candIntersection[i], candIntersection[j], conAngles));
                    }
                }

                candAngles.Add(conAngles);
            }
            else if (c is Intersection)
            {
                Intersection newIntersection = c as Intersection;

                // Find two candidate lines cut by the same transversal
                foreach (Intersection inter in candIntersection)
                {
                    foreach (CongruentAngles cas in candAngles)
                    {
                        newGrounded.AddRange(CheckAndGenerateCorrespondingAnglesImplyParallel(newIntersection, inter, cas));
                    }
                }

                candIntersection.Add(newIntersection);
            }

            return(newGrounded);
        }
        //
        // Intersection(M, Segment(A,B), Segment(C, D)),
        // Congruent(Angle(C, M, B), Angle(D, M, B)) -> Perpendicular(Segment(A, B), Segment(C, D))
        //
        //                                            B
        //                                           /
        //                              C-----------/-----------D
        //                                         / M
        //                                        /
        //                                       A
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_ADJACENT_ANGLES_IMPLY_PERPENDICULAR;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (c is CongruentAngles)
            {
                CongruentAngles conAngles = c as CongruentAngles;

                // We are interested in adjacent angles, not reflexive
                if (conAngles.IsReflexive())
                {
                    return(newGrounded);
                }

                // Any candidates congruent angles need to be adjacent to each other.
                if (conAngles.AreAdjacent() == null)
                {
                    return(newGrounded);
                }

                // Find two candidate lines cut by the same transversal
                foreach (Intersection inter in candIntersection)
                {
                    newGrounded.AddRange(CheckAndGenerateCongruentAdjacentImplyPerpendicular(inter, conAngles));
                }

                candAngles.Add(conAngles);
            }
            else if (c is Intersection)
            {
                Intersection newIntersection = c as Intersection;

                if (!newIntersection.IsStraightAngleIntersection())
                {
                    return(newGrounded);
                }

                foreach (CongruentAngles cas in candAngles)
                {
                    newGrounded.AddRange(CheckAndGenerateCongruentAdjacentImplyPerpendicular(newIntersection, cas));
                }

                candIntersection.Add(newIntersection);
            }

            return(newGrounded);
        }
Exemplo n.º 7
0
        //       A
        //      /\ 
        //     /  \
        //    /    \
        //   /______\
        //  B        C
        //
        // In order for two triangles to be Similar, we require the following:
        //    Triangle(A, B, C), Triangle(D, E, F),
        //    Congruent(Angle(B, C, A), Angle(E, F, D))
        //    Congruent(Angle(A, B, C), Angle(D, E, F)) -> Similar(Triangle(A, B, C), Triangle(D, E, F)),
        //                                                 Proportional(Segment(A, C), Angle(D, F)),
        //                                                 Proportional(Segment(A, B), Segment(D, E)),
        //                                                 Proportional(Segment(B, C), Segment(E, F))
        //                                                 Congruent(Angle(C, A, B), Angle(F, D, E)),
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause clause)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.AA_SIMILARITY;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (clause is CongruentAngles)
            {
                CongruentAngles newCas = clause as CongruentAngles;

                // 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 - 1; i++)
                {
                    for (int j = i + 1; j < candidateTriangles.Count; j++)
                    {
                        foreach (CongruentAngles oldCas in candidateAngles)
                        {
                            newGrounded.AddRange(InstantiateAASimilarity(candidateTriangles[i], candidateTriangles[j], oldCas, newCas));
                        }
                    }
                }

                candidateAngles.Add(newCas);
            }
            // 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;

                // Check all combinations of triangles to see if they are congruent
                // This congruence must include the new segment congruence
                foreach (Triangle oldTri in candidateTriangles)
                {
                    for (int m = 0; m < candidateAngles.Count - 1; m++)
                    {
                        for (int n = m + 1; n < candidateAngles.Count; n++)
                        {
                            newGrounded.AddRange(InstantiateAASimilarity(newTriangle, oldTri, candidateAngles[m], candidateAngles[n]));
                        }
                    }
                }

                candidateTriangles.Add(newTriangle);
            }

            return(newGrounded);
        }
Exemplo n.º 8
0
        private static List <EdgeAggregator> InstantiateCongruent(GroundedClause c)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (c is CongruentAngles)
            {
                CongruentAngles cas = c as CongruentAngles;

                // We are interested in adjacent angles, not reflexive
                if (cas.IsReflexive())
                {
                    return(newGrounded);
                }
                if (cas.AreAdjacent() == null)
                {
                    return(newGrounded);
                }

                //
                // The candidate must equates to a given segment; that is, find the proper segment
                // The segment must pass through the actual vertex of the adjacent angles
                //
                foreach (Segment segment in candidateSegments)
                {
                    newGrounded.AddRange(InstantiateToDef(cas, segment));
                }

                // Did not unify so add to the candidate list
                if (!newGrounded.Any())
                {
                    candidateCongruent.Add(cas);
                }
            }
            else if (c is Segment)
            {
                Segment segment = c as Segment;
                foreach (CongruentAngles cas in candidateCongruent)
                {
                    newGrounded.AddRange(InstantiateToDef(cas, segment));
                }

                candidateSegments.Add(segment);
            }

            return(newGrounded);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Figure out what possible angle combinations are before showing the window.
        /// </summary>
        protected override void OnShow()
        {
            options = new Dictionary <Angle, List <Angle> >();

            //Get a list of all congruent angle givens
            List <GroundedClause> cangs = new List <GroundedClause>();

            foreach (GroundedClause gc in currentGivens)
            {
                CongruentAngles cang = gc as CongruentAngles;
                if (cang != null)
                {
                    cangs.Add(cang);
                }
            }

            //Pick a first angle...
            foreach (Angle a1 in parser.backendParser.implied.angles)
            {
                List <Angle> possible = new List <Angle>();

                //... and see what other angles are viable second options.
                foreach (Angle a2 in parser.backendParser.implied.angles)
                {
                    if (a1.measure == a2.measure)
                    {
                        CongruentAngles cang = new CongruentAngles(a1, a2);

                        if (!a1.StructurallyEquals(a2) && !StructurallyContains(cangs, cang))
                        {
                            possible.Add(a2);
                        }
                    }
                }

                //If we found a possible list of combinations, add it to the dictionary
                if (possible.Count > 0)
                {
                    options.Add(a1, possible);
                }
            }

            //Set the options of the angle1 combo box
            angle1.ItemsSource = null; //Graphical refresh
            angle1.ItemsSource = options.Keys;
        }
Exemplo n.º 10
0
        //
        // Acquires all of the applicable congruent segments as well as congruent angles. Then checks for SAS
        //
        private static List <EdgeAggregator> CheckAndGenerateThirdCongruentPair(Triangle tri1, Triangle tri2, CongruentAngles cas1, CongruentAngles cas2)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // We have eliminated all reflexive relationships at this point

            // The congruent relations should not share any angles
            if (cas1.AngleShared(cas2) != null)
            {
                return(newGrounded);
            }

            // Both congruent pairs of angles must relate both triangles
            if (!cas1.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }
            if (!cas2.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }

            Angle firstAngleTri1  = tri1.AngleBelongs(cas1);
            Angle secondAngleTri1 = tri1.AngleBelongs(cas2);

            Angle firstAngleTri2  = tri2.AngleBelongs(cas1);
            Angle secondAngleTri2 = tri2.AngleBelongs(cas2);

            Angle thirdAngle1 = tri1.OtherAngle(firstAngleTri1, secondAngleTri1);
            Angle thirdAngle2 = tri2.OtherAngle(firstAngleTri2, secondAngleTri2);

            CongruentAngles newCas = new CongruentAngles(thirdAngle1, thirdAngle2);

            // Hypergraph
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(tri1);
            antecedent.Add(tri2);
            antecedent.Add(cas1);
            antecedent.Add(cas2);

            newGrounded.Add(new EdgeAggregator(antecedent, newCas, annotation));

            return(newGrounded);
        }
Exemplo n.º 11
0
        //
        // Implements 'transitivity' with right angles; that is, we may know two angles are congruent and if one is a right angle, the other is well
        //
        // Congruent(Angle(A, B, C), Angle(D, E, F), RightAngle(A, B, C) -> RightAngle(D, E, F)
        //
        public static List <EdgeAggregator> InstantiateToRightAngle(RightAngle ra, CongruentAngles cas, GroundedClause original)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // The congruent must have the given angle in order to generate
            if (!cas.HasAngle(ra))
            {
                return(newGrounded);
            }

            Angle        toBeRight     = cas.OtherAngle(ra);
            Strengthened newRightAngle = new Strengthened(toBeRight, new RightAngle(toBeRight));

            List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(original);

            antecedent.Add(cas);

            newGrounded.Add(new EdgeAggregator(antecedent, newRightAngle, transAnnotation));

            return(newGrounded);
        }
        private static List<EdgeAggregator> InstantiateToTheorem(GroundedClause clause)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            if (clause is Quadrilateral)
            {
                Quadrilateral quad = clause as Quadrilateral;

                if (!quad.IsStrictQuadrilateral()) return newGrounded;

                for (int i = 0; i < candidateCongruent.Count - 1; i++)
                {
                    for (int j = i + 1; j < candidateCongruent.Count; j++)
                    {
                            newGrounded.AddRange(InstantiateToTheorem(quad, candidateCongruent[i], candidateCongruent[j]));
                    }
                }

                candidateQuadrilateral.Add(quad);
            }
            else if (clause is CongruentAngles)
            {
                CongruentAngles newCas = clause as CongruentAngles;

                if (newCas.IsReflexive()) return newGrounded;

                foreach (Quadrilateral quad in candidateQuadrilateral)
                {
                    foreach (CongruentAngles oldCas in candidateCongruent)
                    {
                        newGrounded.AddRange(InstantiateToTheorem(quad, newCas, oldCas));
                    }
                }

                candidateCongruent.Add(newCas);
            }

            return newGrounded;
        }
        //
        // Supplementary(Angle(A, B, D), Angle(B, A, C))
        // Congruent(Angle(A, B, D), Angle(B, A, C)) -> RightAngle(Angle(A, B, D))
        //                                           -> RightAngle(Angle(B, A, C))
        //
        //                            C            D
        //                            |            |
        //                            |____________|
        //                            A            B
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_SUPPLEMENTARY_ANGLES_IMPLY_RIGHT_ANGLES;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (c is CongruentAngles)
            {
                CongruentAngles conAngles = c as CongruentAngles;

                // We are interested in adjacent angles, not reflexive
                if (conAngles.IsReflexive())
                {
                    return(newGrounded);
                }

                foreach (Supplementary suppAngles in candSupplementary)
                {
                    newGrounded.AddRange(CheckAndGenerateSupplementaryCongruentImplyRightAngles(suppAngles, conAngles));
                }

                candCongruent.Add(conAngles);
            }
            else if (c is Supplementary)
            {
                Supplementary supplementary = c as Supplementary;

                foreach (CongruentAngles cc in candCongruent)
                {
                    newGrounded.AddRange(CheckAndGenerateSupplementaryCongruentImplyRightAngles(supplementary, cc));
                }

                candSupplementary.Add(supplementary);
            }

            return(newGrounded);
        }
        private static List<EdgeAggregator> InstantiateToTheorem(Quadrilateral quad, CongruentAngles cas1, CongruentAngles cas2)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // Are the pairs on the opposite side of this quadrilateral?
            if (!quad.HasOppositeCongruentAngles(cas1)) return newGrounded;
            if (!quad.HasOppositeCongruentAngles(cas2)) return newGrounded;

            //
            // Create the new Rhombus object
            //
            Strengthened newParallelogram = new Strengthened(quad, new Parallelogram(quad));

            // For hypergraph
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(quad);
            antecedent.Add(cas1);
            antecedent.Add(cas2);

            newGrounded.Add(new EdgeAggregator(antecedent, newParallelogram, annotation));

            return newGrounded;
        }
Exemplo n.º 15
0
        //
        // All right angles are supplementary.
        //
        public static List <EdgeAggregator> InstantiateToSupplementary(CongruentAngles cas)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (cas.IsReflexive())
            {
                return(newGrounded);
            }

            if (!(cas.ca1 is RightAngle) || !(cas.ca2 is RightAngle))
            {
                return(newGrounded);
            }

            Supplementary supp = new Supplementary(cas.ca1, cas.ca2);

            supp.SetNotASourceNode();
            supp.SetNotAGoalNode();
            supp.SetClearDefinition();

            newGrounded.Add(new EdgeAggregator(Utilities.MakeList <GroundedClause>(cas), supp, annotation));

            return(newGrounded);
        }
        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);
        }
        //
        //       A
        //      / \
        //     B---C
        //
        // Triangle(A, B, C), Congruent(\angle ABC, \angle ACB) -> Congruent(Segment(A, B), Segment(A, C))
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_ANGLES_IN_TRIANGLE_IMPLY_CONGRUENT_SIDES;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (!MayUnifyWith(c))
            {
                return(newGrounded);
            }

            //
            // Unify
            //
            if (c is CongruentAngles)
            {
                CongruentAngles cas = c as CongruentAngles;

                // Only generate or add to possible congruent pairs if this is a non-reflexive relation
                if (!cas.IsReflexive())
                {
                    for (int t = 0; t < candTris.Count; t++)
                    {
                        if (candTris[t].HasAngle(cas.ca1) && candTris[t].HasAngle(cas.ca2))
                        {
                            newGrounded.Add(GenerateCongruentSides(candTris[t], cas));

                            // There should be only one possible Isosceles triangle from this congruent angles
                            // So we can remove this relationship and triangle from consideration
                            candTris.RemoveAt(t);

                            return(newGrounded);
                        }
                    }

                    candAngs.Add(cas);
                }

                return(new List <EdgeAggregator>());
            }

            else if (c is Triangle)
            {
                Triangle newTriangle = c as Triangle;

                //
                // Do any of the congruent segment pairs merit calling this new triangle isosceles?
                //
                for (int ca = 0; ca < candAngs.Count; ca++)
                {
                    // No need to check for this, in theory, since we never add any reflexive expressions to the list
                    if (!candAngs[ca].IsReflexive())
                    {
                        if (newTriangle.HasAngle(candAngs[ca].ca1) && newTriangle.HasAngle(candAngs[ca].ca2))
                        {
                            newGrounded.Add(GenerateCongruentSides(newTriangle, candAngs[ca]));

                            return(newGrounded);
                        }
                    }
                }

                // Add the the list of candidates if it was not determined isosceles now.
                candTris.Add(newTriangle);
            }

            return(newGrounded);
        }
        //               A
        //              /)
        //             /  )
        //            /    )
        // center:   O      )
        //            \    )
        //             \  )
        //              \)
        //               C
        //
        //               D
        //              /)
        //             /  )
        //            /    )
        // center:   Q      )
        //            \    )
        //             \  )
        //              \)
        //               F
        //
        // Congruent(Angle(AOC), Angle(DQF)) -> Congruent(Arc(A, C), Arc(D, F))
        //
        private static List <EdgeAggregator> InstantiateForwardPartOfTheorem(CongruentAngles cas)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            //
            // Determine if the angles are central angles.
            //
            List <Circle> circles1 = Circle.IsCentralAngle(cas.ca1);

            //Circle circle1 = null;  Circle.IsCentralAngle(cas.ca1);
            if (!circles1.Any())
            {
                return(newGrounded);
            }

            List <Circle> circles2 = Circle.IsCentralAngle(cas.ca2);

            //Circle circle2 = null;  Circle.IsCentralAngle(cas.ca2);
            if (!circles2.Any())
            {
                return(newGrounded);
            }

            //Construct arc congruences between congruent circles
            foreach (Circle c1 in circles1)
            {
                foreach (Circle c2 in circles2)
                {
                    if (c1.radius == c2.radius)
                    {
                        Arc a1 = Arc.GetInterceptedArc(c1, cas.ca1);
                        Arc a2 = Arc.GetInterceptedArc(c2, cas.ca2);
                        if (a1 != null & a2 != null)
                        {
                            GeometricCongruentArcs gcas = new GeometricCongruentArcs(a1, a2);

                            // For hypergraph
                            List <GroundedClause> antecedent = new List <GroundedClause>();
                            antecedent.Add(a1);
                            antecedent.Add(a2);
                            antecedent.Add(cas);

                            newGrounded.Add(new EdgeAggregator(antecedent, gcas, forwardAnnotation));
                        }
                    }
                }
            }
            //
            // Construct the arc congruence by acquiring the arc endpoints.
            //
            //Point endpt11, endpt12, garbage;
            //circle1.FindIntersection(cas.ca1.ray1, out endpt11, out garbage);
            //if (endpt11 == null) return newGrounded;

            //circle1.FindIntersection(cas.ca1.ray2, out endpt12, out garbage);
            //if (endpt12 == null) return newGrounded;

            //Point endpt21, endpt22;
            //circle1.FindIntersection(cas.ca2.ray1, out endpt21, out garbage);
            //if (endpt21 == null) return newGrounded;

            //circle1.FindIntersection(cas.ca2.ray2, out endpt22, out garbage);
            //if (endpt22 == null) return newGrounded;

            //Arc arc1 = Arc.GetFigureMinorArc(circle1, endpt11, endpt12);
            //Arc arc2 = Arc.GetFigureMinorArc(circle2, endpt21, endpt22);
            //if (arc1 == null || arc2 == null) return newGrounded;


            return(newGrounded);
        }
Exemplo n.º 19
0
        //
        // 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);
        }
Exemplo n.º 20
0
        //
        //
        //
        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);
        }
Exemplo n.º 21
0
        //
        // Checks for SAS given the 5 values
        //
        private static List <EdgeAggregator> InstantiateSAS(Triangle tri1, Triangle tri2, CongruentSegments css1, CongruentSegments css2, CongruentAngles cas)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            //
            // All congruence pairs must minimally relate the triangles
            //
            if (!css1.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }
            if (!css2.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }
            if (!cas.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }

            // Is this angle an 'extension' of the actual triangle angle? If so, acquire the normalized version of
            // the angle, using only the triangle vertices to represent the angle
            Angle angleTri1 = tri1.NormalizeAngle(tri1.AngleBelongs(cas));
            Angle angleTri2 = tri2.NormalizeAngle(tri2.AngleBelongs(cas));

            Segment seg1Tri1 = tri1.GetSegment(css1);
            Segment seg1Tri2 = tri2.GetSegment(css1);

            Segment seg2Tri1 = tri1.GetSegment(css2);
            Segment seg2Tri2 = tri2.GetSegment(css2);

            if (!angleTri1.IsIncludedAngle(seg1Tri1, seg2Tri1) || !angleTri2.IsIncludedAngle(seg1Tri2, seg2Tri2))
            {
                return(newGrounded);
            }

            //
            // Construct the corrsesponding points between the triangles
            //
            List <Point> triangleOne = new List <Point>();
            List <Point> triangleTwo = new List <Point>();

            triangleOne.Add(angleTri1.GetVertex());
            triangleTwo.Add(angleTri2.GetVertex());

            triangleOne.Add(seg1Tri1.OtherPoint(angleTri1.GetVertex()));
            triangleTwo.Add(seg1Tri2.OtherPoint(angleTri2.GetVertex()));

            triangleOne.Add(seg2Tri1.OtherPoint(angleTri1.GetVertex()));
            triangleTwo.Add(seg2Tri2.OtherPoint(angleTri2.GetVertex()));

            //
            // Construct the new clauses: congruent triangles and CPCTC
            //
            GeometricCongruentTriangles gcts = new GeometricCongruentTriangles(new Triangle(triangleOne), new Triangle(triangleTwo));

            // Hypergraph
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(tri1);
            antecedent.Add(tri2);
            antecedent.Add(css1);
            antecedent.Add(css2);
            antecedent.Add(cas);

            newGrounded.Add(new EdgeAggregator(antecedent, gcts, annotation));

            // Add all the corresponding parts as new congruent clauses
            newGrounded.AddRange(CongruentTriangles.GenerateCPCTC(gcts, triangleOne, triangleTwo));

            return(newGrounded);
        }
        private static List <EdgeAggregator> IndirectRelations(CongruentAngles cas, AnglePairRelation relation1, AnglePairRelation relation2)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            // Do we have the same type of relation?
            if (relation1.GetType() != relation2.GetType())
            {
                return(newGrounded);
            }

            //
            // Determine the shared values amongst the relations
            //
            Angle shared1 = relation1.AngleShared(cas);

            if (shared1 == null)
            {
                return(newGrounded);
            }

            Angle shared2 = cas.OtherAngle(shared1);

            if (!relation2.HasAngle(shared2))
            {
                return(newGrounded);
            }

            Angle otherAngle1 = relation1.OtherAngle(shared1);
            Angle otherAngle2 = relation2.OtherAngle(shared2);

            // Avoid generating a reflexive relationship
            if (otherAngle1.Equates(otherAngle2))
            {
                return(newGrounded);
            }

            //
            // Congruent(Angle(1), Angle(3))
            //
            // The other two angles from the relation pairs are then congruent
            GeometricCongruentAngles gcas = new GeometricCongruentAngles(otherAngle1, otherAngle2);

            // Avoid direct cyclic congruent angle generation
            if (cas.StructurallyEquals(gcas))
            {
                return(newGrounded);
            }

            // Construct hyperedge
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(cas);
            antecedent.Add(relation1);
            antecedent.Add(relation2);

            //
            // AnglePairRelation(Angle(1), Angle(4)),
            // AnglePairRelation(Angle(2), Angle(3)),
            //
            if (relation1 is Complementary && relation2 is Complementary)
            {
                Complementary comp1 = new Complementary(shared1, otherAngle2);
                Complementary comp2 = new Complementary(shared2, otherAngle1);

                newGrounded.Add(new EdgeAggregator(antecedent, comp1, compAnnotation));
                newGrounded.Add(new EdgeAggregator(antecedent, comp2, compAnnotation));
            }
            else if (relation1 is Supplementary && relation2 is Supplementary)
            {
                Supplementary supp1 = new Supplementary(shared1, otherAngle2);
                Supplementary supp2 = new Supplementary(shared2, otherAngle1);

                newGrounded.Add(new EdgeAggregator(antecedent, supp1, suppAnnotation));
                newGrounded.Add(new EdgeAggregator(antecedent, supp2, suppAnnotation));
            }
            else
            {
                throw new ArgumentException("RelationsOfCongruent:: Expected a supplementary or complementary angle, not " + relation1.GetType());
            }

            newGrounded.Add(new EdgeAggregator(antecedent, gcas, relation1 is Complementary ? compAnnotation : suppAnnotation));

            return(newGrounded);
        }
        private static List <EdgeAggregator> CheckAndGenerateSupplementaryCongruentImplyRightAngles(Supplementary supplementary, CongruentAngles conAngles)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            //The given pairs must contain the same angles (i.e., the angles must be both supplementary AND congruent)
            if (!((supplementary.angle1.Equals(conAngles.ca1) && supplementary.angle2.Equals(conAngles.ca2)) ||
                  (supplementary.angle2.Equals(conAngles.ca1) && supplementary.angle1.Equals(conAngles.ca2))))
            {
                return(newGrounded);
            }
            //if (!(supplementary.StructurallyEquals(conAngles))) return newGrounded;

            //
            // Now we have two supplementary and congruent angles, which must be right angles
            //
            Strengthened streng  = new Strengthened(supplementary.angle1, new RightAngle(supplementary.angle1));
            Strengthened streng2 = new Strengthened(supplementary.angle2, new RightAngle(supplementary.angle2));

            // Construct hyperedges
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(supplementary);
            antecedent.Add(conAngles);

            newGrounded.Add(new EdgeAggregator(antecedent, streng, annotation));
            newGrounded.Add(new EdgeAggregator(antecedent, streng2, annotation));

            return(newGrounded);
        }
Exemplo n.º 24
0
        //
        // Checks for AA given the 4 values
        //
        private static List <EdgeAggregator> InstantiateAASimilarity(Triangle tri1, Triangle tri2, CongruentAngles cas1, CongruentAngles cas2)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            //
            // All congruence pairs must minimally relate the triangles
            //
            if (!cas1.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }
            if (!cas2.LinksTriangles(tri1, tri2))
            {
                return(newGrounded);
            }

            // Is this angle an 'extension' of the actual triangle angle? If so, acquire the normalized version of
            // the angle, using only the triangle vertices to represent the angle
            Angle angle1Tri1 = tri1.NormalizeAngle(tri1.AngleBelongs(cas1));
            Angle angle1Tri2 = tri2.NormalizeAngle(tri2.AngleBelongs(cas1));

            Angle angle2Tri1 = tri1.NormalizeAngle(tri1.AngleBelongs(cas2));
            Angle angle2Tri2 = tri2.NormalizeAngle(tri2.AngleBelongs(cas2));

            // The angles for each triangle must be distinct
            if (angle1Tri1.Equals(angle2Tri1) || angle1Tri2.Equals(angle2Tri2))
            {
                return(newGrounded);
            }

            //
            // Construct the corrsesponding points between the triangles
            //
            List <Point> triangleOne = new List <Point>();
            List <Point> triangleTwo = new List <Point>();

            triangleOne.Add(angle1Tri1.GetVertex());
            triangleTwo.Add(angle1Tri2.GetVertex());

            triangleOne.Add(angle2Tri1.GetVertex());
            triangleTwo.Add(angle2Tri2.GetVertex());

            // We know the segment endpoint mappings above, now acquire the opposite point
            triangleOne.Add(tri1.OtherPoint(new Segment(angle1Tri1.GetVertex(), angle2Tri1.GetVertex())));
            triangleTwo.Add(tri2.OtherPoint(new Segment(angle1Tri2.GetVertex(), angle2Tri2.GetVertex())));

            //
            // Construct the new clauses: similar triangles and resultant components
            //
            GeometricSimilarTriangles simTris = new GeometricSimilarTriangles(new Triangle(triangleOne), new Triangle(triangleTwo));

            // Hypergraph edge
            List <GroundedClause> antecedent = new List <GroundedClause>();

            antecedent.Add(tri1);
            antecedent.Add(tri2);
            antecedent.Add(cas1);
            antecedent.Add(cas2);

            newGrounded.Add(new EdgeAggregator(antecedent, simTris, annotation));

            // Add all the corresponding parts as new Similar clauses
            newGrounded.AddRange(SimilarTriangles.GenerateComponents(simTris, triangleOne, triangleTwo));

            return(newGrounded);
        }
Exemplo n.º 25
0
        public static List <EdgeAggregator> InstantiateToRightAngle(GroundedClause clause)
        {
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (clause is AngleEquation)
            {
                AngleEquation eq = clause as AngleEquation;
                //Filter for acceptable equations - both sides atomic
                int atomicity = eq.GetAtomicity();
                if (atomicity != Equation.BOTH_ATOMIC)
                {
                    return(newGrounded);
                }

                //Check that the terms equate an angle to a measure
                List <GroundedClause> lhs = eq.lhs.CollectTerms();
                List <GroundedClause> rhs = eq.rhs.CollectTerms();

                Angle        angle = null;
                NumericValue value = null;
                if (lhs[0] is Angle && rhs[0] is NumericValue)
                {
                    angle = lhs[0] as Angle;
                    value = rhs[0] as NumericValue;
                }
                else if (rhs[0] is Angle && lhs[0] is NumericValue)
                {
                    angle = rhs[0] as Angle;
                    value = lhs[0] as NumericValue;
                }
                else
                {
                    return(newGrounded);
                }

                //Verify that the angle is a right angle
                if (!Utilities.CompareValues(value.DoubleValue, 90.0))
                {
                    return(newGrounded);
                }

                Strengthened newRightAngle = new Strengthened(angle, new RightAngle(angle));

                List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(clause);

                newGrounded.Add(new EdgeAggregator(antecedent, newRightAngle, defAnnotation));

                return(newGrounded);
            }
            else if (clause is CongruentAngles)
            {
                CongruentAngles cas = clause as CongruentAngles;

                // Not interested in reflexive relationships in this case
                if (cas.IsReflexive())
                {
                    return(newGrounded);
                }

                foreach (RightAngle ra in candidateRightAngles)
                {
                    newGrounded.AddRange(InstantiateToRightAngle(ra, cas, ra));
                }

                foreach (Strengthened streng in candidateStrengthened)
                {
                    newGrounded.AddRange(InstantiateToRightAngle(streng.strengthened as RightAngle, cas, streng));
                }

                candidateCongruentAngles.Add(clause as CongruentAngles);
            }
            else if (clause is RightAngle)
            {
                RightAngle ra = clause as RightAngle;

                foreach (CongruentAngles oldCas in candidateCongruentAngles)
                {
                    newGrounded.AddRange(InstantiateToRightAngle(ra, oldCas, ra));
                }

                candidateRightAngles.Add(ra);
            }
            else if (clause is Strengthened)
            {
                Strengthened streng = clause as Strengthened;

                // Only intrerested in right angles
                if (!(streng.strengthened is RightAngle))
                {
                    return(newGrounded);
                }

                foreach (CongruentAngles oldCas in candidateCongruentAngles)
                {
                    newGrounded.AddRange(InstantiateToRightAngle(streng.strengthened as RightAngle, oldCas, streng));
                }

                candidateStrengthened.Add(streng);
            }

            return(newGrounded);
        }
Exemplo n.º 26
0
        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);
        }
Exemplo n.º 27
0
        //       A
        //      /\ 
        //     /  \
        //    /    \
        //   /______\
        //  B        C
        //
        // In order for two triangles to be congruent, we require the following:
        //    Triangle(A, B, C), Triangle(D, E, F),
        //    Congruent(Angle(A, B, C), Angle(D, E, F)),
        //    Congruent(Segment(B, C), Segment(E, F)),
        //    Congruent(Angle(A, C, B), Angle(D, F, E)) -> Congruent(Triangle(A, B, C), Triangle(D, E, F)),
        //                                                 Congruent(Segment(A, B), Angle(D, E)),
        //                                                 Congruent(Segment(A, C), Angle(D, F)),
        //                                                 Congruent(Angle(B, A, C), Angle(E, D, F)),
        //
        public static List <EdgeAggregator> Instantiate(GroundedClause clause)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.ASA;

            // The list of new grounded clauses if they are deduced
            List <EdgeAggregator> newGrounded = new List <EdgeAggregator>();

            if (clause is CongruentSegments)
            {
                CongruentSegments newCss = clause as CongruentSegments;

                // 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 - 1; i++)
                {
                    for (int j = i + 1; j < candidateTriangles.Count; j++)
                    {
                        for (int m = 0; m < candidateAngles.Count - 1; m++)
                        {
                            for (int n = m + 1; n < candidateAngles.Count; n++)
                            {
                                newGrounded.AddRange(InstantiateASA(candidateTriangles[i], candidateTriangles[j], candidateAngles[m], candidateAngles[n], newCss));
                            }
                        }
                    }
                }

                // Add this segment to the list of possible clauses to unify later
                candidateSegments.Add(newCss);
            }
            else if (clause is CongruentAngles)
            {
                CongruentAngles newCas = clause as CongruentAngles;

                // Except for reflexive congruent triangle (a triangle and itself), reflexive angles cannot lead to congruency
                if (newCas.IsReflexive())
                {
                    return(newGrounded);
                }

                // 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 - 1; i++)
                {
                    for (int j = i + 1; j < candidateTriangles.Count; j++)
                    {
                        foreach (CongruentSegments css in candidateSegments)
                        {
                            foreach (CongruentAngles oldCas in candidateAngles)
                            {
                                newGrounded.AddRange(InstantiateASA(candidateTriangles[i], candidateTriangles[j], oldCas, newCas, css));
                            }
                        }
                    }
                }

                candidateAngles.Add(newCas);
            }
            // 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;

                // Check all combinations of triangles to see if they are congruent
                // This congruence must include the new segment congruence
                foreach (Triangle oldTri in candidateTriangles)
                {
                    for (int m = 0; m < candidateAngles.Count - 1; m++)
                    {
                        for (int n = m + 1; n < candidateAngles.Count; n++)
                        {
                            foreach (CongruentSegments css in candidateSegments)
                            {
                                newGrounded.AddRange(InstantiateASA(newTriangle, oldTri, candidateAngles[m], candidateAngles[n], css));
                            }
                        }
                    }
                }

                candidateTriangles.Add(newTriangle);
            }

            return(newGrounded);
        }