Revision: 73826
          http://sourceforge.net/p/brlcad/code/73826
Author:   starseeker
Date:     2019-09-04 19:07:15 +0000 (Wed, 04 Sep 2019)
Log Message:
-----------
Begin scrubbing out the code no longer used by the new logic flow.

Modified Paths:
--------------
    brlcad/trunk/src/libbrep/CMakeLists.txt
    brlcad/trunk/src/libbrep/cdt.cpp
    brlcad/trunk/src/libbrep/cdt.h
    brlcad/trunk/src/libbrep/cdt_mesh.cpp
    brlcad/trunk/src/libbrep/cdt_mesh.h
    brlcad/trunk/src/libbrep/cdt_util.cpp
    brlcad/trunk/src/libbrep/cdt_validate.cpp

Removed Paths:
-------------
    brlcad/trunk/src/libbrep/cdt_edge.cpp
    brlcad/trunk/src/libbrep/cdt_patch.cpp
    brlcad/trunk/src/libbrep/cdt_surf.cpp
    brlcad/trunk/src/libbrep/trimesh.cpp
    brlcad/trunk/src/libbrep/trimesh.h

Modified: brlcad/trunk/src/libbrep/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbrep/CMakeLists.txt     2019-09-04 18:42:32 UTC (rev 
73825)
+++ brlcad/trunk/src/libbrep/CMakeLists.txt     2019-09-04 19:07:15 UTC (rev 
73826)
@@ -24,10 +24,6 @@
   Subcurve.cpp
   Subsurface.cpp
   boolean.cpp
-  cdt_closed_surf.cpp
-  cdt_edge.cpp
-  cdt_patch.cpp
-  cdt_surf.cpp
   cdt_surf2.cpp
   cdt_util.cpp
   cdt_validate.cpp
@@ -46,7 +42,6 @@
   shape_recognition_sphere.cpp
   shape_recognition_util.cpp
   ssx_event.cpp
-  trimesh.cpp
   #opennurbs_fit.cpp
   )
 
@@ -55,6 +50,7 @@
   brep_except.h
   cdt.h
   cdt_mesh.h
+  cdt_closed_surf.cpp
   opennurbs_fit.h
   opennurbs_fit.cpp
   PullbackCurve.h
@@ -61,7 +57,6 @@
   shape_recognition.h
   shape_recognition_torus.cpp
   surface_tree_queue_tests.patch
-  trimesh.h
   )
 CMAKEFILES(${libbrep_ignored_files})
 

Modified: brlcad/trunk/src/libbrep/cdt.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt.cpp    2019-09-04 18:42:32 UTC (rev 73825)
+++ brlcad/trunk/src/libbrep/cdt.cpp    2019-09-04 19:07:15 UTC (rev 73826)
@@ -32,76 +32,6 @@
 #define BREP_PLANAR_TOL 0.05
 #define MAX_TRIANGULATION_ATTEMPTS 5
 
-#if 0
-static int
-full_retriangulation(struct ON_Brep_CDT_Face_State *f)
-{
-
-    // TODO - for now, don't reset before returning the error - we want to see 
the
-    // failed mesh for debugging
-    ON_Brep_CDT_Face_Reset(f, 0);
-
-    p2t::CDT *cdt = NULL;
-    bool outer = build_poly2tri_polylines(f, &cdt, 0);
-    if (outer) {
-       std::cerr << "Error: Face(" << f->ind << ") cannot evaluate its outer 
loop and will not be facetized." << std::endl;
-       return -1;
-    }
-
-    std::set<ON_2dPoint *>::iterator p_it;
-    for (p_it = f->on_surf_points->begin(); p_it != f->on_surf_points->end(); 
p_it++) {
-       ON_2dPoint *p = *p_it;
-       p2t::Point *tp = new p2t::Point(p->x, p->y);
-       (*f->p2t_to_on2_map)[tp] = p;
-       cdt->AddPoint(tp);
-    }
-
-    // All preliminary steps are complete, perform the triangulation using
-    // Poly2Tri's triangulation.  NOTE: it is important that the inputs to
-    // Poly2Tri satisfy its constraints - failure here could cause a crash.
-    cdt->Triangulate(true, -1);
-
-    // Copy triangles to set
-    std::vector<p2t::Triangle*> cdt_tris = cdt->GetTriangles();
-    for (size_t i = 0; i < cdt_tris.size(); i++) {
-       p2t::Triangle *t = cdt_tris[i];
-       f->tris->insert(new p2t::Triangle(*t));
-    }
-    delete cdt;
-
-    populate_3d_pnts(f);
-
-    // Validate that all points have a corresponding 3D point
-    std::set<p2t::Triangle*>::iterator  s_it;
-    for (s_it = f->tris->begin(); s_it != f->tris->end(); s_it++) {
-       p2t::Triangle *t = *s_it;
-       for (size_t j = 0; j < 3; j++) {
-           p2t::Point *tp = t->GetPoint(j);
-           if (f->p2t_to_on3_map->find(tp) == f->p2t_to_on3_map->end()) {
-               bu_log("Error - triangle created with invalid 3D mapping!\n");
-           }
-       }
-    }
-
-    // Identify any singular points
-    f->singularities->clear();
-    if (f->has_singular_trims) {
-       std::set<p2t::Triangle *>::iterator tr_it;
-       for (tr_it = f->tris->begin(); tr_it != f->tris->end(); tr_it++) {
-           p2t::Triangle *t = *tr_it;
-           for (size_t j = 0; j < 3; j++) {
-               ON_3dPoint *p3d = (*f->p2t_to_on3_map)[t->GetPoint(j)];
-               if (f->s_cdt->singular_vert_to_norms->find(p3d) != 
f->s_cdt->singular_vert_to_norms->end()) {
-                   f->singularities->insert(p3d);
-               }
-           }
-       }
-    }
-
-    return 0;
-}
-#endif
-
 bool
 refine_triangulation(struct ON_Brep_CDT_State *s_cdt, cdt_mesh::cdt_mesh_t 
*fmesh, int cnt, int rebuild)
 {
@@ -244,96 +174,6 @@
     return refine_triangulation(s_cdt, fmesh, 0, 0);
 }
 
-#if 0
-int
-ON_Brep_CDT_Face(struct ON_Brep_CDT_Face_State *f)
-{
-    struct ON_Brep_CDT_State *s_cdt = f->s_cdt;
-    int face_index = f->ind;
-    ON_BrepFace &face = f->s_cdt->brep->m_F[face_index];
-    const ON_Surface *s = face.SurfaceOf();
-    int loop_cnt = face.LoopCount();
-    ON_SimpleArray<BrepTrimPoint> *brep_loop_points = (f->face_loop_points) ? 
f->face_loop_points : new ON_SimpleArray<BrepTrimPoint>[loop_cnt];
-    f->face_loop_points = brep_loop_points;
-
-    // If this face is using at least one singular trim, set the flag
-    for (int li = 0; li < loop_cnt; li++) {
-       ON_BrepLoop *l = face.Loop(li);
-       int trim_count = l->TrimCount();
-       for (int lti = 0; lti < trim_count; lti++) {
-           ON_BrepTrim *trim = l->Trim(lti);
-           if (trim->m_type == ON_BrepTrim::singular) {
-               f->has_singular_trims = 1;
-               break;
-           }
-       }
-       if (f->has_singular_trims) {
-           break;
-       }
-    }
-
-
-    // Use the edge curves and loops to generate an initial set of trim 
polygons.
-    for (int li = 0; li < loop_cnt; li++) {
-       Process_Loop_Edges(f, li);
-    }
-
-    // Handle a variety of situations that complicate loop handling on closed 
surfaces
-    if (s->IsClosed(0) || s->IsClosed(1)) {
-       bool verbose = false;
-       PerformClosedSurfaceChecks(s_cdt, s, face, brep_loop_points, 
BREP_SAME_POINT_TOLERANCE, verbose);
-    }
-
-    // Find for this face, find the minimum and maximum edge polyline segment 
lengths
-    (*s_cdt->max_edge_seg_len)[face.m_face_index] = 0.0;
-    (*s_cdt->min_edge_seg_len)[face.m_face_index] = DBL_MAX;
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 1) {
-           ON_3dPoint *p1 = (brep_loop_points[li])[0].p3d;
-           ON_3dPoint *p2 = NULL;
-           for (int i = 1; i < num_loop_points; i++) {
-               p2 = p1;
-               p1 = (brep_loop_points[li])[i].p3d;
-               fastf_t dist = p1->DistanceTo(*p2);
-               if (dist > (*s_cdt->max_edge_seg_len)[face.m_face_index]) {
-                   (*s_cdt->max_edge_seg_len)[face.m_face_index] = dist;
-               }
-               if ((dist > SMALL_FASTF) && (dist < 
(*s_cdt->min_edge_seg_len)[face.m_face_index]))  {
-                   (*s_cdt->min_edge_seg_len)[face.m_face_index] = dist;
-               }
-           }
-       }
-    }
-
-    // Populate fedges
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       for (int i = 1; i < num_loop_points; i++) {
-           // map point to last entry to 3d point
-           f->s_cdt->fedges.insert(std::make_pair((brep_loop_points[li])[i - 
1].p3d, (brep_loop_points[li])[i].p3d));
-       }
-       
f->s_cdt->fedges.insert(std::make_pair((brep_loop_points[li])[num_loop_points-1].p3d,
 (brep_loop_points[li])[0].p3d));
-    }
-
-    // TODO - we may need to add 2D points on trims that the edges didn't know
-    // about.  Since 3D points must be shared along edges and we're using
-    // synchronized numbers of parametric domain ordered 2D and 3D points to
-    // make that work, we will need to track new 2D points and update the
-    // corresponding 3D edge based data structures.  More than that - we must
-    // also update all 2D structures in all other faces associated with the
-    // edge in question to keep things in overall sync.
-
-    // TODO - if we are going to apply clipper boolean resolution to sets of
-    // face loops, that would come here - once we have assembled the loop
-    // polygons for the faces. That also has the potential to generate "new" 3D
-    // points on edges that are driven by 2D boolean intersections between
-    // trimming loops, and may require another update pass as above.
-
-    return do_triangulation(f);
-}
-#endif
-
 static ON_3dVector
 calc_trim_vnorm(ON_BrepVertex& v, ON_BrepTrim *trim)
 {

Modified: brlcad/trunk/src/libbrep/cdt.h
===================================================================
--- brlcad/trunk/src/libbrep/cdt.h      2019-09-04 18:42:32 UTC (rev 73825)
+++ brlcad/trunk/src/libbrep/cdt.h      2019-09-04 19:07:15 UTC (rev 73826)
@@ -36,7 +36,6 @@
 #include <set>
 #include <utility>
 
-#include "poly2tri/poly2tri.h"
 #include "RTree.h"
 
 #include "assert.h"
@@ -59,7 +58,6 @@
 #include "brep/pullback.h"
 #include "brep/util.h"
 
-#include "./trimesh.h"
 #include "./cdt_mesh.h"
 
 #define BREP_PLANAR_TOL 0.05
@@ -86,17 +84,6 @@
     ON_3dPoint vert_pnt; // For auditing normals
 };
 
-/* Halfedge info for local mesh subset building */
-struct trimesh_info {
-    std::vector<trimesh::edge_t> edges;
-    trimesh::trimesh_t mesh;
-    std::set<p2t::Point *> uniq_p2d;
-    std::map<p2t::Point *, trimesh::index_t> p2dind;
-    std::map<trimesh::index_t, p2t::Point *> ind2p2d;
-    std::map<p2t::Triangle *, trimesh::index_t> t2ind;
-    std::vector<trimesh::triangle_t> triangles;
-};
-
 struct brep_cdt_tol {
     fastf_t min_dist;
     fastf_t max_dist;
@@ -104,74 +91,7 @@
 };
 #define BREP_CDT_TOL_ZERO {0.0, 0.0, 0.0}
 
-struct BrepEdgeSegment;
-struct BrepEdgeSegment {
-    struct ON_Brep_CDT_State *s_cdt;
-    ON_BrepEdge *edge;
-    ON_NurbsCurve *nc;
-    const ON_BrepTrim *trim1;
-    const ON_BrepTrim *trim2;
-    BrepTrimPoint *sbtp1;
-    BrepTrimPoint *ebtp1;
-    BrepTrimPoint *sbtp2;
-    BrepTrimPoint *ebtp2;
-    std::map<double, BrepTrimPoint *> *trim1_param_points;
-    std::map<double, BrepTrimPoint *> *trim2_param_points;
-    std::set<struct BrepEdgeSegment *> children;
-    struct BrepEdgeSegment *parent;
-    struct brep_cdt_tol cdt_tol;
-    /* Average length of the child segments below the current segment */
-    double avg_seg_len;
-    /* Distance used when deciding to refine edges */
-    double loop_min_dist;
-};
 
-struct ON_Brep_CDT_State;
-
-struct ON_Brep_CDT_Face_State {
-    struct ON_Brep_CDT_State *s_cdt;
-
-    struct bu_vls face_root;
-
-    cdt_mesh::cdt_mesh_t fmesh;
-    std::map<ON_3dPoint *, ON_3dPoint *> *on3_to_norm_map;
-
-    int has_singular_trims;
-    std::set<ON_3dPoint *> *singularities;
-
-    int ind;
-    std::map<ON_2dPoint *, struct cdt_audit_info *> *pnt2d_audit_info;
-
-    /* 3D data specific to this face (i.e. not shared at an edge) */
-    std::vector<ON_2dPoint *> *w2dpnts;
-    std::vector<ON_3dPoint *> *w3dpnts;
-    std::vector<ON_3dPoint *> *w3dnorms;
-
-    /* loop points */
-    ON_SimpleArray<BrepTrimPoint> *face_loop_points;
-    std::map<p2t::Point *, int> *p2t_trim_ind;
-    std::set<ON_2dPoint *> *on_surf_points;
-    ON_RTree *rt_trims;
-    ON_RTree *rt_trims_3d;
-
-    /* singular trim info */
-    std::map<int,ON_3dPoint *> *strim_pnts;
-    std::map<int,ON_3dPoint *> *strim_norms;
-
-    /* mappings */
-    std::map<p2t::Point *, ON_2dPoint *> *p2t_to_on2_map;
-    std::map<p2t::Point *, ON_3dPoint *> *p2t_to_on3_map;
-    std::map<p2t::Point *, ON_3dPoint *> *p2t_to_on3_norm_map;
-    std::map<ON_3dPoint *, std::set<p2t::Point *>> *on3_to_tri_map;
-
-    /* Poly2Tri information */
-    std::set<p2t::Triangle *> *tris;
-    std::set<p2t::Triangle *> *degen_tris;
-    std::set<p2t::Point *> *degen_pnts;
-    std::set<p2t::Point *> *ext_degen_pnts;
-};
-
-
 struct ON_Brep_CDT_State {
 
     int status;
@@ -250,6 +170,7 @@
     std::set<ON_BoundingBox *> leaf_bboxes;
 };
 
+#if 0
 void
 PerformClosedSurfaceChecks(
        struct ON_Brep_CDT_State *s_cdt,
@@ -258,91 +179,32 @@
        ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
        double same_point_tolerance,
        bool verbose);
+#endif
 
 void
-Get_Edge_Points(struct ON_Brep_CDT_State *s_cdt);
-
-void
-Refine_Edges(struct ON_Brep_CDT_State *s_cdt);
-
-void
-getSurfacePoints(struct ON_Brep_CDT_Face_State *f);
-
-void
 GetInteriorPoints(struct ON_Brep_CDT_State *s_cdt, int face_index);
 
 
-struct ON_Brep_CDT_Face_State *
-ON_Brep_CDT_Face_Create(struct ON_Brep_CDT_State *s_cdt, int ind);
-void
-ON_Brep_CDT_Face_Reset(struct ON_Brep_CDT_Face_State *fcdt, int 
full_surface_sample);
-void
-ON_Brep_CDT_Face_Destroy(struct ON_Brep_CDT_Face_State *fcdt);
-
 void plot_rtree_2d(ON_RTree *rtree, const char *filename);
 void plot_rtree_2d2(RTree<void *, double, 2> &rtree, const char *filename);
-void
-plot_rtree_3d(RTree<void *, double, 3> &rtree, const char *filename);
-void
-plot_bbox(point_t m_min, point_t m_max, const char *filename);
-void
-plot_on_bbox(ON_BoundingBox &bb, const char *filename);
-void
-plot_polyline(std::vector<p2t::Point *> *pnts, const char *filename);
-void
-plot_tri(p2t::Triangle *t, const char *filename);
-void
-plot_tri_2d(p2t::Triangle *t, struct bu_color *c, FILE *plot);
-void
-plot_tri_3d(p2t::Triangle *t, std::map<p2t::Point *, ON_3dPoint *> *pointmap, 
struct bu_color *c, FILE *c_plot);
-void
-plot_trimesh_2d(std::vector<trimesh::triangle_t> &farray, const char 
*filename);
+void plot_rtree_3d(RTree<void *, double, 3> &rtree, const char *filename);
+void plot_bbox(point_t m_min, point_t m_max, const char *filename);
+void plot_on_bbox(ON_BoundingBox &bb, const char *filename);
 
-
 struct cdt_audit_info *
 cdt_ainfo(int fid, int vid, int tid, int eid, fastf_t x2d, fastf_t y2d, double 
px, double py, double pz);
 
 void
-CDT_Add2DPnt(struct ON_Brep_CDT_Face_State *f, ON_2dPoint *p, int fid, int 
vid, int tid, int eid, fastf_t tparam);
-void
 CDT_Add3DPnt(struct ON_Brep_CDT_State *s, ON_3dPoint *p, int fid, int vid, int 
tid, int eid, fastf_t x2d, fastf_t y2d);
 void
 CDT_Add3DNorm(struct ON_Brep_CDT_State *s, ON_3dPoint *norm, ON_3dPoint *vert, 
int fid, int vid, int tid, int eid, fastf_t x2d, fastf_t y2d);
 
-ON_3dVector p2tTri_Normal(p2t::Triangle *t, std::map<p2t::Point *, ON_3dPoint 
*> *pointmap);
-ON_3dVector p2tTri_Brep_Normal(struct ON_Brep_CDT_Face_State *f, p2t::Triangle 
*t);
-
 void cdt_tol_global_calc(struct ON_Brep_CDT_State *s);
-void
-CDT_Tol_Set(struct brep_cdt_tol *cdt, double dist, fastf_t md, double t_abs, 
double t_rel, double t_dist);
+void CDT_Tol_Set(struct brep_cdt_tol *cdt, double dist, fastf_t md, double 
t_abs, double t_rel, double t_dist);
 
-void populate_3d_pnts(struct ON_Brep_CDT_Face_State *f);
-
-void triangles_degenerate_trivial(struct ON_Brep_CDT_Face_State *f);
-void triangles_degenerate_area(struct ON_Brep_CDT_Face_State *f);
-void triangles_degenerate_area_notify(struct ON_Brep_CDT_Face_State *f);
-int triangles_check_edge_tris(struct ON_Brep_CDT_Face_State *f);
-int triangles_slim_edge(struct ON_Brep_CDT_Face_State *f);
-int triangles_incorrect_normals(struct ON_Brep_CDT_Face_State *f, 
std::set<p2t::Triangle *> *atris);
-
-
-int triangles_check_edges(struct ON_Brep_CDT_Face_State *f);
-
-void triangles_rebuild_involved(struct ON_Brep_CDT_Face_State *f);
-
 void
 trimesh_error_report(struct ON_Brep_CDT_State *s_cdt, int valid_fcnt, int 
valid_vcnt, int *valid_faces, fastf_t *valid_vertices, struct 
bg_trimesh_solid_errors *se);
 
-bool build_poly2tri_polylines(struct ON_Brep_CDT_Face_State *f, p2t::CDT 
**cdt, int init_rtree);
-
-void
-Process_Loop_Edges(struct ON_Brep_CDT_Face_State *f, int li);
-
-struct trimesh_info *CDT_Face_Build_Halfedge(std::set<p2t::Triangle *> 
*triangles);
-
-int Remesh_Near_Tri(struct ON_Brep_CDT_Face_State *f, p2t::Triangle *t, 
std::set<p2t::Triangle *> *wq);
-int Remesh_Near_cTri(struct ON_Brep_CDT_Face_State *f, cdt_mesh::triangle_t t, 
std::set<cdt_mesh::triangle_t> *wq, int rcnt);
-
 int
 ON_Brep_CDT_Tessellate2(struct ON_Brep_CDT_State *s_cdt);
 

Deleted: brlcad/trunk/src/libbrep/cdt_edge.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_edge.cpp       2019-09-04 18:42:32 UTC (rev 
73825)
+++ brlcad/trunk/src/libbrep/cdt_edge.cpp       2019-09-04 19:07:15 UTC (rev 
73826)
@@ -1,1252 +0,0 @@
-/*                        C D T . C P P
- * BRL-CAD
- *
- * Copyright (c) 2007-2019 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @addtogroup libbrep */
-/** @{ */
-/** @file cdt.cpp
- *
- * Constrained Delaunay Triangulation of NURBS B-Rep objects.
- *
- * Routines for processing 3D edges
- */
-
-#include "common.h"
-#include "brep.h"
-#include "./cdt.h"
-
-// TODO - need a tree-ish structure for each edge so we can
-// take a 3D point and use it as a guide to refine the
-// splitting up of the edge, without redoing the whole
-// subdivision for the entire edge.  There will almost certainly
-// be a variety of situations were we need to locally refine
-// the edge approximation, and we don't want to have to start
-// over each time.  One already-observed situation is when the
-// edge curve is very blocky compared to the mesh of the associated
-// surface (large cylinder fillet surface - big circle with large
-// linear segments, but curve in the other direction of the surface
-// requires very fine triangles - this creates very distorted
-// triangles at best and can even create "wrong" triangles depending
-// on how the 2D sampling vs 3D projections work out.)  Another
-// highly probable situation will be refinement in object overlap
-// regions - we'll have to first refine any involved edges before
-// we can work on the faces.
-
-struct BrepEdgeSegment *
-NewBrepEdgeSegment(struct BrepEdgeSegment *parent)
-{
-    BrepEdgeSegment *bseg = NULL;
-    if (parent) {
-       bseg = new BrepEdgeSegment(*parent);
-       bseg->children.clear();
-    } else {
-       bseg = new BrepEdgeSegment;
-    }
-    bseg->sbtp1 = NULL;
-    bseg->ebtp1 = NULL;
-    bseg->sbtp2 = NULL;
-    bseg->ebtp2 = NULL;
-    bseg->parent = parent;
-    if (parent) {
-       parent->children.insert(bseg);
-    }
-
-    return bseg;
-}
-
-
-BrepTrimPoint *
-Add_BrepTrimPoint(
-       struct ON_Brep_CDT_State *s_cdt,
-       std::map<double, BrepTrimPoint *> *tpp,
-       ON_3dPoint *p3d, ON_3dPoint *norm,
-       ON_3dVector &tangent, double e, ON_3dPoint &p2d,
-       ON_3dVector &trim_normal, double t, int trim_index
-       )
-{
-    BrepTrimPoint *btp = new BrepTrimPoint;
-    btp->p3d = p3d;
-    btp->n3d = norm;
-    btp->tangent = tangent;
-    btp->e = e;
-    btp->p2d = p2d;
-    if (s_cdt->singular_vert_to_norms->find(p3d) == 
s_cdt->singular_vert_to_norms->end()) {
-       btp->normal = trim_normal;
-    } else {
-       btp->normal = ON_3dVector::UnsetVector;
-    }
-    btp->t = t;
-    btp->trim_ind = trim_index;
-    (*tpp)[btp->t] = btp;
-    (*s_cdt->on_brep_edge_pnts)[p3d].insert(btp);
-    return btp;
-}
-
-double
-midpt_binary_search(fastf_t *tmid, const ON_BrepTrim *trim, double tstart, 
double tend, ON_3dPoint &edge_mid_3d, double tol, int verbose)
-{
-    double tcmid = (tstart + tend) / 2.0;
-    ON_3dPoint trim_mid_2d = trim->PointAt(tcmid);
-    const ON_Surface *s = trim->SurfaceOf();
-    ON_3dPoint trim_mid_3d = s->PointAt(trim_mid_2d.x, trim_mid_2d.y);
-    double dist = edge_mid_3d.DistanceTo(trim_mid_3d);
-
-    if (dist > tol) {
-       ON_3dPoint trim_start_2d = trim->PointAt(tstart);
-       ON_3dPoint trim_end_2d = trim->PointAt(tend);
-       ON_3dPoint trim_start_3d = s->PointAt(trim_start_2d.x, trim_start_2d.y);
-       ON_3dPoint trim_end_3d = s->PointAt(trim_end_2d.x, trim_end_2d.y);
-
-       ON_3dVector v1 = edge_mid_3d - trim_start_3d;
-       ON_3dVector v2 = edge_mid_3d - trim_end_3d;
-
-       if (verbose) {
-           bu_log("start point (%f %f %f) and end point (%f %f %f)\n", 
trim_start_3d.x, trim_start_3d.y, trim_start_3d.z, trim_end_3d.x, 
trim_end_3d.y, trim_end_3d.z);
-           bu_log("Note (%f:%f)%f - edge point (%f %f %f) and trim point (%f 
%f %f): %f, %f\n", tstart, tend, ON_DotProduct(v1,v2), edge_mid_3d.x, 
edge_mid_3d.y, edge_mid_3d.z, trim_mid_3d.x, trim_mid_3d.y, trim_mid_3d.z, 
dist, tol);
-       }
-
-       if (ON_DotProduct(v1,v2) < 0) {
-           if (verbose)
-               bu_log("(%f - %f - %f (%f): searching left and right 
subspans\n", tstart, tcmid, tend, ON_DotProduct(v1,v2));
-           double tlmid, trmid;
-           double fldist = midpt_binary_search(&tlmid, trim, tstart, tcmid, 
edge_mid_3d, tol, 0);
-           double frdist = midpt_binary_search(&trmid, trim, tcmid, tend, 
edge_mid_3d, tol, 0);
-           if (fldist >= 0 && frdist < -1) {
-               if (verbose)
-                   bu_log("(%f - %f - %f: going with fldist: %f\n", tstart, 
tcmid, tend, fldist);
-               (*tmid) = tlmid;
-               return fldist;
-           }
-           if (frdist >= 0 && fldist < -1) {
-               if (verbose)
-                   bu_log("(%f - %f - %f: going with frdist: %f\n", tstart, 
tcmid, tend, frdist);
-               (*tmid) = trmid;
-               return frdist;
-           }
-           if (fldist < -1 && frdist < -1) {
-               if (verbose)
-                   bu_log("(%f - %f: point not in either subspan (%f)\n", 
tstart, tend, ON_DotProduct(v1,v2));
-               return -2;
-           }
-       } else {
-           // Not in this span
-           if (verbose)
-               bu_log("(%f - %f: point not in span (dot-product: %f)\n", 
tstart, tend, ON_DotProduct(v1,v2));
-           return -2;
-       }
-    }
-
-    // close enough - this works
-    if (verbose)
-       bu_log("Workable (%f:%f) - edge point (%f %f %f) and trim point (%f %f 
%f): %f, %f\n", tstart, tend, edge_mid_3d.x, edge_mid_3d.y, edge_mid_3d.z, 
trim_mid_3d.x, trim_mid_3d.y, trim_mid_3d.z, dist, tol);
-
-    (*tmid) = tcmid;
-    return dist;
-}
-
-ON_3dPoint
-get_trim_midpt(fastf_t *t, const ON_BrepTrim *trim, double tstart, double 
tend, ON_3dPoint &edge_mid_3d, double tol, int verbose) {
-    double tmid;
-    double dist = midpt_binary_search(&tmid, trim, tstart, tend, edge_mid_3d, 
tol, verbose);
-    if (dist < 0) {
-       if (verbose)
-           bu_log("Warning - could not find suitable trim point\n");
-       tmid = (tstart + tend) / 2.0;
-    } else {
-       if (verbose) {
-           if (dist > tol)
-               bu_log("going with distance %f greater than desired tolerance 
%f\n", dist, tol);
-       }
-    }
-    ON_3dPoint trim_mid_2d = trim->PointAt(tmid);
-    (*t) = tmid;
-    return trim_mid_2d;
-}
-
-static void
-SplitEdgeSegmentMidPt(struct BrepEdgeSegment *bseg)
-{
-    ON_3dPoint tmp1, tmp2;
-    const ON_Surface *s1 = bseg->trim1->SurfaceOf();
-    const ON_Surface *s2 = bseg->trim2->SurfaceOf();
-
-    ON_3dVector trim1_mid_norm = ON_3dVector::UnsetVector;
-    ON_3dVector trim2_mid_norm = ON_3dVector::UnsetVector;
-    ON_3dPoint edge_mid_3d = ON_3dPoint::UnsetPoint;
-    ON_3dVector edge_mid_tang = ON_3dVector::UnsetVector;
-
-    fastf_t emid = (bseg->sbtp1->e + bseg->ebtp1->e) / 2.0;
-    bool evtangent_status = bseg->nc->EvTangent(emid, edge_mid_3d, 
edge_mid_tang);
-    if (!evtangent_status) {
-       // EvTangent call failed, get 3d point
-       edge_mid_3d = bseg->nc->PointAt(emid);
-    }
-
-    // We need the trim points to be pretty close to the edge point, or
-    // we get distortions in the mesh.
-    fastf_t t1, t2;
-    fastf_t emindist = (bseg->cdt_tol.min_dist < 0.5*bseg->loop_min_dist) ? 
bseg->cdt_tol.min_dist : 0.5 * bseg->loop_min_dist;
-    ON_3dPoint trim1_mid_2d, trim2_mid_2d;
-    trim1_mid_2d = get_trim_midpt(&t1, bseg->trim1, bseg->sbtp1->t, 
bseg->ebtp1->t, edge_mid_3d, emindist, 0);
-    trim2_mid_2d = get_trim_midpt(&t2, bseg->trim2, bseg->sbtp2->t, 
bseg->ebtp2->t, edge_mid_3d, emindist, 0);
-
-    if (!evtangent_status) {
-       // If the edge curve evaluation failed, try to average tangents from 
trims
-       ON_3dVector trim1_mid_tang(0.0, 0.0, 0.0);
-       ON_3dVector trim2_mid_tang(0.0, 0.0, 0.0);
-       int evals = 0;
-       evals += (bseg->trim1->EvTangent(t1, tmp1, trim1_mid_tang)) ? 1 : 0;
-       evals += (bseg->trim2->EvTangent(t2, tmp2, trim2_mid_tang)) ? 1 : 0;
-       if (evals == 2) {
-           edge_mid_tang = (trim1_mid_tang + trim2_mid_tang) / 2;
-       } else {
-           edge_mid_tang = ON_3dVector::UnsetVector;
-       }
-    }
-
-    int dosplit = 0;
-
-    ON_Line line3d(*(bseg->sbtp1->p3d), *(bseg->ebtp1->p3d));
-    double dist3d = edge_mid_3d.DistanceTo(line3d.ClosestPointTo(edge_mid_3d));
-    dosplit += (line3d.Length() > bseg->cdt_tol.max_dist) ? 1 : 0;
-    dosplit += (dist3d > (bseg->cdt_tol.within_dist + ON_ZERO_TOLERANCE)) ? 1 
: 0;
-    dosplit += (dist3d > 2*bseg->loop_min_dist) ? 1 : 0;
-
-    if ((dist3d > bseg->cdt_tol.min_dist + ON_ZERO_TOLERANCE)) {
-       if (!dosplit) {
-           dosplit += ((bseg->sbtp1->tangent * bseg->ebtp1->tangent) < 
bseg->s_cdt->cos_within_ang - ON_ZERO_TOLERANCE) ? 1 : 0;
-       }
-
-       if (!dosplit && bseg->sbtp1->normal != ON_3dVector::UnsetVector && 
bseg->ebtp1->normal != ON_3dVector::UnsetVector) {
-           dosplit += ((bseg->sbtp1->normal * bseg->ebtp1->normal) < 
bseg->s_cdt->cos_within_ang - ON_ZERO_TOLERANCE) ? 1 : 0;
-       }
-
-       if (!dosplit && bseg->sbtp2->normal != ON_3dVector::UnsetVector && 
bseg->ebtp2->normal != ON_3dVector::UnsetVector) {
-           dosplit += ((bseg->sbtp2->normal * bseg->ebtp2->normal) < 
bseg->s_cdt->cos_within_ang - ON_ZERO_TOLERANCE) ? 1 : 0;
-       }
-    }
-
-    if (dosplit) {
-
-       if (!surface_EvNormal(s1, trim1_mid_2d.x, trim1_mid_2d.y, tmp1, 
trim1_mid_norm)) {
-           trim1_mid_norm = ON_3dVector::UnsetVector;
-       } else {
-           if (bseg->trim1->Face()->m_bRev) {
-               trim1_mid_norm = trim1_mid_norm  * -1.0;
-           }
-       }
-
-       if (!surface_EvNormal(s2, trim2_mid_2d.x, trim2_mid_2d.y, tmp2, 
trim2_mid_norm)) {
-           trim2_mid_norm = ON_3dVector::UnsetVector;
-       } else {
-           if (bseg->trim2->Face()->m_bRev) {
-               trim2_mid_norm = trim2_mid_norm  * -1.0;
-           }
-       }
-
-       ON_3dPoint *npt = new ON_3dPoint(edge_mid_3d);
-       CDT_Add3DPnt(bseg->s_cdt, npt, -1, -1, -1, bseg->edge->m_edge_index, 
emid, 0);
-       bseg->s_cdt->edge_pnts->insert(npt);
-
-       BrepTrimPoint *nbtp1 = Add_BrepTrimPoint(bseg->s_cdt, 
bseg->trim1_param_points, npt, NULL, edge_mid_tang, emid, trim1_mid_2d, 
trim1_mid_norm, t1, bseg->trim1->m_trim_index);
-
-       BrepTrimPoint *nbtp2 = Add_BrepTrimPoint(bseg->s_cdt, 
bseg->trim2_param_points, npt, NULL, edge_mid_tang, emid, trim2_mid_2d, 
trim2_mid_norm, t2, bseg->trim2->m_trim_index);
-
-       struct BrepEdgeSegment *bseg1 = NewBrepEdgeSegment(bseg);
-       bseg1->sbtp1 = bseg->sbtp1;
-       bseg1->ebtp1 = nbtp1;
-       bseg1->sbtp2 = bseg->sbtp2;
-       bseg1->ebtp2 = nbtp2;
-       SplitEdgeSegmentMidPt(bseg1);
-
-
-       struct BrepEdgeSegment *bseg2 = NewBrepEdgeSegment(bseg);
-       bseg2->sbtp1 = nbtp1;
-       bseg2->ebtp1 = bseg->ebtp1;
-       bseg2->sbtp2 = nbtp2;
-       bseg2->ebtp2 = bseg->ebtp2;
-       SplitEdgeSegmentMidPt(bseg2);
-
-
-       bseg->avg_seg_len = (bseg1->avg_seg_len + bseg2->avg_seg_len) * 0.5; 
-
-       return;
-    }
-
-    int udir = 0;
-    int vdir = 0;
-    double trim1_seam_t = 0.0;
-    double trim2_seam_t = 0.0;
-    ON_2dPoint trim1_start = bseg->sbtp1->p2d;
-    ON_2dPoint trim1_end = bseg->ebtp1->p2d;
-    ON_2dPoint trim2_start = bseg->sbtp2->p2d;
-    ON_2dPoint trim2_end = bseg->ebtp2->p2d;
-    ON_2dPoint trim1_seam_2d, trim2_seam_2d;
-    ON_3dPoint trim1_seam_3d, trim2_seam_3d;
-    int t1_dosplit = 0;
-    int t2_dosplit = 0;
-
-    if (ConsecutivePointsCrossClosedSeam(s1, trim1_start, trim1_end, udir, 
vdir, BREP_SAME_POINT_TOLERANCE)) {
-       ON_2dPoint from = ON_2dPoint::UnsetPoint;
-       ON_2dPoint to = ON_2dPoint::UnsetPoint;
-       if (FindTrimSeamCrossing(*bseg->trim1, bseg->sbtp1->t, bseg->ebtp1->t, 
trim1_seam_t, from, to, BREP_SAME_POINT_TOLERANCE)) {
-           trim1_seam_2d = bseg->trim1->PointAt(trim1_seam_t);
-           trim1_seam_3d = s1->PointAt(trim1_seam_2d.x, trim1_seam_2d.y);
-           if (bseg->trim1_param_points->find(trim1_seam_t) == 
bseg->trim1_param_points->end()) {
-               t1_dosplit = 1;
-           }
-       }
-    }
-
-    if (ConsecutivePointsCrossClosedSeam(s2, trim2_start, trim2_end, udir, 
vdir, BREP_SAME_POINT_TOLERANCE)) {
-       ON_2dPoint from = ON_2dPoint::UnsetPoint;
-       ON_2dPoint to = ON_2dPoint::UnsetPoint;
-       if (FindTrimSeamCrossing(*bseg->trim2, bseg->sbtp2->t, bseg->ebtp2->t, 
trim2_seam_t, from, to, BREP_SAME_POINT_TOLERANCE)) {
-           trim2_seam_2d = bseg->trim2->PointAt(trim2_seam_t);
-           trim2_seam_3d = s2->PointAt(trim2_seam_2d.x, trim2_seam_2d.y);
-           if (bseg->trim2_param_points->find(trim2_seam_t) == 
bseg->trim2_param_points->end()) {
-               t2_dosplit = 1;
-           }
-       }
-    }
-
-    if (t1_dosplit || t2_dosplit) {
-       ON_3dPoint *nsptp = NULL;
-       if (t1_dosplit && t2_dosplit) {
-           ON_3dPoint nspt = (trim1_seam_3d + trim2_seam_3d)/2;
-           nsptp = new ON_3dPoint(nspt);
-           CDT_Add3DPnt(bseg->s_cdt, nsptp, bseg->trim1->Face()->m_face_index, 
-1, bseg->trim1->m_trim_index, bseg->trim1->Edge()->m_edge_index, 
trim1_seam_2d.x, trim1_seam_2d.y);
-           bseg->s_cdt->edge_pnts->insert(nsptp);
-       } else {
-           // Since the above if test got the both-true case, only one of 
these at
-           // a time will ever be true.  TODO - could this be a source of 
degenerate
-           // faces in 3D if we're only splitting one trim?
-           if (!t1_dosplit) {
-               trim1_seam_t = (bseg->sbtp1->t + bseg->ebtp1->t)/2;
-               trim1_seam_2d = bseg->trim1->PointAt(trim1_seam_t);
-               nsptp = new ON_3dPoint(trim2_seam_3d);
-               CDT_Add3DPnt(bseg->s_cdt, nsptp, 
bseg->trim2->Face()->m_face_index, -1, bseg->trim2->m_trim_index, 
bseg->trim2->Edge()->m_edge_index, trim1_seam_2d.x, trim1_seam_2d.y);
-               bseg->s_cdt->edge_pnts->insert(nsptp);
-           }
-           if (!t2_dosplit) {
-               trim2_seam_t = (bseg->sbtp2->t + bseg->ebtp2->t)/2;
-               trim2_seam_2d = bseg->trim2->PointAt(trim2_seam_t);
-               nsptp = new ON_3dPoint(trim1_seam_3d);
-               CDT_Add3DPnt(bseg->s_cdt, nsptp, 
bseg->trim1->Face()->m_face_index, -1, bseg->trim1->m_trim_index, 
bseg->trim1->Edge()->m_edge_index, trim1_seam_2d.x, trim1_seam_2d.y);
-               bseg->s_cdt->edge_pnts->insert(nsptp);
-           }
-       }
-
-       // Note - by this point we shouldn't need tangents and normals...
-       ON_3dVector v_unset = ON_3dVector::UnsetVector;
-       ON_3dPoint t1s2d(trim1_seam_2d);
-       (void)Add_BrepTrimPoint(bseg->s_cdt, bseg->trim1_param_points, nsptp, 
NULL, v_unset, ON_UNSET_VALUE, t1s2d, v_unset, trim1_seam_t, 
bseg->trim1->m_trim_index);
-
-       ON_3dPoint t2s2d(trim2_seam_2d);
-       (void)Add_BrepTrimPoint(bseg->s_cdt, bseg->trim2_param_points, nsptp, 
NULL, v_unset, ON_UNSET_VALUE, t2s2d, v_unset, trim2_seam_t, 
bseg->trim2->m_trim_index);
-    }
-
-    bseg->avg_seg_len = line3d.Length();
-
-    // This is a leaf - put it in the rtrees
-
-    double p1[3];
-    p1[0] = bseg->sbtp1->p3d->x;
-    p1[1] = bseg->sbtp1->p3d->y;
-    p1[2] = bseg->sbtp1->p3d->z;
-    double p2[3];
-    p2[0] = bseg->ebtp1->p3d->x;
-    p2[1] = bseg->ebtp1->p3d->y;
-    p2[2] = bseg->ebtp1->p3d->z;
-
-    bseg->s_cdt->edge_segs_3d[bseg->trim1->Face()->m_face_index].Insert(p1, 
p2, (void *)bseg);
-    bseg->s_cdt->edge_segs_3d[bseg->trim2->Face()->m_face_index].Insert(p1, 
p2, (void *)bseg);
-}
-
-
-double
-getEdgePoints(
-       struct ON_Brep_CDT_State *s_cdt,
-       ON_BrepEdge *edge,
-       fastf_t max_dist,
-       fastf_t loop_min_dist
-       )
-{
-    std::map<double, BrepTrimPoint *> *trim1_param_points = NULL;
-    std::map<double, BrepTrimPoint *> *trim2_param_points = NULL;
-
-    // Get the trims
-    // TODO - this won't work if we don't have a 1->2 edge to trims 
relationship - in that
-    // case we'll have to split up the edge and find the matching sub-trims 
(possibly splitting
-    // those as well if they don't line up at shared 3D points.)
-    ON_BrepTrim *trim1 = edge->Trim(0);
-    ON_BrepTrim *trim2 = edge->Trim(1);
-
-    double dist = 1000.0;
-
-    const ON_Surface *s1 = trim1->SurfaceOf();
-    const ON_Surface *s2 = trim2->SurfaceOf();
-
-    bool bGrowBox = false;
-    ON_3dPoint min, max;
-
-    /* If we're out of sync, bail - something is very very wrong */
-    if (trim1->m_trim_user.p != NULL && trim2->m_trim_user.p == NULL) {
-       return -1;
-    }
-    if (trim1->m_trim_user.p == NULL && trim2->m_trim_user.p != NULL) {
-       return -1;
-    }
-
-
-    /* If we've already got the points, just return them */
-    if (trim1->m_trim_user.p != NULL) {
-       trim1_param_points = (std::map<double, BrepTrimPoint *> *) 
trim1->m_trim_user.p;
-       return (*s_cdt->etrees)[edge->m_edge_index]->avg_seg_len;
-    }
-
-
-
-    /* Normalize the domain of the curve to the ControlPolygonLength() of the
-     * NURBS form of the curve to attempt to minimize distortion in 3D to
-     * mirror what we do for the surfaces.  (GetSurfaceSize uses this under the
-     * hood for its estimates.)  */
-    const ON_Curve* crv = edge->EdgeCurveOf();
-    ON_NurbsCurve *nc = crv->NurbsCurve();
-    double cplen = nc->ControlPolygonLength();
-    nc->SetDomain(0.0, cplen);
-    s_cdt->brep->m_T[trim1->TrimCurveIndexOf()].SetDomain(0.0, cplen);
-    s_cdt->brep->m_T[trim2->TrimCurveIndexOf()].SetDomain(0.0, cplen);
-    ON_Interval erange = nc->Domain();
-
-
-    /* Begin point collection */
-    ON_3dPoint tmp1, tmp2;
-    int evals = 0;
-    ON_3dPoint *edge_start_3d, *edge_end_3d = NULL;
-    ON_3dVector edge_start_tang, edge_end_tang = ON_3dVector::UnsetVector;
-    ON_3dPoint trim1_start_2d, trim1_end_2d = ON_3dPoint::UnsetPoint;
-    ON_3dVector trim1_start_tang, trim1_end_tang = ON_3dVector::UnsetVector;
-    ON_3dPoint trim2_start_2d, trim2_end_2d = ON_3dPoint::UnsetPoint;
-    ON_3dVector trim2_start_tang, trim2_end_tang = ON_3dVector::UnsetVector;
-
-    trim1_param_points = new std::map<double, BrepTrimPoint *>();
-    trim1->m_trim_user.p = (void *) trim1_param_points;
-    trim2_param_points = new std::map<double, BrepTrimPoint *>();
-    trim2->m_trim_user.p = (void *) trim2_param_points;
-
-    ON_Interval range1 = trim1->Domain();
-    ON_Interval range2 = trim2->Domain();
-
-    // TODO - what is this for?
-    if (s1->IsClosed(0) || s1->IsClosed(1)) {
-       ON_BoundingBox trim_bbox = ON_BoundingBox::EmptyBoundingBox;
-       trim1->GetBoundingBox(trim_bbox, false);
-    }
-    if (s2->IsClosed(0) || s2->IsClosed(1)) {
-       ON_BoundingBox trim_bbox2 = ON_BoundingBox::EmptyBoundingBox;
-       trim2->GetBoundingBox(trim_bbox2, false);
-    }
-
-    /* For the start and end points, use the vertex point */
-    edge_start_3d = (*s_cdt->vert_pnts)[edge->Vertex(0)->m_vertex_index];
-    edge_end_3d = (*s_cdt->vert_pnts)[edge->Vertex(1)->m_vertex_index];
-
-    /* Populate the 2D points */
-    double st1 = (trim1->m_bRev3d) ? range1.m_t[1] : range1.m_t[0];
-    double et1 = (trim1->m_bRev3d) ? range1.m_t[0] : range1.m_t[1];
-    double st2 = (trim2->m_bRev3d) ? range2.m_t[1] : range2.m_t[0];
-    double et2 = (trim2->m_bRev3d) ? range2.m_t[0] : range2.m_t[1];
-    trim1_start_2d = trim1->PointAt(st1);
-    trim1_end_2d = trim1->PointAt(et1);
-    trim2_start_2d = trim2->PointAt(st2);
-    trim2_end_2d = trim2->PointAt(et2);
-
-    /* Get starting tangent from edge*/
-    if (!(nc->EvTangent(erange.m_t[0], tmp1, edge_start_tang))) {
-       // If the edge curve failed, average tangents from trims
-       evals = 0;
-       evals += (trim1->EvTangent(st1, tmp1, trim1_start_tang)) ? 1 : 0;
-       evals += (trim2->EvTangent(st2, tmp2, trim2_start_tang)) ? 1 : 0;
-       if (evals == 2) {
-           edge_start_tang = (trim1_start_tang + trim2_start_tang) / 2;
-       } else {
-           edge_start_tang = ON_3dVector::UnsetVector;
-       }
-    }
-    /* Get ending tangent from edge*/
-    if (!(nc->EvTangent(erange.m_t[1], tmp2, edge_end_tang))) {
-       // If the edge curve failed, average tangents from trims
-       evals = 0;
-       evals += (trim1->EvTangent(et1, tmp1, trim1_end_tang)) ? 1 : 0;
-       evals += (trim2->EvTangent(et2, tmp2, trim2_end_tang)) ? 1 : 0;
-       if (evals == 2) {
-           edge_end_tang = (trim1_end_tang + trim2_end_tang) / 2;
-       } else {
-           edge_end_tang = ON_3dVector::UnsetVector;
-       }
-    }
-
-    // Get the normals
-    ON_3dPoint tmpp;
-    ON_3dVector trim1_start_normal, trim1_end_normal = 
ON_3dVector::UnsetVector;
-    ON_3dVector trim2_start_normal, trim2_end_normal = 
ON_3dVector::UnsetVector;
-    ON_3dPoint *t1_sn, *t1_en, *t2_sn, *t2_en = NULL;
-    ON_3dPoint *edge_start_3dnorm = 
(*s_cdt->vert_avg_norms)[edge->Vertex(0)->m_vertex_index];
-    ON_3dPoint *edge_end_3dnorm = 
(*s_cdt->vert_avg_norms)[edge->Vertex(1)->m_vertex_index];
-
-    /* trim 1 */
-    if (!surface_EvNormal(s1, trim1_start_2d.x, trim1_start_2d.y, tmpp, 
trim1_start_normal)) {
-       t1_sn = edge_start_3dnorm;
-    } else {
-       if (trim1->Face()->m_bRev) {
-           trim1_start_normal = trim1_start_normal  * -1.0;
-       }
-       if (edge_start_3dnorm && ON_DotProduct(trim1_start_normal, 
*edge_start_3dnorm) < -0.5) {
-           t1_sn = edge_start_3dnorm;
-       } else {
-           t1_sn = new ON_3dPoint(trim1_start_normal);
-           *t1_sn = trim1_start_normal;
-           s_cdt->w3dnorms->push_back(t1_sn);
-       }
-    }
-
-    if (!surface_EvNormal(s1, trim1_end_2d.x, trim1_end_2d.y, tmp1, 
trim1_end_normal)) {
-       t1_en = edge_end_3dnorm;
-    } else {
-       if (trim1->Face()->m_bRev) {
-           trim1_end_normal = trim1_end_normal  * -1.0;
-       }
-       if (edge_end_3dnorm && ON_DotProduct(trim1_end_normal, 
*edge_end_3dnorm) < -0.5) {
-           t1_en = edge_end_3dnorm;
-       } else {
-           t1_en = new ON_3dPoint(trim1_end_normal);
-           *t1_en = trim1_end_normal;
-           s_cdt->w3dnorms->push_back(t1_en);
-       }
-    }
-
-
-    /* trim 2 */
-    if (!surface_EvNormal(s2, trim2_start_2d.x, trim2_start_2d.y, tmpp, 
trim2_start_normal)) {
-       t2_sn = edge_start_3dnorm;
-    } else {
-       if (trim2->Face()->m_bRev) {
-           trim2_start_normal = trim2_start_normal  * -1.0;
-       }
-       if (edge_start_3dnorm && ON_DotProduct(trim2_start_normal, 
*edge_start_3dnorm) < -0.5) {
-           t2_sn = edge_start_3dnorm;
-       } else {
-           t2_sn = new ON_3dPoint(trim2_start_normal);
-           *t2_sn = trim2_start_normal;
-           s_cdt->w3dnorms->push_back(t2_sn);
-       }
-    }
-    if (!surface_EvNormal(s2, trim2_end_2d.x, trim2_end_2d.y, tmpp, 
trim2_end_normal)) {
-       t2_en = edge_end_3dnorm;
-    } else {
-       if (trim2->Face()->m_bRev) {
-           trim2_end_normal = trim2_end_normal  * -1.0;
-       }
-       if (edge_end_3dnorm && ON_DotProduct(trim2_end_normal, 
*edge_end_3dnorm) < -0.5) {
-           t2_en = edge_end_3dnorm;
-       } else {
-           t2_en = new ON_3dPoint(trim2_end_normal);
-           *t2_en = trim2_end_normal;
-           s_cdt->w3dnorms->push_back(t2_en);
-       }
-    }
-
-    /* Start and end points for both trims can now be defined */
-    BrepTrimPoint *sbtp1 = Add_BrepTrimPoint(s_cdt, trim1_param_points, 
edge_start_3d, t1_sn, edge_start_tang, erange.m_t[0], trim1_start_2d, 
trim1_start_normal, st1, trim1->m_trim_index);
-
-    BrepTrimPoint *ebtp1 = Add_BrepTrimPoint(s_cdt, trim1_param_points, 
edge_end_3d, t1_en, edge_end_tang, erange.m_t[1], trim1_end_2d, 
trim1_end_normal, et1, trim1->m_trim_index);
-
-    BrepTrimPoint *sbtp2 = Add_BrepTrimPoint(s_cdt, trim2_param_points, 
edge_start_3d, t2_sn, edge_start_tang, erange.m_t[0], trim2_start_2d, 
trim2_start_normal, st2, trim2->m_trim_index);
-
-    BrepTrimPoint *ebtp2 = Add_BrepTrimPoint(s_cdt, trim2_param_points, 
edge_end_3d, t2_en, edge_end_tang, erange.m_t[1], trim2_end_2d, 
trim2_end_normal, et2, trim2->m_trim_index);
-
-
-    // Set up the root BrepEdgeSegment
-    struct BrepEdgeSegment *root = NewBrepEdgeSegment(NULL);
-    root->s_cdt = s_cdt;
-    root->edge = edge;
-    root->nc = nc;
-    root->loop_min_dist = loop_min_dist;
-    root->trim1 = trim1;
-    root->trim2 = trim2;
-    root->sbtp1 = sbtp1;
-    root->ebtp1 = ebtp1;
-    root->sbtp2 = sbtp2;
-    root->ebtp2 = ebtp2;
-    root->trim1_param_points = trim1_param_points;
-    root->trim2_param_points = trim2_param_points;
-
-    (*s_cdt->etrees)[edge->m_edge_index] = root;
-
-
-    /* Establish tolerances (TODO - get from edge curve...)
-     *
-     * TODO - linear edges aren't being split nearly far enough for curved 
surfaces
-     * that generate small triangles - need some sort of heuristic.  One 
possibility - 
-     * for all loops, queue up and process non-linear edge curves first.  Use 
something
-     * (smallest avg. seg length from any non-linear edge curve in the loop?) 
to guide
-     * how far to split linear edge curves. */
-    root->cdt_tol = BREP_CDT_TOL_ZERO;
-    if (trim1->GetBoundingBox(min, max, bGrowBox)) {
-       dist = DIST_PT_PT(min, max);
-    }
-    CDT_Tol_Set(&root->cdt_tol, dist, max_dist, s_cdt->tol.abs, 
s_cdt->tol.rel, BN_TOL_DIST);
-
-    fastf_t emindist = (root->cdt_tol.min_dist < 0.5*loop_min_dist) ? 
root->cdt_tol.min_dist : 0.5 * loop_min_dist;
-
-    if (trim1->IsClosed() || trim2->IsClosed()) {
-
-       double edge_mid_range = (erange.m_t[0] + erange.m_t[1]) / 2.0;
-       ON_3dVector edge_mid_tang, trim1_mid_norm, trim2_mid_norm = 
ON_3dVector::UnsetVector;
-       ON_3dPoint edge_mid_3d = ON_3dPoint::UnsetPoint;
-
-       int ev_tangent = nc->EvTangent(edge_mid_range, edge_mid_3d, 
edge_mid_tang);
-       if (!ev_tangent) {
-           // EvTangent call failed, get 3d point
-           edge_mid_3d = nc->PointAt(edge_mid_range);
-       }
-
-       double trim1_mid_range;
-       double trim2_mid_range;
-       ON_3dPoint trim1_mid_2d = get_trim_midpt(&trim1_mid_range, trim1, 
sbtp1->t, ebtp1->t, edge_mid_3d, emindist, 0);
-       ON_3dPoint trim2_mid_2d = get_trim_midpt(&trim2_mid_range, trim2, 
sbtp2->t, ebtp2->t, edge_mid_3d, emindist, 0);
-
-       if (!ev_tangent) {
-           // If the edge curve failed, try to average tangents from trims
-           ON_3dVector trim1_mid_tang(0.0, 0.0, 0.0);
-           ON_3dVector trim2_mid_tang(0.0, 0.0, 0.0);
-           evals = 0;
-           evals += (trim1->EvTangent(trim1_mid_range, tmp1, trim1_mid_tang)) 
? 1 : 0;
-           evals += (trim2->EvTangent(trim2_mid_range, tmp2, trim2_mid_tang)) 
? 1 : 0;
-           if (evals == 2) {
-               edge_mid_tang = (trim1_start_tang + trim2_start_tang) / 2;
-           } else {
-               edge_mid_tang = ON_3dVector::UnsetVector;
-           }
-       }
-
-       evals = 0;
-       evals += (surface_EvNormal(s1, trim1_mid_2d.x, trim1_mid_2d.y, tmp1, 
trim1_mid_norm)) ? 1 : 0;
-       if (trim1->Face()->m_bRev) {
-           trim1_mid_norm = trim1_mid_norm  * -1.0;
-       }
-
-       evals += (surface_EvNormal(s2, trim2_mid_2d.x, trim2_mid_2d.y, tmp2, 
trim2_mid_norm)) ? 1 : 0;
-       if (trim2->Face()->m_bRev) {
-           trim2_mid_norm = trim2_mid_norm  * -1.0;
-       }
-
-       if (evals != 2) {
-           bu_log("problem with mid normal evals\n");
-       }
-
-       ON_3dPoint *nmp = new ON_3dPoint(edge_mid_3d);
-       CDT_Add3DPnt(s_cdt, nmp, -1, -1, -1, edge->m_edge_index, 
edge_mid_range, 0);
-       s_cdt->edge_pnts->insert(nmp);
-
-       BrepTrimPoint *mbtp1 = Add_BrepTrimPoint(s_cdt, trim1_param_points, 
nmp, NULL, edge_mid_tang, edge_mid_range, trim1_mid_2d, trim1_mid_norm, 
trim1_mid_range, trim1->m_trim_index);
-
-       BrepTrimPoint *mbtp2 = Add_BrepTrimPoint(s_cdt, trim2_param_points, 
nmp, NULL, edge_mid_tang, edge_mid_range, trim2_mid_2d, trim2_mid_norm, 
trim2_mid_range, trim2->m_trim_index);
-
-
-       struct BrepEdgeSegment *bseg1 = NewBrepEdgeSegment(root);
-       bseg1->sbtp1 = sbtp1;
-       bseg1->ebtp1 = mbtp1;
-       bseg1->sbtp2 = sbtp2;
-       bseg1->ebtp2 = mbtp2;
-       SplitEdgeSegmentMidPt(bseg1);
-
-       struct BrepEdgeSegment *bseg2 = NewBrepEdgeSegment(root);
-       bseg2->sbtp1 = mbtp1;
-       bseg2->ebtp1 = ebtp1;
-       bseg2->sbtp2 = mbtp2;
-       bseg2->ebtp2 = ebtp2;
-       SplitEdgeSegmentMidPt(bseg2);
-
-    } else {
-
-       SplitEdgeSegmentMidPt(root);
-
-    }
-
-    (*s_cdt->etrees)[edge->m_edge_index] = root;
-
-    return root->avg_seg_len;
-}
-
-static void
-RefineEdgeSegmentMidPt(struct BrepEdgeSegment *bseg, double split_dist)
-{
-
-    if (bseg->children.size()) {
-       std::set<struct BrepEdgeSegment *>::iterator b_it;
-       for (b_it = bseg->children.begin(); b_it != bseg->children.end(); 
b_it++) {
-           RefineEdgeSegmentMidPt(*b_it, split_dist);
-       }
-       double avg = 0.0;
-       for (b_it = bseg->children.begin(); b_it != bseg->children.end(); 
b_it++) {
-           avg += (*b_it)->avg_seg_len;
-       }
-       avg = avg/((double)bseg->children.size());
-       bseg->avg_seg_len = avg;
-       return;
-    }
-
-    ON_Line line3d(*(bseg->sbtp1->p3d), *(bseg->ebtp1->p3d));
-
-    if (line3d.Length() < split_dist) {
-       bseg->avg_seg_len = line3d.Length(); 
-       return;
-    }
-
-    // Splitting - proceed
-    fastf_t emid = (bseg->sbtp1->e + bseg->ebtp1->e) / 2.0;
-    ON_3dPoint edge_mid_3d = ON_3dPoint::UnsetPoint;
-    ON_3dVector edge_mid_tang = ON_3dVector::UnsetVector;
-    bool evtangent_status = bseg->nc->EvTangent(emid, edge_mid_3d, 
edge_mid_tang);
-    if (!evtangent_status) {
-       // EvTangent call failed, get 3d point
-       edge_mid_3d = bseg->nc->PointAt(emid);
-    }
-
-    // We need the trim points to be pretty close to the edge point, or
-    // we get distortions in the mesh.
-    fastf_t t1, t2;
-    fastf_t emindist = (bseg->cdt_tol.min_dist < 0.5*bseg->loop_min_dist) ? 
bseg->cdt_tol.min_dist : 0.5 * bseg->loop_min_dist;
-    ON_3dPoint trim1_mid_2d, trim2_mid_2d;
-    trim1_mid_2d = get_trim_midpt(&t1, bseg->trim1, bseg->sbtp1->t, 
bseg->ebtp1->t, edge_mid_3d, emindist, 0);
-    trim2_mid_2d = get_trim_midpt(&t2, bseg->trim2, bseg->sbtp2->t, 
bseg->ebtp2->t, edge_mid_3d, emindist, 0);
-
-    ON_3dPoint tmp1, tmp2;
-    const ON_Surface *s1 = bseg->trim1->SurfaceOf();
-    const ON_Surface *s2 = bseg->trim2->SurfaceOf();
-    ON_3dVector trim1_mid_norm = ON_3dVector::UnsetVector;
-    ON_3dVector trim2_mid_norm = ON_3dVector::UnsetVector;
-
-    if (!surface_EvNormal(s1, trim1_mid_2d.x, trim1_mid_2d.y, tmp1, 
trim1_mid_norm)) {
-       trim1_mid_norm = ON_3dVector::UnsetVector;
-    } else {
-       if (bseg->trim1->Face()->m_bRev) {
-           trim1_mid_norm = trim1_mid_norm  * -1.0;
-       }
-    }
-
-    if (!surface_EvNormal(s2, trim2_mid_2d.x, trim2_mid_2d.y, tmp2, 
trim2_mid_norm)) {
-       trim2_mid_norm = ON_3dVector::UnsetVector;
-    } else {
-       if (bseg->trim2->Face()->m_bRev) {
-           trim2_mid_norm = trim2_mid_norm  * -1.0;
-       }
-    }
-
-    ON_3dPoint *npt = new ON_3dPoint(edge_mid_3d);
-    CDT_Add3DPnt(bseg->s_cdt, npt, -1, -1, -1, bseg->edge->m_edge_index, emid, 
0);
-    bseg->s_cdt->edge_pnts->insert(npt);
-
-
-    BrepTrimPoint *nbtp1 = Add_BrepTrimPoint(bseg->s_cdt, 
bseg->trim1_param_points, npt, NULL, edge_mid_tang, emid, trim1_mid_2d, 
trim1_mid_norm, t1, bseg->trim1->m_trim_index);
-
-    BrepTrimPoint *nbtp2 = Add_BrepTrimPoint(bseg->s_cdt, 
bseg->trim2_param_points, npt, NULL, edge_mid_tang, emid, trim2_mid_2d, 
trim2_mid_norm, t2, bseg->trim2->m_trim_index);
-
-    struct BrepEdgeSegment *bseg1 = NewBrepEdgeSegment(bseg);
-    bseg1->sbtp1 = bseg->sbtp1;
-    bseg1->ebtp1 = nbtp1;
-    bseg1->sbtp2 = bseg->sbtp2;
-    bseg1->ebtp2 = nbtp2;
-    RefineEdgeSegmentMidPt(bseg1, split_dist);
-
-
-    struct BrepEdgeSegment *bseg2 = NewBrepEdgeSegment(bseg);
-    bseg2->sbtp1 = nbtp1;
-    bseg2->ebtp1 = bseg->ebtp1;
-    bseg2->sbtp2 = nbtp2;
-    bseg2->ebtp2 = bseg->ebtp2;
-    RefineEdgeSegmentMidPt(bseg2, split_dist);
-
-    bseg->avg_seg_len = (bseg1->avg_seg_len + bseg2->avg_seg_len) * 0.5;
-
-    return;
-}
-
-double
-refineEdgePoints(
-       struct ON_Brep_CDT_State *s_cdt,
-       ON_BrepEdge *edge,
-       fastf_t split_dist
-       )
-{
-    // Get the trims
-    // TODO - this won't work if we don't have a 1->2 edge to trims 
relationship - in that
-    // case we'll have to split up the edge and find the matching sub-trims 
(possibly splitting
-    // those as well if they don't line up at shared 3D points.)
-    ON_BrepTrim *trim1 = edge->Trim(0);
-    ON_BrepTrim *trim2 = edge->Trim(1);
-
-    std::map<double, BrepTrimPoint *> *trim1_param_points = (std::map<double, 
BrepTrimPoint *> *)trim1->m_trim_user.p;
-    std::map<double, BrepTrimPoint *> *trim2_param_points = (std::map<double, 
BrepTrimPoint *> *)trim2->m_trim_user.p;
-
-    /* If we're out of sync, bail - something is very very wrong */
-    if (!trim1_param_points || !trim2_param_points) {
-       return -1;
-    }
-
-    RefineEdgeSegmentMidPt((*s_cdt->etrees)[edge->m_edge_index], split_dist);
-
-    return (*s_cdt->etrees)[edge->m_edge_index]->avg_seg_len;
-}
-
-// Get min and max surface dimensions for an edge's surface pair
-void
-get_edge_surface_dimensions(double *maxd, double *mind, ON_BrepEdge *e)
-{
-    fastf_t max_dist = 0.0;
-    fastf_t min_dist = DBL_MAX;
-
-    ON_BrepTrim *trim1 = e->Trim(0);
-    ON_BrepTrim *trim2 = e->Trim(1);
-    double sw1, sh1, sw2, sh2;
-    const ON_Surface *s1 = trim1->Face()->SurfaceOf();
-    const ON_Surface *s2 = trim2->Face()->SurfaceOf();
-    if (s1->GetSurfaceSize(&sw1, &sh1) && s2->GetSurfaceSize(&sw2, &sh2)) {
-       // For the maximum, use the diagonal
-       fastf_t md1, md2 = 0.0;
-       md1 = sqrt(sw1 * sw1 + sh1 * sh1);
-       md2 = sqrt(sw2 * sw2 + sh2 * sh2);
-       max_dist = (md1 < md2) ? md1 : md2;
-
-       // For the minimum, use the smaller of the width and height
-       fastf_t mw, mh;
-       mw = (sw1 < sw2) ? sw1 : sw2;
-       mh = (sh1 < sh2) ? sh1 : sh2;
-       min_dist = (mw < mh) ? mw : mh;
-    } else {
-       max_dist = 0.0;
-       min_dist = DBL_MAX;
-    }
-
-    (*maxd) = max_dist;
-    (*mind) = min_dist;
-}
-
-// Get initial distance tolerances from surface min/max dimensions and
-// tolerance settings
-void
-get_edge_surface_tolerances(double *maxd, double *mind, double smax, double 
smin, struct ON_Brep_CDT_State *s_cdt)
-{
-    fastf_t max_dist = smax;
-    fastf_t min_dist = smin;
-
-#if 0    
-    bu_log("max_dist(0): %f\n", max_dist);
-    bu_log("min_dist(0): %f\n", min_dist);
-    bu_log("tol.rel: %f\n", s_cdt->tol.rel);
-    bu_log("tol.rel_lmax: %f\n", s_cdt->tol.rel_lmax);
-    bu_log("tol.rel_lmin: %f\n", s_cdt->tol.rel_lmin);
-    bu_log("tol.relmax: %f\n", s_cdt->tol.relmax);
-    bu_log("tol.relmin: %f\n", s_cdt->tol.relmin);
-    bu_log("absmax: %f\n", s_cdt->absmax);
-    bu_log("absmin: %f\n", s_cdt->absmin);
-    bu_log("smax: %f\n", smax);
-    bu_log("smin: %f\n", smin);
-#endif
-
-    if (s_cdt->tol.rel_lmax > ON_ZERO_TOLERANCE) {
-       max_dist = smax * s_cdt->tol.rel_lmax;
-    }
-    if (s_cdt->tol.rel_lmin > ON_ZERO_TOLERANCE) {
-       min_dist = smin * s_cdt->tol.rel_lmin;
-    }
-
-    if (s_cdt->absmax > ON_ZERO_TOLERANCE && max_dist > s_cdt->absmax) {
-       max_dist = s_cdt->absmax;
-    }
-    if (s_cdt->tol.rel_lmin < ON_ZERO_TOLERANCE && s_cdt->absmin > 
ON_ZERO_TOLERANCE && min_dist > s_cdt->absmin) {
-       min_dist = s_cdt->absmin;
-    }
-
-#if 0
-    bu_log("max_dist(1): %f\n", max_dist);
-    bu_log("min_dist(1): %f\n", min_dist);
-#endif
-
-    // Sanity
-    max_dist = (max_dist < min_dist) ? min_dist : max_dist;
-    min_dist = (min_dist > max_dist) ? max_dist : min_dist;
-
-#if 0
-    bu_log("max_dist(2): %f\n", max_dist);
-    bu_log("min_dist(2): %f\n", min_dist);
-#endif
-
-    (*maxd) = max_dist;
-    (*mind) = min_dist;
-}
-
-void
-Get_Edge_Points(struct ON_Brep_CDT_State *s_cdt)
-{
-    ON_Brep *brep = s_cdt->brep;
-
-    // Process the non-linear edges first - we will need information
-    // from them to handle the linear edges
-    for (int index = 0; index < brep->m_E.Count(); index++) {
-       ON_BrepEdge& edge = brep->m_E[index];
-
-       const ON_Curve* crv = edge.EdgeCurveOf();
-       if (!crv->IsLinear(BN_TOL_DIST)) {
-           fastf_t max_dist, min_dist;
-           get_edge_surface_dimensions(&max_dist, &min_dist, &edge);
-           get_edge_surface_tolerances(&max_dist, &min_dist, max_dist, 
min_dist, s_cdt);
-           (void)getEdgePoints(s_cdt, &edge, max_dist, min_dist);
-       }
-    }
-
-    // TODO For loops with multiple curved edges, check relative sizing - we 
don't
-    // want loops with wildly different segment lengths on the same surface
-    // loop, so refine curved edges that are much larger avg. seg. length
-    // compared to other edges in the loop
-    for (int index = 0; index < brep->m_L.Count(); index++) {
-       ON_BrepLoop &loop = brep->m_L[index];
-       double emin = DBL_MAX;
-       double emax = -DBL_MAX;
-       int ccnt = 0;
-       for (int j = 0; j < loop.TrimCount(); j++) {
-           ON_BrepTrim *t = loop.Trim(j);
-           ON_BrepEdge *e = t->Edge();
-           if (!e) continue;
-           const ON_Curve* crv = e->EdgeCurveOf();
-           if (crv && !crv->IsLinear(BN_TOL_DIST)) {
-               double cavg = (*s_cdt->etrees)[e->m_edge_index]->avg_seg_len;
-               emin = (cavg < emin) ? cavg : emin;
-               emax = (cavg > emax) ? cavg : emax;
-               ccnt++;
-           }
-       }
-       if (!ccnt || emax < 5*emin) continue;
-
-       //bu_log("loop %d (%f, %f)\n", loop.m_loop_index, emin, emax);
-       for (int j = 0; j < loop.TrimCount(); j++) {
-           ON_BrepTrim *t = loop.Trim(j);
-           ON_BrepEdge *e = t->Edge();
-           if (!e) continue;
-
-           const ON_Curve* crv = e->EdgeCurveOf();
-           if (crv && !crv->IsLinear(BN_TOL_DIST)) {
-               double cavg = (*s_cdt->etrees)[e->m_edge_index]->avg_seg_len;
-               if (cavg > 5*emin) {
-                   (void)refineEdgePoints(s_cdt, e, 5*emin);
-               }
-           }
-       }
-       //bu_log("loop %d, face %d refined\n", loop.m_loop_index, 
loop.Face()->m_face_index);
-    }
-
-    // For each linear edge, for both loops associated with its trims
-    // find the smallest calculated average segment length from any
-    // curved edges in the loops.  Use that as a targeted segment
-    // dimension for the linear edge
-    //
-    // TODO - change to using a weighted avg, using the ratio of the
-    // total segment length per edge as the weight - the longer the
-    // edge, the more it's average segment length counts (curved edges only!).
-    for (int index = 0; index < brep->m_E.Count(); index++) {
-       ON_BrepEdge& edge = brep->m_E[index];
-
-       const ON_Curve* crv = edge.EdgeCurveOf();
-       if (crv->IsLinear(BN_TOL_DIST)) {
-           fastf_t max_dist, min_dist;
-           int have_curve = 0;
-           double smallest_curve_avg_seg = DBL_MAX;
-           ON_BrepLoop *l[2];
-           for (int i = 0; i < 2; i++) {
-               ON_BrepTrim& trim = brep->m_T[edge.Trim(i)->m_trim_index];
-               l[i] = trim.Loop();
-           }
-           for (int i = 0; i < 2; i++) {
-               for (int j = 0; j < l[i]->TrimCount(); j++) {
-                   ON_BrepTrim *t = l[i]->Trim(j);
-                   ON_BrepEdge *e = t->Edge();
-                   if (!e) continue;
-                   const ON_Curve* ecrv = e->EdgeCurveOf();
-                   if (!ecrv->IsLinear(BN_TOL_DIST)) {
-                       have_curve = 1;
-                       if (s_cdt->etrees->find(e->m_edge_index) != 
s_cdt->etrees->end()) {
-                           if (smallest_curve_avg_seg > 
(*s_cdt->etrees)[e->m_edge_index]->avg_seg_len) {
-                               smallest_curve_avg_seg = 
(*s_cdt->etrees)[e->m_edge_index]->avg_seg_len;
-                           }
-                       }
-                   }
-               }
-           }
-
-           if (have_curve) {
-
-               // Set max_dist and min_dist from the curve information
-               max_dist = 2*smallest_curve_avg_seg;
-               min_dist = 0.5*smallest_curve_avg_seg;
-
-               //bu_log("curve limits linear edge %d: min %f max %f\n", 
edge.m_edge_index, min_dist, max_dist);
-
-           } else {
-               // No curve edges on this loop - fall back on standard surface 
seeding
-               get_edge_surface_dimensions(&max_dist, &min_dist, &edge);
-               get_edge_surface_tolerances(&max_dist, &min_dist, max_dist, 
min_dist, s_cdt);
-               //bu_log("linear edge %d: min %f max %f\n", edge.m_edge_index, 
min_dist, max_dist);
-           }
-
-           (void)getEdgePoints(s_cdt, &edge, max_dist, min_dist);
-       }
-    }
-
-}
-
-#define BB_PLOT_2D(min, max) {         \
-    fastf_t pt[4][3];                  \
-    VSET(pt[0], max[X], min[Y], 0);    \
-    VSET(pt[1], max[X], max[Y], 0);    \
-    VSET(pt[2], min[X], max[Y], 0);    \
-    VSET(pt[3], min[X], min[Y], 0);    \
-    pdv_3move(plot_file, pt[0]); \
-    pdv_3cont(plot_file, pt[1]); \
-    pdv_3cont(plot_file, pt[2]); \
-    pdv_3cont(plot_file, pt[3]); \
-    pdv_3cont(plot_file, pt[0]); \
-}
-
-#define TREE_LEAF_FACE_3D(valp, a, b, c, d)  \
-    pdv_3move(plot_file, pt[a]); \
-    pdv_3cont(plot_file, pt[b]); \
-    pdv_3cont(plot_file, pt[c]); \
-    pdv_3cont(plot_file, pt[d]); \
-    pdv_3cont(plot_file, pt[a]); \
-
-#define BB_PLOT(min, max) {                 \
-    fastf_t pt[8][3];                       \
-    VSET(pt[0], max[X], min[Y], min[Z]);    \
-    VSET(pt[1], max[X], max[Y], min[Z]);    \
-    VSET(pt[2], max[X], max[Y], max[Z]);    \
-    VSET(pt[3], max[X], min[Y], max[Z]);    \
-    VSET(pt[4], min[X], min[Y], min[Z]);    \
-    VSET(pt[5], min[X], max[Y], min[Z]);    \
-    VSET(pt[6], min[X], max[Y], max[Z]);    \
-    VSET(pt[7], min[X], min[Y], max[Z]);    \
-    TREE_LEAF_FACE_3D(pt, 0, 1, 2, 3);      \
-    TREE_LEAF_FACE_3D(pt, 4, 0, 3, 7);      \
-    TREE_LEAF_FACE_3D(pt, 5, 4, 7, 6);      \
-    TREE_LEAF_FACE_3D(pt, 1, 5, 6, 2);      \
-}
-
-
-bool
-build_poly2tri_polylines(struct ON_Brep_CDT_Face_State *f, p2t::CDT **cdt, int 
init_rtree)
-{
-    // Process through loops, building Poly2Tri polygons for facetization.
-    std::map<p2t::Point *, ON_3dPoint *> *pointmap = f->p2t_to_on3_map;
-    std::map<ON_3dPoint *, std::set<p2t::Point *>> *on3_to_tri = 
f->on3_to_tri_map;
-    std::map<p2t::Point *, ON_3dPoint *> *normalmap = f->p2t_to_on3_norm_map;
-    std::map<ON_3dPoint *, ON_3dPoint *> *nmap= f->on3_to_norm_map;
-    std::vector<p2t::Point*> polyline;
-    ON_BrepFace &face = f->s_cdt->brep->m_F[f->ind];
-    int loop_cnt = face.LoopCount();
-    ON_SimpleArray<BrepTrimPoint> *brep_loop_points = f->face_loop_points;
-    bool outer = true;
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 2) {
-           for (int i = 1; i < num_loop_points; i++) {
-               // map point to last entry to 3d point
-               p2t::Point *p = new p2t::Point((brep_loop_points[li])[i].p2d.x, 
(brep_loop_points[li])[i].p2d.y);
-               polyline.push_back(p);
-               (*f->p2t_trim_ind)[p] = (brep_loop_points[li])[i].trim_ind;
-               (*pointmap)[p] = (brep_loop_points[li])[i].p3d;
-               (*on3_to_tri)[(brep_loop_points[li])[i].p3d].insert(p);
-               (*normalmap)[p] = (brep_loop_points[li])[i].n3d;
-               (*nmap)[(*pointmap)[p]] = (brep_loop_points[li])[i].n3d;
-           }
-
-           if (init_rtree) {
-               for (int i = 1; i < brep_loop_points[li].Count(); i++) {
-                   ON_Line *line = new ON_Line((brep_loop_points[li])[i - 
1].p2d, (brep_loop_points[li])[i].p2d);
-                   ON_BoundingBox bb = line->BoundingBox();
-
-                   bb.m_max.x = bb.m_max.x + ON_ZERO_TOLERANCE;
-                   bb.m_max.y = bb.m_max.y + ON_ZERO_TOLERANCE;
-                   bb.m_max.z = bb.m_max.z + ON_ZERO_TOLERANCE;
-                   bb.m_min.x = bb.m_min.x - ON_ZERO_TOLERANCE;
-                   bb.m_min.y = bb.m_min.y - ON_ZERO_TOLERANCE;
-                   bb.m_min.z = bb.m_min.z - ON_ZERO_TOLERANCE;
-
-                   f->rt_trims->Insert2d(bb.Min(), bb.Max(), line);
-               }
-               {
-                   // TODO - do we need the closing line segment?
-                   ON_Line *line = new 
ON_Line((brep_loop_points[li])[brep_loop_points[li].Count() - 1].p2d, 
(brep_loop_points[li])[0].p2d);
-                   ON_BoundingBox bb = line->BoundingBox();
-
-                   bb.m_max.x = bb.m_max.x + ON_ZERO_TOLERANCE;
-                   bb.m_max.y = bb.m_max.y + ON_ZERO_TOLERANCE;
-                   bb.m_max.z = bb.m_max.z + ON_ZERO_TOLERANCE;
-                   bb.m_min.x = bb.m_min.x - ON_ZERO_TOLERANCE;
-                   bb.m_min.y = bb.m_min.y - ON_ZERO_TOLERANCE;
-                   bb.m_min.z = bb.m_min.z - ON_ZERO_TOLERANCE;
-
-                   f->rt_trims->Insert2d(bb.Min(), bb.Max(), line);
-               }
-
-               for (int i = 1; i < brep_loop_points[li].Count(); i++) {
-                   ON_Line *line = new ON_Line(*(brep_loop_points[li])[i - 
1].p3d, *(brep_loop_points[li])[i].p3d);
-                   ON_BoundingBox bb = line->BoundingBox();
-
-                   bb.m_max.x = bb.m_max.x + ON_ZERO_TOLERANCE;
-                   bb.m_max.y = bb.m_max.y + ON_ZERO_TOLERANCE;
-                   bb.m_max.z = bb.m_max.z + ON_ZERO_TOLERANCE;
-                   bb.m_min.x = bb.m_min.x - ON_ZERO_TOLERANCE;
-                   bb.m_min.y = bb.m_min.y - ON_ZERO_TOLERANCE;
-                   bb.m_min.z = bb.m_min.z - ON_ZERO_TOLERANCE;
-
-                   f->rt_trims_3d->Insert(bb.Min(), bb.Max(), line);
-               }
-               {
-                   // TODO - do we need the closing line segment?
-                   ON_Line *line = new 
ON_Line(*(brep_loop_points[li])[brep_loop_points[li].Count() - 1].p3d, 
*(brep_loop_points[li])[0].p3d);
-                   ON_BoundingBox bb = line->BoundingBox();
-
-                   bb.m_max.x = bb.m_max.x + ON_ZERO_TOLERANCE;
-                   bb.m_max.y = bb.m_max.y + ON_ZERO_TOLERANCE;
-                   bb.m_max.z = bb.m_max.z + ON_ZERO_TOLERANCE;
-                   bb.m_min.x = bb.m_min.x - ON_ZERO_TOLERANCE;
-                   bb.m_min.y = bb.m_min.y - ON_ZERO_TOLERANCE;
-                   bb.m_min.z = bb.m_min.z - ON_ZERO_TOLERANCE;
-
-                   f->rt_trims_3d->Insert(bb.Min(), bb.Max(), line);
-               }
-
-               //plot_rtree_2d(f->rt_trims, "rtree_2d.plot3");
-           }
-           if (outer) {
-               if (f->tris->size() > 0) {
-                   ON_Brep_CDT_Face_Reset(f, init_rtree);
-               }
-               (*cdt) = new p2t::CDT(polyline);
-               outer = false;
-           } else {
-               (*cdt)->AddHole(polyline);
-           }
-           polyline.clear();
-       }
-    }
-    return outer;
-}
-
-void
-Process_Loop_Edges(struct ON_Brep_CDT_Face_State *f, int li)
-{
-    struct ON_Brep_CDT_State *s_cdt = f->s_cdt;
-    ON_SimpleArray<BrepTrimPoint> *points = &(f->face_loop_points[li]);
-    const ON_BrepFace &face = s_cdt->brep->m_F[f->ind];
-    const ON_BrepLoop *loop = face.Loop(li);
-    int trim_count = loop->TrimCount();
-
-    for (int lti = 0; lti < trim_count; lti++) {
-       ON_BrepTrim *trim = loop->Trim(lti);
-
-       /* Provide 2D points for p2d, but we need to be aware that this will
-        * result in (trivially) degenerate 3D faces that we need to filter out
-        * when assembling a mesh */
-       if (trim->m_type == ON_BrepTrim::singular) {
-           BrepTrimPoint btp;
-           const ON_BrepVertex& v1 = face.Brep()->m_V[trim->m_vi[0]];
-           ON_3dPoint *p3d = (*s_cdt->vert_pnts)[v1.m_vertex_index];
-           
(*s_cdt->faces)[face.m_face_index]->strim_pnts->insert(std::make_pair(trim->m_trim_index,
 p3d));
-           ON_3dPoint *n3d = (*s_cdt->vert_avg_norms)[v1.m_vertex_index];
-           if (n3d) {
-               
(*s_cdt->faces)[face.m_face_index]->strim_norms->insert(std::make_pair(trim->m_trim_index,
 n3d));
-           }
-           double delta =  trim->Domain().Length() / 10.0;
-           ON_Interval trim_dom = trim->Domain();
-
-           for (int i = 1; i <= 10; i++) {
-               btp.p3d = p3d;
-               btp.n3d = n3d;
-               btp.p2d = v1.Point();
-               btp.t = trim->Domain().m_t[0] + (i - 1) * delta;
-               btp.p2d = trim->PointAt(btp.t);
-               btp.e = ON_UNSET_VALUE;
-               points->Append(btp);
-           }
-           // skip last point of trim if not last trim
-           if (lti < trim_count - 1)
-               continue;
-
-           const ON_BrepVertex& v2 = face.Brep()->m_V[trim->m_vi[1]];
-           btp.p3d = p3d;
-           btp.n3d = n3d;
-           btp.p2d = v2.Point();
-           btp.t = trim->Domain().m_t[1];
-           btp.p2d = trim->PointAt(btp.t);
-           btp.e = ON_UNSET_VALUE;
-           points->Append(btp);
-
-           continue;
-       }
-
-       if (!trim->m_trim_user.p) {
-           bu_log("Error - uninitialized trim->m_trim_user.p: Trim %d 
(associated with Edge %d)\n", trim->m_trim_index, trim->Edge()->m_edge_index);
-           return;
-       }
-
-       // If we can bound it, assemble the trim segments in order on the
-       // loop array (which will in turn be used to generate the poly2tri
-       // polyline for CDT)
-       ON_3dPoint boxmin, boxmax;
-       if (trim->GetBoundingBox(boxmin, boxmax, false)) {
-           std::map<double, BrepTrimPoint *> *param_points3d = 
(std::map<double, BrepTrimPoint *> *)trim->m_trim_user.p;
-           std::map<double, BrepTrimPoint*>::const_iterator i, ni;
-           for (i = param_points3d->begin(); i != param_points3d->end();) {
-               BrepTrimPoint *btp = (*i).second;
-               ni = ++i;
-               // skip last point of trim if not last trim
-               if (ni == param_points3d->end()) {
-                   if (lti < trim_count - 1) {
-                       continue;
-                   }
-               }
-               points->Append(*btp);
-           }
-       }
-    }
-}
-
-
-/** @} */
-
-// Local Variables:
-// mode: C++
-// tab-width: 8
-// c-basic-offset: 4
-// indent-tabs-mode: t
-// c-file-style: "stroustrup"
-// End:
-// ex: shiftwidth=4 tabstop=8
-

Modified: brlcad/trunk/src/libbrep/cdt_mesh.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_mesh.cpp       2019-09-04 18:42:32 UTC (rev 
73825)
+++ brlcad/trunk/src/libbrep/cdt_mesh.cpp       2019-09-04 19:07:15 UTC (rev 
73826)
@@ -1,13 +1,34 @@
+/*                    C D T _ M E S H . C P P
+ * BRL-CAD
+ *
+ * Copyright (c) 2019 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file cdt_mesh.cpp
+ *
+ * Mesh routines in support of Constrained Delaunay Triangulation of NURBS
+ * B-Rep objects
+ *
+ */
+
 // This evolved from the original trimesh halfedge data structure code:
 
 // Author: Yotam Gingold <yotam (strudel) yotamgingold.com>
 // License: Public Domain.  (I, Yotam Gingold, the author, release this code 
into the public domain.)
 // GitHub: https://github.com/yig/halfedge
-//
-// It ended up rather different, as we are concerned with somewhat different
-// mesh properties for CDT and the halfedge data structure didn't end up being
-// a good fit, but as it's derived from that source the public domain license
-// is maintained for the changes as well.
 
 #include "common.h"
 
@@ -3176,6 +3197,52 @@
     return NULL;
 }
 
+void
+cdt_mesh_t::best_fit_plane_plot(point_t *center, vect_t *norm, const char 
*fname)
+{
+    FILE* plot_file = fopen(fname, "w");
+    int r = int(256*drand48() + 1.0);
+    int g = int(256*drand48() + 1.0);
+    int b = int(256*drand48() + 1.0);
+    pl_color(plot_file, r, g, b);
+
+    vect_t xbase, ybase, tip;
+    vect_t x_1, x_2, y_1, y_2;
+    bn_vec_perp(xbase, *norm);
+    VCROSS(ybase, xbase, *norm);
+    VUNITIZE(xbase);
+    VUNITIZE(ybase);
+    VSCALE(xbase, xbase, 10);
+    VSCALE(ybase, ybase, 10);
+    VADD2(x_1, *center, xbase);
+    VSUB2(x_2, *center, xbase);
+    VADD2(y_1, *center, ybase);
+    VSUB2(y_2, *center, ybase);
+
+    pdv_3move(plot_file, x_1);
+    pdv_3cont(plot_file, x_2);
+    pdv_3move(plot_file, y_1);
+    pdv_3cont(plot_file, y_2);
+
+    pdv_3move(plot_file, x_1);
+    pdv_3cont(plot_file, y_1);
+    pdv_3move(plot_file, x_2);
+    pdv_3cont(plot_file, y_2);
+
+    pdv_3move(plot_file, x_2);
+    pdv_3cont(plot_file, y_1);
+    pdv_3move(plot_file, x_1);
+    pdv_3cont(plot_file, y_2);
+
+    VSCALE(tip, *norm, 5);
+    VADD2(tip, *center, tip);
+    pdv_3move(plot_file, *center);
+    pdv_3cont(plot_file, tip);
+
+    fclose(plot_file);
+}
+
+
 bool
 cdt_mesh_t::best_fit_plane_reproject(cpolygon_t *polygon)
 {

Modified: brlcad/trunk/src/libbrep/cdt_mesh.h
===================================================================
--- brlcad/trunk/src/libbrep/cdt_mesh.h 2019-09-04 18:42:32 UTC (rev 73825)
+++ brlcad/trunk/src/libbrep/cdt_mesh.h 2019-09-04 19:07:15 UTC (rev 73826)
@@ -1,24 +1,36 @@
+/*                      C D T _ M E S H . H
+ * BRL-CAD
+ *
+ * Copyright (c) 2019 United States Government as represented by
+ * the U.S. Army Research Laboratory.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; see the file named COPYING for more
+ * information.
+ */
+/** @file cdt_mesh.h
+ *
+ * Mesh routines in support of Constrained Delaunay Triangulation of NURBS
+ * B-Rep objects
+ *
+ */
+
 // This evolved from the original trimesh halfedge data structure code:
 
 // Author: Yotam Gingold <yotam (strudel) yotamgingold.com>
 // License: Public Domain.  (I, Yotam Gingold, the author, release this code 
into the public domain.)
 // GitHub: https://github.com/yig/halfedge
-//
-// It ended up rather different, as we are concerned with somewhat different
-// mesh properties for CDT and the halfedge data structure didn't end up being
-// a good fit, but as it's derived from that source the public domain license
-// is maintained for the changes as well.
 
 
-// TODO - I've got the wrong conceptual separation here - cpolygon_t needs to 
be concerned
-// ONLY with polygons, not with the cdt_mesh.  Any cdt_mesh using functions 
need to be
-// moved up to the cdt_mesh structure, operating on a cpolygon object using 
the cdt_mesh
-// information, rather than having cpolygon_t operations using information 
from cdt_mesh.
-//
-// That should resolve a lot of the complexities that emerged trying to used 
cpolygon_t
-// both for repair and for the initial triangulation.
-
-
 #ifndef __cdt_mesh_h__
 #define __cdt_mesh_h__
 
@@ -524,6 +536,7 @@
     long grow_loop(cpolygon_t *polygon, double deg, bool stop_on_contained, 
triangle_t &target);
 
     bool best_fit_plane_reproject(cpolygon_t *polygon);
+    void best_fit_plane_plot(point_t *center, vect_t *norm, const char *fname);
 
     long tri_process(cpolygon_t *polygon, std::set<uedge_t> *ne, 
std::set<uedge_t> *se, long *nv, triangle_t &t);
 

Deleted: brlcad/trunk/src/libbrep/cdt_patch.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_patch.cpp      2019-09-04 18:42:32 UTC (rev 
73825)
+++ brlcad/trunk/src/libbrep/cdt_patch.cpp      2019-09-04 19:07:15 UTC (rev 
73826)
@@ -1,1012 +0,0 @@
-/*                 C D T _ P A T C H . C P P
- * BRL-CAD
- *
- * Copyright (c) 2007-2019 United States Government as represented by
- * the U.S. Army Research Laboratory.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this file; see the file named COPYING for more
- * information.
- */
-/** @addtogroup libbrep */
-/** @{ */
-/** @file cdt_patch.cpp
- *
- * Local remeshing of portions of a previously triangulated mesh.
- *
- */
-
-#include "common.h"
-#include "bg/chull.h"
-#include "./cdt.h"
-
-#define CDT_DEBUG_PLOTS 1
-
-#if CDT_DEBUG_PLOTS
-static void
-plot_edge_set_2d(std::vector<std::pair<trimesh::index_t, trimesh::index_t>> 
&es, std::vector<ON_2dPoint *> &pnts_2d, const char *filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    pl_color_buc(plot_file, &c);
-
-    for (size_t i = 0; i < es.size(); i++) {
-       ON_2dPoint *p1 = pnts_2d[es[i].first];
-       ON_2dPoint *p2 = pnts_2d[es[i].second];
-       point_t bnp1, bnp2;
-       VSET(bnp1, p1->x, p1->y, 0);
-       VSET(bnp2, p2->x, p2->y, 0);
-
-       pdv_3move(plot_file, bnp1);
-       pdv_3cont(plot_file, bnp2);
-    }
-
-    fclose(plot_file);
-}
-
-static void
-plot_edge_set(std::vector<std::pair<trimesh::index_t, trimesh::index_t>> &es, 
std::vector<ON_3dPoint *> &pnts_3d, const char *filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    for (size_t i = 0; i < es.size(); i++) {
-       ON_3dPoint *p1 = pnts_3d[es[i].first];
-       ON_3dPoint *p2 = pnts_3d[es[i].second];
-       point_t bnp1, bnp2;
-       VSET(bnp1, p1->x, p1->y, p1->z);
-       VSET(bnp2, p2->x, p2->y, p2->z);
-
-       // Arrowhead
-       vect_t vrev, vperp, varrow;
-       VSUB2(vrev, bnp2, bnp1);
-       VSCALE(vrev, vrev, 0.1);
-       bn_vec_perp(vperp, vrev);
-       VSCALE(vperp, vperp, 0.5);
-       VADD2(varrow, vperp, vrev);
-       VADD2(varrow, varrow, bnp2);
-
-       pdv_3move(plot_file, bnp1);
-       pdv_3cont(plot_file, bnp2);
-       pdv_3cont(plot_file, varrow);
-    }
-
-    fclose(plot_file);
-}
-
-static void
-plot_edge_loop(std::vector<trimesh::index_t> &el, std::vector<ON_3dPoint *> 
&pnts_3d, const char *filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    point_t bnp1, bnp2;
-    ON_3dPoint *p1, *p2;
-    p2 = pnts_3d[el[0]];
-    VSET(bnp2, p2->x, p2->y, p2->z);
-    pdv_3move(plot_file, bnp2);
-
-    for (size_t i = 1; i < el.size(); i++) {
-       p1 = p2;
-       p2 = pnts_3d[el[i]];
-       VSET(bnp1, p1->x, p1->y, p1->z);
-       VSET(bnp2, p2->x, p2->y, p2->z);
-
-       // Arrowhead
-       vect_t vrev, vperp, varrow;
-       VSUB2(vrev, bnp2, bnp1);
-       VSCALE(vrev, vrev, 0.1);
-       bn_vec_perp(vperp, vrev);
-       VSCALE(vperp, vperp, 0.5);
-       VADD2(varrow, vperp, vrev);
-       VADD2(varrow, varrow, bnp2);
-
-       pdv_3cont(plot_file, bnp2);
-
-       pdv_3cont(plot_file, varrow);
-       pdv_3cont(plot_file, bnp2);
-    }
-
-    fclose(plot_file);
-}
-
-static void
-plot_edge_loop_2d(std::vector<p2t::Point *> &el , const char *filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    point_t bnp;
-    VSET(bnp, el[0]->x, el[0]->y, 0);
-    pdv_3move(plot_file, bnp);
-
-    for (size_t i = 1; i < el.size(); i++) {
-       VSET(bnp, el[i]->x, el[i]->y, 0);
-       pdv_3cont(plot_file, bnp);
-    }
-
-    fclose(plot_file);
-}
-
-void
-plot_2d_bg_tri(int *ecfaces, int num_faces, point2d_t *pnts, const char 
*filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    for (int k = 0; k < num_faces; k++) {
-       point_t p1, p2, p3;
-       VSET(p1, pnts[ecfaces[3*k]][X], pnts[ecfaces[3*k]][Y], 0);
-       VSET(p2, pnts[ecfaces[3*k+1]][X], pnts[ecfaces[3*k+1]][Y], 0);
-       VSET(p3, pnts[ecfaces[3*k+2]][X], pnts[ecfaces[3*k+2]][Y], 0);
-
-       pdv_3move(plot_file, p1);
-       pdv_3cont(plot_file, p2);
-       pdv_3move(plot_file, p1);
-       pdv_3cont(plot_file, p3);
-       pdv_3move(plot_file, p2);
-       pdv_3cont(plot_file, p3);
-    }
-    fclose(plot_file);
-}
-
-void
-plot_2d_cdt_tri(p2t::CDT *ncdt, const char *filename)
-{
-    bu_file_delete(filename);
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    std::vector<p2t::Triangle*> ntris = ncdt->GetTriangles();
-    for (size_t i = 0; i < ntris.size(); i++) {
-       point_t pp1, pp2, pp3;
-       p2t::Triangle *t = ntris[i];
-       p2t::Point *p1 = t->GetPoint(0);
-       p2t::Point *p2 = t->GetPoint(1);
-       p2t::Point *p3 = t->GetPoint(2);
-       VSET(pp1, p1->x, p1->y, 0);
-       VSET(pp2, p2->x, p2->y, 0);
-       VSET(pp3, p3->x, p3->y, 0);
-
-       pdv_3move(plot_file, pp1);
-       pdv_3cont(plot_file, pp2);
-       pdv_3move(plot_file, pp1);
-       pdv_3cont(plot_file, pp3);
-       pdv_3move(plot_file, pp2);
-       pdv_3cont(plot_file, pp3);
-
-    }
-    fclose(plot_file);
-}
-
-
-
-static void
-plot_best_fit_plane(point_t *center, vect_t *norm, const char *filename)
-{
-    FILE* plot_file = fopen(filename, "w");
-    int r = int(256*drand48() + 1.0);
-    int g = int(256*drand48() + 1.0);
-    int b = int(256*drand48() + 1.0);
-    pl_color(plot_file, r, g, b);
-
-    vect_t xbase, ybase, tip;
-    vect_t x_1, x_2, y_1, y_2;
-    bn_vec_perp(xbase, *norm);
-    VCROSS(ybase, xbase, *norm);
-    VUNITIZE(xbase);
-    VUNITIZE(ybase);
-    VSCALE(xbase, xbase, 10);
-    VSCALE(ybase, ybase, 10);
-    VADD2(x_1, *center, xbase);
-    VSUB2(x_2, *center, xbase);
-    VADD2(y_1, *center, ybase);
-    VSUB2(y_2, *center, ybase);
-
-    pdv_3move(plot_file, x_1);
-    pdv_3cont(plot_file, x_2);
-    pdv_3move(plot_file, y_1);
-    pdv_3cont(plot_file, y_2);
-
-    pdv_3move(plot_file, x_1);
-    pdv_3cont(plot_file, y_1);
-    pdv_3move(plot_file, x_2);
-    pdv_3cont(plot_file, y_2);
-
-    pdv_3move(plot_file, x_2);
-    pdv_3cont(plot_file, y_1);
-    pdv_3move(plot_file, x_1);
-    pdv_3cont(plot_file, y_2);
-
-    VSCALE(tip, *norm, 5);
-    VADD2(tip, *center, tip);
-    pdv_3move(plot_file, *center);
-    pdv_3cont(plot_file, tip);
-
-    fclose(plot_file);
-
-}
-
-static void
-plot_trimesh_tris_3d_each_tri(std::set<trimesh::index_t> *faces, 
std::vector<trimesh::triangle_t> &farray, std::map<p2t::Point *, ON_3dPoint *> 
*pointmap, const char *filename)
-{
-    std::set<trimesh::index_t>::iterator f_it;
-    struct bu_vls fname = BU_VLS_INIT_ZERO;
-    int cnt = 0;
-    for (f_it = faces->begin(); f_it != faces->end(); f_it++) {
-       bu_vls_sprintf(&fname, "%s-3d-%d.plot3", filename, cnt);
-       FILE* plot_file = fopen(bu_vls_cstr(&fname), "w");
-       struct bu_color c = BU_COLOR_INIT_ZERO;
-       bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-       p2t::Triangle *t = farray[*f_it].t;
-       plot_tri_3d(t, pointmap, &c, plot_file);
-       fclose(plot_file);
-       bu_vls_sprintf(&fname, "%s-2d-%d.plot3", filename, cnt);
-       FILE* plot_file_2 = fopen(bu_vls_cstr(&fname), "w");
-       plot_tri_2d(t, &c, plot_file_2);
-       fclose(plot_file_2);
-       cnt++;
-    }
-    bu_vls_free(&fname);
-}
-
-static void
-plot_tri_2d_file(p2t::Triangle *t, const char *filename)
-{
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    plot_tri_2d(t, &c, plot_file);
-    fclose(plot_file);
-}
-
-static void
-plot_tri_3d_file(p2t::Triangle *t, std::map<p2t::Point *, ON_3dPoint *> 
*pointmap, const char *filename)
-{
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    plot_tri_3d(t, pointmap, &c, plot_file);
-    fclose(plot_file);
-}
-
-static void
-plot_all_trimesh_tris_3d(std::vector<trimesh::triangle_t> &farray, 
std::map<p2t::Point *, ON_3dPoint *> *pointmap, const char *filename)
-{
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    for (size_t i = 0; i < farray.size(); i++) {
-       p2t::Triangle *t = farray[i].t;
-       plot_tri_3d(t, pointmap, &c, plot_file);
-    }
-    fclose(plot_file);
-}
-
-static void
-plot_trimesh_tris_3d(std::set<trimesh::index_t> *faces, 
std::vector<trimesh::triangle_t> &farray, std::map<p2t::Point *, ON_3dPoint *> 
*pointmap, const char *filename)
-{
-    std::set<trimesh::index_t>::iterator f_it;
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    for (f_it = faces->begin(); f_it != faces->end(); f_it++) {
-       p2t::Triangle *t = farray[*f_it].t;
-       plot_tri_3d(t, pointmap, &c, plot_file);
-    }
-    fclose(plot_file);
-}
-
-static void
-plot_all_trimesh_tris_2d(std::vector<trimesh::triangle_t> &farray, 
std::vector<ON_2dPoint *> &pnts_2d, const char *filename)
-{
-    std::set<trimesh::index_t>::iterator f_it;
-    FILE* plot = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-
-    for (size_t i = 0; i < farray.size(); i++) {
-       point_t pc;
-       point_t pc_orig;
-       point_t center = VINIT_ZERO;
-
-       for (size_t j = 0; j < 3; j++) {
-           ON_2dPoint *pt = pnts_2d[farray[i].v[j]];
-           center[X] += pt->x;
-           center[Y] += pt->y;
-       }
-       center[X] = center[X]/3.0;
-       center[Y] = center[Y]/3.0;
-       center[Z] = 0;
-
-       pl_color_buc(plot, &c);
-       for (size_t j = 0; j < 3; j++) {
-           ON_2dPoint *pt = pnts_2d[farray[i].v[j]];
-           VSET(pc, pt->x, pt->y, 0);
-           if (j == 0) {
-               VSET(pc_orig, pt->x, pt->y, 0);
-               pdv_3move(plot, pc);
-           }
-           pdv_3cont(plot, pc);
-       }
-       pdv_3cont(plot, pc_orig);
-
-       /* fill in the "interior" using red */
-       pl_color(plot, 255,0,0);
-       for (size_t j = 0; j < 3; j++) {
-           ON_2dPoint *pt = pnts_2d[farray[i].v[j]];
-           VSET(pc, pt->x, pt->y, 0);
-           pdv_3move(plot, pc);
-           pdv_3cont(plot, center);
-       }
-    }
-
-    fclose(plot);
-}
-
-#if 0
-static void
-plot_all_trimesh_tris_2d_each_tri(std::vector<trimesh::triangle_t> &farray, 
std::vector<ON_2dPoint *> &pnts_2d, const char *filename)
-{
-    struct bu_vls fname = BU_VLS_INIT_ZERO;
-    for (size_t i = 0; i < farray.size(); i++) {
-       bu_vls_sprintf(&fname, "%s-2d-%zd.plot3", filename, i);
-       FILE* plot = fopen(bu_vls_cstr(&fname), "w");
-       struct bu_color c = BU_COLOR_INIT_ZERO;
-       bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-       point_t pc;
-       point_t pc_orig;
-       for (size_t j = 0; j < 3; j++) {
-           ON_2dPoint *pt = pnts_2d[farray[i].v[j]];
-           VSET(pc, pt->x, pt->y, 0);
-           if (j == 0) {
-               VSET(pc_orig, pt->x, pt->y, 0);
-               pdv_3move(plot, pc);
-           }
-           pdv_3cont(plot, pc);
-       }
-       pdv_3cont(plot, pc_orig);
-       fclose(plot);
-    }
-}
-#endif
-
-static void
-plot_trimesh_tris_2d(std::set<trimesh::index_t> *faces, 
std::vector<trimesh::triangle_t> &farray, const char *filename)
-{
-    std::set<trimesh::index_t>::iterator f_it;
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    for (f_it = faces->begin(); f_it != faces->end(); f_it++) {
-       p2t::Triangle *t = farray[*f_it].t;
-       plot_tri_2d(t, &c, plot_file);
-    }
-    fclose(plot_file);
-}
-
-static void
-plot_trimesh(std::vector<trimesh::triangle_t> &farray, std::map<p2t::Point *, 
ON_3dPoint *> *pointmap, const char *filename)
-{
-    std::set<trimesh::index_t>::iterator f_it;
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    for (size_t i = 0; i < farray.size(); i++) {
-       p2t::Triangle *t = farray[i].t;
-       plot_tri_3d(t, pointmap, &c, plot_file);
-    }
-    fclose(plot_file);
-}
-
-static void
-plot_3d_cdt_tri(std::set<p2t::Triangle *> *faces, std::map<p2t::Point *, 
ON_3dPoint *> *pointmap, const char *filename)
-{
-    std::set<p2t::Triangle *>::iterator f_it;
-    FILE* plot_file = fopen(filename, "w");
-    struct bu_color c = BU_COLOR_INIT_ZERO;
-    bu_color_rand(&c, BU_COLOR_RANDOM_LIGHTENED);
-    for (f_it = faces->begin(); f_it != faces->end(); f_it++) {
-       p2t::Triangle *t = *f_it;
-       plot_tri_3d(t, pointmap, &c, plot_file);
-    }
-    fclose(plot_file);
-}
-#endif
-
-
-void
-best_fit_plane(point_t *orig, vect_t *norm, struct trimesh_info *tm, 
std::set<trimesh::index_t> *remesh_triangles,
-    struct ON_Brep_CDT_Face_State *f)
-{
-    // Find the best fit plane for the Brep normals of the vertices of the 
triangles involved with
-    // the remeshing
-    std::map<p2t::Point *, ON_3dPoint *> *pointmap = f->p2t_to_on3_map;
-    std::set<ON_3dPoint *> active_3d_pnts;
-    ON_3dVector avgtnorm(0.0,0.0,0.0);
-    std::set<trimesh::index_t>::iterator f_it;
-    for (f_it = remesh_triangles->begin(); f_it != remesh_triangles->end(); 
f_it++) {
-       p2t::Triangle *t = tm->triangles[*f_it].t;
-       ON_3dVector ltdir = p2tTri_Brep_Normal(f, t);
-       avgtnorm += ltdir;
-       for (size_t j = 0; j < 3; j++) {
-           active_3d_pnts.insert((*pointmap)[t->GetPoint(j)]);
-       }
-    }
-    avgtnorm = avgtnorm * 1.0/(double)remesh_triangles->size();
-
-    point_t pcenter;
-    vect_t pnorm;
-    {
-       point_t *pnts = (point_t *)bu_calloc(active_3d_pnts.size()+1, 
sizeof(point_t), "fitting points");
-       int pnts_ind = 0;
-       std::set<ON_3dPoint *>::iterator a_it;
-       for (a_it = active_3d_pnts.begin(); a_it != active_3d_pnts.end(); 
a_it++) {
-           ON_3dPoint *p = *a_it;
-           pnts[pnts_ind][X] = p->x;
-           pnts[pnts_ind][Y] = p->y;
-           pnts[pnts_ind][Z] = p->z;
-           pnts_ind++;
-       }
-       if (bn_fit_plane(&pcenter, &pnorm, pnts_ind, pnts)) {
-           bu_log("Failed to get best fit plane!\n");
-       }
-       bu_free(pnts, "fitting points");
-
-       ON_3dVector on_norm(pnorm[X], pnorm[Y], pnorm[Z]);
-       if (ON_DotProduct(on_norm, avgtnorm) < 0) {
-           VSCALE(pnorm, pnorm, -1);
-       }
-    }
-
-    VMOVE(*orig, pcenter);
-    VMOVE(*norm, pnorm);
-}
-
-
-static int
-remove_butterfly_vertices(std::vector<trimesh::triangle_t> &triangles, size_t 
pnt_size, std::set<trimesh::index_t> *remesh_triangles, trimesh::index_t 
seed_id, std::map<p2t::Point *, ON_3dPoint *> *pointmap, std::vector<ON_2dPoint 
*> &pnts_2d, struct ON_Brep_CDT_Face_State *f)
-{
-    int butterfly_verts = 1;
-    int pass = 1;
-
-    while (butterfly_verts) {
-
-       std::set<trimesh::index_t> culls;
-       std::vector<trimesh::triangle_t> submesh_triangles;
-       std::map<trimesh::index_t, trimesh::index_t> n2o;
-       std::set<trimesh::index_t>::iterator tm_it;
-       for (tm_it = remesh_triangles->begin(); tm_it != 
remesh_triangles->end(); tm_it++) {
-           trimesh::triangle_t tmt = triangles[*tm_it];
-           submesh_triangles.push_back(tmt);
-           n2o[submesh_triangles.size()-1] = *tm_it;
-       }
-       bu_log("initial submesh triangle cnt: %zd\n", submesh_triangles.size());
-
-       trimesh::trimesh_t smesh;
-       std::vector<trimesh::edge_t> sedges;
-       trimesh::unordered_edges_from_triangles(submesh_triangles.size(), 
&submesh_triangles[0], sedges);
-
-       smesh.build(pnt_size, submesh_triangles.size(), &submesh_triangles[0], 
sedges.size(), &sedges[0]);
-
-       bu_log("butterfly vertex cnt: %zd\n", 
smesh.m_butterfly_vertices.size());
-       if (smesh.m_butterfly_vertices.size()) {
-           bu_log("butterfly verts!\n");
-           std::set<trimesh::index_t>::iterator v_it;
-           for (v_it = smesh.m_butterfly_vertices.begin(); v_it != 
smesh.m_butterfly_vertices.end(); v_it++) {
-               bu_log("v: %f %f 0\n", pnts_2d[*v_it]->x, pnts_2d[*v_it]->y);
-           }
-       } else {
-           return 0;
-       }
-
-       // For each butterfly vertex, pull the set of associated faces.
-       // For each triangle, if not the seed triangle, yank it.
-       std::set<trimesh::index_t>::iterator bf_it;
-       for (bf_it = smesh.m_butterfly_vertices.begin(); bf_it != 
smesh.m_butterfly_vertices.end(); bf_it++) {
-           std::vector<trimesh::index_t> faces = 
smesh.vertex_face_neighbors(*bf_it);
-           bu_log("bf faces cnt: %zd\n", faces.size());
-           for (size_t i = 0; i < faces.size(); i++) {
-               if (n2o[faces[i]] == seed_id) continue;
-
-               // Get the trimesh index from the original mesh, not the 
working submesh
-               culls.insert(n2o[faces[i]]);
-               bu_log("cull %ld -> %ld\n", faces[i], n2o[faces[i]]);
-           }
-       }
-
-       // Thin down the remesh triangle set based on the edge analysis
-       std::set<trimesh::index_t>::iterator c_it;
-       for (c_it = culls.begin(); c_it != culls.end(); c_it++) {
-           remesh_triangles->erase(*c_it);
-           bu_log("culling %ld\n", *c_it);
-       }
-
-       // If we didn't have to pull anything, we should be done (may still 
have to deal with holes,
-       // but that involves a generalization of boundary_loop in trimesh...)
-       if (!culls.size()) {
-           butterfly_verts = 0;
-       }
-
-#if CDT_DEBUG_PLOTS
-       struct bu_vls pname = BU_VLS_INIT_ZERO;
-       bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-04-pass_%d_butterfly_removal_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, pass);
-       plot_trimesh_tris_3d(remesh_triangles, triangles, pointmap, 
bu_vls_cstr(&pname));
-       bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-04-pass_%d_butterfly_removal_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, pass);
-       plot_trimesh_tris_2d(remesh_triangles, triangles, bu_vls_cstr(&pname));
-       // TODO - need to see 2D projection mesh as well, since that's actually 
the one poly2tri needs
-       // to work on
-#endif
-
-    }
-
-    return 0;
-}
-
-size_t
-collect_neighbor_triangles(std::set<trimesh::index_t> *remesh_triangles, 
double deg, struct ON_Brep_CDT_Face_State *f, struct trimesh_info *tm, 
p2t::Triangle *seed_tri)
-{
-    double angle = deg*ON_PI/180.0;
-    
-    std::set<trimesh::index_t> visited_triangles;
-
-    remesh_triangles->clear();
-
-    trimesh::index_t seed_id = tm->t2ind[seed_tri];
-    ON_3dVector tdir = p2tTri_Brep_Normal(f, seed_tri);
-    tdir.Unitize();
-
-    // Walk out along the mesh, adding triangles whose triangle normal is < deg
-    // degrees away from that of the original triangle.  These form the initial
-    // candidate set of remeshing triangles, although they are not yet the
-    // final set.
-    std::queue<trimesh::index_t> q1, q2;
-    std::queue<trimesh::index_t> *tq, *nq;
-    tq = &q1;
-    nq = &q2;
-    q1.push(seed_id);
-    while (!tq->empty()) {
-       trimesh::index_t t_he = tq->front();
-       tq->pop();
-       p2t::Triangle *ct = tm->triangles[t_he].t;
-       // Check normal
-       ON_3dVector ctdir = p2tTri_Brep_Normal(f, ct);
-       ctdir.Unitize();
-
-       double dprd = ON_DotProduct(ctdir, tdir);
-       double dang = (NEAR_EQUAL(dprd, 1.0, ON_ZERO_TOLERANCE)) ? 0 : 
acos(dprd); 
-
-       if (dang > angle) {
-           bu_log("reject: %f > %f\n", dang, angle);
-           continue;
-       } else {
-           (*remesh_triangles).insert(t_he);
-       }
-
-       // Queue up the connected faces we don't already have in the set
-       std::vector<trimesh::index_t> faces = tm->mesh.face_neighbors(t_he);
-       for (size_t j = 0; j < faces.size(); j++) {
-           if (visited_triangles.find(faces[j]) == visited_triangles.end()) {
-               // We haven't seen this one yet
-               nq->push(faces[j]);
-               visited_triangles.insert(faces[j]);
-           }
-       }
-
-       if (tq->empty()) {
-           std::queue<trimesh::index_t> *tmpq = tq;
-           tq = nq;
-           nq = tmpq;
-       }
-    }
-
-    return remesh_triangles->size();
-}
-
-int
-Remesh_Near_Tri(struct ON_Brep_CDT_Face_State *f, p2t::Triangle *seed_tri, 
std::set<p2t::Triangle *> *wq)
-{
-#if CDT_DEBUG_PLOTS
-    struct bu_vls pname = BU_VLS_INIT_ZERO;
-#endif
-
-    struct trimesh_info *tm = CDT_Face_Build_Halfedge(f->tris);
-
-    std::map<p2t::Point *, ON_3dPoint *> *pointmap = f->p2t_to_on3_map;
-    std::map<p2t::Point *, ON_3dPoint *> *normalmap = f->p2t_to_on3_norm_map;
-    std::set<trimesh::index_t> remesh_triangles;
-    std::set<trimesh::index_t>::iterator f_it;
-    trimesh::index_t seed_id = tm->t2ind[seed_tri];
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-00_initial_tmesh_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_trimesh(tm->triangles, pointmap, bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-00_initial_tmesh_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_trimesh_2d(tm->triangles, bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-00_initial_seed_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_tri_3d_file(seed_tri, pointmap, bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-00_initial_seed_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_tri_2d_file(seed_tri, bu_vls_cstr(&pname));
-#endif
-
-    double deg = 10;
-    size_t ntricnt = collect_neighbor_triangles(&remesh_triangles, deg, f, tm, 
seed_tri);
-    int nit_cnt = 0;
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-01_neighbors_3d_%d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, nit_cnt);
-    plot_trimesh_tris_3d(&remesh_triangles, tm->triangles, pointmap, 
bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-01_neighbors_2d_%d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, nit_cnt);
-    plot_trimesh_tris_2d(&remesh_triangles, tm->triangles, 
bu_vls_cstr(&pname));
-    while (ntricnt < 10 && deg < 45) {
-       bu_log("too few triangles: %zd\n", ntricnt);
-       deg = deg + 5;
-       ntricnt = collect_neighbor_triangles(&remesh_triangles, deg, f, tm, 
seed_tri);
-    }
-
-    if (remesh_triangles.size() < 3) {
-       bu_log("Could not get enough triangles, even at degree %f: %zd\n", deg, 
remesh_triangles.size());
-#if CDT_DEBUG_PLOTS
-       bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-01_neighbors_small_cnt", 
bu_vls_cstr(&f->face_root), seed_id);
-       plot_trimesh_tris_3d_each_tri(&remesh_triangles, tm->triangles, 
pointmap, bu_vls_cstr(&pname));
-#endif
-       bu_exit(1, "fail");
-    }
-
-    bu_log("remesh triangle stage 1 cnt: %zd\n", remesh_triangles.size());
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-02_working_neighbors_2d_%d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, nit_cnt);
-    plot_trimesh_tris_2d(&remesh_triangles, tm->triangles, 
bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-02_working_neighbors_3d_%d.plot3", 
bu_vls_cstr(&f->face_root), seed_id, nit_cnt);
-    plot_trimesh_tris_3d(&remesh_triangles, tm->triangles, pointmap, 
bu_vls_cstr(&pname));
-#endif
-
-    // Find the best fit plane for the vertices of the triangles involved with
-    // the remeshing
-    point_t pcenter;
-    vect_t pnorm;
-    best_fit_plane(&pcenter, &pnorm, tm, &remesh_triangles, f);
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-03-best_fit_plane.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_best_fit_plane(&pcenter, &pnorm, bu_vls_cstr(&pname));
-#endif
-
-    // Project all 3D points in the subset into the best fit plane. We need XY 
coordinates
-    // for poly2Tri.
-    std::set<ON_3dPoint *> sub_3d;
-    std::map<ON_3dPoint *, ON_3dPoint *> sub_3d_norm;
-    std::set<trimesh::index_t>::iterator tm_it;
-    for (tm_it = remesh_triangles.begin(); tm_it != remesh_triangles.end(); 
tm_it++) {
-       p2t::Triangle *t = tm->triangles[*tm_it].t;
-       for (size_t j = 0; j < 3; j++) {
-           sub_3d.insert((*pointmap)[t->GetPoint(j)]);
-           sub_3d_norm[(*pointmap)[t->GetPoint(j)]] = 
(*normalmap)[t->GetPoint(j)];
-       }
-    }
-    std::vector<ON_3dPoint *> pnts_3d(sub_3d.begin(), sub_3d.end());
-    std::vector<ON_2dPoint *> pnts_2d;
-    std::map<ON_3dPoint *, size_t> pnts_3d_ind;
-
-    ON_Plane 
bfplane(ON_3dPoint(pcenter[X],pcenter[Y],pcenter[Z]),ON_3dVector(pnorm[X],pnorm[Y],pnorm[Z]));
-    ON_Xform to_plane;
-    to_plane.PlanarProjection(bfplane);
-    std::map<ON_2dPoint *, ON_3dPoint *> on2_3;
-    std::map<ON_2dPoint *, ON_3dPoint *> on2_3n;
-    for (size_t i = 0; i < pnts_3d.size(); i++) {
-       pnts_3d_ind[pnts_3d[i]] = i;
-       ON_3dPoint op3d = (*pnts_3d[i]);
-       op3d.Transform(to_plane);
-       ON_2dPoint *n2d = new ON_2dPoint(op3d.x, op3d.y);
-       pnts_2d.push_back(n2d);
-       on2_3[n2d] = pnts_3d[i];
-       on2_3n[n2d] = sub_3d_norm[pnts_3d[i]];
-    }
-
-    // Translate the poly2tri triangle into trimesh
-    //
-    // TODO - we actually probably don't want a full trimesh here.  What we 
need
-    // for p2t is the polygon outer loop and the interior points - "butterfly"
-    // vertices are an issue only if they indicate a hole in the mesh from the
-    // perspective of the outer loop.  Those cases are apparenty hard to 
detect,
-    // so what we might try instead is to build up the projected mesh at the
-    // same time as we are assigning faces from the original mesh, using the 
initial
-    // brep normal avg from the seed face as the plane for projecting, and 
"walk out"
-    // the outer loop at the same time.  Track edge uses and check outer point 
edge
-    // use counts in the projection, and evaluate each new candidate triangle 
to see
-    // if it will produce a problem in the outer loop.  That will mean 
refactoring
-    // this whole thing to build a candidate projection at the same time as the
-    // initial set is built.
-    std::set<std::set<trimesh::index_t>> tri_pntsets;
-    std::map<trimesh::index_t, trimesh::index_t> sp2o;
-    std::vector<trimesh::triangle_t> submesh_triangles_prelim;
-    std::set<trimesh::index_t> smtri;
-    for (tm_it = remesh_triangles.begin(); tm_it != remesh_triangles.end(); 
tm_it++) {
-       p2t::Triangle *t = tm->triangles[*tm_it].t;
-       trimesh::triangle_t tmt;
-       std::set<trimesh::index_t> pset;
-       for (size_t j = 0; j < 3; j++) {
-           tmt.v[j] = pnts_3d_ind[(*pointmap)[t->GetPoint(j)]];
-           pset.insert(tmt.v[j]);
-       }
-       tmt.t = t;
-       if (tmt.v[0] != tmt.v[1] && tmt.v[0] != tmt.v[2] && tmt.v[1] != 
tmt.v[2]) {
-           if (tri_pntsets.find(pset) == tri_pntsets.end()) {
-               submesh_triangles_prelim.push_back(tmt);
-               sp2o[submesh_triangles_prelim.size()-1] = *tm_it;
-               smtri.insert(submesh_triangles_prelim.size()-1);
-               tri_pntsets.insert(pset);
-           } else {
-               bu_log("Skipping duplicate: %ld -> %ld -> %ld\n", tmt.v[0], 
tmt.v[1], tmt.v[2]);
-           }
-       } else {
-           bu_log("Skipping: %ld -> %ld -> %ld\n", tmt.v[0], tmt.v[1], 
tmt.v[2]);
-       }
-
-    }
-
-    bu_log("submesh triangle prelim cnt: %zd\n", 
submesh_triangles_prelim.size());
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-10_submesh_triangles-pre_butterfly_tmesh_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_all_trimesh_tris_3d(submesh_triangles_prelim, pointmap, 
bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-10_submesh_triangles-pre_butterfly_tmesh_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_all_trimesh_tris_2d(submesh_triangles_prelim, pnts_2d, 
bu_vls_cstr(&pname));
-#endif
-
-    // The above selection isn't guaranteed to produce something poly2tri can
-    // handle - do a filtering pass to deactivate triangles causing butterfly
-    // vertices in the mesh.
-    // TODO - any triangles removed here also need to have
-    // their corresponding triangle in the remesh set yanked, since we'll no 
longer
-    // be handling it here...
-    remove_butterfly_vertices(submesh_triangles_prelim, pnts_2d.size(), 
&smtri, seed_id, pointmap, pnts_2d, f);
-
-    std::vector<trimesh::triangle_t> submesh_triangles;
-    std::map<trimesh::index_t, trimesh::index_t> s2sp;
-    for (tm_it = smtri.begin(); tm_it != smtri.end(); tm_it++) {
-       trimesh::triangle_t tmt = submesh_triangles_prelim[*tm_it];
-       submesh_triangles.push_back(tmt);
-       s2sp[submesh_triangles.size()-1] = *tm_it;
-    }
-    bu_log("submesh triangle cnt: %zd\n", submesh_triangles.size());
-
-    std::vector<trimesh::edge_t> sedges;
-    trimesh::trimesh_t smesh;
-    trimesh::unordered_edges_from_triangles(submesh_triangles.size(), 
&submesh_triangles[0], sedges);
-    smesh.build(pnts_2d.size(), submesh_triangles.size(), 
&submesh_triangles[0], sedges.size(), &sedges[0]);
-
-#if CDT_DEBUG_PLOTS
-    // TODO - need to plot the projection, not the p2t triangles... this is 
wrong
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-10_submesh_triangles_tmesh_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_all_trimesh_tris_3d(submesh_triangles, pointmap, bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, 
"%sremesh_tri-seed_%ld-10_submesh_triangles_tmesh_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_all_trimesh_tris_2d(submesh_triangles, pnts_2d, bu_vls_cstr(&pname));
-#if 0
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-00_submesh", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_all_trimesh_tris_2d_each_tri(submesh_triangles, pnts_2d, 
bu_vls_cstr(&pname));
-#endif
-#endif
-
-    // Build the new outer boundary
-    std::vector<std::pair<trimesh::index_t, trimesh::index_t>> bedges = 
smesh.boundary_edges();
-    bu_log("boundary edge segment cnt: %zd\n", bedges.size());
-
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-05_outer_edge_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_edge_set_2d(bedges, pnts_2d, bu_vls_cstr(&pname));
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-05_outer_edge_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_edge_set(bedges, pnts_3d, bu_vls_cstr(&pname));
-#endif
-
-    // Given the set of unordered boundary edge segments, construct the outer 
loop
-    // TODO - triangle selection doesn't guarantee no-hole mesh sets - need to 
handle
-    std::vector<trimesh::index_t> sloop = smesh.boundary_loop();
-
-    if (!sloop.size()) {
-       bu_log("Error - failed to generate boundary loop!\n");
-       bu_exit(1, "bail");
-       return -1;
-    }
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-06_outer_loop_3d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_edge_loop(sloop, pnts_3d, bu_vls_cstr(&pname));
-#endif
-
-    // Perform the new triangulation
-    std::set<ON_2dPoint *> handled;
-    std::set<ON_2dPoint *>::iterator u_it;
-    std::vector<p2t::Point *> polyline;
-    p2t::Point *fp = NULL;
-    for (size_t i = 0; i < sloop.size(); i++) {
-       ON_2dPoint *onp2d = pnts_2d[sloop[i]];
-       if (!onp2d) {
-           bu_log("missing onp2d!\n");
-       }
-       p2t::Point *np = new p2t::Point(onp2d->x, onp2d->y);
-       if (!fp) fp = np;
-       if (on2_3.find(onp2d) == on2_3.end()) {
-           bu_log("missing onp2d to 3D mapping!\n");
-       }
-       (*pointmap)[np] = on2_3[onp2d];
-       //bu_log("polyline %f %f -> %f %f %f\n", np->x, np->y, 
(*pointmap)[np]->x, (*pointmap)[np]->y, (*pointmap)[np]->z);
-       (*normalmap)[np] = on2_3n[onp2d];
-       polyline.push_back(np);
-       handled.insert(onp2d);
-    }
-
-    if (!polyline.size()) {
-       bu_log("Error - failed to generate polyline!\n");
-       return -1;
-    }
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-07_polyline_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_edge_loop_2d(polyline, bu_vls_cstr(&pname));
-#endif
-
-    p2t::CDT *ncdt = new p2t::CDT(polyline);
-
-    for (size_t i = 0; i < pnts_2d.size(); i++) {
-       ON_2dPoint *onp2d = pnts_2d[i];
-       if (!onp2d) {
-           bu_log("missing onp2d!\n");
-       }
-       if (handled.find(onp2d) != handled.end()) continue;
-       p2t::Point *np = new p2t::Point(onp2d->x, onp2d->y);
-       if (on2_3.find(onp2d) == on2_3.end()) {
-           bu_log("missing onp2d to 3D mapping!\n");
-       }
-       (*pointmap)[np] = on2_3[onp2d];
-       //bu_log("AddPoint %f %f -> %f %f %f\n", np->x, np->y, 
(*pointmap)[np]->x, (*pointmap)[np]->y, (*pointmap)[np]->z);
-       (*normalmap)[np] = on2_3n[onp2d];
-       ncdt->AddPoint(np);
-    }
-    ncdt->Triangulate(true, -1);
-
-    // Validate that all points have a corresponding 3D point
-    std::vector<p2t::Triangle*> fntris = ncdt->GetTriangles();
-    for (size_t i = 0; i < fntris.size(); i++) {
-       p2t::Triangle *t = fntris[i];
-       for (size_t j = 0; j < 3; j++) {
-           p2t::Point *tp = t->GetPoint(j);
-           if (f->p2t_to_on3_map->find(tp) == f->p2t_to_on3_map->end()) {
-               bu_log("Error - triangle created with invalid 3D mapping!\n");
-           } else {
-               //bu_log("TPnt(%zd,%zd) %f %f -> %f %f %f\n", i,j, tp->x, 
tp->y, (*pointmap)[tp]->x, (*pointmap)[tp]->y, (*pointmap)[tp]->z);
-           }
-       }
-    }
-
-#if CDT_DEBUG_PLOTS
-    bu_vls_sprintf(&pname, "%sremesh_tri-seed_%ld-08_poly2tri_2d.plot3", 
bu_vls_cstr(&f->face_root), seed_id);
-    plot_2d_cdt_tri(ncdt, bu_vls_cstr(&pname));
-#endif
-
-    // assemble the new p2t Triangle set using
-    // the mappings, and check the new 3D mesh thus created for issues.  If it
-    // is clean, replace the original subset of the parent face with the new
-    // triangle set, else fail.
-
-    std::set<p2t::Triangle*> new_faces;
-    std::vector<p2t::Triangle*> ftris = ncdt->GetTriangles();
-    for (size_t i = 0; i < ftris.size(); i++) {
-       p2t::Triangle *t = ftris[i];
-       p2t::Point *p2_1 = t->GetPoint(0);
-       p2t::Point *p2_2 = t->GetPoint(1);
-       p2t::Point *p2_3 = t->GetPoint(2);
-       for (size_t j = 0; j < 3; j++) {
-           p2t::Point *tp = t->GetPoint(j);
-           if (pointmap->find(tp) == pointmap->end()) {
-               bu_log("Error - triangle created with invalid 3D mapping!\n");
-           } else {
-               //bu_log("TPnt2(%zd,%zd) %f %f -> %f %f %f\n", i,j, tp->x, 
tp->y, (*pointmap)[tp]->x, (*pointmap)[tp]->y, (*pointmap)[tp]->z);
-           }
-       }
-
-       //bu_log("TPnt1 %f %f -> %f %f %f\n", p2_1->x, p2_1->y, 
(*pointmap)[p2_1]->x, (*pointmap)[p2_1]->y, (*pointmap)[p2_1]->z);
-       //bu_log("TPnt2 %f %f -> %f %f %f\n", p2_2->x, p2_2->y, 
(*pointmap)[p2_2]->x, (*pointmap)[p2_2]->y, (*pointmap)[p2_2]->z);
-       //bu_log("TPnt3 %f %f -> %f %f %f\n", p2_3->x, p2_3->y, 
(*pointmap)[p2_3]->x, (*pointmap)[p2_3]->y, (*pointmap)[p2_3]->z);
-       //bu_log("TPoints %f %f -> %f %f -> %f %f\n", p2_1->x, p2_1->y, 
p2_2->x, p2_2->y, p2_3->x, p2_3->y);
-       // Check the triangle direction against the normals
-       ON_3dVector ltdir = p2tTri_Normal(t, pointmap);
-       ON_3dPoint *onorm = (*normalmap)[t->GetPoint(0)];

@@ Diff output truncated at 100000 characters. @@
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