Beispiel #1
0
        /// <summary>
        /// A splitter can split a vertex-indexed face set, based on the
        /// supplied array of vertexHeights, which indicate for each vertex
        /// vi if it belongs to the negative split side (vertexHeights[vi]
        /// &lt; 0.0) or positive split side (vertexHeights[vi] &gt;= 0.0).
        /// </summary>
        public PolygonSplitter(
            int[] fia, int faceCount,
            int[] via, int maxFaceVertexCount,
            double[] vertexHeights, double eps,
            SplitterOptions options)
        {
            int vc = vertexHeights.Length;
            int vertexIndexCount = fia[faceCount];

            bool doNeg = (options & SplitterOptions.Negative) != 0;
            bool doPos = (options & SplitterOptions.Positive) != 0;

            if (doPos && vertexHeights.All(h => h >= -eps))
            {
                m_pfia = fia; m_pvia = via; m_ofia = null; return;
            }

            if (doNeg && vertexHeights.All(h => h <= eps))
            {
                m_nfia = fia; m_nvia = via; m_ofia = null; return;
            }

            m_ofia = fia;

            var lineMap = new Dict <Line1i, (int, int, int)>();

            m_spl = doNeg ? new List <SplitPoint>() : null;
            m_nvl = doPos ? new List <Vertex>() : null;
            m_pvl = doPos ? new List <Vertex>() : null;
            m_nfl = doNeg ? new List <Face>() : null;
            m_pfl = doPos ? new List <Face>() : null;

            int[] nffm = doNeg ? new int[faceCount].Set(-1) : null;
            int[] pffm = doPos ? new int[faceCount].Set(-1) : null;

            int[] nvfm = doNeg ? new int[vc].Set(-1) : null;
            int[] pvfm = doPos ? new int[vc].Set(-1) : null;

            var ha = new double[maxFaceVertexCount];
            int nfc = 0, pfc = 0, nvic = 0, pvic = 0, nvc = 0, pvc = 0;

            for (int fvi = fia[0], fi = 0; fi < faceCount; fi++)
            {
                int nc = 0, pc = 0, zc = 0, fve = fia[fi + 1], fvc = fve - fvi;
                for (int fs = 0; fs < fvc; fs++)
                {
                    double height = ha[fs] = vertexHeights[via[fvi + fs]];
                    if (height < -eps)
                    {
                        ++nc; continue;
                    }
                    if (height > +eps)
                    {
                        ++pc; continue;
                    }
                    ++zc;
                }
                if (nc == 0)
                {
                    if (doPos)
                    {
                        pffm[fi] = pfc++; pvic += fvc;
                        for (int fs = 0; fs < fvc; fs++)
                        {
                            pvfm.ForwardMapAdd(via[fvi + fs], ref pvc);
                        }
                    }
                }
                else if (pc == 0)
                {
                    if (doNeg)
                    {
                        nffm[fi] = nfc++; nvic += fvc;
                        for (int fs = 0; fs < fvc; fs++)
                        {
                            nvfm.ForwardMapAdd(via[fvi + fs], ref nvc);
                        }
                    }
                }
                else
                {
                    if (zc > 2)
                    {
                        Report.Warn("non-convex polygon encountered");
                    }
                    var nfvl = new List <FaceVertex>(nc + 2);
                    var pfvl = new List <FaceVertex>(pc + 2);

                    int sb = ha[0] > eps ? 1 : (ha[0] < -eps ? -1 : 0), vib = via[fvi];
                    int i0 = 0, s0 = sb, vi0 = vib;
                    if (doNeg && sb <= 0)
                    {
                        nfvl.Add(new FaceVertex(nvfm.ForwardMapAdd(vib, ref nvc), 0));
                    }
                    if (doPos && sb >= 0)
                    {
                        pfvl.Add(new FaceVertex(pvfm.ForwardMapAdd(vib, ref pvc), 0));
                    }
                    for (int i1 = 1; i1 < fvc; i0 = i1++)
                    {
                        int s1 = ha[i1] > eps ? 1 : (ha[i1] < -eps ? -1 : 0), vi1 = via[fvi + i1];
                        if (s0 != 0 && s1 != 0 && s0 != s1)
                        {
                            double t   = ha[i0] / (ha[i0] - ha[i1]);
                            var    key = Line1i.CreateSorted(vi0, vi1);
                            (int, int, int)v;
                            if (!lineMap.TryGetValue(key, out v))
                            {
                                v = lineMap[key] = (nvc++, pvc++, m_spl.Count);
                                m_spl.Add(new SplitPoint(t, vi0, vi1));
                            }
                            if (doNeg)
                            {
                                m_nvl.Add(new Vertex(v.Item1, v.Item3, t, i0));
                                nfvl.Add(new FaceVertex(v.Item1, -m_nvl.Count));
                            }
                            if (doPos)
                            {
                                m_pvl.Add(new Vertex(v.Item2, v.Item3, t, i0));
                                pfvl.Add(new FaceVertex(v.Item2, -m_pvl.Count));
                            }
                        }
                        if (doNeg && s1 <= 0)
                        {
                            nfvl.Add(new FaceVertex(nvfm.ForwardMapAdd(vi1, ref nvc), i1));
                        }
                        if (doPos && s1 >= 0)
                        {
                            pfvl.Add(new FaceVertex(pvfm.ForwardMapAdd(vi1, ref pvc), i1));
                        }
                        vi0 = vi1; s0 = s1;
                    }
                    if (s0 != 0 && sb != 0 && s0 != sb)
                    {
                        double t   = ha[i0] / (ha[i0] - ha[0]);
                        var    key = Line1i.CreateSorted(vi0, vib);
                        (int, int, int)v;
                        if (!lineMap.TryGetValue(key, out v))
                        {
                            v = lineMap[key] = (nvc++, pvc++, m_spl.Count);
                            m_spl.Add(new SplitPoint(t, vi0, vib));
                        }
                        if (doNeg)
                        {
                            m_nvl.Add(new Vertex(v.Item1, v.Item3, t, i0));
                            nfvl.Add(new FaceVertex(v.Item1, -m_nvl.Count));
                        }
                        if (doPos)
                        {
                            m_pvl.Add(new Vertex(v.Item2, v.Item3, t, i0));
                            pfvl.Add(new FaceVertex(v.Item2, -m_pvl.Count));
                        }
                    }
                    if (doNeg && nfvl.Count > 2)
                    {
                        m_nfl.Add(new Face(fi, nfvl)); nvic += nfvl.Count;
                    }
                    if (doPos && pfvl.Count > 2)
                    {
                        m_pfl.Add(new Face(fi, pfvl)); pvic += pfvl.Count;
                    }
                }
                fvi = fve;
            }

            if (doNeg && (nfc > 0 || m_nfl.Count > 0))
            {
                CalculateIndices(fia, faceCount, via, nfc, nvic, nvc, nffm, m_nfl, nvfm,
                                 out m_nfia, out m_nvia, out m_nfbm, out m_nvbm);
            }
            if (doPos && (pfc > 0 || m_pfl.Count > 0))
            {
                CalculateIndices(fia, faceCount, via, pfc, pvic, pvc, pffm, m_pfl, pvfm,
                                 out m_pfia, out m_pvia, out m_pfbm, out m_pvbm);
            }
        }
Beispiel #2
0
        /// <summary>
        /// A splitter can split a vertex-indexed triangle set, based on the
        /// supplied array of vertexHeights, which indicate for each vertex
        /// vi if it belongs to the negative split side (vertexHeights[vi]
        /// &lt; 0.0) or positive split side (vertexHeights[vi] &gt;= 0.0).
        /// </summary>
        public TriangleSplitter(int[] indices, double[] vertexHeights, double eps,
                                SplitterOptions options)
        {
            m_negativeIndices = null;
            m_positiveIndices = null;

            bool doNeg = (options & SplitterOptions.Negative) != 0;
            bool doPos = (options & SplitterOptions.Positive) != 0;

            if (doPos && vertexHeights.All(h => h >= -eps))
            {
                m_positiveIndices           = indices;
                m_positiveVertexBackwardMap = null; // flag: move input to positive
                return;
            }
            if (doNeg && vertexHeights.All(h => h <= eps))
            {
                m_negativeIndices           = indices;
                m_negativeVertexBackwardMap = null; // flag: move input to negative
                return;
            }

            var lineMap         = new Dictionary <Line1i, Line1i>();
            var negTriangleList = doNeg ? new List <(int, Triangle1i)>() : null;
            var posTriangleList = doPos ? new List <(int, Triangle1i)>() : null;

            m_negVertexMap = doNeg ? new Dictionary <int, Line1iPoint>() : null;
            m_posVertexMap = doPos ? new Dictionary <int, Line1iPoint>() : null;

            int tc = indices.Length / 3;

            int ntc = 0;
            int ptc = 0;

            int nvc = 0;
            int pvc = 0;

            int[] negTriangleForwardMap = doNeg ? new int[tc].Set(-1) : null;
            int[] posTriangleForwardMap = doPos ? new int[tc].Set(-1) : null;

            int[] negVertexForwardMap = doNeg ? new int[vertexHeights.Length].Set(-1) : null;
            int[] posVertexForwardMap = doPos ? new int[vertexHeights.Length].Set(-1) : null;

            var ia         = new int[3];
            var ha         = new double[3];
            var negIndices = new List <int>(4);
            var posIndices = new List <int>(4);

            for (int ti = 0; ti < tc; ti++)
            {
                int nc = 0, pc = 0;
                int tvi = 3 * ti;

                for (int ts = 0; ts < 3; ts++)
                {
                    int vi = indices[tvi + ts];
                    ia[ts] = vi;
                    double height = ha[ts] = vertexHeights[vi];
                    if (height < -eps)
                    {
                        ++nc; continue;
                    }
                    if (height > +eps)
                    {
                        ++pc; continue;
                    }
                }

                if (nc == 0)
                {
                    if (doPos)
                    {
                        posTriangleForwardMap[ti] = ptc++;
                        foreach (var vi in ia)
                        {
                            posVertexForwardMap.ForwardMapAdd(vi, ref pvc);
                        }
                    }
                }
                else if (pc == 0)
                {
                    if (doNeg)
                    {
                        negTriangleForwardMap[ti] = ntc++;
                        foreach (var vi in ia)
                        {
                            negVertexForwardMap.ForwardMapAdd(vi, ref nvc);
                        }
                    }
                }
                else
                {
                    int sb = ha[0] > eps ? 1 : (ha[0] < -eps ? -1 : 0);

                    int vi = ia[0];
                    if (doNeg && sb <= 0)
                    {
                        negIndices.Add(negVertexForwardMap.ForwardMapAdd(vi, ref nvc));
                    }
                    if (doPos && sb >= 0)
                    {
                        posIndices.Add(posVertexForwardMap.ForwardMapAdd(vi, ref pvc));
                    }

                    int i0 = 0, i1 = 1;
                    int s0 = sb;

                    while (i1 < 3)
                    {
                        int s1 = ha[i1] > eps ? 1 : (ha[i1] < -eps ? -1 : 0);

                        if (s0 != 0 && s1 != 0 && s0 != s1)
                        {
                            double t = ha[i0] / (ha[i0] - ha[i1]);
                            int    vi0 = ia[i0], vi1 = ia[i1];
                            var    key = Line1i.CreateSorted(vi0, vi1);
                            if (!lineMap.TryGetValue(key, out Line1i line))
                            {
                                var sp = new Line1iPoint(vi0, vi1, t);
                                if (doNeg)
                                {
                                    m_negVertexMap[line.I0 = nvc++] = sp;
                                }
                                if (doPos)
                                {
                                    m_posVertexMap[line.I1 = pvc++] = sp;
                                }
                                lineMap[key] = line;
                            }
                            if (doNeg)
                            {
                                negIndices.Add(line.I0);
                            }
                            if (doPos)
                            {
                                posIndices.Add(line.I1);
                            }
                        }

                        vi = ia[i1];
                        if (doNeg && s1 <= 0)
                        {
                            negIndices.Add(negVertexForwardMap.ForwardMapAdd(vi, ref nvc));
                        }
                        if (doPos && s1 >= 0)
                        {
                            posIndices.Add(posVertexForwardMap.ForwardMapAdd(vi, ref pvc));
                        }

                        i0 = i1++;  s0 = s1;
                    }
                    if (s0 != 0 && sb != 0 && s0 != sb)
                    {
                        double t = ha[i0] / (ha[i0] - ha[0]);
                        int    vi0 = ia[i0], vi1 = ia[0];
                        var    key = Line1i.CreateSorted(vi0, vi1);
                        if (!lineMap.TryGetValue(key, out Line1i line))
                        {
                            var sp = new Line1iPoint(vi0, vi1, t);
                            if (doNeg)
                            {
                                m_negVertexMap[line.I0 = nvc++] = sp;
                            }
                            if (doPos)
                            {
                                m_posVertexMap[line.I1 = pvc++] = sp;
                            }
                            lineMap[key] = line;
                        }
                        if (doNeg)
                        {
                            negIndices.Add(line.I0);
                        }
                        if (doPos)
                        {
                            posIndices.Add(line.I1);
                        }
                    }

                    // at this point we have lists of indices for the positive and
                    // negative triangles
                    if (doNeg && negIndices.Count > 2)
                    {
                        for (int i = 1; i < negIndices.Count - 1; i++)
                        {
                            negTriangleList.Add(
                                (ntc++, new Triangle1i(negIndices[0],
                                                       negIndices[i], negIndices[i + 1])));
                        }
                    }
                    if (doPos && posIndices.Count > 2)
                    {
                        for (int i = 1; i < posIndices.Count - 1; i++)
                        {
                            posTriangleList.Add(
                                (ptc++, new Triangle1i(posIndices[0],
                                                       posIndices[i], posIndices[i + 1])));
                        }
                    }
                    negIndices.Clear(); posIndices.Clear();
                }
            }

            if (doNeg && ntc > 0)
            {
                m_negativeIndices = CalculateIndices(indices, ntc, negTriangleForwardMap,
                                                     negTriangleList, negVertexForwardMap);
                m_negativeVertexBackwardMap = negVertexForwardMap.CreateBackMap(nvc);
            }
            if (doPos && ptc > 0)
            {
                m_positiveIndices = CalculateIndices(indices, ptc, posTriangleForwardMap,
                                                     posTriangleList, posVertexForwardMap);
                m_positiveVertexBackwardMap = posVertexForwardMap.CreateBackMap(pvc);
            }
        }