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;
        }
        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;
        }