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