예제 #1
0
        public List<Area_Based_Analyses.Atomizer.AtomicRegion> Atomize(List<Point> figurePoints)
        {
            List<Segment> constructedChords = new List<Segment>();
            List<Segment> constructedRadii = new List<Segment>();
            List<Point> imagPoints = new List<Point>();

            List<Point> interPts = GetIntersectingPoints();

            //
            // Construct the radii
            //
            switch (interPts.Count)
            {
                // If there are no points of interest, the circle is the atomic region.
                case 0:
                  return Utilities.MakeList<AtomicRegion>(new ShapeAtomicRegion(this));

                // If only 1 intersection point, create the diameter.
                case 1:
                  Point opp = Utilities.AcquirePoint(figurePoints, this.OppositePoint(interPts[0]));
                  constructedRadii.Add(new Segment(center, interPts[0]));
                  constructedRadii.Add(new Segment(center, opp));
                  imagPoints.Add(opp);
                  interPts.Add(opp);
                  break;

                default:
                  foreach (Point interPt in interPts)
                  {
                      constructedRadii.Add(new Segment(center, interPt));
                  }
                  break;
            }

            //
            // Construct the chords
            //
            List<Segment> chords = new List<Segment>();
            for (int p1 = 0; p1 < interPts.Count - 1; p1++)
            {
                for (int p2 = p1 + 1; p2 < interPts.Count; p2++)
                {
                    Segment chord = new Segment(interPts[p1], interPts[p2]);
                    if (!DefinesDiameter(chord)) constructedChords.Add(chord);
                }
            }

            //
            // Do any of the created segments result in imaginary intersection points.
            //
            foreach (Segment chord in constructedChords)
            {
                foreach (Segment radius in constructedRadii)
                {
                    Point inter = Utilities.AcquireRestrictedPoint(figurePoints, chord.FindIntersection(radius), chord, radius);
                    if (inter != null)
                    {
                        chord.AddCollinearPoint(inter);
                        radius.AddCollinearPoint(inter);

                        // if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter);
                        Utilities.AddUnique<Point>(imagPoints, inter);
                    }
                }
            }

            for (int c1 = 0; c1 < constructedChords.Count - 1; c1++)
            {
                for (int c2 = c1 + 1; c2 < constructedChords.Count; c2++)
                {
                    Point inter = constructedChords[c1].FindIntersection(constructedChords[c2]);
                    inter = Utilities.AcquireRestrictedPoint(figurePoints, inter, constructedChords[c1], constructedChords[c2]);
                    if (inter != null)
                    {
                        constructedChords[c1].AddCollinearPoint(inter);
                        constructedChords[c2].AddCollinearPoint(inter);

                        //if (!Utilities.HasStructurally<Point>(figurePoints, inter)) imagPoints.Add(inter);
                        Utilities.AddUnique<Point>(imagPoints, inter);
                    }
                }
            }

            //
            // Add all imaginary points to the list of figure points.
            //
            Utilities.AddUniqueList<Point>(figurePoints, imagPoints);

            //
            // Construct the Planar graph for atomic region identification.
            //
            Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph graph = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph();

            //
            // Add all imaginary points, intersection points, and center.
            //
            foreach (Point pt in imagPoints)
            {
                graph.AddNode(pt);
            }

            foreach (Point pt in interPts)
            {
                graph.AddNode(pt);
            }

            graph.AddNode(this.center);

            //
            // Add all chords and radii as edges.
            //
            foreach (Segment chord in constructedChords)
            {
                for (int p = 0; p < chord.collinear.Count - 1; p++)
                {
                    graph.AddUndirectedEdge(chord.collinear[p], chord.collinear[p + 1],
                                            new Segment(chord.collinear[p], chord.collinear[p + 1]).Length,
                                            Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
                }
            }

            foreach (Segment radius in constructedRadii)
            {
                for (int p = 0; p < radius.collinear.Count - 1; p++)
                {
                    graph.AddUndirectedEdge(radius.collinear[p], radius.collinear[p + 1],
                                            new Segment(radius.collinear[p], radius.collinear[p + 1]).Length,
                                            Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
                }
            }

            //
            // Add all arcs
            //
            List<Point> arcPts = this.ConstructAllMidpoints(interPts);
            for (int p = 0; p < arcPts.Count; p++)
            {
                graph.AddNode(arcPts[p]);
                graph.AddNode(arcPts[(p + 1) % arcPts.Count]);

                graph.AddUndirectedEdge(arcPts[p], arcPts[(p + 1) % arcPts.Count],
                                        new Segment(arcPts[p], arcPts[(p + 1) % interPts.Count]).Length,
                                        Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC);
            }

            //
            // Convert the planar graph to atomic regions.
            //
            Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph);
            FacetCalculator atomFinder = new FacetCalculator(copy);
            List<Primitive> primitives = atomFinder.GetPrimitives();
            List<AtomicRegion> atoms = PrimitiveToRegionConverter.Convert(graph, primitives, Utilities.MakeList<Circle>(this));

            //
            // A filament may result in the creation of a major AND minor arc; both are not required.
            // Figure out which one to omit.
            // Multiple semi-circles may arise as well; omit if they can be broken into constituent elements.
            //
            List <AtomicRegion> trueAtoms = new List<AtomicRegion>();

            for (int a1 = 0; a1 < atoms.Count; a1++)
            {
                bool trueAtom = true;
                for (int a2 = 0; a2 < atoms.Count; a2++)
                {
                    if (a1 != a2)
                    {
                        if (atoms[a1].Contains(atoms[a2]))
                        {
                            trueAtom = false;
                            break;
                        }

                    }
                }

                if (trueAtom) trueAtoms.Add(atoms[a1]);
            }

            atoms = trueAtoms;

            return trueAtoms;
        }
예제 #2
0
        //
        // This is a complex situation because we need to identify situations where circles intersect with the resultant regions:
        //    (|     (|)
        //   ( |    ( | )
        //  (  |   (  |  )
        //   ( |    ( | )
        //    (|     (|)
        //
        // Note: There will always be a chord because of our implied construction.
        // We are interested in only minor arcs of the given circles.
        //
        private List<Atomizer.AtomicRegion> ConvertToCircleCircle(Segment chord,
                                                                  List<Circle> circles,
                                                                  out Circle leftOuterCircle,
                                                                  out Circle rightOuterCircle)
        {
            List<Atomizer.AtomicRegion> regions = new List<Atomizer.AtomicRegion>();
            leftOuterCircle = null;
            rightOuterCircle = null;

            //
            // Simple cases that require no special attention.
            //
            if (!circles.Any()) return null;
            if (circles.Count == 1)
            {
                leftOuterCircle = circles[0];

                regions.AddRange(ConstructBasicLineCircleRegion(chord, circles[0]));

                return regions;
            }

            // All circles that are on each side of the chord
            List<Circle> leftSide = new List<Circle>();
            List<Circle> rightSide = new List<Circle>();

            // For now, assume max, one circle per side.
            // Construct a collinear list of points that includes all circle centers as well as the single intersection point between the chord and the line passing through all circle centers.
            // This orders the sides and provides implied sizes.

            Segment centerLine = new Segment(circles[0].center, circles[1].center);
            for (int c = 2; c < circles.Count; c++)
            {
                centerLine.AddCollinearPoint(circles[c].center);
            }
            // Find the intersection between the center-line and the chord; add that to the list.
            Point intersection = centerLine.FindIntersection(chord);
            centerLine.AddCollinearPoint(intersection);

            List<Point> collPoints = centerLine.collinear;
            int interIndex = collPoints.IndexOf(intersection);

            for (int i = 0; i < collPoints.Count; i++)
            {
                // find the circle based on center
                int c;
                for (c = 0; c < circles.Count; c++)
                {
                    if (circles[c].center.StructurallyEquals(collPoints[i])) break;
                }

                // Add the circle in order
                if (i < interIndex) leftSide.Add(circles[c]);
                else if (i > interIndex) rightSide.Add(circles[c]);
            }

            // the outermost circle is first in the left list and last in the right list.
            if (leftSide.Any()) leftOuterCircle = leftSide[0];
            if (rightSide.Any()) rightOuterCircle = rightSide[rightSide.Count - 1];

            //
            // Main combining algorithm:
            //     Assume: Increasing Arc sequence A \in A_1, A_2, ..., A_n and the single chord C
            //
            //     Construct region B = (C, A_1)
            //     For the increasing Arc sequence (k subscript)  A_2, A_3, ..., A_n
            //         B = Construct ((C, A_k) \ B)
            //
            // Alternatively:
            //     Construct(C, A_1)
            //     for each pair Construct (A_k, A_{k+1})
            //
            //
            // Handle each side: left and right.
            //
            if (leftSide.Any()) regions.AddRange(ConstructBasicLineCircleRegion(chord, leftSide[leftSide.Count - 1]));
            for (int ell = 0; ell < leftSide.Count - 2; ell++)
            {
                regions.Add(ConstructBasicCircleCircleRegion(chord, leftSide[ell], leftSide[ell + 1]));
            }

            if (rightSide.Any()) regions.AddRange(ConstructBasicLineCircleRegion(chord, rightSide[0]));
            for (int r = 1; r < rightSide.Count - 1; r++)
            {
                regions.Add(ConstructBasicCircleCircleRegion(chord, rightSide[r], rightSide[r + 1]));
            }

            return regions;
        }