Ejemplo n.º 1
0
        public bool CreatesAValidTransversalWith(Intersection thatInter)
        {
            Segment transversal = this.AcquireTransversal(thatInter);

            if (transversal == null)
            {
                return(false);
            }

            // Ensure the non-traversal segments align with the parallel segments
            Segment nonTransversalThis = this.OtherSegment(transversal);
            Segment nonTransversalThat = thatInter.OtherSegment(transversal);

            Segment thisTransversalSegment = this.OtherSegment(nonTransversalThis);
            Segment thatTransversalSegment = thatInter.OtherSegment(nonTransversalThat);

            // Parallel lines should not coincide
            if (nonTransversalThis.IsCollinearWith(nonTransversalThat))
            {
                return(false);
            }

            // Avoid:
            //      |            |
            //    __|    ________|
            //      |            |
            //      |            |

            // Both intersections (transversal segments) must contain the actual transversal
            return(thatTransversalSegment.HasSubSegment(transversal) && thisTransversalSegment.HasSubSegment(transversal));
        }
Ejemplo n.º 2
0
        //
        // Creates a basic S-Shape with standsOnEndpoints
        //
        //   offThis   ______
        //                   |
        //   offThat   ______|
        //
        // Return <offThis, offThat>
        public KeyValuePair <Point, Point> CreatesBasicCShape(Intersection thatInter)
        {
            KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter))
            {
                return(nullPair);
            }

            if (!this.StandsOnEndpoint())
            {
                return(nullPair);
            }
            if (!thatInter.StandsOnEndpoint())
            {
                return(nullPair);
            }

            //
            // Determine offThis and offThat
            //
            Segment transversal = this.AcquireTransversal(thatInter);

            Segment parallelThis = this.OtherSegment(transversal);
            Segment parallelThat = thatInter.OtherSegment(transversal);

            Point offThis = transversal.PointLiesOnAndBetweenEndpoints(parallelThis.Point1) ? parallelThis.Point2 : parallelThis.Point1;
            Point offThat = transversal.PointLiesOnAndBetweenEndpoints(parallelThat.Point1) ? parallelThat.Point2 : parallelThat.Point1;

            // Avoid S-shape scenario
            Segment crossingTester = new Segment(offThis, offThat);
            Point   intersection   = transversal.FindIntersection(crossingTester);

            // We may have parallel crossingTester and transversal; that's ok
            if (crossingTester.IsParallelWith(transversal))
            {
                return(new KeyValuePair <Point, Point>(offThis, offThat));
            }

            // S-shape
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                return(nullPair);
            }

            // C-Shape
            return(new KeyValuePair <Point, Point>(offThis, offThat));
        }
Ejemplo n.º 3
0
        //
        //                    o
        //                    eoooooooo  offStands
        //                    e
        //offEndpoint   eeeeeee
        //                    o
        //                       Returns: <offEndpoint, offStands>
        public KeyValuePair <Point, Point> CreatesSimpleSShape(Intersection thatInter)
        {
            KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter))
            {
                return(nullPair);
            }

            // Restrict to desired combination
            if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint())
            {
                return(nullPair);
            }

            //
            // Determine which is the stands and which is the endpoint
            //
            Intersection endpointInter = null;
            Intersection standsInter   = null;

            if (this.StandsOnEndpoint() && thatInter.StandsOn())
            {
                endpointInter = this;
                standsInter   = thatInter;
            }
            else if (thatInter.StandsOnEndpoint() && this.StandsOn())
            {
                endpointInter = this;
                standsInter   = thatInter;
            }
            else
            {
                return(nullPair);
            }

            // Determine S shape
            Point   offStands        = standsInter.CreatesTShape();
            Segment transversal      = this.AcquireTransversal(thatInter);
            Segment parallelEndpoint = endpointInter.OtherSegment(transversal);
            Point   offEndpoint      = parallelEndpoint.OtherPoint(endpointInter.intersect);

            Segment crossingTester = new Segment(offStands, offEndpoint);
            Point   intersection   = transversal.FindIntersection(crossingTester);

            return(transversal.PointLiesOnAndBetweenEndpoints(intersection) ? new KeyValuePair <Point, Point>(offEndpoint, offStands) : nullPair);
        }
Ejemplo n.º 4
0
        //
        // Creates a Topped F-Shape
        //            top
        // offLeft __________ offEnd    <--- Stands on
        //             |
        //             |_____ off       <--- Stands on
        //             |
        //             |
        //           bottom
        //
        //   Returns: <bottom, off>
        public KeyValuePair<Intersection, Point> CreatesToppedFShape(Intersection thatInter)
        {
            KeyValuePair<Intersection, Point> nullPair = new KeyValuePair<Intersection, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter)) return nullPair;

            // Avoid both standing on an endpoint OR crossing
            if (this.StandsOnEndpoint() || thatInter.StandsOnEndpoint()) return nullPair;
            if (this.Crossing() || thatInter.Crossing()) return nullPair;

            Segment transversal = this.AcquireTransversal(thatInter);

            Intersection standsOnTop = null;
            Intersection standsOnBottom = null;

            // Top has 2 points on the transversal; bottom has 3
            Segment nonTransversalThis = this.OtherSegment(transversal);
            Segment nonTransversalThat = thatInter.OtherSegment(transversal);

            if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point1) ||
                transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point2))
            {
                //             |
                //         ____|                <--- Stands on
                //             |
                //             |_____ off       <--- Stands on
                //             |
                //             |
                if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) ||
                    transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2)) return nullPair;

                standsOnBottom = this;
                standsOnTop = thatInter;
            }
            else if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) ||
                     transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2))
            {
                standsOnBottom = this;
                standsOnTop = thatInter;
            }
            else return nullPair;

            // Check that the bottom extends the transversal
            if (!standsOnBottom.GetCollinearSegment(transversal).HasStrictSubSegment(transversal)) return nullPair;

            Point off = standsOnBottom.OtherSegment(transversal).OtherPoint(standsOnBottom.intersect);

            return new KeyValuePair<Intersection, Point>(standsOnBottom, off);
        }
Ejemplo n.º 5
0
        //
        // Creates a basic S-Shape with standsOnEndpoints
        //
        //                  ______ offThat
        //                 |
        //   offThis ______|
        //
        // Return <offThis, offThat>
        public KeyValuePair<Point, Point> CreatesBasicSShape(Intersection thatInter)
        {
            KeyValuePair<Point, Point> nullPair = new KeyValuePair<Point, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter)) return nullPair;

            if (!this.StandsOnEndpoint()) return nullPair;
            if (!thatInter.StandsOnEndpoint()) return nullPair;

            //
            // Determine offThis and offThat
            //
            Segment transversal = this.AcquireTransversal(thatInter);

            Segment parallelThis = this.OtherSegment(transversal);
            Segment parallelThat = thatInter.OtherSegment(transversal);

            Point offThis = transversal.PointLiesOnAndBetweenEndpoints(parallelThis.Point1) ? parallelThis.Point2 : parallelThis.Point1;
            Point offThat = transversal.PointLiesOnAndBetweenEndpoints(parallelThat.Point1) ? parallelThat.Point2 : parallelThat.Point1;

            // Avoid C-like scenario
            Segment crossingTester = new Segment(offThis, offThat);
            Point intersection = transversal.FindIntersection(crossingTester);

            // C-shape
            if (!transversal.PointLiesOnAndBetweenEndpoints(intersection)) return nullPair;

            // S-Shape
            return new KeyValuePair<Point, Point>(offThis, offThat);
        }
Ejemplo n.º 6
0
        public bool CreatesAValidTransversalWith(Intersection thatInter)
        {
            Segment transversal = this.AcquireTransversal(thatInter);
            if (transversal == null) return false;

            // Ensure the non-traversal segments align with the parallel segments
            Segment nonTransversalThis = this.OtherSegment(transversal);
            Segment nonTransversalThat = thatInter.OtherSegment(transversal);

            Segment thisTransversalSegment = this.OtherSegment(nonTransversalThis);
            Segment thatTransversalSegment = thatInter.OtherSegment(nonTransversalThat);

            // Parallel lines should not coincide
            if (nonTransversalThis.IsCollinearWith(nonTransversalThat)) return false;

            // Avoid:
            //      |            |
            //    __|    ________|
            //      |            |
            //      |            |

            // Both intersections (transversal segments) must contain the actual transversal
            return thatTransversalSegment.HasSubSegment(transversal) && thisTransversalSegment.HasSubSegment(transversal);
        }
        //     leftTop    rightTop
        //         |         |
        //         |_________|
        //         |         |
        //         |         |
        //   leftBottom rightBottom
        //
        private static List<EdgeAggregator> GenerateH(Parallel parallel, Intersection crossingInterLeft, Intersection crossingInterRight)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Segment transversal = crossingInterLeft.AcquireTransversal(crossingInterRight);

            //
            // Find tops and bottoms
            //
            Segment crossingLeftParallel = crossingInterLeft.OtherSegment(transversal);
            Segment crossingRightParallel = crossingInterRight.OtherSegment(transversal);

            //
            // Determine which points are on the same side of the transversal.
            //
            Segment testingCrossSegment = new Segment(crossingLeftParallel.Point1, crossingRightParallel.Point1);
            Point intersection = transversal.FindIntersection(testingCrossSegment);

            Point leftTop = crossingLeftParallel.Point1;
            Point leftBottom = crossingLeftParallel.Point2;

            Point rightTop = null;
            Point rightBottom = null;
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                rightTop = crossingRightParallel.Point2;
                rightBottom = crossingRightParallel.Point1;
            }
            else
            {
                rightTop = crossingRightParallel.Point1;
                rightBottom = crossingRightParallel.Point2;
            }

            //
            // Generate the new supplement relationship
            //
            List<Supplementary> newSupps = new List<Supplementary>();

            Supplementary supp = new Supplementary(new Angle(leftTop, crossingInterLeft.intersect, crossingInterRight.intersect),
                                                   new Angle(rightTop, crossingInterRight.intersect, crossingInterLeft.intersect));
            newSupps.Add(supp);

            supp = new Supplementary(new Angle(leftBottom, crossingInterLeft.intersect, crossingInterRight.intersect),
                                     new Angle(rightBottom, crossingInterRight.intersect, crossingInterLeft.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, parallel, crossingInterLeft, crossingInterRight);
        }
        //
        //    A \
        //       \    B
        //        \  /
        //  O      \/ X
        //         /\
        //        /  \
        //     C /    D
        //
        // One Secant, One Tangent
        // Intersection(X, AD, BC), Tangent(Circle(O), BC) -> 2 * Angle(AXC) = MajorArc(AC) - MinorArc(AC)
        //
        public static List<EdgeAggregator> InstantiateOneSecantOneTangentTheorem(Intersection inter, Tangent tangent, GroundedClause original)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            CircleSegmentIntersection tan = tangent.intersection as CircleSegmentIntersection;

            // Is the tangent segment part of the intersection?
            if (!inter.HasSegment(tan.segment)) return newGrounded;

            // Acquire the chord that the intersection creates.
            Segment secant = inter.OtherSegment(tan.segment);

            Circle circle = tan.theCircle;
            Segment chord = circle.ContainsChord(secant);

            // Check if this segment never intersects the circle or doesn't create a chord.
            if (chord == null) return newGrounded;

            //
            // Get the near / far points out of the chord
            //
            Point closeChordPt = null;
            Point farChordPt = null;
            if (Segment.Between(chord.Point1, chord.Point2, inter.intersect))
            {
                closeChordPt = chord.Point1;
                farChordPt = chord.Point2;
            }
            else
            {
                closeChordPt = chord.Point2;
                farChordPt = chord.Point1;
            }

            //
            // Acquire the arcs
            //
            // Get the close arc first which we know exactly how it is constructed AND that it's a minor arc.
            Arc closeArc = Arc.GetFigureMinorArc(circle, closeChordPt, tan.intersect);

            // The far arc MAY be a major arc; if it is, the first candidate arc will contain the close arc.
            Arc farArc = Arc.GetFigureMinorArc(circle, farChordPt, tan.intersect);

            if (farArc.HasMinorSubArc(closeArc))
            {
                farArc = Arc.GetFigureMajorArc(circle, farChordPt, tan.intersect);
            }

            Angle theAngle = Angle.AcquireFigureAngle(new Angle(closeChordPt, inter.intersect, tan.intersect));

            //
            // Construct the new relationship
            //
            NumericValue two = new NumericValue(2);

            GeometricAngleArcEquation gaaeq = new GeometricAngleArcEquation(new Multiplication(two, theAngle), new Subtraction(farArc, closeArc));

            // For hypergraph
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(original);
            antecedent.Add(inter);
            antecedent.Add(closeArc);
            antecedent.Add(farArc);

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

            return newGrounded;
        }
        //
        // Creates a Topped F-Shape
        //            top
        // oppSide __________       <--- Stands on
        //             |
        //             |_____ off   <--- Stands on
        //             |
        //             |
        //           bottom
        //
        //   Returns: <bottom, off>
        private static List<EdgeAggregator> GenerateToppedFShape(Parallel parallel, Intersection inter1, Intersection inter2, Intersection bottom, Point off)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Intersection top = inter1.Equals(bottom) ? inter2 : inter1;

            // Determine the side of the top intersection needed for the angle
            Segment transversal = inter1.AcquireTransversal(inter2);

            Segment parallelTop = top.OtherSegment(transversal);
            Segment parallelBottom = bottom.OtherSegment(transversal);

            Segment crossingTester = new Segment(off, parallelTop.Point1);
            Point intersection = transversal.FindIntersection(crossingTester);

            Point oppSide = transversal.PointLiesOnAndBetweenEndpoints(intersection) ? parallelTop.Point1 : parallelTop.Point2;

            //
            // Generate the new congruence
            //
            List<CongruentAngles> newAngleRelations = new List<CongruentAngles>();

            GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(off, bottom.intersect, top.intersect),
                                                                        new Angle(oppSide, top.intersect, bottom.intersect));
            newAngleRelations.Add(gca);

            return MakeRelations(newAngleRelations, parallel, inter1, inter2);
        }
Ejemplo n.º 10
0
        private static List<EdgeAggregator> CheckAndGenerateProportionality(Triangle tri, Intersection inter1,
                                                                            Intersection inter2, Parallel parallel)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // The two intersections should not be at the same vertex
            if (inter1.intersect.Equals(inter2.intersect)) return newGrounded;

            //
            // Do these intersections share a segment? That is, do they share the transversal?
            //
            Segment transversal = inter1.AcquireTransversal(inter2);
            if (transversal == null) return newGrounded;

            //
            // Is the transversal a side of the triangle? It should not be.
            //
            if (tri.LiesOn(transversal)) return newGrounded;

            //
            // Determine if one parallel segment is a side of the triangle (which must occur)
            //
            Segment coinciding = tri.DoesParallelCoincideWith(parallel);
            if (coinciding == null) return newGrounded;

            // The transversal and common segment must be distinct
            if (coinciding.IsCollinearWith(transversal)) return newGrounded;

            //
            // Determine if the simplified transversal is within the parallel relationship.
            //
            Segment parallelTransversal = parallel.OtherSegment(coinciding);
            Segment simpleParallelTransversal = new Segment(inter1.intersect, inter2.intersect);

            if (!parallelTransversal.IsCollinearWith(simpleParallelTransversal)) return newGrounded;

            //            A
            //           /\
            //          /  \
            //         /    \
            //  off1  /------\ off2
            //       /        \
            //    B /__________\ C

            //
            // Both intersections should create a T-shape.
            //
            Point off1 = inter1.CreatesTShape();
            Point off2 = inter2.CreatesTShape();
            if (off1 == null || off2 == null) return newGrounded;

            // Get the intersection segments which should coincide with the triangle sides
            KeyValuePair<Segment, Segment> otherSides = tri.OtherSides(coinciding);

            // The intersections may be outside this triangle
            if (otherSides.Key == null || otherSides.Value == null) return newGrounded;

            Segment side1 = inter1.OtherSegment(transversal);
            Segment side2 = inter2.OtherSegment(transversal);

            // Get the actual sides of the triangle
            Segment triangleSide1 = null;
            Segment triangleSide2 = null;
            if (side1.IsCollinearWith(otherSides.Key) && side2.IsCollinearWith(otherSides.Value))
            {
                triangleSide1 = otherSides.Key;
                triangleSide2 = otherSides.Value;
            }
            else if (side1.IsCollinearWith(otherSides.Value) && side2.IsCollinearWith(otherSides.Key))
            {
                triangleSide1 = otherSides.Value;
                triangleSide2 = otherSides.Key;
            }
            else return newGrounded;

            // Verify the opposing parts of the T are on the opposite sides of the triangle
            if (!triangleSide1.PointLiesOnAndExactlyBetweenEndpoints(off2)) return newGrounded;
            if (!triangleSide2.PointLiesOnAndExactlyBetweenEndpoints(off1)) return newGrounded;

            //
            // Construct the new proprtional relationship and resultant equation
            //
            Point sharedVertex = triangleSide1.SharedVertex(triangleSide2);
            SegmentRatio newProp1 = new SegmentRatio(new Segment(sharedVertex, off2), triangleSide1);
            SegmentRatio newProp2 = new SegmentRatio(new Segment(sharedVertex, off1), triangleSide2);

            GeometricSegmentRatioEquation newEq = new GeometricSegmentRatioEquation(newProp1, newProp2);

            // Construct hyperedge
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(tri);
            antecedent.Add(inter1);
            antecedent.Add(inter2);
            antecedent.Add(parallel);

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

            return newGrounded;
        }
Ejemplo n.º 11
0
        //                   top
        //                    o
        //  offStands  oooooooe
        //                    e
        //offEndpoint   eeeeeee
        //                    o
        //                 bottom
        //                       Returns: <offEndpoint, offStands>
        public KeyValuePair <Point, Point> CreatesSimplePIShape(Intersection thatInter)
        {
            KeyValuePair <Point, Point> nullPair = new KeyValuePair <Point, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter))
            {
                return(nullPair);
            }

            // Restrict to desired combination
            if (this.StandsOnEndpoint() && thatInter.StandsOnEndpoint())
            {
                return(nullPair);
            }

            //
            // Determine which is the stands and which is the endpoint
            //
            Intersection endpointInter = null;
            Intersection standsInter   = null;

            if (this.StandsOnEndpoint() && thatInter.StandsOn())
            {
                endpointInter = this;
                standsInter   = thatInter;
            }
            else if (thatInter.StandsOnEndpoint() && this.StandsOn())
            {
                endpointInter = this;
                standsInter   = thatInter;
            }
            else
            {
                return(nullPair);
            }

            //
            // Avoid Some shapes
            //
            Segment transversal       = this.AcquireTransversal(thatInter);
            Segment transversalStands = standsInter.GetCollinearSegment(transversal);

            Point top    = null;
            Point bottom = null;

            if (Segment.Between(standsInter.intersect, transversalStands.Point1, endpointInter.intersect))
            {
                top    = transversalStands.Point1;
                bottom = transversalStands.Point2;
            }
            else
            {
                top    = transversalStands.Point2;
                bottom = transversalStands.Point1;
            }

            // Avoid: ____  Although this shouldn't happen since both intersections do not stand on endpoints
            //        ____|
            //
            // Also avoid Simple F-Shape
            //
            if (transversal.HasPoint(top) || transversal.HasPoint(bottom))
            {
                return(nullPair);
            }

            // Determine S shape
            Point offStands = standsInter.CreatesTShape();

            Segment parallelEndpoint = endpointInter.OtherSegment(transversal);
            Point   offEndpoint      = parallelEndpoint.OtherPoint(endpointInter.intersect);


            Segment crossingTester = new Segment(offStands, offEndpoint);
            Point   intersection   = transversal.FindIntersection(crossingTester);

            // S-shape    // PI-Shape
            return(transversal.PointLiesOnAndBetweenEndpoints(intersection) ? nullPair : new KeyValuePair <Point, Point>(offEndpoint, offStands));
        }
Ejemplo n.º 12
0
        //
        // Creates a Topped F-Shape
        //            top
        // offLeft __________ offEnd    <--- Stands on
        //             |
        //             |_____ off       <--- Stands on
        //             |
        //             |
        //           bottom
        //
        //   Returns: <bottom, off>
        public KeyValuePair <Intersection, Point> CreatesToppedFShape(Intersection thatInter)
        {
            KeyValuePair <Intersection, Point> nullPair = new KeyValuePair <Intersection, Point>(null, null);

            // A valid transversal is required for this shape
            if (!this.CreatesAValidTransversalWith(thatInter))
            {
                return(nullPair);
            }

            // Avoid both standing on an endpoint OR crossing
            if (this.StandsOnEndpoint() || thatInter.StandsOnEndpoint())
            {
                return(nullPair);
            }
            if (this.Crossing() || thatInter.Crossing())
            {
                return(nullPair);
            }

            Segment transversal = this.AcquireTransversal(thatInter);

            Intersection standsOnTop    = null;
            Intersection standsOnBottom = null;

            // Top has 2 points on the transversal; bottom has 3
            Segment nonTransversalThis = this.OtherSegment(transversal);
            Segment nonTransversalThat = thatInter.OtherSegment(transversal);

            if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point1) ||
                transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThis.Point2))
            {
                //             |
                //         ____|                <--- Stands on
                //             |
                //             |_____ off       <--- Stands on
                //             |
                //             |
                if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) ||
                    transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2))
                {
                    return(nullPair);
                }

                standsOnBottom = this;
                standsOnTop    = thatInter;
            }
            else if (transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point1) ||
                     transversal.PointLiesOnAndBetweenEndpoints(nonTransversalThat.Point2))
            {
                standsOnBottom = this;
                standsOnTop    = thatInter;
            }
            else
            {
                return(nullPair);
            }

            // Check that the bottom extends the transversal
            if (!standsOnBottom.GetCollinearSegment(transversal).HasStrictSubSegment(transversal))
            {
                return(nullPair);
            }

            Point off = standsOnBottom.OtherSegment(transversal).OtherPoint(standsOnBottom.intersect);

            return(new KeyValuePair <Intersection, Point>(standsOnBottom, off));
        }
        private static List<EdgeAggregator> CheckAndGenerateSameSideInteriorImplyParallel(Intersection inter1, Intersection inter2, Supplementary supp)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // Get the transversal (shared segment), if it exists
            Segment transversal = inter1.AcquireTransversal(inter2);
            if (transversal == null) return newGrounded;

            Angle angleI = inter1.GetInducedNonStraightAngle(supp);
            Angle angleJ = inter2.GetInducedNonStraightAngle(supp);

            //
            // Do we have valid intersections and congruent angle pairs
            //
            if (angleI == null || angleJ == null) return newGrounded;

            //
            // Check to see if they are, in fact, alternate interior angles respectively
            //
            // Are the angles within the interior
            Segment parallelCand1 = inter1.OtherSegment(transversal);
            Segment parallelCand2 = inter2.OtherSegment(transversal);

            if (!angleI.OnInteriorOf(inter1, inter2) || !angleJ.OnInteriorOf(inter1, inter2)) return newGrounded;

            //
            // Are these angles on the opposite 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 intersect the real transversal in the middle of the two segments? If it DOES NOT, it is same side
            //
            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(supp);

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

            return newGrounded;
        }
        private static List<EdgeAggregator> CheckAndGeneratePerpendicular(Perpendicular perp, Parallel parallel, Intersection inter, GroundedClause original)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // The perpendicular intersection must refer to one of the parallel segments
            Segment shared = perp.CommonSegment(parallel);
            if (shared == null) return newGrounded;

            // The other intersection must refer to a segment in the parallel pair
            Segment otherShared = inter.CommonSegment(parallel);
            if (otherShared == null) return newGrounded;

            // The two shared segments must be distinct
            if (shared.Equals(otherShared)) return newGrounded;

            // Transversals must align
            if (!inter.OtherSegment(otherShared).Equals(perp.OtherSegment(shared))) return newGrounded;

            // Strengthen the old intersection to be perpendicular
            Strengthened strengthenedPerp = new Strengthened(inter, new Perpendicular(inter));

            // Construct hyperedge
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(original);
            antecedent.Add(parallel);
            antecedent.Add(inter);

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

            return newGrounded;
        }
        // Corresponding angles if (we have 8 points here)
        //
        //  InterLeft                        InterRight
        //                |          |
        //      offLeft __|__________|__ offRight
        //                |          |
        //                |          |
        //
        private static List<EdgeAggregator> InstantiateCompleteIntersection(Parallel parallel, Intersection crossingInterLeft, Intersection crossingInterRight)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Segment transversal = crossingInterLeft.AcquireTransversal(crossingInterRight);

            //
            // Find off1 and off2
            //
            Segment crossingLeftParallel = crossingInterLeft.OtherSegment(transversal);
            Segment crossingRightParallel = crossingInterRight.OtherSegment(transversal);

            //
            // Determine which points are on the same side of the transversal.
            //
            Segment testingCrossSegment = new Segment(crossingLeftParallel.Point1, crossingRightParallel.Point1);
            Point intersection = transversal.FindIntersection(testingCrossSegment);

            Point crossingLeftTop = crossingLeftParallel.Point1;
            Point crossingLeftBottom = crossingLeftParallel.Point2;

            Point crossingRightTop = null;
            Point crossingRightBottom = null;
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                crossingRightTop = crossingRightParallel.Point2;
                crossingRightBottom = crossingRightParallel.Point1;
            }
            else
            {
                crossingRightTop = crossingRightParallel.Point1;
                crossingRightBottom = crossingRightParallel.Point2;
            }

            // Point that is outside of the parallel lines and transversal
            Segment leftTransversal = crossingInterLeft.GetCollinearSegment(transversal);
            Segment rightTransversal = crossingInterRight.GetCollinearSegment(transversal);

            Point offCrossingLeft = Segment.Between(crossingInterLeft.intersect, leftTransversal.Point1, crossingInterRight.intersect) ? leftTransversal.Point1 : leftTransversal.Point2;
            Point offCrossingRight = Segment.Between(crossingInterRight.intersect, crossingInterLeft.intersect, rightTransversal.Point1) ? rightTransversal.Point1 : rightTransversal.Point2;

            //
            // Generate the new congruences
            //
            List<CongruentAngles> newAngleRelations = new List<CongruentAngles>();

            GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(crossingLeftTop, crossingInterLeft.intersect, crossingInterRight.intersect),
                                                                        new Angle(crossingRightTop, crossingInterRight.intersect, offCrossingRight));
            newAngleRelations.Add(gca);
            gca = new GeometricCongruentAngles(new Angle(crossingLeftTop, crossingInterLeft.intersect, offCrossingLeft),
                                               new Angle(crossingRightTop, crossingInterRight.intersect, crossingInterLeft.intersect));
            newAngleRelations.Add(gca);
            gca = new GeometricCongruentAngles(new Angle(crossingLeftBottom, crossingInterLeft.intersect, offCrossingLeft),
                                               new Angle(crossingRightBottom, crossingInterRight.intersect, crossingInterLeft.intersect));
            newAngleRelations.Add(gca);
            gca = new GeometricCongruentAngles(new Angle(crossingLeftBottom, crossingInterLeft.intersect, crossingInterRight.intersect),
                                               new Angle(crossingRightBottom, crossingInterRight.intersect, offCrossingRight));
            newAngleRelations.Add(gca);

            return MakeRelations(newAngleRelations, parallel, crossingInterLeft, crossingInterRight);
        }
Ejemplo n.º 16
0
        private static List<EdgeAggregator> InstantiateFromAltitude(Intersection inter, Altitude altitude)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // The intersection should contain the altitude segment
            if (!inter.HasSegment(altitude.segment)) return newGrounded;

            // The triangle should contain the other segment in the intersection
            Segment triangleSide = altitude.triangle.CoincidesWithASide(inter.OtherSegment(altitude.segment));
            if (triangleSide == null) return newGrounded;
            if (!inter.OtherSegment(altitude.segment).HasSubSegment(triangleSide)) return newGrounded;

            //
            // Create the Perpendicular relationship
            //
            Strengthened streng = new Strengthened(inter, new Perpendicular(inter));

            // For hypergraph
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(inter);
            antecedent.Add(altitude);

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

            return newGrounded;
        }
        //
        // Creates a shape like a crazy person flying
        //
        //            top   top
        //             |     |
        // larger      |_____|___ off
        //             |     |
        //             |     |
        //
        // Similar to H-shape with an extended point
        // Returns the 'larger' intersection that contains the point: off
        private static List<EdgeAggregator> InstantiateFlyingIntersection(Parallel parallel, Intersection inter1, Intersection inter2, Intersection larger, Point off)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Intersection smallerInter = inter1.Equals(larger) ? inter2 : inter1;

            Segment transversal = inter1.AcquireTransversal(inter2);

            Segment parallel1 = inter1.OtherSegment(transversal);
            Segment parallel2 = inter2.OtherSegment(transversal);

            Point largerTop = parallel1.Point1;
            Point largerBottom = parallel1.Point2;

            Point otherTop = null;
            Point otherBottom = null;

            Segment crossingTester = new Segment(parallel1.Point1, parallel2.Point1);
            Point intersection = transversal.FindIntersection(crossingTester);
            // opposite sides
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                otherTop = parallel2.Point2;
                otherBottom = parallel2.Point1;
            }
            // same sides
            else
            {
                otherTop = parallel2.Point1;
                otherBottom = parallel2.Point2;
            }

            //
            // Generate the new congruence
            //
            List<CongruentAngles> newAngleRelations = new List<CongruentAngles>();

            GeometricCongruentAngles gca1 = new GeometricCongruentAngles(new Angle(off, smallerInter.intersect, otherTop),
                                                                         new Angle(smallerInter.intersect, larger.intersect, largerTop));
            newAngleRelations.Add(gca1);
            GeometricCongruentAngles gca2 = new GeometricCongruentAngles(new Angle(off, smallerInter.intersect, otherBottom),
                                                                         new Angle(smallerInter.intersect, larger.intersect, largerBottom));
            newAngleRelations.Add(gca2);

            return MakeRelations(newAngleRelations, parallel, inter1, inter2);
        }
        //     leftTop    rightTop
        //         |         |
        //         |_________|
        //         |         |
        //         |         |
        //   leftBottom rightBottom
        //
        private static List<EdgeAggregator> GenerateH(Parallel parallel, Intersection crossingInterLeft, Intersection crossingInterRight)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Segment transversal = crossingInterLeft.AcquireTransversal(crossingInterRight);

            //
            // Find tops and bottoms
            //
            Segment crossingLeftParallel = crossingInterLeft.OtherSegment(transversal);
            Segment crossingRightParallel = crossingInterRight.OtherSegment(transversal);

            //
            // Determine which points are on the same side of the transversal.
            //
            Segment testingCrossSegment = new Segment(crossingLeftParallel.Point1, crossingRightParallel.Point1);
            Point intersection = transversal.FindIntersection(testingCrossSegment);

            Point leftTop = crossingLeftParallel.Point1;
            Point leftBottom = crossingLeftParallel.Point2;

            Point rightTop = null;
            Point rightBottom = null;
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                rightTop = crossingRightParallel.Point2;
                rightBottom = crossingRightParallel.Point1;
            }
            else
            {
                rightTop = crossingRightParallel.Point1;
                rightBottom = crossingRightParallel.Point2;
            }

            //
            // Generate the new congruences
            //
            List<CongruentAngles> newAngleRelations = new List<CongruentAngles>();

            GeometricCongruentAngles gca = new GeometricCongruentAngles(new Angle(leftTop, crossingInterLeft.intersect, crossingInterRight.intersect),
                                                                        new Angle(rightBottom, crossingInterRight.intersect, crossingInterLeft.intersect));
            newAngleRelations.Add(gca);
            gca = new GeometricCongruentAngles(new Angle(rightTop, crossingInterRight.intersect, crossingInterLeft.intersect),
                                               new Angle(leftBottom, crossingInterLeft.intersect, crossingInterRight.intersect));
            newAngleRelations.Add(gca);

            return MakeRelations(newAngleRelations, parallel, crossingInterLeft, crossingInterRight);
        }
        private static List<EdgeAggregator> InstantiateIntersection(Parallel parallel, Intersection inter1, Intersection inter2)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // Avoid:
            //      |            |
            //    __|    ________|
            //      |            |
            //      |            |
            // Both intersections (transversal segments) must contain the actual transversal; that is, a direct, segment relationship must exist
            if (!inter1.CreatesAValidTransversalWith(inter2)) return newGrounded;

            // No corresponding angles if we have:
            //
            //    |          |         |
            //    |__________|         |_________
            //                                   |
            //                                   |
            //
            if (inter1.StandsOnEndpoint() && inter2.StandsOnEndpoint()) return newGrounded;

            // if (Utilities.DEBUG) System.Diagnostics.Debug.WriteLine("Working on: \n\t" + inter1.ToString() + "\n\t" + inter2.ToString());

            //
            // Verify we have a parallel / intersection situation using the given information
            //
            Segment transversal = inter1.AcquireTransversal(inter2);

            // Ensure the non-traversal segments align with the parallel segments
            Segment coincidingParallel1 = parallel.CoincidesWith(inter1.OtherSegment(transversal));
            Segment coincidingParallel2 = parallel.CoincidesWith(inter2.OtherSegment(transversal));

            // The pair of non-transversals needs to align exactly with the parallel pair of segments
            if (coincidingParallel1 == null || coincidingParallel2 == null) return newGrounded;

            // STANDARD Dual Crossings
            // Corresponding angles:
            //
            //      |          |
            //   ___|__________|__
            //      |          |
            //      |          |
            //
            if (inter1.Crossing() && inter2.Crossing()) return InstantiateCompleteIntersection(parallel, inter1, inter2);

            // NOT Corresponding if an H-Shape
            //
            // |     |
            // |_____|
            // |     |
            // |     |
            //
            if (inter1.CreatesHShape(inter2)) return newGrounded;

            // NOT Corresponding angles if:
            //
            //         |______
            //         |
            //   ______|
            //         |
            //
            KeyValuePair<Point, Point> sShapePoints = inter1.CreatesStandardSShape(inter2);
            if (sShapePoints.Key != null && sShapePoints.Value != null) return newGrounded;

            // NOT Corresponding angles if:
            //
            //       |______
            //       |
            // ______|
            KeyValuePair<Point, Point> leanerShapePoints = inter1.CreatesLeanerShape(inter2);
            if (leanerShapePoints.Key != null && leanerShapePoints.Value != null) return newGrounded;

            // Corresponding angles if:
            //    _____
            //   |
            //   |_____
            //   |
            //   |
            //
            KeyValuePair<Point, Point> fShapePoints = inter1.CreatesFShape(inter2);
            if (fShapePoints.Key != null && fShapePoints.Value != null)
            {
                return InstantiateFIntersection(parallel, inter1, fShapePoints.Key, inter2, fShapePoints.Value);
            }

            sShapePoints = inter1.CreatesSimpleSShape(inter2);
            if (sShapePoints.Key != null && sShapePoints.Value != null) return newGrounded;

            // Corresponding angles if:
            //                o       e
            // standsOn (o)   o       e    standsOnEndpoint (e)
            //             eeeoeeeeeeee
            //                o
            //                o
            //
            KeyValuePair<Point, Point> simpleTShapePoints = inter1.CreatesSimpleTShape(inter2);
            if (simpleTShapePoints.Key != null && simpleTShapePoints.Value != null)
            {
                return InstantiateSimpleTIntersection(parallel, inter1, inter2, simpleTShapePoints.Key, simpleTShapePoints.Value);
            }

            // Corresponding angles if:
            //    ____________
            //       |    |
            //       |    |
            //
            KeyValuePair<Point, Point> piShapePoints = inter1.CreatesSimplePIShape(inter2);
            if (piShapePoints.Key != null && piShapePoints.Value != null)
            {
                return InstantiateSimplePiIntersection(parallel, inter1, inter2, piShapePoints.Key, piShapePoints.Value);
            }

            // Corresponding if:
            //
            // |     |        |
            // |_____|____    |_________
            // |              |     |
            // |              |     |
            //
            KeyValuePair<Point, Point> chairShapePoints = inter1.CreatesChairShape(inter2);
            if (chairShapePoints.Key != null && chairShapePoints.Value != null)
            {
                return InstantiateChairIntersection(parallel, inter1, chairShapePoints.Key, inter2, chairShapePoints.Value);
            }

            // Corresponding angles if:
            //    ____________
            //       |    |
            //       |    |
            //
            piShapePoints = inter1.CreatesPIShape(inter2);
            if (piShapePoints.Key != null && piShapePoints.Value != null)
            {
                return InstantiatePiIntersection(parallel, inter1, piShapePoints.Key, inter2, piShapePoints.Value);
            }

            //
            //      |                |
            // _____|____      ______|______
            //      |                |
            //      |_____      _____|
            //
            KeyValuePair<Point, Point> crossedTShapePoints = inter1.CreatesCrossedTShape(inter2);
            if (crossedTShapePoints.Key != null && crossedTShapePoints.Value != null)
            {
                return InstantiateCrossedTIntersection(parallel, inter1, inter2, crossedTShapePoints.Key, crossedTShapePoints.Value);
            }

            // Corresponding if a flying-Shape
            //
            // |     |
            // |_____|___
            // |     |
            // |     |
            //
            KeyValuePair<Intersection, Point> flyingShapeValues = inter1.CreatesFlyingShape(inter2);
            if (flyingShapeValues.Key != null && flyingShapeValues.Value != null)
            {
                return InstantiateFlyingIntersection(parallel, inter1, inter2, flyingShapeValues.Key, flyingShapeValues.Value);
            }

            //        |
            //  ______|______
            //        |
            //   _____|_____
            Point offCross = inter1.CreatesFlyingShapeWithCrossing(inter2);
            if (offCross != null) return InstantiateFlyingCrossedIntersection(parallel, inter1, inter2, offCross);

            //        |
            //  ______|______
            //        |
            //        |_____
            //        |
            offCross = inter1.CreatesExtendedChairShape(inter2);
            if (offCross != null) return InstantiateExtendedChairIntersection(parallel, inter1, inter2, offCross);

            return newGrounded;
        }
        private static List<EdgeAggregator> CheckAndGenerateParallelImplyAlternateInterior(Intersection inter1, Intersection inter2, Parallel parallel)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // The two intersections should not be at the same vertex
            if (inter1.intersect.Equals(inter2.intersect)) return newGrounded;

            // Determine the transversal
            Segment transversal = inter1.AcquireTransversal(inter2);
            if (transversal == null) return newGrounded;

            //
            // Ensure the non-traversal segments align with the parallel segments
            //
            Segment parallel1 = inter1.OtherSegment(transversal);
            Segment parallel2 = inter2.OtherSegment(transversal);

            // The non-transversals should not be the same (coinciding)
            if (parallel1.IsCollinearWith(parallel2)) return newGrounded;

            Segment coincidingParallel1 = parallel.CoincidesWith(parallel1);
            Segment coincidingParallel2 = parallel.CoincidesWith(parallel2);

            // The pair of non-transversals needs to align exactly with the parallel pair of segments
            if (coincidingParallel1 == null || coincidingParallel2 == null) return newGrounded;

            // Both intersections should not be referring to an intersection point on the same parallel segment
            if (parallel.segment1.PointLiesOn(inter1.intersect) && parallel.segment1.PointLiesOn(inter2.intersect)) return newGrounded;
            if (parallel.segment2.PointLiesOn(inter1.intersect) && parallel.segment2.PointLiesOn(inter2.intersect)) return newGrounded;

            // The resultant candidate parallel segments shouldn't share any vertices
            if (coincidingParallel1.SharedVertex(coincidingParallel2) != null) return newGrounded;

            if (inter1.StandsOnEndpoint() && inter2.StandsOnEndpoint())
            {
                //
                // Creates a basic S-Shape with standsOnEndpoints
                //
                //   offThis   ______
                //                   |
                //   offThat   ______|
                //
                // Return <offThis, offThat>
                KeyValuePair<Point, Point> cShapePoints = inter1.CreatesBasicCShape(inter2);
                if (cShapePoints.Key != null && cShapePoints.Value != null) return newGrounded;

                //
                // Creates a basic S-Shape with standsOnEndpoints
                //
                //                  ______ offThat       _______
                //                 |                     \
                //   offThis ______|                 _____\
                //
                // Return <offThis, offThat>
                KeyValuePair<Point, Point> sShapePoints = inter1.CreatesBasicSShape(inter2);
                if (sShapePoints.Key != null && sShapePoints.Value != null)
                {
                    return GenerateSimpleS(parallel, inter1, sShapePoints.Key, inter2, sShapePoints.Value);
                }

                return newGrounded;
            }

            //     _______/________
            //           /
            //          /
            //   ______/_______
            //        /
            if (inter1.Crossing() && inter2.Crossing()) return GenerateDualCrossings(parallel, inter1, inter2);

            // No alt int in this case:
            // Creates an F-Shape
            //   top
            //    _____ offEnd     <--- Stands on Endpt
            //   |
            //   |_____ offStands  <--- Stands on
            //   |
            //   |
            //  bottom
            KeyValuePair<Point, Point> fShapePoints = inter1.CreatesFShape(inter2);
            if (fShapePoints.Key != null && fShapePoints.Value != null) return newGrounded;

            // Alt. Int if an H-Shape
            //
            // |     |
            // |_____|
            // |     |
            // |     |
            //
            if (inter1.CreatesHShape(inter2)) return GenerateH(parallel, inter1, inter2);

            // Creates an S-Shape
            //
            //         |______
            //         |
            //   ______|
            //         |
            //
            //   Order of non-collinear points is order of intersections: <this, that>
            KeyValuePair<Point, Point> standardSShapePoints = inter1.CreatesStandardSShape(inter2);
            if (standardSShapePoints.Key != null && standardSShapePoints.Value != null)
            {
                return GenerateSimpleS(parallel, inter1, standardSShapePoints.Key, inter2, standardSShapePoints.Value);
            }

            // Corresponding if a flying-Shape
            //
            // |     |
            // |_____|___ offCross
            // |     |
            // |     |
            //
            Point offCross = inter1.CreatesFlyingShapeWithCrossing(inter2);
            if (offCross != null)
            {
                return GenerateFlying(parallel, inter1, inter2, offCross);
            }

            //
            // Creates a shape like an extended t
            //     offCross                          offCross
            //      |                                   |
            // _____|____                         ______|______
            //      |                                   |
            //      |_____ offStands     offStands _____|
            //
            // Returns <offStands, offCross>
            KeyValuePair<Point, Point> tShapePoints = inter1.CreatesCrossedTShape(inter2);
            if (tShapePoints.Key != null && tShapePoints.Value != null)
            {
                return GenerateCrossedT(parallel, inter1, inter2, tShapePoints.Key, tShapePoints.Value);
            }

            //
            // Creates a Topped F-Shape
            //            top
            // offLeft __________ offEnd    <--- Stands on
            //             |
            //             |_____ off       <--- Stands on
            //             |
            //             |
            //           bottom
            //
            //   Returns: <bottom, off>
            KeyValuePair<Intersection, Point> toppedFShapePoints = inter1.CreatesToppedFShape(inter2);
            if (toppedFShapePoints.Key != null && toppedFShapePoints.Value != null)
            {
                return GenerateToppedFShape(parallel, inter1, inter2, toppedFShapePoints.Key, toppedFShapePoints.Value);
            }

            return newGrounded;
        }
Ejemplo n.º 21
0
        //
        // Take the angle congruence and bisector and create the AngleBisector relation
        //              \
        //               \
        //     B ---------V---------A
        //                 \
        //                  \
        //                   C
        //
        private static List<EdgeAggregator> InstantiateToDef(Point intersectionPoint, Intersection inter, CongruentSegments cs)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // Does the given point of intersection apply to this actual intersection object
            if (!intersectionPoint.Equals(inter.intersect)) return newGrounded;

            // The entire segment AB
            Segment overallSegment = new Segment(cs.cs1.OtherPoint(intersectionPoint), cs.cs2.OtherPoint(intersectionPoint));

            // The segment must align completely with one of the intersection segments
            Segment interCollinearSegment = inter.GetCollinearSegment(overallSegment);
            if (interCollinearSegment == null) return newGrounded;

            // Does this intersection have the entire segment AB
            if (!inter.HasSegment(overallSegment)) return newGrounded;

            Segment bisector = inter.OtherSegment(overallSegment);
            Segment bisectedSegment = inter.GetCollinearSegment(overallSegment);

            // Check if the bisected segment extends is the exact same segment as the overall segment AB
            if (!bisectedSegment.StructurallyEquals(overallSegment))
            {
                if (overallSegment.PointLiesOnAndBetweenEndpoints(bisectedSegment.Point1) &&
                    overallSegment.PointLiesOnAndBetweenEndpoints(bisectedSegment.Point2)) return newGrounded;
            }

            SegmentBisector newSB = new SegmentBisector(inter, bisector);

            // For hypergraph
            List<GroundedClause> antecedent = new List<GroundedClause>();
            antecedent.Add(inter);
            antecedent.Add(cs);

            newGrounded.Add(new EdgeAggregator(antecedent, newSB, annotation));
            return newGrounded;
        }
        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;
        }
        //          leftTop    rightTop
        //              |         |
        //  offleft ____|_________|_____ offRight
        //              |         |
        //              |         |
        //         leftBottom rightBottom
        //
        private static List<EdgeAggregator> GenerateDualCrossings(Parallel parallel, Intersection crossingInterLeft, Intersection crossingInterRight)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Segment transversal = crossingInterLeft.AcquireTransversal(crossingInterRight);

            //
            // Find offLeft and offRight
            //
            Segment crossingLeftParallel = crossingInterLeft.OtherSegment(transversal);
            Segment crossingRightParallel = crossingInterRight.OtherSegment(transversal);

            //
            // Determine which points are on the same side of the transversal.
            //
            Segment testingCrossSegment = new Segment(crossingLeftParallel.Point1, crossingRightParallel.Point1);
            Point intersection = transversal.FindIntersection(testingCrossSegment);

            Point leftTop = crossingLeftParallel.Point1;
            Point leftBottom = crossingLeftParallel.Point2;

            Point rightTop = null;
            Point rightBottom = null;
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                rightTop = crossingRightParallel.Point2;
                rightBottom = crossingRightParallel.Point1;
            }
            else
            {
                rightTop = crossingRightParallel.Point1;
                rightBottom = crossingRightParallel.Point2;
            }

            // Point that is outside of the parallel lines and transversal
            Segment leftTransversal = crossingInterLeft.GetCollinearSegment(transversal);
            Segment rightTransversal = crossingInterRight.GetCollinearSegment(transversal);

            Point offLeft = Segment.Between(crossingInterLeft.intersect, leftTransversal.Point1, crossingInterRight.intersect) ? leftTransversal.Point1 : leftTransversal.Point2;
            Point offRight = Segment.Between(crossingInterRight.intersect, crossingInterLeft.intersect, rightTransversal.Point1) ? rightTransversal.Point1 : rightTransversal.Point2;

            //
            // Generate the new congruences
            //

            //          leftTop    rightTop
            //              |         |
            //  offleft ____|_________|_____ offRight
            //              |         |
            //              |         |
            //         leftBottom rightBottom
            List<Supplementary> newSupps = new List<Supplementary>();

            Supplementary supp = new Supplementary(new Angle(leftTop, crossingInterLeft.intersect, crossingInterRight.intersect),
                                                   new Angle(rightTop, crossingInterRight.intersect, crossingInterLeft.intersect));
            newSupps.Add(supp);

            supp = new Supplementary(new Angle(leftBottom, crossingInterLeft.intersect, crossingInterRight.intersect),
                                     new Angle(rightBottom, crossingInterRight.intersect, crossingInterLeft.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, parallel, crossingInterLeft, crossingInterRight);
        }