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 *> ¶m_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 *> ¶m_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