Example #1
0
        //
        // Since we are cutting segments into sections, there is a direct relationship between the split side lengths for each side.
        //
        protected void GetGranularMidpointEquations(out List <Equation> eqs, out List <Congruent> congs)
        {
            eqs   = new List <Equation>();
            congs = new List <Congruent>();

            //
            // Each sub-segment is equal to each other on each side.
            //
            for (int side = 0; side < sideSubsegments.Length; side++)
            {
                for (int s1 = 0; s1 < sideSubsegments[side].Count - 1; s1++)
                {
                    for (int s2 = s1 + 1; s2 < sideSubsegments[side].Count; s2++)
                    {
                        congs.Add(new GeometricCongruentSegments(sideSubsegments[side][s1], sideSubsegments[side][s2]));
                    }
                }
            }

            //
            // Each sub-segment is equation to a fraction of the side length.
            //
            int          factor    = (int)Math.Pow(2, NUM_MID_SEGMENT_POINTS);
            NumericValue factorVal = new NumericValue(factor);

            if (factor != sideSubsegments[0].Count)
            {
                throw new Exception("Disagreement with the number of sub-segments in polygon");
            }

            for (int side = 0; side < sideSubsegments.Length; side++)
            {
                foreach (Segment subSeg in sideSubsegments[side])
                {
                    // Factor * sub-segment = whole side
                    eqs.Add(new GeometricSegmentEquation(new Multiplication(factorVal, subSeg), orderedSides[side]));
                }
            }
        }
        //
        // Triangle(A, B, C) -> m\angle ABC + m\angle CAB + m\angle BCA = 180^o
        //
        public static List<EdgeAggregator> Instantiate(GroundedClause c)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.SUM_ANGLES_IN_TRIANGLE_180;

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

            Triangle tri = c as Triangle;
            if (tri == null) return newGrounded;

            // Generate, by definition the sum of the three angles equal 180^o
            Angle a1 = new Angle(tri.Point1, tri.Point2, tri.Point3);
            Angle a2 = new Angle(tri.Point3, tri.Point1, tri.Point2);
            Angle a3 = new Angle(tri.Point2, tri.Point3, tri.Point1);

            Addition add = new Addition(a1, a2);
            Addition overallAdd = new Addition(add, a3);
            NumericValue value = new NumericValue(180); // Sum is 180^o
            GeometricAngleEquation eq = new GeometricAngleEquation(overallAdd, value);

            List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(tri);
            newGrounded.Add(new EdgeAggregator(antecedent, eq, annotation));

            return newGrounded;
        }
        //
        //    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;
        }
        //
        //    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;
        }
        //
        //    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;
        }
Example #6
0
        //
        // Check for (basically) atomic equations involving one unknown and constants otherwise.
        //
        private static FlatEquation SimplifyForMultipliersAndConstants(FlatEquation inEq)
        {
            if (inEq.lhsExps.Count != 1 || inEq.rhsExps.Count != 1) return inEq;

            //
            // Figure out what we're looking at.
            //
            NumericValue value = null;
            GroundedClause unknown = null;
            if (inEq.lhsExps[0] is NumericValue)
            {
                value = inEq.lhsExps[0] as NumericValue;
                unknown = inEq.rhsExps[0];
            }
            else if (inEq.rhsExps[0] is NumericValue)
            {
                value = inEq.rhsExps[0] as NumericValue;
                unknown = inEq.lhsExps[0];
            }
            // Not the type of equation we were looking for.
            else return inEq;

            //
            // Divide both sides to simplify.
            //
            if (unknown.multiplier != 1)
            {
                NumericValue newValue = new NumericValue(value.DoubleValue / unknown.multiplier);

                // reset the multiplier
                unknown.multiplier = 1;

                return new FlatEquation(Utilities.MakeList<GroundedClause>(unknown), Utilities.MakeList<GroundedClause>(newValue));
            }

            // Nothing happened so return original
            return inEq;
        }
        //
        //    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;
        }