示例#1
0
        // 从三角序列创建矢量图层
        static GeomLayer FromTriangles(IEnumerable <Triangle> triangles, List <GeomPoint> originalPoints)
        {
            // 创建字典用于反查
            var pt_mapper = new Dictionary <Vector2, GeomPoint>();

            foreach (GeomPoint tmp in originalPoints)
            {
                pt_mapper[tmp] = tmp;
            }

            // 构造矢量图层
            GeomLayer result = new GeomLayer(GeomType.Polygon);
            var       g_points = new Dictionary <Vector2, GeomPoint>();
            var       g_arcs = new Dictionary <Edge, GeomArc>();
            int       point_cnt = 0, arc_cnt = 0, poly_cnt = 0;

            foreach (Triangle tri in triangles)
            {
                // 按需创建点
                foreach (Vector2 tmp in tri.Points())
                {
                    if (!g_points.ContainsKey(tmp))
                    {
                        var new_point = pt_mapper[tmp].Copy(); // 反查原始数据
                        new_point.id  = ++point_cnt;
                        g_points[tmp] = new_point;
                    }
                }

                // 去重获取三边
                var arcs = new List <GeomArc>();
                foreach (var tmp in tri.Edges())
                {
                    GeomArc cur_arc;
                    if (g_arcs.ContainsKey(tmp))
                    {
                        cur_arc = g_arcs[tmp];
                    }
                    else
                    {
                        cur_arc     = new GeomArc(new GeomPoint[] { g_points[tmp.Item1], g_points[tmp.Item2] }, ++arc_cnt);
                        g_arcs[tmp] = g_arcs[tmp.Reverse()] = cur_arc;
                    }
                    arcs.Add(cur_arc);
                }

                // 创建三角形
                GeomPoly tri_poly = new GeomPoly(arcs, ++poly_cnt);
                result.polygons.Add(tri_poly);
            }

            // 加入点集、边集
            result.points.AddRange(g_points.Values);
            result.arcs.AddRange(g_arcs.Values);

            return(result);
        }
        /** Look-up table to relate polygon key with the vertices that should be used for
            the sub polygon in marching squares
        **/

        /** Perform a single celled marching square for for the given cell defined by (x0,y0) (x1,y1)
            using the function f for recursive interpolation, given the look-up table 'fs' of
            the values of 'f' at cell vertices with the result to be stored in 'poly' given the actual
            coordinates of 'ax' 'ay' in the marching squares mesh.
        **/

        private static int MarchSquare(sbyte[,] f, sbyte[,] fs, ref GeomPoly poly, int ax, int ay, float x0, float y0,
                                       float x1, float y1, int bin)
        {
            //key lookup
            int key = 0;
            sbyte v0 = fs[ax, ay];
            if (v0 < 0) key |= 8;
            sbyte v1 = fs[ax + 1, ay];
            if (v1 < 0) key |= 4;
            sbyte v2 = fs[ax + 1, ay + 1];
            if (v2 < 0) key |= 2;
            sbyte v3 = fs[ax, ay + 1];
            if (v3 < 0) key |= 1;

            int val = _lookMarch[key];
            if (val != 0)
            {
                CxFastListNode<Vector2> pi = null;
                for (int i = 0; i < 8; i++)
                {
                    Vector2 p;
                    if ((val & (1 << i)) != 0)
                    {
                        if (i == 7 && (val & 1) == 0)
                            poly.Points.Add(p = new Vector2(x0, Ylerp(y0, y1, x0, v0, v3, f, bin)));
                        else
                        {
                            if (i == 0) p = new Vector2(x0, y0);
                            else if (i == 2) p = new Vector2(x1, y0);
                            else if (i == 4) p = new Vector2(x1, y1);
                            else if (i == 6) p = new Vector2(x0, y1);

                            else if (i == 1) p = new Vector2(Xlerp(x0, x1, y0, v0, v1, f, bin), y0);
                            else if (i == 5) p = new Vector2(Xlerp(x0, x1, y1, v3, v2, f, bin), y1);

                            else if (i == 3) p = new Vector2(x1, Ylerp(y0, y1, x1, v1, v2, f, bin));
                            else p = new Vector2(x0, Ylerp(y0, y1, x0, v0, v3, f, bin));

                            pi = poly.Points.Insert(pi, p);
                        }
                        poly.Length++;
                    }
                }
                //poly.simplify(float.Epsilon,float.Epsilon);
            }
            return key;
        }
示例#3
0
        // 2.1 从指定弧段与端点开始搜索相连多边形
        static void PolyTopoGroup(GeomPoint pt, GeomArc arc)
        {
            inners = new HashSet <GeomPoly>();
            stack  = new LinkedList <Tuple <GeomPoint, GeomArc> >();
            stack.AddFirst(new Tuple <GeomPoint, GeomArc>(pt, arc));

            while (stack.Count > 0)
            {
                var data = stack.First;
                stack.RemoveFirst();
                PolyTopoUnit(data.Value);
            }

            if (inners.Count == 0)
            {
                return;
            }

            // 获取并删除外包多边形(面积最大)
            GeomPoly outer = null;

            if (inners.Count > 1)
            {
                outer = null;
                foreach (var poly in inners)
                {
                    if (outer == null || outer.OuterArea < poly.OuterArea)
                    {
                        outer = poly;
                    }
                }
                inners.Remove(outer);
            }
            else
            {
                outer = inners.First();
            }

            // 加入待处理孔洞列表
            holesGroup.Add(new Tuple <GeomPoly, HashSet <GeomPoly> >(outer, inners));

            cPoly.AddRange(inners);
        }
示例#4
0
        // 2.1.1 搜索相连多边形:单元操作,返回当前搜索
        static void PolyTopoUnit(Tuple <GeomPoint, GeomArc> data)
        {
            if (arcUsed.Contains(data))
            {
                return;
            }
            var res = new List <Tuple <GeomPoint, GeomArc> >();

            // 搜索直到首尾相接
            while (true)
            {
                // 加入当前弧段
                res.Add(data);
                arcUsed.Add(data);
                // 获取下一弧段
                GeomPoint prevPt  = data.Item1;
                GeomArc   prevArc = data.Item2;
                GeomPoint nextPt  = prevArc.First;
                if (nextPt == prevPt)
                {
                    nextPt = prevArc.Last;
                }
                GeomArc nextArc = vertNext[nextPt][data.Item2];
                data = new Tuple <GeomPoint, GeomArc>(nextPt, prevArc); // 同弧段不同顶点
                if (!arcUsed.Contains(data))
                {
                    stack.AddFirst(data);
                }
                data = new Tuple <GeomPoint, GeomArc>(nextPt, nextArc);
                // 首尾相接时跳出
                if (data.Equals(res[0]))
                {
                    break;
                }
            }

            // 创造多边形
            var newPoly = new GeomPoly(from pair in res select pair.Item2);

            inners.Add(newPoly);
        }
 public GeomPolyVal(GeomPoly geomP, int K)
 {
     GeomP = geomP;
     Key   = K;
 }
        /** Used in polygon composition to composit polygons into scan lines
         * Combining polya and polyb into one super-polygon stored in polya.
         **/

        private static void CombLeft(ref GeomPoly polya, ref GeomPoly polyb)
        {
            CxFastList <Vector2>     ap = polya.Points;
            CxFastList <Vector2>     bp = polyb.Points;
            CxFastListNode <Vector2> ai = ap.Begin();
            CxFastListNode <Vector2> bi = bp.Begin();

            Vector2 b = bi.Elem();
            CxFastListNode <Vector2> prea = null;

            while (ai != ap.End())
            {
                Vector2 a = ai.Elem();
                if (VecDsq(a, b) < Settings.Epsilon)
                {
                    //ignore shared vertex if parallel
                    if (prea != null)
                    {
                        Vector2 a0 = prea.Elem();
                        b = bi.Next().Elem();

                        Vector2 u = a - a0;

                        //vec_new(u); vec_sub(a.p.p, a0.p.p, u);
                        Vector2 v = b - a;

                        //vec_new(v); vec_sub(b.p.p, a.p.p, v);
                        float dot = VecCross(u, v);
                        if (dot * dot < Settings.Epsilon)
                        {
                            ap.Erase(prea, ai);
                            polya.Length--;
                            ai = prea;
                        }
                    }

                    //insert polyb into polya
                    bool fst = true;
                    CxFastListNode <Vector2> preb = null;
                    while (!bp.Empty())
                    {
                        Vector2 bb = bp.Front();
                        bp.Pop();
                        if (!fst && !bp.Empty())
                        {
                            ai = ap.Insert(ai, bb);
                            polya.Length++;
                            preb = ai;
                        }

                        fst = false;
                    }

                    //ignore shared vertex if parallel
                    ai = ai.Next();
                    Vector2 a1 = ai.Elem();
                    ai = ai.Next();
                    if (ai == ap.End())
                    {
                        ai = ap.Begin();
                    }

                    Vector2 a2  = ai.Elem();
                    Vector2 a00 = preb.Elem();
                    Vector2 uu  = a1 - a00;

                    //vec_new(u); vec_sub(a1.p, a0.p, u);
                    Vector2 vv = a2 - a1;

                    //vec_new(v); vec_sub(a2.p, a1.p, v);
                    float dot1 = VecCross(uu, vv);
                    if (dot1 * dot1 < Settings.Epsilon)
                    {
                        ap.Erase(preb, preb.Next());
                        polya.Length--;
                    }

                    return;
                }

                prea = ai;
                ai   = ai.Next();
            }
        }
        /// <summary>
        /// Marching squares over the given domain using the mesh defined via the dimensions
        ///    (wid,hei) to build a set of polygons such that f(x,y) less than 0, using the given number
        ///    'bin' for recursive linear inteprolation along cell boundaries.
        ///
        ///    if 'comb' is true, then the polygons will also be composited into larger possible concave
        ///    polygons.
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="cellWidth"></param>
        /// <param name="cellHeight"></param>
        /// <param name="f"></param>
        /// <param name="lerpCount"></param>
        /// <param name="combine"></param>
        /// <returns></returns>
        public static List <Vertices> DetectSquares(AABB domain, float cellWidth, float cellHeight, sbyte[,] f,
                                                    int lerpCount, bool combine)
        {
            CxFastList <GeomPoly> ret          = new CxFastList <GeomPoly>();
            List <Vertices>       verticesList = new List <Vertices>();

            //NOTE: removed assignments as they were not used.
            List <GeomPoly> polyList;
            GeomPoly        gp;

            int  xn = (int)(domain.Extents.X * 2 / cellWidth);
            bool xp = xn == (domain.Extents.X * 2 / cellWidth);
            int  yn = (int)(domain.Extents.Y * 2 / cellHeight);
            bool yp = yn == (domain.Extents.Y * 2 / cellHeight);

            if (!xp)
            {
                xn++;
            }

            if (!yp)
            {
                yn++;
            }

            sbyte[,] fs       = new sbyte[xn + 1, yn + 1];
            GeomPolyVal[,] ps = new GeomPolyVal[xn + 1, yn + 1];

            //populate shared function lookups.
            for (int x = 0; x < xn + 1; x++)
            {
                int x0;
                if (x == xn)
                {
                    x0 = (int)domain.UpperBound.X;
                }
                else
                {
                    x0 = (int)(x * cellWidth + domain.LowerBound.X);
                }

                for (int y = 0; y < yn + 1; y++)
                {
                    int y0;
                    if (y == yn)
                    {
                        y0 = (int)domain.UpperBound.Y;
                    }
                    else
                    {
                        y0 = (int)(y * cellHeight + domain.LowerBound.Y);
                    }

                    fs[x, y] = f[x0, y0];
                }
            }

            //generate sub-polys and combine to scan lines
            for (int y = 0; y < yn; y++)
            {
                float y0 = y * cellHeight + domain.LowerBound.Y;
                float y1;
                if (y == yn - 1)
                {
                    y1 = domain.UpperBound.Y;
                }
                else
                {
                    y1 = y0 + cellHeight;
                }

                GeomPoly pre = null;
                for (int x = 0; x < xn; x++)
                {
                    float x0 = x * cellWidth + domain.LowerBound.X;
                    float x1;
                    if (x == xn - 1)
                    {
                        x1 = domain.UpperBound.X;
                    }
                    else
                    {
                        x1 = x0 + cellWidth;
                    }

                    gp = new GeomPoly();

                    int key = MarchSquare(f, fs, ref gp, x, y, x0, y0, x1, y1, lerpCount);
                    if (gp.Length != 0)
                    {
                        if (combine && pre != null && (key & 9) != 0)
                        {
                            CombLeft(ref pre, ref gp);
                            gp = pre;
                        }
                        else
                        {
                            ret.Add(gp);
                        }

                        ps[x, y] = new GeomPolyVal(gp, key);
                    }
                    else
                    {
                        gp = null;
                    }

                    pre = gp;
                }
            }

            if (!combine)
            {
                polyList = ret.GetListOfElements();

                foreach (GeomPoly poly in polyList)
                {
                    verticesList.Add(new Vertices(poly.Points.GetListOfElements()));
                }

                return(verticesList);
            }

            //combine scan lines together
            for (int y = 1; y < yn; y++)
            {
                int x = 0;
                while (x < xn)
                {
                    GeomPolyVal p = ps[x, y];

                    //skip along scan line if no polygon exists at this point
                    if (p == null)
                    {
                        x++;
                        continue;
                    }

                    //skip along if current polygon cannot be combined above.
                    if ((p.Key & 12) == 0)
                    {
                        x++;
                        continue;
                    }

                    //skip along if no polygon exists above.
                    GeomPolyVal u = ps[x, y - 1];
                    if (u == null)
                    {
                        x++;
                        continue;
                    }

                    //skip along if polygon above cannot be combined with.
                    if ((u.Key & 3) == 0)
                    {
                        x++;
                        continue;
                    }

                    float ax = x * cellWidth + domain.LowerBound.X;
                    float ay = y * cellHeight + domain.LowerBound.Y;

                    CxFastList <Vector2> bp = p.GeomP.Points;
                    CxFastList <Vector2> ap = u.GeomP.Points;

                    //skip if it's already been combined with above polygon
                    if (u.GeomP == p.GeomP)
                    {
                        x++;
                        continue;
                    }

                    //combine above (but disallow the hole thingies
                    CxFastListNode <Vector2> bi = bp.Begin();
                    while (Square(bi.Elem().Y - ay) > Settings.Epsilon || bi.Elem().X < ax)
                    {
                        bi = bi.Next();
                    }

                    //NOTE: Unused
                    //Vector2 b0 = bi.elem();
                    Vector2 b1 = bi.Next().Elem();
                    if (Square(b1.Y - ay) > Settings.Epsilon)
                    {
                        x++;
                        continue;
                    }

                    bool brk = true;
                    CxFastListNode <Vector2> ai = ap.Begin();
                    while (ai != ap.End())
                    {
                        if (VecDsq(ai.Elem(), b1) < Settings.Epsilon)
                        {
                            brk = false;
                            break;
                        }

                        ai = ai.Next();
                    }

                    if (brk)
                    {
                        x++;
                        continue;
                    }

                    CxFastListNode <Vector2> bj = bi.Next().Next();
                    if (bj == bp.End())
                    {
                        bj = bp.Begin();
                    }

                    while (bj != bi)
                    {
                        ai = ap.Insert(ai, bj.Elem());                         // .clone()
                        bj = bj.Next();
                        if (bj == bp.End())
                        {
                            bj = bp.Begin();
                        }

                        u.GeomP.Length++;
                    }

                    //u.p.simplify(float.Epsilon,float.Epsilon);
                    //
                    ax = x + 1;
                    while (ax < xn)
                    {
                        GeomPolyVal p2 = ps[(int)ax, y];
                        if (p2 == null || p2.GeomP != p.GeomP)
                        {
                            ax++;
                            continue;
                        }

                        p2.GeomP = u.GeomP;
                        ax++;
                    }

                    ax = x - 1;
                    while (ax >= 0)
                    {
                        GeomPolyVal p2 = ps[(int)ax, y];
                        if (p2 == null || p2.GeomP != p.GeomP)
                        {
                            ax--;
                            continue;
                        }

                        p2.GeomP = u.GeomP;
                        ax--;
                    }

                    ret.Remove(p.GeomP);
                    p.GeomP = u.GeomP;

                    x = (int)((bi.Next().Elem().X - domain.LowerBound.X) / cellWidth) + 1;

                    //x++; this was already commented out!
                }
            }

            polyList = ret.GetListOfElements();

            foreach (GeomPoly poly in polyList)
            {
                verticesList.Add(new Vertices(poly.Points.GetListOfElements()));
            }

            return(verticesList);
        }
示例#8
0
        /** Look-up table to relate polygon key with the vertices that should be used for
         *  the sub polygon in marching squares
         **/

        /** Perform a single celled marching square for for the given cell defined by (x0,y0) (x1,y1)
         *  using the function f for recursive interpolation, given the look-up table 'fs' of
         *  the values of 'f' at cell vertices with the result to be stored in 'poly' given the actual
         *  coordinates of 'ax' 'ay' in the marching squares mesh.
         **/

        private static int MarchSquare(sbyte[,] f, sbyte[,] fs, ref GeomPoly poly, int ax, int ay, GGame.Math.Fix64 x0, GGame.Math.Fix64 y0,
                                       GGame.Math.Fix64 x1, GGame.Math.Fix64 y1, int bin)
        {
            //key lookup
            int   key = 0;
            sbyte v0  = fs[ax, ay];

            if (v0 < 0)
            {
                key |= 8;
            }
            sbyte v1 = fs[ax + 1, ay];

            if (v1 < 0)
            {
                key |= 4;
            }
            sbyte v2 = fs[ax + 1, ay + 1];

            if (v2 < 0)
            {
                key |= 2;
            }
            sbyte v3 = fs[ax, ay + 1];

            if (v3 < 0)
            {
                key |= 1;
            }

            int val = _lookMarch[key];

            if (val != 0)
            {
                CxFastListNode <Vector2> pi = null;
                for (int i = 0; i < 8; i++)
                {
                    Vector2 p;
                    if ((val & (1 << i)) != 0)
                    {
                        if (i == 7 && (val & 1) == 0)
                        {
                            poly.Points.Add(p = new Vector2(x0, Ylerp(y0, y1, x0, v0, v3, f, bin)));
                        }
                        else
                        {
                            if (i == 0)
                            {
                                p = new Vector2(x0, y0);
                            }
                            else if (i == 2)
                            {
                                p = new Vector2(x1, y0);
                            }
                            else if (i == 4)
                            {
                                p = new Vector2(x1, y1);
                            }
                            else if (i == 6)
                            {
                                p = new Vector2(x0, y1);
                            }

                            else if (i == 1)
                            {
                                p = new Vector2(Xlerp(x0, x1, y0, v0, v1, f, bin), y0);
                            }
                            else if (i == 5)
                            {
                                p = new Vector2(Xlerp(x0, x1, y1, v3, v2, f, bin), y1);
                            }

                            else if (i == 3)
                            {
                                p = new Vector2(x1, Ylerp(y0, y1, x1, v1, v2, f, bin));
                            }
                            else
                            {
                                p = new Vector2(x0, Ylerp(y0, y1, x0, v0, v3, f, bin));
                            }

                            pi = poly.Points.Insert(pi, p);
                        }
                        poly.Length++;
                    }
                }

                //poly.simplify(GGame.Math.Fix64.Epsilon,GGame.Math.Fix64.Epsilon);
            }
            return(key);
        }
示例#9
0
 public GeomPolyVal(GeomPoly geomP, int K)
 {
     this.GeomP = geomP;
     this.Key   = K;
 }
示例#10
0
 public GeomPolyVal(GeomPoly P, int K)
 {
     p   = P;
     key = K;
 }
示例#11
0
        /// <summary>
        /// Marching squares over the given domain using the mesh defined via the dimensions
        ///    (wid,hei) to build a set of polygons such that f(x,y) < 0, using the given number
        ///    'bin' for recursive linear inteprolation along cell boundaries.
        ///
        ///    if 'comb' is true, then the polygons will also be composited into larger possible concave
        ///    polygons.
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="cell_width"></param>
        /// <param name="cell_height"></param>
        /// <param name="f"></param>
        /// <param name="lerp_count"></param>
        /// <param name="combine"></param>
        /// <returns></returns>
        public static List <Vertices> DetectSquares(AABB domain, float cell_width, float cell_height, sbyte[,] f, int lerp_count, bool combine)
        {
            var ret = new CxFastList <GeomPoly>();

            List <Vertices> verticesList = new List <Vertices>();

            List <GeomPoly> polyList = ret.GetListOfElements();

            GeomPoly gp = new GeomPoly();

            var xn = (int)(domain.Extents.X * 2 / cell_width); var xp = xn == (domain.Extents.X * 2 / cell_width);
            var yn = (int)(domain.Extents.Y * 2 / cell_height); var yp = yn == (domain.Extents.Y * 2 / cell_height);

            if (!xp)
            {
                xn++;
            }
            if (!yp)
            {
                yn++;
            }

            var fs = new sbyte[xn + 1, yn + 1];
            var ps = new GeomPolyVal[xn + 1, yn + 1];

            //populate shared function lookups.
            for (int x = 0; x < xn + 1; x++)
            {
                int x0;
                if (x == xn)
                {
                    x0 = (int)domain.UpperBound.X;
                }
                else
                {
                    x0 = (int)(x * cell_width + domain.LowerBound.X);
                }
                for (int y = 0; y < yn + 1; y++)
                {
                    int y0;
                    if (y == yn)
                    {
                        y0 = (int)domain.UpperBound.Y;
                    }
                    else
                    {
                        y0 = (int)(y * cell_height + domain.LowerBound.Y);
                    }
                    fs[x, y] = f[x0, y0];
                }
            }

            //generate sub-polys and combine to scan lines
            for (int y = 0; y < yn; y++)
            {
                var y0 = y * cell_height + domain.LowerBound.Y; float y1; if (y == yn - 1)
                {
                    y1 = domain.UpperBound.Y;
                }
                else
                {
                    y1 = y0 + cell_height;
                }
                GeomPoly pre = null;
                for (int x = 0; x < xn; x++)
                {
                    var x0 = x * cell_width + domain.LowerBound.X; float x1; if (x == xn - 1)
                    {
                        x1 = domain.UpperBound.X;
                    }
                    else
                    {
                        x1 = x0 + cell_width;
                    }

                    gp = new GeomPoly();

                    var key = marchSquare(f, fs, ref gp, x, y, x0, y0, x1, y1, lerp_count);
                    if (gp.length != 0)
                    {
                        if (combine && pre != null && (key & 9) != 0)
                        {
                            combLeft(ref pre, ref gp);
                            gp = pre;
                        }
                        else
                        {
                            ret.add(gp);
                        }
                        ps[x, y] = new GeomPolyVal(gp, key);
                    }
                    else
                    {
                        gp = null;
                    }
                    pre = gp;
                }
            }
            if (!combine)
            {
                polyList = ret.GetListOfElements();

                foreach (var poly in polyList)
                {
                    verticesList.Add(new Vertices(poly.points.GetListOfElements()));
                }

                return(verticesList);
            }

            //combine scan lines together
            for (int y = 1; y < yn; y++)
            {
                var x = 0;
                while (x < xn)
                {
                    var p = ps[x, y];

                    //skip along scan line if no polygon exists at this point
                    if (p == null)
                    {
                        x++; continue;
                    }

                    //skip along if current polygon cannot be combined above.
                    if ((p.key & 12) == 0)
                    {
                        x++; continue;
                    }

                    //skip along if no polygon exists above.
                    var u = ps[x, y - 1];
                    if (u == null)
                    {
                        x++; continue;
                    }

                    //skip along if polygon above cannot be combined with.
                    if ((u.key & 3) == 0)
                    {
                        x++; continue;
                    }

                    var ax = x * cell_width + domain.LowerBound.X;
                    var ay = y * cell_height + domain.LowerBound.Y;

                    var bp = p.p.points;
                    var ap = u.p.points;

                    //skip if it's already been combined with above polygon
                    if (u.p == p.p)
                    {
                        x++; continue;
                    }

                    //combine above (but disallow the hole thingies
                    var bi = bp.begin();
                    while (square(bi.elem().Y - ay) > float.Epsilon || bi.elem().X < ax)
                    {
                        bi = bi.next();
                    }

                    Vector2 b0 = bi.elem();
                    var     b1 = bi.next().elem();
                    if (square(b1.Y - ay) > float.Epsilon)
                    {
                        x++; continue;
                    }

                    var brk = true;
                    var ai  = ap.begin();
                    while (ai != ap.end())
                    {
                        if (vec_dsq(ai.elem(), b1) < float.Epsilon)
                        {
                            brk = false;
                            break;
                        }
                        ai = ai.next();
                    }
                    if (brk)
                    {
                        x++; continue;
                    }

                    var bj = bi.next().next(); if (bj == bp.end())
                    {
                        bj = bp.begin();
                    }
                    while (bj != bi)
                    {
                        ai = ap.insert(ai, bj.elem());  // .clone()
                        bj = bj.next(); if (bj == bp.end())
                        {
                            bj = bp.begin();
                        }
                        u.p.length++;
                    }
                    //u.p.simplify(float.Epsilon,float.Epsilon);
                    //
                    ax = x + 1;
                    while (ax < xn)
                    {
                        var p2 = ps[(int)ax, y];
                        if (p2 == null || p2.p != p.p)
                        {
                            ax++; continue;
                        }
                        p2.p = u.p;
                        ax++;
                    }
                    ax = x - 1;
                    while (ax >= 0)
                    {
                        var p2 = ps[(int)ax, y];
                        if (p2 == null || p2.p != p.p)
                        {
                            ax--; continue;
                        }
                        p2.p = u.p;
                        ax--;
                    }
                    ret.remove(p.p);
                    p.p = u.p;

                    x = (int)((bi.next().elem().X - domain.LowerBound.X) / cell_width) + 1;
                    //x++; this was already commented out!
                }
            }

            polyList = ret.GetListOfElements();

            foreach (var poly in polyList)
            {
                verticesList.Add(new Vertices(poly.points.GetListOfElements()));
            }

            return(verticesList);
        }
示例#12
0
        /** Used in polygon composition to composit polygons into scan lines
         *  Combining polya and polyb into one super-polygon stored in polya.
         **/
        private static void combLeft(ref GeomPoly polya, ref GeomPoly polyb)
        {
            var ap = polya.points;
            var bp = polyb.points;
            var ai = ap.begin();
            var bi = bp.begin();

            var b = bi.elem();
            CxFastListNode <Vector2> prea = null;

            while (ai != ap.end())
            {
                var a = ai.elem();
                if (vec_dsq(a, b) < float.Epsilon)
                {
                    //ignore shared vertex if parallel
                    if (prea != null)
                    {
                        var a0 = prea.elem();
                        b = bi.next().elem();

                        Vector2 u = a - a0;
                        //vec_new(u); vec_sub(a.p.p, a0.p.p, u);
                        Vector2 v = b - a;
                        //vec_new(v); vec_sub(b.p.p, a.p.p, v);
                        var dot = vec_cross(u, v);
                        if (dot * dot < float.Epsilon)
                        {
                            ap.erase(prea, ai);
                            polya.length--;
                            ai = prea;
                        }
                    }

                    //insert polyb into polya
                    var fst = true;
                    CxFastListNode <Vector2> preb = null;
                    while (!bp.empty())
                    {
                        var bb = bp.front();
                        bp.pop();
                        if (!fst && !bp.empty())
                        {
                            ai = ap.insert(ai, bb);
                            polya.length++;
                            preb = ai;
                        }
                        fst = false;
                    }

                    //ignore shared vertex if parallel
                    ai = ai.next();
                    var a1 = ai.elem();
                    ai = ai.next(); if (ai == ap.end())
                    {
                        ai = ap.begin();
                    }
                    var     a2  = ai.elem();
                    var     a00 = preb.elem();
                    Vector2 uu  = a1 - a00;
                    //vec_new(u); vec_sub(a1.p, a0.p, u);
                    Vector2 vv = a2 - a1;
                    //vec_new(v); vec_sub(a2.p, a1.p, v);
                    var dot1 = vec_cross(uu, vv);
                    if (dot1 * dot1 < float.Epsilon)
                    {
                        ap.erase(preb, preb.next());
                        polya.length--;
                    }

                    return;
                }
                prea = ai;
                ai   = ai.next();
            }
        }
示例#13
0
        /** Perform a single celled marching square for for the given cell defined by (x0,y0) (x1,y1)
         *  using the function f for recursive interpolation, given the look-up table 'fs' of
         *  the values of 'f' at cell vertices with the result to be stored in 'poly' given the actual
         *  coordinates of 'ax' 'ay' in the marching squares mesh.
         **/
        private static int marchSquare(sbyte[,] f, sbyte[,] fs, ref GeomPoly poly, int ax, int ay, float x0, float y0, float x1, float y1, int bin)
        {
            //key lookup
            var key = 0;
            var v0  = fs[ax, ay]; if (v0 < 0)
            {
                key |= 8;
            }
            var v1 = fs[ax + 1, ay]; if (v1 < 0)
            {
                key |= 4;
            }
            var v2 = fs[ax + 1, ay + 1]; if (v2 < 0)
            {
                key |= 2;
            }
            var v3 = fs[ax, ay + 1]; if (v3 < 0)
            {
                key |= 1;
            }

            var val = look_march[key];

            if (val != 0)
            {
                CxFastListNode <Vector2> pi = null;
                for (int i = 0; i < 8; i++)
                {
                    Vector2 p;
                    if ((val & (1 << i)) != 0)
                    {
                        if (i == 7 && (val & 1) == 0)
                        {
                            poly.points.add(p = new Vector2(x0, ylerp(y0, y1, x0, v0, v3, f, bin)));
                        }
                        else
                        {
                            if (i == 0)
                            {
                                p = new Vector2(x0, y0);
                            }
                            else if (i == 2)
                            {
                                p = new Vector2(x1, y0);
                            }
                            else if (i == 4)
                            {
                                p = new Vector2(x1, y1);
                            }
                            else if (i == 6)
                            {
                                p = new Vector2(x0, y1);
                            }

                            else if (i == 1)
                            {
                                p = new Vector2(xlerp(x0, x1, y0, v0, v1, f, bin), y0);
                            }
                            else if (i == 5)
                            {
                                p = new Vector2(xlerp(x0, x1, y1, v3, v2, f, bin), y1);
                            }

                            else if (i == 3)
                            {
                                p = new Vector2(x1, ylerp(y0, y1, x1, v1, v2, f, bin));
                            }
                            else
                            {
                                p = new Vector2(x0, ylerp(y0, y1, x0, v0, v3, f, bin));
                            }

                            pi = poly.points.insert(pi, p);
                        }
                        poly.length++;
                    }
                }
                //poly.simplify(float.Epsilon,float.Epsilon);
            }
            return(key);
        }
示例#14
0
 // 比较多边形外包面积大小
 static int CompArea(GeomPoly p1, GeomPoly p2) => Math.Sign(p1.OuterArea - p2.OuterArea);