Exemple #1
0
        ////
        //// The given atomic region is the 'outside' perimeter.
        //// All information is based on intersection points inside or on the perimeter.
        ////
        //List<AtomicRegion> Compose(List<Point> figurePoints, AtomicRegion theAtom,
        //                           List<AtomicRegion> intersecting, List<AtomicRegion> contained)
        //{
        //    List<AtomicRegion> atoms = new List<AtomicRegion>();

        //    foreach (AtomicRegion

        //    return atoms;
        //}


        //
        // Combine two atoms together into a set of atomic regions.
        // toadd refers to atomic regions that are new / modified.
        // toRemove is a subset of the atoms that may be removed from the worklist since they have been replaced as a non-atomic.
        //
        public static void Compose(List <Point> figurePoints, AtomicRegion thisAtom, AtomicRegion thatAtom, out List <AtomicRegion> toAdd, out List <AtomicRegion> toRemove)
        {
            toAdd    = new List <AtomicRegion>();
            toRemove = new List <AtomicRegion>();

            //
            // Do these regions interact at all?
            //
            if (thisAtom.OnExteriorOf(thatAtom))
            {
                return;
            }

            //
            // If there is a single inscribed node then this is containment.
            // If there are no intersections then the regions may be (1) disjoint or (2) containment.
            //
            if (thisAtom.StrictlyContains(thatAtom) || thisAtom.ContainsWithOneInscription(thatAtom))
            {
                //AtomicRegion diff = GenerateDifferenceRegion(thisAtom, thatAtom);
                //toAdd(diff);
                //toRemove.Add(thisAtom);
                //return;
            }
            if (thatAtom.StrictlyContains(thisAtom) || thatAtom.ContainsWithOneInscription(thisAtom))
            {
//                return GenerateDifferenceRegion(thatAtom, thisAtom);
            }


            //
            // The atoms overlap.
            //
            Overlap(figurePoints, thisAtom, thatAtom, out toAdd, out toRemove);
        }
 public DifferenceAtomicRegion(AtomicRegion outer, AtomicRegion inner)
     : base()
 {
     outerShape = outer;
     innerShapes = new List<AtomicRegion>();
     innerShapes.Add(inner);
 }
Exemple #3
0
        ////
        //// The given atomic region is the 'outside' perimeter.
        //// All information is based on intersection points inside or on the perimeter.
        ////
        //List<AtomicRegion> Compose(List<Point> figurePoints, AtomicRegion theAtom,
        //                           List<AtomicRegion> intersecting, List<AtomicRegion> contained)
        //{
        //    List<AtomicRegion> atoms = new List<AtomicRegion>();
        //    foreach (AtomicRegion
        //    return atoms;
        //}
        //
        // Combine two atoms together into a set of atomic regions.
        // toadd refers to atomic regions that are new / modified.
        // toRemove is a subset of the atoms that may be removed from the worklist since they have been replaced as a non-atomic.
        //
        public static void Compose(List<Point> figurePoints, AtomicRegion thisAtom, AtomicRegion thatAtom, out List<AtomicRegion> toAdd, out List<AtomicRegion> toRemove)
        {
            toAdd = new List<AtomicRegion>();
            toRemove = new List<AtomicRegion>();

            //
            // Do these regions interact at all?
            //
            if (thisAtom.OnExteriorOf(thatAtom)) return;

            //
            // If there is a single inscribed node then this is containment.
            // If there are no intersections then the regions may be (1) disjoint or (2) containment.
            //
            if (thisAtom.StrictlyContains(thatAtom) || thisAtom.ContainsWithOneInscription(thatAtom))
            {
                //AtomicRegion diff = GenerateDifferenceRegion(thisAtom, thatAtom);
                //toAdd(diff);
                //toRemove.Add(thisAtom);
                //return;
            }
            if (thatAtom.StrictlyContains(thisAtom) || thatAtom.ContainsWithOneInscription(thisAtom))
            {
            //                return GenerateDifferenceRegion(thatAtom, thisAtom);
            }

            //
            // The atoms overlap.
            //
            Overlap(figurePoints, thisAtom, thatAtom, out toAdd, out toRemove);
        }
Exemple #4
0
    // 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);
    }
        public override bool CoordinateCongruent(AtomicRegion that)
        {
            ShapeAtomicRegion shapeAtom = that as ShapeAtomicRegion;

            if (shapeAtom == null) return false;

            return this.shape.CoordinateCongruent(shapeAtom.shape);
        }
Exemple #6
0
        private List <Atomizer.AtomicRegion> ConvertToTruncation(Segment chord, MinorArc arc)
        {
            AtomicRegion atom = new AtomicRegion();

            atom.AddConnection(new Connection(chord.Point1, chord.Point2, ConnectionType.SEGMENT, chord));

            atom.AddConnection(new Connection(chord.Point1, chord.Point2, ConnectionType.ARC, arc));

            return(Utilities.MakeList <AtomicRegion>(atom));
        }
Exemple #7
0
        //
        // Do all the endpoints in that region lie within this region?
        // And, are all intersection points, if any, on this perimeter?
        //
        public virtual bool Contains(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List <Point> thatVertices = that.GetVertices();

            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOnOrInside(vertex))
                {
                    return(false);
                }
            }

            //
            // Check all midpoints of conenctions are on the interior.
            //
            foreach (Connection thatConn in that.connections)
            {
                if (!this.PointLiesOnOrInside(thatConn.Midpoint()))
                {
                    return(false);
                }
            }

            //
            // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter.
            //
            List <IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    if (!this.PointLiesOn(agg.intersection1))
                    {
                        return(false);
                    }
                    if (agg.intersection2 != null)
                    {
                        if (!this.PointLiesOn(agg.intersection2))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
        public override bool CoordinateCongruent(AtomicRegion that)
        {
            ShapeAtomicRegion shapeAtom = that as ShapeAtomicRegion;

            if (shapeAtom == null)
            {
                return(false);
            }

            return(this.shape.CoordinateCongruent(shapeAtom.shape));
        }
Exemple #9
0
        public void AddAtomicRegion(AtomicRegion atom)
        {
            // Avoid adding an atomic region which is itself
            //if (atom is ShapeAtomicRegion)
            //{
            //    if ((atom as ShapeAtomicRegion).shape.StructurallyEquals(this)) return;
            //}

            if (atoms.Contains(atom)) return;

            atoms.Add(atom);
        }
        public bool HasInnerAtom(AtomicRegion that)
        {
            foreach (AtomicRegion inner in innerShapes)
            {
                if (inner.Equals(that))
                {
                    return(true);
                }
            }

            return(false);
        }
        public override bool Contains(AtomicRegion that)
        {
            ShapeAtomicRegion thatAtom = that as ShapeAtomicRegion;

            if (thatAtom != null)
            {
                return(this.shape.Contains(thatAtom.shape));
            }
            else
            {
                return(base.Contains(that));
            }
        }
        public override bool Contains(AtomicRegion that)
        {
            ShapeAtomicRegion thatAtom = that as ShapeAtomicRegion;

            if (thatAtom != null)
            {
                return this.shape.Contains(thatAtom.shape);
            }
            else
            {
                return base.Contains(that);
            }
        }
Exemple #13
0
        //
        // All vertices of that region on the perimeter of this.
        // Number of intersections must equate to the number of vertices.
        //
        public bool Inscribed(AtomicRegion that)
        {
            List <Point> thatVertices = that.GetVertices();

            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOn(vertex))
                {
                    return(false);
                }
            }

            return(this.GetIntersections(that).Count == thatVertices.Count);
        }
Exemple #14
0
        public bool HasVertexExteriorTo(AtomicRegion that)
        {
            List <IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (!agg.overlap)
                {
                    if (!this.PointLiesOnOrInside(agg.intersection1))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #15
0
        //
        // Do all the endpoints in that region lie within this region?
        // There should be no intersection points.
        //
        public bool StrictlyContains(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List <Point> thatVertices = that.GetVertices();

            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesInside(vertex))
                {
                    return(false);
                }
            }

            // There should be no intersections
            return(!this.GetIntersections(that).Any());
        }
Exemple #16
0
        //
        // A region (that) lies inside this with one intersection.
        //
        public bool ContainsWithGreaterOneInscription(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List <Point> thatVertices = that.GetVertices();

            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOnOrInside(vertex))
                {
                    return(false);
                }
            }

            // There should be only ONE intersection
            return(this.GetIntersections(that).Count > 1);
        }
Exemple #17
0
        private static void SplitConnections(AtomicRegion atom, out List <Segment> segs, out List <Arc> arcs)
        {
            segs = new List <Segment>();
            arcs = new List <Arc>();

            foreach (Connection conn in atom.connections)
            {
                if (conn.segmentOrArc != null)
                {
                    if (conn.type == ConnectionType.SEGMENT)
                    {
                        segs.Add(conn.segmentOrArc as Segment);
                    }
                    if (conn.type == ConnectionType.ARC)
                    {
                        arcs.Add(conn.segmentOrArc as Arc);
                    }
                }
            }
        }
Exemple #18
0
        public bool OverlapsWith(AtomicRegion that)
        {
            // Point based overlapping.
            if (Overlap(that.GetApproximatingPoints()))
            {
                return(true);
            }

            // Crossing-based overlap.
            List <IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.thisConn.Crosses(agg.thatConn))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #19
0
        //
        // Imagine 2 equilateral triangles to make the Star of David: all
        //
        public bool OverlapWithSingleConnections(AtomicRegion that)
        {
            List <IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    if (agg.intersection1 == null || agg.intersection2 == null)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Exemple #20
0
        //
        // If there is no interaction between these atomic regions OR just touching
        //
        public bool InteriorOfWithTouching(AtomicRegion that)
        {
            List <IntersectionAgg> intersections = this.GetIntersections(that);

            // All vertices cannot be interior to the region.
            List <Point> thatVertices = that.GetVertices();

            foreach (Point vertex in thatVertices)
            {
                if (this.PointLiesOnOrInside(vertex))
                {
                    return(false);
                }
            }

            // All intersections must overlap; only point-based intersections which are on the perimeter.
            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    if (PointLiesExterior(agg.intersection1))
                    {
                        return(false);
                    }
                    if (agg.intersection2 != null)
                    {
                        if (PointLiesExterior(agg.intersection2))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Exemple #21
0
    // 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);
    }
Exemple #22
0
        private List <IntersectionAgg> GetIntersections(AtomicRegion thatAtom)
        {
            List <IntersectionAgg> intersections = new List <IntersectionAgg>();

            foreach (Connection thisConn in this.connections)
            {
                foreach (Connection thatConn in thatAtom.connections)
                {
                    Point inter1 = null;
                    Point inter2 = null;
                    thisConn.FindIntersection(thatConn, out inter1, out inter2);

                    if (thisConn.Overlap(thatConn))
                    {
                        IntersectionAgg newAgg = new IntersectionAgg();
                        newAgg.thisConn      = thisConn;
                        newAgg.thatConn      = thatConn;
                        newAgg.intersection1 = null;
                        newAgg.intersection2 = null;
                        newAgg.overlap       = true;
                        AddIntersection(intersections, newAgg);
                    }
                    else if (inter1 != null)
                    {
                        IntersectionAgg newAgg = new IntersectionAgg();
                        newAgg.thisConn      = thisConn;
                        newAgg.thatConn      = thatConn;
                        newAgg.intersection1 = inter1;
                        newAgg.intersection2 = inter2;
                        newAgg.overlap       = thisConn.Overlap(thatConn);
                        AddIntersection(intersections, newAgg);
                    }
                }
            }

            return(intersections);
        }
Exemple #23
0
        public override bool Equals(Object obj)
        {
            AtomicRegion thatAtom = obj as AtomicRegion;

            if (thatAtom == null)
            {
                return(false);
            }

            if (this.connections.Count != thatAtom.connections.Count)
            {
                return(false);
            }

            foreach (Connection conn in this.connections)
            {
                if (!thatAtom.HasConnection(conn))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #24
0
        private List<IntersectionAgg> GetIntersections(AtomicRegion thatAtom)
        {
            List<IntersectionAgg> intersections = new List<IntersectionAgg>();

            foreach (Connection thisConn in this.connections)
            {
                foreach (Connection thatConn in thatAtom.connections)
                {
                    Point inter1 = null;
                    Point inter2 = null;
                    thisConn.FindIntersection(thatConn, out inter1, out inter2);

                    if (thisConn.Overlap(thatConn))
                    {
                        IntersectionAgg newAgg = new IntersectionAgg();
                        newAgg.thisConn = thisConn;
                        newAgg.thatConn = thatConn;
                        newAgg.intersection1 = null;
                        newAgg.intersection2 = null;
                        newAgg.overlap = true;
                        AddIntersection(intersections, newAgg);
                    }
                    else if (inter1 != null)
                    {
                        IntersectionAgg newAgg = new IntersectionAgg();
                        newAgg.thisConn = thisConn;
                        newAgg.thatConn = thatConn;
                        newAgg.intersection1 = inter1;
                        newAgg.intersection2 = inter2;
                        newAgg.overlap = thisConn.Overlap(thatConn);
                        AddIntersection(intersections, newAgg);
                    }

                }
            }

            return intersections;
        }
Exemple #25
0
        private static void SplitConnections(AtomicRegion atom, out List<Segment> segs, out List<Arc> arcs)
        {
            segs = new List<Segment>();
            arcs = new List<Arc>();

            foreach (Connection conn in atom.connections)
            {
                if (conn.segmentOrArc != null)
                {
                    if (conn.type == ConnectionType.SEGMENT) segs.Add(conn.segmentOrArc as Segment);
                    if (conn.type == ConnectionType.ARC) arcs.Add(conn.segmentOrArc as Arc);
                }
            }
        }
Exemple #26
0
        //
        // Do all the endpoints in that region lie within this region?
        // There should be no intersection points.
        //
        public bool StrictlyContains(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List<Point> thatVertices = that.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesInside(vertex)) return false;
            }

            // There should be no intersections
            return !this.GetIntersections(that).Any();
        }
Exemple #27
0
        //
        // Imagine 2 equilateral triangles to make the Star of David: all
        //
        public bool OverlapWithSingleConnections(AtomicRegion that)
        {
            List<IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    if (agg.intersection1 == null || agg.intersection2 == null) return false;
                }
            }

            return true;
        }
Exemple #28
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);
        }
Exemple #29
0
 public virtual bool CoordinateCongruent(AtomicRegion that)
 {
     throw new NotImplementedException();
 }
        private static bool AddAtom(List<AtomicRegion> atoms, AtomicRegion atom)
        {
            if (atoms.Contains(atom)) return false;

            atoms.Add(atom);

            return true;
        }
Exemple #31
0
 public Region(Atomizer.AtomicRegion atom) : this(Utilities.MakeList <Atomizer.AtomicRegion>(atom))
 {
 }
Exemple #32
0
 private static List <AtomicRegion> GenerateDifferenceRegion(AtomicRegion outer, AtomicRegion inner)
 {
     return(Utilities.MakeList <AtomicRegion>(new DifferenceAtomicRegion(outer, inner)));
 }
Exemple #33
0
        //
        // Determine if this is a true polygon situation or if it is a sequence of segments and arcs.
        //
        private List <AtomicRegion> GeneralAtomicRegion(Segment[] segments, Arc[] arcs)
        {
            List <AtomicRegion> regions = new List <AtomicRegion>();

            //
            // Determine if the parts are all segments.
            // Concurrently determine the proper starting point in the sequence to construct the atomic region.
            //
            bool hasArc     = false;
            bool hasSegment = false;
            int  startIndex = 0;

            for (int i = 0; i < segments.Length && i < arcs.Length; i++)
            {
                // Both an arc and a segment.
                if (segments[i] != null && arcs[i] != null)
                {
                    return(regions);
                }

                // Determine if we have an arc and/or a segment.
                if (segments[i] != null)
                {
                    hasSegment = true;
                }
                if (arcs[i] != null)
                {
                    hasArc = true;
                }

                // A solid starting point is an arc right after a null.
                if (arcs[i] == null && arcs[(i + 1) % arcs.Length] != null)
                {
                    // Assign only once to the startIndex
                    if (startIndex == 0)
                    {
                        startIndex = (i + 1) % arcs.Length;
                    }
                }
            }

            // If only segments, we have a polygon.
            if (hasSegment && !hasArc)
            {
                return(regions);
            }

            //
            // If the set ONLY consists of arcs, ensure we have a good starting point.
            //
            if (hasArc && !hasSegment)
            {
                // Seek the first index where a change among arcs occurs.
                for (int i = 0; i < arcs.Length; i++)
                {
                    // A solid starting point is an arc right after a null.
                    if (!arcs[i].theCircle.StructurallyEquals(arcs[(i + 1) % arcs.Length].theCircle))
                    {
                        startIndex = (i + 1) % arcs.Length;
                        break;
                    }
                }
            }

            AtomicRegion theRegion = new AtomicRegion();

            for (int i = 0; i < segments.Length && i < arcs.Length; i++)
            {
                int currIndex = (i + startIndex) % arcs.Length;

                if (segments[currIndex] == null && arcs[currIndex] == null) /* No-Op */ } {
                if (segments[currIndex] != null)
                {
                    theRegion.AddConnection(new Connection(segments[currIndex].Point1,
                                                           segments[currIndex].Point2, ConnectionType.SEGMENT, segments[currIndex]));
                }
                else if (arcs[currIndex] != null)
                {
                    //
                    // Compose the arcs (from a single circle) together.
                    //
                    List <MinorArc> sequentialArcs = new List <MinorArc>();
                    sequentialArcs.Add(arcs[currIndex] as MinorArc);

                    int seqIndex;
                    for (seqIndex = (currIndex + 1) % arcs.Length; ; seqIndex = (seqIndex + 1) % arcs.Length, i++)
                    {
                        if (arcs[seqIndex] == null)
                        {
                            break;
                        }

                        if (arcs[currIndex].theCircle.StructurallyEquals(arcs[seqIndex].theCircle))
                        {
                            sequentialArcs.Add(arcs[seqIndex] as MinorArc);
                        }
                        else
                        {
                            break;
                        }
                    }

                    Arc composed;
                    if (sequentialArcs.Count > 1)
                    {
                        composed = this.ComposeArcsIntoArc(sequentialArcs);
                    }
                    else
                    {
                        composed = arcs[currIndex];
                    }

                    //
                    // Add the connection.
                    //
                    theRegion.AddConnection(new Connection(composed.endpoint1, composed.endpoint2, ConnectionType.ARC, composed));
                }
        }

        return(Utilities.MakeList <AtomicRegion>(theRegion));
    }
Exemple #34
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;
        }
Exemple #35
0
 public bool Circumscribed(AtomicRegion that)
 {
     return that.Inscribed(this);
 }
Exemple #36
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));
        }
Exemple #37
0
 /// <summary>
 /// Create a new ShadedRegion
 /// </summary>
 /// <param name="region">The region to shade</param>
 public ShadedRegion(AtomicRegion region)
 {
     Region = region;
 }
Exemple #38
0
 public bool Circumscribed(AtomicRegion that)
 {
     return(that.Inscribed(this));
 }
 public DifferenceAtomicRegion(AtomicRegion outer, AtomicRegion inner) : base()
 {
     outerShape  = outer;
     innerShapes = new List <AtomicRegion>();
     innerShapes.Add(inner);
 }
Exemple #40
0
 public bool HasAtom(Atomizer.AtomicRegion atom)
 {
     return(atoms.Contains(atom));
 }
Exemple #41
0
        public virtual bool CoordinateCongruent(AtomicRegion that)
        {
            //
            // Collect segment and arc connections.
            //
            List <Segment> thisSegs = new List <Segment>();
            List <Arc>     thisArcs = new List <Arc>();
            List <Segment> thatSegs = new List <Segment>();
            List <Arc>     thatArcs = new List <Arc>();

            SplitConnections(this, out thisSegs, out thisArcs);
            SplitConnections(that, out thatSegs, out thatArcs);

            //
            // We must have the same number of each type of connections
            //
            if (thisSegs.Count != thatSegs.Count)
            {
                return(false);
            }
            if (thisArcs.Count != thatArcs.Count)
            {
                return(false);
            }

            //
            // This is a naive approach since a more formal approach should follow order of connections; should generally work
            //
            //
            // An atomic region must have the same number of segments, each of the same length.
            //
            bool[] marked = new bool[thisSegs.Count];
            foreach (Segment thisSeg in thisSegs)
            {
                bool found = false;
                for (int c = 0; c < thatSegs.Count; c++)
                {
                    if (!marked[c])
                    {
                        if (thisSeg.CoordinateCongruent(thatSegs[c]))
                        {
                            marked[c] = true;
                            found     = true;
                            break;
                        }
                    }
                }
                if (!found)
                {
                    return(false);
                }
            }
            // Redundant:
            // if (marked.Contains(false)) return false;

            // Exit early if no arcs.
            if (!thisArcs.Any())
            {
                return(true);
            }

            //
            // An atomic region must have the same number of arcs, each of the same length (using the radius of the circle).
            //
            marked = new bool[thisArcs.Count];
            foreach (Arc thisArc in thisArcs)
            {
                bool found = false;
                for (int c = 0; c < thatArcs.Count; c++)
                {
                    if (!marked[c])
                    {
                        if (thisArc.CoordinateCongruent(thatArcs[c]))
                        {
                            marked[c] = true;
                            found     = true;
                            break;
                        }
                    }
                }
                if (!found)
                {
                    return(false);
                }
            }
            // Redundant:
            // if (marked.Contains(false)) return false;

            return(true);
        }
        private static void HandleSegmentSegmentIntersections(List<Point> figurePoints, List<Point> points, List<Segment> segments, AtomicRegion outerBounds)
        {
            // Segment-Segment
            for (int s1 = 0; s1 < segments.Count - 1; s1++)
            {
                for (int s2 = s1 + 1; s2 < segments.Count; s2++)
                {
                    Point intersection = segments[s1].FindIntersection(segments[s2]);
                    intersection = GeometryTutorLib.Utilities.AcquirePoint(figurePoints, intersection);

                    if (intersection != null)
                    {
                        if (outerBounds.PointLiesOnOrInside(intersection))
                        {
                            segments[s1].AddCollinearPoint(intersection);
                            segments[s2].AddCollinearPoint(intersection);

                            // It may be the case that this intersection was due to a completely contained region.
                            GeometryTutorLib.Utilities.AddUnique<Point>(points, intersection);
                        }
                    }
                }
            }
        }
        private static void HandleArcArcIntersections(List<Point> figurePoints, List<Point> points, List<Arc> arcs, AtomicRegion outerBounds)
        {
            // Arc-Arc
            for (int a1 = 0; a1 < arcs.Count - 1; a1++)
            {
                for (int a2 = a1 + 1; a2 < arcs.Count; a2++)
                {
                    Point pt1 = null;
                    Point pt2 = null;
                    arcs[a1].theCircle.FindIntersection(arcs[a2].theCircle, out pt1, out pt2);
                    pt1 = GeometryTutorLib.Utilities.AcquirePoint(figurePoints, pt1);
                    pt2 = GeometryTutorLib.Utilities.AcquirePoint(figurePoints, pt2);

                    if (pt1 != null)
                    {
                        if (outerBounds.PointLiesOnOrInside(pt1))
                        {
                            arcs[a1].AddCollinearPoint(pt1);
                            arcs[a2].AddCollinearPoint(pt1);

                            // It may be the case that this intersection was due to a completely contained region.
                            GeometryTutorLib.Utilities.AddUnique<Point>(points, pt1);
                        }
                    }
                    if (pt2 != null)
                    {
                        if (outerBounds.PointLiesOnOrInside(pt2))
                        {
                            arcs[a1].AddCollinearPoint(pt2);
                            arcs[a2].AddCollinearPoint(pt2);

                            // It may be the case that this intersection was due to a completely contained region.
                            GeometryTutorLib.Utilities.AddUnique<Point>(points, pt2);
                        }
                    }
                }
            }
        }
        private static void HandleSegmentArcIntersections(List<Point> figurePoints, List<Point> points, List<Segment> segments, List<Arc> arcs, AtomicRegion outerBounds)
        {
            // Segment-Arc
            foreach (Segment segment in segments)
            {
                foreach (Arc arc in arcs)
                {
                    Point pt1 = null;
                    Point pt2 = null;
                    arc.theCircle.FindIntersection(segment, out pt1, out pt2);
                    pt1 = GeometryTutorLib.Utilities.AcquirePoint(figurePoints, pt1);
                    pt2 = GeometryTutorLib.Utilities.AcquirePoint(figurePoints, pt2);

                    if (pt1 != null)
                    {
                        if (outerBounds.PointLiesOnOrInside(pt1))
                        {
                            segment.AddCollinearPoint(pt1);
                            arc.AddCollinearPoint(pt1);

                            // It may be the case that this intersection was due to a completely contained region.
                            GeometryTutorLib.Utilities.AddUnique<Point>(points, pt1);
                        }
                    }
                    if (pt2 != null)
                    {
                        if (outerBounds.PointLiesOnOrInside(pt2))
                        {
                            segment.AddCollinearPoint(pt2);
                            arc.AddCollinearPoint(pt2);

                            // It may be the case that this intersection was due to a completely contained region.
                            GeometryTutorLib.Utilities.AddUnique<Point>(points, pt2);
                        }
                    }
                }
            }
        }
Exemple #45
0
        public bool OverlapsWith(AtomicRegion that)
        {
            // Point based overlapping.
            if (Overlap(that.GetApproximatingPoints())) return true;

            // Crossing-based overlap.
            List<IntersectionAgg> intersections = this.GetIntersections(that);
            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.thisConn.Crosses(agg.thatConn)) return true;
            }

            return false;
        }
Exemple #46
0
 public virtual bool Covers(AtomicRegion a)
 {
     throw new NotImplementedException();
 }
        //
        // Using a single atomic region as a set of bounds:
        //    (1) Find all interesting regions (contained and intersecting)
        //    (2) Recursively compose all contained regions.
        //    (3) Combine all into the original boundary region.
        //
        private static List<AtomicRegion> ComposeSingleRegion(List<Point> figurePoints, AtomicRegion outerBounds, List<AtomicRegion> allRegions, 
                                                              List<AtomicRegion> knownAtomicRegions, List<AtomicRegion> knownNonAtomicRegions,
                                                              List<List<AtomicRegion>> setsForNonAtomicRegions, Dictionary<Circle, int> circGranularity)
        {
            //
            // Base cases: we have already processed this atom as a sub-atom in a previous iteration.
            //
            if (knownAtomicRegions.Contains(outerBounds)) return Utilities.MakeList<AtomicRegion>(outerBounds);
            // We've processed this atom already.
            int index = knownNonAtomicRegions.IndexOf(outerBounds);
            if (index != -1) return setsForNonAtomicRegions[index];

            //
            // Acquire the current set of regions under consideration.
            //
            List<AtomicRegion> currentAtoms = new List<AtomicRegion>(allRegions);
            AddRange(currentAtoms, knownAtomicRegions);

            //
            // Collect all interesting regions for this region: those that intersect with it and those that are contained inside.
            //
            List<AtomicRegion> intersectingSet = null;
            List<AtomicRegion> containedSet = null;
            GetInterestingRegions(currentAtoms, outerBounds, out intersectingSet, out containedSet);

            // If we have have no interactions, this is a truly atomic region.
            if (!intersectingSet.Any() && !containedSet.Any()) return Utilities.MakeList<AtomicRegion>(outerBounds);

            //
            // Recur on all containing regions.
            //
            List<AtomicRegion> newContainedAtoms = new List<AtomicRegion>();
            foreach (AtomicRegion containedAtom in containedSet)
            {
                if (knownAtomicRegions.Contains(containedAtom)) AddAtom(newContainedAtoms, containedAtom);
                else if (knownNonAtomicRegions.Contains(containedAtom))
                {
                    AddRange(newContainedAtoms, setsForNonAtomicRegions[knownNonAtomicRegions.IndexOf(containedAtom)]);
                }
                else
                {
                    // Get all regions using containedAtom as the boundary region.
                    List<AtomicRegion> newContainedBoundedAtoms = ComposeSingleRegion(figurePoints, containedAtom, currentAtoms,
                                                                                      knownAtomicRegions, knownNonAtomicRegions, setsForNonAtomicRegions, circGranularity);

                    AddRange(newContainedAtoms, newContainedBoundedAtoms);

                    //
                    // This is a true atomic region that cannot be split.
                    //
                    if (newContainedBoundedAtoms.Count == 1) AddAtom(knownAtomicRegions, containedAtom);
                    //
                    // The boundary atom is replaced by all of the newAtoms
                    else
                    {
                        // Save all of the contained atomic regions for this atom.
                        if (AddAtom(knownNonAtomicRegions, containedAtom))
                        {
                            setsForNonAtomicRegions.Add(newContainedBoundedAtoms);
                        }

                        // Indicate all found regions are truly atomic
                        AddRange(knownAtomicRegions, newContainedBoundedAtoms);
                    }
                }
            }

            //
            // Now that all contained regions are atomized, combine ALL intersections and atomic regions.
            //
            //  Collect all segments and arcs (with explicit endpoints).
            //  Extend only if they do not touch the sides of the boundaries.
            //

            // inside of the boundaries; determine all intersection points.
            //
            //  (1) All intersecting regions.
            //      (a) For all vertices inside the boundaries, extend to the closest atom.
            //      (b) For all sides that pass through determine any intersections.
            //  (2) All contained atoms
            //      (a) For each side of a region, extend to the closest region.
            //      (b) If a single circle or concentric circles, extend a diameter from the closest point inside the region, through the center.
            //      (c) If several non-intersecting circles, extend diameters through the centers of each pair.
            //
            List<Point> points = new List<Point>();
            List<Segment> segments = new List<Segment>();
            List<Arc> arcs = new List<Arc>();

            //
            // Add the outer boundaries.
            //
            points.AddRange(outerBounds.GetVertices());
            foreach (Connection boundaryConn in outerBounds.connections)
            {
                if (boundaryConn.type == ConnectionType.ARC)
                {
                    arcs.Add(boundaryConn.segmentOrArc as Arc);
                }
                if (boundaryConn.type == ConnectionType.SEGMENT)
                {
                    segments.Add(boundaryConn.segmentOrArc as Segment);
                }
            }

            //
            // Regions that intersect the boundaries; selectively take connections.
            //
            foreach (AtomicRegion intersecting in intersectingSet)
            {
                List<AtomicRegion.IntersectionAgg> intersections = outerBounds.GetIntersections(figurePoints, intersecting);

                // Determine which intersections are interior to the boundaries.
                foreach (AtomicRegion.IntersectionAgg agg in intersections)
                {
                    if (agg.overlap) { /* No-op */ }
                    else
                    {
                        if (agg.intersection1 != null)
                        {
                            if (outerBounds.PointLiesOnOrInside(agg.intersection1))
                            {
                                if (!outerBounds.NotInteriorTo(agg.thatConn))
                                {
                                    if (agg.thatConn.type == ConnectionType.ARC) GeometryTutorLib.Utilities.AddUnique<Arc>(arcs, agg.thatConn.segmentOrArc as Arc);
                                    if (agg.thatConn.type == ConnectionType.SEGMENT)
                                        GeometryTutorLib.Utilities.AddUnique<Segment>(segments, agg.thatConn.segmentOrArc as Segment);
                                }
                                GeometryTutorLib.Utilities.AddUnique<Point>(points, agg.intersection1);
                            }
                        }
                        if (agg.intersection2 != null)
                        {
                            if (outerBounds.PointLiesOnOrInside(agg.intersection2))
                            {
                                GeometryTutorLib.Utilities.AddUnique<Point>(points, agg.intersection2);
                            }
                        }
                    }
                }
            }

            //
            // Deal with contained regions.
            //
            // TO BE COMPLETED: Deal with isolated circles.
            foreach (AtomicRegion contained in newContainedAtoms)
            {
                List<Point> verts = contained.GetVertices();
                GeometryTutorLib.Utilities.AddUniqueList<Point>(points, verts);

                foreach (Connection conn in contained.connections)
                {
                    if (conn.type == ConnectionType.ARC) Utilities.AddUnique<Arc>(arcs, conn.segmentOrArc as Arc);
                    if (conn.type == ConnectionType.SEGMENT)
                    {
                        Utilities.AddUnique<Segment>(segments, conn.segmentOrArc as Segment);
                    }
                }
            }

            //
            // Find all intersections...among segments and arcs.
            //
            foreach (Segment segment in segments)
            {
                segment.ClearCollinear();
            }
            foreach (Arc arc in arcs)
            {
                arc.ClearCollinear();
            }

            HandleSegmentSegmentIntersections(figurePoints, points, segments, outerBounds);
            HandleSegmentArcIntersections(figurePoints, points, segments, arcs, outerBounds);
            HandleArcArcIntersections(figurePoints, points, arcs, outerBounds);
            // Returns the list of maximal segments.
            segments = HandleCollinearSubSegments(segments);
            // HandleCollinearSubArcs(arcs);

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

            // Add the points as nodes in the graph.
            foreach (Point pt in points)
            {
                graph.AddNode(pt);
            }

            //
            // Edges are based on all the collinear relationships.
            // To ensure we are taking ONLY the closest extended intersections, choose ONLY the 1 point around the actual endpoints of the arc or segment.
            //
            foreach (Segment segment in segments)
            {
                for (int p = 0; p < segment.collinear.Count - 1; p++)
                {
                    if (outerBounds.PointLiesInOrOn(segment.collinear[p]) && outerBounds.PointLiesInOrOn(segment.collinear[p + 1]))
                    {
                        graph.AddUndirectedEdge(segment.collinear[p], segment.collinear[p + 1],
                                                new Segment(segment.collinear[p], segment.collinear[p + 1]).Length,
                                                GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
                    }
                }
            }

            foreach (Arc arc in arcs)
            {
                List<Point> applicWithMidpoints = GetArcPoints(arc, circGranularity);

                // Add the points to the graph; preprocess to see if all points are inside the region.
                bool[] inOrOn = new bool[applicWithMidpoints.Count];
                for (int p = 0; p < applicWithMidpoints.Count; p++)
                {
                    if (outerBounds.PointLiesInOrOn(applicWithMidpoints[p]))
                    {
                        graph.AddNode(applicWithMidpoints[p]);
                        inOrOn[p] = true;
                    }
                }

                for (int p = 0; p < applicWithMidpoints.Count - 1; p++)
                {
                    if (inOrOn[p] && inOrOn[p + 1])
                    {
                        graph.AddUndirectedEdge(applicWithMidpoints[p], applicWithMidpoints[p + 1],
                                                new Segment(applicWithMidpoints[p], applicWithMidpoints[p + 1]).Length,
                                                GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_ARC);
                    }
                }
            }

            //
            // Collect the circles from the arcs.
            //
            List<Circle> circles = new List<Circle>();
            foreach (Arc arc in arcs)
            {
                GeometryTutorLib.Utilities.AddStructurallyUnique<Circle>(circles, arc.theCircle);
            }

            //
            // Convert the planar graph to atomic regions.
            //
            GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph copy = new GeometryTutorLib.Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.PlanarGraph(graph);
            FacetCalculator atomFinder = new FacetCalculator(copy);
            List<Primitive> primitives = atomFinder.GetPrimitives();
            List<AtomicRegion> boundedAtoms = PrimitiveToRegionConverter.Convert(graph, primitives, circles);

            ////
            //// Realign this set of atoms with the current set of working atoms; this guarantees we are looking at the same atom objects.
            ////
            //List<AtomicRegion> finalBoundedAtoms = new List<AtomicRegion>();
            //foreach (AtomicRegion boundedAtom in boundedAtoms)
            //{
            //    int tempIndex = currentAtoms.IndexOf(boundedAtom);
            //    if (tempIndex == -1) finalBoundedAtoms.Add(boundedAtom);
            //    else finalBoundedAtoms.Add(currentAtoms[tempIndex]);
            //}

            //
            // Determine ownership of the atomic regions.
            //
            foreach (AtomicRegion boundedAtom in boundedAtoms)
            {
                boundedAtom.AddOwners(outerBounds.owners);

                // Indicate that the given boundary shape owns all of the new regions within.
                ShapeAtomicRegion shapeAtom = outerBounds as ShapeAtomicRegion;
                if (shapeAtom != null)
                {
                    shapeAtom.shape.AddAtomicRegion(boundedAtom);
                }
            }

            return boundedAtoms;
        }
Exemple #48
0
        //
        // Determine if this is a true polygon situation or if it is a sequence of segments and arcs.
        //
        private List<AtomicRegion> GeneralAtomicRegion(Segment[] segments, Arc[] arcs)
        {
            List<AtomicRegion> regions = new List<AtomicRegion>();

            //
            // Determine if the parts are all segments.
            // Concurrently determine the proper starting point in the sequence to construct the atomic region.
            //
            bool hasArc = false;
            bool hasSegment = false;
            int startIndex = 0;
            for (int i = 0; i < segments.Length && i < arcs.Length; i++)
            {
                // Both an arc and a segment.
                if (segments[i] != null && arcs[i] != null) return regions;

                // Determine if we have an arc and/or a segment.
                if (segments[i] != null) hasSegment = true;
                if (arcs[i] != null) hasArc = true;

                // A solid starting point is an arc right after a null.
                if (arcs[i] == null && arcs[(i + 1) % arcs.Length] != null)
                {
                    // Assign only once to the startIndex
                    if (startIndex == 0) startIndex = (i + 1) % arcs.Length;
                }
            }

            // If only segments, we have a polygon.
            if (hasSegment && !hasArc) return regions;

            //
            // If the set ONLY consists of arcs, ensure we have a good starting point.
            //
            if (hasArc && !hasSegment)
            {
                // Seek the first index where a change among arcs occurs.
                for (int i = 0; i < arcs.Length; i++)
                {
                    // A solid starting point is an arc right after a null.
                    if (!arcs[i].theCircle.StructurallyEquals(arcs[(i + 1) % arcs.Length].theCircle))
                    {
                        startIndex = (i + 1) % arcs.Length;
                        break;
                    }
                }
            }

            AtomicRegion theRegion = new AtomicRegion();
            for (int i = 0; i < segments.Length && i < arcs.Length; i++)
            {
                int currIndex = (i + startIndex) % arcs.Length;

                if (segments[currIndex] == null && arcs[currIndex] == null) { /* No-Op */ }

                if (segments[currIndex] != null)
                {
                    theRegion.AddConnection(new Connection(segments[currIndex].Point1,
                                                           segments[currIndex].Point2, ConnectionType.SEGMENT, segments[currIndex]));
                }
                else if (arcs[currIndex] != null)
                {
                    //
                    // Compose the arcs (from a single circle) together.
                    //
                    List<MinorArc> sequentialArcs = new List<MinorArc>();
                    sequentialArcs.Add(arcs[currIndex] as MinorArc);

                    int seqIndex;
                    for (seqIndex = (currIndex + 1) % arcs.Length; ; seqIndex = (seqIndex + 1) % arcs.Length, i++)
                    {
                        if (arcs[seqIndex] == null) break;

                        if (arcs[currIndex].theCircle.StructurallyEquals(arcs[seqIndex].theCircle))
                        {
                            sequentialArcs.Add(arcs[seqIndex] as MinorArc);
                        }
                        else break;
                    }

                    Arc composed;
                    if (sequentialArcs.Count > 1) composed = this.ComposeArcsIntoArc(sequentialArcs);
                    else composed = arcs[currIndex];

                    //
                    // Add the connection.
                    //
                    theRegion.AddConnection(new Connection(composed.endpoint1, composed.endpoint2, ConnectionType.ARC, composed));
                }
            }

            return Utilities.MakeList<AtomicRegion>(theRegion);
        }
Exemple #49
0
        //
        // All vertices of that region on the perimeter of this.
        // Number of intersections must equate to the number of vertices.
        //
        public bool Inscribed(AtomicRegion that)
        {
            List<Point> thatVertices = that.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOn(vertex)) return false;
            }

            return this.GetIntersections(that).Count == thatVertices.Count;
        }
Exemple #50
0
        //
        // Does the atom have a connection which intersects the sides of the polygon.
        //
        public override bool Covers(AtomicRegion atom)
        {
            foreach (Connection conn in atom.connections)
            {
                if (conn.type == ConnectionType.SEGMENT)
                {
                    if (this.Covers(conn.segmentOrArc as Segment)) return true;
                }
                else if (conn.type == ConnectionType.ARC)
                {
                    if (this.Covers(conn.segmentOrArc as Arc)) return true;
                }
            }

            return false;
        }
Exemple #51
0
        //
        // If there is no interaction between these atomic regions OR just touching
        //
        public bool OnExteriorOf(AtomicRegion that)
        {
            List<IntersectionAgg> intersections = this.GetIntersections(that);

            // All vertices cannot be interior to the region.
            List<Point> thatVertices = that.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (this.PointLiesInside(vertex)) return false;
            }

            // All intersections must be overlap; only point-based intersections which are on the perimeter.
            foreach (IntersectionAgg agg in intersections)
            {
                if (!agg.overlap)
                {
                    if (agg.intersection2 != null) return false;
                    if (!this.PointLiesOn(agg.intersection1)) return false;
                }
                else // agg.overlap
                {
                    // No-Op
                }
            }

            return true;
        }
Exemple #52
0
        //
        // Do all the endpoints in that region lie within this region?
        // And, are all intersection points, if any, on this perimeter?
        //
        public virtual bool Contains(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List<Point> thatVertices = that.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOnOrInside(vertex)) return false;
            }

            //
            // Check all midpoints of conenctions are on the interior.
            //
            foreach (Connection thatConn in that.connections)
            {
                if (!this.PointLiesOnOrInside(thatConn.Midpoint())) return false;
            }

            //
            // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter.
            //
            List<IntersectionAgg> intersections = this.GetIntersections(that);
            foreach (IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    if (!this.PointLiesOn(agg.intersection1)) return false;
                    if (agg.intersection2 != null)
                    {
                        if (!this.PointLiesOn(agg.intersection2)) return false;
                    }
                }
            }

            return true;
        }
        //
        // Find all regions that overlap this region.
        //
        private static void GetInterestingRegions(List<AtomicRegion> atoms, AtomicRegion theAtom,
                                                  out List<AtomicRegion> intersecting, out List<AtomicRegion> contained)
        {
            intersecting = new List<AtomicRegion>();
            contained = new List<AtomicRegion>();

            foreach (AtomicRegion atom in atoms)
            {
                // An atom should not intersect itself.
                if (!theAtom.Equals(atom))
                {
                    if (theAtom.Contains(atom))
                    {
                        contained.Add(atom);
                    }
                    //else if (theAtom.StrictlyContains(atom))
                    //{
                    //    contained.Add(theAtom);
                    //}
                    else if (theAtom.OverlapsWith(atom))
                    {
                        intersecting.Add(atom);
                    }
                }
            }
        }
Exemple #54
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);
        }
Exemple #55
0
        //
        // A region (that) lies inside this with one intersection.
        //
        public bool ContainsWithOneInscription(AtomicRegion that)
        {
            //
            // Do all vertices of that lie on the interior of this atomic region?
            //
            List<Point> thatVertices = that.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesOnOrInside(vertex)) return false;
            }

            // There should be only ONE intersection
            return this.GetIntersections(that).Count == 1;
        }
Exemple #56
0
        public virtual bool Contains(List<Point> figurePoints, AtomicRegion atom)
        {
            // A figure contains itself.
            ShapeAtomicRegion shapeAtom = atom as ShapeAtomicRegion;
            if (shapeAtom != null)
            {
                if (this.StructurallyEquals(shapeAtom.shape)) return true;
            }

            //
            // Do all vertices of that lie on the interior of this figure
            //
            List<Point> thatVertices = atom.GetVertices();
            foreach (Point vertex in thatVertices)
            {
                if (!this.PointLiesInOrOn(vertex)) return false;
            }

            //
            // Check all midpoints of conenctions are on the interior.
            //
            foreach (Connection thatConn in atom.connections)
            {
                if (!this.PointLiesInOrOn(thatConn.Midpoint())) return false;
            }

            //
            // For any intersections between the atomic regions, the resultant points of intersection must be on the perimeter.
            //
            AtomicRegion thisFigureRegion = this.GetFigureAsAtomicRegion();
            List<AtomicRegion.IntersectionAgg> intersections = thisFigureRegion.GetIntersections(figurePoints, atom);
            foreach (AtomicRegion.IntersectionAgg agg in intersections)
            {
                if (agg.overlap)
                {
                    // No-Op
                }
                else
                {
                    // An approximation may result in an intersection inside the figure (although we would expect on)
                    if (!this.PointLiesInOrOn(agg.intersection1)) return false;
                    if (agg.intersection2 != null)
                    {
                        if (!this.PointLiesInOrOn(agg.intersection2)) return false;
                    }
                }
            }

            return true;
        }
Exemple #57
0
        public virtual bool CoordinateCongruent(AtomicRegion that)
        {
            //
            // Collect segment and arc connections.
            //
            List<Segment> thisSegs = new List<Segment>();
            List<Arc> thisArcs = new List<Arc>();
            List<Segment> thatSegs = new List<Segment>();
            List<Arc> thatArcs = new List<Arc>();

            SplitConnections(this, out thisSegs, out thisArcs);
            SplitConnections(that, out thatSegs, out thatArcs);

            //
            // We must have the same number of each type of connections
            //
            if (thisSegs.Count != thatSegs.Count) return false;
            if (thisArcs.Count != thatArcs.Count) return false;

            //
            // This is a naive approach since a more formal approach should follow order of connections; should generally work
            //
            //
            // An atomic region must have the same number of segments, each of the same length.
            //
            bool[] marked = new bool[thisSegs.Count];
            foreach (Segment thisSeg in thisSegs)
            {
                bool found = false;
                for (int c = 0; c < thatSegs.Count; c++)
                {
                    if (!marked[c])
                    {
                        if (thisSeg.CoordinateCongruent(thatSegs[c]))
                        {
                            marked[c] = true;
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) return false;
            }
            // Redundant:
            // if (marked.Contains(false)) return false;

            // Exit early if no arcs.
            if (!thisArcs.Any()) return true;

            //
            // An atomic region must have the same number of arcs, each of the same length (using the radius of the circle).
            //
            marked = new bool[thisArcs.Count];
            foreach (Arc thisArc in thisArcs)
            {
                bool found = false;
                for (int c = 0; c < thatArcs.Count; c++)
                {
                    if (!marked[c])
                    {
                        if (thisArc.CoordinateCongruent(thatArcs[c]))
                        {
                            marked[c] = true;
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) return false;
            }
            // Redundant:
            // if (marked.Contains(false)) return false;

            return true;
        }
Exemple #58
0
        public bool HasVertexExteriorTo(AtomicRegion that)
        {
            List<IntersectionAgg> intersections = this.GetIntersections(that);

            foreach (IntersectionAgg agg in intersections)
            {
                if (!agg.overlap)
                {
                    if (!this.PointLiesOnOrInside(agg.intersection1)) return true;
                }
            }

            return false;
        }
Exemple #59
0
        //
        // Compose this atomic region with a segment
        // This operation will return a list of atomic regions iff the segment passes through the atomic region; this
        // creates two new atomic regions since the segment divides the atom.
        //
        //public static List<AtomicRegion> Compose(AtomicRegion thisAtom, Segment that, Figure owner)
        //{
        //    List<AtomicRegion> newAtoms = new List<AtomicRegion>();
        //    List<AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(that);

        //    // If there is only 1 intersection then we may have a 'corner' inside of the atomic region.
        //    if (intersections.Count == 1) return newAtoms;

        //    if (intersections.Count > 2) throw new ArgumentException("More than 3 intersections due to a segment during atomic region composition");

        //    // If there are two intersection points, this atomic region is split into 2 regions.
        //    if (intersections.Count != 2)
        //    {
        //        throw new ArgumentException("Expected 2 intersections due to a segment during atomic region composition; have " + intersections.Count);
        //    }

        //    //
        //    // Split the region into 2 new atomic regions.
        //    //
        //    // (0) Order the connections of this atomic region.
        //    // (1) Make a copy of the list of connections
        //    // (2) Replace 2 intersected connections with (up to) 4 new connections.
        //    // (3) Add this segment connection
        //    //
        //    thisAtom.OrderConnections();

        //    AtomicRegion newAtom1 = new AtomicRegion();
        //    AtomicRegion newAtom2 = new AtomicRegion();

        //    bool[] marked = new bool[intersections.Count];
        //    bool atom1 = true;
        //    foreach (Connection conn in thisAtom.connections)
        //    {
        //        bool found = false;
        //        for (int i = 0; i < intersections.Count; i++)
        //        {
        //            if (!marked[i])
        //            {
        //                marked[i] = true;
        //                if (conn.Equals(intersections[i].Key))
        //                {
        //                    found = true;

        //                    //
        //                    // How does this new segment intersect this connection?
        //                    //
        //                    // Endpoint
        //                    if (conn.HasPoint(intersections[i].Value))
        //                    {
        //                        // No-op
        //                    }
        //                    // Split this connection in the middle
        //                    else
        //                    {
        //                        Connection newConn1 = new Connection(conn.endpoint1, intersections[i].Value, conn.type, conn.segmentOwner);
        //                        Connection newConn2 = new Connection(conn.endpoint2, intersections[i].Value, conn.type, conn.segmentOwner);

        //                        //
        //                        // Which atomic region owns which new connection.
        //                        //
        //                        if (newAtom1.HasPoint(conn.endpoint1))
        //                        {
        //                            newAtom1.AddConnection(newConn1);
        //                            newAtom2.AddConnection(newConn2);
        //                        }
        //                        else if (newAtom2.HasPoint(conn.endpoint1))
        //                        {
        //                            newAtom2.AddConnection(newConn1);
        //                            newAtom1.AddConnection(newConn2);
        //                        }
        //                        // Neither atomic region has the point (possibly the first connection encountered).
        //                        else
        //                        {
        //                            // Arbitrary assignment
        //                            newAtom1.AddConnection(newConn1);
        //                            newAtom2.AddConnection(newConn2);
        //                        }
        //                    }

        //                    // Shift to the second (new) atomic region.
        //                    atom1 = false;
        //                }
        //            }
        //        }

        //        // This is not a splittable connection so just add it to the list.
        //        if (!found)
        //        {
        //            if (atom1) newAtom1.AddConnection(conn);
        //            else newAtom2.AddConnection(conn);
        //        }
        //    }

        //    //
        //    // Add this new segment as a connection to both atomic regions.
        //    //
        //    newAtom1.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner);
        //    newAtom2.AddConnection(intersections[0].Value, intersections[1].Value, ConnectionType.SEGMENT, owner);

        //    // Order the connections in the new regions we created.
        //    newAtom1.OrderConnections();
        //    newAtom2.OrderConnections();
        //    newAtoms.Add(newAtom1);
        //    newAtoms.Add(newAtom2);

        //    return newAtoms;
        //}

        public static void Overlap(List <Point> figurePoints, AtomicRegion thisAtom, AtomicRegion thatAtom, out List <AtomicRegion> toAdd, out List <AtomicRegion> toRemove)
        {
            //
            // Acquire all arcs and segments.
            //
            List <Arc>     graphArcs     = new List <Arc>();
            List <Segment> graphSegments = new List <Segment>();

            foreach (Connection thisConn in thisAtom.connections)
            {
                if (thisConn.type == ConnectionType.SEGMENT)
                {
                    graphSegments.Add(thisConn.segmentOrArc as Segment);
                }
                else
                {
                    graphArcs.Add(thisConn.segmentOrArc as Arc);
                }
            }

            foreach (Connection thatConn in thatAtom.connections)
            {
                if (thatConn.type == ConnectionType.SEGMENT)
                {
                    graphSegments.Add(thatConn.segmentOrArc as Segment);
                }
                else
                {
                    graphArcs.Add(thatConn.segmentOrArc as Arc);
                }
            }

            //
            // Clear collinearities of all segments / arcs.
            //
            List <Circle> circles = new List <Circle>(); // get the list of applicable circles to these atoms.

            foreach (Segment seg in graphSegments)
            {
                seg.ClearCollinear();
            }
            foreach (Arc arc in graphArcs)
            {
                Utilities.AddStructurallyUnique <Circle>(circles, arc.theCircle);
                arc.ClearCollinear();
            }

            //
            // All points of interest for these atoms.
            //
            List <Point> allPoints = new List <Point>();

            allPoints.AddRange(thisAtom.GetVertices());
            allPoints.AddRange(thatAtom.GetVertices());

            //
            // Determine 'collinearities' for the intersections.
            //
            List <AtomicRegion.IntersectionAgg> intersections = thisAtom.GetIntersections(figurePoints, thatAtom);

            List <Point> intersectionPts = new List <Point>();

            foreach (AtomicRegion.IntersectionAgg agg in intersections)
            {
                if (agg.intersection1 != null)
                {
                    if (!Utilities.HasStructurally <Point>(allPoints, agg.intersection1))
                    {
                        intersectionPts.Add(agg.intersection1);
                    }
                    agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection1);
                    agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection1);
                }
                if (agg.intersection2 != null)
                {
                    if (!Utilities.HasStructurally <Point>(allPoints, agg.intersection2))
                    {
                        intersectionPts.Add(agg.intersection2);
                    }
                    intersectionPts.Add(agg.intersection2);
                    agg.thisConn.segmentOrArc.AddCollinearPoint(agg.intersection2);
                    agg.thatConn.segmentOrArc.AddCollinearPoint(agg.intersection2);
                }
            }

            // Add any unlabeled intersection points.
            allPoints.AddRange(intersectionPts);

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

            // Add the points as nodes in the graph.
            foreach (Point pt in allPoints)
            {
                graph.AddNode(pt);
            }

            //
            // Edges are based on all the collinear relationships.
            //
            foreach (Segment segment in graphSegments)
            {
                for (int p = 0; p < segment.collinear.Count - 1; p++)
                {
                    graph.AddUndirectedEdge(segment.collinear[p], segment.collinear[p + 1],
                                            new Segment(segment.collinear[p], segment.collinear[p + 1]).Length,
                                            Area_Based_Analyses.Atomizer.UndirectedPlanarGraph.EdgeType.REAL_SEGMENT);
                }
            }

            foreach (Arc arc in graphArcs)
            {
                for (int p = 0; p < arc.collinear.Count - 1; p++)
                {
                    graph.AddUndirectedEdge(arc.collinear[p], arc.collinear[p + 1],
                                            new Segment(arc.collinear[p], arc.collinear[p + 1]).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, circles);

            //
            // Determine ownership of the atomic regions.
            //
            foreach (AtomicRegion atom in atoms)
            {
                if (thisAtom.Contains(atom))
                {
                    atom.AddOwners(thisAtom.owners);
                }
                if (thatAtom.Contains(atom))
                {
                    atom.AddOwners(thatAtom.owners);
                }
            }

            toAdd    = atoms;
            toRemove = new List <AtomicRegion>();
            toRemove.Add(thisAtom);
            toRemove.Add(thatAtom);
        }