//         B ____________________ C
        //          /                   /
        //         /                   /
        //        / Circle (center)   /
        //       /        O          /
        //      /                   /
        //   A /___________________/ D
        //
        // Circle(O), Quad(A, B, C, D) -> Supplementary(Angle(ABC), Angle(ADC)), Supplementary(Angle(BAD), Angle(BCD))
        //
        public static List<EdgeAggregator> Instantiate(GroundedClause clause)
        {
            annotation.active = EngineUIBridge.JustificationSwitch.INSCRIBED_QUADRILATERAL_OPPOSITE_ANGLES_SUPPLEMENTARY;

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

            Circle circle = clause as Circle;

            if (circle == null) return newGrounded;

            //
            // For each inscribed quadrilateral, generate accordingly.
            //
            foreach (Quadrilateral quad in circle.inscribedPolys[Polygon.QUADRILATERAL_INDEX])
            {
                Supplementary supp1 = new Supplementary(quad.topLeftAngle, quad.bottomRightAngle);
                Supplementary supp2 = new Supplementary(quad.bottomLeftAngle, quad.topRightAngle);

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

                newGrounded.Add(new EdgeAggregator(antecedent, supp1, annotation));
                newGrounded.Add(new EdgeAggregator(antecedent, supp2, annotation));
            }

            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;
        }
Ejemplo n.º 3
0
        public override bool Equals(Object obj)
        {
            Supplementary supp = obj as Supplementary;

            if (supp == null)
            {
                return(false);
            }
            return(base.Equals(supp));
        }
Ejemplo n.º 4
0
        public Angle GetInducedNonStraightAngle(Supplementary supp)
        {
            if (this.InducesNonStraightAngle(supp.angle1))
            {
                return(supp.angle1);
            }
            if (this.InducesNonStraightAngle(supp.angle2))
            {
                return(supp.angle2);
            }

            return(null);
        }
Ejemplo n.º 5
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;
        }
Ejemplo n.º 6
0
        //  A      B
        //   \    /
        //    \  /
        //     \/
        //     /\ X
        //    /  \
        //   /    \
        //  C      D
        //
        // Intersection(X, Segment(A, D), Segment(B, C)) -> Supplementary(Angle(A, X, B), Angle(B, X, D))
        //                                                  Supplementary(Angle(B, X, D), Angle(D, X, C))
        //                                                  Supplementary(Angle(D, X, C), Angle(C, X, A))
        //                                                  Supplementary(Angle(C, X, A), Angle(A, X, B))
        //
        public static List<EdgeAggregator> InstantiateToSupplementary(Intersection inter)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            // The situation looks like this:
            //  |
            //  |
            //  |_______
            //
            if (inter.StandsOnEndpoint()) return newGrounded;

            // The situation looks like this:
            //       |
            //       |
            //  _____|_______
            //
            if (inter.StandsOn())
            {
                Point up = null;
                Point left = null;
                Point right = null;
                if (inter.lhs.HasPoint(inter.intersect))
                {
                    up = inter.lhs.OtherPoint(inter.intersect);
                    left = inter.rhs.Point1;
                    right = inter.rhs.Point2;
                }
                else
                {
                    up = inter.rhs.OtherPoint(inter.intersect);
                    left = inter.lhs.Point1;
                    right = inter.lhs.Point2;
                }

                // Gets the single angle object from the original figure
                Angle newAngle1 = Angle.AcquireFigureAngle(new Angle(left, inter.intersect, up));
                Angle newAngle2 = Angle.AcquireFigureAngle(new Angle(right, inter.intersect, up));

                Supplementary supp = new Supplementary(newAngle1, newAngle2);
                supp.SetNotASourceNode();
                supp.SetNotAGoalNode();
                supp.SetClearDefinition();

                newGrounded.Add(new EdgeAggregator(MakeAntecedent(inter, supp.angle1, supp.angle2), supp, annotation));
            }

            //
            // The situation is standard and results in 4 supplementary relationships
            //
            else
            {
                Angle newAngle1 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point1, inter.intersect, inter.rhs.Point1));
                Angle newAngle2 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point1, inter.intersect, inter.rhs.Point2));
                Angle newAngle3 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point2, inter.intersect, inter.rhs.Point1));
                Angle newAngle4 = Angle.AcquireFigureAngle(new Angle(inter.lhs.Point2, inter.intersect, inter.rhs.Point2));

                List<Supplementary> newSupps = new List<Supplementary>();
                newSupps.Add(new Supplementary(newAngle1, newAngle2));
                newSupps.Add(new Supplementary(newAngle2, newAngle4));
                newSupps.Add(new Supplementary(newAngle3, newAngle4));
                newSupps.Add(new Supplementary(newAngle3, newAngle1));

                foreach (Supplementary supp in newSupps)
                {
                    supp.SetNotASourceNode();
                    supp.SetNotAGoalNode();
                    supp.SetClearDefinition();

                    newGrounded.Add(new EdgeAggregator(MakeAntecedent(inter, supp.angle1, supp.angle2), supp, annotation));
                }
            }

            return newGrounded;
        }
        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;
        }
Ejemplo n.º 8
0
        public Angle GetInducedNonStraightAngle(Supplementary supp)
        {
            if (this.InducesNonStraightAngle(supp.angle1)) return supp.angle1;
            if (this.InducesNonStraightAngle(supp.angle2)) return supp.angle2;

            return null;
        }
        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;
        }
        // Corresponding angles if:
        //
        //   up  <- may not occur
        //   |_____  offEnd
        //   |
        //   |_____  offStands
        //   |
        //   |
        //  down
        //
        private static List<EdgeAggregator> InstantiateFIntersection(Parallel parallel, Intersection inter1, Point off1, Intersection inter2, Point off2)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            Point offEnd = null;
            Point offStands = null;
            Intersection endpt = null;
            Intersection stands = null;
            if (inter1.StandsOnEndpoint())
            {
                endpt = inter1;
                offEnd = off1;
                stands = inter2;
                offStands = off2;
            }
            else if (inter2.StandsOnEndpoint())
            {
                endpt = inter2;
                offEnd = off2;
                stands = inter1;
                offStands = off1;
            }

            Segment transversal = inter1.AcquireTransversal(inter2);

            Segment nonParallelEndpt = endpt.GetCollinearSegment(transversal);
            Segment nonParallelStands = stands.GetCollinearSegment(transversal);

            Point down = null;
            Point up = null;
            if (Segment.Between(stands.intersect, nonParallelStands.Point1, endpt.intersect))
            {
                down = nonParallelStands.Point1;
                up = nonParallelStands.Point2;
            }
            else
            {
                down = nonParallelStands.Point2;
                up = nonParallelStands.Point1;
            }

            //
            //   up  <- may not occur
            //   |_____  offEnd
            //   |
            //   |_____  offStands
            //   |
            //   |
            //  down
            //

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

            Supplementary supp = new Supplementary(new Angle(offEnd, endpt.intersect, stands.intersect),
                                                   new Angle(offStands, stands.intersect, endpt.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, parallel, inter1, inter2);
        }
        // Same-Side supplementary angles if:
        //
        //   left _____________ right
        //           |     |
        //           |     |
        //          off1  off2
        //
        //     Inter 1       Inter 2
        //
        private static List<EdgeAggregator> InstantiatePiIntersection(Parallel parallel, Intersection inter1, Point off1, Intersection inter2, Point off2)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            //Segment transversal = inter1.AcquireTransversal(inter2);

            //Segment nonParallel1 = inter1.GetCollinearSegment(transversal);
            //Segment nonParallel2 = inter2.GetCollinearSegment(transversal);

            //Point left = Segment.Between(inter1.intersect, nonParallel1.Point1, inter2.intersect) ? nonParallel1.Point1 : nonParallel1.Point2;
            //Point right = Segment.Between(inter2.intersect, inter1.intersect, nonParallel2.Point1) ? nonParallel2.Point1 : nonParallel2.Point2;

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

            // CTA:
            // Hack to avoid exception during long tests.
            try
            {
                Supplementary supp = new Supplementary(new Angle(off1, inter1.intersect, inter2.intersect),
                                                       new Angle(off2, inter2.intersect, inter1.intersect));
                newSupps.Add(supp);

            } catch (Exception e)
            {
                if (Utilities.DEBUG) System.Diagnostics.Debug.WriteLine(e.ToString());

                return newGrounded;
            }

            return MakeHypergraphRelation(newSupps, parallel, inter1, inter2);
        }
        //
        // 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;
            Point sameSide = parallelTop.OtherPoint(oppSide);

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

            Supplementary supp = new Supplementary(new Angle(off, bottom.intersect, top.intersect),
                                                   new Angle(sameSide, top.intersect, bottom.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, parallel, inter1, inter2);
        }
        //
        // Creates a basic C-Shape with standsOnEndpoints
        //
        //   offThis   ______
        //                   |
        //   offThat   ______|
        //
        // Return <offThis, offThat>
        private static List<EdgeAggregator> GenerateSimpleC(Parallel parallel, Intersection inter1, Point offThis, Intersection inter2, Point offThat)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

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

            Supplementary supp = new Supplementary(new Angle(offThis, inter1.intersect, inter2.intersect),
                                                   new Angle(offThat, inter2.intersect, inter1.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, 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 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);
        }
        //                 offCross
        //                     |
        // leftCross     ______|______   rightCross
        //                     |
        // leftStands     _____|_____    rightStands
        //
        private static List<EdgeAggregator> GenerateFlying(Parallel parallel, Intersection inter1, Intersection inter2, Point offCross)
        {
            List<EdgeAggregator> newGrounded = new List<EdgeAggregator>();

            //
            // Determine which is the crossing intersection and which stands on the endpoints
            //
            Intersection crossingInter = null;
            Intersection standsInter = null;
            if (inter1.Crossing())
            {
                crossingInter = inter1;
                standsInter = inter2;
            }
            else if (inter2.Crossing())
            {
                crossingInter = inter2;
                standsInter = inter1;
            }

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

            Segment parallelStands = standsInter.OtherSegment(transversal);
            Segment parallelCrossing = crossingInter.OtherSegment(transversal);

            // Determine point orientation in the plane
            Point leftStands = parallelStands.Point1;
            Point rightStands = parallelStands.Point2;
            Point leftCross = null;
            Point rightCross = null;

            Segment crossingTester = new Segment(leftStands, parallelCrossing.Point1);
            Point intersection = transversal.FindIntersection(crossingTester);
            if (transversal.PointLiesOnAndBetweenEndpoints(intersection))
            {
                leftCross = parallelCrossing.Point2;
                rightCross = parallelCrossing.Point1;
            }
            else
            {
                leftCross = parallelCrossing.Point1;
                rightCross = parallelCrossing.Point2;
            }

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

            Supplementary supp = new Supplementary(new Angle(leftStands, standsInter.intersect, crossingInter.intersect),
                                                   new Angle(leftCross, crossingInter.intersect, standsInter.intersect));
            newSupps.Add(supp);

            supp = new Supplementary(new Angle(rightStands, standsInter.intersect, crossingInter.intersect),
                                     new Angle(rightCross, crossingInter.intersect, standsInter.intersect));
            newSupps.Add(supp);

            return MakeHypergraphRelation(newSupps, parallel, inter1, inter2);
        }
        //          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);
        }