[brlcad-commits] SF.net SVN: brlcad:[55762] brlcad/trunk/src/libbrep
Open Source Solid Modeling CAD
Brought to you by:
brlcad
From: <sta...@us...> - 2013-06-13 19:11:17
|
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. |