Пример #1
0
        //
        // Based on the two points, extract the circle which results in the connection (if the connection exists).
        //
        private List <AtomicRegion> HandleConnection(UndirectedPlanarGraph.PlanarGraph graph, List <Circle> circles, Point pt1, Point pt2)
        {
            List <AtomicRegion> atoms = new List <AtomicRegion>();

            UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(pt1, pt2);

            if (edge == null)
            {
                return(atoms);
            }

            //
            // Find the one circle that applies to this set of points.
            //
            Circle theCircle = null;

            foreach (Circle circle in circles)
            {
                if (circle.PointLiesOn(pt1) && circle.PointLiesOn(pt2))
                {
                    theCircle = circle;
                }
            }

            switch (edge.edgeType)
            {
            case UndirectedPlanarGraph.EdgeType.REAL_ARC:
            case UndirectedPlanarGraph.EdgeType.REAL_DUAL:
                atoms.AddRange(CreateSectors(theCircle, pt1, pt2));
//                    atoms.AddRange(CreateSemiCircleRegions());
                break;
            }

            return(atoms);
        }
Пример #2
0
        //
        // Collect all arcs attributed to this this cycle;
        //
        private List <MinorArc> CollectStrictArcs(List <Circle> circles, UndirectedPlanarGraph.PlanarGraph graph)
        {
            List <MinorArc> minors = new List <MinorArc>();

            for (int p = 0; p < points.Count; p++)
            {
                UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p], points[(p + 1) % points.Count]);

                if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC)
                {
                    // Find the applicable circle.
                    Circle theCircle = null;
                    foreach (Circle circle in circles)
                    {
                        if (circle.HasArc(points[p], points[(p + 1) % points.Count]))
                        {
                            theCircle = circle;
                            break;
                        }
                    }

                    minors.Add(new MinorArc(theCircle, points[p], points[(p + 1) % points.Count]));
                }
            }

            return(minors);
        }
Пример #3
0
        //
        // Extract the atomic regions.
        //
        public List <AtomicRegion> ExtractAtomicRegions(UndirectedPlanarGraph.PlanarGraph graph, List <Circle> circles)
        {
            memoized = new Agg[points.Count, points.Count];

            // Recursively construct.
            return(MakeRegions(graph, circles, 0, points.Count - 1).atoms);
        }
        //
        // Take the cycle-based representation and convert in into AtomicRegion objects.
        //
        public static List <AtomicRegion> Convert(UndirectedPlanarGraph.PlanarGraph graph,
                                                  List <Primitive> primitives, List <Circle> circles)
        {
            List <MinimalCycle> cycles    = new List <MinimalCycle>();
            List <Filament>     filaments = new List <Filament>();

            foreach (Primitive primitive in primitives)
            {
                if (primitive is MinimalCycle)
                {
                    cycles.Add(primitive as MinimalCycle);
                }
                if (primitive is Filament)
                {
                    filaments.Add(primitive as Filament);
                }
            }

            //
            // Convert the filaments to atomic regions.
            //
            List <AtomicRegion> regions = new List <AtomicRegion>();

            if (filaments.Any())
            {
                throw new Exception("A filament occurred in conversion to atomic regions.");
            }
            // regions.AddRange(HandleFilaments(graph, circles, filaments));



            ComposeCycles(graph, cycles);

            if (GeometryTutorLib.Utilities.ATOMIC_REGION_GEN_DEBUG)
            {
                Debug.WriteLine("Composed:");
                foreach (MinimalCycle cycle in cycles)
                {
                    Debug.WriteLine("\t" + cycle.ToString());
                }
            }

            //
            // Convert all cycles (perimeters) to atomic regions
            //
            foreach (MinimalCycle cycle in cycles)
            {
                List <AtomicRegion> temp = cycle.ConstructAtomicRegions(circles, graph);
                foreach (AtomicRegion atom in temp)
                {
                    if (!regions.Contains(atom))
                    {
                        regions.Add(atom);
                    }
                }
            }

            return(regions);
        }
Пример #5
0
 //
 // Shallow copy constructor
 //
 public PlanarGraph(PlanarGraph thatG)
     : this()
 {
     foreach (PlanarGraphNode node in thatG.nodes)
     {
         nodes.Add(new PlanarGraphNode(node));
     }
 }
        //
        // A filament is a path from one node to another; it does not invoke a cycle.
        // In shaded-area problems this can only be accomplished with arcs of circles.
        //
        private static List <AtomicRegion> HandleFilaments(UndirectedPlanarGraph.PlanarGraph graph, List <Circle> circles, List <Filament> filaments)
        {
            List <AtomicRegion> atoms = new List <AtomicRegion>();

            foreach (Filament filament in filaments)
            {
                atoms.AddRange(filament.ExtractAtomicRegions(graph, circles));
            }

            return(atoms);
        }
 private static int HasComposableCycle(UndirectedPlanarGraph.PlanarGraph graph, List <MinimalCycle> cycles)
 {
     for (int c = 0; c < cycles.Count; c++)
     {
         if (cycles[c].HasExtendedSegment(graph))
         {
             return(c);
         }
     }
     return(-1);
 }
Пример #8
0
        public Segment GetExtendedSegment(UndirectedPlanarGraph.PlanarGraph graph)
        {
            for (int p = 0; p < points.Count; p++)
            {
                if (graph.GetEdgeType(points[p], points[(p + 1) % points.Count]) == UndirectedPlanarGraph.EdgeType.EXTENDED_SEGMENT)
                {
                    return(new Segment(points[p], points[p + 1 < points.Count ? p + 1 : 0]));
                }
            }

            return(null);
        }
Пример #9
0
        public FacetCalculator(UndirectedPlanarGraph.PlanarGraph g)
        {
            graph = g;

            if (Utilities.ATOMIC_REGION_GEN_DEBUG)
            {
                Debug.WriteLine(graph);
            }

            primitives = new List<Primitive>();

            ExtractPrimitives();
        }
Пример #10
0
        public FacetCalculator(UndirectedPlanarGraph.PlanarGraph g)
        {
            graph = g;

            if (Utilities.ATOMIC_REGION_GEN_DEBUG)
            {
                Debug.WriteLine(graph);
            }

            primitives = new List <Primitive>();

            ExtractPrimitives();
        }
Пример #11
0
        public bool HasThisExtendedSegment(UndirectedPlanarGraph.PlanarGraph graph, Segment segment)
        {
            if (!points.Contains(segment.Point1))
            {
                return(false);
            }
            if (!points.Contains(segment.Point2))
            {
                return(false);
            }

            return(graph.GetEdgeType(segment.Point1, segment.Point2) == UndirectedPlanarGraph.EdgeType.EXTENDED_SEGMENT);
        }
Пример #12
0
        private Atomizer.AtomicRegion PolygonDefinesRegion(UndirectedPlanarGraph.PlanarGraph graph)
        {
            List <Segment> sides = new List <Segment>();

            //
            // All connections between adjacent connections MUST be segments.
            //
            for (int p = 0; p < points.Count; p++)
            {
                Segment segment = new Segment(points[p], points[(p + 1) % points.Count]);

                sides.Add(segment);

                if (graph.GetEdge(points[p], points[(p + 1) % points.Count]).edgeType != UndirectedPlanarGraph.EdgeType.REAL_SEGMENT)
                {
                    return(null);
                }
            }

            //
            // All iterative connections cannot be arcs.
            //
            for (int p1 = 0; p1 < points.Count - 1; p1++)
            {
                // We want to check for a direct cycle, therefore, p2 starts at p1 not p1 + 1
                for (int p2 = p1; p2 < points.Count; p2++)
                {
                    UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p1], points[(p2 + 1) % points.Count]);

                    if (edge != null)
                    {
                        if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_ARC)
                        {
                            return(null);
                        }
                    }
                }
            }

            //
            // Make the Polygon
            //
            Polygon poly = Polygon.MakePolygon(sides);

            if (poly == null)
            {
                throw new ArgumentException("Real segments should define a polygon; they did not.");
            }

            return(new ShapeAtomicRegion(poly));
        }
        private static int GetComposableCycleWithSegment(UndirectedPlanarGraph.PlanarGraph graph,
                                                         List <MinimalCycle> cycles,
                                                         GeometryTutorLib.ConcreteAST.Segment segment)
        {
            for (int c = 0; c < cycles.Count; c++)
            {
                if (cycles[c].HasThisExtendedSegment(graph, segment))
                {
                    return(c);
                }
            }

            return(-1);
        }
Пример #14
0
        //
        // Collect all segments attributed to this this cycle
        //
        private List <Segment> CollectSegments(UndirectedPlanarGraph.PlanarGraph graph)
        {
            List <Segment> segments = new List <Segment>();

            for (int p = 0; p < points.Count; p++)
            {
                UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p], points[(p + 1) % points.Count]);

                if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_SEGMENT)
                {
                    segments.Add(new Segment(points[p], points[(p + 1) % points.Count]));
                }
            }

            return(segments);
        }
Пример #15
0
        ////
        //// Determine the number of intersection points between this atomic region and a segment.
        ////
        //public List<KeyValuePair<Point, Connection>> GetIntersections(Circle circle, Point endpt1, Point endp12)
        //{
        //    List<KeyValuePair<Point, Connection>> intersections = new List<KeyValuePair<Point, Connection>>();
        //    Point pt1 = null;
        //    Point pt2 = null;

        //    foreach (Connection conn in connections)
        //    {
        //        conn.FindIntersection(that, out pt1, out pt2);
        //        if (pt1 != null) intersections.Add(new KeyValuePair<Point, Connection>(pt1, conn));
        //        if (pt2 != null) intersections.Add(new KeyValuePair<Point, Connection>(pt2, conn));

        //        // A segment should only intersect an atomic region in 2 places.
        //        if (intersections.Count >= 2) break;
        //    }

        //    return intersections;
        //}

        //
        // Convert an atomic region to a planar graph.
        //
        public UndirectedPlanarGraph.PlanarGraph ConvertToPlanarGraph()
        {
            UndirectedPlanarGraph.PlanarGraph graph = new UndirectedPlanarGraph.PlanarGraph();

            if (!ordered)
            {
                OrderConnections();
            }

            //
            // Traverse the connections and add vertices / edges
            //
            foreach (Connection conn in connections)
            {
                graph.AddNode(conn.endpoint1);
                graph.AddNode(conn.endpoint2);

                graph.AddUndirectedEdge(conn.endpoint1, conn.endpoint2,
                                        new Segment(conn.endpoint1, conn.endpoint2).Length,
                                        conn.type == ConnectionType.ARC ? UndirectedPlanarGraph.EdgeType.REAL_ARC : UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
            }

            return(graph);
        }
        //
        // If a cycle has an edge that is EXTENDED, there exist two regions, one on each side of the segment; compose the two segments.
        //
        // Fixed point algorithm: while there exists a cycle with an extended segment, compose.
        private static void ComposeCycles(UndirectedPlanarGraph.PlanarGraph graph, List <MinimalCycle> cycles)
        {
            for (int cycleIndex = HasComposableCycle(graph, cycles); cycleIndex != -1; cycleIndex = HasComposableCycle(graph, cycles))
            {
                // Get the cycle and remove it from the list.
                MinimalCycle thisCycle = cycles[cycleIndex];

                cycles.RemoveAt(cycleIndex);

                // Get the extended segment which is the focal segment of composition.
                GeometryTutorLib.ConcreteAST.Segment extendedSeg = thisCycle.GetExtendedSegment(graph);

                // Find the matching cycle that has the same Extended segment
                int          otherIndex = GetComposableCycleWithSegment(graph, cycles, extendedSeg);
                MinimalCycle otherCycle = cycles[otherIndex];
                cycles.RemoveAt(otherIndex);

                // Compose the two cycles into a single cycle.
                MinimalCycle composed = thisCycle.Compose(otherCycle, extendedSeg);

                // Add the new, composed cycle
                cycles.Add(composed);
            }
        }
Пример #17
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);
        }
Пример #18
0
 public bool HasExtendedSegment(UndirectedPlanarGraph.PlanarGraph graph)
 {
     return(GetExtendedSegment(graph) != null);
 }
Пример #19
0
        private List <Atomizer.AtomicRegion> SectorOrTruncationDefinesRegion(List <Circle> circles, UndirectedPlanarGraph.PlanarGraph graph)
        {
            //
            // Do there exist any real-dual edges or extended segments? If so, this is not a sector.
            //
            for (int p = 0; p < points.Count; p++)
            {
                UndirectedPlanarGraph.PlanarGraphEdge edge = graph.GetEdge(points[p], points[(p + 1) % points.Count]);

                if (edge.edgeType == UndirectedPlanarGraph.EdgeType.EXTENDED_SEGMENT)
                {
                    return(null);
                }
                else if (edge.edgeType == UndirectedPlanarGraph.EdgeType.REAL_DUAL)
                {
                    return(null);
                }
            }

            //
            // Collect all segments; split into two collinear lists.
            //
            List <Segment>         segments            = CollectSegments(graph);
            List <List <Segment> > collinearSegmentSet = SplitSegmentsIntoCollinearSequences(segments);

            // A sector requires one (semicircl) or two sets of segments ('normal' arc).
            if (collinearSegmentSet.Count > 2)
            {
                return(null);
            }

            //
            // Collect all arcs.
            //
            List <MinorArc>         arcs            = CollectStrictArcs(circles, graph);
            List <List <MinorArc> > collinearArcSet = SplitArcsIntoCollinearSequences(arcs);

            // A sector requires one set of arcs (no more, no less).
            if (collinearArcSet.Count != 1)
            {
                return(null);
            }

            // Semicircle has one set of sides
            if (collinearSegmentSet.Count == 1)
            {
                return(ConvertToTruncationOrSemicircle(collinearSegmentSet[0], collinearArcSet[0]));
            }

            // Pacman shape created with a circle results in Sector
            return(ConvertToGeneralSector(collinearSegmentSet[0], collinearSegmentSet[1], collinearArcSet[0]));
        }
Пример #20
0
        //
        //
        // Create the actual set of atomic regions for this cycle.
        //
        //   We need to check to see if any of the cycle segments are based on arcs.
        //   We have to handle the degree of each segment: do many circles intersect at these points?
        //
        public List <Atomizer.AtomicRegion> ConstructAtomicRegions(List <Circle> circles, UndirectedPlanarGraph.PlanarGraph graph)
        {
            List <Atomizer.AtomicRegion> regions = new List <Atomizer.AtomicRegion>();

            Atomizer.AtomicRegion region = null;

            //
            // Check for a direct polygon (no arcs).
            //
            region = PolygonDefinesRegion(graph);
            if (region != null)
            {
                regions.Add(region);
                return(regions);
            }

            //
            // Does this region define a sector?
            //
            List <AtomicRegion> sectors = SectorOrTruncationDefinesRegion(circles, graph);

            if (sectors != null && sectors.Any())
            {
                regions.AddRange(sectors);
                return(regions);
            }

            //
            // Do we have a set of regions defined by a polygon in which circle(s) cut out some of that region?
            //
            regions.AddRange(MixedArcChordedRegion(circles, graph));

            return(regions);
        }
Пример #21
0
        ////
        //// Determine the number of intersection points between this atomic region and a segment.
        ////
        //public List<KeyValuePair<Point, Connection>> GetIntersections(Circle circle, Point endpt1, Point endp12)
        //{
        //    List<KeyValuePair<Point, Connection>> intersections = new List<KeyValuePair<Point, Connection>>();
        //    Point pt1 = null;
        //    Point pt2 = null;
        //    foreach (Connection conn in connections)
        //    {
        //        conn.FindIntersection(that, out pt1, out pt2);
        //        if (pt1 != null) intersections.Add(new KeyValuePair<Point, Connection>(pt1, conn));
        //        if (pt2 != null) intersections.Add(new KeyValuePair<Point, Connection>(pt2, conn));
        //        // A segment should only intersect an atomic region in 2 places.
        //        if (intersections.Count >= 2) break;
        //    }
        //    return intersections;
        //}
        //
        // Convert an atomic region to a planar graph.
        //
        public UndirectedPlanarGraph.PlanarGraph ConvertToPlanarGraph()
        {
            UndirectedPlanarGraph.PlanarGraph graph = new UndirectedPlanarGraph.PlanarGraph();

            if (!ordered) OrderConnections();

            //
            // Traverse the connections and add vertices / edges
            //
            foreach (Connection conn in connections)
            {
                graph.AddNode(conn.endpoint1);
                graph.AddNode(conn.endpoint2);

                graph.AddUndirectedEdge(conn.endpoint1, conn.endpoint2,
                                        new Segment(conn.endpoint1, conn.endpoint2).Length,
                                        conn.type == ConnectionType.ARC ? UndirectedPlanarGraph.EdgeType.REAL_ARC : UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
            }

            return graph;
        }
Пример #22
0
        //
        // The order of the points in the filament were established by the algorithm
        // Recursively seek smaller and smaller circular regions.
        //
        // Returns the set of atomic regions characterized by the largest circle (containing all the other atoms).
        private Agg MakeRegions(UndirectedPlanarGraph.PlanarGraph graph, List <Circle> circles, int beginIndex, int endIndex)
        {
            if (memoized[beginIndex, endIndex] != null)
            {
                return(memoized[beginIndex, endIndex]);
            }

            //
            // Find the circle for these given points.
            //
            Circle outerCircle = null;

            foreach (Circle circle in circles)
            {
                if (circle.PointLiesOn(points[beginIndex]) && circle.PointLiesOn(points[endIndex]))
                {
                    outerCircle = circle;
                }
            }

            //
            // Base Case: Gap between the given indices is 1.
            //
            if (endIndex - beginIndex == 1)
            {
                return(new Agg(beginIndex, endIndex, -1, outerCircle, HandleConnection(graph, circles, points[beginIndex], points[endIndex])));
            }

            //
            // Look at all combinations of indices from beginIndex to endIndex; start with larger gaps between indices -> small gaps
            //
            Agg maxLeftCoveredAgg  = null;
            Agg maxRightCoveredAgg = null;
            int maxCoveredNodes    = 0;

            for (int gap = endIndex - beginIndex - 1; gap > 0; gap--)
            {
                for (int index = beginIndex; index < endIndex; index++)
                {
                    Agg left  = MakeRegions(graph, circles, index, index + gap);
                    Agg right = MakeRegions(graph, circles, index + gap, endIndex);

                    // Check for new maxmimum coverage.
                    if (left.coveredPoints + right.coveredPoints > maxCoveredNodes)
                    {
                        maxLeftCoveredAgg  = left;
                        maxRightCoveredAgg = right;
                    }

                    // Found complete coverage
                    if (left.coveredPoints + right.coveredPoints == endIndex - beginIndex + 1)
                    {
                        maxCoveredNodes = endIndex - beginIndex + 1;
                        break;
                    }
                }
            }

            //
            // We have the two maximal circles: create the new regions.
            //
            // The atoms from the left / right.
            List <AtomicRegion> atoms = new List <AtomicRegion>();

            atoms.AddRange(maxLeftCoveredAgg.atoms);
            atoms.AddRange(maxRightCoveredAgg.atoms);

            // New regions are based on this outer circle minus the left / right outer circles.
            AtomicRegion newAtomTop    = new AtomicRegion();
            AtomicRegion newAtomBottom = new AtomicRegion();

            // The outer circle.
            newAtomTop.AddConnection(points[beginIndex], points[endIndex], ConnectionType.ARC, outerCircle);
            newAtomBottom.AddConnection(points[beginIndex], points[endIndex], ConnectionType.ARC, outerCircle);

            // The left / right maximal circles.
            newAtomTop.AddConnection(points[maxLeftCoveredAgg.beginPointIndex], points[maxLeftCoveredAgg.endPointIndex], ConnectionType.ARC, maxLeftCoveredAgg.outerCircle);
            newAtomBottom.AddConnection(points[maxLeftCoveredAgg.beginPointIndex], points[maxLeftCoveredAgg.endPointIndex], ConnectionType.ARC, maxLeftCoveredAgg.outerCircle);

            newAtomTop.AddConnection(points[maxRightCoveredAgg.beginPointIndex], points[maxRightCoveredAgg.endPointIndex], ConnectionType.ARC, maxRightCoveredAgg.outerCircle);
            newAtomBottom.AddConnection(points[maxRightCoveredAgg.beginPointIndex], points[maxRightCoveredAgg.endPointIndex], ConnectionType.ARC, maxRightCoveredAgg.outerCircle);

            atoms.Add(newAtomTop);
            atoms.Add(newAtomBottom);

            //
            // Make / return the new aggregator
            //
            return(new Agg(beginIndex, endIndex, maxCoveredNodes, outerCircle, atoms));
        }