Revision: 73111
          http://sourceforge.net/p/brlcad/code/73111
Author:   starseeker
Date:     2019-05-21 18:45:22 +0000 (Tue, 21 May 2019)
Log Message:
-----------
Break the CDT logic out into topical files to make it a bit easier to work with.

Modified Paths:
--------------
    brlcad/trunk/src/libbrep/CMakeLists.txt
    brlcad/trunk/src/libbrep/cdt.cpp

Added Paths:
-----------
    brlcad/trunk/src/libbrep/cdt.h
    brlcad/trunk/src/libbrep/cdt_closed_surf.cpp
    brlcad/trunk/src/libbrep/cdt_edge.cpp
    brlcad/trunk/src/libbrep/cdt_surf.cpp
    brlcad/trunk/src/libbrep/cdt_util.cpp

Modified: brlcad/trunk/src/libbrep/CMakeLists.txt
===================================================================
--- brlcad/trunk/src/libbrep/CMakeLists.txt     2019-05-21 18:31:56 UTC (rev 
73110)
+++ brlcad/trunk/src/libbrep/CMakeLists.txt     2019-05-21 18:45:22 UTC (rev 
73111)
@@ -24,6 +24,10 @@
   Subcurve.cpp
   Subsurface.cpp
   boolean.cpp
+  cdt_closed_surf.cpp
+  cdt_edge.cpp
+  cdt_surf.cpp
+  cdt_util.cpp
   cdt.cpp
   intersect.cpp
   libbrep_brep_tools.cpp
@@ -43,6 +47,7 @@
 set(libbrep_ignored_files
   libbrep_brep_tools.h
   brep_except.h
+  cdt.h
   opennurbs_fit.h
   opennurbs_fit.cpp
   PullbackCurve.h

Modified: brlcad/trunk/src/libbrep/cdt.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt.cpp    2019-05-21 18:31:56 UTC (rev 73110)
+++ brlcad/trunk/src/libbrep/cdt.cpp    2019-05-21 18:45:22 UTC (rev 73111)
@@ -26,1874 +26,9 @@
  */
 
 #include "common.h"
+#include "./cdt.h"
 
-#include <vector>
-#include <list>
-#include <map>
-#include <stack>
-#include <iostream>
-#include <algorithm>
-#include <set>
-#include <utility>
-
-#include "poly2tri/poly2tri.h"
-
-#include "assert.h"
-
-#include "vmath.h"
-
-#include "bu/color.h"
-#include "bu/cv.h"
-#include "bu/opt.h"
-#include "bu/time.h"
-#include "bn/plot3.h"
-#include "bn/tol.h"
-#include "bn/vlist.h"
-#include "bg/polygon.h"
-#include "bg/trimesh.h"
-#include "brep/defines.h"
-#include "brep/cdt.h"
-#include "brep/pullback.h"
-#include "brep/util.h"
-
-/***************************************************
- * debugging routines
- ***************************************************/
-
-void
-plot_polyline(std::vector<p2t::Point *> *pnts, const char *filename)
-{
-    FILE *plot = fopen(filename, "w");
-    int r = 255; int g = 0; int b = 0;
-    point_t pc;
-    pl_color(plot, r, g, b); 
-    for (size_t i = 0; i < pnts->size(); i++) {
-       p2t::Point *pt = (*pnts)[i];
-       VSET(pc, pt->x, pt->y, 0);
-       if (i == 0) {
-           pdv_3move(plot, pc);
-       }
-       pdv_3cont(plot, pc);
-    }
-    fclose(plot);
-}
-
-
-void
-plot_tri(p2t::Triangle *t, const char *filename)
-{
-    FILE *plot = fopen(filename, "w");
-    int r = 0; int g = 255; int b = 0;
-    point_t pc;
-    pl_color(plot, r, g, b); 
-    for (size_t i = 0; i < 3; i++) {
-       p2t::Point *pt = t->GetPoint(i);
-       VSET(pc, pt->x, pt->y, 0);
-       if (i == 0) {
-           pdv_3move(plot, pc);
-       }
-       pdv_3cont(plot, pc);
-    }
-    fclose(plot);
-}
-
-
-
-/***************************************************/
-typedef std::pair<ON_3dPoint *, ON_3dPoint *> Edge;
-typedef std::map< Edge, std::set<p2t::Triangle*> > EdgeToTri;
-
-static Edge
-mk_edge(ON_3dPoint *pt_A, ON_3dPoint *pt_B)
-{
-    if (pt_A <= pt_B) {
-       return std::make_pair(pt_A, pt_B);
-    } else {
-       return std::make_pair(pt_B, pt_A);
-    }
-}
-
 static void
-add_tri_edges(EdgeToTri *e2f, p2t::Triangle *t,
-    std::map<p2t::Point *, ON_3dPoint *> *pointmap)
-{
-    ON_3dPoint *pt_A, *pt_B, *pt_C;
-
-    p2t::Point *p2_A = t->GetPoint(0);
-    p2t::Point *p2_B = t->GetPoint(1);
-    p2t::Point *p2_C = t->GetPoint(2);
-    pt_A = (*pointmap)[p2_A];
-    pt_B = (*pointmap)[p2_B];
-    pt_C = (*pointmap)[p2_C];
-    (*e2f)[(mk_edge(pt_A, pt_B))].insert(t);
-    (*e2f)[(mk_edge(pt_B, pt_C))].insert(t);
-    (*e2f)[(mk_edge(pt_C, pt_A))].insert(t);
-}
-
-#define BREP_CDT_FAILED -3
-#define BREP_CDT_NON_SOLID -2
-#define BREP_CDT_UNTESSELLATED -1
-#define BREP_CDT_SOLID 0
-
-/* Note - these tolerance values are based on the default
- * values from the GED 'tol' command */
-#define BREP_CDT_DEFAULT_TOL_ABS 0.0
-#define BREP_CDT_DEFAULT_TOL_REL 0.01
-#define BREP_CDT_DEFAULT_TOL_NORM 0.0
-#define BREP_CDT_DEFAULT_TOL_DIST BN_TOL_DIST
-
-/* this is a debugging structure - it holds origin information for
- * a point added to the CDT state */
-struct cdt_audit_info {
-    int face_index;
-    int vert_index;
-    int trim_index;
-    int edge_index;
-    ON_2dPoint surf_uv;
-};
-
-struct cdt_audit_info *
-cdt_ainfo(int fid, int vid, int tid, int eid, fastf_t x2d, fastf_t y2d)
-{
-    struct cdt_audit_info *a = new struct cdt_audit_info;
-    a->face_index = fid;
-    a->vert_index = vid;
-    a->trim_index = tid;
-    a->edge_index = eid;
-    a->surf_uv = ON_2dPoint(x2d, y2d);
-    return a;
-}
-
-struct ON_Brep_CDT_State {
-
-    int status;
-    ON_Brep *brep;
-
-    /* Tolerances */
-    fastf_t abs;
-    fastf_t rel;
-    fastf_t norm;
-    fastf_t dist;
-
-    /* 3D data */
-    std::vector<ON_3dPoint *> *w3dpnts;
-    std::map<int, ON_3dPoint *> *vert_pnts;
-    std::vector<ON_3dPoint *> *w3dnorms;
-    std::map<int, ON_3dPoint *> *vert_norms;
-
-    /* singular trim info */
-    std::map<int, std::map<int,ON_3dPoint *>> *strim_pnts;
-    std::map<int, std::map<int,ON_3dPoint *>> *strim_norms;
-
-    /* Poly2Tri data */
-    p2t::CDT **p2t_faces;
-    std::vector<p2t::Triangle *> **p2t_extra_faces;
-    std::map<ON_2dPoint *, ON_3dPoint *> **on2_to_on3_maps;
-    std::map<p2t::Point *, ON_3dPoint *> **tri_to_on3_maps;
-    std::map<p2t::Point *, ON_3dPoint *> **tri_to_on3_norm_maps;
-    std::map<ON_3dPoint *, std::set<p2t::Point *>> **on3_to_tri_maps;
-
-    /* Audit data */
-    std::map<ON_3dPoint *, struct cdt_audit_info *> pnt_audit_info;
-
-    /* BoT -> ON mappings */
-    std::map<ON_3dPoint *, std::set<BrepTrimPoint *>> on_brep_edge_pnts;
-    std::map<int, ON_3dPoint *> *vert_to_on;
-    std::set<ON_3dPoint *> *edge_pnts;
-    ON_SimpleArray<BrepTrimPoint> **brep_face_loop_points;
-    std::set<p2t::Point *> **face_degen_pnts;
-};
-
-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)
-{
-    s->w3dpnts->push_back(p);
-    s->pnt_audit_info[p] = cdt_ainfo(fid, vid, tid, eid, x2d, y2d);
-}
-
-
-struct brep_cdt_tol {
-    fastf_t min_dist;
-    fastf_t max_dist;
-    fastf_t within_dist;
-    fastf_t cos_within_ang;
-};
-
-#define BREP_CDT_TOL_ZERO {0.0, 0.0, 0.0, 0.0}
-
-// Digest tessellation tolerances...
-static void
-CDT_Tol_Set(struct brep_cdt_tol *cdt, double dist, fastf_t md, double t_abs, 
double t_rel, double t_norm, double t_dist)
-{
-    fastf_t min_dist, max_dist, within_dist, cos_within_ang;
-
-    max_dist = md;
-
-    if (t_abs < t_dist + ON_ZERO_TOLERANCE) {
-       min_dist = t_dist;
-    } else {
-       min_dist = t_abs;
-    }
-
-    double rel = 0.0;
-    if (t_rel > 0.0 + ON_ZERO_TOLERANCE) {
-       rel = t_rel * dist;
-       // TODO - think about what we want maximum distance to mean and how it
-       // relates to other tessellation settings...
-       if (max_dist < rel * 10.0) {
-           max_dist = rel * 10.0;
-       }
-       within_dist = rel < min_dist ? min_dist : rel;
-    } else if (t_abs > 0.0 + ON_ZERO_TOLERANCE) {
-       within_dist = min_dist;
-    } else {
-       within_dist = 0.01 * dist; // default to 1% of dist
-    }
-
-    if (t_norm > 0.0 + ON_ZERO_TOLERANCE) {
-       cos_within_ang = cos(t_norm);
-    } else {
-       cos_within_ang = cos(ON_PI / 2.0);
-    }
-
-    cdt->min_dist = min_dist;
-    cdt->max_dist = max_dist;
-    cdt->within_dist = within_dist;
-    cdt->cos_within_ang = cos_within_ang;
-}
-
-
-static void
-getEdgePoints(
-       struct ON_Brep_CDT_State *s_cdt,
-       ON_BrepEdge *edge,
-       ON_NurbsCurve *nc,
-       const ON_BrepTrim &trim,
-       BrepTrimPoint *sbtp1,
-       BrepTrimPoint *ebtp1,
-       BrepTrimPoint *sbtp2,
-       BrepTrimPoint *ebtp2,
-       const struct brep_cdt_tol *cdt_tol,
-       std::map<double, BrepTrimPoint *> *trim1_param_points,
-       std::map<double, BrepTrimPoint *> *trim2_param_points
-       )
-{
-    ON_3dPoint tmp1, tmp2;
-    ON_BrepTrim *trim2 = (edge->Trim(0)->m_trim_index == trim.m_trim_index) ? 
edge->Trim(1) : edge->Trim(0);
-    const ON_Surface *s1 = trim.SurfaceOf();
-    const ON_Surface *s2 = trim2->SurfaceOf();
-    fastf_t t1 = (sbtp1->t + ebtp1->t) / 2.0;
-    fastf_t t2 = (sbtp2->t + ebtp2->t) / 2.0;
-    ON_3dPoint trim1_mid_2d = trim.PointAt(t1);
-    ON_3dPoint trim2_mid_2d = trim2->PointAt(t2);
-    fastf_t emid = (sbtp1->e + ebtp1->e) / 2.0;
-
-    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;
-
-    if (!(nc->EvTangent(emid, edge_mid_3d, edge_mid_tang))) {
-       // EvTangent call failed, get 3d point
-       edge_mid_3d = nc->PointAt(emid);
-       // 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);
-       int evals = 0;
-       evals += (trim.EvTangent(t1, tmp1, trim1_mid_tang)) ? 1 : 0;
-       evals += (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;
-       }
-    }
-
-    // bu_log("Edge %d, Trim %d(%d): %f %f %f\n", edge->m_edge_index, 
trim.m_trim_index, trim.m_bRev3d, edge_mid_3d.x, edge_mid_3d.y, edge_mid_3d.z);
-
-    int dosplit = 0;
-
-    ON_Line line3d(*(sbtp1->p3d), *(ebtp1->p3d));
-    double dist3d = edge_mid_3d.DistanceTo(line3d.ClosestPointTo(edge_mid_3d));
-    dosplit += (line3d.Length() > cdt_tol->max_dist) ? 1 : 0;
-    dosplit += (dist3d > (cdt_tol->within_dist + ON_ZERO_TOLERANCE)) ? 1 : 0;
-
-    if ((dist3d > cdt_tol->min_dist + ON_ZERO_TOLERANCE)) {
-       if (!dosplit) {
-           dosplit += ((sbtp1->tangent * ebtp1->tangent) < 
cdt_tol->cos_within_ang - ON_ZERO_TOLERANCE) ? 1 : 0;
-       }
-
-       if (!dosplit && sbtp1->normal != ON_3dVector::UnsetVector && 
ebtp1->normal != ON_3dVector::UnsetVector) {
-           dosplit += ((sbtp1->normal * ebtp1->normal) < 
cdt_tol->cos_within_ang - ON_ZERO_TOLERANCE) ? 1 : 0;
-       }
-
-       if (!dosplit && sbtp2->normal != ON_3dVector::UnsetVector && 
ebtp2->normal != ON_3dVector::UnsetVector) {
-           dosplit += ((sbtp2->normal * ebtp2->normal) < 
cdt_tol->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 (trim.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 (trim2->Face()->m_bRev) {
-               trim2_mid_norm = trim2_mid_norm  * -1.0;
-           }
-       }
-
-       ON_3dPoint *npt = new ON_3dPoint(edge_mid_3d);
-       CDT_Add3DPnt(s_cdt, npt, -1, -1, -1, edge->m_edge_index, emid, 0);
-       s_cdt->edge_pnts->insert(npt);
-
-       BrepTrimPoint *nbtp1 = new BrepTrimPoint;
-       nbtp1->p3d = npt;
-       nbtp1->n3d = NULL;
-       nbtp1->p2d = trim1_mid_2d;
-       nbtp1->normal = trim1_mid_norm;
-       nbtp1->tangent = edge_mid_tang;
-       nbtp1->t = t1;
-       nbtp1->e = emid;
-       nbtp1->trim_ind = trim.m_trim_index;
-       (*trim1_param_points)[nbtp1->t] = nbtp1;
-       s_cdt->on_brep_edge_pnts[npt].insert(nbtp1);
-
-       BrepTrimPoint *nbtp2 = new BrepTrimPoint;
-       nbtp2->p3d = npt;
-       nbtp2->n3d = NULL;
-       nbtp2->p2d = trim2_mid_2d;
-       nbtp2->normal = trim2_mid_norm;
-       nbtp2->tangent = edge_mid_tang;
-       nbtp2->t = t2;
-       nbtp2->e = emid;
-       nbtp2->trim_ind = trim2->m_trim_index;
-       (*trim2_param_points)[nbtp2->t] = nbtp2;
-       s_cdt->on_brep_edge_pnts[npt].insert(nbtp2);
-
-       getEdgePoints(s_cdt, edge, nc, trim, sbtp1, nbtp1, sbtp2, nbtp2, 
cdt_tol, trim1_param_points, trim2_param_points);
-       getEdgePoints(s_cdt, edge, nc, trim, nbtp1, ebtp1, nbtp2, ebtp2, 
cdt_tol, trim1_param_points, trim2_param_points);
-       return;
-    }
-
-    int udir = 0;
-    int vdir = 0;
-    double trim1_seam_t = 0.0;
-    double trim2_seam_t = 0.0;
-    ON_2dPoint trim1_start = sbtp1->p2d;
-    ON_2dPoint trim1_end = ebtp1->p2d;
-    ON_2dPoint trim2_start = sbtp2->p2d;
-    ON_2dPoint trim2_end = 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(trim, sbtp1->t, ebtp1->t, trim1_seam_t, from, 
to, BREP_SAME_POINT_TOLERANCE)) {
-           trim1_seam_2d = trim.PointAt(trim1_seam_t);
-           trim1_seam_3d = s1->PointAt(trim1_seam_2d.x, trim1_seam_2d.y);
-           if (trim1_param_points->find(trim1_seam_t) == 
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(trim, sbtp2->t, ebtp2->t, trim2_seam_t, from, 
to, BREP_SAME_POINT_TOLERANCE)) {
-           trim2_seam_2d = trim2->PointAt(trim2_seam_t);
-           trim2_seam_3d = s2->PointAt(trim2_seam_2d.x, trim2_seam_2d.y);
-           if (trim2_param_points->find(trim2_seam_t) == 
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(s_cdt, nsptp, trim.Face()->m_face_index, -1, 
trim.m_trim_index, trim.Edge()->m_edge_index, trim1_seam_2d.x, trim1_seam_2d.y);
-           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 = (sbtp1->t + ebtp1->t)/2;
-               trim1_seam_2d = trim.PointAt(trim1_seam_t);
-               nsptp = new ON_3dPoint(trim2_seam_3d);
-               CDT_Add3DPnt(s_cdt, nsptp, trim2->Face()->m_face_index, -1, 
trim2->m_trim_index, trim2->Edge()->m_edge_index, trim1_seam_2d.x, 
trim1_seam_2d.y);
-               s_cdt->edge_pnts->insert(nsptp);
-           }
-           if (!t2_dosplit) {
-               trim2_seam_t = (sbtp2->t + ebtp2->t)/2;
-               trim2_seam_2d = trim2->PointAt(trim2_seam_t);
-               nsptp = new ON_3dPoint(trim1_seam_3d);
-               CDT_Add3DPnt(s_cdt, nsptp, trim.Face()->m_face_index, -1, 
trim.m_trim_index, trim.Edge()->m_edge_index, trim1_seam_2d.x, trim1_seam_2d.y);
-               s_cdt->edge_pnts->insert(nsptp);
-           }
-       }
-
-       // Note - by this point we shouldn't need tangents and normals...
-       BrepTrimPoint *nbtp1 = new BrepTrimPoint;
-       nbtp1->p3d = nsptp;
-       nbtp1->p2d = trim1_seam_2d;
-       nbtp1->t = trim1_seam_t;
-       nbtp1->trim_ind = trim.m_trim_index;
-       nbtp1->e = ON_UNSET_VALUE;
-       (*trim1_param_points)[nbtp1->t] = nbtp1;
-       s_cdt->on_brep_edge_pnts[nsptp].insert(nbtp1);
-
-       BrepTrimPoint *nbtp2 = new BrepTrimPoint;
-       nbtp2->p3d = nsptp;
-       nbtp2->p2d = trim2_seam_2d;
-       nbtp2->t = trim2_seam_t;
-       nbtp2->trim_ind = trim2->m_trim_index;
-       nbtp2->e = ON_UNSET_VALUE;
-       (*trim2_param_points)[nbtp2->t] = nbtp2;
-       s_cdt->on_brep_edge_pnts[nsptp].insert(nbtp2);
-    }
-
-}
-
-static std::map<double, BrepTrimPoint *> *
-getEdgePoints(
-       struct ON_Brep_CDT_State *s_cdt,
-       ON_BrepEdge *edge,
-       ON_BrepTrim &trim,
-       fastf_t max_dist,
-       std::map<int, ON_3dPoint *> *vert_pnts,
-       std::map<int, ON_3dPoint *> *vert_norms
-       )
-{
-    struct brep_cdt_tol cdt_tol = BREP_CDT_TOL_ZERO;
-    std::map<double, BrepTrimPoint *> *trim1_param_points = NULL;
-    std::map<double, BrepTrimPoint *> *trim2_param_points = NULL;
-
-    // Get the other trim
-    // 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 *trim2 = (edge->Trim(0)->m_trim_index == trim.m_trim_index) ? 
edge->Trim(1) : edge->Trim(0);
-
-    double dist = 1000.0;
-
-    const ON_Surface *s1 = trim.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 (trim.m_trim_user.p != NULL && trim2->m_trim_user.p == NULL) {
-       return NULL;
-    }
-    if (trim.m_trim_user.p == NULL && trim2->m_trim_user.p != NULL) {
-       return NULL;
-    }
-
-
-    /* If we've already got the points, just return them */
-    if (trim.m_trim_user.p != NULL) {
-       trim1_param_points = (std::map<double, BrepTrimPoint *> *) 
trim.m_trim_user.p;
-       return trim1_param_points;
-    }
-
-    /* Establish tolerances (TODO - get from edge curve...) */
-    if (trim.GetBoundingBox(min, max, bGrowBox)) {
-       dist = DIST_PT_PT(min, max);
-    }
-    CDT_Tol_Set(&cdt_tol, dist, max_dist, s_cdt->abs, s_cdt->rel, s_cdt->norm, 
s_cdt->dist);
-
-    /* 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 *>();
-    trim.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 = trim.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;
-       trim.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 = (*vert_pnts)[edge->Vertex(0)->m_vertex_index];
-    edge_end_3d = (*vert_pnts)[edge->Vertex(1)->m_vertex_index];
-
-    /* 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);
-    ON_Interval erange = nc->Domain();
-
-    /* Populate the 2D points */
-    double st1 = (trim.m_bRev3d) ? range1.m_t[1] : range1.m_t[0];
-    double et1 = (trim.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 = trim.PointAt(st1);
-    trim1_end_2d = trim.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 += (trim.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 += (trim.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 = 
(*vert_norms)[edge->Vertex(0)->m_vertex_index];
-    ON_3dPoint *edge_end_3dnorm = 
(*vert_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 (trim.Face()->m_bRev) {
-           trim1_start_normal = trim1_start_normal  * -1.0;
-       }
-       if (ON_DotProduct(trim1_start_normal, *edge_start_3dnorm) < 0) {
-           t1_sn = edge_start_3dnorm;
-       } else {
-           t1_sn = new ON_3dPoint(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 (trim.Face()->m_bRev) {
-           trim1_end_normal = trim1_end_normal  * -1.0;
-       }
-       if (ON_DotProduct(trim1_end_normal, *edge_end_3dnorm) < 0) {
-           t1_en = edge_end_3dnorm;
-       } else {
-           t1_en = new ON_3dPoint(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 (ON_DotProduct(trim2_start_normal, *edge_start_3dnorm) < 0) {
-           t2_sn = edge_start_3dnorm;
-       } else {
-           t2_sn = new ON_3dPoint(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 (ON_DotProduct(trim2_end_normal, *edge_end_3dnorm) < 0) {
-           t2_en = edge_end_3dnorm;
-       } else {
-           t2_en = new ON_3dPoint(trim2_end_normal);
-           s_cdt->w3dnorms->push_back(t2_en);
-       }
-    }
-
-    /* Start and end points for both trims can now be defined */
-    BrepTrimPoint *sbtp1 = new BrepTrimPoint;
-    sbtp1->p3d = edge_start_3d;
-    sbtp1->n3d = t1_sn;
-    sbtp1->tangent = edge_start_tang;
-    sbtp1->e = erange.m_t[0];
-    sbtp1->p2d = trim1_start_2d;
-    sbtp1->normal = trim1_start_normal;
-    sbtp1->t = st1;
-    sbtp1->trim_ind = trim.m_trim_index;
-    (*trim1_param_points)[sbtp1->t] = sbtp1;
-    s_cdt->on_brep_edge_pnts[edge_start_3d].insert(sbtp1);
-
-    BrepTrimPoint *ebtp1 = new BrepTrimPoint;
-    ebtp1->p3d = edge_end_3d;
-    ebtp1->n3d = t1_en;
-    ebtp1->tangent = edge_end_tang;
-    ebtp1->e = erange.m_t[1];
-    ebtp1->p2d = trim1_end_2d;
-    ebtp1->normal = trim1_end_normal;
-    ebtp1->t = et1;
-    ebtp1->trim_ind = trim.m_trim_index;
-    (*trim1_param_points)[ebtp1->t] = ebtp1;
-    s_cdt->on_brep_edge_pnts[edge_end_3d].insert(ebtp1);
-
-    BrepTrimPoint *sbtp2 = new BrepTrimPoint;
-    sbtp2->p3d = edge_start_3d;
-    sbtp2->n3d = t2_sn;
-    sbtp2->tangent = edge_start_tang;
-    sbtp2->e = erange.m_t[0];
-    sbtp2->p2d = trim2_start_2d;
-    sbtp2->normal = trim2_start_normal;
-    sbtp2->t = st2;
-    sbtp2->trim_ind = trim2->m_trim_index;
-    (*trim2_param_points)[sbtp2->t] = sbtp2;
-    s_cdt->on_brep_edge_pnts[edge_start_3d].insert(sbtp2);
-
-    BrepTrimPoint *ebtp2 = new BrepTrimPoint;
-    ebtp2->p3d = edge_end_3d;
-    ebtp2->n3d = t2_en;
-    ebtp2->tangent = edge_end_tang;
-    ebtp2->e = erange.m_t[1];
-    ebtp2->p2d = trim2_end_2d;
-    ebtp2->normal = trim2_end_normal;
-    ebtp2->t = et2;
-    ebtp2->trim_ind = trim2->m_trim_index;
-    (*trim2_param_points)[ebtp2->t] = ebtp2;
-    s_cdt->on_brep_edge_pnts[edge_end_3d].insert(ebtp2);
-
-
-    if (trim.IsClosed() || trim2->IsClosed()) {
-
-       double trim1_mid_range = (st1 + et1) / 2.0;
-       double trim2_mid_range = (st2 + et2) / 2.0;
-       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;
-
-       if (!(nc->EvTangent(edge_mid_range, edge_mid_3d, edge_mid_tang))) {
-           // EvTangent call failed, get 3d point
-           edge_mid_3d = nc->PointAt(edge_mid_range);
-           // 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 += (trim.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;
-       ON_3dPoint trim1_mid_2d = trim.PointAt(trim1_mid_range);
-       ON_3dPoint trim2_mid_2d = trim2->PointAt(trim2_mid_range);
-
-       evals += (surface_EvNormal(s1, trim1_mid_2d.x, trim1_mid_2d.y, tmp1, 
trim1_mid_norm)) ? 1 : 0;
-       if (trim.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 = new BrepTrimPoint;
-       mbtp1->p3d = nmp;
-       mbtp1->n3d = NULL;
-       mbtp1->p2d = trim1_mid_2d;
-       mbtp1->tangent = edge_mid_tang;
-       mbtp1->normal = trim1_mid_norm;
-       mbtp1->t = trim1_mid_range;
-       mbtp1->e = edge_mid_range;
-       mbtp1->trim_ind = trim.m_trim_index;
-       (*trim1_param_points)[mbtp1->t] = mbtp1;
-       s_cdt->on_brep_edge_pnts[nmp].insert(mbtp1);
-
-       BrepTrimPoint *mbtp2 = new BrepTrimPoint;
-       mbtp2->p3d = nmp;
-       mbtp2->n3d = NULL;
-       mbtp2->p2d = trim2_mid_2d;
-       mbtp2->tangent = edge_mid_tang;
-       mbtp2->normal = trim2_mid_norm;
-       mbtp2->t = trim2_mid_range;
-       mbtp1->e = edge_mid_range;
-       mbtp2->trim_ind = trim2->m_trim_index;
-       (*trim2_param_points)[mbtp2->t] = mbtp2;
-       s_cdt->on_brep_edge_pnts[nmp].insert(mbtp2);
-
-       getEdgePoints(s_cdt, edge, nc, trim, sbtp1, mbtp1, sbtp2, mbtp2, 
&cdt_tol, trim1_param_points, trim2_param_points);
-       getEdgePoints(s_cdt, edge, nc, trim, mbtp1, ebtp1, mbtp2, ebtp2, 
&cdt_tol, trim1_param_points, trim2_param_points);
-
-    } else {
-
-       getEdgePoints(s_cdt, edge, nc, trim, sbtp1, ebtp1, sbtp2, ebtp2, 
&cdt_tol, trim1_param_points, trim2_param_points);
-
-    }
-
-    return trim1_param_points;
-}
-
-struct cdt_surf_info {
-    const ON_Surface *s;
-    const ON_BrepFace *f;
-    std::map<int, std::map<int,ON_3dPoint *>> *strim_pnts;
-    std::map<int, std::map<int,ON_3dPoint *>> *strim_norms;
-    double u1, u2, v1, v2;
-    fastf_t ulen;
-    fastf_t u_lower_3dlen;
-    fastf_t u_mid_3dlen;
-    fastf_t u_upper_3dlen;
-    fastf_t vlen;
-    fastf_t v_lower_3dlen;
-    fastf_t v_mid_3dlen;
-    fastf_t v_upper_3dlen;
-};
-
-double
-uline_len_est(struct cdt_surf_info *sinfo, double u1, double u2, double v)
-{
-    double t, lenfact, lenest;
-    int active_half = (fabs(sinfo->v1 - v) < fabs(sinfo->v2 - v)) ? 0 : 1;
-    t = (active_half == 0) ? 1 - fabs(sinfo->v1 - v)/fabs((sinfo->v2 - 
sinfo->v1)*0.5) : 1 - fabs(sinfo->v2 - v)/fabs((sinfo->v2 - sinfo->v1)*0.5);
-    if (active_half == 0) {
-       lenfact = sinfo->u_lower_3dlen * (1 - (t)) + sinfo->u_mid_3dlen * (t);
-       lenest = (u2 - u1)/sinfo->ulen * lenfact;
-    } else {
-       lenfact = sinfo->u_mid_3dlen * (1 - (t)) + sinfo->u_upper_3dlen * (t);
-       lenest = (u2 - u1)/sinfo->ulen * lenfact;
-    }
-    //if (print_debug) {
-    // bu_log("active_half: %d u1:%f u2:%f v: %f -> t: %f lenfact: %f lenest: 
%f\n", active_half, u1, u2, v, t, lenfact, lenest);
-    //}
-    return lenest;
-}
-
-
-double
-vline_len_est(struct cdt_surf_info *sinfo, double u, double v1, double v2)
-{
-    double t, lenfact, lenest;
-    int active_half = (fabs(sinfo->u1 - u) < fabs(sinfo->u2 - u)) ? 0 : 1;
-    t = (active_half == 0) ? 1 - fabs(sinfo->u1 - u)/fabs((sinfo->u2 - 
sinfo->u1)*0.5) : 1 - fabs(sinfo->u2 - u)/fabs((sinfo->u2 - sinfo->u1)*0.5);
-    if (active_half == 0) {
-       lenfact = sinfo->v_lower_3dlen * (1 - (t)) + sinfo->v_mid_3dlen * (t);
-       lenest = (v2 - v1)/sinfo->vlen * lenfact;
-    } else {
-       lenfact = sinfo->v_mid_3dlen * (1 - (t)) + sinfo->v_upper_3dlen * (t);
-       lenest = (v2 - v1)/sinfo->vlen * lenfact;
-    }
-
-    //if (print_debug) {
-    //    bu_log("active_half: %d u:%f v1:%f v2: %f -> t: %f lenfact: %f 
lenest: %f\n", active_half, u, v1, v2, t, lenfact, lenest);
-    //}
-    return lenest;
-}
-
-ON_3dPoint *
-singular_trim_norm(struct cdt_surf_info *sinfo, fastf_t uc, fastf_t vc)
-{
-    if (sinfo->strim_pnts->find(sinfo->f->m_face_index) != 
sinfo->strim_pnts->end()) {
-       bu_log("Face %d has singular trims\n", sinfo->f->m_face_index);
-       if (sinfo->strim_norms->find(sinfo->f->m_face_index) == 
sinfo->strim_norms->end()) {
-           bu_log("Face %d has no singular trim normal information\n", 
sinfo->f->m_face_index);
-           return NULL;
-       }
-       std::map<int, ON_3dPoint *>::iterator m_it;
-       // Check the trims to see if uc,vc is on one of them
-       for (m_it = (*sinfo->strim_pnts)[sinfo->f->m_face_index].begin(); m_it 
!= (*sinfo->strim_pnts)[sinfo->f->m_face_index].end(); m_it++) {
-           bu_log("  trim %d\n", (*m_it).first);
-           ON_Interval trim_dom = 
sinfo->f->Brep()->m_T[(*m_it).first].Domain();
-           ON_2dPoint p2d1 = 
sinfo->f->Brep()->m_T[(*m_it).first].PointAt(trim_dom.m_t[0]);
-           ON_2dPoint p2d2 = 
sinfo->f->Brep()->m_T[(*m_it).first].PointAt(trim_dom.m_t[1]);
-           bu_log("  points: %f,%f -> %f,%f\n", p2d1.x, p2d1.y, p2d2.x, 
p2d2.y);
-           int on_trim = 1;
-           if (NEAR_EQUAL(p2d1.x, p2d2.x, ON_ZERO_TOLERANCE)) {
-               if (!NEAR_EQUAL(p2d1.x, uc, ON_ZERO_TOLERANCE)) {
-                   on_trim = 0;
-               }
-           } else {
-               if (!NEAR_EQUAL(p2d1.x, uc, ON_ZERO_TOLERANCE) && 
!NEAR_EQUAL(p2d2.x, uc, ON_ZERO_TOLERANCE)) {
-                   if (!((uc > p2d1.x && uc < p2d2.x) || (uc < p2d1.x && uc > 
p2d2.x))) {
-                       on_trim = 0;
-                   }
-               }
-           }
-           if (NEAR_EQUAL(p2d1.y, p2d2.y, ON_ZERO_TOLERANCE)) {
-               if (!NEAR_EQUAL(p2d1.y, vc, ON_ZERO_TOLERANCE)) {
-                   on_trim = 0;
-               }
-           } else {
-               if (!NEAR_EQUAL(p2d1.y, vc, ON_ZERO_TOLERANCE) && 
!NEAR_EQUAL(p2d2.y, vc, ON_ZERO_TOLERANCE)) {
-                   if (!((vc > p2d1.y && vc < p2d2.y) || (vc < p2d1.y && vc > 
p2d2.y))) {
-                       on_trim = 0;
-                   }
-               }
-           }
-
-           if (on_trim) {
-               if 
((*sinfo->strim_norms)[sinfo->f->m_face_index].find((*m_it).first) != 
(*sinfo->strim_norms)[sinfo->f->m_face_index].end()) {
-                   ON_3dPoint *vnorm = NULL;
-                   vnorm = 
(*sinfo->strim_norms)[sinfo->f->m_face_index][(*m_it).first];
-                   bu_log(" normal: %f, %f, %f\n", vnorm->x, vnorm->y, 
vnorm->z);
-                   return vnorm;
-               } else {
-                   bu_log(" on singular trim, but no matching normal\n");
-                   return NULL;
-               }
-           }
-       }
-    }
-    return NULL;
-}
-
-static void
-getSurfacePoints(
-                struct ON_Brep_CDT_State *s_cdt,
-                struct cdt_surf_info *sinfo,
-                fastf_t u1,
-                fastf_t u2,
-                fastf_t v1,
-                fastf_t v2,
-                fastf_t min_dist,
-                fastf_t within_dist,
-                fastf_t cos_within_ang,
-                ON_2dPointArray &on_surf_points,
-                bool left,
-                bool below)
-{
-    double ldfactor = 2.0;
-    ON_2dPoint p2d(0.0, 0.0);
-    ON_3dPoint p[4] = {ON_3dPoint(), ON_3dPoint(), ON_3dPoint(), ON_3dPoint()};
-    ON_3dVector norm[4] = {ON_3dVector(), ON_3dVector(), ON_3dVector(), 
ON_3dVector()};
-    ON_3dPoint mid(0.0, 0.0, 0.0);
-    ON_3dVector norm_mid(0.0, 0.0, 0.0);
-    fastf_t u = (u1 + u2) / 2.0;
-    fastf_t v = (v1 + v2) / 2.0;
-    fastf_t udist = u2 - u1;
-    fastf_t vdist = v2 - v1;
-
-    if ((udist < min_dist + ON_ZERO_TOLERANCE)
-           || (vdist < min_dist + ON_ZERO_TOLERANCE)) {
-       return;
-    }
-
-    if (udist > ldfactor * vdist) {
-       int isteps = (int)(udist / vdist);
-       isteps = (int)(udist / vdist / ldfactor * 2.0);
-       fastf_t step = udist / (fastf_t) isteps;
-
-       //bu_log("split: udist > ldfactor * vdist\n");
-
-       fastf_t step_u;
-       for (int i = 1; i <= isteps; i++) {
-           step_u = u1 + i * step;
-           if ((below) && (i < isteps)) {
-               p2d.Set(step_u, v1);
-               on_surf_points.Append(p2d);
-           }
-           if (i == 1) {
-
-               // Check the distance between v1 and v2 at u1 && u1+step.
-               // If they're both less than threshold, skip
-               double est1 = vline_len_est(sinfo, u1, v1, v2);
-               double est2 = vline_len_est(sinfo, u1+step, v1, v2);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, u1, u1 + step, v1, v2, min_dist,
-                       within_dist, cos_within_ang, on_surf_points, left,
-                       below);
-           } else if (i == isteps) {
-
-               // Check the distance between v1 and v2 at u2-step && u2
-               // If they're both less than threshold, skip
-               double est1 = vline_len_est(sinfo, u2-step, v1, v2);
-               double est2 = vline_len_est(sinfo, u2, v1, v2);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, u2 - step, u2, v1, v2, min_dist,
-                       within_dist, cos_within_ang, on_surf_points, left,
-                       below);
-           } else {
-               // Check the distance between v1 and v2 at step_u - step and 
step_u
-               // If they're both less than threshold, skip
-               double est1 = vline_len_est(sinfo, step_u - step, v1, v2);
-               double est2 = vline_len_est(sinfo, step_u, v1, v2);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, step_u - step, step_u, v1, v2, 
min_dist, within_dist,
-                       cos_within_ang, on_surf_points, left, below);
-           }
-           left = false;
-
-           if (i < isteps) {
-               //top
-               p2d.Set(step_u, v2);
-               on_surf_points.Append(p2d);
-           }
-       }
-       return;
-    }
-    if (vdist > ldfactor * udist) {
-       int isteps = (int)(vdist / udist);
-       isteps = (int)(vdist / udist / ldfactor * 2.0);
-       fastf_t step = vdist / (fastf_t) isteps;
-       fastf_t step_v;
-
-       //bu_log("split: vdist > ldfactor * udist\n");
-
-       for (int i = 1; i <= isteps; i++) {
-           step_v = v1 + i * step;
-           if ((left) && (i < isteps)) {
-               p2d.Set(u1, step_v);
-               on_surf_points.Append(p2d);
-           }
-
-           if (i == 1) {
-               double est1 = uline_len_est(sinfo, u1, u2, v1);
-               double est2 = uline_len_est(sinfo, u1, u2, v1 + step);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, u1, u2, v1, v1 + step, min_dist,
-                       within_dist, cos_within_ang, on_surf_points, left,
-                       below);
-           } else if (i == isteps) {
-               double est1 = uline_len_est(sinfo, u1, u2, v2 - step);
-               double est2 = uline_len_est(sinfo, u1, u2, v2);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, u1, u2, v2 - step, v2, min_dist,
-                       within_dist, cos_within_ang, on_surf_points, left,
-                       below);
-           } else {
-               double est1 = uline_len_est(sinfo, u1, u2, step_v - step);
-               double est2 = uline_len_est(sinfo, u1, u2, step_v);
-               if (est1 < min_dist && est2 < min_dist) {
-                   //bu_log("Small estimates: %f, %f\n", est1, est2);
-                   continue;
-               }
-
-               getSurfacePoints(s_cdt, sinfo, u1, u2, step_v - step, step_v, 
min_dist, within_dist,
-                       cos_within_ang, on_surf_points, left, below);
-           }
-
-           below = false;
-
-           if (i < isteps) {
-               //right
-               p2d.Set(u2, step_v);
-               on_surf_points.Append(p2d);
-           }
-       }
-       return;
-    }
-
-    double est1 = uline_len_est(sinfo, u1, u2, v1);
-    double est2 = uline_len_est(sinfo, u1, u2, v2);
-    double est3 = vline_len_est(sinfo, u1, v1, v2);
-    double est4 = vline_len_est(sinfo, u2, v1, v2);
-
-    //bu_log("(min: %f) est1, est2, est3, est4: %f, %f, %f, %f\n", min_dist, 
est1, est2, est3, est4);
-    if (est1 < 0.01*within_dist && est2 < 0.01*within_dist) {
-       //bu_log("e12 Small estimates: %f, %f\n", est1, est2);
-       return;
-    }
-    if (est3 < 0.01*within_dist && est4 < 0.01*within_dist) {
-       //bu_log("e34 Small estimates: %f, %f\n", est3, est4);
-       return;
-    }
-
-    if ((surface_EvNormal(sinfo->s, u1, v1, p[0], norm[0]))
-           && (surface_EvNormal(sinfo->s, u2, v1, p[1], norm[1])) // for u
-           && (surface_EvNormal(sinfo->s, u2, v2, p[2], norm[2]))
-           && (surface_EvNormal(sinfo->s, u1, v2, p[3], norm[3]))
-           && (surface_EvNormal(sinfo->s, u, v, mid, norm_mid))) {
-       double udot;
-       double vdot;
-       ON_Line line1(p[0], p[2]);
-       ON_Line line2(p[1], p[3]);
-       double dist = mid.DistanceTo(line1.ClosestPointTo(mid));
-       V_MAX(dist, mid.DistanceTo(line2.ClosestPointTo(mid)));
-       
-       for (int i = 0; i < 4; i++) {
-           if (ON_DotProduct(norm[i], norm_mid) < 0) {
-               fastf_t uc = (i == 0 || i == 3) ? u1 : u2;
-               fastf_t vc = (i == 0 || i == 1) ? v1 : v2;
-               bu_log("norm[%d](%f %f %f) backwards at %d point %f,%f\n", i, 
norm[i].x, norm[i].y, norm[i].z, i, uc, vc);
-               ON_3dPoint *vnorm = singular_trim_norm(sinfo, uc, vc);
-               if (vnorm && ON_DotProduct(*vnorm, norm_mid) > 0) {
-                   bu_log("vert norm works\n");
-                   norm[i] = *vnorm;
-               } else {
-                   bu_log("no matching vert normal, problem...\n");
-               }
-           }
-       }
-
-       if (dist < min_dist + ON_ZERO_TOLERANCE) {
-           return;
-       }
-
-       udot = (VNEAR_EQUAL(norm[0], norm[1], ON_ZERO_TOLERANCE)) ? 1.0 : 
norm[0] * norm[1];
-       vdot = (VNEAR_EQUAL(norm[0], norm[3], ON_ZERO_TOLERANCE)) ? 1.0 : 
norm[0] * norm[3];
-
-       if ((udot < cos_within_ang - ON_ZERO_TOLERANCE) && (vdot < 
cos_within_ang - ON_ZERO_TOLERANCE)) {
-           //bu_log("split: both cos_within_ang\n");
-           if (left) {
-               p2d.Set(u1, v);
-               on_surf_points.Append(p2d);
-           }
-           if (below) {
-               p2d.Set(u, v1);
-               on_surf_points.Append(p2d);
-           }
-           //center
-           p2d.Set(u, v);
-           on_surf_points.Append(p2d);
-           //right
-           p2d.Set(u2, v);
-           on_surf_points.Append(p2d);
-           //top
-           p2d.Set(u, v2);
-           on_surf_points.Append(p2d);
-
-           getSurfacePoints(s_cdt, sinfo, u1, u, v1, v, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, below);
-           getSurfacePoints(s_cdt, sinfo, u1, u, v, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, false);
-           getSurfacePoints(s_cdt, sinfo, u, u2, v1, v, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, false, below);
-           getSurfacePoints(s_cdt, sinfo, u, u2, v, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, false, false);
-           return;
-       }
-       if (udot < cos_within_ang - ON_ZERO_TOLERANCE) {
-           //bu_log("split: udot cos_within_ang\n");
-           if (below) {
-               p2d.Set(u, v1);
-               on_surf_points.Append(p2d);
-           }
-           //top
-           p2d.Set(u, v2);
-           on_surf_points.Append(p2d);
-           getSurfacePoints(s_cdt, sinfo, u1, u, v1, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, below);
-           getSurfacePoints(s_cdt, sinfo, u, u2, v1, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, false, below);
-           return;
-       }
-       if (vdot < cos_within_ang - ON_ZERO_TOLERANCE) {
-           //bu_log("split: vdot cos_within_ang\n");
-           if (left) {
-               p2d.Set(u1, v);
-               on_surf_points.Append(p2d);
-           }
-           //right
-           p2d.Set(u2, v);
-           on_surf_points.Append(p2d);
-
-           getSurfacePoints(s_cdt, sinfo, u1, u2, v1, v, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, below);
-           getSurfacePoints(s_cdt, sinfo, u1, u2, v, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, false);
-           return;
-       }
-
-       if (left) {
-           p2d.Set(u1, v);
-           on_surf_points.Append(p2d);
-       }
-       if (below) {
-           p2d.Set(u, v1);
-           on_surf_points.Append(p2d);
-       }
-       //center
-       p2d.Set(u, v);
-       on_surf_points.Append(p2d);
-       //right
-       p2d.Set(u2, v);
-       on_surf_points.Append(p2d);
-       //top
-       p2d.Set(u, v2);
-       on_surf_points.Append(p2d);
-
-       if (dist > within_dist + ON_ZERO_TOLERANCE) {
-           //bu_log("split: dist(%f) > within_dist(%f)\n", dist, within_dist);
-
-           getSurfacePoints(s_cdt, sinfo, u1, u, v1, v, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, below);
-           getSurfacePoints(s_cdt, sinfo, u1, u, v, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, left, false);
-           getSurfacePoints(s_cdt, sinfo, u, u2, v1, v, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, false, below);
-           getSurfacePoints(s_cdt, sinfo, u, u2, v, v2, min_dist, within_dist,
-                   cos_within_ang, on_surf_points, false, false);
-       }
-    }
-}
-
-
-/* flags identifying which side of the surface we're calculating
- *
- *                        u_upper
- *                        (2,0)
- *
- *               u1v2---------------- u2v2
- *                |          |         |
- *                |          |         |
- *                |  u_lmid  |         |
- *    v_lower     |----------|---------|     v_upper
- *     (0,1)      |  (1,0)   |         |      (2,1)
- *                |         v|lmid     |
- *                |          |(1,1)    |
- *               u1v1-----------------u2v1
- *
- *                        u_lower
- *                         (0,0)
- */
-double
-_cdt_get_uv_edge_3d_len(struct cdt_surf_info *sinfo, int c1, int c2)
-{
-    int line_set = 0;
-    double wu1, wv1, wu2, wv2, umid, vmid = 0.0;
-
-    /* u_lower */
-    if (c1 == 0 && c2 == 0) {
-       wu1 = sinfo->u1;
-       wu2 = sinfo->u2;
-       wv1 = sinfo->v1;
-       wv2 = sinfo->v1;
-       umid = (sinfo->u2 - sinfo->u1)/2.0;
-       vmid = sinfo->v1;
-       line_set = 1;
-    }
-
-    /* u_lmid */
-    if (c1 == 1 && c2 == 0) {
-       wu1 = sinfo->u1;
-       wu2 = sinfo->u2;
-       wv1 = (sinfo->v2 - sinfo->v1)/2.0;
-       wv2 = (sinfo->v2 - sinfo->v1)/2.0;
-       umid = (sinfo->u2 - sinfo->u1)/2.0;
-       vmid = (sinfo->v2 - sinfo->v1)/2.0;
-       line_set = 1;
-    }
-
-    /* u_upper */
-    if (c1 == 2 && c2 == 0) {
-       wu1 = sinfo->u1;
-       wu2 = sinfo->u2;
-       wv1 = sinfo->v2;
-       wv2 = sinfo->v2;
-       umid = (sinfo->u2 - sinfo->u1)/2.0;
-       vmid = sinfo->v2;
-       line_set = 1;
-    }
-
-    /* v_lower */
-    if (c1 == 0 && c2 == 1) {
-       wu1 = sinfo->u1;
-       wu2 = sinfo->u1;
-       wv1 = sinfo->v1;
-       wv2 = sinfo->v2;
-       umid = sinfo->u1;
-       vmid = (sinfo->v2 - sinfo->v1)/2.0;
-       line_set = 1;
-    }
-
-    /* v_lmid */
-    if (c1 == 1 && c2 == 1) {
-       wu1 = (sinfo->u2 - sinfo->u1)/2.0;
-       wu2 = (sinfo->u2 - sinfo->u1)/2.0;
-       wv1 = sinfo->v1;
-       wv2 = sinfo->v2;
-       umid = (sinfo->u2 - sinfo->u1)/2.0;
-       vmid = (sinfo->v2 - sinfo->v1)/2.0;
-       line_set = 1;
-    }
-
-    /* v_upper */
-    if (c1 == 2 && c2 == 1) {
-       wu1 = sinfo->u2;
-       wu2 = sinfo->u2;
-       wv1 = sinfo->v1;
-       wv2 = sinfo->v2;
-       umid = sinfo->u2;
-       vmid = (sinfo->v2 - sinfo->v1)/2.0;
-       line_set = 1;
-    }
-
-    if (!line_set) {
-       bu_log("Invalid edge %d, %d specified\n", c1, c2);
-       return DBL_MAX;
-    }
-
-    // 1st 3d point
-    ON_3dPoint p1 = sinfo->s->PointAt(wu1, wv1);
-
-    // middle 3d point
-    ON_3dPoint pmid = sinfo->s->PointAt(umid, vmid);
-
-    // last 3d point
-    ON_3dPoint p2 = sinfo->s->PointAt(wu2, wv2);
-
-    // length
-    double d1 = pmid.DistanceTo(p1);
-    double d2 = p2.DistanceTo(pmid);
-    return d1+d2;
-}
-
-
-
-static void
-getSurfacePoints(struct ON_Brep_CDT_State *s_cdt,
-                const ON_BrepFace &face,
-                ON_2dPointArray &on_surf_points)
-{
-    double surface_width, surface_height;
-
-    const ON_Surface *s = face.SurfaceOf();
-    const ON_Brep *brep = face.Brep();
-
-    if (s->GetSurfaceSize(&surface_width, &surface_height)) {
-       double dist = 0.0;
-       double min_dist = 0.0;
-       double within_dist = 0.0;
-       double  cos_within_ang = 0.0;
-
-       if ((surface_width < s_cdt->dist) || (surface_height < s_cdt->dist)) {
-           return;
-       }
-
-       if (!s_cdt->on2_to_on3_maps[face.m_face_index]) {
-           std::map<ON_2dPoint *, ON_3dPoint *> *on2to3 = new 
std::map<ON_2dPoint *, ON_3dPoint *>();
-           s_cdt->on2_to_on3_maps[face.m_face_index] = on2to3;
-       }
-
-       struct cdt_surf_info sinfo;
-       sinfo.s = s;
-       sinfo.f = &face;
-       sinfo.strim_pnts = s_cdt->strim_pnts;
-       sinfo.strim_norms = s_cdt->strim_norms;
-       double t1, t2;
-       s->GetDomain(0, &t1, &t2);
-       sinfo.ulen = fabs(t2 - t1);
-       s->GetDomain(1, &t1, &t2);
-       sinfo.vlen = fabs(t2 - t1);
-       s->GetDomain(0, &sinfo.u1, &sinfo.u2);
-       s->GetDomain(1, &sinfo.v1, &sinfo.v2);
-       sinfo.u_lower_3dlen = _cdt_get_uv_edge_3d_len(&sinfo, 0, 0);
-       sinfo.u_mid_3dlen   = _cdt_get_uv_edge_3d_len(&sinfo, 1, 0);
-       sinfo.u_upper_3dlen = _cdt_get_uv_edge_3d_len(&sinfo, 2, 0);
-       sinfo.v_lower_3dlen = _cdt_get_uv_edge_3d_len(&sinfo, 0, 1);
-       sinfo.v_mid_3dlen   = _cdt_get_uv_edge_3d_len(&sinfo, 1, 1);
-       sinfo.v_upper_3dlen = _cdt_get_uv_edge_3d_len(&sinfo, 2, 1);
-
-       // may be a smaller trimmed subset of surface so worth getting
-       // face boundary
-       bool bGrowBox = false;
-       ON_3dPoint min, max;
-       for (int li = 0; li < face.LoopCount(); li++) {
-           for (int ti = 0; ti < face.Loop(li)->TrimCount(); ti++) {
-               const ON_BrepTrim *trim = face.Loop(li)->Trim(ti);
-               trim->GetBoundingBox(min, max, bGrowBox);
-               bGrowBox = true;
-           }
-       }
-
-       ON_BoundingBox tight_bbox;
-       if (brep->GetTightBoundingBox(tight_bbox)) {
-           // Note: this needs to be based on the smallest dimension of the
-           // box, not the diagonal, in case we've got something really long
-           // and narrow.
-           fastf_t d1 = tight_bbox.m_max[0] - tight_bbox.m_min[0];
-           fastf_t d2 = tight_bbox.m_max[1] - tight_bbox.m_min[1];
-           dist = (d1 < d2) ? d1 : d2;
-       }
-
-       if (s_cdt->abs < s_cdt->dist + ON_ZERO_TOLERANCE) {
-           min_dist = s_cdt->dist;
-       } else {
-           min_dist = s_cdt->abs;
-       }
-
-       double rel = 0.0;
-       if (s_cdt->rel > 0.0 + ON_ZERO_TOLERANCE) {
-           rel = s_cdt->rel * dist;
-           within_dist = rel < min_dist ? min_dist : rel;
-           //if (s_cdt->abs < s_cdt->dist + ON_ZERO_TOLERANCE) {
-           //    min_dist = within_dist;
-           //}
-       } else if ((s_cdt->abs > 0.0 + ON_ZERO_TOLERANCE)
-                  && (s_cdt->norm < 0.0 + ON_ZERO_TOLERANCE)) {
-           within_dist = min_dist;
-       } else if ((s_cdt->abs > 0.0 + ON_ZERO_TOLERANCE)
-                  || (s_cdt->norm > 0.0 + ON_ZERO_TOLERANCE)) {
-           within_dist = dist;
-       } else {
-           within_dist = 0.01 * dist; // default to 1% minimum surface distance
-       }
-
-       if (s_cdt->norm > 0.0 + ON_ZERO_TOLERANCE) {
-           cos_within_ang = cos(s_cdt->norm);
-       } else {
-           cos_within_ang = cos(ON_PI / 2.0);
-       }
-       ON_BOOL32 uclosed = s->IsClosed(0);
-       ON_BOOL32 vclosed = s->IsClosed(1);
-       if (uclosed && vclosed) {
-           ON_2dPoint p(0.0, 0.0);
-           double midx = (min.x + max.x) / 2.0;
-           double midy = (min.y + max.y) / 2.0;
-
-           //bottom left
-           p.Set(min.x, min.y);
-           on_surf_points.Append(p);
-
-           //midy left
-           p.Set(min.x, midy);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, midx, min.y, midy, min_dist, 
within_dist,
-                            cos_within_ang, on_surf_points, true, true);
-
-           //bottom midx
-           p.Set(midx, min.y);
-           on_surf_points.Append(p);
-
-           //midx midy
-           p.Set(midx, midy);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, midx, max.x, min.y, midy, min_dist, 
within_dist,
-                            cos_within_ang, on_surf_points, false, true);
-
-           //bottom right
-           p.Set(max.x, min.y);
-           on_surf_points.Append(p);
-
-           //right  midy
-           p.Set(max.x, midy);
-           on_surf_points.Append(p);
-
-           //top left
-           p.Set(min.x, max.y);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, midx, midy, max.y, min_dist, 
within_dist,
-                            cos_within_ang, on_surf_points, true, false);
-
-           //top midx
-           p.Set(midx, max.y);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, midx, max.x, midy, max.y, min_dist, 
within_dist,
-                            cos_within_ang, on_surf_points, false, false);
-
-           //top left
-           p.Set(max.x, max.y);
-           on_surf_points.Append(p);
-       } else if (uclosed) {
-           ON_2dPoint p(0.0, 0.0);
-           double midx = (min.x + max.x) / 2.0;
-
-           //bottom left
-           p.Set(min.x, min.y);
-           on_surf_points.Append(p);
-
-           //top left
-           p.Set(min.x, max.y);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, midx, min.y, max.y, min_dist,
-                            within_dist, cos_within_ang, on_surf_points, true, 
true);
-
-           //bottom midx
-           p.Set(midx, min.y);
-           on_surf_points.Append(p);
-
-           //top midx
-           p.Set(midx, max.y);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, midx, max.x, min.y, max.y, min_dist,
-                            within_dist, cos_within_ang, on_surf_points, 
false, true);
-
-           //bottom right
-           p.Set(max.x, min.y);
-           on_surf_points.Append(p);
-
-           //top right
-           p.Set(max.x, max.y);
-           on_surf_points.Append(p);
-       } else if (vclosed) {
-           ON_2dPoint p(0.0, 0.0);
-           double midy = (min.y + max.y) / 2.0;
-
-           //bottom left
-           p.Set(min.x, min.y);
-           on_surf_points.Append(p);
-
-           //left midy
-           p.Set(min.x, midy);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, max.x, min.y, midy, min_dist,
-                            within_dist, cos_within_ang, on_surf_points, true, 
true);
-
-           //bottom right
-           p.Set(max.x, min.y);
-           on_surf_points.Append(p);
-
-           //right midy
-           p.Set(max.x, midy);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, max.x, midy, max.y, min_dist,
-                            within_dist, cos_within_ang, on_surf_points, true, 
false);
-
-           // top left
-           p.Set(min.x, max.y);
-           on_surf_points.Append(p);
-
-           //top right
-           p.Set(max.x, max.y);
-           on_surf_points.Append(p);
-       } else {
-           ON_2dPoint p(0.0, 0.0);
-
-           //bottom left
-           p.Set(min.x, min.y);
-           on_surf_points.Append(p);
-
-           //top left
-           p.Set(min.x, max.y);
-           on_surf_points.Append(p);
-
-           getSurfacePoints(s_cdt, &sinfo, min.x, max.x, min.y, max.y, 
min_dist,
-                            within_dist, cos_within_ang, on_surf_points, true, 
true);
-
-           //bottom right
-           p.Set(max.x, min.y);
-           on_surf_points.Append(p);
-
-           //top right
-           p.Set(max.x, max.y);
-           on_surf_points.Append(p);
-       }
-    }
-}
-
-
-static void
-getUVCurveSamples(
-                 const ON_Surface *s,
-                 const ON_Curve *curve,
-                 fastf_t t1,
-                 const ON_3dPoint &start_2d,
-                 const ON_3dVector &start_tang,
-                 const ON_3dPoint &start_3d,
-                 const ON_3dVector &start_norm,
-                 fastf_t t2,
-                 const ON_3dPoint &end_2d,
-                 const ON_3dVector &end_tang,
-                 const ON_3dPoint &end_3d,
-                 const ON_3dVector &end_norm,
-                 fastf_t min_dist,
-                 fastf_t max_dist,
-                 fastf_t within_dist,
-                 fastf_t cos_within_ang,
-                 std::map<double, ON_3dPoint *> &param_points)
-{
-    ON_Interval range = curve->Domain();
-    ON_3dPoint mid_2d(0.0, 0.0, 0.0);
-    ON_3dPoint mid_3d(0.0, 0.0, 0.0);
-    ON_3dVector mid_norm(0.0, 0.0, 0.0);
-    ON_3dVector mid_tang(0.0, 0.0, 0.0);
-    fastf_t t = (t1 + t2) / 2.0;
-
-    if (curve->EvTangent(t, mid_2d, mid_tang)
-       && surface_EvNormal(s, mid_2d.x, mid_2d.y, mid_3d, mid_norm)) {
-       ON_Line line3d(start_3d, end_3d);
-       double dist3d;
-
-       if ((line3d.Length() > max_dist)
-           || ((dist3d = mid_3d.DistanceTo(line3d.ClosestPointTo(mid_3d)))
-               > within_dist + ON_ZERO_TOLERANCE)
-           || ((((start_tang * end_tang)
-                 < cos_within_ang - ON_ZERO_TOLERANCE)
-                || ((start_norm * end_norm)
-                    < cos_within_ang - ON_ZERO_TOLERANCE))
-               && (dist3d > min_dist + ON_ZERO_TOLERANCE))) {
-           getUVCurveSamples(s, curve, t1, start_2d, start_tang, start_3d, 
start_norm,
-                             t, mid_2d, mid_tang, mid_3d, mid_norm, min_dist, 
max_dist,
-                             within_dist, cos_within_ang, param_points);
-           param_points[(t - range.m_t[0]) / (range.m_t[1] - range.m_t[0])] =
-               new ON_3dPoint(mid_3d);
-           getUVCurveSamples(s, curve, t, mid_2d, mid_tang, mid_3d, mid_norm, 
t2,
-                             end_2d, end_tang, end_3d, end_norm, min_dist, 
max_dist,
-                             within_dist, cos_within_ang, param_points);
-       }
-    }
-}
-
-
-static std::map<double, ON_3dPoint *> *
-getUVCurveSamples(struct ON_Brep_CDT_State *s_cdt,
-                 const ON_Surface *surf,
-                 const ON_Curve *curve,
-                 fastf_t max_dist)
-{
-    fastf_t min_dist, within_dist, cos_within_ang;
-
-    double dist = 1000.0;
-
-    bool bGrowBox = false;
-    ON_3dPoint min, max;
-    if (curve->GetBoundingBox(min, max, bGrowBox)) {
-       dist = DIST_PT_PT(min, max);
-    }
-
-    if (s_cdt->abs < s_cdt->dist + ON_ZERO_TOLERANCE) {
-       min_dist = s_cdt->dist;
-    } else {
-       min_dist = s_cdt->abs;
-    }
-
-    double rel = 0.0;
-    if (s_cdt->rel > 0.0 + ON_ZERO_TOLERANCE) {
-       rel = s_cdt->rel * dist;
-       if (max_dist < rel * 10.0) {
-           max_dist = rel * 10.0;
-       }
-       within_dist = rel < min_dist ? min_dist : rel;
-    } else if (s_cdt->abs > 0.0 + ON_ZERO_TOLERANCE) {
-       within_dist = min_dist;
-    } else {
-       within_dist = 0.01 * dist; // default to 1% minimum surface distance
-    }
-
-    if (s_cdt->norm > 0.0 + ON_ZERO_TOLERANCE) {
-       cos_within_ang = cos(s_cdt->norm);
-    } else {
-       cos_within_ang = cos(ON_PI / 2.0);
-    }
-
-    std::map<double, ON_3dPoint *> *param_points = new std::map<double, 
ON_3dPoint *>();
-    ON_Interval range = curve->Domain();
-
-    if (curve->IsClosed()) {
-       double mid_range = (range.m_t[0] + range.m_t[1]) / 2.0;
-       ON_3dPoint start_2d(0.0, 0.0, 0.0);
-       ON_3dPoint start_3d(0.0, 0.0, 0.0);
-       ON_3dVector start_tang(0.0, 0.0, 0.0);
-       ON_3dVector start_norm(0.0, 0.0, 0.0);
-       ON_3dPoint mid_2d(0.0, 0.0, 0.0);
-       ON_3dPoint mid_3d(0.0, 0.0, 0.0);
-       ON_3dVector mid_tang(0.0, 0.0, 0.0);
-       ON_3dVector mid_norm(0.0, 0.0, 0.0);
-       ON_3dPoint end_2d(0.0, 0.0, 0.0);
-       ON_3dPoint end_3d(0.0, 0.0, 0.0);
-       ON_3dVector end_tang(0.0, 0.0, 0.0);
-       ON_3dVector end_norm(0.0, 0.0, 0.0);
-
-       if (curve->EvTangent(range.m_t[0], start_2d, start_tang)
-           && curve->EvTangent(mid_range, mid_2d, mid_tang)
-           && curve->EvTangent(range.m_t[1], end_2d, end_tang)
-           && surface_EvNormal(surf, mid_2d.x, mid_2d.y, mid_3d, mid_norm)
-           && surface_EvNormal(surf, start_2d.x, start_2d.y, start_3d, 
start_norm)
-           && surface_EvNormal(surf, end_2d.x, end_2d.y, end_3d, end_norm))
-       {
-           (*param_points)[0.0] = new ON_3dPoint(
-               surf->PointAt(curve->PointAt(range.m_t[0]).x,
-                             curve->PointAt(range.m_t[0]).y));
-           getUVCurveSamples(surf, curve, range.m_t[0], start_2d, start_tang,
-                             start_3d, start_norm, mid_range, mid_2d, mid_tang,
-                             mid_3d, mid_norm, min_dist, max_dist, within_dist,
-                             cos_within_ang, *param_points);
-           (*param_points)[0.5] = new ON_3dPoint(
-               surf->PointAt(curve->PointAt(mid_range).x,
-                             curve->PointAt(mid_range).y));
-           getUVCurveSamples(surf, curve, mid_range, mid_2d, mid_tang, mid_3d,
-                             mid_norm, range.m_t[1], end_2d, end_tang, end_3d,
-                             end_norm, min_dist, max_dist, within_dist,
-                             cos_within_ang, *param_points);
-           (*param_points)[1.0] = new ON_3dPoint(
-               surf->PointAt(curve->PointAt(range.m_t[1]).x,
-                             curve->PointAt(range.m_t[1]).y));
-       }
-    } else {
-       ON_3dPoint start_2d(0.0, 0.0, 0.0);
-       ON_3dPoint start_3d(0.0, 0.0, 0.0);
-       ON_3dVector start_tang(0.0, 0.0, 0.0);
-       ON_3dVector start_norm(0.0, 0.0, 0.0);
-       ON_3dPoint end_2d(0.0, 0.0, 0.0);
-       ON_3dPoint end_3d(0.0, 0.0, 0.0);
-       ON_3dVector end_tang(0.0, 0.0, 0.0);
-       ON_3dVector end_norm(0.0, 0.0, 0.0);
-
-       if (curve->EvTangent(range.m_t[0], start_2d, start_tang)
-           && curve->EvTangent(range.m_t[1], end_2d, end_tang)
-           && surface_EvNormal(surf, start_2d.x, start_2d.y, start_3d, 
start_norm)
-           && surface_EvNormal(surf, end_2d.x, end_2d.y, end_3d, end_norm))
-       {
-           (*param_points)[0.0] = new ON_3dPoint(start_3d);
-           getUVCurveSamples(surf, curve, range.m_t[0], start_2d, start_tang,
-                             start_3d, start_norm, range.m_t[1], end_2d, 
end_tang,
-                             end_3d, end_norm, min_dist, max_dist, within_dist,
-                             cos_within_ang, *param_points);
-           (*param_points)[1.0] = new ON_3dPoint(end_3d);
-       }
-    }
-
-
-    return param_points;
-}
-
-
-/*
- * number_of_seam_crossings
- */
-static int
-number_of_seam_crossings(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_trim_points)
-{
-    int rc = 0;
-    const ON_2dPoint *prev_non_seam_pt = NULL;
-    for (int i = 0; i < brep_trim_points.Count(); i++) {
-       const ON_2dPoint *pt = &brep_trim_points[i].p2d;
-       if (!IsAtSeam(surf, *pt, BREP_SAME_POINT_TOLERANCE)) {
-           int udir = 0;
-           int vdir = 0;
-           if (prev_non_seam_pt != NULL) {
-               if (ConsecutivePointsCrossClosedSeam(surf, *prev_non_seam_pt, 
*pt, udir, vdir, BREP_SAME_POINT_TOLERANCE)) {
-                   rc++;
-               }
-           }
-           prev_non_seam_pt = pt;
-       }
-    }
-
-    return rc;
-}
-
-
-static bool
-LoopStraddlesDomain(const ON_Surface *surf,  ON_SimpleArray<BrepTrimPoint> 
&brep_loop_points)
-{
-    if (surf->IsClosed(0) || surf->IsClosed(1)) {
-       int num_crossings = number_of_seam_crossings(surf, brep_loop_points);
-       if (num_crossings == 1) {
-           return true;
-       }
-    }
-    return false;
-}
-
-
-/*
- * entering - 1
- * exiting - 2
- * contained - 0
- */
-static int
-is_entering(const ON_Surface *surf,  const ON_SimpleArray<BrepTrimPoint> 
&brep_loop_points)
-{
-    int numpoints = brep_loop_points.Count();
-    for (int i = 1; i < numpoints - 1; i++) {
-       int seam = 0;
-       ON_2dPoint p = brep_loop_points[i].p2d;
-       if ((seam = IsAtSeam(surf, p, BREP_SAME_POINT_TOLERANCE)) > 0) {
-           ON_2dPoint unwrapped = UnwrapUVPoint(surf, p, 
BREP_SAME_POINT_TOLERANCE);
-           if (seam == 1) {
-               bool right_seam = unwrapped.x > surf->Domain(0).Mid();
-               bool decreasing = (brep_loop_points[numpoints - 1].p2d.x - 
brep_loop_points[0].p2d.x) < 0;
-               if (right_seam != decreasing) { // basically XOR'ing here
-                   return 2;
-               } else {
-                   return 1;
-               }
-           } else {
-               bool top_seam = unwrapped.y > surf->Domain(1).Mid();
-               bool decreasing = (brep_loop_points[numpoints - 1].p2d.y - 
brep_loop_points[0].p2d.y) < 0;
-               if (top_seam != decreasing) { // basically XOR'ing here
-                   return 2;
-               } else {
-                   return 1;
-               }
-           }
-       }
-    }
-    return 0;
-}
-
-/*
- * shift_closed_curve_split_over_seam
- */
-static bool
-shift_loop_straddled_over_seam(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_loop_points, double same_point_tolerance)
-{
-    if (surf->IsClosed(0) || surf->IsClosed(1)) {
-       ON_Interval dom[2];
-       int entering = is_entering(surf, brep_loop_points);
-
-       dom[0] = surf->Domain(0);
-       dom[1] = surf->Domain(1);
-
-       int seam = 0;
-       int i;
-       BrepTrimPoint btp;
-       BrepTrimPoint end_btp;
-       ON_SimpleArray<BrepTrimPoint> part1;
-       ON_SimpleArray<BrepTrimPoint> part2;
-
-       end_btp.p2d = ON_2dPoint::UnsetPoint;
-       int numpoints = brep_loop_points.Count();
-       bool first_seam_pt = true;
-       for (i = 0; i < numpoints; i++) {
-           btp = brep_loop_points[i];
-           if ((seam = IsAtSeam(surf, btp.p2d, same_point_tolerance)) > 0) {
-               if (first_seam_pt) {
-                   part1.Append(btp);
-                   first_seam_pt = false;
-               }
-               end_btp = btp;
-               SwapUVSeamPoint(surf, end_btp.p2d);
-               part2.Append(end_btp);
-           } else {
-               if (dom[0].Includes(btp.p2d.x, false) && 
dom[1].Includes(btp.p2d.y, false)) {
-                   part1.Append(brep_loop_points[i]);
-               } else {
-                   btp = brep_loop_points[i];
-                   btp.p2d = UnwrapUVPoint(surf, brep_loop_points[i].p2d, 
same_point_tolerance);
-                   part2.Append(btp);
-               }
-           }
-       }
-
-       brep_loop_points.Empty();
-       if (entering == 1) {
-           brep_loop_points.Append(part1.Count() - 1, part1.Array());
-           brep_loop_points.Append(part2.Count(), part2.Array());
-       } else {
-           brep_loop_points.Append(part2.Count() - 1, part2.Array());
-           brep_loop_points.Append(part1.Count(), part1.Array());
-       }
-    }
-    return true;
-}
-
-
-/*
- * extend_over_seam_crossings
- */
-static bool
-extend_over_seam_crossings(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_loop_points)
-{
-    int num_points = brep_loop_points.Count();
-    double ulength = surf->Domain(0).Length();
-    double vlength = surf->Domain(1).Length();
-    for (int i = 1; i < num_points; i++) {
-       if (surf->IsClosed(0)) {
-           double delta = brep_loop_points[i].p2d.x - brep_loop_points[i - 
1].p2d.x;
-           while (fabs(delta) > ulength / 2.0) {
-               if (delta < 0.0) {
-                   brep_loop_points[i].p2d.x += ulength; // east bound
-               } else {
-                   brep_loop_points[i].p2d.x -= ulength;; // west bound
-               }
-               delta = brep_loop_points[i].p2d.x - brep_loop_points[i - 
1].p2d.x;
-           }
-       }
-       if (surf->IsClosed(1)) {
-           double delta = brep_loop_points[i].p2d.y - brep_loop_points[i - 
1].p2d.y;
-           while (fabs(delta) > vlength / 2.0) {
-               if (delta < 0.0) {
-                   brep_loop_points[i].p2d.y += vlength; // north bound
-               } else {
-                   brep_loop_points[i].p2d.y -= vlength;; // south bound
-               }
-               delta = brep_loop_points[i].p2d.y - brep_loop_points[i - 
1].p2d.y;
-           }
-       }
-    }
-
-    return true;
-}
-
-static void
 get_loop_sample_points(
        struct ON_Brep_CDT_State *s_cdt,
        ON_SimpleArray<BrepTrimPoint> *points,
@@ -1984,647 +119,6 @@
 }
 
 
-/* force near seam points to seam */
-static void
-ForceNearSeamPointsToSeam(
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
-       double same_point_tolerance)
-{
-    int loop_cnt = face.LoopCount();
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 1) {
-           for (int i = 0; i < num_loop_points; i++) {
-               ON_2dPoint &p = brep_loop_points[li][i].p2d;
-               if (IsAtSeam(s, p, same_point_tolerance)) {
-                   ForceToClosestSeam(s, p, same_point_tolerance);
-               }
-           }
-       }
-    }
-}
-
-
-static void
-ExtendPointsOverClosedSeam(
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points)
-{
-    int loop_cnt = face.LoopCount();
-    // extend loop points over seam if needed.
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 1) {
-           if (!extend_over_seam_crossings(s, brep_loop_points[li])) {
-               std::cerr << "Error: Face(" << face.m_face_index << ") cannot 
extend loops over closed seams." << std::endl;
-           }
-       }
-    }
-}
-
-
-// process through loops checking for straddle condition.
-static void
-ShiftLoopsThatStraddleSeam(
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
-       double same_point_tolerance)
-{
-    int loop_cnt = face.LoopCount();
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 1) {
-           ON_2dPoint brep_loop_begin = brep_loop_points[li][0].p2d;
-           ON_2dPoint brep_loop_end = brep_loop_points[li][num_loop_points - 
1].p2d;
-
-           if (!V2NEAR_EQUAL(brep_loop_begin, brep_loop_end, 
same_point_tolerance)) {
-               if (LoopStraddlesDomain(s, brep_loop_points[li])) {
-                   // reorder loop points
-                   shift_loop_straddled_over_seam(s, brep_loop_points[li], 
same_point_tolerance);
-               }
-           }
-       }
-    }
-}
-
-
-// process through closing open loops that begin and end on closed seam
-static void
-CloseOpenLoops(
-       struct ON_Brep_CDT_State *s_cdt,
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
-       double same_point_tolerance)
-{
-    std::list<std::map<double, ON_3dPoint *> *> bridgePoints;
-    int loop_cnt = face.LoopCount();
-    for (int li = 0; li < loop_cnt; li++) {
-       int num_loop_points = brep_loop_points[li].Count();
-       if (num_loop_points > 1) {
-           ON_2dPoint brep_loop_begin = brep_loop_points[li][0].p2d;
-           ON_2dPoint brep_loop_end = brep_loop_points[li][num_loop_points - 
1].p2d;
-           ON_3dPoint brep_loop_begin3d = s->PointAt(brep_loop_begin.x, 
brep_loop_begin.y);
-           ON_3dPoint brep_loop_end3d = s->PointAt(brep_loop_end.x, 
brep_loop_end.y);
-
-           if (!V2NEAR_EQUAL(brep_loop_begin, brep_loop_end, 
same_point_tolerance) &&
-               VNEAR_EQUAL(brep_loop_begin3d, brep_loop_end3d, 
same_point_tolerance)) {
-               int seam_begin = 0;
-               int seam_end = 0;
-               if ((seam_begin = IsAtSeam(s, brep_loop_begin, 
same_point_tolerance)) &&
-                   (seam_end = IsAtSeam(s, brep_loop_end, 
same_point_tolerance))) {
-                   bool loop_not_closed = true;
-                   if ((li + 1) < loop_cnt) {
-                       // close using remaining loops
-                       for (int rli = li + 1; rli < loop_cnt; rli++) {
-                           int rnum_loop_points = 
brep_loop_points[rli].Count();
-                           ON_2dPoint rbrep_loop_begin = 
brep_loop_points[rli][0].p2d;
-                           ON_2dPoint rbrep_loop_end = 
brep_loop_points[rli][rnum_loop_points - 1].p2d;
-                           if (!V2NEAR_EQUAL(rbrep_loop_begin, rbrep_loop_end, 
same_point_tolerance)) {
-                               if (IsAtSeam(s, rbrep_loop_begin, 
same_point_tolerance) && IsAtSeam(s, rbrep_loop_end, same_point_tolerance)) {
-                                   double t0, t1;
-                                   ON_LineCurve line1(brep_loop_end, 
rbrep_loop_begin);
-                                   std::map<double, ON_3dPoint *> 
*linepoints3d = getUVCurveSamples(s_cdt, s, &line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   std::map<double, 
ON_3dPoint*>::const_iterator i;
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   
//brep_loop_points[li].Append(brep_loop_points[rli].Count(),brep_loop_points[rli].Array());
-                                   for (int j = 1; j < rnum_loop_points; j++) {
-                                       
brep_loop_points[li].Append(brep_loop_points[rli][j]);
-                                   }
-                                   ON_LineCurve line2(rbrep_loop_end, 
brep_loop_begin);
-                                   linepoints3d = getUVCurveSamples(s_cdt, s, 
&line2, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line2.GetDomain(&t0, &t1);
-
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line2.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   brep_loop_points[rli].Empty();
-                                   loop_not_closed = false;
-                               }
-                           }
-                       }
-                   }
-                   if (loop_not_closed) {
-                       // no matching loops found that would close so use 
domain boundary
-                       ON_Interval u = s->Domain(0);
-                       ON_Interval v = s->Domain(1);
-                       if (seam_end == 1) {
-                           if (NEAR_EQUAL(brep_loop_end.x, u.m_t[0], 
same_point_tolerance)) {
-                               // low end so decreasing
-
-                               // now where do we have to close to
-                               if (seam_begin == 1) {
-                                   // has to be on opposite seam
-                                   double t0, t1;
-                                   ON_2dPoint p = brep_loop_end;
-                                   p.y = v.m_t[0];
-                                   ON_LineCurve line1(brep_loop_end, p);
-                                   std::map<double, ON_3dPoint *> 
*linepoints3d = getUVCurveSamples(s_cdt, s, &line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   std::map<double, 
ON_3dPoint*>::const_iterator i;
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   line1.SetStartPoint(p);
-                                   p.x = u.m_t[1];
-                                   line1.SetEndPoint(p);
-                                   linepoints3d = getUVCurveSamples(s_cdt, s, 
&line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   line1.SetStartPoint(p);
-                                   line1.SetEndPoint(brep_loop_begin);
-                                   linepoints3d = getUVCurveSamples(s_cdt, s, 
&line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-
-                               } else if (seam_begin == 2) {
-
-                               } else {
-                                   //both needed
-                               }
-
-                           } else { //assume on other end
-                               // high end so increasing
-                               // now where do we have to close to
-                               if (seam_begin == 1) {
-                                   // has to be on opposite seam
-                                   double t0, t1;
-                                   ON_2dPoint p = brep_loop_end;
-                                   p.y = v.m_t[1];
-                                   ON_LineCurve line1(brep_loop_end, p);
-                                   std::map<double, ON_3dPoint *> 
*linepoints3d = getUVCurveSamples(s_cdt, s, &line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   std::map<double, 
ON_3dPoint*>::const_iterator i;
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   line1.SetStartPoint(p);
-                                   p.x = u.m_t[0];
-                                   line1.SetEndPoint(p);
-                                   linepoints3d = getUVCurveSamples(s_cdt, s, 
&line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                                   line1.SetStartPoint(p);
-                                   line1.SetEndPoint(brep_loop_begin);
-                                   linepoints3d = getUVCurveSamples(s_cdt, s, 
&line1, 1000.0);
-                                   bridgePoints.push_back(linepoints3d);
-                                   line1.GetDomain(&t0, &t1);
-                                   for (i = linepoints3d->begin();
-                                        i != linepoints3d->end(); i++) {
-                                       BrepTrimPoint btp;
-
-                                       // skips first point
-                                       if (i == linepoints3d->begin())
-                                           continue;
-
-                                       btp.t = (*i).first;
-                                       btp.p3d = (*i).second;
-                                       btp.p2d = line1.PointAt(t0 + (t1 - t0) 
* btp.t);
-                                       btp.e = ON_UNSET_VALUE;
-                                       brep_loop_points[li].Append(btp);
-                                   }
-                               } else if (seam_begin == 2) {
-
-                               } else {
-                                   //both
-                               }
-                           }
-                       } else if (seam_end == 2) {
-                           if (NEAR_EQUAL(brep_loop_end.y, v.m_t[0], 
same_point_tolerance)) {
-
-                           } else { //assume on other end
-
-                           }
-                       } else {
-                           //both
-                       }
-                   }
-               }
-           }
-       }
-    }
-}
-
-
-/*
- * lifted from Clipper private function and rework for brep_loop_points
- */
-static bool
-PointInPolygon(const ON_2dPoint &pt, ON_SimpleArray<BrepTrimPoint> 
&brep_loop_points)
-{
-    bool result = false;
-
-    for( int i = 0; i < brep_loop_points.Count(); i++){
-       ON_2dPoint curr_pt = brep_loop_points[i].p2d;
-       ON_2dPoint prev_pt = ON_2dPoint::UnsetPoint;
-       if (i == 0) {
-           prev_pt = brep_loop_points[brep_loop_points.Count()-1].p2d;
-       } else {
-           prev_pt = brep_loop_points[i-1].p2d;
-       }
-       if ((((curr_pt.y <= pt.y) && (pt.y < prev_pt.y)) ||
-               ((prev_pt.y <= pt.y) && (pt.y < curr_pt.y))) &&
-               (pt.x < (prev_pt.x - curr_pt.x) * (pt.y - curr_pt.y) /
-                       (prev_pt.y - curr_pt.y) + curr_pt.x ))
-           result = !result;
-    }
-    return result;
-}
-
-
-static void
-ShiftPoints(ON_SimpleArray<BrepTrimPoint> &brep_loop_points, double ushift, 
double vshift)
-{
-    for( int i = 0; i < brep_loop_points.Count(); i++){
-       brep_loop_points[i].p2d.x += ushift;
-       brep_loop_points[i].p2d.y += vshift;
-    }
-}
-
-
-// process through to make sure inner hole loops are actually inside of outer 
polygon
-// need to make sure that any hole polygons are properly shifted over correct 
closed seams
-// going to try and do an inside test on hole vertex
-static void
-ShiftInnerLoops(
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points)
-{
-    int loop_cnt = face.LoopCount();
-    if (loop_cnt > 1) { // has inner loops or holes
-       for( int li = 1; li < loop_cnt; li++) {
-           ON_2dPoint p2d((brep_loop_points[li])[0].p2d.x, 
(brep_loop_points[li])[0].p2d.y);
-           if (!PointInPolygon(p2d, brep_loop_points[0])) {
-               double ulength = s->Domain(0).Length();
-               double vlength = s->Domain(1).Length();
-               ON_2dPoint sftd_pt = p2d;
-
-               //do shift until inside
-               if (s->IsClosed(0) && s->IsClosed(1)) {
-                   // First just U
-                   for(int iu = 0; iu < 2; iu++) {
-                       double ushift = 0.0;
-                       if (iu == 0) {
-                           ushift = -ulength;
-                       } else {
-                           ushift =  ulength;
-                       }
-                       sftd_pt.x = p2d.x + ushift;
-                       if (PointInPolygon(sftd_pt, brep_loop_points[0])) {
-                           // shift all U accordingly
-                           ShiftPoints(brep_loop_points[li], ushift, 0.0);
-                           break;
-                       }
-                   }
-                   // Second just V
-                   for(int iv = 0; iv < 2; iv++) {
-                       double vshift = 0.0;
-                       if (iv == 0) {
-                           vshift = -vlength;
-                       } else {
-                           vshift = vlength;
-                       }
-                       sftd_pt.y = p2d.y + vshift;
-                       if (PointInPolygon(sftd_pt, brep_loop_points[0])) {
-                           // shift all V accordingly
-                           ShiftPoints(brep_loop_points[li], 0.0, vshift);
-                           break;
-                       }
-                   }
-                   // Third both U & V
-                   for(int iu = 0; iu < 2; iu++) {
-                       double ushift = 0.0;
-                       if (iu == 0) {
-                           ushift = -ulength;
-                       } else {
-                           ushift =  ulength;
-                       }
-                       sftd_pt.x = p2d.x + ushift;
-                       for(int iv = 0; iv < 2; iv++) {
-                           double vshift = 0.0;
-                           if (iv == 0) {
-                               vshift = -vlength;
-                           } else {
-                               vshift = vlength;
-                           }
-                           sftd_pt.y = p2d.y + vshift;
-                           if (PointInPolygon(sftd_pt, brep_loop_points[0])) {
-                               // shift all U & V accordingly
-                               ShiftPoints(brep_loop_points[li], ushift, 
vshift);
-                               break;
-                           }
-                       }
-                   }
-               } else if (s->IsClosed(0)) {
-                   // just U
-                   for(int iu = 0; iu < 2; iu++) {
-                       double ushift = 0.0;
-                       if (iu == 0) {
-                           ushift = -ulength;
-                       } else {
-                           ushift =  ulength;
-                       }
-                       sftd_pt.x = p2d.x + ushift;
-                       if (PointInPolygon(sftd_pt, brep_loop_points[0])) {
-                           // shift all U accordingly
-                           ShiftPoints(brep_loop_points[li], ushift, 0.0);
-                           break;
-                       }
-                   }
-               } else if (s->IsClosed(1)) {
-                   // just V
-                   for(int iv = 0; iv < 2; iv++) {
-                       double vshift = 0.0;
-                       if (iv == 0) {
-                           vshift = -vlength;
-                       } else {
-                           vshift = vlength;
-                       }
-                       sftd_pt.y = p2d.y + vshift;
-                       if (PointInPolygon(sftd_pt, brep_loop_points[0])) {
-                           // shift all V accordingly
-                           ShiftPoints(brep_loop_points[li], 0.0, vshift);
-                           break;
-                       }
-                   }
-               }
-           }
-       }
-    }
-}
-
-
-static void
-PerformClosedSurfaceChecks(
-       struct ON_Brep_CDT_State *s_cdt,
-       const ON_Surface *s,
-       const ON_BrepFace &face,
-       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
-       double same_point_tolerance)
-{
-    // force near seam points to seam.
-    ForceNearSeamPointsToSeam(s, face, brep_loop_points, same_point_tolerance);
-
-    // extend loop points over closed seam if needed.
-    ExtendPointsOverClosedSeam(s, face, brep_loop_points);
-
-    // shift open loops that straddle a closed seam with the intent of closure 
at the surface boundary.
-    ShiftLoopsThatStraddleSeam(s, face, brep_loop_points, 
same_point_tolerance);
-
-    // process through closing open loops that begin and end on closed seam
-    CloseOpenLoops(s_cdt, s, face, brep_loop_points, same_point_tolerance);
-
-    // process through to make sure inner hole loops are actually inside of 
outer polygon
-    // need to make sure that any hole polygons are properly shifted over 
correct closed seams
-    ShiftInnerLoops(s, face, brep_loop_points);
-}
-
-
-
-struct ON_Brep_CDT_State *
-ON_Brep_CDT_Create(void *bv)
-{
-    ON_Brep *brep = (ON_Brep *)bv;
-    struct ON_Brep_CDT_State *cdt = new struct ON_Brep_CDT_State;
-    cdt->brep = brep;
-
-    cdt->w3dpnts = new std::vector<ON_3dPoint *>;
-    cdt->vert_pnts = new std::map<int, ON_3dPoint *>;
-    cdt->w3dnorms = new std::vector<ON_3dPoint *>;
-    cdt->vert_norms = new std::map<int, ON_3dPoint *>;
-    cdt->strim_pnts = new std::map<int,std::map<int, ON_3dPoint *> >;
-    cdt->strim_norms = new std::map<int,std::map<int, ON_3dPoint *> >;
-    cdt->vert_to_on = new std::map<int, ON_3dPoint *>;
-    cdt->edge_pnts = new std::set<ON_3dPoint *>;
-    cdt->brep_face_loop_points = (ON_SimpleArray<BrepTrimPoint> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::map<p2t::Point *, BrepTrimPoint *> 
*), "face loop pnts");
-    cdt->face_degen_pnts = (std::set<p2t::Point *> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::set<p2t::Point *> *), "degenerate 
edge points");
-
-    cdt->p2t_faces = (p2t::CDT **)bu_calloc(brep->m_F.Count(), sizeof(p2t::CDT 
*), "poly2tri triangulations");
-    cdt->p2t_extra_faces = (std::vector<p2t::Triangle *> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::vector<p2t::Triangle *> *), "extra 
p2t faces");
-    cdt->on2_to_on3_maps = (std::map<ON_2dPoint *, ON_3dPoint *> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::map<ON_2dPoint *, ON_3dPoint *> *), 
"ON_2dPoint to ON_3dPoint maps");
-    cdt->tri_to_on3_maps = (std::map<p2t::Point *, ON_3dPoint *> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::map<p2t::Point *, ON_3dPoint *> *), 
"poly2tri point to ON_3dPoint maps");
-    cdt->on3_to_tri_maps = (std::map<ON_3dPoint *, std::set<p2t::Point *>> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::map<ON_3dPoint *, 
std::set<p2t::Point *>> *), "poly2tri point to ON_3dPoint maps");
-    cdt->tri_to_on3_norm_maps = (std::map<p2t::Point *, ON_3dPoint *> 
**)bu_calloc(brep->m_F.Count(), sizeof(std::map<p2t::Point *, ON_3dPoint *> *), 
"poly2tri point to ON_3dVector normal maps");
-
-    /* Set status to "never evaluated" */
-    cdt->status = BREP_CDT_UNTESSELLATED;
-
-    /* Set sane default tolerances.  May want to do
-     * something better (perhaps brep dimension based...) */
-    cdt->abs = BREP_CDT_DEFAULT_TOL_ABS;
-    cdt->rel = BREP_CDT_DEFAULT_TOL_REL ;
-    cdt->norm = BREP_CDT_DEFAULT_TOL_NORM ;
-    cdt->dist = BREP_CDT_DEFAULT_TOL_DIST ;
-
-    return cdt;
-}
-
-void
-ON_Brep_CDT_Destroy(struct ON_Brep_CDT_State *s_cdt)
-{
-    for (size_t i = 0; i < s_cdt->w3dpnts->size(); i++) {
-       delete (*(s_cdt->w3dpnts))[i];
-    }
-    for (size_t i = 0; i < s_cdt->w3dnorms->size(); i++) {
-       delete (*(s_cdt->w3dnorms))[i];
-    }
-
-    for (int i = 0; i < s_cdt->brep->m_F.Count(); i++) {
-       std::vector<p2t::Triangle *> *ef = s_cdt->p2t_extra_faces[i];
-       if (ef) {
-           std::vector<p2t::Triangle *>::iterator trit;
-           for (trit = ef->begin(); trit != ef->end(); trit++) {
-               p2t::Triangle *t = *trit;
-               delete t;
-           }
-       }
-    }
-
-    for (int i = 0; i < s_cdt->brep->m_F.Count(); i++) {
-       if (s_cdt->brep_face_loop_points[i] != NULL) {
-           delete [] s_cdt->brep_face_loop_points[i];
-       }
-       if (s_cdt->face_degen_pnts[i] != NULL) {
-           delete s_cdt->face_degen_pnts[i];
-       }
-    }
-
-    for (int i = 0; i < s_cdt->brep->m_F.Count(); i++) {
-       if (s_cdt->on2_to_on3_maps[i] != NULL) {
-           delete s_cdt->on2_to_on3_maps[i];
-       }
-    }
-    bu_free(s_cdt->on2_to_on3_maps, "degen pnts");
-
-    delete s_cdt->w3dpnts;
-    delete s_cdt->vert_pnts;
-    delete s_cdt->w3dnorms;
-    delete s_cdt->vert_norms;
-    delete s_cdt->strim_pnts;
-    delete s_cdt->strim_norms;
-    delete s_cdt->vert_to_on;
-    delete s_cdt->edge_pnts;
-    delete s_cdt->p2t_extra_faces;
-
-    bu_free(s_cdt->brep_face_loop_points, "flp array");
-    bu_free(s_cdt->face_degen_pnts, "degen pnts");
-    // TODO - delete p2t data
-
-    delete s_cdt;
-}
-
-int
-ON_Brep_CDT_Status(struct ON_Brep_CDT_State *s_cdt)
-{
-    return s_cdt->status;
-}
-
-
-void *
-ON_Brep_CDT_Brep(struct ON_Brep_CDT_State *s_cdt)
-{
-    return (void *)s_cdt->brep;
-}
-
-void
-ON_Brep_CDT_Tol_Set(struct ON_Brep_CDT_State *s, const struct ON_Brep_CDT_Tols 
*t)
-{
-    if (!s) {
-       return;
-    }
-
-    if (!t) {
-       /* reset to defaults */
-       s->abs = BREP_CDT_DEFAULT_TOL_ABS;
-       s->rel = BREP_CDT_DEFAULT_TOL_REL ;
-       s->norm = BREP_CDT_DEFAULT_TOL_NORM ;
-       s->dist = BREP_CDT_DEFAULT_TOL_DIST ;
-    }
-
-    s->abs = t->abs;
-    s->rel = t->rel;
-    s->norm = t->norm;
-    s->dist = t->dist;
-}
-
-void
-ON_Brep_CDT_Tol_Get(struct ON_Brep_CDT_Tols *t, const struct ON_Brep_CDT_State 
*s)
-{
-    if (!t) {
-       return;
-    }
-
-    if (!s) {
-       /* set to defaults */
-       t->abs = BREP_CDT_DEFAULT_TOL_ABS;
-       t->rel = BREP_CDT_DEFAULT_TOL_REL ;
-       t->norm = BREP_CDT_DEFAULT_TOL_NORM ;
-       t->dist = BREP_CDT_DEFAULT_TOL_DIST ;
-    }
-
-    t->abs = s->abs;
-    t->rel = s->rel;
-    t->norm = s->norm;
-    t->dist = s->dist;
-}
-
 static int
 ON_Brep_CDT_Face(struct ON_Brep_CDT_State *s_cdt, std::map<const ON_Surface *, 
double> *s_to_maxdist, ON_BrepFace &face)
 {

Added: brlcad/trunk/src/libbrep/cdt.h
===================================================================
--- brlcad/trunk/src/libbrep/cdt.h                              (rev 0)
+++ brlcad/trunk/src/libbrep/cdt.h      2019-05-21 18:45:22 UTC (rev 73111)
@@ -0,0 +1,203 @@
+/*                        C D T . H 
+ * 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.h
+ *
+ * Constrained Delaunay Triangulation of NURBS B-Rep objects.
+ *
+ */
+
+#include "common.h"
+
+#include <vector>
+#include <list>
+#include <map>
+#include <stack>
+#include <iostream>
+#include <algorithm>
+#include <set>
+#include <utility>
+
+#include "poly2tri/poly2tri.h"
+
+#include "assert.h"
+
+#include "vmath.h"
+
+#include "bu/color.h"
+#include "bu/cv.h"
+#include "bu/opt.h"
+#include "bu/time.h"
+#include "bn/plot3.h"
+#include "bn/tol.h"
+#include "bn/vlist.h"
+#include "bg/polygon.h"
+#include "bg/trimesh.h"
+#include "brep/defines.h"
+#include "brep/cdt.h"
+#include "brep/pullback.h"
+#include "brep/util.h"
+
+
+/***************************************************/
+typedef std::pair<ON_3dPoint *, ON_3dPoint *> Edge;
+typedef std::map< Edge, std::set<p2t::Triangle*> > EdgeToTri;
+
+#define BREP_CDT_FAILED -3
+#define BREP_CDT_NON_SOLID -2
+#define BREP_CDT_UNTESSELLATED -1
+#define BREP_CDT_SOLID 0
+
+/* Note - these tolerance values are based on the default
+ * values from the GED 'tol' command */
+#define BREP_CDT_DEFAULT_TOL_ABS 0.0
+#define BREP_CDT_DEFAULT_TOL_REL 0.01
+#define BREP_CDT_DEFAULT_TOL_NORM 0.0
+#define BREP_CDT_DEFAULT_TOL_DIST BN_TOL_DIST
+
+/* this is a debugging structure - it holds origin information for
+ * a point added to the CDT state */
+struct cdt_audit_info {
+    int face_index;
+    int vert_index;
+    int trim_index;
+    int edge_index;
+    ON_2dPoint surf_uv;
+};
+
+struct ON_Brep_CDT_State {
+
+    int status;
+    ON_Brep *brep;
+
+    /* Tolerances */
+    fastf_t abs;
+    fastf_t rel;
+    fastf_t norm;
+    fastf_t dist;
+
+    /* 3D data */
+    std::vector<ON_3dPoint *> *w3dpnts;
+    std::map<int, ON_3dPoint *> *vert_pnts;
+    std::vector<ON_3dPoint *> *w3dnorms;
+    std::map<int, ON_3dPoint *> *vert_norms;
+
+    /* singular trim info */
+    std::map<int, std::map<int,ON_3dPoint *>> *strim_pnts;
+    std::map<int, std::map<int,ON_3dPoint *>> *strim_norms;
+
+    /* Poly2Tri data */
+    p2t::CDT **p2t_faces;
+    std::vector<p2t::Triangle *> **p2t_extra_faces;
+    std::map<ON_2dPoint *, ON_3dPoint *> **on2_to_on3_maps;
+    std::map<p2t::Point *, ON_3dPoint *> **tri_to_on3_maps;
+    std::map<p2t::Point *, ON_3dPoint *> **tri_to_on3_norm_maps;
+    std::map<ON_3dPoint *, std::set<p2t::Point *>> **on3_to_tri_maps;
+
+    /* Audit data */
+    std::map<ON_3dPoint *, struct cdt_audit_info *> pnt_audit_info;
+
+    /* BoT -> ON mappings */
+    std::map<ON_3dPoint *, std::set<BrepTrimPoint *>> on_brep_edge_pnts;
+    std::map<int, ON_3dPoint *> *vert_to_on;
+    std::set<ON_3dPoint *> *edge_pnts;
+    ON_SimpleArray<BrepTrimPoint> **brep_face_loop_points;
+    std::set<p2t::Point *> **face_degen_pnts;
+};
+
+struct brep_cdt_tol {
+    fastf_t min_dist;
+    fastf_t max_dist;
+    fastf_t within_dist;
+    fastf_t cos_within_ang;
+};
+#define BREP_CDT_TOL_ZERO {0.0, 0.0, 0.0, 0.0}
+
+struct cdt_surf_info {
+    const ON_Surface *s;
+    const ON_BrepFace *f;
+    std::map<int, std::map<int,ON_3dPoint *>> *strim_pnts;
+    std::map<int, std::map<int,ON_3dPoint *>> *strim_norms;
+    double u1, u2, v1, v2;
+    fastf_t ulen;
+    fastf_t u_lower_3dlen;
+    fastf_t u_mid_3dlen;
+    fastf_t u_upper_3dlen;
+    fastf_t vlen;
+    fastf_t v_lower_3dlen;
+    fastf_t v_mid_3dlen;
+    fastf_t v_upper_3dlen;
+};
+
+
+void
+PerformClosedSurfaceChecks(
+       struct ON_Brep_CDT_State *s_cdt,
+       const ON_Surface *s,
+       const ON_BrepFace &face,
+       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
+       double same_point_tolerance);
+
+std::map<double, BrepTrimPoint *> *
+getEdgePoints(
+       struct ON_Brep_CDT_State *s_cdt,
+       ON_BrepEdge *edge,
+       ON_BrepTrim &trim,
+       fastf_t max_dist,
+       std::map<int, ON_3dPoint *> *vert_pnts,
+       std::map<int, ON_3dPoint *> *vert_norms
+       );
+
+void
+getSurfacePoints(struct ON_Brep_CDT_State *s_cdt,
+                const ON_BrepFace &face,
+                ON_2dPointArray &on_surf_points);
+
+void
+plot_polyline(std::vector<p2t::Point *> *pnts, const char *filename);
+void
+plot_tri(p2t::Triangle *t, const char *filename);
+
+struct cdt_audit_info *
+cdt_ainfo(int fid, int vid, int tid, int eid, fastf_t x2d, fastf_t y2d);
+
+void
+add_tri_edges(EdgeToTri *e2f, p2t::Triangle *t,
+    std::map<p2t::Point *, ON_3dPoint *> *pointmap);
+
+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_Tol_Set(struct brep_cdt_tol *cdt, double dist, fastf_t md, double t_abs, 
double t_rel, double t_norm, double t_dist);
+
+
+/** @} */
+
+// 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
+


Property changes on: brlcad/trunk/src/libbrep/cdt.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: brlcad/trunk/src/libbrep/cdt_closed_surf.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_closed_surf.cpp                                
(rev 0)
+++ brlcad/trunk/src/libbrep/cdt_closed_surf.cpp        2019-05-21 18:45:22 UTC 
(rev 73111)
@@ -0,0 +1,870 @@
+/*                        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 closed surface checks.
+ */
+
+#include "common.h"
+
+#include "./cdt.h"
+
+static void
+getUVCurveSamples(
+                 const ON_Surface *s,
+                 const ON_Curve *curve,
+                 fastf_t t1,
+                 const ON_3dPoint &start_2d,
+                 const ON_3dVector &start_tang,
+                 const ON_3dPoint &start_3d,
+                 const ON_3dVector &start_norm,
+                 fastf_t t2,
+                 const ON_3dPoint &end_2d,
+                 const ON_3dVector &end_tang,
+                 const ON_3dPoint &end_3d,
+                 const ON_3dVector &end_norm,
+                 fastf_t min_dist,
+                 fastf_t max_dist,
+                 fastf_t within_dist,
+                 fastf_t cos_within_ang,
+                 std::map<double, ON_3dPoint *> &param_points)
+{
+    ON_Interval range = curve->Domain();
+    ON_3dPoint mid_2d(0.0, 0.0, 0.0);
+    ON_3dPoint mid_3d(0.0, 0.0, 0.0);
+    ON_3dVector mid_norm(0.0, 0.0, 0.0);
+    ON_3dVector mid_tang(0.0, 0.0, 0.0);
+    fastf_t t = (t1 + t2) / 2.0;
+
+    if (curve->EvTangent(t, mid_2d, mid_tang)
+       && surface_EvNormal(s, mid_2d.x, mid_2d.y, mid_3d, mid_norm)) {
+       ON_Line line3d(start_3d, end_3d);
+       double dist3d;
+
+       if ((line3d.Length() > max_dist)
+           || ((dist3d = mid_3d.DistanceTo(line3d.ClosestPointTo(mid_3d)))
+               > within_dist + ON_ZERO_TOLERANCE)
+           || ((((start_tang * end_tang)
+                 < cos_within_ang - ON_ZERO_TOLERANCE)
+                || ((start_norm * end_norm)
+                    < cos_within_ang - ON_ZERO_TOLERANCE))
+               && (dist3d > min_dist + ON_ZERO_TOLERANCE))) {
+           getUVCurveSamples(s, curve, t1, start_2d, start_tang, start_3d, 
start_norm,
+                             t, mid_2d, mid_tang, mid_3d, mid_norm, min_dist, 
max_dist,
+                             within_dist, cos_within_ang, param_points);
+           param_points[(t - range.m_t[0]) / (range.m_t[1] - range.m_t[0])] =
+               new ON_3dPoint(mid_3d);
+           getUVCurveSamples(s, curve, t, mid_2d, mid_tang, mid_3d, mid_norm, 
t2,
+                             end_2d, end_tang, end_3d, end_norm, min_dist, 
max_dist,
+                             within_dist, cos_within_ang, param_points);
+       }
+    }
+}
+
+
+static std::map<double, ON_3dPoint *> *
+getUVCurveSamples(struct ON_Brep_CDT_State *s_cdt,
+                 const ON_Surface *surf,
+                 const ON_Curve *curve,
+                 fastf_t max_dist)
+{
+    fastf_t min_dist, within_dist, cos_within_ang;
+
+    double dist = 1000.0;
+
+    bool bGrowBox = false;
+    ON_3dPoint min, max;
+    if (curve->GetBoundingBox(min, max, bGrowBox)) {
+       dist = DIST_PT_PT(min, max);
+    }
+
+    if (s_cdt->abs < s_cdt->dist + ON_ZERO_TOLERANCE) {
+       min_dist = s_cdt->dist;
+    } else {
+       min_dist = s_cdt->abs;
+    }
+
+    double rel = 0.0;
+    if (s_cdt->rel > 0.0 + ON_ZERO_TOLERANCE) {
+       rel = s_cdt->rel * dist;
+       if (max_dist < rel * 10.0) {
+           max_dist = rel * 10.0;
+       }
+       within_dist = rel < min_dist ? min_dist : rel;
+    } else if (s_cdt->abs > 0.0 + ON_ZERO_TOLERANCE) {
+       within_dist = min_dist;
+    } else {
+       within_dist = 0.01 * dist; // default to 1% minimum surface distance
+    }
+
+    if (s_cdt->norm > 0.0 + ON_ZERO_TOLERANCE) {
+       cos_within_ang = cos(s_cdt->norm);
+    } else {
+       cos_within_ang = cos(ON_PI / 2.0);
+    }
+
+    std::map<double, ON_3dPoint *> *param_points = new std::map<double, 
ON_3dPoint *>();
+    ON_Interval range = curve->Domain();
+
+    if (curve->IsClosed()) {
+       double mid_range = (range.m_t[0] + range.m_t[1]) / 2.0;
+       ON_3dPoint start_2d(0.0, 0.0, 0.0);
+       ON_3dPoint start_3d(0.0, 0.0, 0.0);
+       ON_3dVector start_tang(0.0, 0.0, 0.0);
+       ON_3dVector start_norm(0.0, 0.0, 0.0);
+       ON_3dPoint mid_2d(0.0, 0.0, 0.0);
+       ON_3dPoint mid_3d(0.0, 0.0, 0.0);
+       ON_3dVector mid_tang(0.0, 0.0, 0.0);
+       ON_3dVector mid_norm(0.0, 0.0, 0.0);
+       ON_3dPoint end_2d(0.0, 0.0, 0.0);
+       ON_3dPoint end_3d(0.0, 0.0, 0.0);
+       ON_3dVector end_tang(0.0, 0.0, 0.0);
+       ON_3dVector end_norm(0.0, 0.0, 0.0);
+
+       if (curve->EvTangent(range.m_t[0], start_2d, start_tang)
+           && curve->EvTangent(mid_range, mid_2d, mid_tang)
+           && curve->EvTangent(range.m_t[1], end_2d, end_tang)
+           && surface_EvNormal(surf, mid_2d.x, mid_2d.y, mid_3d, mid_norm)
+           && surface_EvNormal(surf, start_2d.x, start_2d.y, start_3d, 
start_norm)
+           && surface_EvNormal(surf, end_2d.x, end_2d.y, end_3d, end_norm))
+       {
+           (*param_points)[0.0] = new ON_3dPoint(
+               surf->PointAt(curve->PointAt(range.m_t[0]).x,
+                             curve->PointAt(range.m_t[0]).y));
+           getUVCurveSamples(surf, curve, range.m_t[0], start_2d, start_tang,
+                             start_3d, start_norm, mid_range, mid_2d, mid_tang,
+                             mid_3d, mid_norm, min_dist, max_dist, within_dist,
+                             cos_within_ang, *param_points);
+           (*param_points)[0.5] = new ON_3dPoint(
+               surf->PointAt(curve->PointAt(mid_range).x,
+                             curve->PointAt(mid_range).y));
+           getUVCurveSamples(surf, curve, mid_range, mid_2d, mid_tang, mid_3d,
+                             mid_norm, range.m_t[1], end_2d, end_tang, end_3d,
+                             end_norm, min_dist, max_dist, within_dist,
+                             cos_within_ang, *param_points);
+           (*param_points)[1.0] = new ON_3dPoint(
+               surf->PointAt(curve->PointAt(range.m_t[1]).x,
+                             curve->PointAt(range.m_t[1]).y));
+       }
+    } else {
+       ON_3dPoint start_2d(0.0, 0.0, 0.0);
+       ON_3dPoint start_3d(0.0, 0.0, 0.0);
+       ON_3dVector start_tang(0.0, 0.0, 0.0);
+       ON_3dVector start_norm(0.0, 0.0, 0.0);
+       ON_3dPoint end_2d(0.0, 0.0, 0.0);
+       ON_3dPoint end_3d(0.0, 0.0, 0.0);
+       ON_3dVector end_tang(0.0, 0.0, 0.0);
+       ON_3dVector end_norm(0.0, 0.0, 0.0);
+
+       if (curve->EvTangent(range.m_t[0], start_2d, start_tang)
+           && curve->EvTangent(range.m_t[1], end_2d, end_tang)
+           && surface_EvNormal(surf, start_2d.x, start_2d.y, start_3d, 
start_norm)
+           && surface_EvNormal(surf, end_2d.x, end_2d.y, end_3d, end_norm))
+       {
+           (*param_points)[0.0] = new ON_3dPoint(start_3d);
+           getUVCurveSamples(surf, curve, range.m_t[0], start_2d, start_tang,
+                             start_3d, start_norm, range.m_t[1], end_2d, 
end_tang,
+                             end_3d, end_norm, min_dist, max_dist, within_dist,
+                             cos_within_ang, *param_points);
+           (*param_points)[1.0] = new ON_3dPoint(end_3d);
+       }
+    }
+
+
+    return param_points;
+}
+
+
+/*
+ * number_of_seam_crossings
+ */
+static int
+number_of_seam_crossings(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_trim_points)
+{
+    int rc = 0;
+    const ON_2dPoint *prev_non_seam_pt = NULL;
+    for (int i = 0; i < brep_trim_points.Count(); i++) {
+       const ON_2dPoint *pt = &brep_trim_points[i].p2d;
+       if (!IsAtSeam(surf, *pt, BREP_SAME_POINT_TOLERANCE)) {
+           int udir = 0;
+           int vdir = 0;
+           if (prev_non_seam_pt != NULL) {
+               if (ConsecutivePointsCrossClosedSeam(surf, *prev_non_seam_pt, 
*pt, udir, vdir, BREP_SAME_POINT_TOLERANCE)) {
+                   rc++;
+               }
+           }
+           prev_non_seam_pt = pt;
+       }
+    }
+
+    return rc;
+}
+
+
+static bool
+LoopStraddlesDomain(const ON_Surface *surf,  ON_SimpleArray<BrepTrimPoint> 
&brep_loop_points)
+{
+    if (surf->IsClosed(0) || surf->IsClosed(1)) {
+       int num_crossings = number_of_seam_crossings(surf, brep_loop_points);
+       if (num_crossings == 1) {
+           return true;
+       }
+    }
+    return false;
+}
+
+
+/*
+ * entering - 1
+ * exiting - 2
+ * contained - 0
+ */
+static int
+is_entering(const ON_Surface *surf,  const ON_SimpleArray<BrepTrimPoint> 
&brep_loop_points)
+{
+    int numpoints = brep_loop_points.Count();
+    for (int i = 1; i < numpoints - 1; i++) {
+       int seam = 0;
+       ON_2dPoint p = brep_loop_points[i].p2d;
+       if ((seam = IsAtSeam(surf, p, BREP_SAME_POINT_TOLERANCE)) > 0) {
+           ON_2dPoint unwrapped = UnwrapUVPoint(surf, p, 
BREP_SAME_POINT_TOLERANCE);
+           if (seam == 1) {
+               bool right_seam = unwrapped.x > surf->Domain(0).Mid();
+               bool decreasing = (brep_loop_points[numpoints - 1].p2d.x - 
brep_loop_points[0].p2d.x) < 0;
+               if (right_seam != decreasing) { // basically XOR'ing here
+                   return 2;
+               } else {
+                   return 1;
+               }
+           } else {
+               bool top_seam = unwrapped.y > surf->Domain(1).Mid();
+               bool decreasing = (brep_loop_points[numpoints - 1].p2d.y - 
brep_loop_points[0].p2d.y) < 0;
+               if (top_seam != decreasing) { // basically XOR'ing here
+                   return 2;
+               } else {
+                   return 1;
+               }
+           }
+       }
+    }
+    return 0;
+}
+
+/*
+ * shift_closed_curve_split_over_seam
+ */
+static bool
+shift_loop_straddled_over_seam(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_loop_points, double same_point_tolerance)
+{
+    if (surf->IsClosed(0) || surf->IsClosed(1)) {
+       ON_Interval dom[2];
+       int entering = is_entering(surf, brep_loop_points);
+
+       dom[0] = surf->Domain(0);
+       dom[1] = surf->Domain(1);
+
+       int seam = 0;
+       int i;
+       BrepTrimPoint btp;
+       BrepTrimPoint end_btp;
+       ON_SimpleArray<BrepTrimPoint> part1;
+       ON_SimpleArray<BrepTrimPoint> part2;
+
+       end_btp.p2d = ON_2dPoint::UnsetPoint;
+       int numpoints = brep_loop_points.Count();
+       bool first_seam_pt = true;
+       for (i = 0; i < numpoints; i++) {
+           btp = brep_loop_points[i];
+           if ((seam = IsAtSeam(surf, btp.p2d, same_point_tolerance)) > 0) {
+               if (first_seam_pt) {
+                   part1.Append(btp);
+                   first_seam_pt = false;
+               }
+               end_btp = btp;
+               SwapUVSeamPoint(surf, end_btp.p2d);
+               part2.Append(end_btp);
+           } else {
+               if (dom[0].Includes(btp.p2d.x, false) && 
dom[1].Includes(btp.p2d.y, false)) {
+                   part1.Append(brep_loop_points[i]);
+               } else {
+                   btp = brep_loop_points[i];
+                   btp.p2d = UnwrapUVPoint(surf, brep_loop_points[i].p2d, 
same_point_tolerance);
+                   part2.Append(btp);
+               }
+           }
+       }
+
+       brep_loop_points.Empty();
+       if (entering == 1) {
+           brep_loop_points.Append(part1.Count() - 1, part1.Array());
+           brep_loop_points.Append(part2.Count(), part2.Array());
+       } else {
+           brep_loop_points.Append(part2.Count() - 1, part2.Array());
+           brep_loop_points.Append(part1.Count(), part1.Array());
+       }
+    }
+    return true;
+}
+
+
+/*
+ * extend_over_seam_crossings
+ */
+static bool
+extend_over_seam_crossings(const ON_Surface *surf,  
ON_SimpleArray<BrepTrimPoint> &brep_loop_points)
+{
+    int num_points = brep_loop_points.Count();
+    double ulength = surf->Domain(0).Length();
+    double vlength = surf->Domain(1).Length();
+    for (int i = 1; i < num_points; i++) {
+       if (surf->IsClosed(0)) {
+           double delta = brep_loop_points[i].p2d.x - brep_loop_points[i - 
1].p2d.x;
+           while (fabs(delta) > ulength / 2.0) {
+               if (delta < 0.0) {
+                   brep_loop_points[i].p2d.x += ulength; // east bound
+               } else {
+                   brep_loop_points[i].p2d.x -= ulength;; // west bound
+               }
+               delta = brep_loop_points[i].p2d.x - brep_loop_points[i - 
1].p2d.x;
+           }
+       }
+       if (surf->IsClosed(1)) {
+           double delta = brep_loop_points[i].p2d.y - brep_loop_points[i - 
1].p2d.y;
+           while (fabs(delta) > vlength / 2.0) {
+               if (delta < 0.0) {
+                   brep_loop_points[i].p2d.y += vlength; // north bound
+               } else {
+                   brep_loop_points[i].p2d.y -= vlength;; // south bound
+               }
+               delta = brep_loop_points[i].p2d.y - brep_loop_points[i - 
1].p2d.y;
+           }
+       }
+    }
+
+    return true;
+}
+
+/* force near seam points to seam */
+static void
+ForceNearSeamPointsToSeam(
+       const ON_Surface *s,
+       const ON_BrepFace &face,
+       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
+       double same_point_tolerance)
+{
+    int loop_cnt = face.LoopCount();
+    for (int li = 0; li < loop_cnt; li++) {
+       int num_loop_points = brep_loop_points[li].Count();
+       if (num_loop_points > 1) {
+           for (int i = 0; i < num_loop_points; i++) {
+               ON_2dPoint &p = brep_loop_points[li][i].p2d;
+               if (IsAtSeam(s, p, same_point_tolerance)) {
+                   ForceToClosestSeam(s, p, same_point_tolerance);
+               }
+           }
+       }
+    }
+}
+
+
+static void
+ExtendPointsOverClosedSeam(
+       const ON_Surface *s,
+       const ON_BrepFace &face,
+       ON_SimpleArray<BrepTrimPoint> *brep_loop_points)
+{
+    int loop_cnt = face.LoopCount();
+    // extend loop points over seam if needed.
+    for (int li = 0; li < loop_cnt; li++) {
+       int num_loop_points = brep_loop_points[li].Count();
+       if (num_loop_points > 1) {
+           if (!extend_over_seam_crossings(s, brep_loop_points[li])) {
+               std::cerr << "Error: Face(" << face.m_face_index << ") cannot 
extend loops over closed seams." << std::endl;
+           }
+       }
+    }
+}
+
+
+// process through loops checking for straddle condition.
+static void
+ShiftLoopsThatStraddleSeam(
+       const ON_Surface *s,
+       const ON_BrepFace &face,
+       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
+       double same_point_tolerance)
+{
+    int loop_cnt = face.LoopCount();
+    for (int li = 0; li < loop_cnt; li++) {
+       int num_loop_points = brep_loop_points[li].Count();
+       if (num_loop_points > 1) {
+           ON_2dPoint brep_loop_begin = brep_loop_points[li][0].p2d;
+           ON_2dPoint brep_loop_end = brep_loop_points[li][num_loop_points - 
1].p2d;
+
+           if (!V2NEAR_EQUAL(brep_loop_begin, brep_loop_end, 
same_point_tolerance)) {
+               if (LoopStraddlesDomain(s, brep_loop_points[li])) {
+                   // reorder loop points
+                   shift_loop_straddled_over_seam(s, brep_loop_points[li], 
same_point_tolerance);
+               }
+           }
+       }
+    }
+}
+
+
+// process through closing open loops that begin and end on closed seam
+static void
+CloseOpenLoops(
+       struct ON_Brep_CDT_State *s_cdt,
+       const ON_Surface *s,
+       const ON_BrepFace &face,
+       ON_SimpleArray<BrepTrimPoint> *brep_loop_points,
+       double same_point_tolerance)
+{
+    std::list<std::map<double, ON_3dPoint *> *> bridgePoints;
+    int loop_cnt = face.LoopCount();
+    for (int li = 0; li < loop_cnt; li++) {
+       int num_loop_points = brep_loop_points[li].Count();
+       if (num_loop_points > 1) {
+           ON_2dPoint brep_loop_begin = brep_loop_points[li][0].p2d;
+           ON_2dPoint brep_loop_end = brep_loop_points[li][num_loop_points - 
1].p2d;
+           ON_3dPoint brep_loop_begin3d = s->PointAt(brep_loop_begin.x, 
brep_loop_begin.y);
+           ON_3dPoint brep_loop_end3d = s->PointAt(brep_loop_end.x, 
brep_loop_end.y);
+
+           if (!V2NEAR_EQUAL(brep_loop_begin, brep_loop_end, 
same_point_tolerance) &&
+               VNEAR_EQUAL(brep_loop_begin3d, brep_loop_end3d, 
same_point_tolerance)) {
+               int seam_begin = 0;
+               int seam_end = 0;
+               if ((seam_begin = IsAtSeam(s, brep_loop_begin, 
same_point_tolerance)) &&
+                   (seam_end = IsAtSeam(s, brep_loop_end, 
same_point_tolerance))) {
+                   bool loop_not_closed = true;
+                   if ((li + 1) < loop_cnt) {
+                       // close using remaining loops

@@ 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