// Assumes that points being passed in the list are connected and form a polygon.
        // Note that some error checking is done for robustness, but for the most part,
        // we have to rely on the user to feed us "correct" data
        public bool AddHole(List <TriangulationPoint> points, string name)
        {
            if (points == null)
            {
                return(false);
            }

            //// split our self-intersection sections into their own lists
            List <Contour> pts     = new List <Contour> ();
            int            listIdx = 0;

            {
                Contour c = new Contour(this, points, WindingOrderType.Unknown);
                pts.Add(c);

                // only constrain the points if we actually HAVE a bounding rect
                if (mPoints.Count > 1)
                {
                    // constrain the points to bounding rect
                    int numPoints = pts [listIdx].Count;
                    for (int i = 0; i < numPoints; ++i)
                    {
                        ConstrainPointToBounds(pts [listIdx] [i]);
                    }
                }
            }

            while (listIdx < pts.Count)
            {
                // simple sanity checking - remove duplicate coincident points before
                // we check the polygon: fast, simple algorithm that eliminate lots of problems
                // that only more expensive checks will find
                pts [listIdx].RemoveDuplicateNeighborPoints();
                pts [listIdx].WindingOrder = Point2DList.WindingOrderType.Default;

                bool bListOK = true;
                Point2DList.PolygonError err = pts [listIdx].CheckPolygon();
                while (bListOK && err != PolygonError.None)
                {
                    if ((err & PolygonError.NotEnoughVertices) == PolygonError.NotEnoughVertices)
                    {
                        bListOK = false;
                        continue;
                    }
                    if ((err & PolygonError.NotSimple) == PolygonError.NotSimple)
                    {
                        // split the polygons, remove the current list and add the resulting list to the end
                        //List<Point2DList> l = TriangulationUtil.SplitSelfIntersectingPolygon(pts[listIdx], pts[listIdx].Epsilon);
                        List <Point2DList> l = PolygonUtil.SplitComplexPolygon(pts [listIdx], pts [listIdx].Epsilon);
                        pts.RemoveAt(listIdx);
                        foreach (Point2DList newList in l)
                        {
                            Contour c = new Contour(this);
                            c.AddRange(newList);
                            pts.Add(c);
                        }
                        err = pts [listIdx].CheckPolygon();
                        continue;
                    }
                    if ((err & PolygonError.Degenerate) == PolygonError.Degenerate)
                    {
                        pts [listIdx].Simplify(this.Epsilon);
                        err = pts [listIdx].CheckPolygon();
                        continue;
                        //err &= ~(PolygonError.Degenerate);
                        //if (pts[listIdx].Count < 3)
                        //{
                        //    err |= PolygonError.NotEnoughVertices;
                        //    bListOK = false;
                        //    continue;
                        //}
                    }
                    if ((err & PolygonError.AreaTooSmall) == PolygonError.AreaTooSmall ||
                        (err & PolygonError.SidesTooCloseToParallel) == PolygonError.SidesTooCloseToParallel ||
                        (err & PolygonError.TooThin) == PolygonError.TooThin ||
                        (err & PolygonError.Unknown) == PolygonError.Unknown)
                    {
                        bListOK = false;
                        continue;
                    }
                    // non-convex polygons are ok
                    //if ((err & PolygonError.NotConvex) == PolygonError.NotConvex)
                    //{
                    //}
                }
                if (!bListOK && pts [listIdx].Count != 2)
                {
                    pts.RemoveAt(listIdx);
                }
                else
                {
                    ++listIdx;
                }
            }

            bool bOK = true;

            listIdx = 0;
            while (listIdx < pts.Count)
            {
                int numPoints = pts [listIdx].Count;
                if (numPoints < 2)
                {
                    // should not be possible by this point...
                    ++listIdx;
                    bOK = false;
                    continue;
                }
                else if (numPoints == 2)
                {
                    uint constraintCode        = TriangulationConstraint.CalculateContraintCode(pts [listIdx] [0], pts [listIdx] [1]);
                    TriangulationConstraint tc = null;
                    if (!mConstraintMap.TryGetValue(constraintCode, out tc))
                    {
                        tc = new TriangulationConstraint(pts [listIdx] [0], pts [listIdx] [1]);
                        AddConstraint(tc);
                    }
                }
                else
                {
                    Contour ph = new Contour(this, pts [listIdx], Point2DList.WindingOrderType.Unknown);
                    ph.WindingOrder = Point2DList.WindingOrderType.Default;
                    ph.Name         = name + ":" + listIdx.ToString();
                    mHoles.Add(ph);
                }
                ++listIdx;
            }

            return(bOK);
        }
示例#2
0
        public bool AddHole(List <TriangulationPoint> points, string name)
        {
            if (points == null)
            {
                return(false);
            }

            List <Contour> pts     = new List <Contour>();
            int            listIdx = 0;

            {
                Contour c = new Contour(this, points, WindingOrderType.Unknown);
                pts.Add(c);

                if (mPoints.Count > 1)
                {
                    int numPoints = pts[listIdx].Count;
                    for (int i = 0; i < numPoints; ++i)
                    {
                        ConstrainPointToBounds(pts[listIdx][i]);
                    }
                }
            }

            while (listIdx < pts.Count)
            {
                pts[listIdx].RemoveDuplicateNeighborPoints();
                pts[listIdx].WindingOrder = Point2DList.WindingOrderType.Default;

                bool bListOK = true;
                Point2DList.PolygonError err = pts[listIdx].CheckPolygon();
                while (bListOK && err != PolygonError.None)
                {
                    if ((err & PolygonError.NotEnoughVertices) == PolygonError.NotEnoughVertices)
                    {
                        bListOK = false;
                        continue;
                    }
                    if ((err & PolygonError.NotSimple) == PolygonError.NotSimple)
                    {
                        List <Point2DList> l = PolygonUtil.SplitComplexPolygon(pts[listIdx], pts[listIdx].Epsilon);
                        pts.RemoveAt(listIdx);
                        foreach (Point2DList newList in l)
                        {
                            Contour c = new Contour(this);
                            c.AddRange(newList);
                            pts.Add(c);
                        }
                        err = pts[listIdx].CheckPolygon();
                        continue;
                    }
                    if ((err & PolygonError.Degenerate) == PolygonError.Degenerate)
                    {
                        pts[listIdx].Simplify(this.Epsilon);
                        err = pts[listIdx].CheckPolygon();
                        continue;
                    }
                    if ((err & PolygonError.AreaTooSmall) == PolygonError.AreaTooSmall || (err & PolygonError.SidesTooCloseToParallel) == PolygonError.SidesTooCloseToParallel || (err & PolygonError.TooThin) == PolygonError.TooThin || (err & PolygonError.Unknown) == PolygonError.Unknown)
                    {
                        bListOK = false;
                        continue;
                    }
                }
                if (!bListOK && pts[listIdx].Count != 2)
                {
                    pts.RemoveAt(listIdx);
                }
                else
                {
                    ++listIdx;
                }
            }

            bool bOK = true;

            listIdx = 0;
            while (listIdx < pts.Count)
            {
                int numPoints = pts[listIdx].Count;
                if (numPoints < 2)
                {
                    ++listIdx;
                    bOK = false;
                    continue;
                }
                else if (numPoints == 2)
                {
                    uint constraintCode        = TriangulationConstraint.CalculateContraintCode(pts[listIdx][0], pts[listIdx][1]);
                    TriangulationConstraint tc = null;
                    if (!mConstraintMap.TryGetValue(constraintCode, out tc))
                    {
                        tc = new TriangulationConstraint(pts[listIdx][0], pts[listIdx][1]);
                        AddConstraint(tc);
                    }
                }
                else
                {
                    Contour ph = new Contour(this, pts[listIdx], Point2DList.WindingOrderType.Unknown);
                    ph.WindingOrder = Point2DList.WindingOrderType.Default;
                    ph.Name         = name + ":" + listIdx.ToString();
                    mHoles.Add(ph);
                }
                ++listIdx;
            }

            return(bOK);
        }