Revision: 73843
          http://sourceforge.net/p/brlcad/code/73843
Author:   starseeker
Date:     2019-09-06 13:12:00 +0000 (Fri, 06 Sep 2019)
Log Message:
-----------
Do a test on the post initialization polygons to see if we can get a valid face 
from the sparse inputs.  If not, split the longer edges until we can.  In a 
sense, this is similar to the inital breakdown of closed loops and always 
splitting curved edges at least once (probably should be at least twice, really 
- squares in place of circles is a jarring visual) in that we need to do this 
refinement regardless of how liberal the tolerance settings are in order to be 
able to return something valid.  Have the rest of the processing turned off for 
now - need to hammer out each stage and build on it.  The repair logic can mask 
problems earlier in the chain, which we don't want - repair is a last resort 
after everything else has been done right.

Modified Paths:
--------------
    brlcad/trunk/src/libbrep/cdt.cpp
    brlcad/trunk/src/libbrep/cdt_mesh.cpp
    brlcad/trunk/src/libbrep/cdt_mesh.h

Modified: brlcad/trunk/src/libbrep/cdt.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt.cpp    2019-09-06 02:04:37 UTC (rev 73842)
+++ brlcad/trunk/src/libbrep/cdt.cpp    2019-09-06 13:12:00 UTC (rev 73843)
@@ -27,6 +27,7 @@
 
 #include "common.h"
 #include <queue>
+#include <numeric>
 #include "bg/chull.h"
 #include "./cdt.h"
 
@@ -174,6 +175,7 @@
     s_cdt->edge_segs_3d[trim.Face()->m_face_index].Insert(p1, p2, (void *)pe);
 }
 
+#if 0
 struct rtree_loop_leaf {
     struct ON_Brep_CDT_State *s_cdt;
     int loop_index;
@@ -228,6 +230,7 @@
     // Keep checking for other loops - we want the smallest target length
     return true;
 }
+#endif
 
 double
 median_seg_len(std::vector<double> &lsegs)
@@ -713,6 +716,88 @@
     return nedges;
 }
 
+// Calculate loop avg segment length
+static double
+loop_avg_seg_len(struct ON_Brep_CDT_State *s_cdt, int loop_index)
+{
+    const ON_BrepLoop &loop = s_cdt->brep->m_L[loop_index];
+    std::vector<double> lsegs;
+    for (int lti = 0; lti < loop.TrimCount(); lti++) {
+       ON_BrepTrim *trim = loop.Trim(lti);
+       ON_BrepEdge *edge = trim->Edge();
+       if (!edge) continue;
+       const ON_Curve* crv = edge->EdgeCurveOf();
+       if (!crv) continue;
+       std::set<cdt_mesh::bedge_seg_t *> &epsegs = 
s_cdt->e2polysegs[edge->m_edge_index];
+       if (!epsegs.size()) continue;
+       std::set<cdt_mesh::bedge_seg_t *>::iterator e_it;
+       for (e_it = epsegs.begin(); e_it != epsegs.end(); e_it++) {
+           cdt_mesh::bedge_seg_t *b = *e_it;
+           double seg_dist = b->e_start->DistanceTo(*b->e_end);
+           lsegs.push_back(seg_dist);
+       }
+    }
+    return (std::accumulate(lsegs.begin(), lsegs.end(), 0.0)/lsegs.size());
+}
+
+static void
+split_long_edges(struct ON_Brep_CDT_State *s_cdt, int face_index)
+{
+    ON_BrepFace &face = s_cdt->brep->m_F[face_index];
+    int loop_cnt = face.LoopCount();
+    
+    for (int li = 0; li < loop_cnt; li++) {
+       const ON_BrepLoop *loop = face.Loop(li);
+       double avg_seg_len = loop_avg_seg_len(s_cdt, loop->m_loop_index);
+       int trim_count = loop->TrimCount();
+       for (int lti = 0; lti < trim_count; lti++) {
+           ON_BrepTrim *trim = loop->Trim(lti);
+           ON_BrepEdge *edge = trim->Edge();
+           if (!edge) continue;
+           const ON_Curve* crv = edge->EdgeCurveOf();
+           if (!crv || crv->IsLinear(BN_TOL_DIST)) {
+               continue;
+           }
+           std::set<cdt_mesh::bedge_seg_t *> &epsegs = 
s_cdt->e2polysegs[edge->m_edge_index];
+           if (!epsegs.size()) continue;
+           std::set<cdt_mesh::bedge_seg_t *>::iterator e_it;
+           std::set<cdt_mesh::bedge_seg_t *> new_segs;
+           std::set<cdt_mesh::bedge_seg_t *> ws1, ws2;
+           std::set<cdt_mesh::bedge_seg_t *> *ws = &ws1;
+           std::set<cdt_mesh::bedge_seg_t *> *ns = &ws2;
+           for (e_it = epsegs.begin(); e_it != epsegs.end(); e_it++) {
+               cdt_mesh::bedge_seg_t *b = *e_it;
+               ws->insert(b);
+           }
+           while (ws->size()) {
+               cdt_mesh::bedge_seg_t *b = *ws->begin();
+               ws->erase(ws->begin());
+               double seg_dist = b->e_start->DistanceTo(*b->e_end);
+               if (seg_dist > 0.5*avg_seg_len) {
+                   std::set<cdt_mesh::bedge_seg_t *> esegs_split = 
split_edge_seg(s_cdt, b, 1);
+                   if (esegs_split.size()) {
+                       ns->insert(esegs_split.begin(), esegs_split.end());
+                   } else {
+                       new_segs.insert(b);
+                   }
+               } else {
+                   new_segs.insert(b);
+               }
+               if (!ws->size() && ns->size()) {
+                   std::set<cdt_mesh::bedge_seg_t *> *tmp = ws;
+                   ws = ns;
+                   ns = tmp;
+               }
+           }
+           s_cdt->e2polysegs[edge->m_edge_index].clear();
+           s_cdt->e2polysegs[edge->m_edge_index].insert(new_segs.begin(), 
new_segs.end());
+       }
+    }
+}
+
+
+
+
 std::set<cdt_mesh::cpolyedge_t *>
 split_singular_seg(struct ON_Brep_CDT_State *s_cdt, cdt_mesh::cpolyedge_t *ce)
 {
@@ -843,12 +928,14 @@
 
     // Now, the hard part - create local subsets, remesh them, and replace the 
original
     // triangles with the new ones.
+#if 0 
     if (!fmesh->repair()) {
        bu_log("Face %d: repair FAILED!\n", fmesh->f_id);
        return false;
     }
+#endif
 
-    if (fmesh->valid()) {
+    if (fmesh->valid(1)) {
        bu_log("Face %d: successful triangulation after %d passes\n", 
fmesh->f_id, cnt);
     } else {
        bu_log("Face %d: triangulation produced invalid mesh!\n", fmesh->f_id);
@@ -918,7 +1005,7 @@
 
     // Sample the surface, independent of the trimming curves, to get points 
that
     // will tie the mesh to the interior surface.
-    GetInteriorPoints(s_cdt, face.m_face_index);
+    //GetInteriorPoints(s_cdt, face.m_face_index);
 
     cdt_mesh::cdt_mesh_t *fmesh = &s_cdt->fmeshes[face.m_face_index];
     fmesh->f_id = face.m_face_index;
@@ -1451,45 +1538,73 @@
            }
        }
 
-       // Check the CDT meshing - at this point, we should be able to produce 
a valid
-       // triangulation for all faces.  If not, refine the larger curved edges 
until we can.
+       // Check the CDT meshing - at this point, we should be able to produce
+       // a valid triangulation for all faces.  If not, refine the larger
+       // curved edges until we can.
+       //
+       // In theory this is an expensive test, but as we are at the very
+       // beginning of the process triangle counts should be relatively low
+       // and all of these operations should be very fast.  More critically,
+       // in combination with the above this should give us the sparsest valid
+       // triangulation we can return and provide a solid basis on which to
+       // build.
        for (int index = 0; index < brep->m_F.Count(); index++) {
            ON_BrepFace &face = s_cdt->brep->m_F[index];
            cdt_mesh::cdt_mesh_t *fmesh = &s_cdt->fmeshes[face.m_face_index];
            fmesh->f_id = face.m_face_index;
            fmesh->m_bRev = face.m_bRev;
+           // List singularities
+           for (size_t i = 0; i < fmesh->pnts.size(); i++) {
+               ON_3dPoint *p3d = fmesh->pnts[i];
+               if (s_cdt->singular_vert_to_norms->find(p3d) != 
s_cdt->singular_vert_to_norms->end()) {
+                   fmesh->sv.insert(fmesh->p2ind[p3d]);
+               }
+           }
 
-           if (!fmesh->outer_loop.closed()) {
-               std::cout << "Warning - loop not closed\n";
+           // List edges
+           fmesh->brep_edges.clear();
+           loop_edges(fmesh, &fmesh->outer_loop);
+           std::map<int, cdt_mesh::cpolygon_t*>::iterator i_it;
+           for (i_it = fmesh->inner_loops.begin(); i_it != 
fmesh->inner_loops.end(); i_it++) {
+               loop_edges(fmesh, i_it->second);
            }
-           if (fmesh->cdt()) {
 
-               // List singularities
-               for (size_t i = 0; i < fmesh->pnts.size(); i++) {
-                   ON_3dPoint *p3d = fmesh->pnts[i];
-                   if (s_cdt->singular_vert_to_norms->find(p3d) != 
s_cdt->singular_vert_to_norms->end()) {
-                       fmesh->sv.insert(fmesh->p2ind[p3d]);
+           bool success = (fmesh->cdt() && fmesh->valid(0));
+
+           if (!success) {
+       
+               // Start iterating
+               int cnt = 0;
+               while (!fmesh->valid(0)) {
+                   //std::cout << "Face " << face.m_face_index << " , 
iteration " << cnt << ": base mesh CDT invalid\n";
+                   fmesh->reset();
+                   split_long_edges(s_cdt, index);
+
+                   // Replace old edge list with new edges
+                   fmesh->brep_edges.clear();
+                   loop_edges(fmesh, &fmesh->outer_loop);
+                   for (i_it = fmesh->inner_loops.begin(); i_it != 
fmesh->inner_loops.end(); i_it++) {
+                       loop_edges(fmesh, i_it->second);
                    }
-               }
+                   fmesh->boundary_edges_update();
 
-               // List edges
-               fmesh->brep_edges.clear();
-               loop_edges(fmesh, &fmesh->outer_loop);
-               std::map<int, cdt_mesh::cpolygon_t*>::iterator i_it;
-               for (i_it = fmesh->inner_loops.begin(); i_it != 
fmesh->inner_loops.end(); i_it++) {
-                   loop_edges(fmesh, i_it->second);
+                   fmesh->cdt();
+
+                   cnt++;
+#if 0
+                   struct bu_vls fname = BU_VLS_INIT_ZERO;
+                   bu_vls_sprintf(&fname, "iteration-%d-tris.p3", cnt);
+                   fmesh->tris_plot(bu_vls_cstr(&fname));
+                   bu_vls_free(&fname);
+#endif
                }
-               fmesh->boundary_edges_update();
-               if (!fmesh->valid()) {
-                   std::cout << "Face " << face.m_face_index << " base mesh 
CDT invalid\n";
-               }
-           } else {
-               std::cout << "Face " << face.m_face_index << " base mesh CDT 
failed\n";
            }
+
+           // Unless we're doing NO additional refinement, this is not our 
final mesh
            fmesh->reset();
 
        }
-
+#if 0
        // On to tolerance based splitting.  Process the non-linear edges first 
-
        // we will need information from them to handle the linear edges
        //
@@ -1823,8 +1938,8 @@
            s_cdt->e2polysegs[edge.m_edge_index].clear();
            s_cdt->e2polysegs[edge.m_edge_index].insert(new_segs.begin(), 
new_segs.end());
        }
+#endif
 
-
        // Split singularity trims in 2D to provide an easier input to the 2D 
CDT logic.  NOTE: these
        // splits will produce degenerate (zero area, two identical vertex) 
triangles in 3D that have
        // to be cleaned up.

Modified: brlcad/trunk/src/libbrep/cdt_mesh.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_mesh.cpp       2019-09-06 02:04:37 UTC (rev 
73842)
+++ brlcad/trunk/src/libbrep/cdt_mesh.cpp       2019-09-06 13:12:00 UTC (rev 
73843)
@@ -2542,7 +2542,7 @@
 }
 
 bool
-cdt_mesh_t::valid()
+cdt_mesh_t::valid(int verbose)
 {
     struct bu_vls fname = BU_VLS_INIT_ZERO;
     bool nret = true;
@@ -2552,14 +2552,18 @@
        ON_3dVector tdir = tnorm(*tr_it);
        ON_3dVector bdir = bnorm(*tr_it);
        if (tdir.Length() > 0 && bdir.Length() > 0 && ON_DotProduct(tdir, bdir) 
< 0.1) {
-           std::cout << "Still have invalid normals in mesh, triangle (" << 
(*tr_it).v[0] << "," << (*tr_it).v[1] << "," << (*tr_it).v[2] << ")\n";
-           bu_vls_sprintf(&fname, "%d-invalid_normal_tri_%ld_%ld_%ld.plot3", 
f_id, (*tr_it).v[0], (*tr_it).v[1], (*tr_it).v[2]);
-           tri_plot(*tr_it, bu_vls_cstr(&fname));
+           if (verbose > 0) {
+               std::cout << "Still have invalid normals in mesh, triangle (" 
<< (*tr_it).v[0] << "," << (*tr_it).v[1] << "," << (*tr_it).v[2] << ")\n";
+           }
+           if (verbose > 1) {
+               bu_vls_sprintf(&fname, 
"%d-invalid_normal_tri_%ld_%ld_%ld.plot3", f_id, (*tr_it).v[0], (*tr_it).v[1], 
(*tr_it).v[2]);
+               tri_plot(*tr_it, bu_vls_cstr(&fname));
+           }
            nret = false;
        }
     }
 
-    if (!nret) {
+    if (!nret && verbose > 1) {
        bu_vls_sprintf(&fname, "%d-invalid_normals_mesh.plot3", f_id);
        tris_plot(bu_vls_cstr(&fname));
        bu_vls_sprintf(&fname, "%d-invalid_normals.cdtmesh", f_id);
@@ -2568,11 +2572,13 @@
 
     boundary_edges_update();
     if (problem_edges.size() > 0) {
-       std::cout << "Still have problem edges in mesh\n";
+       if (verbose > 0) {
+           std::cout << "Still have problem edges in mesh\n";
+       }
        eret = false;
     }
 
-    if (!eret) {
+    if (!eret && verbose > 1) {
        bu_vls_sprintf(&fname, "%d-invalid_normals_mesh.plot3", f_id);
        tris_plot(bu_vls_cstr(&fname));
        bu_vls_sprintf(&fname, "%d-invalid_edges.cdtmesh", f_id);
@@ -2581,7 +2587,6 @@
        boundary_edges_plot(bu_vls_cstr(&fname));
     }
 
-
     bu_vls_free(&fname);
     return (nret && eret);
 }

Modified: brlcad/trunk/src/libbrep/cdt_mesh.h
===================================================================
--- brlcad/trunk/src/libbrep/cdt_mesh.h 2019-09-06 02:04:37 UTC (rev 73842)
+++ brlcad/trunk/src/libbrep/cdt_mesh.h 2019-09-06 13:12:00 UTC (rev 73843)
@@ -424,7 +424,7 @@
            );
     bool repair();
     void reset();
-    bool valid();
+    bool valid(int verbose);
     bool serialize(const char *fname);
     bool deserialize(const char *fname);
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to