Пример #1
0
        /// <summary>
        /// Adds a new polygon ONLY if there is a unifications.
        /// Assumes current set is distinct.
        /// </summary>
        /// <param name="pPoly">The polygon to add if there is a union.</param>
        public bool AddIfUnify(C2DHoledPolyBase pPoly)
        {
            var TempSet  = new C2DHoledPolyBaseSet();
            var UnionSet = new C2DHoledPolyBaseSet();
            var grid     = new CGrid();

            while (Count > 0 && pPoly != null)
            {
                var pLast = this[Count - 1];
                this.RemoveAt(Count - 1);

                pLast.GetUnion(pPoly, UnionSet, grid);

                if (UnionSet.Count == 1)
                {
                    pPoly = null;
                    pLast = null;

                    AddAndUnify(UnionSet[0]);
                    UnionSet.Clear();
                }
                else
                {
                    //Debug.Assert(UnionSet.Count == 0);
                    UnionSet.Clear();
                    TempSet.Add(pLast);
                }
            }

            this.AddRange(TempSet);
            TempSet.Clear();

            return(pPoly == null);
        }
Пример #2
0
        /// <summary>
        /// Adds a new polygon set and looks for a possible unifications.
        /// Assumes both sets are distinct.
        /// </summary>
        /// <param name="pOther">The polygon set to add and possible unify.</param>
        public void AddAndUnify(C2DHoledPolyBaseSet pOther)
        {
            var TempSet = new C2DHoledPolyBaseSet();

            while (pOther.Count > 0)
            {
                var pLast = pOther[pOther.Count - 1];
                pOther.RemoveAt(pOther.Count - 1);

                if (!AddIfUnify(pLast))
                {
                    TempSet.Add(pLast);
                }
            }

            this.AddRange(TempSet);
        }
Пример #3
0
        /// <summary>
        /// Basic multiple unification.
        /// </summary>
        public void UnifyBasic()
        {
            var TempSet  = new C2DHoledPolyBaseSet();
            var UnionSet = new C2DHoledPolyBaseSet();

            while (Count > 0)
            {
                var pLast = this[Count - 1];
                this.RemoveAt(Count - 1);

                var bIntersect = false;
                var i          = 0;

                while (i < Count && !bIntersect)
                {
                    var grid = new CGrid();
                    this[i].GetUnion(pLast, UnionSet, grid);

                    if (UnionSet.Count == 1)
                    {
                        this[i]    = UnionSet[0];
                        bIntersect = true;
                    }
                    else
                    {
                        //Debug.Assert(UnionSet.Count == 0);
                        UnionSet.Clear();
                        i++;
                    }
                }

                if (!bIntersect)
                {
                    TempSet.Add(pLast);
                }
            }

            this.AddRange(TempSet);
        }
Пример #4
0
        /// <summary>
        /// Gets the boolean operation with the other. e.g. union / intersection.
        /// </summary>
        /// <param name="Other">The other polygon.</param>
        /// <param name="HoledPolys">The set to recieve the result.</param>
        /// <param name="bThisInside">The flag to indicate routes inside.</param>
        /// <param name="bOtherInside">The flag to indicate routes inside for the other.</param>
        /// <param name="grid">The degenerate settings.</param>
        public void GetBoolean(C2DPolyBase Other, List <C2DHoledPolyBase> HoledPolys,
                               bool bThisInside, bool bOtherInside,
                               CGrid grid)
        {
            if (BoundingRect.Overlaps(Other.BoundingRect))
            {
                switch (grid.DegenerateHandling)
                {
                case CGrid.eDegenerateHandling.None:
                {
                    var Routes1 = new C2DLineBaseSetSet();
                    var Routes2 = new C2DLineBaseSetSet();
                    C2DPolyBase.GetRoutes(this, bThisInside, Other, bOtherInside, Routes1, Routes2);
                    Routes1.ExtractAllOf(Routes2);

                    if (Routes1.Count > 0)
                    {
                        // Add all the joining routes together to form closed routes
                        Routes1.MergeJoining();
                        // Set up some temporary polygons.
                        var Polygons = new List <C2DPolyBase>();
                        // Turn the routes into polygons.
                        for (var i = Routes1.Count - 1; i >= 0; i--)
                        {
                            if (Routes1[i].IsClosed(true) && Routes1[i].Count > 2)
                            {
                                Polygons.Add(new C2DPolyBase());
                                Polygons[Polygons.Count - 1].CreateDirect(Routes1[i]);
                            }
                            else
                            {
                                //   Debug.Assert(false);
                                grid.LogDegenerateError();
                            }
                        }


                        // Set up some temporary holed polygons
                        var NewComPolys = new C2DHoledPolyBaseSet();
                        // Turn the set of polygons into holed polygons. Not needed for intersection.
                        if (!(bThisInside && bOtherInside))
                        {
                            C2DHoledPolyBase.PolygonsToHoledPolygons(NewComPolys, Polygons);
                            if (NewComPolys.Count != 1)
                            {
                                //   Debug.Assert(false);
                                grid.LogDegenerateError();
                            }
                        }
                        else
                        {
                            for (var i = 0; i < Polygons.Count; i++)
                            {
                                HoledPolys.Add(new C2DHoledPolyBase(Polygons[i]));
                            }
                        }

                        // Now add them all to the provided set.
                        for (var i = 0; i < NewComPolys.Count; i++)
                        {
                            HoledPolys.Add(NewComPolys[i]);
                        }
                    }
                }
                break;

                case CGrid.eDegenerateHandling.RandomPerturbation:
                {
                    var OtherCopy = new C2DPolyBase(Other);
                    OtherCopy.RandomPerturb();
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    GetBoolean(OtherCopy, HoledPolys, bThisInside, bOtherInside, grid);
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.RandomPerturbation;
                }
                break;

                case CGrid.eDegenerateHandling.DynamicGrid:
                {
                    var Rect = new C2DRect();
                    if (this.BoundingRect.Overlaps(Other.BoundingRect, Rect))
                    {
                        var dOldGrid = grid.GridSize;
                        grid.SetToMinGridSize(Rect, false);
                        grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid;
                        GetBoolean(Other, HoledPolys, bThisInside, bOtherInside, grid);
                        grid.DegenerateHandling = CGrid.eDegenerateHandling.DynamicGrid;
                    }
                }
                break;

                case CGrid.eDegenerateHandling.PreDefinedGrid:
                {
                    var P1 = new C2DPolyBase(this);
                    var P2 = new C2DPolyBase(Other);
                    P1.SnapToGrid(grid);
                    P2.SnapToGrid(grid);
                    var V1            = new C2DVector(P1.BoundingRect.TopLeft, P2.BoundingRect.TopLeft);
                    var dPerturbation = grid.GridSize;                     // ensure it snaps back to original grid positions.
                    if (V1.i > 0)
                    {
                        V1.i = dPerturbation;
                    }
                    else
                    {
                        V1.i = -dPerturbation;          // move away slightly if possible
                    }
                    if (V1.j > 0)
                    {
                        V1.j = dPerturbation;
                    }
                    else
                    {
                        V1.j = -dPerturbation;     // move away slightly if possible
                    }
                    V1.i *= 0.411923;              // ensure it snaps back to original grid positions.
                    V1.j *= 0.313131;              // ensure it snaps back to original grid positions.

                    P2.Move(V1);
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    P1.GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid);

                    for (var i = 0; i < HoledPolys.Count; i++)
                    {
                        HoledPolys[i].SnapToGrid(grid);
                    }

                    grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid;
                }
                break;

                case CGrid.eDegenerateHandling.PreDefinedGridPreSnapped:
                {
                    var P2            = new C2DPolyBase(Other);
                    var V1            = new C2DVector(this.BoundingRect.TopLeft, P2.BoundingRect.TopLeft);
                    var dPerturbation = grid.GridSize;                     // ensure it snaps back to original grid positions.
                    if (V1.i > 0)
                    {
                        V1.i = dPerturbation;
                    }
                    else
                    {
                        V1.i = -dPerturbation;     // move away slightly if possible
                    }
                    if (V1.j > 0)
                    {
                        V1.j = dPerturbation;
                    }
                    else
                    {
                        V1.j = -dPerturbation;     // move away slightly if possible
                    }
                    V1.i *= 0.411923;              // ensure it snaps back to original grid positions.
                    V1.j *= 0.313131;              // ensure it snaps back to original grid positions.

                    P2.Move(V1);
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid);

                    for (var i = 0; i < HoledPolys.Count; i++)
                    {
                        HoledPolys[i].SnapToGrid(grid);
                    }
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGridPreSnapped;
                }
                break;
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Unification by growing shapes of fairly equal size (fastest for large groups).
        /// </summary>
        /// <param name="grid">The CGrid with the degenerate settings.</param>
        public void UnifyProgressive(CGrid grid)
        {
            // Record the degenerate handling so we can reset.
            CGrid.eDegenerateHandling DegenerateHandling = grid.DegenerateHandling;
            switch (grid.DegenerateHandling)
            {
            case CGrid.eDegenerateHandling.RandomPerturbation:
                for (var i = 0; i < Count; i++)
                {
                    this[i].RandomPerturb();
                }
                grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                break;

            case CGrid.eDegenerateHandling.DynamicGrid:

                break;

            case CGrid.eDegenerateHandling.PreDefinedGrid:
                for (var i = 0; i < Count; i++)
                {
                    this[i].SnapToGrid(grid);
                }
                grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGridPreSnapped;
                break;

            case CGrid.eDegenerateHandling.PreDefinedGridPreSnapped:

                break;
            }


            var NoUnionSet   = new C2DHoledPolyBaseSet();
            var PossUnionSet = new C2DHoledPolyBaseSet();
            var SizeHoldSet  = new C2DHoledPolyBaseSet();
            var UnionSet     = new C2DHoledPolyBaseSet();
            var TempSet      = new C2DHoledPolyBaseSet();

            var nThreshold = GetMinLineCount();

            if (nThreshold == 0)
            {
                nThreshold = 10;                // avoid infinate loop.
            }
            // Assumed all are size held to start
            SizeHoldSet.AddRange(this);
            this.Clear();

            do
            {
                // double the threshold
                nThreshold *= 3;

                // Put all the possible intersects back in this.
                this.AddRange(PossUnionSet);
                PossUnionSet.Clear();

                // Put all the size held that are small enough back (or in to start with)
                while (SizeHoldSet.Count > 0)
                {
                    var pLast = SizeHoldSet[SizeHoldSet.Count - 1];
                    SizeHoldSet.RemoveAt(SizeHoldSet.Count - 1);

                    if (pLast.GetLineCount() > nThreshold)
                    {
                        TempSet.Add(pLast);
                    }
                    else
                    {
                        this.Add(pLast);
                    }
                }
                SizeHoldSet.AddRange(TempSet);
                TempSet.Clear();


                // Cycle through all popping the last and finding a union
                while (Count > 0)
                {
                    var pLast = this[Count - 1];
                    this.RemoveAt(Count - 1);

                    var bIntersect = false;

                    var i = 0;
                    while (i < Count && !bIntersect)
                    {
                        this[i].GetUnion(pLast, UnionSet, grid);

                        if (UnionSet.Count == 1)
                        {
                            var pUnion = UnionSet[UnionSet.Count - 1];
                            UnionSet.RemoveAt(UnionSet.Count - 1);

                            if (pUnion.GetLineCount() > nThreshold)
                            {
                                RemoveAt(i);
                                SizeHoldSet.Add(pUnion);
                            }
                            else
                            {
                                this[i] = pUnion;
                                i++;
                            }

                            bIntersect = true;
                        }
                        else
                        {
                            if (UnionSet.Count != 0)
                            {
                                grid.LogDegenerateError();
                            }
                            UnionSet.Clear();
                            i++;
                        }
                    }

                    if (!bIntersect)
                    {
                        var bPosInterSect = false;
                        for (var j = 0; j < SizeHoldSet.Count; j++)
                        {
                            if (pLast.Rim.BoundingRect.Overlaps(
                                    SizeHoldSet[j].Rim.BoundingRect))
                            {
                                bPosInterSect = true;
                                break;
                            }
                        }

                        if (bPosInterSect)
                        {
                            PossUnionSet.Add(pLast);
                        }
                        else
                        {
                            NoUnionSet.Add(pLast);
                        }
                    }
                }
            }while (SizeHoldSet.Count != 0);


            this.AddRange(NoUnionSet);
            NoUnionSet.Clear();

            grid.DegenerateHandling = DegenerateHandling;
        }
Пример #6
0
        /// <summary>
        /// Returns the boolean result (e.g. union) of 2 shapes. Boolean Operation defined by
        /// the inside / outside flags.
        /// </summary>
        /// <param name="Other">Other polygon.</param>
        /// <param name="HoledPolys">Set of polygons to recieve the result.</param>
        /// <param name="bThisInside">Does the operation require elements of this INSIDE the other.</param>
        /// <param name="bOtherInside">Does the operation require elements of the other INSIDE this.</param>
        /// <param name="grid">The grid with the degenerate settings.</param>
        public void GetBoolean(C2DHoledPolyBase Other, List <C2DHoledPolyBase> HoledPolys,
                               bool bThisInside, bool bOtherInside,
                               CGrid grid)
        {
            if (_Rim.Lines.Count == 0 || Other.Rim.Lines.Count == 0)
            {
                return;
            }

            if (_Rim.BoundingRect.Overlaps(Other.Rim.BoundingRect))
            {
                switch (grid.DegenerateHandling)
                {
                case CGrid.eDegenerateHandling.None:
                {
                    var CompleteHoles1 = new List <C2DPolyBase>();
                    var CompleteHoles2 = new List <C2DPolyBase>();
                    var Routes1        = new C2DLineBaseSetSet();
                    var Routes2        = new C2DLineBaseSetSet();
                    GetRoutes(this, bThisInside, Other, bOtherInside, Routes1, Routes2,
                              CompleteHoles1, CompleteHoles2, grid);

                    Routes1.ExtractAllOf(Routes2);

                    if (Routes1.Count > 0)
                    {
                        Routes1.MergeJoining();

                        var Polygons = new List <C2DPolyBase>();

                        for (var i = Routes1.Count - 1; i >= 0; i--)
                        {
                            C2DLineBaseSet pRoute = Routes1[i];
                            if (pRoute.IsClosed(true))
                            {
                                Polygons.Add(new C2DPolyBase());
                                Polygons[Polygons.Count - 1].CreateDirect(pRoute);
                            }
                            else
                            {
                                //   Debug.Assert(false);
                                grid.LogDegenerateError();
                            }
                        }

                        var NewComPolys = new C2DHoledPolyBaseSet();

                        PolygonsToHoledPolygons(NewComPolys, Polygons);

                        NewComPolys.AddKnownHoles(CompleteHoles1);

                        NewComPolys.AddKnownHoles(CompleteHoles2);

                        if (!bThisInside && !bOtherInside && NewComPolys.Count != 1)
                        {
                            //  Debug.Assert(false);
                            grid.LogDegenerateError();
                        }


                        HoledPolys.AddRange(NewComPolys);

                        NewComPolys.Clear();
                    }
                }
                break;

                case CGrid.eDegenerateHandling.RandomPerturbation:
                {
                    var OtherCopy = new C2DHoledPolyBase(Other);
                    OtherCopy.RandomPerturb();
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    GetBoolean(OtherCopy, HoledPolys, bThisInside, bOtherInside, grid);
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.RandomPerturbation;
                }
                break;

                case CGrid.eDegenerateHandling.DynamicGrid:
                {
                    var Rect = new C2DRect();
                    if (_Rim.BoundingRect.Overlaps(Other.Rim.BoundingRect, Rect))
                    {
                        //double dOldGrid = CGrid::GetGridSize();
                        grid.SetToMinGridSize(Rect, false);
                        grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid;
                        GetBoolean(Other, HoledPolys, bThisInside, bOtherInside, grid);
                        grid.DegenerateHandling = CGrid.eDegenerateHandling.DynamicGrid;
                    }
                }
                break;

                case CGrid.eDegenerateHandling.PreDefinedGrid:
                {
                    var P1 = new C2DHoledPolyBase(this);
                    var P2 = new C2DHoledPolyBase(Other);
                    P1.SnapToGrid(grid);
                    P2.SnapToGrid(grid);
                    var V1            = new C2DVector(P1.Rim.BoundingRect.TopLeft, P2.Rim.BoundingRect.TopLeft);
                    var dPerturbation = grid.GridSize;                     // ensure it snaps back to original grid positions.
                    if (V1.i > 0)
                    {
                        V1.i = dPerturbation;
                    }
                    else
                    {
                        V1.i = -dPerturbation;          // move away slightly if possible
                    }
                    if (V1.j > 0)
                    {
                        V1.j = dPerturbation;
                    }
                    else
                    {
                        V1.j = -dPerturbation;     // move away slightly if possible
                    }
                    V1.i *= 0.411923;              // ensure it snaps back to original grid positions.
                    V1.j *= 0.313131;              // ensure it snaps back to original grid positions.

                    P2.Move(V1);
                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    P1.GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid);

                    for (var i = 0; i < HoledPolys.Count; i++)
                    {
                        HoledPolys[i].SnapToGrid(grid);
                    }

                    grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGrid;
                }
                break;

                case CGrid.eDegenerateHandling.PreDefinedGridPreSnapped:
                {
                    var P2            = new C2DHoledPolyBase(Other);
                    var V1            = new C2DVector(_Rim.BoundingRect.TopLeft, P2.Rim.BoundingRect.TopLeft);
                    var dPerturbation = grid.GridSize;
                    if (V1.i > 0)
                    {
                        V1.i = dPerturbation;
                    }
                    else
                    {
                        V1.i = -dPerturbation;     // move away slightly if possible
                    }
                    if (V1.j > 0)
                    {
                        V1.j = dPerturbation;
                    }
                    else
                    {
                        V1.j = -dPerturbation;     // move away slightly if possible
                    }
                    V1.i *= 0.411923;              // ensure it snaps back to original grid positions.
                    V1.j *= 0.313131;              // ensure it snaps back to original grid positions.
                    P2.Move(V1);

                    grid.DegenerateHandling = CGrid.eDegenerateHandling.None;
                    GetBoolean(P2, HoledPolys, bThisInside, bOtherInside, grid);

                    for (var i = 0; i < HoledPolys.Count; i++)
                    {
                        HoledPolys[i].SnapToGrid(grid);
                    }

                    grid.DegenerateHandling = CGrid.eDegenerateHandling.PreDefinedGridPreSnapped;
                }
                break;
                }        // switch
            }
        }