示例#1
0
        /// <summary>
        /// Adds the other to this if there is a common end i.e. they can be joined up.
        /// </summary>
        /// <param name="Other">Input. The other set.</param>
        public bool AddIfCommonEnd(C2DLineBaseSet Other)
        {
            Debug.Assert(!IsClosed(true));
            Debug.Assert(!Other.IsClosed(true));

            var nThisCount = Count;

            if (nThisCount < 1)
            {
                return(false);
            }

            var nOtherCount = Other.Count;

            if (nOtherCount < 1)
            {
                return(false);
            }

            if (this[0].GetPointFrom().PointEqualTo(Other[0].GetPointFrom()))
            {
                ReverseDirection();

                this.ExtractAllOf(Other);

                return(true);
            }
            else if (this[0].GetPointFrom().PointEqualTo(Other[nOtherCount - 1].GetPointTo()))
            {
                ReverseDirection();

                Other.ReverseDirection();

                this.ExtractAllOf(Other);

                return(true);
            }
            else if (this[nThisCount - 1].GetPointTo().PointEqualTo(Other[0].GetPointFrom()))
            {
                this.ExtractAllOf(Other);

                return(true);
            }
            else if (this[nThisCount - 1].GetPointTo().PointEqualTo(Other[nOtherCount - 1].GetPointTo()))
            {
                Other.ReverseDirection();

                this.ExtractAllOf(Other);

                return(true);
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Returns true if there are crossing lines.
        /// </summary>
        public bool HasCrossingLines()
        {
            var Lines = new C2DLineBaseSet();

            Lines.InsertRange(0, _Rim.Lines);

            for (var i = 0; i < _Holes.Count; i++)
            {
                Lines.InsertRange(0, _Holes[i].Lines);
            }

            return(Lines.HasCrossingLines());
        }
        /// <summary>
        /// Returns the routes (collection of lines and sublines) either inside or outside another
        /// Given the intersection points.
        /// </summary>
        /// <param name="IntPts">The intersection points of this with the other polygon.</param>
        /// <param name="IntIndexes">The corresponding line indexes.</param>
        /// <param name="Routes">Output. The routes to get the result.</param>
        /// <param name="bStartInside">True if this polygon starts inside the other.</param>
        /// <param name="bRoutesInside">True if we require routes of this polygon inside the other.</param>
        public void GetRoutes(C2DPointSet IntPts, List <int> IntIndexes,
                              C2DLineBaseSetSet Routes, bool bStartInside, bool bRoutesInside)
        {
            // Make sure the intersection indexes and points are the same size.
            if (IntIndexes.Count != IntPts.Count)
            {
                Debug.Assert(false);
                return;
            }
            // Set up a new collection of routes.
            var NewRoutes = new C2DLineBaseSetSet();

            // If the polygon has no points then return.
            if (_Lines.Count < 1)
            {
                return;
            }
            // Sort the intersections by index so we can go through them in order.
            IntPts.SortByIndex(IntIndexes);

            // Set the inside / outside flag to the same as the start inside / outside flag.
            var bInside = bStartInside;

            // If we are inside and want route inside or outside and want routes outside then add a new route.
            if (bInside == bRoutesInside)
            {
                NewRoutes.Add(new C2DLineBaseSet());
            }

            // The current index of the intersects.
            var usCurrentIntIndex = 0;

            // cycle through the lines on the polygon.
            for (var i = 0; i < Lines.Count; i++)
            {
                // Set up a list of intersection points on this line only.
                var IntsOnLine = new C2DPointSet();
                // Cycle through all intersections on this line (leaving the usCurrentIntIndex at the next intersected line).
                while (usCurrentIntIndex < IntIndexes.Count && IntIndexes[usCurrentIntIndex] == i)
                {
                    // Add a copy of the points on this line that are intersections
                    IntsOnLine.AddCopy(IntPts[usCurrentIntIndex]);
                    usCurrentIntIndex++;
                }

                // If the line in question intersects the other poly then we have left / entered.
                if (IntsOnLine.Count > 0)
                {
                    var SubLines = new C2DLineBaseSet();
                    Lines[i].GetSubLines(IntsOnLine, SubLines);

                    while (SubLines.Count > 1)
                    {
                        if (bInside == bRoutesInside)
                        {
                            // We have 1. Left and want route in. OR 2. Entered and want routes out.
                            NewRoutes[NewRoutes.Count - 1].Add(SubLines.ExtractAt(0));
                            bInside = true ^ bRoutesInside;
                        }
                        else
                        {
                            NewRoutes.Add(new C2DLineBaseSet());
                            bInside = false ^ bRoutesInside;
                            SubLines.RemoveAt(0);
                        }
                    }
                    if (bInside == bRoutesInside)
                    {
                        NewRoutes[NewRoutes.Count - 1].Add(SubLines.ExtractAt(SubLines.Count - 1));
                    }
                    else
                    {
                        SubLines.RemoveAt(SubLines.Count - 1);
                    }
                }
                // Otherwise, if we are e.g. inside and want routes in the keep adding the end poitn of the line.
                else if (bInside == bRoutesInside)
                {
                    NewRoutes[NewRoutes.Count - 1].AddCopy(Lines[i]);
                }
            }
            // Put all the new routes into the provided collection.
            Routes.ExtractAllOf(NewRoutes);
        }
示例#4
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
            }
        }