Revision: 55762
http://sourceforge.net/p/brlcad/code/55762
Author: starseeker
Date: 2013-06-13 19:11:14 +0000 (Thu, 13 Jun 2013)
Log Message:
-----------
Refactor some NURBS functionality from the tree methods into functions, and add
doxygen comments.
Modified Paths:
--------------
brlcad/trunk/src/libbrep/libbrep_brep_tools.cpp
brlcad/trunk/src/libbrep/libbrep_brep_tools.h
brlcad/trunk/src/libbrep/opennurbs_ext.cpp
Modified: brlcad/trunk/src/libbrep/libbrep_brep_tools.cpp
===================================================================
--- brlcad/trunk/src/libbrep/libbrep_brep_tools.cpp 2013-06-13 19:08:31 UTC
(rev 55761)
+++ brlcad/trunk/src/libbrep/libbrep_brep_tools.cpp 2013-06-13 19:11:14 UTC
(rev 55762)
@@ -27,8 +27,151 @@
#include "opennurbs.h"
-// For any pre-existing surface passed as one of the t* args, this is a no-op
-void ON_Surface_Create_Scratch_Surfaces(
+bool ON_NearZero(double val, double epsilon) {
+ return (val > -epsilon) && (val < epsilon);
+}
+
+int ON_Curve_Has_Tangent(const ON_Curve* curve, double ct_min, double ct_max,
double t_tol) {
+
+ bool tanx1, tanx2, x_changed;
+ bool tany1, tany2, y_changed;
+ bool slopex, slopey;
+ double xdelta, ydelta;
+ ON_3dVector tangent1, tangent2;
+ ON_3dPoint p1, p2;
+ ON_Interval t(ct_min, ct_max);
+
+ tangent1 = curve->TangentAt(t[0]);
+ tangent2 = curve->TangentAt(t[1]);
+
+ tanx1 = (tangent1[0] < 0.0);
+ tanx2 = (tangent2[0] < 0.0);
+ tany1 = (tangent1[1] < 0.0);
+ tany2 = (tangent2[1] < 0.0);
+
+ x_changed =(tanx1 != tanx2);
+ y_changed =(tany1 != tany2);
+
+ if (x_changed && y_changed) return 3; //horz & vert
+ if (x_changed) return 1;//need to get vertical tangent
+ if (y_changed) return 2;//need to find horizontal tangent
+
+ p1 = curve->PointAt(t[0]);
+ p2 = curve->PointAt(t[1]);
+
+ xdelta = (p2[0] - p1[0]);
+ slopex = (xdelta < 0.0);
+ ydelta = (p2[1] - p1[1]);
+ slopey = (ydelta < 0.0);
+
+ // If we have no slope change
+ // in x or y, we have a tangent line
+ if (ON_NearZero(xdelta, t_tol) || ON_NearZero(ydelta, t_tol)) return 0;
+
+ if ((slopex != tanx1) || (slopey != tany1)) return 3;
+
+ return 0;
+}
+
+bool ON_Surface_IsFlat(ON_Plane *frames, double f_tol)
+{
+ double Ndot=1.0;
+
+ for(int i=0; i<8; i++) {
+ for( int j=i+1; j<9; j++) {
+ if ((Ndot = Ndot * frames[i].zaxis * frames[j].zaxis) < f_tol) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ON_Surface_IsFlat_U(ON_Plane *frames, double f_tol)
+{
+ // check surface normals in U direction
+ double Ndot = 1.0;
+ if ((Ndot=frames[0].zaxis * frames[1].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[2].zaxis * frames[3].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[5].zaxis * frames[7].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[6].zaxis * frames[8].zaxis) < f_tol) {
+ return false;
+ }
+
+ // check for U twist within plane
+ double Xdot = 1.0;
+ if ((Xdot=frames[0].xaxis * frames[1].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[2].xaxis * frames[3].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[5].xaxis * frames[7].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[6].xaxis * frames[8].xaxis) < f_tol) {
+ return false;
+ }
+
+ return true;
+}
+
+bool ON_Surface_IsFlat_V(ON_Plane *frames, double f_tol)
+{
+ // check surface normals in V direction
+ double Ndot = 1.0;
+ if ((Ndot=frames[0].zaxis * frames[3].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[1].zaxis * frames[2].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[5].zaxis * frames[6].zaxis) < f_tol) {
+ return false;
+ } else if ((Ndot=Ndot * frames[7].zaxis * frames[8].zaxis) < f_tol) {
+ return false;
+ }
+
+ // check for V twist within plane
+ double Xdot = 1.0;
+ if ((Xdot=frames[0].xaxis * frames[3].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[1].xaxis * frames[2].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[5].xaxis * frames[6].xaxis) < f_tol) {
+ return false;
+ } else if ((Xdot=Xdot * frames[7].xaxis * frames[8].xaxis) < f_tol) {
+ return false;
+ }
+
+ return true;
+}
+
+bool ON_Surface_IsStraight(ON_Plane *frames, double s_tol)
+{
+ double Xdot=1.0;
+
+ for(int i=0; i<8; i++) {
+ for( int j=i+1; j<9; j++) {
+ if ((Xdot = Xdot * frames[0].xaxis * frames[1].xaxis) < s_tol) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ \brief Create surfaces and store their pointers in the t* arguments.
+
+ For any pre-existing surface passed as one of the t* args, this is a no-op.
+
+ @param t1 Pointer to pointer addressing first surface
+ @param t2 Pointer to pointer addressing second surface
+ @param t3 Pointer to pointer addressing third surface
+ @param t4 Pointer to pointer addressing fourth surface
+*/
+ void ON_Surface_Create_Scratch_Surfaces(
ON_Surface **t1,
ON_Surface **t2,
ON_Surface **t3,
Modified: brlcad/trunk/src/libbrep/libbrep_brep_tools.h
===================================================================
--- brlcad/trunk/src/libbrep/libbrep_brep_tools.h 2013-06-13 19:08:31 UTC
(rev 55761)
+++ brlcad/trunk/src/libbrep/libbrep_brep_tools.h 2013-06-13 19:11:14 UTC
(rev 55762)
@@ -44,6 +44,140 @@
#endif
/**
+ \brief Return truthfully whether a value is within a specified epsilon
distance from zero.
+
+
+ @param val value to be tested
+ @param epsilon distance from zero defining the interval to be treated as
"near" zero for the test
+
+ @return @c true if the value is within the near-zero interval specified by
epsilon, @c false otherwise.
+*/
+NURBS_EXPORT
+bool ON_NearZero(double val, double epsilon);
+
+
+/**
+ \brief Test whether a curve interval contains one or more horizontal or
vertical tangents
+
+ @param curve ON_Curve to be tested
+ @param ct_min minimum t parameter value of the curve interval to be tested
+ @param ct_max maximum t parameter value of the curve interval to be tested
+ @param t_tol tolerance used to decide when a curve is a line tangent to X or
Y axis
+
+ @return @c 0 if there are no tangent points in the interval, @c 1 if there
is a single vertical tangent,
+ @c 2 if there is a single horizontal tangent, and @c 3 if multiple tangents
are present.
+*/
+NURBS_EXPORT
+int ON_Curve_Has_Tangent(const ON_Curve* curve, double ct_min, double ct_max,
double t_tol);
+
+
+#if 0
+/*
+ \verbatim
+ 3-------------------2
+ | |
+ | 6 8 |
+ | |
+ V| 4 |
+ | |
+ | 5 7 |
+ | |
+ 0-------------------1
+ U
+ \endverbatim
+*/
+#endif
+
+/**
+ \brief Perform flatness test of surface
+
+ Determine whether a given surface is flat enough, i.e. it falls
+ beneath our simple flatness constraints. The flatness constraint in
+ this case is a sampling of normals across the surface such that the
+ product of their combined dot products is close to 1.
+
+ @f[ \prod_{i=1}^{7} n_i \dot n_{i+1} = 1 @f]
+
+ This code is using a slightly different placement of the interior normal
+ tests as compared to <a
href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90.7500&rep=rep1&type=pdf">Abert's</a>
approach:
+
+ \verbatim
+ +-------------------+
+ | |
+ | + + |
+ | |
+ V | + |
+ | |
+ | + + |
+ | |
+ +-------------------+
+ U
+ \endverbatim
+
+
+ The "+" indicates the normal sample.
+
+ The frenet frames are stored in the frames arrays according
+ to the following index values:
+
+ \verbatim
+ 3-------------------2
+ | |
+ | 6 8 |
+ | |
+ V | 4 |
+ | |
+ | 5 7 |
+ | |
+ 0-------------------1
+ U
+ \endverbatim
+
+ @param frames Array of 9 frenet frames
+ @param f_tol Flatness tolerance - 0 always evaluates to flat, 1 would be a
perfectly flat surface. Generally something in the range 0.8-0.9 should suffice
in raytracing subdivision (per <a
href="http://www.uni-koblenz.de/~cg/Diplomarbeiten/DA_Oliver_Abert.pdf">Abert,
2005</a>)
+*/
+NURBS_EXPORT
+bool ON_Surface_IsFlat(ON_Plane *frames, double f_tol);
+
+/**
+ \brief Perform flatness test of surface in U only
+
+ Array index conventions are the same as ::ON_Surface_IsFlat.
+
+ @param frames Array of 9 frenet frames
+ @param s_tol Straightness tolerance - 0 always evaluates to straight, 1
requires perfect straightness
+*/
+NURBS_EXPORT
+bool ON_Surface_IsFlat_U(ON_Plane *frames, double f_tol);
+
+
+/**
+ \brief Perform flatness test of surface in V only
+
+ Array index conventions are the same as ::ON_Surface_IsFlat.
+
+ @param frames Array of 9 frenet frames
+ @param s_tol Straightness tolerance - 0 always evaluates to straight, 1
requires perfect straightness
+*/
+NURBS_EXPORT
+bool ON_Surface_IsFlat_V(ON_Plane *frames, double f_tol);
+
+
+/**
+ \brief Perform straightness test of surface
+
+ The straightness test compares flatness criteria to running product of the
tangent vector of
+ the frenet frame projected onto each other tangent in the frame set. Array
index conventions
+ are the same as ::ON_Surface_IsFlat.
+
+ @param frames Array of 9 frenet frames
+ @param s_tol Straightness tolerance - 0 always evaluates to straight, 1
requires perfect straightness
+*/
+NURBS_EXPORT
+bool ON_Surface_IsStraight(ON_Plane *frames, double s_tol);
+
+
+/**
\brief Create a surface based on a subset of a parent surface
Create a NURBS surface that corresponds to a subset
Modified: brlcad/trunk/src/libbrep/opennurbs_ext.cpp
===================================================================
--- brlcad/trunk/src/libbrep/opennurbs_ext.cpp 2013-06-13 19:08:31 UTC (rev
55761)
+++ brlcad/trunk/src/libbrep/opennurbs_ext.cpp 2013-06-13 19:11:14 UTC (rev
55762)
@@ -36,6 +36,7 @@
#include "bu.h"
#include "brep.h"
+#include "libbrep_brep_tools.h"
#include "dvec.h"
#define RANGE_HI 0.55
@@ -53,12 +54,6 @@
/// another arbitrary calculation tolerance (need to try VDIVIDE_TOL or
VUNITIZE_TOL to tighten the bounds)
#define TOL2 0.00001
-
-bool
-ON_NearZero(double x, double tolerance) {
- return (x > -tolerance) && (x < tolerance);
-}
-
void
brep_get_plane_ray(ON_Ray& r, plane_ray& pr)
{
@@ -462,81 +457,39 @@
bool
CurveTree::getHVTangents(const ON_Curve* curve, ON_Interval& t,
std::list<fastf_t>& list)
{
- bool tanx1, tanx2, tanx_changed;
- bool tany1, tany2, tany_changed;
- bool tan_changed;
- ON_3dVector tangent1, tangent2;
- ON_3dPoint p1, p2;
+ double x;
+ double midpoint = (t[1]+t[0])/2.0;
+ ON_Interval left(t[0], midpoint);
+ ON_Interval right(midpoint, t[1]);
+ int status = ON_Curve_Has_Tangent(curve, t[0], t[1], TOL);
- tangent1 = curve->TangentAt(t[0]);
- tangent2 = curve->TangentAt(t[1]);
+ switch (status) {
- tanx1 = (tangent1[X] < 0.0);
- tanx2 = (tangent2[X] < 0.0);
- tany1 = (tangent1[Y] < 0.0);
- tany2 = (tangent2[Y] < 0.0);
+ case 1: /* 1 Vertical tangent */
+ x = getVerticalTangent(curve, t[0], t[1]);
+ list.push_back(x);
+ return true;
- tanx_changed =(tanx1 != tanx2);
- tany_changed =(tany1 != tany2);
+ case 2: /* 1 Horizontal tangent */
+ x = getHorizontalTangent(curve, t[0], t[1]);
+ list.push_back(x);
+ return true;
- tan_changed = tanx_changed || tany_changed;
-
- if (tan_changed) {
- if (tanx_changed && tany_changed) {//horz & vert simply split
- double midpoint = (t[1]+t[0])/2.0;
- ON_Interval left(t[0], midpoint);
- ON_Interval right(midpoint, t[1]);
+ case 3: /* Horizontal and vertical tangents present - Simple midpoint
split */
if (left.Length() > TOL)
getHVTangents(curve, left, list);
if (right.Length() > TOL)
getHVTangents(curve, right, list);
return true;
- } else if (tanx_changed) {//find horz
- double x = getVerticalTangent(curve, t[0], t[1]);
- list.push_back(x);
- } else { //find vert
- double x = getHorizontalTangent(curve, t[0], t[1]);
- list.push_back(x);
- }
- } else { // check point slope for change
- bool slopex, slopex_changed;
- bool slopey, slopey_changed;
- bool slope_changed;
- fastf_t xdelta, ydelta;
- p1 = curve->PointAt(t[0]);
- p2 = curve->PointAt(t[1]);
+ default:
+ return false;
- xdelta = (p2[X] - p1[X]);
- slopex = (xdelta < 0.0);
- ydelta = (p2[Y] - p1[Y]);
- slopey = (ydelta < 0.0);
+ }
- if (NEAR_ZERO(xdelta, TOL) ||
- NEAR_ZERO(ydelta, TOL)) {
- return true;
- }
-
- slopex_changed = (slopex != tanx1);
- slopey_changed = (slopey != tany1);
-
- slope_changed = slopex_changed || slopey_changed;
-
- if (slope_changed) { //2 horz or 2 vert changes simply split
- double midpoint = (t[1]+t[0])/2.0;
- ON_Interval left(t[0], midpoint);
- ON_Interval right(midpoint, t[1]);
- if (left.Length() > TOL)
- getHVTangents(curve, left, list);
- if (right.Length() > TOL)
- getHVTangents(curve, right, list);
- return true;
- }
- }
- return true;
+ return false; //Should never get here
}
-
BRNode*
CurveTree::curveBBox(const ON_Curve* curve, int adj_face_index, ON_Interval&
t, bool isLeaf, bool innerTrim, const ON_BoundingBox& bb)
{
@@ -2396,102 +2349,28 @@
bool
SurfaceTree::isFlat(ON_Plane *frames)
{
- double Ndot=1.0;
-
- /* The flatness test compares flatness criteria to running product of the
normal vector of
- * the frenet frame projected onto each other normal in the frame set.
- */
- for(int i=0; i<8; i++) {
- for( int j=i+1; j<9; j++) {
- if ((Ndot = Ndot * frames[i].zaxis * frames[j].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
- }
- }
-
- return true;
+ return ON_Surface_IsFlat(frames, BREP_SURFACE_FLATNESS);
}
bool
SurfaceTree::isStraight(ON_Plane *frames)
{
- double Xdot=1.0;
-
- /* The straightness test compares flatness criteria to running product of
the tangent vector of
- * the frenet frame projected onto each other tangent in the frame set.
- */
- for(int i=0; i<8; i++) {
- for( int j=i+1; j<9; j++) {
- if ((Xdot = Xdot * frames[0].xaxis * frames[1].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
- }
- }
-
- return true;
+ return ON_Surface_IsStraight(frames, BREP_SURFACE_FLATNESS);
}
bool
SurfaceTree::isFlatU(ON_Plane *frames)
{
- // check surface normals in U direction
- double Ndot = 1.0;
- if ((Ndot=frames[0].zaxis * frames[1].zaxis) < BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[2].zaxis * frames[3].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[5].zaxis * frames[7].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[6].zaxis * frames[8].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
-
- // check for U twist within plane
- double Xdot = 1.0;
- if ((Xdot=frames[0].xaxis * frames[1].xaxis) < BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[2].xaxis * frames[3].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[5].xaxis * frames[7].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[6].xaxis * frames[8].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
-
- return true;
+ ON_Surface_IsFlat_U(frames, BREP_SURFACE_FLATNESS);
}
bool
SurfaceTree::isFlatV(ON_Plane *frames)
{
- // check surface normals in V direction
- double Ndot = 1.0;
- if ((Ndot=frames[0].zaxis * frames[3].zaxis) < BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[1].zaxis * frames[2].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[5].zaxis * frames[6].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Ndot=Ndot * frames[7].zaxis * frames[8].zaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
-
- // check for V twist within plane
- double Xdot = 1.0;
- if ((Xdot=frames[0].xaxis * frames[3].xaxis) < BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[1].xaxis * frames[2].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[5].xaxis * frames[6].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- } else if ((Xdot=Xdot * frames[7].xaxis * frames[8].xaxis) <
BREP_SURFACE_FLATNESS) {
- return false;
- }
-
- return true;
+ ON_Surface_IsFlat_V(frames, BREP_SURFACE_FLATNESS);
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits