public override bool Equals(object obj) { Semicircle semi = obj as Semicircle; if (semi == null) { return(false); } return(this.diameter.Equals(semi.diameter) && this.middlePoint.Equals(semi.middlePoint) && base.Equals(obj)); }
public override bool CoordinateCongruent(Figure that) { Semicircle thatSemi = that as Semicircle; if (thatSemi == null) { return(false); } return(theCircle.CoordinateCongruent(thatSemi.theCircle)); }
// // Point must be in the given circle and then, specifically in the specified angle // public override bool PointLiesInside(Point pt) { // Is the point in the sector's circle? if (!theArc.theCircle.PointLiesInside(pt)) { return(false); } // Radii if (radius1.PointLiesOnAndBetweenEndpoints(pt)) { return(false); } if (radius2.PointLiesOnAndBetweenEndpoints(pt)) { return(false); } // // For the Minor Arc, create two angles. // The sum must equal the measure of the angle created by the endpoints. // double originalMinorMeasure = theArc.minorMeasure; double centralAngle1 = new Angle(theArc.endpoint1, theArc.theCircle.center, pt).measure; double centralAngle2 = new Angle(theArc.endpoint2, theArc.theCircle.center, pt).measure; bool isInMinorArc = Utilities.CompareValues(theArc.minorMeasure, centralAngle1 + centralAngle2); if (theArc is MinorArc) { return(isInMinorArc); } if (theArc is MajorArc) { return(!isInMinorArc); } if (theArc is Semicircle) { Semicircle semi = theArc as Semicircle; // The point in question must lie on the same side of the diameter as the middle point Segment candSeg = new Segment(pt, semi.middlePoint); Point intersection = semi.diameter.FindIntersection(candSeg); return(!candSeg.PointLiesOnAndBetweenEndpoints(intersection)); } return(false); }
public static Arc GetFigureSemicircle(Circle circle, Point pt1, Point pt2, Point middle) { Segment diameter = new Segment(pt1, pt2); Semicircle candArc = new Semicircle(circle, pt1, pt2, middle, diameter); foreach (Semicircle arc in figureSemicircles) { if (arc.StructurallyEquals(candArc)) { return(arc); } } return(null); }
// // that Polygon lies within this circle. // private bool ContainsSector(Sector that) { if (!this.PointLiesInOrOn(that.theArc.endpoint1)) { return(false); } if (!this.PointLiesInOrOn(that.theArc.endpoint2)) { return(false); } if (!this.PointLiesInOrOn(that.theArc.theCircle.center)) { return(false); } if (that.theArc is Semicircle) { Semicircle semi = that.theArc as Semicircle; if (!this.PointLiesInOrOn(semi.middlePoint)) { return(false); } if (!this.PointLiesInOrOn(semi.theCircle.Midpoint(semi.endpoint1, semi.middlePoint))) { return(false); } if (!this.PointLiesInOrOn(semi.theCircle.Midpoint(semi.endpoint2, semi.middlePoint))) { return(false); } } else { if (!this.PointLiesInOrOn(that.theArc.Midpoint())) { return(false); } } // Check all point approximations for containment. //List<Point> approx = that.GetFigureAsAtomicRegion().GetVertices(); //foreach (Point pt in approx) //{ // if (!this.PointLiesInOrOn(pt)) return false; //} return(true); }
// // Point is on the perimeter? // public override bool PointLiesOn(Point pt) { if (pt == null) { return(false); } // Radii KeyValuePair <Segment, Segment> radii = theArc.GetRadii(); if (radii.Key.PointLiesOnAndBetweenEndpoints(pt) || radii.Value.PointLiesOnAndBetweenEndpoints(pt)) { return(true); } // This point must lie on the circle in question, minimally. if (!theArc.theCircle.PointLiesOn(pt)) { return(false); } // Arc if (theArc is MajorArc) { return(Arc.BetweenMajor(pt, theArc as MajorArc)); } else if (theArc is MinorArc) { return(Arc.BetweenMinor(pt, theArc as MinorArc)); } else if (theArc is Semicircle) { Semicircle semi = theArc as Semicircle; // The point in question must lie on the same side of the diameter as the middle point Segment candSeg = new Segment(pt, semi.middlePoint); Point intersection = semi.diameter.FindIntersection(candSeg); return(!candSeg.PointLiesOnAndBetweenEndpoints(intersection)); } return(false); }
private static Arc GetInscribedInterceptedArc(Circle circle, Angle angle) { Point endpt1, endpt2; Point pt1, pt2; circle.FindIntersection(angle.ray1, out pt1, out pt2); endpt1 = pt1.StructurallyEquals(angle.GetVertex()) ? pt2 : pt1; circle.FindIntersection(angle.ray2, out pt1, out pt2); endpt2 = pt1.StructurallyEquals(angle.GetVertex()) ? pt2 : pt1; // Need to check if the angle is a diameter and create a semicircle Segment chord = new Segment(endpt1, endpt2); if (circle.DefinesDiameter(chord)) { Point opp = circle.Midpoint(endpt1, endpt2, angle.GetVertex()); Semicircle semi = new Semicircle(circle, endpt1, endpt2, circle.OppositePoint(opp), chord); //Find a defined semicircle of the figure that lies on the same side Semicircle sameSideSemi = figureSemicircles.Where(s => semi.SameSideSemicircle(s)).FirstOrDefault(); //If none were found, should we throw an exception or just return the original semi? if (sameSideSemi == null) { return(semi); } else { return(sameSideSemi); } } //Initially assume intercepted arc is the minor arc Arc intercepted = null; intercepted = new MinorArc(circle, endpt1, endpt2); //Verify assumption, create major arc if necessary if (Arc.BetweenMinor(angle.GetVertex(), intercepted)) { intercepted = new MajorArc(circle, endpt1, endpt2); } return(intercepted); }
public override bool HasSubArc(Arc that) { if (!this.theCircle.StructurallyEquals(that.theCircle)) { return(false); } if (that is MajorArc) { return(this.HasMajorSubArc(that)); } if (that is Semicircle) { Semicircle semi = that as Semicircle; return(this.HasMinorSubArc(new MinorArc(semi.theCircle, semi.endpoint1, semi.middlePoint)) && this.HasMinorSubArc(new MinorArc(semi.theCircle, semi.endpoint2, semi.middlePoint))); } return(this.HasMinorSubArc(that)); }
public bool SameSideSemicircle(Semicircle thatSemi) { // First, the endpoints and the diameter must match if (!(this.diameter.StructurallyEquals(thatSemi.diameter) && base.StructurallyEquals(thatSemi))) { return(false); } // if either of the 2 minor arcs formed by this semicircle's middlepoint contain the middlepoint of thatSemi, // then the two semicircles form the same 'side' of the circle MinorArc m = new MinorArc(this.theCircle, this.endpoint1, this.middlePoint); MinorArc m2 = new MinorArc(this.theCircle, this.middlePoint, this.endpoint2); if (Arc.BetweenMinor(thatSemi.middlePoint, m) || Arc.BetweenMinor(thatSemi.middlePoint, m2)) { return(true); } else { return(false); } }
// Construct the region between a circle and circle: // __ // ( ( // ( ( // ( ( // ( ( // ( ( // -- private Atomizer.AtomicRegion ConstructBasicCircleCircleRegion(Segment chord, Circle smaller, Circle larger) { AtomicRegion region = new AtomicRegion(); Arc arc1 = null; if (smaller.DefinesDiameter(chord)) { Point midpt = smaller.Midpoint(chord.Point1, chord.Point2, larger.Midpoint(chord.Point1, chord.Point2)); arc1 = new Semicircle(smaller, chord.Point1, chord.Point2, midpt, chord); } else { arc1 = new MinorArc(smaller, chord.Point1, chord.Point2); } MinorArc arc2 = new MinorArc(larger, chord.Point1, chord.Point2); region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, arc1); region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, arc2); return region; }
// // Detect diameters and generate all of the Semicircle Arc and ArcInMiddle clauses // private void GenerateSemicircleClauses(Circle circle) { if (circle.pointsOnCircle.Count == 2) { Segment diameter = new Segment(circle.pointsOnCircle[0], circle.pointsOnCircle[1]); if (circle.DefinesDiameter(diameter)) { Point midpt = circle.Midpoint(diameter.Point1, diameter.Point2); Point opp = circle.OppositePoint(midpt); AddSemicircleClauses(new Semicircle(circle, diameter.Point1, diameter.Point2, midpt, diameter)); AddSemicircleClauses(new Semicircle(circle, diameter.Point1, diameter.Point2, opp, diameter)); } } for (int p1 = 0; p1 < circle.pointsOnCircle.Count - 1; p1++) { for (int p2 = p1 + 1; p2 < circle.pointsOnCircle.Count; p2++) { Segment diameter = new Segment(circle.pointsOnCircle[p1], circle.pointsOnCircle[p2]); if (circle.DefinesDiameter(diameter)) { //Get the endpoints of the diameter and the indices of these endpoints Point e1 = diameter.Point1; Point e2 = diameter.Point2; //int p1 = circle.pointsOnCircle.IndexOf(e1); //int p2 = circle.pointsOnCircle.IndexOf(e2); ////For partitioning purposes, order of the endpoints matters. Make sure p1 holds the lower of the two indices //if (p1 > p2) //{ // int p3 = p1; // p1 = p2; // p2 = p3; //} // Partition the remaining points on the circle List<Point> minorArcPoints; List<Point> majorArcPoints; PartitionSemiCircleArcPoints(circle.pointsOnCircle, p1, p2, out minorArcPoints, out majorArcPoints); // Semicircle requires 3 points to be defined - the two endpoints and a point inbetween // The minorArcPoints and majorArcPoints lists contain all the potential inbetween points for either side of the diameter // Handle 'side' 1: // If majorArcPoints is empty, create an implied semicircle (minorArcPoints should be guaranteed to have at least one point, since // the case of having only 2 points on the circle was already handled) if (majorArcPoints.Count == 0 && minorArcPoints.Count != 0) AddSemicircleClauses(CreateImpliedSemicircle(circle, diameter, minorArcPoints[0])); else for (int i = 0; i < majorArcPoints.Count; ++i) { Semicircle semi = new Semicircle(circle, e1, e2, majorArcPoints[i], minorArcPoints, majorArcPoints, diameter); AddSemicircleClauses(semi); } // Handle 'side' 2: if (minorArcPoints.Count == 0 && majorArcPoints.Count != 0) AddSemicircleClauses(CreateImpliedSemicircle(circle, diameter, majorArcPoints[0])); else for (int i = 0; i < minorArcPoints.Count; ++i) { Semicircle semi = new Semicircle(circle, e1, e2, minorArcPoints[i], majorArcPoints, minorArcPoints, diameter); AddSemicircleClauses(semi); } } } } }
private Semicircle CreateImpliedSemicircle(Circle circle, Segment diameter, Point oppositePnt) { Point midpt = circle.Midpoint(diameter.Point1, diameter.Point2); //Create semicircles from the midpt and the given oppositePnt, make sure they do not form the same side Semicircle semi1 = new Semicircle(circle, diameter.Point1, diameter.Point2, midpt, diameter); if (semi1.SameSideSemicircle(new Semicircle(circle, diameter.Point1, diameter.Point2, oppositePnt, diameter))) { semi1 = new Semicircle(circle, diameter.Point1, diameter.Point2, circle.OppositePoint(midpt), diameter); } return semi1; }
private void AddSemicircleClauses(Semicircle semi) { if (!GeometryTutorLib.Utilities.HasStructurally<Semicircle>(semiCircles, semi)) { semiCircles.Add(semi); semicircleSectors.Add(new Sector(semi)); } //Add arcInMiddle //For semicircles, only considering the defining middle point as an inMiddle point //This is to avoid arc equations such as MinorArc(RX) + MinorArc(XT) = Semicircle(RST), which might not make sense to a user GeometryTutorLib.Utilities.AddStructurallyUnique<ArcInMiddle>(arcInMiddle, new ArcInMiddle(semi.middlePoint, semi)); }
// // C // |\ // | \ // | \ // | O // | \ // |_ \ // A |_|____\ B // // SemiCircle(O, BC), Angle(BAC) -> RightAngle(BAC) // public static List<EdgeAggregator> InstantiateTheorem(Semicircle semi, Angle angle, GroundedClause original) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // The angle needs to be inscribed in the given semicircle // Note: Previously this was checked indirectly by verifying that the angle intercepts a semicircle, but since semicircles now // require 3 points to be defined, it is safer to directly verify that the angle is inscribed in the semicircle. // (There may not have been any points defined on the other side of the diameter, // meaning there would not actually be any defined semicircles which the angle intercepts). if (!semi.AngleIsInscribed(angle)) return newGrounded; Strengthened newRight = new Strengthened(angle, new RightAngle(angle)); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(original); antecedent.Add(angle); newGrounded.Add(new EdgeAggregator(antecedent, newRight, annotation)); return newGrounded; }
// Construct the region between a chord and the circle arc: // (| // ( | // ( | // ( | // (| // private List<AtomicRegion> ConstructBasicLineCircleRegion(Segment chord, Circle circle) { // // Standard // if (!circle.DefinesDiameter(chord)) { AtomicRegion region = new AtomicRegion(); Arc theArc = new MinorArc(circle, chord.Point1, chord.Point2); region.AddConnection(chord.Point1, chord.Point2, ConnectionType.ARC, theArc); region.AddConnection(chord.Point1, chord.Point2, ConnectionType.SEGMENT, chord); return Utilities.MakeList<AtomicRegion>(region); } // // Semi-circles // Point midpt = circle.Midpoint(chord.Point1, chord.Point2); Arc semi1 = new Semicircle(circle, chord.Point1, chord.Point2, midpt, chord); ShapeAtomicRegion region1 = new ShapeAtomicRegion(new Sector(semi1)); Point opp = circle.OppositePoint(midpt); Arc semi2 = new Semicircle(circle, chord.Point1, chord.Point2, opp, chord); ShapeAtomicRegion region2 = new ShapeAtomicRegion(new Sector(semi2)); List<AtomicRegion> regions = new List<AtomicRegion>(); regions.Add(region1); regions.Add(region2); return regions; }
// // C // /) // / ) // / ) // / ) // A /)_________ B // // Tangent(Circle(O), Segment(AB)), Intersection(Segment(AC), Segment(AB)) -> 2 * Angle(CAB) = Arc(C, B) // public static List<EdgeAggregator> InstantiateTheorem(Intersection inter, Tangent tangent, GroundedClause original) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); CircleSegmentIntersection tan = tangent.intersection as CircleSegmentIntersection; // // Does this tangent apply to this intersection? // if (!inter.intersect.StructurallyEquals(tangent.intersection.intersect)) return newGrounded; Segment secant = null; Segment tanSegment = null; if (tan.HasSegment(inter.lhs)) { secant = inter.rhs; tanSegment = inter.lhs; } else if (tan.HasSegment(inter.rhs)) { secant = inter.lhs; tanSegment = inter.rhs; } else return newGrounded; // // Acquire the angle and intercepted arc. // Segment chord = tan.theCircle.GetChord(secant); if (chord == null) return newGrounded; //Segment chord = tan.theCircle.ContainsChord(secant); // Arc // We want the MINOR ARC only! if (tan.theCircle.DefinesDiameter(chord)) { Arc theArc = null; Point midpt = PointFactory.GeneratePoint(tan.theCircle.Midpoint(chord.Point1, chord.Point2)); Point opp = PointFactory.GeneratePoint(tan.theCircle.OppositePoint(midpt)); Point tanPoint = tanSegment.OtherPoint(inter.intersect); if (tanPoint != null) { // Angle; the smaller angle is always the chosen angle Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanPoint); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); } else { // Angle; the smaller angle is always the chosen angle Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point1); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); // Angle; the smaller angle is always the chosen angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point2); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, midpt, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); theArc = new Semicircle(tan.theCircle, chord.Point1, chord.Point2, opp, chord); newGrounded.Add(CreateClause(inter, original, theAngle, theArc)); } } else { Arc theArc = new MinorArc(tan.theCircle, chord.Point1, chord.Point2); // Angle; the smaller angle is always the chosen angle Point endPnt = (inter.intersect.StructurallyEquals(tanSegment.Point1)) ? tanSegment.Point2 : tanSegment.Point1; Angle theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, endPnt); if (theAngle.measure > 90) { //If the angle endpoint was already set to Point2, or if the intersect equals Point2, then the smaller angle does not exist //In this case, should we create a major arc or return nothing? if (endPnt.StructurallyEquals(tanSegment.Point2) || inter.intersect.StructurallyEquals(tanSegment.Point2)) return newGrounded; theAngle = new Angle(chord.OtherPoint(inter.intersect), inter.intersect, tanSegment.Point2); } Multiplication product = new Multiplication(new NumericValue(2), theAngle); GeometricAngleArcEquation angArcEq = new GeometricAngleArcEquation(product, theArc); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(original); antecedent.Add(inter); antecedent.Add(theArc); antecedent.Add(theAngle); newGrounded.Add(new EdgeAggregator(antecedent, angArcEq, annotation)); } return newGrounded; }
private List<Atomizer.AtomicRegion> ConvertToSemicircle(Segment diameter, Semicircle semi) { // Verification Step 2. if (!diameter.PointLiesOnAndExactlyBetweenEndpoints(semi.theCircle.center)) { throw new Exception("Semicircle: expected center between endpoints."); } Sector sector = new Sector(semi); return Utilities.MakeList<AtomicRegion>(new ShapeAtomicRegion(sector)); }
public static Arc GetFigureSemicircle(Circle circle, Point pt1, Point pt2, Point middle) { Segment diameter = new Segment(pt1, pt2); Semicircle candArc = new Semicircle(circle, pt1, pt2, middle, diameter); foreach (Semicircle arc in figureSemicircles) { if (arc.StructurallyEquals(candArc)) return arc; } return null; }
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; }
private static Arc GetInscribedInterceptedArc(Circle circle, Angle angle) { Point endpt1, endpt2; Point pt1, pt2; circle.FindIntersection(angle.ray1, out pt1, out pt2); endpt1 = pt1.StructurallyEquals(angle.GetVertex()) ? pt2 : pt1; circle.FindIntersection(angle.ray2, out pt1, out pt2); endpt2 = pt1.StructurallyEquals(angle.GetVertex()) ? pt2 : pt1; // Need to check if the angle is a diameter and create a semicircle Segment chord = new Segment(endpt1, endpt2); if (circle.DefinesDiameter(chord)) { Point opp = circle.Midpoint(endpt1, endpt2, angle.GetVertex()); Semicircle semi = new Semicircle(circle, endpt1, endpt2, circle.OppositePoint(opp), chord); //Find a defined semicircle of the figure that lies on the same side Semicircle sameSideSemi = figureSemicircles.Where(s => semi.SameSideSemicircle(s)).FirstOrDefault(); //If none were found, should we throw an exception or just return the original semi? if (sameSideSemi == null) return semi; else return sameSideSemi; } //Initially assume intercepted arc is the minor arc Arc intercepted = null; intercepted = new MinorArc(circle, endpt1, endpt2); //Verify assumption, create major arc if necessary if (Arc.BetweenMinor(angle.GetVertex(), intercepted)) intercepted = new MajorArc(circle, endpt1, endpt2); return intercepted; }
public bool SameSideSemicircle(Semicircle thatSemi) { // First, the endpoints and the diameter must match if (!(this.diameter.StructurallyEquals(thatSemi.diameter) && base.StructurallyEquals(thatSemi))) return false; // if either of the 2 minor arcs formed by this semicircle's middlepoint contain the middlepoint of thatSemi, // then the two semicircles form the same 'side' of the circle MinorArc m = new MinorArc(this.theCircle, this.endpoint1, this.middlePoint); MinorArc m2 = new MinorArc(this.theCircle, this.middlePoint, this.endpoint2); if (Arc.BetweenMinor(thatSemi.middlePoint, m) || Arc.BetweenMinor(thatSemi.middlePoint, m2)) return true; else return false; }