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)); }
private static Polygon ActuallyConstructThePolygonObject(List <Segment> orderedSides) { // // Check for lines that are actually collinear (and can be compressed into a single segment). // bool change = true; while (change) { change = false; for (int s = 0; s < orderedSides.Count; s++) { Segment first = orderedSides[s]; Segment second = orderedSides[(s + 1) % orderedSides.Count]; Point shared = first.SharedVertex(second); // We know these lines share an endpoint and that they are collinear. if (first.IsCollinearWith(second)) { Segment newSegment = new Segment(first.OtherPoint(shared), second.OtherPoint(shared)); // Replace the two original lines with the new line. orderedSides.Insert(s, newSegment); orderedSides.Remove(first); orderedSides.Remove(second); change = true; } } } KeyValuePair <List <Point>, List <Angle> > pair = MakePointsAngle(orderedSides); // If the polygon is concave, make that object. if (IsConcavePolygon(pair.Key)) { return(new ConcavePolygon(orderedSides, pair.Key, pair.Value)); } // Otherwise, make the other polygons switch (orderedSides.Count) { case 3: return(new Triangle(orderedSides)); case 4: return(Quadrilateral.GenerateQuadrilateral(orderedSides)); default: return(new Polygon(orderedSides, pair.Key, pair.Value)); } //return null; }
public bool CoordinateAngleBisector(Segment thatSegment) { if (!thatSegment.PointLiesOnAndBetweenEndpoints(this.GetVertex())) { return(false); } if (thatSegment.IsCollinearWith(this.ray1) || thatSegment.IsCollinearWith(this.ray2)) { return(false); } Point interiorPoint = this.IsOnInteriorExplicitly(thatSegment.Point1) ? thatSegment.Point1 : thatSegment.Point2; if (!this.IsOnInteriorExplicitly(interiorPoint)) { return(false); } Angle angle1 = new Angle(A, GetVertex(), interiorPoint); Angle angle2 = new Angle(C, GetVertex(), interiorPoint); return(Utilities.CompareValues(angle1.measure, angle2.measure)); }
// // Construct the AngleBisector if we have // // V---------------A // / \ // / \ // / \ // B C // // Congruent(Angle, A, V, C), Angle(C, V, B)), Segment(V, C)) -> AngleBisector(Angle(A, V, B) // // private static List<EdgeAggregator> InstantiateToDef(CongruentAngles cas, Segment segment) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // Find the shared segment between the two angles; we know it is valid if we reach this point Segment shared = cas.AreAdjacent(); // The bisector must align with the given segment if (!segment.IsCollinearWith(shared)) return newGrounded; // We need a true bisector in which the shared vertex of the angles in between the endpoints of this segment if (!segment.PointLiesOnAndBetweenEndpoints(cas.ca1.GetVertex())) return newGrounded; // // Create the overall angle which is being bisected // Point vertex = cas.ca1.GetVertex(); Segment newRay1 = cas.ca1.OtherRayEquates(shared); Segment newRay2 = cas.ca2.OtherRayEquates(shared); Angle combinedAngle = new Angle(newRay1.OtherPoint(vertex), vertex, newRay2.OtherPoint(vertex)); // Determine if the segment is a straight angle (we don't want an angle bisector here, we would want a segment bisector) if (newRay1.IsCollinearWith(newRay2)) return newGrounded; // The bisector cannot be of the form: // \ // \ // V---------------A // / // / // B if (!combinedAngle.IsOnInteriorExplicitly(segment.Point1) && !combinedAngle.IsOnInteriorExplicitly(segment.Point2)) return newGrounded; AngleBisector newAB = new AngleBisector(combinedAngle, segment); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(segment); antecedent.Add(cas); newGrounded.Add(new EdgeAggregator(antecedent, newAB, annotation)); return newGrounded; }
public bool CoordinateAngleBisector(Segment thatSegment) { if (!thatSegment.PointLiesOnAndBetweenEndpoints(this.GetVertex())) return false; if (thatSegment.IsCollinearWith(this.ray1) || thatSegment.IsCollinearWith(this.ray2)) return false; Point interiorPoint = this.IsOnInteriorExplicitly(thatSegment.Point1) ? thatSegment.Point1 : thatSegment.Point2; if (!this.IsOnInteriorExplicitly(interiorPoint)) return false; Angle angle1 = new Angle(A, GetVertex(), interiorPoint); Angle angle2 = new Angle(C, GetVertex(), interiorPoint); return Utilities.CompareValues(angle1.measure, angle2.measure); }
private List<Atomizer.AtomicRegion> MixedArcChordedRegion(List<Circle> thatCircles, UndirectedPlanarGraph.PlanarGraph graph) { List<AtomicRegion> regions = new List<AtomicRegion>(); // Every segment may be have a set of circles. (on each side) surrounding it. // Keep parallel lists of: (1) segments, (2) (real) arcs, (3) left outer circles, and (4) right outer circles Segment[] regionsSegments = new Segment[points.Count]; Arc[] arcSegments = new Arc[points.Count]; Circle[] leftOuterCircles = new Circle[points.Count]; Circle[] rightOuterCircles = new Circle[points.Count]; // // Populate the parallel arrays. // int currCounter = 0; for (int p = 0; p < points.Count; ) { UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p], points[(p + 1) % points.Count]); Segment currSegment = new Segment(points[p], points[(p + 1) % points.Count]); // // If a known segment, seek a sequence of collinear segments. // if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_SEGMENT) { Segment actualSeg = currSegment; bool collinearExists = false; int prevPtIndex; for (prevPtIndex = p + 1; prevPtIndex < points.Count; prevPtIndex++) { // Make another segment with the next point. Segment nextSeg = new Segment(points[p], points[(prevPtIndex + 1) % points.Count]); // CTA: This criteria seems invalid in some cases....; may not have collinearity // We hit the end of the line of collinear segments. if (!currSegment.IsCollinearWith(nextSeg)) break; collinearExists = true; actualSeg = nextSeg; } // If there exists an arc over the actual segment, we have an embedded circle to consider. regionsSegments[currCounter] = actualSeg; if (collinearExists) { UndirectedPlanarGraph.PlanarGraphEdge collEdge = graph.GetEdge(actualSeg.Point1, actualSeg.Point2); if (collEdge != null) { if (collEdge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC) { // Find all applicable circles List<Circle> circles = GetAllApplicableCircles(thatCircles, actualSeg.Point1, actualSeg.Point2); // Get the exact outer circles for this segment (and create any embedded regions). regions.AddRange(ConvertToCircleCircle(actualSeg, circles, out leftOuterCircles[currCounter], out rightOuterCircles[currCounter])); } } } currCounter++; p = prevPtIndex; } else if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_DUAL) { regionsSegments[currCounter] = new Segment(points[p], points[(p + 1) % points.Count]); // Get the exact chord and set of circles Segment chord = regionsSegments[currCounter]; // Find all applicable circles List<Circle> circles = GetAllApplicableCircles(thatCircles, points[p], points[(p + 1) % points.Count]); // Get the exact outer circles for this segment (and create any embedded regions). regions.AddRange(ConvertToCircleCircle(chord, circles, out leftOuterCircles[currCounter], out rightOuterCircles[currCounter])); currCounter++; p++; } else if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC) { // // Find the unique circle that contains these two points. // (if more than one circle has these points, we would have had more intersections and it would be a direct chorded region) // List<Circle> circles = GetAllApplicableCircles(thatCircles, points[p], points[(p + 1) % points.Count]); if (circles.Count != 1) throw new Exception("Need ONLY 1 circle for REAL_ARC atom id; found (" + circles.Count + ")"); arcSegments[currCounter++] = new MinorArc(circles[0], points[p], points[(p + 1) % points.Count]); p++; } } // // Check to see if this is a region in which some connections are segments and some are arcs. // This means there were no REAL_DUAL edges. // List<AtomicRegion> generalRegions = GeneralAtomicRegion(regionsSegments, arcSegments); if (generalRegions.Any()) return generalRegions; // Copy the segments into a list (ensuring no nulls) List<Segment> actSegments = new List<Segment>(); foreach (Segment side in regionsSegments) { if (side != null) actSegments.Add(side); } // Construct a polygon out of the straight-up segments // This might be a polygon that defines a pathological region. Polygon poly = Polygon.MakePolygon(actSegments); // Determine which outermost circles apply inside of this polygon. Circle[] circlesCutInsidePoly = new Circle[actSegments.Count]; for (int p = 0; p < actSegments.Count; p++) { if (leftOuterCircles[p] != null && rightOuterCircles[p] == null) { circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, leftOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2); } else if (leftOuterCircles[p] == null && rightOuterCircles[p] != null) { circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, rightOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2); } else if (leftOuterCircles[p] != null && rightOuterCircles[p] != null) { circlesCutInsidePoly[p] = CheckCircleCutInsidePolygon(poly, leftOuterCircles[p], actSegments[p].Point1, actSegments[p].Point2); if (circlesCutInsidePoly[p] == null) circlesCutInsidePoly[p] = rightOuterCircles[p]; } else { circlesCutInsidePoly[p] = null; } } bool isStrictPoly = true; for (int p = 0; p < actSegments.Count; p++) { if (circlesCutInsidePoly[p] != null || arcSegments[p] != null) { isStrictPoly = false; break; } } // This is just a normal shape region: polygon. if (isStrictPoly) { regions.Add(new ShapeAtomicRegion(poly)); } // A circle cuts into the polygon. else { // // Now that all interior arcs have been identified, construct the atomic (probably pathological) region // AtomicRegion pathological = new AtomicRegion(); for (int p = 0; p < actSegments.Count; p++) { // // A circle cutting inside the polygon // if (circlesCutInsidePoly[p] != null) { Arc theArc = null; if (circlesCutInsidePoly[p].DefinesDiameter(regionsSegments[p])) { Point midpt = circlesCutInsidePoly[p].Midpoint(regionsSegments[p].Point1, regionsSegments[p].Point2); if (!poly.IsInPolygon(midpt)) midpt = circlesCutInsidePoly[p].OppositePoint(midpt); theArc = new Semicircle(circlesCutInsidePoly[p], regionsSegments[p].Point1, regionsSegments[p].Point2, midpt, regionsSegments[p]); } else { theArc = new MinorArc(circlesCutInsidePoly[p], regionsSegments[p].Point1, regionsSegments[p].Point2); } pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2, ConnectionType.ARC, theArc); } // else { // We have a direct arc if (arcSegments[p] != null) { pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2, ConnectionType.ARC, arcSegments[p]); } // Use the segment else { pathological.AddConnection(regionsSegments[p].Point1, regionsSegments[p].Point2, ConnectionType.SEGMENT, regionsSegments[p]); } } } regions.Add(pathological); } return regions; }