예제 #1
0
        protected void compute_full(IEnumerable <int> Triangles, bool bIsFullMeshHint = false)
        {
            Graph = new DGraph3();
            if (WantGraphEdgeInfo)
            {
                GraphEdges = new DVector <GraphEdgeInfo>();
            }

            Vertices = new Dictionary <Vector3d, int>();


            // multithreaded precomputation of per-vertex values
            double[] vertex_values = null;
            if (PrecomputeVertexValues)
            {
                vertex_values = new double[Mesh.MaxVertexID];
                IEnumerable <int> verts = Mesh.VertexIndices();
                if (bIsFullMeshHint == false)
                {
                    MeshVertexSelection vertices = new MeshVertexSelection(Mesh);
                    vertices.SelectTriangleVertices(Triangles);
                    verts = vertices;
                }
                gParallel.ForEach(verts, (vid) => {
                    vertex_values[vid] = ValueF(Mesh.GetVertex(vid));
                });
                VertexValueF = (vid) => { return(vertex_values[vid]); };
            }


            foreach (int tid in Triangles)
            {
                Vector3dTuple3 tv = new Vector3dTuple3();
                Mesh.GetTriVertices(tid, ref tv.V0, ref tv.V1, ref tv.V2);
                Index3i triVerts = Mesh.GetTriangle(tid);

                Vector3d f = (VertexValueF != null) ?
                             new Vector3d(VertexValueF(triVerts.a), VertexValueF(triVerts.b), VertexValueF(triVerts.c))
                    : new Vector3d(ValueF(tv.V0), ValueF(tv.V1), ValueF(tv.V2));

                // round f to 0 within epsilon?

                if (f.x < 0 && f.y < 0 && f.z < 0)
                {
                    continue;
                }
                if (f.x > 0 && f.y > 0 && f.z > 0)
                {
                    continue;
                }

                Index3i triEdges = Mesh.GetTriEdges(tid);

                if (f.x * f.y * f.z == 0)
                {
                    int z0 = (f.x == 0) ? 0 : ((f.y == 0) ? 1 : 2);
                    int i1 = (z0 + 1) % 3, i2 = (z0 + 2) % 3;
                    if (f[i1] * f[i2] > 0)
                    {
                        continue;       // single-vertex-crossing case, skip here and let other edges catch it
                    }
                    if (f[i1] == 0 || f[i2] == 0)
                    {
                        // on-edge case
                        int z1 = f[i1] == 0 ? i1 : i2;
                        if ((z0 + 1) % 3 != z1)
                        {
                            int tmp = z0; z0 = z1; z1 = tmp;        // catch reverse-orientation cases
                        }
                        int e0        = add_or_append_vertex(Mesh.GetVertex(triVerts[z0]));
                        int e1        = add_or_append_vertex(Mesh.GetVertex(triVerts[z1]));
                        int graph_eid = Graph.AppendEdge(e0, e1, (int)TriangleCase.OnEdge);
                        if (graph_eid >= 0 && WantGraphEdgeInfo)
                        {
                            add_on_edge(graph_eid, tid, triEdges[z0], new Index2i(e0, e1));
                        }
                    }
                    else
                    {
                        // edge/vertex case
                        Util.gDevAssert(f[i1] * f[i2] < 0);

                        int vert_vid = add_or_append_vertex(Mesh.GetVertex(triVerts[z0]));

                        int i = i1, j = i2;
                        if (triVerts[j] < triVerts[i])
                        {
                            int tmp = i; i = j; j = tmp;
                        }
                        Vector3d cross     = find_crossing(tv[i], tv[j], f[i], f[j]);
                        int      cross_vid = add_or_append_vertex(cross);
                        add_edge_pos(triVerts[i], triVerts[j], cross);

                        int graph_eid = Graph.AppendEdge(vert_vid, cross_vid, (int)TriangleCase.EdgeVertex);
                        if (graph_eid >= 0 && WantGraphEdgeInfo)
                        {
                            add_edge_vert(graph_eid, tid, triEdges[(z0 + 1) % 3], triVerts[z0], new Index2i(vert_vid, cross_vid));
                        }
                    }
                }
                else
                {
                    Index3i cross_verts = Index3i.Min;
                    int     less_than   = 0;
                    for (int tei = 0; tei < 3; ++tei)
                    {
                        int i = tei, j = (tei + 1) % 3;
                        if (f[i] < 0)
                        {
                            less_than++;
                        }
                        if (f[i] * f[j] > 0)
                        {
                            continue;
                        }
                        if (triVerts[j] < triVerts[i])
                        {
                            int tmp = i; i = j; j = tmp;
                        }
                        Vector3d cross = find_crossing(tv[i], tv[j], f[i], f[j]);
                        cross_verts[tei] = add_or_append_vertex(cross);
                        add_edge_pos(triVerts[i], triVerts[j], cross);
                    }
                    int e0 = (cross_verts.a == int.MinValue) ? 1 : 0;
                    int e1 = (cross_verts.c == int.MinValue) ? 1 : 2;
                    if (e0 == 0 && e1 == 2)         // preserve orientation order
                    {
                        e0 = 2; e1 = 0;
                    }

                    // preserving orientation does not mean we get a *consistent* orientation across faces.
                    // To do that, we need to assign "sides". Either we have 1 less-than-0 or 1 greater-than-0 vtx.
                    // Arbitrary decide that we want loops oriented like bdry loops would be if we discarded less-than side.
                    // In that case, when we are "cutting off" one vertex, orientation would end up flipped
                    if (less_than == 1)
                    {
                        int tmp = e0; e0 = e1; e1 = tmp;
                    }

                    int ev0 = cross_verts[e0];
                    int ev1 = cross_verts[e1];
                    // [RMS] if function is garbage, we can end up w/ case where both crossings
                    //   happen at same vertex, even though values are not the same (eg if
                    //   some values are double.MaxValue). We will just fail in these cases.
                    if (ev0 != ev1)
                    {
                        Util.gDevAssert(ev0 != int.MinValue && ev1 != int.MinValue);
                        int graph_eid = Graph.AppendEdge(ev0, ev1, (int)TriangleCase.EdgeEdge);
                        if (graph_eid >= 0 && WantGraphEdgeInfo)
                        {
                            add_edge_edge(graph_eid, tid, new Index2i(triEdges[e0], triEdges[e1]), new Index2i(ev0, ev1));
                        }
                    }
                }
            }


            Vertices = null;
        }
예제 #2
0
        protected void compute_full(IEnumerable <int> Triangles)
        {
            Graph = new DGraph3();
            if (WantGraphEdgeInfo)
            {
                GraphEdges = new DVector <GraphEdgeInfo>();
            }

            Vertices = new Dictionary <Vector3d, int>();

            foreach (int tid in Triangles)
            {
                Vector3dTuple3 tv = new Vector3dTuple3();
                Mesh.GetTriVertices(tid, ref tv.V0, ref tv.V1, ref tv.V2);
                Vector3d f = new Vector3d(ValueF(tv.V0), ValueF(tv.V1), ValueF(tv.V2));

                // round f to 0 within epsilon?

                if (f.x < 0 && f.y < 0 && f.z < 0)
                {
                    continue;
                }
                if (f.x > 0 && f.y > 0 && f.z > 0)
                {
                    continue;
                }

                Index3i triVerts = Mesh.GetTriangle(tid);
                Index3i triEdges = Mesh.GetTriEdges(tid);

                if (f.x * f.y * f.z == 0)
                {
                    int z0 = (f.x == 0) ? 0 : ((f.y == 0) ? 1 : 2);
                    int i1 = (z0 + 1) % 3, i2 = (z0 + 2) % 3;
                    if (f[i1] * f[i2] > 0)
                    {
                        continue;       // single-vertex-crossing case, skip here and let other edges catch it
                    }
                    if (f[i1] == 0 || f[i2] == 0)
                    {
                        // on-edge case
                        int z1        = f[i1] == 0 ? i1 : i2;
                        int e0        = add_or_append_vertex(Mesh.GetVertex(triVerts[z0]));
                        int e1        = add_or_append_vertex(Mesh.GetVertex(triVerts[z1]));
                        int graph_eid = Graph.AppendEdge(e0, e1, (int)TriangleCase.OnEdge);
                        if (WantGraphEdgeInfo)
                        {
                            add_on_edge(graph_eid, tid, triEdges[z0]);
                        }
                    }
                    else
                    {
                        // edge/vertex case
                        Util.gDevAssert(f[i1] * f[i2] < 0);

                        int vert_vid = add_or_append_vertex(Mesh.GetVertex(triVerts[z0]));

                        int i = i1, j = i2;
                        if (triVerts[j] < triVerts[i])
                        {
                            int tmp = i; i = j; j = tmp;
                        }
                        Vector3d cross     = find_crossing(tv[i], tv[j], f[i], f[j]);
                        int      cross_vid = add_or_append_vertex(cross);

                        int graph_eid = Graph.AppendEdge(vert_vid, cross_vid, (int)TriangleCase.EdgeVertex);
                        if (WantGraphEdgeInfo)
                        {
                            add_edge_edge(graph_eid, tid, new Index2i(triEdges[(z0 + 1) % 3], triVerts[z0]));
                        }
                    }
                }
                else
                {
                    Index3i cross_verts = Index3i.Min;
                    for (int ti = 0; ti < 3; ++ti)
                    {
                        int i = ti, j = (ti + 1) % 3;
                        if (f[i] * f[j] > 0)
                        {
                            continue;
                        }
                        if (triVerts[j] < triVerts[i])
                        {
                            int tmp = i; i = j; j = tmp;
                        }
                        Vector3d cross = find_crossing(tv[i], tv[j], f[i], f[j]);
                        cross_verts[ti] = add_or_append_vertex(cross);
                    }
                    int e0  = (cross_verts.a == int.MinValue) ? 1 : 0;
                    int e1  = (cross_verts.c == int.MinValue) ? 1 : 2;
                    int ev0 = cross_verts[e0];
                    int ev1 = cross_verts[e1];
                    Util.gDevAssert(ev0 != int.MinValue && ev1 != int.MinValue);
                    int graph_eid = Graph.AppendEdge(ev0, ev1, (int)TriangleCase.EdgeEdge);
                    if (WantGraphEdgeInfo)
                    {
                        add_edge_edge(graph_eid, tid, new Index2i(triEdges[e0], triEdges[e1]));
                    }
                }
            }


            Vertices = null;
        }