Exemple #1
0
        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));
        }
Exemple #2
0
        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;
        }
Exemple #3
0
        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;
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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;
        }