From cf8984bb9af96dc828d4a111b61e5c8212031e24 Mon Sep 17 00:00:00 2001 From: Bozo the Builder Date: Wed, 13 Mar 2024 09:41:56 -0700 Subject: [PATCH] Sync changes from upstream repository --- example_test/CMakeLists.txt | 2 +- example_test/README.md | 20 +- opennurbs_array.h | 4 + opennurbs_array_defs.h | 30 +- opennurbs_convex_poly.cpp | 113 +- opennurbs_convex_poly.h | 8 +- opennurbs_decals.cpp | 3 + opennurbs_defines.h | 10 +- opennurbs_dimension.cpp | 7 +- opennurbs_intersect.cpp | 85 +- opennurbs_light.cpp | 5 +- opennurbs_locale.cpp | 18 +- opennurbs_mesh.cpp | 8 +- opennurbs_point.cpp | 6 + opennurbs_point.h | 10 + opennurbs_public_version.h | 20 +- opennurbs_render_content.cpp | 2 +- opennurbs_statics.cpp | 6 + opennurbs_subd.cpp | 144 +- opennurbs_subd.h | 84 +- opennurbs_subd_data.cpp | 2 +- opennurbs_subd_data.h | 2 +- opennurbs_subd_fragment.cpp | 2 +- tests/CMakeLists.txt | 36 - tests/Input/TestCSX.3dm | Bin 100103 -> 0 bytes tests/Input/TestClosestPoint.3dm | Bin 179086 -> 0 bytes tests/Input/TestCurveCurveIntersection.3dm | Bin 124349 -> 0 bytes tests/Input/mesh_clspt_test.3dm | Bin 326101 -> 0 bytes tests/README.md | 24 - tests/TestBase64.cpp | 289 -- tests/TestBooleanUnion.cpp | 67 - tests/TestClosestPoint.cpp | 3670 -------------------- tests/TestCurveCurveIntersection.cpp | 709 ---- tests/TestCurveSurfaceIntersection.cpp | 816 ----- tests/TestNurbsCageEvaluate.cpp | 191 - tests/TestPrecompiledHeader.cpp | 1 - tests/TestQuotientRule.cpp | 451 --- tests/TestTree.cpp | 647 ---- tests/TestZLib.cpp | 253 -- tests/Tests.cpp | 1090 ------ tests/Tests.h | 257 -- tests/Tests.vcproj | 249 -- tests/fileio/CMakeLists.txt | 36 - tests/fileio/README.md | 20 - tests/fileio/test_ON_FileIO.cpp | 105 - tests/test_ClassSize.cpp | 2631 -------------- zlib/CMakeLists.txt | 2 +- 47 files changed, 397 insertions(+), 11738 deletions(-) delete mode 100644 tests/CMakeLists.txt delete mode 100644 tests/Input/TestCSX.3dm delete mode 100644 tests/Input/TestClosestPoint.3dm delete mode 100644 tests/Input/TestCurveCurveIntersection.3dm delete mode 100644 tests/Input/mesh_clspt_test.3dm delete mode 100644 tests/README.md delete mode 100644 tests/TestBase64.cpp delete mode 100644 tests/TestBooleanUnion.cpp delete mode 100644 tests/TestClosestPoint.cpp delete mode 100644 tests/TestCurveCurveIntersection.cpp delete mode 100644 tests/TestCurveSurfaceIntersection.cpp delete mode 100644 tests/TestNurbsCageEvaluate.cpp delete mode 100644 tests/TestPrecompiledHeader.cpp delete mode 100644 tests/TestQuotientRule.cpp delete mode 100644 tests/TestTree.cpp delete mode 100644 tests/TestZLib.cpp delete mode 100644 tests/Tests.cpp delete mode 100644 tests/Tests.h delete mode 100644 tests/Tests.vcproj delete mode 100644 tests/fileio/CMakeLists.txt delete mode 100644 tests/fileio/README.md delete mode 100644 tests/fileio/test_ON_FileIO.cpp delete mode 100644 tests/test_ClassSize.cpp diff --git a/example_test/CMakeLists.txt b/example_test/CMakeLists.txt index b9899e93..1cd2a2f9 100644 --- a/example_test/CMakeLists.txt +++ b/example_test/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(ON_Test) # GoogleTest requires at least C++14 -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/example_test/README.md b/example_test/README.md index 7d55d338..3702f042 100644 --- a/example_test/README.md +++ b/example_test/README.md @@ -2,19 +2,31 @@ This is a basic project to test OpenNURBS FileIO. -## Associated files +## prerequisites + +- A compatible operating system (e.g. Linux, macOS, Windows). +- A compatible C++ compiler that supports at least C++14. These tests are set to use C++17. +- CMake (3.16 and above) and a compatible build tool for building the project. These will depend on the operating system. In general: + - macos: apple clang (usually installed via xcode) + - windows: MSVC (usually installed via Visual Studio) + - linux: gcc + +## associated files - rhino/src4/opennurbs/example_test/CMakeLists.txt - rhino/src4/opennurbs/example_test/example_test.cpp ## building & running -From the example_test directory: +From the `src4/opennurbs/example_test` directory: - `cmake -S . -B build` - `cmake --build build` - `cd build && ./example_test -r ../../example_files` +- run + - macos: `cd build && ./example_test -r ../../example_files` + - windows: `cd build/Debug && ./example_test -r ../../example_files` -## Notes +## notes -- This is a test that I will eventually convert to gtest \ No newline at end of file +- Part of the functionality of this test has been converted to a GoogleTest in `src4/opennurbs/tests/fileio` \ No newline at end of file diff --git a/opennurbs_array.h b/opennurbs_array.h index 0506bcfe..37725090 100644 --- a/opennurbs_array.h +++ b/opennurbs_array.h @@ -207,6 +207,10 @@ public: int BinarySearch( const T*, int (*)(const T*,const T*) ) const; int BinarySearch( const T*, int (*)(const T*,const T*), int ) const; + const T* BinarySearchPtr(const T*, int (*)(const T*, const T*)) const; + const T* BinarySearchPtr(const T*, int (*)(const T*, const T*), int) const; + + int InsertInSortedList(const T&, int (*)(const T*, const T*)); int InsertInSortedList(const T&, int (*)(const T*, const T*), int); diff --git a/opennurbs_array_defs.h b/opennurbs_array_defs.h index ba5a36ad..96d8de92 100644 --- a/opennurbs_array_defs.h +++ b/opennurbs_array_defs.h @@ -692,9 +692,9 @@ int ON_SimpleArray::Search( const T* key, int (*compar)(const T*,const T*) ) template int ON_SimpleArray::BinarySearch( const T* key, int (*compar)(const T*,const T*) ) const { - const T* found = (key&&m_a&&m_count>0) + const T* found = (nullptr != key && nullptr != m_a && m_count>0) ? (const T*)bsearch( key, m_a, m_count, sizeof(T), (int(*)(const void*,const void*))compar ) - : 0; + : nullptr; // This worked on a wide range of 32 bit compilers. @@ -742,9 +742,9 @@ int ON_SimpleArray::BinarySearch( const T* key, int (*compar)(const T*,const count = m_count; if ( count <= 0 ) return -1; - const T* found = (key&&m_a&&m_count>0) + const T* found = (nullptr != key && nullptr != m_a && count > 0) ? (const T*)bsearch( key, m_a, count, sizeof(T), (int(*)(const void*,const void*))compar ) - : 0; + : nullptr; // This worked on a wide range of 32 bit compilers. @@ -783,6 +783,28 @@ int ON_SimpleArray::BinarySearch( const T* key, int (*compar)(const T*,const return rc; } + +template +const T* ON_SimpleArray::BinarySearchPtr(const T* key, int (*compar)(const T*, const T*)) const +{ + return + (nullptr != key && nullptr != m_a && m_count > 0) + ? (const T*)bsearch(key, m_a, m_count, sizeof(T), (int(*)(const void*, const void*))compar) + : nullptr; +} + +template +const T* ON_SimpleArray::BinarySearchPtr(const T* key, int (*compar)(const T*, const T*), int count) const +{ + if (count > m_count) + count = m_count; + return + (nullptr != key && nullptr != m_a && count > 0) + ? (const T*)bsearch(key, m_a, count, sizeof(T), (int(*)(const void*, const void*))compar) + : nullptr; +} + + template int ON_SimpleArray::InsertInSortedList(const T& e, int (*compar)(const T*, const T*)) { diff --git a/opennurbs_convex_poly.cpp b/opennurbs_convex_poly.cpp index 8528bd55..27868088 100644 --- a/opennurbs_convex_poly.cpp +++ b/opennurbs_convex_poly.cpp @@ -1112,29 +1112,52 @@ bool ON_ConvexPoly::GetClosestPointSeeded(const ON_ConvexPoly& B, } -// Is PQR a right hnd turn +// Is PQR a strictly left hand turn. +// Will return false if the point Q*, closest to PR from Q, +// IsCoincident to Q. static bool IsLeftTurn(const ON_2dPoint& P, const ON_2dPoint& Q, const ON_2dPoint& R) { ON_2dVector A = R - Q; ON_2dVector B = P - Q; double det = A.x* B.y - B.x*A.y; - return det > 0.0; + + bool Left = det > 0.0; + if (Left) + { + ON_2dVector Dir = R - P; + ON_2dVector N(-Dir.y, Dir.x); + N.Unitize(); + // todo choose A or B + ON_2dVector Delta = B * N * N; // Delta from Q to PR + // Is Q.IsCoincident(Q+Delta) + Left = false; + for (int di = 0; !Left && di < 2; di++) + { + if( fabs(Delta[di])>ON_ZERO_TOLERANCE && fabs(Delta[di])>ON_RELATIVE_TOLERANCE* fabs( Q[di]) ) + Left = true; + } + } + + return Left; } int ON_ConvexHull2d(const ON_SimpleArray& Pnt, ON_SimpleArray& Hull, ON_SimpleArray< int>* PntInd) { - int rval = -1; + int dim = -1; + if (Pnt.Count() == 0) + return dim; + Hull.Empty(); + if (PntInd) + PntInd->Empty(); + ON_SimpleArray Ind(Pnt.Count()); Ind.SetCount(Pnt.Count()); - if (PntInd) - PntInd->Empty(); + if (!Pnt.Sort(ON::sort_algorithm::quick_sort, Ind, [](const ON_2dPoint* A, const ON_2dPoint* B) { return ON_2dPoint::Compare(*A, *B); })) - return rval; - if (Pnt.Count() == 0) - return rval; + return dim; Hull.Append(Pnt[Ind[0]]); if (PntInd) @@ -1146,22 +1169,36 @@ int ON_ConvexHull2d(const ON_SimpleArray& Pnt, ON_SimpleArray= 0; ri += inc) { - ON_2dPoint R = Pnt[Ind[ri]]; + ON_2dPoint Q = *Hull.Last(); + ON_2dPoint R = Pnt[Ind[ri]]; + + // Ensure R is sufficiently distinct from Q + if (R.IsCoincident(Q)) + { + if (ri == Pnt.Count() - 1 && Hull.Count()>1) + { + // Use x-most point as second fixed end + *Hull.Last() = R; + if (PntInd) + *PntInd->Last() = Ind[ri]; + } + } - if (Hull.Count() == fixed) + else if (Hull.Count() == fixed) { - if (R != *Hull.Last()) - { - Hull.Append(R); - if (PntInd) - PntInd->Append(Ind[ri]); - } + Hull.Append(R); + if (PntInd) + PntInd->Append(Ind[ri]); } else { int pi = Hull.Count() - 2; ON_2dPoint P = Hull[pi]; - ON_2dPoint Q = *Hull.Last(); + + if (R.IsCoincident(P)) + { + //TODO what about this case?! + } if (IsLeftTurn(P, Q, R)) { Hull.Append(R); @@ -1171,20 +1208,19 @@ int ON_ConvexHull2d(const ON_SimpleArray& Pnt, ON_SimpleArrayRemove(); - Q = P; - done = (pi == ((inc==1)?0:fixed-1)); - if (!done) - { - P = Hull[--pi]; - done = IsLeftTurn(P, Q, R); - } - - } + while (!done) + { + Hull.Remove(); + if (PntInd) + PntInd->Remove(); + Q = P; + done = (pi == ((inc == 1) ? 0 : fixed - 1)); + if (!done) + { + P = Hull[--pi]; + done = IsLeftTurn(P, Q, R); + } + } Hull.Append(R); if (PntInd) PntInd->Append(Ind[ri]); @@ -1192,18 +1228,23 @@ int ON_ConvexHull2d(const ON_SimpleArray& Pnt, ON_SimpleArray 2) + dim = 2; + return dim; } diff --git a/opennurbs_convex_poly.h b/opennurbs_convex_poly.h index cbf982d7..a26d1e21 100644 --- a/opennurbs_convex_poly.h +++ b/opennurbs_convex_poly.h @@ -449,13 +449,13 @@ private: /* Compute Convex hull of 2d points Parameters: - Pnt - array of points, this is array of working data. The points are sorted in place as part of the algorithm - HUll - the sequence Hull[0], HUll[1]... ,*Hull.Last() == Hull[0] defines the convex hull with a positive orientation returns 2. - PntInd - otional array to be filled in so that Hull[i] = Pnt[ PntInd[i]] where Pnt is the original input point + Pnt - array of points. + HUll - the sequence Hull[0], HUll[1]... ,*Hull.Last() == Hull[0] defines the convex hull with a positive orientation when returns 2. + PntInd - optional array to be filled in so that Hull[i] = Pnt[ PntInd[i]] . Returns dimension of the convex hull 2 - Hull is 2 dimensional - 1 - Hull is a line segments + 1 - Hull is a line segment 0 - hull is a point <0 error */ diff --git a/opennurbs_decals.cpp b/opennurbs_decals.cpp index 9405b71d..327e2783 100644 --- a/opennurbs_decals.cpp +++ b/opennurbs_decals.cpp @@ -1088,6 +1088,8 @@ const ON_DecalCollection& ON_DecalCollection::operator = (const ON_DecalCollecti } } + m_populated = dc.m_populated; + return *this; } @@ -1115,6 +1117,7 @@ void ON_DecalCollection::Populate(void) const if (nullptr != decals_node) { // Iterate over the decals under the decals node adding a new decal for each one. + ON_ASSERT(m_decals.Count() == 0); auto it = decals_node->GetChildIterator(); ON_XMLNode* child_node = nullptr; while (nullptr != (child_node = it.GetNextChild())) diff --git a/opennurbs_defines.h b/opennurbs_defines.h index b44ccc16..8b5db81c 100644 --- a/opennurbs_defines.h +++ b/opennurbs_defines.h @@ -108,6 +108,12 @@ #define ON_DECL __attribute__ ((visibility ("default"))) #define ON_EXTERN_DECL __attribute__ ((visibility ("default"))) +#elif defined(ON_RUNTIME_LINUX) +/* Linux defaults to exporting all functions*/ +#define ON_CLASS +#define ON_DECL +#define ON_EXTERN_DECL + #else #error fill in your compiler dynamic linking decorations #endif @@ -1557,7 +1563,7 @@ public: ON::AngleUnitSystem us_to ); - +#pragma region RH_C_SHARED_ENUM [ON::EarthCoordinateSystem] [Rhino.DocObjects.EarthCoordinateSystem] [byte] /// /// ON::EarthCoordinateSystem identifies the standard used to define Earth latitude, longitude, and elevation coordinates. /// @@ -1594,6 +1600,8 @@ public: EGM2008 = 6 }; +#pragma endregion + static ON::EarthCoordinateSystem EarthCoordinateSystemFromUnsigned( unsigned int earth_coordinte_system_as_unsigned ); diff --git a/opennurbs_dimension.cpp b/opennurbs_dimension.cpp index 98203c60..83dc1173 100644 --- a/opennurbs_dimension.cpp +++ b/opennurbs_dimension.cpp @@ -3613,7 +3613,12 @@ bool ON_DimAngular::GetDisplayLines( if (0.0 < dim_ext[1]) dim_ext_ang[1] = dim_ext[1] / radius; - while (a0 + ON_ZERO_TOLERANCE > ON_PI * 2.0) + // 6-Jan-2024 Dale Fugier, ON_ZERO_TOLERANCE is too + // small for an angle tolerace. 1e-6 is more than accurate + // but let's start with 1e-8. + //const double atol = ON_ZERO_TOLERANCE; + const double atol = 1e-8; + while (a0 + atol > ON_PI * 2.0) a0 -= ON_PI * 2.0; a0 -= dim_ext_ang[0]; a1 += dim_ext_ang[1]; diff --git a/opennurbs_intersect.cpp b/opennurbs_intersect.cpp index 72944b09..c067789f 100644 --- a/opennurbs_intersect.cpp +++ b/opennurbs_intersect.cpp @@ -817,7 +817,7 @@ int ON_Intersect( ON_Line L = line; L.Transform(xform); double r = fabs(circle.radius); - double tol = r*ON_SQRT_EPSILON; + double tol = (circle.Center().MaximumCoordinate()+ r)*ON_RELATIVE_TOLERANCE; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; int xcnt; @@ -825,7 +825,13 @@ int ON_Intersect( && fabs(L.from.y - L.to.y) <= tol && fabs(L.from.z - L.to.z) > tol ) { - xcnt = 0; + if (fabs(L.from.x * L.from.x + L.from.y * L.from.y - r*r) < tol) + { + *line_t0 = -L.from.z / (L.to.z - L.from.z); + xcnt = 1; + } + else + xcnt = 0; } else { @@ -833,53 +839,38 @@ int ON_Intersect( if ( xcnt == 3 ) xcnt = 1; } - - if ( xcnt == 0 ) + + int rcnt = 0; // actual number of intersections within tol + if (xcnt > 0) { - if ( L.ClosestPointTo( circle.Center(), line_t0 ) ) + ON_3dPoint line_point1, line_point0 = line.PointAt(*line_t0); + circle_point0 = circle.ClosestPointTo(line_point0); + bool x0 = circle_point0.IsCoincident(line_point0); + bool x1 = false; + + if (xcnt == 2) { - xcnt = 1; - *line_t1 = *line_t0; + line_point1 = line.PointAt(*line_t1); + circle_point1 = circle.ClosestPointTo(line_point1); + x1 = circle_point1.IsCoincident(line_point1); + } + + + if(x0) + rcnt ++; + + if (x1) + { + rcnt++; + if (rcnt == 1) + { + circle_point0 = circle_point1; + line_t0 = line_t1; + } } } - ON_3dPoint line_point1, line_point0 = line.PointAt(*line_t0); - circle_point0 = circle.ClosestPointTo(line_point0); - double d1, d0 = line_point0.DistanceTo(circle_point0); - if ( xcnt == 2 ) - { - line_point1 = line.PointAt(*line_t1); - circle_point1 = circle.ClosestPointTo(line_point1); - d1 = line_point1.DistanceTo(circle_point1); - } - else - { - line_point1 = line_point0; - circle_point1 = circle_point0; - d1 = d0; - } - if ( xcnt==2 && (d0 > tol && d1 > tol) ) - { - xcnt = 1; - if ( d0 <= d1 ) - { - *line_t1 = *line_t0; - line_point1 = line_point0; - circle_point1 = circle_point0; - d1 = d0; - } - else - { - *line_t0 = *line_t1; - line_point0 = line_point1; - circle_point0 = circle_point1; - d0 = d1; - } - } - if ( xcnt == 1 && d0 > tol ) - { - // TODO: iterate to closest point - } - return xcnt; + + return rcnt; } int ON_Intersect( @@ -1169,11 +1160,15 @@ int ON_Intersect( ON_3dPoint& arc_point1 ) { + // RH-48633 In V7 and earlier there were cases where 1 was returned and the + // returned arc_point0 is the closest point on the arc to the line but not an + // intersection point ON_Circle c = arc; ON_3dPoint p[2]; double t[2], a[2], s; bool b[2] = {false,false}; int i, xcnt = ON_Intersect( line, c, &t[0], p[0], &t[1], p[1] ); + if ( xcnt > 0 ) { // make sure points are on the arc; diff --git a/opennurbs_light.cpp b/opennurbs_light.cpp index 0e6f2dd7..fc7e5792 100644 --- a/opennurbs_light.cpp +++ b/opennurbs_light.cpp @@ -365,8 +365,9 @@ bool ON_Light::GetTightBoundingBox( { rc = ON_GetPointListBoundingBox(3, 0, points.Count(), 3, (double*)points.Array(), - tight_bbox.m_min, tight_bbox.m_max, - bGrowBox ? true : false) + tight_bbox, + bGrowBox ? true : false, + xform) ? true : false; } diff --git a/opennurbs_locale.cpp b/opennurbs_locale.cpp index a16a7e20..cb2235fa 100644 --- a/opennurbs_locale.cpp +++ b/opennurbs_locale.cpp @@ -1049,21 +1049,25 @@ ON_Locale ON_Locale::FromWindowsName( if (ON_String::EqualOrdinal("Hans", -1, script_subtag, -1, true)) { // Apple uses "zh-Hans" to mean BCP 47 "zh-CN" - if ( 0 == region_subtag[0] || ON_String::EqualOrdinal("CN", -1, region_subtag, -1, true) ) - ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_CN_LCID, "zh-CN" ); + // January 26, 2024 - Tim + // I don't think we should fail if the region is not set to China, "zh-Hans" is sufficient to choose "zh-CN" + //if ( 0 == region_subtag[0] || ON_String::EqualOrdinal("CN", -1, region_subtag, -1, true) ) + return ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_CN_LCID, "zh-CN" ); } else if (ON_String::EqualOrdinal("Hant", -1, script_subtag, -1, true)) { // Apple uses "zh-Hant" to mean BCP 47 "zh-CN" - if ( 0 == region_subtag[0] || ON_String::EqualOrdinal("TW", -1, region_subtag, -1, true) ) - ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); + // January 26, 2024 - Tim + // I don't think we should fail if the region is not set to Taiwan, "zh-Hant" is sufficient to choose "zh-TW" + //if ( 0 == region_subtag[0] || ON_String::EqualOrdinal("TW", -1, region_subtag, -1, true) ) + return ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); } else if ( ON_String::EqualOrdinal("CN", -1, region_subtag, -1, true) ) - ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_CN_LCID, "zh-CN" ); + return ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_CN_LCID, "zh-CN" ); else if ( ON_String::EqualOrdinal("TW", -1, region_subtag, -1, true) ) - ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); + return ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); else - ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); + return ON_Locale::FromWindowsLCIDAndName(ON_Locale::zh_TW_LCID, "zh-TW" ); } else { diff --git a/opennurbs_mesh.cpp b/opennurbs_mesh.cpp index dcd3b8ea..42107ee1 100644 --- a/opennurbs_mesh.cpp +++ b/opennurbs_mesh.cpp @@ -8855,7 +8855,9 @@ bool ON_Mesh::TransposeTextureCoordinates() f = tc.x; tc.x = tc.y; tc.y = f; } } - return true; + // 12 Jan 2024 - Jeff: https://mcneel.myjetbrains.com/youtrack/issue/RH-79611 + InvalidateCachedTextureCoordinates(); + return true; } bool ON_Mesh::ReverseTextureCoordinates( int dir ) @@ -8903,7 +8905,9 @@ bool ON_Mesh::ReverseTextureCoordinates( int dir ) tc.x = 1.0f-tc.x; } } - return true; + // 12 Jan 2024 - Jeff: https://mcneel.myjetbrains.com/youtrack/issue/RH-79611 + InvalidateCachedTextureCoordinates(); + return true; } bool ON_Mesh::ReverseSurfaceParameters( int dir ) diff --git a/opennurbs_point.cpp b/opennurbs_point.cpp index 1d62ebb7..af0dc5f7 100644 --- a/opennurbs_point.cpp +++ b/opennurbs_point.cpp @@ -4198,6 +4198,12 @@ float ON_TripleProduct( const float* a, const float* b, const float* c ) // ON_2dPoint // + +bool ON_2dPoint::IsCoincident(const ON_2dPoint& p) const +{ + return ON_PointsAreCoincident(2, false, *this, p); +} + ON_2dPoint::ON_2dPoint( const float* p ) { if (p) { diff --git a/opennurbs_point.h b/opennurbs_point.h index 61dc4c74..b253022b 100644 --- a/opennurbs_point.h +++ b/opennurbs_point.h @@ -396,6 +396,16 @@ public: const ON_2dPoint& rhs ); + /* + In opennurbs points within ON_ZERO_TOLERANCE are generally considered + to be the same. + Returns: + True if for each coordinate pair, + |a-b| <= ON_ZERO_TOLERANCE + or |a-b| <= (fabs(a)+fabs(b))*ON_RELATIVE_TOLERANCE. + */ + bool IsCoincident(const ON_2dPoint& P) const; + /* Returns: (A+B)/2 diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index 3dc02e7b..53f805f2 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -6,7 +6,7 @@ // To update version numbers, edit ..\build\build_dates.msbuild #define RMA_VERSION_MAJOR 8 -#define RMA_VERSION_MINOR 4 +#define RMA_VERSION_MINOR 5 //////////////////////////////////////////////////////////////// // @@ -14,9 +14,9 @@ // first step in each build. // #define RMA_VERSION_YEAR 2024 -#define RMA_VERSION_MONTH 2 -#define RMA_VERSION_DATE 13 -#define RMA_VERSION_HOUR 15 +#define RMA_VERSION_MONTH 3 +#define RMA_VERSION_DATE 12 +#define RMA_VERSION_HOUR 13 #define RMA_VERSION_MINUTE 0 //////////////////////////////////////////////////////////////// @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,4,24044,15000 -#define VERSION_WITH_PERIODS 8.4.24044.15000 +#define VERSION_WITH_COMMAS 8,5,24072,13000 +#define VERSION_WITH_PERIODS 8.5.24072.13000 #define COPYRIGHT "Copyright (C) 1993-2024, Robert McNeel & Associates. All Rights Reserved." #define SPECIAL_BUILD_DESCRIPTION "Public OpenNURBS C++ 3dm file IO library." @@ -44,11 +44,11 @@ #define RMA_VERSION_NUMBER_MAJOR_WSTRING L"8" #define RMA_PREVIOUS_VERSION_NUMBER_MAJOR_WSTRING L"7" -#define RMA_VERSION_NUMBER_SR_STRING "SR4" -#define RMA_VERSION_NUMBER_SR_WSTRING L"SR4" +#define RMA_VERSION_NUMBER_SR_STRING "SR5" +#define RMA_VERSION_NUMBER_SR_WSTRING L"SR5" -#define RMA_VERSION_WITH_PERIODS_STRING "8.4.24044.15000" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.4.24044.15000" +#define RMA_VERSION_WITH_PERIODS_STRING "8.5.24072.13000" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.5.24072.13000" diff --git a/opennurbs_render_content.cpp b/opennurbs_render_content.cpp index aeeb74d0..f5607bad 100644 --- a/opennurbs_render_content.cpp +++ b/opennurbs_render_content.cpp @@ -358,7 +358,7 @@ static void EnsureNameValid(ON_wString& name) wchar_t c = name_copy[i]; if (first) { - if ((c == L' ') ) continue; + if ( c == L' ' ) continue; if ((c == L'(') || (c == L')')) continue; if ((c == L'[') || (c == L']')) continue; if ((c == L'{') || (c == L'}')) continue; diff --git a/opennurbs_statics.cpp b/opennurbs_statics.cpp index 6329d6c0..2d6ab95c 100644 --- a/opennurbs_statics.cpp +++ b/opennurbs_statics.cpp @@ -705,10 +705,12 @@ const ON_3fPoint ON_3fPoint::NanPoint(ON_FLT_QNAN, ON_FLT_QNAN, ON_FLT_QNAN); const ON_4fPoint ON_4fPoint::Zero(0.0f, 0.0f, 0.0f, 0.0f); const ON_4fPoint ON_4fPoint::Nan(ON_FLT_QNAN, ON_FLT_QNAN, ON_FLT_QNAN, ON_FLT_QNAN); +const ON_2fVector ON_2fVector::NanVector(ON_FLT_QNAN, ON_FLT_QNAN); const ON_2fVector ON_2fVector::ZeroVector(0.0f, 0.0f); const ON_2fVector ON_2fVector::XAxis(1.0f, 0.0f); const ON_2fVector ON_2fVector::YAxis(0.0f, 1.0f); +const ON_3fVector ON_3fVector::NanVector(ON_FLT_QNAN, ON_FLT_QNAN, ON_FLT_QNAN); const ON_3fVector ON_3fVector::ZeroVector(0.0f, 0.0f, 0.0f); const ON_3fVector ON_3fVector::XAxis(1.0f, 0.0f, 0.0f); const ON_3fVector ON_3fVector::YAxis(0.0f, 1.0f, 0.0f); @@ -2751,6 +2753,10 @@ const ON_SubDVertexPtr ON_SubDVertexPtr::Null = { 0 }; const ON_SubDEdgePtr ON_SubDEdgePtr::Null = { 0 }; const ON_SubDFacePtr ON_SubDFacePtr::Null = { 0 }; const ON_SubDComponentPtr ON_SubDComponentPtr::Null = { 0 }; +const ON_SubDComponentPtr ON_SubDComponentPtr::NullVertex = { 2 }; +const ON_SubDComponentPtr ON_SubDComponentPtr::NullEdge = { 4 }; +const ON_SubDComponentPtr ON_SubDComponentPtr::NullFace = { 6 }; + const ON_SubDComponentPtrPair ON_SubDComponentPtrPair::Null = ON_SubDComponentPtrPair::Create(ON_SubDComponentPtr::Null,ON_SubDComponentPtr::Null); const ON_SubDComponentAndNumber ON_SubDComponentAndNumber::NullAndNan = ON_SubDComponentAndNumber::Create(ON_SubDComponentPtr::Null, ON_DBL_QNAN); diff --git a/opennurbs_subd.cpp b/opennurbs_subd.cpp index 316cd723..dc43e6e0 100644 --- a/opennurbs_subd.cpp +++ b/opennurbs_subd.cpp @@ -2185,10 +2185,11 @@ int ON_SubDComponentPtr::CompareType( { if ( a == b ) return 0; + // sort nullptrs to ends of arrays if ( nullptr == a ) - return 1; + return 1; // nonzero b < nullptr a if ( nullptr == b ) - return -1; + return -1; // nonzero a < nullptr b return ON_SubDComponentPtr::CompareComponentPtrType(a->ComponentType(), b->ComponentType()); } @@ -2198,11 +2199,10 @@ int ON_SubDComponentPtr::CompareComponent( const ON_SubDComponentPtr* b ) { - if (a == b) - return 0; - const int rc = ON_SubDComponentPtr::CompareComponentPtrType(a->ComponentType(), b->ComponentType()); - if (0 == rc) + const int rc = ON_SubDComponentPtr::CompareType(a, b); + if (0 == rc && a != b) { + // 0 == ON_SubDComponentPtr::CompareType(a, b) and a != b insures both pointers are not nullptr. const ON__UINT_PTR x = (a->m_ptr & ON_SUBD_COMPONENT_POINTER_MASK); const ON__UINT_PTR y = (b->m_ptr & ON_SUBD_COMPONENT_POINTER_MASK); if (x < y) @@ -2213,16 +2213,35 @@ int ON_SubDComponentPtr::CompareComponent( return rc; } + +int ON_SubDComponentPtr::CompareComponentId( + const ON_SubDComponentPtr* a, + const ON_SubDComponentPtr* b +) +{ + const int rc = ON_SubDComponentPtr::CompareType(a, b); + if (0 == rc && a != b) + { + // 0 == ON_SubDComponentPtr::CompareType(a, b) and a != b insures both pointers are not nullptr. + const unsigned x = a->ComponentId(); + const unsigned y = b->ComponentId(); + if (x < y) + return -1; + if (x > y) + return 1; + } + return rc; +} + int ON_SubDComponentPtr::CompareComponentAndDirection( const ON_SubDComponentPtr* a, const ON_SubDComponentPtr* b ) { - if (a == b) - return 0; const int rc = ON_SubDComponentPtr::CompareComponent(a, b); - if (0 == rc) + if (0 == rc && a != b) { + // 0 == ON_SubDComponentPtr::CompareComponent(a, b) and a != b insures both pointers are not nullptr. const ON__UINT_PTR x = (a->m_ptr & ON_SUBD_COMPONENT_DIRECTION_MASK); const ON__UINT_PTR y = (b->m_ptr & ON_SUBD_COMPONENT_DIRECTION_MASK); if (x < y) @@ -3908,7 +3927,17 @@ double ON_SubDEdge::EndSharpness( unsigned evi ) const { - return (IsSmooth() && evi >= 0 && evi <= 1) ? m_sharpness[evi] : 0.0; + return EndSharpness(evi, false); +} + +double ON_SubDEdge::EndSharpness( + unsigned evi, + bool bUseCreaseSharpness +) const +{ + return (IsSmooth() && evi >= 0 && evi <= 1) + ? m_sharpness[evi] + : ((bUseCreaseSharpness && IsCrease()) ? ON_SubDEdgeSharpness::CreaseValue : ON_SubDEdgeSharpness::SmoothValue); } double ON_SubDEdge::EndSharpness( @@ -4017,13 +4046,13 @@ const ON_wString ON_SubDEdgeSharpness::ToPercentageText(double sharpness) return ON_wString(ON_wString::WarningSign); } -const ON_wString ON_SubDEdgeSharpness::ToPercentageText( bool bVarableMinToMax ) const +const ON_wString ON_SubDEdgeSharpness::ToPercentageText(bool bOrderMinToMax) const { if (IsValid()) { if ( IsConstant() ) return ON_SubDEdgeSharpness::ToPercentageText(EndSharpness(0)); - const int i0 = (bVarableMinToMax && EndSharpness(0) > EndSharpness(2)) ? 1 : 0; + const int i0 = (bOrderMinToMax && (EndSharpness(0) > EndSharpness(1))) ? 1 : 0; const double s0 = EndSharpness(i0); const double s1 = EndSharpness(1-i0); return @@ -13616,7 +13645,7 @@ bool ON_SubDEdge::EvaluateCatmullClarkSubdivisionPoint(double subdivision_point[ else { // error: - // Both ends of a smooth vertex are tagged + // Both ends of a smooth edge are tagged and coefficients are not ignored, // or coefficients are incorrectly set // or ... return ON_SubDEdge_GetSubdivisionPointError(this, subdivision_point, edgeP, true); @@ -19783,52 +19812,29 @@ bool ON_SubDVertexQuadSector::Initialize( } } - for (unsigned vi = 0; vi < sector_vertex_count; ++vi) - { - m_v[vi].UnsetControlNetPoint(); - m_v[vi].m_id = vi + 1U; - } - - for (unsigned ei = 0; ei < sector_edge_count; ++ei) - { - m_e[ei].m_id = ei + 1U; - } - - for (unsigned fi = 0; fi < sector_face_count; ++fi) - { - m_f[fi].m_id = fi + 1U; - } - - if (false == SetCenterVertexTag(center_vertex_tag)) - { - this->Internal_Destroy(); - return false; - } - + // 2024-01-12, Pierre: + // Move up code setting control net points and edge sharpnesses. + // Remove code that was copied below from SetCenterVertexTagAndCenterVertexEdgesTags, + // that is not needed if sector_control_net_points and center_edge_sharpnesses are + // properly set before the call to SetCenterVertexTagAndCenterVertexEdgesTags. if (nullptr != sector_control_net_points) { for (unsigned vi = 0; vi < sector_vertex_count; ++vi) { const ON_3dPoint P = sector_control_net_points[vi]; - if ( P.IsValid()) - m_v[vi].SetControlNetPoint(P,false); + if (P.IsValid()) + m_v[vi].SetControlNetPoint(P, false); + else + m_v[vi].UnsetControlNetPoint(); + m_v[vi].m_id = vi + 1U; } - - - if (ON_SubDVertexTag::Corner == center_vertex_tag) + } + else + { + for (unsigned vi = 0; vi < sector_vertex_count; ++vi) { - // The sector coefficient on smooth edges ending at the center vertex depends on the - // angle bewteen the bounding crease edges. - ON_SubDEdge* creases[2] = { &m_e[0], &m_e[m_sector_face_count] }; - const bool bValidEdges = creases[0]->ControlNetLine().IsValid() && creases[1]->ControlNetLine().IsValid(); - const double angle_radians - = bValidEdges - ? ON_SubDSectorType::CornerSectorAngleRadiansFromEdges(ON_SubDEdgePtr::Create(creases[0], 0), ON_SubDEdgePtr::Create(creases[1], 0)) - : ON_HALFPI; - const double sector_coefficient = ON_SubDSectorType::CornerSectorCoefficient(m_sector_face_count, angle_radians); - this->m_sector_coefficient = sector_coefficient; - for ( unsigned ei = 1; ei < m_sector_face_count; ++ei) - m_e[ei].m_sector_coefficient[0] = sector_coefficient; + m_v[vi].UnsetControlNetPoint(); + m_v[vi].m_id = vi + 1U; } } @@ -19853,7 +19859,30 @@ bool ON_SubDVertexQuadSector::Initialize( if (y > center_vertex_sharpness) center_vertex_sharpness = y; } + m_e[ei].m_id = ei + 1U; } + for (unsigned ei = m_center_vertex_edge_count; ei < sector_edge_count; ++ei) + { + m_e[ei].m_id = ei + 1U; + } + } + else + { + for (unsigned ei = 0; ei < sector_edge_count; ++ei) + { + m_e[ei].m_id = ei + 1U; + } + } + + for (unsigned fi = 0; fi < sector_face_count; ++fi) + { + m_f[fi].m_id = fi + 1U; + } + + if (false == SetCenterVertexTagAndCenterVertexEdgesTags(center_vertex_tag)) + { + this->Internal_Destroy(); + return false; } this->SetCenterVertexSharpness(center_vertex_sharpness); @@ -19941,7 +19970,7 @@ double ON_SubDVertexQuadSector::MaximumSharpness() const return (max_vs > max_es) ? max_vs : max_es; } -bool ON_SubDVertexQuadSector::SetCenterVertexTag(ON_SubDVertexTag center_vertex_tag) +bool ON_SubDVertexQuadSector::SetCenterVertexTagAndCenterVertexEdgesTags(ON_SubDVertexTag center_vertex_tag) { this->m_sector_coefficient = ON_DBL_QNAN; bool bValidTag = false; @@ -20025,6 +20054,12 @@ bool ON_SubDVertexQuadSector::SetCenterVertexTag(ON_SubDVertexTag center_vertex_ } } + // 2024-01-12, Pierre, RH-79544: There is no reason not to set these tags properly, so do it + if (creases[0] != nullptr) + m_v[1].m_vertex_tag = ON_SubDVertexTag::Crease; + if (creases[1] != nullptr) + m_v[m_center_vertex_edge_count + m_sector_face_count].m_vertex_tag = ON_SubDVertexTag::Crease; + return true; } @@ -20374,7 +20409,8 @@ bool ON_SubDVertexQuadSector::Subdivide() m_v[vi].SetSubdivisionLevel(subdivision_level); if (1 == vi) m_v[vi].m_vertex_tag = bCreaseOrCornerOrDartSector ? ON_SubDVertexTag::Crease : ON_SubDVertexTag::Smooth; - else if (vi == center_vertex_edge_count) + // 2024-01-12, Pierre, RH-79544: Fix wrong vertex getting tagged Crease (was vi == center_vertex_edge_count) + else if (vi + 1U == sector_vertex_count) // or vi == 1 + 2 * (center_vertex_edge_count - 1) m_v[vi].m_vertex_tag = bCreaseOrCornerSector ? ON_SubDVertexTag::Crease : ON_SubDVertexTag::Smooth; else if (vi > 0U) m_v[vi].m_vertex_tag = ON_SubDVertexTag::Smooth; diff --git a/opennurbs_subd.h b/opennurbs_subd.h index 64867dc2..380b03ed 100644 --- a/opennurbs_subd.h +++ b/opennurbs_subd.h @@ -387,7 +387,20 @@ public: /// static const ON_SubDEdgeSharpness Nan; - + /// + /// Create a text string describing the sharpness as a percentage. + /// If the sharpness is constant, and single percentage is returned. + /// If the sharpness is variable, percentage range returned. + /// If the sharpness is not valid, a warning sign is returned. + /// + /// + /// If the sharpness is not constant and bOrderMinToMax is true, then + /// the string has the format min%-max%. + /// If the sharpness is not constant and bOrderMinToMax is false, then + /// the string has the format EndSharpness(0)%-EndSharpness(1)%. + /// + /// A string describing the sharpness as a percentage range. + const ON_wString ToPercentageText(bool bOrderMinToMax) const; /// /// Create a text string describing the sharpness as a percentage. @@ -408,28 +421,12 @@ public: /// /// /// - /// If 0 <= sharpenss <= ON_SubDEdgeSharpness::MaximumValue, then 100.0*sharpenss/ON_SubDEdgeSharpness::MaximumValue is returned. - /// If sharpenss = ON_SubDEdgeSharpness::CreaseValue, then crease_percentage is returned. + /// If 0 <= sharpness <= ON_SubDEdgeSharpness::MaximumValue, then 100.0*sharpness/ON_SubDEdgeSharpness::MaximumValue is returned. + /// If sharpness = ON_SubDEdgeSharpness::CreaseValue, then crease_percentage is returned. /// Otherwise ON_DBL_QNAN is returned. /// static double ToPercentage(double sharpness, double crease_percentage); - /// - /// Create a text string describing the sharpness as a percentage. - /// If the sharpenss is constant, and single percentage is returned. - /// If the sharpenss is varable, percentage range returned. - /// If the sharpness is not valid, a warning sign is returned. - /// - /// - /// If the sharpness is not contanst and bVarableMinToMax is true, then - /// the string has the format min%-max%. - /// If the sharpness is not contanst and bVarableMinToMax is false, then - /// the string has the format EndSharpness(0)%-EndSharpness(1)%. - /// - /// A string describing the sharpness as a percentage range. - const ON_wString ToPercentageText( bool bVarableMinToMax ) const; - - /// /// If the sharpness value is valid and contant, returns true. /// Otherwise returns false. @@ -2060,7 +2057,25 @@ public: // or x = ON_SubDComponentPtr::Create(...). ON__UINT_PTR m_ptr; - static const ON_SubDComponentPtr Null; // // nullptr, type = unset, mark = 0 + /// + /// nullptr, type = Unset, direction = 0 + /// + static const ON_SubDComponentPtr Null; + + /// + /// nullptr, type = Vertex, direction = 0 + /// + static const ON_SubDComponentPtr NullVertex; + + /// + /// nullptr, type = Edge, direction = 0 + /// + static const ON_SubDComponentPtr NullEdge; + + /// + /// nullptr, type = Face, direction = 0 + /// + static const ON_SubDComponentPtr NullFace; /// /// ON_SubDComponentPtr::Type identifies the type of subdivision component referenced by @@ -2105,6 +2120,15 @@ public: const ON_SubDComponentPtr* b ); + /* + Description: + Dictionary compares type and ComponentBase() id. + */ + static int CompareComponentId( + const ON_SubDComponentPtr* a, + const ON_SubDComponentPtr* b + ); + /* Description: Dictionary compares type, ComponentBase() pointer as an unsigned, @@ -14498,6 +14522,7 @@ public: /// /// Get the edge's sharpness at the end with the specified vertex. + /// If the edge is a crease, ON_SubDEdgeSharpness::Smooth is returned. /// See ON_SubDEdge::IsSharp() for more information about sharp edges. /// /// End index (0=start or 1=end). @@ -14511,6 +14536,25 @@ public: unsigned evi ) const; + /// + /// Get the edge's sharpness at the end with the specified vertex. + /// See ON_SubDEdge::IsSharp() for more information about sharp edges. + /// + /// End index (0=start or 1=end). + /// + /// If the edge is a crease and bUseCreaseSharpness is false, then ON_SubDEdgeSharpness::Smooth is returned. + /// If the edge is a crease and bUseCreaseSharpness is true, then ON_SubDEdgeSharpness::Crease is returned. + /// + /// + /// If the edge is sharp, the sharpness at the end with the specified by evi is returned. + /// If the edge is smooth or a crease, 0 is returned. + /// Otherwise, 0.0 is returned. + /// + /// The sharpness at the end of the edge specified by evi. + double EndSharpness( + unsigned evi, + bool bUseCreaseSharpness + ) const; /// /// Get the edge sharpenss values for the subdivided edge at the specified end of this edge. diff --git a/opennurbs_subd_data.cpp b/opennurbs_subd_data.cpp index 788eaf18..14b3e832 100644 --- a/opennurbs_subd_data.cpp +++ b/opennurbs_subd_data.cpp @@ -976,7 +976,7 @@ bool ON_SubDimple::Transform( break; } - if (level->m_face_count > 0 && level->m_face) + if (level->m_face_count > 0 && level->m_face[0]) { const ON_SubDMeshFragment* frag = level->m_face[0]->MeshFragments(); if (nullptr != frag) diff --git a/opennurbs_subd_data.h b/opennurbs_subd_data.h index efc3f80b..58322396 100644 --- a/opennurbs_subd_data.h +++ b/opennurbs_subd_data.h @@ -3450,7 +3450,7 @@ public: ON_SimpleArray& sector_control_net_points ) const; - bool SetCenterVertexTag(ON_SubDVertexTag center_vertex_tag); + bool SetCenterVertexTagAndCenterVertexEdgesTags(ON_SubDVertexTag center_vertex_tag); bool SetCenterVertexSharpness(double center_vertex_sharpness); diff --git a/opennurbs_subd_fragment.cpp b/opennurbs_subd_fragment.cpp index a8ac8026..83912c0b 100644 --- a/opennurbs_subd_fragment.cpp +++ b/opennurbs_subd_fragment.cpp @@ -580,7 +580,7 @@ bool ON_SubDMeshFragment::SetColorsFromCallback( T = nan3; const ON_SurfaceCurvature* K = CurvatureArray(subd_appearance); - const size_t Kstride = this->CurvatureArrayStride(subd_appearance); (nullptr != K) ? 1 : 0; + const size_t Kstride = (nullptr != K) ? CurvatureArrayStride(subd_appearance) : 0; if (nullptr == K) K = &ON_SurfaceCurvature::Nan; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index d255f557..00000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(ON_Test) - -# GoogleTest requires at least C++14 -set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/b10fad38c4026a29ea6561ab15fc4818170d1c10.zip -) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(googletest) - -enable_testing() - -add_subdirectory(../../opennurbs build_opennurbs) - -add_executable( - test_ClassSize - test_ClassSize.cpp -) - -target_link_libraries( - test_ClassSize - GTest::gtest_main - OpenNURBS -) - -include(GoogleTest) -gtest_discover_tests(test_ClassSize) \ No newline at end of file diff --git a/tests/Input/TestCSX.3dm b/tests/Input/TestCSX.3dm deleted file mode 100644 index 6d0bcceefc920ad36f30802b1574ad2018db69f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100103 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

>$zPMQ$ntHVWPxoDq6cujqQMVE#L@i+h^IP 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 B2toh= diff --git a/tests/Input/TestCurveCurveIntersection.3dm b/tests/Input/TestCurveCurveIntersection.3dm deleted file mode 100644 index e42b7de109045cb56210b298506fe39b63f79eb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 124349 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�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 diff --git a/tests/Input/mesh_clspt_test.3dm b/tests/Input/mesh_clspt_test.3dm deleted file mode 100644 index 12db65ce4a19412ddf3d03ea936ed7aa43afbeb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326101 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 diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 3362b2bc..00000000 --- a/tests/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Google Test and OpenNURBS - -This is a basic project to get OpenNURBS working with Google Test. - -Based on this Google Test Quickstart: https://google.github.io/googletest/quickstart-cmake.html - -## Associated files - -- rhino/src4/opennurbs/tests/test_ClassSize.cpp -- rhino/src4/opennurbs/tests/CMakeLists.txt - -## building & running - -- `cmake -S . -B build` -- `cmake --build build` -- `cd build && ctest` - -## Notes - -- Since `ON_WindowsDWriteFontInformation` isn't available for macos or linux, we have to comment out that test before building. -- 2023.12.28 On macos and linux the following tests fail: - - `ON_3dmRevisionHistory` 96 expected / 136 calculated - - `ON_3dmProperties` 512 expected / 552 calculated - - `ON_SleepLock` 4 expected / 1 calculated \ No newline at end of file diff --git a/tests/TestBase64.cpp b/tests/TestBase64.cpp deleted file mode 100644 index eeaff4d0..00000000 --- a/tests/TestBase64.cpp +++ /dev/null @@ -1,289 +0,0 @@ -#if 0 - -#include "opennurbs.h" - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// BEGIN TestBase64 command -// - -class CCommandTestBase64 : public CRhinoTestCommand -{ -public: - CCommandTestBase64() {} - ~CCommandTestBase64() {} - UUID CommandUUID() - { - // {2BE047C-CC30-4178-AFA5-136E79A4335C} - static const GUID TestBase64Command_UUID = - { 0x2BE047C, 0xCC30, 0x4178, { 0xAF, 0xA5, 0x13, 0x6E, 0x79, 0xA4, 0x33, 0x5C } }; - return TestBase64Command_UUID; - } - const wchar_t* EnglishCommandName() { return RHINOSTRING_COMMAND_NAME(L"TestBase64"); } - CRhinoCommand::result RunCommand( const CRhinoCommandContext& ); -}; - -// The one and only CCommandTestBase64 object -static class CCommandTestBase64 theTestBase64Command; - -class MyDecode : public ON_DecodeBase64 -{ -public: - const unsigned char* m_buf; - unsigned char* m_buf1; - int m_buf_count; - MyDecode(const unsigned char* buf, unsigned char* buf1); - void Output(); -}; - -MyDecode::MyDecode(const unsigned char* buf, unsigned char* buf1) : m_buf(buf), m_buf1(buf1), m_buf_count(0) -{ -} - -void MyDecode::Output() -{ - memcpy(m_buf1+m_buf_count,m_output,m_output_count); - m_buf_count += m_output_count; - - //for( int i = 0; i < m_output_count; i++ ) - //{ - // m_buf1[m_buf_count] = m_output[i]; - // if ( m_buf[m_buf_count++] != m_output[i] ) - // { - // m_buf_count--; - // SetError(); - // break; - // } - //} -} - -class MyEncode : public ON_EncodeBase64 -{ -public: - char* m_base64; - int m_base64_count; - MyEncode(char* p); - void Output(); -}; - -MyEncode::MyEncode(char* p) : m_base64(p), m_base64_count(0) {} - -void MyEncode::Output() -{ - if ( m_base64_count + m_output_count <= 4000 ) - { - memcpy(m_base64+m_base64_count,m_output,m_output_count); - m_base64_count += m_output_count; - m_base64[m_base64_count] = 0; - } -} - -bool Test64(const char* s, const char* e64) -{ - unsigned char buf[3000]; - char base64[4001]; - const int ec = ON_GetErrorCount(); - - const int buf_count = (int)strlen(s); - if ( buf_count > 3000 ) - return false; - - const int base64_count = 4*(buf_count/3) + ((buf_count%3)?4:0); - - memset(buf,0,sizeof(buf)); - memset(base64,0,sizeof(base64)); - MyEncode encode(base64); - MyDecode decode((unsigned char*)s,buf); - - encode.Begin(); - encode.Encode(s,buf_count); - encode.End(); - - if ( ec != ON_GetErrorCount() ) - return false; - - if ( buf_count != encode.m_encode_count ) - return false; - - if ( base64_count != encode.m_base64_count ) - return false; - - if ( strcmp(base64,e64) ) - return false; - - decode.Begin(); - decode.Decode(e64); - decode.End(); - - if ( ec != ON_GetErrorCount() ) - return false; - - if ( base64_count != decode.m_decode_count ) - return false; - - if ( buf_count != decode.m_buf_count ) - return false; - - if ( strcmp((const char*)buf,s) ) - return false; - - return true; -} - -CRhinoCommand::result CCommandTestBase64::RunCommand( const CRhinoCommandContext& context ) -{ - unsigned char buf[3000]; - unsigned char buf1[3000]; - char base64[4001]; - int ec = ON_GetErrorCount(); - int jjj; - - memset(buf,0,sizeof(buf)); - memset(base64,0,sizeof(base64)); - MyEncode encode(base64); - MyDecode decode(buf,buf1); - - { - bool b; - b = Test64("This is a test", "VGhpcyBpcyBhIHRlc3Q="); - if ( b) - b = Test64("This is a test1", "VGhpcyBpcyBhIHRlc3Qx"); - if (b) - b = Test64("This is a test12","VGhpcyBpcyBhIHRlc3QxMg=="); - if ( !b) - { - ON_ERROR("tests failed"); - } - } - - for ( int buf_count = 1; buf_count <= 64; buf_count++) - { - RhinoApp().Print("buf_count %d\n",buf_count); - const int base64_count = 4*(buf_count/3) + ((buf_count%3)?4:0); - - for ( int buf_index = 0; buf_index < buf_count; buf_index++ ) - for ( int buf_val = 0; buf_val < 256; buf_val++ ) - for ( int val_count = 1; val_count <= 5; val_count++ ) - { - int ii=-99; - ec = ON_GetErrorCount(); - for ( int attempt = 0; attempt <= 2; attempt++ ) - { - if ( attempt ) - { - int tryagain = 123; - } - - memset(buf,0,buf_count+6); - memset(base64,0,base64_count); - - for ( jjj = 0; jjj < val_count; jjj++ ) - buf[buf_index+jjj] = (buf_val+jjj)%256; - - buf1[0] = buf[0] ? 0 : 0xFF; - buf1[buf_count-1] = buf[buf_count-1] ? 0 : 0xFF; - buf1[buf_count] = buf[buf_count]; - - encode.m_base64_count = 0; - encode.Begin(); - encode.Encode(buf,buf_count); - encode.End(); - - - if ( encode.m_encode_count != buf_count ) - { - ON_ERROR("encode - encode.m_encode_count != buf_count"); - continue; - } - if ( encode.m_base64_count != base64_count ) - { - ON_ERROR("encode - encode.m_base64_count != base64_count"); - continue; - } - - for ( ii = 0; ii < base64_count; ii++ ) - { - const char* ss; - int sz; - decode.m_buf_count = 0; - decode.Begin(); - char c = base64[ii]; - - if ( ii > 0 ) - { - base64[ii] = 0; - ss = decode.Decode(base64); - if ( !ss || decode.Error() ) - { - ON_ERROR("decode - first block error"); - break; - } - sz = (int)(ss-base64); - if ( sz != ii || decode.Error() ) - { - ON_ERROR("decode - first block trauma"); - break; - } - base64[ii] = c; - } - - ss = decode.Decode(base64+ii); - if ( !ss || decode.Error() ) - { - ON_ERROR("decode - 2nd block error"); - break; - } - sz = (int)(ss-base64); - if ( sz != base64_count || decode.Error() ) - { - ON_ERROR("decode - 2nd block trauma"); - break; - } - - if ( !decode.End() ) - { - ON_ERROR("decode - error"); - break; - } - - if ( decode.m_decode_count != base64_count ) - { - ON_ERROR("decode decode.m_decode_count != base64_count"); - break; - } - - if ( memcmp(buf,buf1,buf_count+1) ) - { - ON_ERROR("decode failure"); - break; - } - - break; - - if ( ii > 8 && ii < base64_count-8 ) - { - if ( ii < base64_count/2 ) - ii = base64_count/2; - else - ii = base64_count-8; - } - } - if ( 0 == attempt && ec == ON_GetErrorCount() ) - { - break; // no errors - no need to repeat - } - } - } - } - return CRhinoCommand::success; -} - -// -// END TestBase64 command -// -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// - -#endif diff --git a/tests/TestBooleanUnion.cpp b/tests/TestBooleanUnion.cpp deleted file mode 100644 index 21b0ca83..00000000 --- a/tests/TestBooleanUnion.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* $Header: /src4/opennurbs/Tests/TestBooleanUnion.cpp 1 2/11/05 6:32a Dalelear $ */ -/* $NoKeywords: $ */ - -#include "Tests.h" - -void TestBooleanUnion( - const ON_Brep* brepA, const wchar_t* nameA - const ON_Brep* brepB, const wchar_t* nameB - ) -{ - // todo test this union -} - -void TestBooleanUnion( ON_TextLog& text_log ) -{ - TEST_HEADER(text_log,"TestBooleanUnion"); - - ONX_Model model; - int i, pass; - - double sample_start_distance = 0.0; - double sample_stop_distance = 0.0; - - const char* filename = "\\src4\\opennurbs\\Tests\\Input\\TestBooleanUnion.3dm"; - //const char* filename = "\\src4\\opennurbs\\Tests\\Input\\SmallTest.3dm"; - - ON_SimpleArray brep; - ON_ClassArray brep_name; - - if ( model.Read( filename,&text_log) ) - { - brep.Reserve(model.m_object_table.Count()); - brep_name.Reserve(model.m_object_table.Count()); - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Brep* b = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( b ) - { - const wchar_t* name = model.m_object_table[i].m_attributes.m_name; - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - brep_name.AppendNew() = name; - brep.Append(brep); - } - } - } - - const wchar_t *nameA, *nameB; - const ON_Brep *brepA, *brepB; - for ( i = 0; i < brep.Count(); i++ ) - { - brepA = brep[i]; - nameA = brep_name[i]; - for ( j = i+1; j < brep.Count(); j++ ) - { - brepB = brep[j]; - nameB = brep_name[j]; - TestBooleanUnion( brepA,nameA,brepB,nameB); - TestBooleanUnion( brepB,nameB,brepA,nameA); - } - } - -} - - diff --git a/tests/TestClosestPoint.cpp b/tests/TestClosestPoint.cpp deleted file mode 100644 index 07d12243..00000000 --- a/tests/TestClosestPoint.cpp +++ /dev/null @@ -1,3670 +0,0 @@ -/* $Header: /src4/opennurbs/Tests/TestClosestPoint.cpp 36 10/07/05 4:27p Dalelear $ */ -/* $NoKeywords: $ */ - -#include "Tests.h" - -static const bool bPurify = false; -static const bool bDoPoints = true; -static const bool bSmallTest = false; -static const bool bDoGooseTests = false; // SLOW - -static void CCXHelper3( const ON_CurveTreeNode* nodeA, const ON_CurveTreeNode* nodeB, - double tol3d, - ON_SimpleArray& ccx - ) -{ - // third level checker for CCX - both nodes are bottom level - // leaves with m_bez != NULL - const ON_CurveTreeBezier& bezA = *nodeA->m_bez; - const ON_CurveTreeBezier& bezB = *nodeB->m_bez; - double a, b; - ON_3dPoint A, B; - bezA.m_leafbox.GetClosestPointSeed( bezB.m_leafbox,&a,&b ); - - // TODO - call 2d solver here - - // make sure results are ok. - A = bezA.PointAt(a); - B = bezB.PointAt(b); - if ( A.DistanceTo(B) <= tol3d ) - { - TL_CX_EVENT& x = ccx.AppendNew(); - x.A[0] = A; - x.A[1] = A; - x.B[0] = B; - x.B[1] = B; - x.a[0] = x.a[1] = nodeA->m_domain.ParameterAt(a); - x.b[0] = x.b[1] = x.b[2] = x.b[3] = nodeB->m_domain.ParameterAt(b); - x.type = TL_CCX_POINT; - x.cnodeA[0] = nodeA; - x.cnodeB[0] = nodeB; - x.x[0] = A.DistanceTo(B); - } -} - -static void CCXHelper1( const ON_CurveTreeNode* nodeA, const ON_CurveTreeNode* nodeB, - double tol3d, - ON_SimpleArray& ccx - ); - -static void CCXHelper2( const ON_CurveTreeNode* nodeA, const ON_CurveTreeNode* nodeB, - double tol3d, - ON_SimpleArray& ccx - ) -{ - // second level checker for CCX - both nodes have m_bez != NULL and valid leaf boxes - // but they may have down nodes - if ( nodeA->m_down[0] || nodeA->m_down[1] ) - { - if ( (nodeB->m_down[0] || nodeB->m_down[1]) - && (nodeA->m_bez->m_leafbox.m_L.Length() <= nodeB->m_bez->m_leafbox.m_L.Length()) ) - { - // nodeB is bigger, split it - CCXHelper1( nodeA, nodeB->m_down[0], tol3d, ccx ); - CCXHelper1( nodeA, nodeB->m_down[1], tol3d, ccx ); - } - else - { - // nodeA is bigger, split t - CCXHelper1( nodeA->m_down[0], nodeB, tol3d, ccx ); - CCXHelper1( nodeA->m_down[1], nodeB, tol3d, ccx ); - } - } - else if ( nodeB->m_down[0] || nodeB->m_down[1] ) - { - CCXHelper1( nodeA, nodeB->m_down[0], tol3d, ccx ); - CCXHelper1( nodeA, nodeB->m_down[1], tol3d, ccx ); - } - else - { - // time to look fot intersections on leaves - CCXHelper3( nodeA, nodeB, tol3d, ccx ); - } -} - -static void CCXHelper1( const ON_CurveTreeNode* nodeA, const ON_CurveTreeNode* nodeB, - double tol3d, - ON_SimpleArray& ccx - ) -{ - // first level checker for CCX - double a,b; - if ( !nodeA ) - return; - if ( !nodeB ) - return; - if ( nodeA->IsFartherThan(tol3d,nodeB) ) - { - return; - } - if ( nodeA->m_bez ) - { - if ( nodeB->m_bez ) - { - CCXHelper2( nodeA, nodeB, tol3d, ccx ); - } - else - { - CCXHelper1(nodeA,nodeB->m_down[0],tol3d,ccx); - CCXHelper1(nodeA,nodeB->m_down[1],tol3d,ccx); - } - } - else if ( nodeB->m_bez ) - { - if ( nodeA->m_bez ) - { - CCXHelper2( nodeA, nodeB, tol3d, ccx ); - } - else - { - CCXHelper1(nodeA->m_down[0],nodeB,tol3d,ccx); - CCXHelper1(nodeA->m_down[1],nodeB,tol3d,ccx); - } - } - else - { - a = nodeA->m_bbox.Diagonal().LengthSquared(); - b = nodeB->m_bbox.Diagonal().LengthSquared(); - if ( a <= b ) - { - CCXHelper1(nodeA,nodeB->m_down[0],tol3d,ccx); - CCXHelper1(nodeA,nodeB->m_down[1],tol3d,ccx); - } - else - { - CCXHelper1(nodeA->m_down[0],nodeB,tol3d,ccx); - CCXHelper1(nodeA->m_down[1],nodeB,tol3d,ccx); - } - } -} - - -void DaleCCX( const ON_Curve& curveA, - const ON_Curve& curveB, - double tol3d, - ON_SimpleArray& ccx - ) -{ - ON_SimpleArray xxx(16); - curveA.IntersectCurve(&curveB,xxx,tol3d); - for(int i=0; im_root, treeB->m_root, tol3d, ccx ); - - /* - while ( i < ccx.Count() ) - { - bRedo = false; - TL_CX_EVENT& e = ccx[i++]; - A = curveA.PointAt(e.a[0]); - B = curveB.PointAt(e.b[0]); - d = A.DistanceTo(B); - if ( d > tol3d ) - bRedo = true; - } - - if ( bRedo ) - { - CCXHelper1( treeA->m_root, treeB->m_root, tol3d, ccx ); - } - */ -} - - - - -class EF -{ -public: - const ON_CurveTree* ct; - const ON_CurveTreeNode* node; - ON_3dPoint P; - ON_BezierCurve b; - double d; - double s; // bezier parameter - double t; // curve parameter - int local_solves; -}; - - -class Greg_farg -{ -public: - const ON_BezierCurve* bez; - ON_3dPoint P; - double GregLocalSolveAbsThresh2; -}; - -static -int GregDistance2CrvPtHess(void* fdata, int n, const double* x, double& fx, double* df, double** Hess){ - Greg_farg* farg = (Greg_farg*) fdata; - ON_3dVector CEval[3]; - ON_3dVector& C=CEval[0]; - ON_3dVector& Ct=CEval[1]; - ON_3dVector& Ctt=CEval[2]; - ON_BOOL32 rc = farg->bez->Evaluate(*x,(Hess)?2:1,3,CEval[0]); - for(int i=farg->bez->Dimension(); i<3; i++) - CEval[0][i]=CEval[1][i]=CEval[2][i] = 0.0; - C -= farg->P; - fx = C*C; - if(df) - *df = 2 * C* Ct; - if(Hess && *Hess) - Hess[0][0] = 2.0 * ( Ct*Ct + Ctt*C); - if( fx <= farg->GregLocalSolveAbsThresh2 ) - return 2; - return rc?1:-1; -} - -int ClosestForkHelper_dbrent( EF& ef, const ON_CurveTreeNode* node ) -{ - const ON_CurveTreeBezier* bez = node->m_bez; - - ON_3dPoint Q; - double x, w, t; - int i; - - ef.local_solves++; - - // set "t" to best guess based on the line. - bez->m_leafbox.GetClosestPointSeed(ef.P,&t); - - if ( 2 == bez->m_order && !bez->m_is_rat ) - { - Q = bez->PointAt(t); - w = Q.DistanceTo(ef.P); - if ( ef.d < 0.0 || w < ef.d ) - { - ef.d = w; - ef.s = t; - ef.t = node->m_domain.ParameterAt(ef.s); - ef.node = node; - return 1; - } - return 0; - } - - if ( ef.b.m_dim != bez->m_dim || ef.b.m_is_rat != bez->m_is_rat || ef.b.m_order != bez->m_order ) - { - ef.b.m_dim = bez->m_dim; - ef.b.m_is_rat = bez->m_is_rat; - ef.b.m_cv_stride = bez->m_cv_stride; - ef.b.m_order = bez->m_order; - ef.b.ReserveCVCapacity(ef.b.m_cv_stride*ef.b.m_order); - } - double *cv = ef.b.m_cv; - memcpy( cv, bez->m_cv, ef.b.m_cv_stride*ef.b.m_order*sizeof(*cv)); - i = ef.b.m_order; - if ( ef.b.m_is_rat ) - { - while(i--) - { - w = cv[3]; - x = 1.0/w; - cv[0] = w*(x*cv[0] - ef.P.x); - cv[1] = w*(x*cv[1] - ef.P.y); - cv[2] = w*(x*cv[2] - ef.P.z); - cv += 4; - } - } - else - { - while(i--) - { - *cv++ -= ef.P.x; - *cv++ -= ef.P.y; - *cv++ -= ef.P.z; - } - } - - i = TL_EvBezierLocalExtremum( - 0, // means look for a local min - ef.b.m_dim, ef.b.m_is_rat, ef.b.m_order, - ef.b.m_cv, - 0.0,1.0, // search entire bezier from 0.0 <= s <= 1.0 - 0.0, // stop search if a distance of 0.0 is found - 0.5*ON_SQRT_EPSILON, // step tol - &t); - - Q = bez->PointAt(t); - x = Q.DistanceTo(ef.P); - - if ( x < ef.d || ef.d < 0.0 ) - { - ef.s = t; - ef.t = node->m_domain.ParameterAt(ef.s); - ef.d = x; - ef.node = node; - i = 1; - } - else - { - i = 0; - } - return i; -} - -class CGooseEv : public IwEvalFunctionObject -{ -public: - const ON_CurveTreeBezier& m_bez; - const IwPoint3d m_crTestPoint; - double m_dSquaredTolerance; - IwSolverOperationType m_eSolverOperation; - IwBoolean m_bHaveScale; - ULONG m_lNumScale; - - CGooseEv(const EF& ef, const ON_CurveTreeNode* node, - double dSquaredTolerance, IwSolverOperationType eSolverOperation) - : m_bez(*node->m_bez), - m_crTestPoint(ef.P.x,ef.P.y,ef.P.z), - m_dSquaredTolerance(dSquaredTolerance), - m_eSolverOperation(eSolverOperation), - m_bHaveScale(false), m_lNumScale(0) {} - - IwStatus Evaluate(double dT, - double & rdFOfT, - double & rdFPrimeOfT, - IwBoolean & rbFoundAnswer); -}; - -IwStatus CGooseEv::Evaluate(double dT, - double & rdFOfT, - double & rdFPrimeOfT, - IwBoolean & rbFoundAnswer) -{ - rbFoundAnswer = false; - IwPoint3d sPVV[3]; - - // put pt, 1rst, 2nd der in sPVV - m_bez.Evaluate(dT,2,3,&sPVV[0].x); - //SER(m_crCurve.Evaluate(dT,2,true,sPVV)); - - IwVector3d sVec = sPVV[0] - m_crTestPoint; - - // Scale the problem down to a reasonable size (0-100) - if (!m_bHaveScale) { - while (sPVV[1].LengthSquared() > 1.0e4) { - m_lNumScale ++; - sVec = sVec / 10.0; - sPVV[0] = sPVV[0] / 10.0; - sPVV[1] = sPVV[1] / 10.0; - sPVV[2] = sPVV[2] / 10.0; - } - m_bHaveScale = true; - } - else { - for (ULONG kk=0; kkm_bez->m_leafbox.GetClosestPointSeed(ef.P,&t); - - CGooseEv sEFO(ef,node,IW_EFF_ZERO_SQ,IW_SO_MINIMIZE); - IwLocalSolve1d sLS(sEFO, IwExtent1d(0.0,1.0), false); - IwBoolean bFoundSolution; - double dFoundT; - if (sLS.SolveIt(t,1.0e-8,bFoundSolution,dFoundT) != IW_SUCCESS) - { - // Goose failed - use foolproof method. - ClosestForkHelper_dbrent(ef,node); - } - else - { - ON_3dPoint Q = node->m_bez->PointAt(dFoundT); - double d = Q.DistanceTo(ef.P); - if ( ef.d < 0.0 || d < ef.d ) - { - ef.s = dFoundT; - ef.t = node->m_domain.ParameterAt(ef.s); - ef.d = d; - ef.node = node; - } - } - - return 1; -} - -static bool ClosestFork( EF& ef, double d, ON_CurveTreeNode* node ) -{ - double downd[2]; - int i; - bool rc = false; - - if ( ef.d > 0.0 ) - { - if ( d < 0.0 ) - { - d = node->MinimumDistanceLowerBound(ef.P); - } - if ( d > ef.d ) - return false; - } - - if ( node->m_down[0] ) - { - if ( node->m_down[1] ) - { - downd[0] = node->m_down[0]->MinimumDistanceLowerBound(ef.P); - downd[1] = node->m_down[1]->MinimumDistanceLowerBound(ef.P); - i = ( downd[0] <= downd[1] ) ? 0 : 1; - if ( ef.d < 0.0 || downd[i] < ef.d ) - { - rc = ClosestFork( ef, downd[i], node->m_down[i] ); - if ( ef.d < 0.0 || downd[1-i] < ef.d ) - { - if ( ClosestFork( ef, downd[1-i], node->m_down[1-i] ) ) - { - rc = true; - } - } - } - } - else - { - rc = ClosestFork( ef, ON_UNSET_VALUE, node->m_down[0] ); - } - } - else if ( node->m_down[1] ) - { - rc = ClosestFork( ef, ON_UNSET_VALUE, node->m_down[1] ); - } - else if ( node->m_bez ) - { - // it's a leaf - if ( ClosestForkHelper_hybrid(ef,node) ) - { - rc = true; - } - } - - return rc; -} - -class CPolishUp : public ON_NurbsCurve -{ -public: - ON_3dPoint m_P; -}; - -static void fff(void* farg,double t,double* x,double* dx) -{ - ON_3dVector V[3]; - double d; - CPolishUp* p = (CPolishUp*)farg; - - ON_EvaluateNurbsSpan( - p->m_dim, p->m_is_rat, p->m_order, - p->m_knot, - p->m_cv_stride, p->m_cv, - dx?2:1, //der_count, - t, - 3, //v_stride, - &V[0].x - ); - - V[0].x -= p->m_P.x; - V[0].y -= p->m_P.y; - V[0].z -= p->m_P.z; - - d = V[0].x*V[1].x + V[0].y*V[1].y + V[0].z*V[1].z; - *x = d; - if ( dx ) - { - *dx = V[0].x*V[2].x + V[0].y*V[2].y + V[0].z*V[2].z -(V[1].x*V[1].x + V[1].y*V[1].y + V[1].z*V[1].z); - } -} - -class CCurveTestPoint -{ -public: - int test_point_index; - - ON_3dPoint P; // test point = C + d*(variable unit vector) - double t; - double d; - - // The information below is filled in during accuracy testing phase - - enum FUNC_CRV_CLSPT - { - FUNC_CRV_CLSPT_NONE = 0, - FUNC_CRV_CLSPT_BASELINE = 1, // Dale's new tree with hybrid newton/debrent local solve - FUNC_CRV_CLSPT_ON_TREETEST = 2, // Used to determine where code is spending time - FUNC_CRV_CLSPT_ON_CRV = 3, // Generic ON_Curve::GetClosestPoint() - FUNC_CRV_CLSPT_ON_NURBS = 4, // OpenNurbs ON_NurbsCurve::GetClosestPoint() - FUNC_CRV_CLSPT_GOOSE = 5, // old gslib - FUNC_CRV_CLSPT_COUNT = 6 - }; - - // paramter of closest point - double crv_t[FUNC_CRV_CLSPT_COUNT]; - - // distance from P to - double crv_d[FUNC_CRV_CLSPT_COUNT]; - - // best result from a test - double best_t; - double best_d; -}; - - -void GetCurvePointCloud( const ON_Curve& curve, - double sample_start_distance, - double sample_stop_distance, - ON_SimpleArray& CPT ) -{ - // appends a cloud of points to pts. - int hint = 0; - int i,j,k,n,m; - - ON_Plane plane; - ON_3dPoint P; - ON_3dVector T; - ON_Interval span_domain; - double r, a, t; - - if ( sample_start_distance >= sample_stop_distance ) - sample_start_distance = sample_stop_distance; - - int span_count = curve.SpanCount(); - if (span_count < 1 ) - { - return; - } - double* span_vector = (double*)onmalloc((span_count+1)*sizeof(*span_vector)); - if ( !curve.GetSpanVector(span_vector)) - return; - - int degree = curve.Degree(); - - int span_sample_count = 4*3*5*7; - if ( sample_stop_distance <= 0.0 ) - { - k = 1; - } - else - { - k = 0; - for ( r = sample_start_distance; r <= sample_stop_distance*(1.0+ON_SQRT_EPSILON); r *= 2.0 ) - { - k++; - } - if ( k < 1 ) - k = 1; - k *= 4; - } - - - while ( span_count*span_sample_count*k < 30000 ) - { - span_sample_count *= 2; - } - - if ( degree <= 2 && span_count <= 4 ) - { - while ( span_count*span_sample_count*k < 60000 ) - span_sample_count *= 2; - } - - if ( bPurify ) - { - // reduce sample counts so purify will finish somtime today - span_sample_count = 3; - sample_stop_distance = sample_start_distance; - } - - CPT.Reserve(span_count*span_sample_count*17); - - for (i = 0; i < span_count; i++ ) - { - span_domain.Set(span_vector[i],span_vector[i+1]); - for ( j = i?0:1; j <= span_sample_count; j++ ) - { - t = span_domain.ParameterAt(((double)j)/((double)span_sample_count)); - curve.EvTangent(t,P,T,1,&hint); - plane.CreateFromNormal(P,T); - - if ( sample_stop_distance <= 0.0 ) - { - CCurveTestPoint& CP = CPT.AppendNew(); - CP.test_point_index = CPT.Count()-1; - CP.P = P; - CP.t = t; - CP.d = 0.0; - CP.best_t = ON_UNSET_VALUE; - CP.best_d = ON_UNSET_VALUE; - for( m = 0; m < CCurveTestPoint::FUNC_CRV_CLSPT_COUNT; m++ ) - { - CP.crv_d[m] = ON_UNSET_VALUE; - CP.crv_t[m] = ON_UNSET_VALUE; - } - } - else - { - k = 0; - for ( r = sample_start_distance; r <= sample_stop_distance*(1.0+ON_SQRT_EPSILON); r *= 2.0 ) - { - for ( n = 0; n <= 4; n++ ) - { - CCurveTestPoint& CP = CPT.AppendNew(); - CP.test_point_index = CPT.Count()-1; - a = (k/6.0 + n*0.5)*ON_PI; - CP.P = plane.origin + r*(cos(a)*plane.xaxis + sin(a)*plane.yaxis); - CP.t = t; - CP.d = P.DistanceTo(CP.P); - CP.best_t = ON_UNSET_VALUE; - CP.best_d = ON_UNSET_VALUE; - for( m = 0; m < CCurveTestPoint::FUNC_CRV_CLSPT_COUNT; m++ ) - { - CP.crv_d[m] = ON_UNSET_VALUE; - CP.crv_t[m] = ON_UNSET_VALUE; - } - if ( 0.0 == r ) - break; - } - k++; - } - } - } - } - onfree(span_vector); - - // FOR DEBUGGING A CLOSEST POINT TO CURVE BAD POINT - int singleton_index = -1; - if ( singleton_index >= 0 && singleton_index < CPT.Count() ) - { - CPT[0] = CPT[singleton_index]; - CPT.SetCount(1); - } -} - -class CClosestPointToCurveTestResults -{ -public: - bool m_bSpeedTest; - bool m_bAccuracyTest; - double m_elapsed_time; - double m_speed_factor; // =m_elapsed_time/best_time. 1 = best, > 1 means slower than the best - - double m_on_curve_3d_error; // average absolute 3d distance error for points on the curve - double m_on_curve_t_error; // relative t error for points on the curve - - double m_off_curve_3d_error; // average relative error for points away from the curve - double m_off_curve_t_error; // relative t error for points on the curve - - int m_test_count; // total number of tests - int m_failure_count; // number of failures to return any answer - - int m_error_count; // number of calls to ON_Error - int m_warning_count; // number of calls to ON_Warning - - int m_on_test_count; - int m_on_best_count; - int m_on_sloppy_count; // number of sloppy answers for points on the curve - int m_on_wrong_count; // number of wrong answers for points on the curve - - int m_off_test_count; - int m_off_best_count; // number of times this got the best answer - int m_off_sloppy_count; // number of sloppy answers for points off of the curve - int m_off_wrong_count; // number of wrong answers for points off of the curve - -}; - -class CClosestPointToSurfaceTestResults -{ -public: - bool m_bSpeedTest; - bool m_bAccuracyTest; - double m_elapsed_time; - double m_speed_factor; // =m_elapsed_time/best_time. 1 = best, > 1 means slower than the best - - double m_on_surface_3d_error; // average absolute 3d distance error for points on the surface - ON_2dVector m_on_surface_uv_error; // relative t error for points on the surface - - double m_off_surface_3d_error; // average relative error for points away from the surface - ON_2dVector m_off_surface_uv_error; // relative t error for points on the surface - - int m_test_count; // total number of tests - int m_failure_count; // number of failures to return any answer - - int m_error_count; // number of calls to ON_Error - int m_warning_count; // number of calls to ON_Warning - - int m_on_test_count; - int m_on_best_count; - int m_on_sloppy_count; // number of sloppy answers for points on the surface - int m_on_wrong_count; // number of wrong answers for points on the surface - - int m_off_test_count; - int m_off_best_count; // number of times this got the best answer - int m_off_sloppy_count; // number of sloppy answers for points off of the surface - int m_off_wrong_count; // number of wrong answers for points off of the surface - -}; - -class CClosestPointToMeshTestResults -{ -public: - bool m_bSpeedTest; - bool m_bAccuracyTest; - double m_mesh_elapsed_time; - double m_surface_elapsed_time; - double m_speed_factor; // =m_mesh_elapsed_time/m_surface_elapsed_time; (bigger = slower) - - double m_on_mesh_3d_error; // average absolute 3d distance error for points on the mesh - - double m_off_mesh_3d_error; // average relative error for points away from the mesh - - int m_test_count; // total number of tests - int m_failure_count; // number of failures to return any answer - - int m_error_count; // number of calls to ON_Error - int m_warning_count; // number of calls to ON_Warning - - int m_on_test_count; - int m_on_best_count; - int m_on_sloppy_count; // number of sloppy answers for points on the mesh - int m_on_wrong_count; // number of wrong answers for points on the mesh - - int m_off_test_count; - int m_off_best_count; // number of times this got the best answer - int m_off_sloppy_count; // number of sloppy answers for points off of the mesh - int m_off_wrong_count; // number of wrong answers for points off of the mesh -}; - - -class CClosestPointToCurveTest -{ -public: - virtual void Setup( const ON_Curve* curve ) = 0; - - virtual int GetClosestPoint( ON_3dPoint P, double* t ) = 0; - - // returns time in seconds - double SpeedTest( int test_point_count, const CCurveTestPoint* tp); - - // returns error count - int AccuracyTest( int test_point_count, CCurveTestPoint* tp ); - - void CalculateResults( const ON_Curve& curve, - int test_point_count, - const CCurveTestPoint* tp, - double best_time - ); - - void Print( ON_TextLog& text_log, int test_count ); - - CCurveTestPoint::FUNC_CRV_CLSPT m_func; - - //const ON_NurbsCurve* m_nurbs_curve; - const ON_Curve* m_curve; - - CClosestPointToCurveTestResults m_results; - - void SetupHelper( CCurveTestPoint::FUNC_CRV_CLSPT func, const ON_Curve* curve ); -}; - -void CClosestPointToCurveTest::SetupHelper( CCurveTestPoint::FUNC_CRV_CLSPT func, const ON_Curve* curve ) -{ - m_func = func; - m_curve = curve; - memset(&m_results,0,sizeof(m_results)); - m_results.m_elapsed_time = ON_UNSET_VALUE; -} - -double CClosestPointToCurveTest::SpeedTest(int point_count, const CCurveTestPoint* tp) -{ - double t; - int i; - clock_t time0, time1; - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - i = point_count; - time0 = clock(); - while(i--) - { - t = ON_UNSET_VALUE; - GetClosestPoint(tp->P,&t); - tp++; - } - time1 = clock(); - - m_results.m_elapsed_time = ((double)(time1 - time0))/((double)CLOCKS_PER_SEC); - - m_results.m_bSpeedTest = true; - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return m_results.m_elapsed_time; -} - -int CClosestPointToCurveTest::AccuracyTest(int point_count, CCurveTestPoint* tp) -{ - ON_3dPoint Q; - double d; - int rc = 0; - int i; - double t; - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - m_results.m_bAccuracyTest = true; - m_results.m_test_count = point_count; - - for ( i = 0; i < point_count; i++ ) - { - t = ON_UNSET_VALUE; - if( !GetClosestPoint(tp[i].P,&t) ) - { - rc++; - tp[i].crv_t[m_func] = ON_UNSET_VALUE; - tp[i].crv_d[m_func] = ON_UNSET_VALUE; - m_results.m_failure_count++; - } - else - { - Q = m_curve->PointAt(t); - d = Q.DistanceTo(tp[i].P); - tp[i].crv_t[m_func] = t; - tp[i].crv_d[m_func] = d; - if ( ON_UNSET_VALUE == tp[i].best_d || d < tp[i].best_d ) - { - tp[i].best_d = d; - tp[i].best_t = t; - } - } - } - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return rc; -} - - -void CClosestPointToCurveTest::CalculateResults( const ON_Curve& curve, - int test_point_count, - const CCurveTestPoint* tp, - double best_time - ) -{ - int badi = -1; - double badd = 0.0; - m_results.m_speed_factor = (m_results.m_bSpeedTest && best_time>0.0) ? m_results.m_elapsed_time/best_time : 0.0; - if ( m_results.m_bAccuracyTest ) - { - ON_Sum on_3d_error; - ON_Sum off_3d_error; - ON_Sum on_t_error; - ON_Sum off_t_error; - double d_err, t_err; - int i; - int hint = 0; - ON_3dPoint P; - ON_3dVector D; - for ( i = 0; i < test_point_count; i++ ) - { - const CCurveTestPoint& T = tp[i]; - - if ( !ON_IsValid(T.crv_t[m_func]) ) - continue; - - curve.Ev1Der( T.best_t, P, D, 1, &hint ); - - t_err = D.Length(); - t_err = ( t_err > ON_ZERO_TOLERANCE ) ? 1.0/t_err : 0.0; - t_err *= fabs(T.crv_t[m_func] - T.best_t); - - d_err = (T.best_d < T.d) ? T.best_d : T.d; - - d_err = T.crv_d[m_func] - d_err; - if ( 0.0 == T.d || 0.0 == T.best_d ) - { - m_results.m_on_test_count++; - - if ( T.crv_d[m_func] <= T.best_d ) - { - m_results.m_on_best_count++; - t_err = 0.0; - } - if ( d_err > 1.0e-4 ) - { - m_results.m_on_wrong_count++; - if ( CCurveTestPoint::FUNC_CRV_CLSPT_GOOSE != m_func && d_err > badd ) - { - badd = d_err; - badi = T.test_point_index; - } - } - else if ( d_err > 1.0e-6 ) - { - m_results.m_on_sloppy_count++; - } - else - { - on_3d_error.Plus(d_err); - on_t_error.Plus(t_err); - } - } - else if ( T.best_d > 0.0 ) - { - m_results.m_off_test_count++; - - if( T.crv_d[m_func] <= T.best_d ) - { - m_results.m_off_best_count++; - t_err = 0.0; - } - d_err /= T.best_d; - if ( d_err > 0.15 ) - { - m_results.m_off_wrong_count++; - } - else if ( d_err > 0.05 ) - { - m_results.m_off_sloppy_count++; - } - else - { - off_3d_error.Plus(d_err); - off_t_error.Plus(t_err); - } - } - } - - i = on_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = on_3d_error.Total()/((double)i); - t_err = on_t_error.Total()/((double)i); - m_results.m_on_curve_3d_error = d_err; - m_results.m_on_curve_t_error = t_err; - } - - i = off_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = off_3d_error.Total()/((double)i); - t_err = off_t_error.Total()/((double)i); - m_results.m_off_curve_3d_error = d_err; - m_results.m_off_curve_t_error = t_err; - } - } - - if ( badi>=0) - { - printf("TEST POINT %d had error of = %g. This is a ClosestPointToCurve BUG.\n",badi,badd); - } -} - -void CClosestPointToCurveTest::Print( ON_TextLog& text_log, int test_count ) -{ - const char* format = "%s %s %5d %4.1fX (%6.3f secs) %3d%% %.1g %.1g"; - - const char* name = 0; - if ( test_count > 0 ) - { - text_log.Print("Name Test Point Speed Accuracy\n"); - text_log.Print(" count sloth time best 3d err t err\n"); - name = "Perfect "; - } - else - { - switch(m_func) - { - case CCurveTestPoint::FUNC_CRV_CLSPT_BASELINE: - name = "Baseline "; - break; - case CCurveTestPoint::FUNC_CRV_CLSPT_ON_TREETEST: - name = "Tree Test "; - break; - case CCurveTestPoint::FUNC_CRV_CLSPT_ON_CRV: - name = "ON_Curve "; - break; - case CCurveTestPoint::FUNC_CRV_CLSPT_ON_NURBS: - name = "NURBS form "; - break; - case CCurveTestPoint::FUNC_CRV_CLSPT_GOOSE: - name = "Goose "; - break; - default: - name = "Anonymous "; - break; - } - } - - - if ( test_count > 0 ) - { - text_log.Print(format, - name, - " ", - test_count, // m_results.m_test_count, - 1.0, //m_results.m_speed_factor, - 0.0, //m_results.m_elapsed_time, - 100,//test_count, //m_results.m_best_count, - 1e-18, //m_results.m_on_curve_3d_error, - 1e-18, //m_results.m_on_curve_t_error, - 0, //m_results.m_on_wrong_count, - 0 //m_results.m_on_sloppy_count - ); - text_log.Print("\n"); - } - else - { - if ( m_results.m_on_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_on_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - name, - "on ", - m_results.m_on_test_count, - m_results.m_speed_factor, - m_results.m_elapsed_time, - best,//m_results.m_on_best_count, - m_results.m_on_curve_3d_error, - m_results.m_on_curve_t_error - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - - if( m_results.m_on_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_on_wrong_count); - if( m_results.m_on_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_on_sloppy_count); - text_log.Print("\n"); - } - - if ( m_results.m_off_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_off_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - name, - "off ", - m_results.m_off_test_count, - m_results.m_speed_factor, - m_results.m_elapsed_time, - best, //m_results.m_off_best_count, - m_results.m_off_curve_3d_error, - m_results.m_off_curve_t_error - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - - if( m_results.m_off_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_off_wrong_count); - if( m_results.m_off_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_off_sloppy_count); - text_log.Print("\n"); - } - } -} - - - -class CSurfaceTestPoint -{ -public: - int test_point_index; - - ON_3dPoint P; // test point = C + d*(variable unit vector) - ON_2dPoint uv; - double d; - - // The information below is filled in during accuracy testing phase - - enum FUNC_SRF_CLSPT - { - FUNC_SRF_CLSPT_NONE = 0, - FUNC_SRF_CLSPT_NEWON = 1, // - FUNC_SRF_CLSPT_GOOSE = 2, // old gslib - FUNC_SRF_CLSPT_COUNT = 3 - }; - - // paramter of closest point - ON_2dPoint srf_uv[FUNC_SRF_CLSPT_COUNT]; - - // distance from P to - double srf_d[FUNC_SRF_CLSPT_COUNT]; - - // best result from a test - ON_2dPoint best_uv; - double best_d; -}; - - - - -class CMeshTestPoint -{ -public: - int test_point_index; - - ON_MESH_POINT S; // seed point on mesh - ON_3dVector N; // normal for offsets - ON_3dPoint P; // test point - - ON_MESH_POINT M; // best answer we found - - double S_d; // distance from S to P. - double M_d; // distance from M to P. -}; - -ON_3dPoint FacePoint( const ON_MESH_POINT& S ) -{ - ON_3dPoint P(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE); - if ( S.m_mesh ) - { - if ( S.m_face_index >= 0 && S.m_face_index < S.m_mesh->m_F.Count() ) - { - ON_3dPoint V[4]; - const int* fvi = S.m_mesh->m_F[S.m_face_index].vi; - const ON_3fPoint* mesh_V = S.m_mesh->m_V.Array(); - V[0] = mesh_V[fvi[0]]; - V[1] = mesh_V[fvi[1]]; - V[2] = mesh_V[fvi[2]]; - V[3] = mesh_V[fvi[3]]; - const double* t = S.m_t; - P.x = t[0]*V[0].x + t[1]*V[1].x + t[2]*V[2].x + t[3]*V[3].x; - P.y = t[0]*V[0].y + t[1]*V[1].y + t[2]*V[2].y + t[3]*V[3].y; - P.z = t[0]*V[0].z + t[1]*V[1].z + t[2]*V[2].z + t[3]*V[3].z; - } - } - return P; -} - -static -bool GetMeshPointCloudVertexHelper( - const ON_Mesh& mesh, - const ON_MeshTopology& top, - int topvi, - ON_SimpleArray& CPT - ) -{ - const ON_MeshTopologyVertex& V = top.m_topv[topvi]; - if ( V.m_tope_count < 1 || V.m_v_count < 1 ) - return false; - - const ON_MeshTopologyEdge& E = top.m_tope[V.m_topei[0]]; - if ( E.m_topf_count < 1 ) - return false; - - int fi = E.m_topfi[0]; - const int* fvi = mesh.m_F[fi].vi; - int j; - for ( j = 0; j < 4; j++ ) - { - int vi = fvi[j]; - if ( top.m_topv_map[vi] == topvi ) - { - CMeshTestPoint& tp = CPT.AppendNew(); - tp.test_point_index = CPT.Count()-1; - tp.N = mesh.m_N[vi]; - tp.S.m_P = mesh.m_V[vi]; - tp.S.m_face_index = fi; - tp.S.m_t[j] = 1.0; - tp.S.m_mesh = &mesh; - return true; - } - } - return false; -} - - -static -bool GetMeshPointCloudEdgeHelper( - const ON_Mesh& mesh, - const ON_MeshTopology& top, - int topei, - int edge_sample_count, - ON_SimpleArray& CPT - ) -{ - const ON_MeshTopologyEdge& E = top.m_tope[topei]; - if ( E.m_topf_count < 1 ) - return false; - const int fi = E.m_topfi[0]; - const ON_MeshTopologyFace& F0 = top.m_topf[fi]; - int fei; - for ( fei = 0; fei < 4; fei++ ) - { - if ( F0.m_topei[fei] == topei ) - { - int fvi0 = ( F0.IsTriangle() ) - ? ((fei+2)%3) - : ((fei+3)%4); - int fvi1 = fei; - const int* fvi = mesh.m_F[fi].vi; - ON_Line L; - L.from = mesh.m_V[fvi[fvi0]]; - L.to = mesh.m_V[fvi[fvi1]]; - - ON_3dVector edgeN = mesh.m_FN[fi]; - int j; - for ( j = 1; j < E.m_topf_count; j++ ) - { - edgeN = edgeN + ON_3dVector(mesh.m_FN[E.m_topfi[j]]); - } - edgeN.Unitize(); - - for ( j = 1; j <= edge_sample_count; j++ ) - { - double t = ((double)j)/((double)(edge_sample_count+1)); - CMeshTestPoint& CP = CPT.AppendNew(); - CP.test_point_index = CPT.Count()-1; - CP.N = edgeN; - CP.S.m_P = L.PointAt(t); - CP.S.m_face_index = fi; - CP.S.m_t[fvi0] = 1.0-t; - CP.S.m_t[fvi1] = t; - CP.S.m_mesh = &mesh; - } - return true; - } - } - return false; -} - -static -bool GetMeshPointCloudFaceHelper( - const ON_Mesh& mesh, - const ON_MeshTopology& top, - int fi, - int face_sample_count, - int edge_sample_count, - ON_SimpleArray& CPT - ) -{ - ON_MeshFace f = mesh.m_F[fi]; - ON_3dVector N = mesh.m_FN[fi]; - ON_3dPoint V[4]; - int tri[2][3]; - int edge[2]; - V[0] = mesh.m_V[f.vi[0]]; - V[1] = mesh.m_V[f.vi[1]]; - V[2] = mesh.m_V[f.vi[2]]; - V[3] = mesh.m_V[f.vi[3]]; - - int tricount; - if ( f.IsTriangle() ) - { - tri[0][0] = tri[1][0] = 0; - tri[0][1] = tri[1][1] = 1; - tri[0][2] = tri[1][2] = 2; - tricount = 1; - edge[0] = edge[1] = -1; - } - else - { - tricount = 2; - double d0 = V[0].DistanceTo(V[2]); - double d1 = V[1].DistanceTo(V[3]); - if ( d0 <= d1 ) - { - tri[0][0] = 0; - tri[0][1] = 1; - tri[0][2] = 2; - tri[1][0] = 0; - tri[1][1] = 2; - tri[1][2] = 3; - edge[0] = 0; - edge[1] = 2; - } - else - { - tri[0][0] = 0; - tri[0][1] = 1; - tri[0][2] = 3; - tri[1][0] = 1; - tri[1][1] = 2; - tri[1][2] = 3; - edge[0] = 1; - edge[1] = 3; - } - } - - double r, s, t; - - int i, a, b, n; - - for( n = 3; (n-2)*(n-1) < face_sample_count*2; n++ ) - { - // empty - } - - - for ( i = 0; i < tricount; i++ ) - { - for ( a = 1; a < n-1; a++ ) - { - for ( b = 1; a+b < n; b++ ) - { - r = ((double)a)/((double)n); - s = ((double)b)/((double)n); - t = 1.0-r-s; - CMeshTestPoint& tp = CPT.AppendNew(); - tp.test_point_index = CPT.Count()-1; - tp.N = N; - tp.S.m_t[tri[i][0]] = r; - tp.S.m_t[tri[i][1]] = s; - tp.S.m_t[tri[i][2]] = t; - tp.S.m_face_index = fi; - tp.S.m_mesh = &mesh; - tp.S.m_P = r*V[tri[i][0]] + s*V[tri[i][1]] + t*V[tri[i][2]]; - } - } - } - - if ( edge[0] != edge[1] ) - { - for ( i = 1; i <= edge_sample_count; i++ ) - { - t = ((double)i)/((double)(edge_sample_count+1)); - s = 1.0-t; - CMeshTestPoint& tp = CPT.AppendNew(); - tp.test_point_index = CPT.Count()-1; - tp.N = N; - tp.S.m_t[edge[0]] = s; - tp.S.m_t[edge[1]] = t; - tp.S.m_face_index = fi; - tp.S.m_mesh = &mesh; - tp.S.m_P = s*V[edge[0]] + t*V[edge[1]]; - } - } - return true; -} - -void GetMeshPointCloud( const ON_Mesh& mesh, - double sample_start_distance, - double sample_stop_distance, - ON_SimpleArray& CPT ) -{ - // appends a cloud of points to pts. - const int i0 = CPT.Count(); - - int i,n; - double r; - - if ( sample_stop_distance < 0.0 ) - sample_stop_distance = 0.0; - if ( sample_start_distance >= sample_stop_distance ) - sample_start_distance = sample_stop_distance; - - const ON_MeshTopology& top = mesh.Topology(); - const int face_count = mesh.m_F.Count(); - const int vertex_count = top.m_topv.Count(); - const int edge_count = top.m_tope.Count(); - const int quad_count = mesh.QuadCount(); - const int triangle_count = face_count + quad_count; - - int face_n = 4; - int triangle_sample_count = ((face_n-2)*(face_n-1))/2; - int edge_sample_count = 1; - int vertical_count = 0; - if ( sample_start_distance > 0.0 ) - { - for ( r = sample_start_distance; r <= sample_stop_distance*(1.0+ON_SQRT_EPSILON); r *= 2.0 ) - { - if ( 0.0 != r ) - vertical_count += 2; - } - } - if ( vertical_count < 1 ) - vertical_count = 1; - - int test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - - while ( test_point_count < 1000 ) - { - face_n++; - triangle_sample_count = ((face_n-2)*(face_n-1))/2; - if ( (face_n % 2) ) - edge_sample_count++; - - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - - if ( face_n >= 7 ) - break; - } - - const int max_test_point_count = 750000; - - if ( test_point_count > max_test_point_count ) - { - while ( edge_sample_count > 1 && test_point_count > max_test_point_count ) - { - edge_sample_count--; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - while ( triangle_sample_count > 3 && test_point_count > max_test_point_count ) - { - face_n--; - triangle_sample_count = ((face_n-2)*(face_n-1))/2; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - while ( vertical_count > 2 ) - { - sample_start_distance *= 2.0; - vertical_count -= 2; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - while ( edge_sample_count > 0 && test_point_count > max_test_point_count ) - { - edge_sample_count--; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - while ( triangle_sample_count > 1 && test_point_count > max_test_point_count ) - { - face_n--; - triangle_sample_count = ((face_n-2)*(face_n-1))/2; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - } - - if ( bPurify ) - { - // reduce sample counts so purify will finish somtime today - triangle_sample_count = 1; - edge_sample_count = 0; - sample_stop_distance = sample_start_distance; - vertical_count = (sample_stop_distance>0.0) ? 2 : 1; - test_point_count = (triangle_sample_count*triangle_count + edge_sample_count*(edge_count+quad_count) + vertex_count)*vertical_count; - } - - CPT.Reserve( test_point_count ); - - if ( !mesh.HasFaceNormals() ) - { - const_cast(&mesh)->ComputeFaceNormals(); - } - if ( !mesh.HasVertexNormals() ) - { - const_cast(&mesh)->ComputeVertexNormals(); - } - - // get a test point at each vertex - for ( i = 0; i < vertex_count; i++ ) - { - GetMeshPointCloudVertexHelper( mesh, top, i, CPT ); - } - - // get test points along each edge - if ( edge_sample_count > 0 ) - { - for ( i = 0; i < edge_count; i++ ) - { - GetMeshPointCloudEdgeHelper( mesh, top, i, edge_sample_count, CPT ); - } - } - - // get test points along each face - if ( triangle_sample_count > 0 ) - { - for (i = 0; i < face_count; i++) - { - GetMeshPointCloudFaceHelper( mesh, top, i, triangle_sample_count, edge_sample_count, CPT ); - } - } - - CMeshTestPoint TP; - const int i1 = CPT.Count(); - for ( i = i0; i < i1; i++ ) - { - CMeshTestPoint& CP0 = CPT[i]; - CP0.P = FacePoint( CP0.S ); - CP0.S_d = CP0.P.DistanceTo(CP0.S.m_P); - CP0.M_d = ON_UNSET_VALUE; - ON_3dVector D = CP0.P - CP0.S.m_P; - if ( fabs(D.x) >= (1.0+fabs(CP0.P.x))*ON_EPSILON - && fabs(D.y) >= (1.0+fabs(CP0.P.y))*ON_EPSILON - && fabs(D.z) >= (1.0+fabs(CP0.P.z))*ON_EPSILON ) - { - ON_ERROR("GetMeshPointCloud - created bogus input values"); - } - TP = CP0; - - bool bAppend = false; - if ( 0.0 < sample_start_distance ) - { - int level_count; - r = sample_start_distance; - for ( level_count = 0; level_count < vertical_count; level_count += 2 ) - { - for ( n = 0; n <= 1; n++ ) - { - CMeshTestPoint& CP = bAppend ? CPT.AppendNew() : CP0; - CP = TP; - if ( bAppend ) - CP.test_point_index = CPT.Count()-1; - CP.P = TP.P + (n?-r:r)*TP.N; - CP.S_d = CP.S.m_P.DistanceTo(CP.P); - bAppend = true; - } - r *= 2.0; - } - } - } - - return; - -} - - -void GetSurfacePointCloud( const ON_Surface& surface, - double sample_start_distance, - double sample_stop_distance, - ON_SimpleArray& CPT ) -{ - // appends a cloud of points to pts. - int hint[2] = {0,0}; - int j,jj,n,m,spani,spanj; - - ON_3dPoint P; - ON_3dVector N; - ON_Interval span_domain[2]; - double r, s, t; - - if ( sample_start_distance >= sample_stop_distance ) - sample_start_distance = sample_stop_distance; - - int span_count0 = surface.SpanCount(0); - if (span_count0 < 1 ) - { - return; - } - - int span_count1 = surface.SpanCount(1); - if (span_count1 < 1 ) - { - return; - } - - double* span_vector0 = (double*)onmalloc((span_count0+span_count1+2)*sizeof(*span_vector0)); - double* span_vector1 = span_vector0 + (span_count0+1); - - if ( !surface.GetSpanVector(0,span_vector0)) - return; - - if ( !surface.GetSpanVector(1,span_vector1)) - return; - - int degree0 = surface.Degree(0); - int degree1 = surface.Degree(1); - - int span_sample_count = 4*3*5; - int vertical_count = 1; - if ( sample_stop_distance > 0.0 ) - { - for ( r = sample_start_distance; r <= sample_stop_distance*(1.0+ON_SQRT_EPSILON); r *= 2.0 ) - { - if ( 0.0 != r ) - vertical_count += 2; - } - } - - while ( span_count0*span_count1*span_sample_count*span_sample_count < 1000 ) - span_sample_count *= 2; - - if ( 1 == degree0 && 1 == degree1 && span_count0*span_count1*span_sample_count*span_sample_count < 10000 ) - { - while ( span_count0*span_count1*span_sample_count*span_sample_count < 10000 ) - span_sample_count *= 2; - } - else if ( span_sample_count > 5 ) - { - while ( span_sample_count > 5 && span_count0*span_count1*span_sample_count*span_sample_count > 1000000 ) - { - span_sample_count /= 2; - } - while ( span_sample_count > 5 && span_count0*span_count1*span_sample_count*span_sample_count > 200000 ) - { - span_sample_count *= 2; - span_sample_count /= 3; - } - } - - if ( bPurify ) - { - // reduce sample counts so purify will finish somtime today - span_sample_count = 3; - sample_stop_distance = sample_start_distance; - } - - CPT.Reserve(span_count0*span_count1*span_sample_count*span_sample_count*vertical_count); - - for (spani = 0; spani < span_count0; spani++ ) - { - span_domain[0].Set(span_vector0[spani],span_vector0[spani+1]); - for ( j = spani?1:0; j <= span_sample_count; j++ ) - { - s = span_domain[0].ParameterAt(((double)j)/((double)span_sample_count)); - for ( spanj = 0; spanj < span_count1; spanj++ ) - { - span_domain[1].Set(span_vector1[spanj],span_vector1[spanj+1]); - for ( jj = spanj?1:0; jj <= span_sample_count; jj++ ) - { - t = span_domain[1].ParameterAt(((double)jj)/((double)span_sample_count)); - surface.EvNormal(s,t,P,N,1,hint); - - if ( sample_stop_distance <= 0.0 ) - { - CSurfaceTestPoint& CP = CPT.AppendNew(); - CP.test_point_index = CPT.Count()-1; - CP.P = P; - CP.uv.Set(s,t); - CP.d = 0.0; - CP.best_uv.Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - CP.best_d = ON_UNSET_VALUE; - for( m = 0; m < CSurfaceTestPoint::FUNC_SRF_CLSPT_COUNT; m++ ) - { - CP.srf_d[m] = ON_UNSET_VALUE; - CP.srf_uv[m].Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - } - } - else - { - for ( r = sample_start_distance; r <= sample_stop_distance*(1.0+ON_SQRT_EPSILON); r *= 2.0 ) - { - for ( n = 0; n <= 1; n++ ) - { - CSurfaceTestPoint& CP = CPT.AppendNew(); - CP.test_point_index = CPT.Count()-1; - CP.P = P + (n?-r:r)*N; - CP.uv.Set(s,t); - CP.d = P.DistanceTo(CP.P); - CP.best_uv.Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - CP.best_d = ON_UNSET_VALUE; - for( m = 0; m < CSurfaceTestPoint::FUNC_SRF_CLSPT_COUNT; m++ ) - { - CP.srf_d[m] = ON_UNSET_VALUE; - CP.srf_uv[m].Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - } - if ( 0.0 == r ) - break; - } - } - } - } - } - } - } - onfree(span_vector0); - - // FOR DEBUGGING A CLOSEST POINT TO SURFACE BAD POINT - int singleton_index = -1; - if ( singleton_index >= 0 && singleton_index < CPT.Count() ) - { - CPT[0] = CPT[singleton_index]; - CPT.SetCount(1); - } -} - - - -class CClosestPointToMeshTest -{ -public: - bool GetClosestPoint( ON_3dPoint P, ON_MESH_POINT* mp ); - - // returns time in seconds - double SpeedTest( int test_point_count, const CMeshTestPoint* tp); - - // returns error count - int AccuracyTest( int test_point_count, CMeshTestPoint* tp ); - - void CalculateResults( int test_point_count, - const CMeshTestPoint* tp - ); - - void Print( ON_TextLog& text_log, int test_count ); - - void SetupHelper( const ON_Mesh* mesh, const ON_Surface* surface ); - - const ON_Mesh* m_mesh; - const ON_MeshTree* m_mesh_tree; - - const ON_Surface* m_surface; - const ON_SurfaceTree* m_surface_tree; - - CClosestPointToMeshTestResults m_results; -}; - -bool CClosestPointToMeshTest::GetClosestPoint( ON_3dPoint P, ON_MESH_POINT* mp ) -{ - return m_mesh_tree->GetClosestPoint( P, mp ); -} - -void CClosestPointToMeshTest::SetupHelper( const ON_Mesh* mesh, const ON_Surface* surface ) -{ - m_mesh = mesh; - m_mesh_tree = m_mesh ? m_mesh->MeshTree() : 0; - - m_surface = surface; - m_surface_tree = m_surface ? m_surface->SurfaceTree() : 0; - - memset(&m_results,0,sizeof(m_results)); -} - - - -double CClosestPointToMeshTest::SpeedTest(int point_count, const CMeshTestPoint* tp0) -{ - ON_MESH_POINT mp; - const CMeshTestPoint* tp;; - - double s, t; - int i; - clock_t time0, time1; - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - m_results.m_mesh_elapsed_time = 0.0; - m_results.m_surface_elapsed_time = 0.0; - - if ( m_mesh_tree ) - { - tp = tp0; - i = point_count; - - time0 = clock(); - while(i--) - { - s = t = ON_UNSET_VALUE; - m_mesh_tree->GetClosestPoint(tp->P,&mp); - tp++; - } - time1 = clock(); - - m_results.m_mesh_elapsed_time = ((double)(time1 - time0))/((double)CLOCKS_PER_SEC); - } - - if ( m_surface_tree ) - { - tp = tp0; - i = point_count; - - time0 = clock(); - while(i--) - { - s = t = ON_UNSET_VALUE; - m_surface_tree->GetClosestPoint(tp->P,&s,&t); - tp++; - } - time1 = clock(); - - m_results.m_surface_elapsed_time = ((double)(time1 - time0))/((double)CLOCKS_PER_SEC); - } - - m_results.m_bSpeedTest = true; - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return m_results.m_mesh_elapsed_time; -} - -int CClosestPointToMeshTest::AccuracyTest(int point_count, CMeshTestPoint* tp) -{ - ON_3dPoint Q; - double d; - int rc = 0; - int i; - - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - m_results.m_bAccuracyTest = true; - m_results.m_test_count = 0; - - if ( m_mesh_tree ) - { - m_results.m_test_count = point_count; - - - - for ( i = 0; i < point_count; i++ ) - { - if( !m_mesh_tree->GetClosestPoint(tp[i].P,&tp[i].M) ) - { - rc++; - memset(&tp[i].M,0,sizeof(tp[i].M)); - tp[i].M_d = ON_UNSET_VALUE; - m_results.m_failure_count++; - } - else - { - Q = FacePoint(tp[i].M); - d = Q.DistanceTo(tp[i].P); - tp[i].M_d = d; - ON_3dVector D = Q - tp[i].M.m_P; - if ( fabs(D.x) >= (1.0+fabs(Q.x))*ON_EPSILON - && fabs(D.y) >= (1.0+fabs(Q.y))*ON_EPSILON - && fabs(D.z) >= (1.0+fabs(Q.z))*ON_EPSILON ) - { - ON_String msg; - msg.Format( - "Bogus ON_MESH_POINT tp[%d].M.m_P value returned from ON_MeshTree::GetClosestPoint()\n", - i); - ON_ERROR(msg); - } - } - } - } - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return rc; -} - - -void CClosestPointToMeshTest::CalculateResults( - int test_point_count, - const CMeshTestPoint* tp - ) -{ - int badi = -1; - double badd = 0.0; - - m_results.m_speed_factor = (m_results.m_bSpeedTest && m_results.m_surface_elapsed_time > 0.0) - ? m_results.m_mesh_elapsed_time/m_results.m_surface_elapsed_time - : 0.0; - - if ( m_results.m_bAccuracyTest ) - { - ON_Sum on_3d_error; - ON_Sum off_3d_error; - double best_d, d_err; - int i; - ON_3dPoint P; - for ( i = 0; i < test_point_count; i++ ) - { - const CMeshTestPoint& T = tp[i]; - - if ( !T.M.m_mesh ) - continue; - - best_d = (T.M_d < T.S_d) ? T.M_d : T.S_d; - - d_err = T.M_d - best_d; - if ( 0.0 == best_d ) - { - m_results.m_on_test_count++; - - if ( T.M_d <= best_d ) - { - m_results.m_on_best_count++; - } - if ( d_err > 1.0e-4 ) - { - m_results.m_on_wrong_count++; - if ( d_err > badd ) - { - badd = d_err; - badi = T.test_point_index; - } - } - else if ( d_err > 1.0e-6 ) - { - m_results.m_on_sloppy_count++; - } - else - { - on_3d_error.Plus(d_err); - } - } - else - { - m_results.m_off_test_count++; - - if( T.M_d <= best_d ) - { - m_results.m_off_best_count++; - } - d_err /= best_d; - if ( d_err > 0.15 ) - { - m_results.m_off_wrong_count++; - } - else if ( d_err > 0.05 ) - { - m_results.m_off_sloppy_count++; - } - else - { - off_3d_error.Plus(d_err); - } - } - } - - i = on_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = on_3d_error.Total()/((double)i); - m_results.m_on_mesh_3d_error = d_err; - } - - i = off_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = off_3d_error.Total()/((double)i); - m_results.m_off_mesh_3d_error = d_err; - } - } - - if ( badi>=0) - { - printf("TEST POINT %d had error of = %g. This is a ClosestPointToSurface BUG.\n",badi,badd); - } -} - - - -void CClosestPointToMeshTest::Print( ON_TextLog& text_log, int test_count ) -{ - const char* format = "%s %s %5d %4.1fX (%6.3f secs) %3d%% %.1g"; - - text_log.Print("Name Test Point mesh/ Mesh Accuracy\n"); - text_log.Print(" count srf time best 3d err\n"); - text_log.Print(format, - "Perfect ", - " ", - test_count, // m_results.m_test_count, - 1.0, //m_results.m_speed_factor, - 0.0, //m_results.m_elapsed_time, - 100,//test_count, //m_results.m_best_count, - 1e-18 //m_results.m_on_surface_3d_error, - ); - text_log.Print("\n"); - - if ( m_results.m_on_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_on_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - "mesh ", - "on ", - m_results.m_on_test_count, - m_results.m_speed_factor, - m_results.m_mesh_elapsed_time, - best, - m_results.m_on_mesh_3d_error - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - - if( m_results.m_on_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_on_wrong_count); - if( m_results.m_on_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_on_sloppy_count); - text_log.Print("\n"); - } - - if ( m_results.m_off_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_off_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - "mesh ", - "off ", - m_results.m_off_test_count, - m_results.m_speed_factor, - m_results.m_mesh_elapsed_time, - best, - m_results.m_off_mesh_3d_error - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - if( m_results.m_off_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_off_wrong_count); - if( m_results.m_off_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_off_sloppy_count); - text_log.Print("\n"); - } -} - - - -class CClosestPointToSurfaceTest -{ -public: - virtual void Setup( ON_NurbsSurface* nurbs_surface ) = 0; - - virtual int GetClosestPoint( ON_3dPoint P, double* s, double* t ) = 0; - - // returns time in seconds - double SpeedTest( int test_point_count, const CSurfaceTestPoint* tp); - - // returns error count - int AccuracyTest( int test_point_count, CSurfaceTestPoint* tp ); - - void CalculateResults( const ON_NurbsSurface& nurbs_surface, - int test_point_count, - const CSurfaceTestPoint* tp, - double best_time - ); - - void Print( ON_TextLog& text_log, int test_count ); - - CSurfaceTestPoint::FUNC_SRF_CLSPT m_func; - - const ON_NurbsSurface* m_nurbs_surface; - - CClosestPointToSurfaceTestResults m_results; - - void SetupHelper( CSurfaceTestPoint::FUNC_SRF_CLSPT func, ON_NurbsSurface* nurbs_surface ); -}; - -void CClosestPointToSurfaceTest::SetupHelper( CSurfaceTestPoint::FUNC_SRF_CLSPT func, ON_NurbsSurface* nurbs_surface ) -{ - m_func = func; - m_nurbs_surface = nurbs_surface; - memset(&m_results,0,sizeof(m_results)); - m_results.m_elapsed_time = ON_UNSET_VALUE; -} - -double CClosestPointToSurfaceTest::SpeedTest(int point_count, const CSurfaceTestPoint* tp) -{ - double s, t; - int i; - clock_t time0, time1; - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - i = point_count; - - time0 = clock(); - while(i--) - { - s = t = ON_UNSET_VALUE; - GetClosestPoint(tp->P,&s,&t); - tp++; - } - time1 = clock(); - - m_results.m_elapsed_time = ((double)(time1 - time0))/((double)CLOCKS_PER_SEC); - - m_results.m_bSpeedTest = true; - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return m_results.m_elapsed_time; -} - -int CClosestPointToSurfaceTest::AccuracyTest(int point_count, CSurfaceTestPoint* tp) -{ - ON_3dPoint Q; - double d; - int rc = 0; - int i; - double s,t; - - - int error_count0 = ON_GetErrorCount(); - int warning_count0 = ON_GetWarningCount(); - - m_results.m_bAccuracyTest = true; - m_results.m_test_count = point_count; - - for ( i = 0; i < point_count; i++ ) - { - s = t = ON_UNSET_VALUE; - if( !GetClosestPoint(tp[i].P,&s,&t) ) - { - rc++; - tp[i].srf_uv[m_func].Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - tp[i].srf_d[m_func] = ON_UNSET_VALUE; - m_results.m_failure_count++; - } - else - { - Q = m_nurbs_surface->PointAt(s,t); - d = Q.DistanceTo(tp[i].P); - tp[i].srf_uv[m_func].Set(s,t); - tp[i].srf_d[m_func] = d; - if ( ON_UNSET_VALUE == tp[i].best_d || d < tp[i].best_d ) - { - tp[i].best_d = d; - tp[i].best_uv.Set(s,t); - } - } - } - - m_results.m_error_count += (ON_GetErrorCount()-error_count0); - m_results.m_warning_count += (ON_GetWarningCount()-warning_count0); - - return rc; -} - - -void CClosestPointToSurfaceTest::CalculateResults( const ON_NurbsSurface& nurbs_surface, - int test_point_count, - const CSurfaceTestPoint* tp, - double best_time - ) -{ - int badi = -1; - double badd = 0.0; - - m_results.m_speed_factor = (m_results.m_bSpeedTest && best_time>0.0) ? m_results.m_elapsed_time/best_time : 0.0; - if ( m_results.m_bAccuracyTest ) - { - ON_Sum on_3d_error; - ON_Sum off_3d_error; - ON_Sum on_uvx_error, on_uvy_error; - ON_Sum off_uvx_error, off_uvy_error; - double d_err; - ON_2dVector uv_err; - int i; - int hint[2] = {0,0}; - ON_3dPoint P; - ON_3dVector Du, Dv; - for ( i = 0; i < test_point_count; i++ ) - { - const CSurfaceTestPoint& T = tp[i]; - - if ( !T.srf_uv[m_func].IsValid() ) - continue; - - nurbs_surface.Ev1Der( T.best_uv.x, T.best_uv.y, P, Du, Dv, 1, hint ); - - uv_err.Set( Du.Length(), Dv.Length() ); - uv_err.x = ( uv_err.x > ON_ZERO_TOLERANCE ) ? 1.0/uv_err.x : 0.0; - uv_err.y = ( uv_err.y > ON_ZERO_TOLERANCE ) ? 1.0/uv_err.y : 0.0; - uv_err.x *= fabs(T.srf_uv[m_func].x - T.best_uv.x); - uv_err.y *= fabs(T.srf_uv[m_func].y - T.best_uv.y); - - d_err = (T.best_d < T.d) ? T.best_d : T.d; - - d_err = T.srf_d[m_func] - d_err; - if ( 0.0 == T.d || 0.0 == T.best_d ) - { - m_results.m_on_test_count++; - - if ( T.srf_d[m_func] <= T.best_d ) - { - m_results.m_on_best_count++; - uv_err.Set(0.0,0.0); - } - if ( d_err > 1.0e-4 ) - { - m_results.m_on_wrong_count++; - if ( CSurfaceTestPoint::FUNC_SRF_CLSPT_GOOSE != m_func && d_err > badd ) - { - badd = d_err; - badi = T.test_point_index; - } - } - else if ( d_err > 1.0e-6 ) - { - m_results.m_on_sloppy_count++; - } - else - { - on_3d_error.Plus(d_err); - on_uvx_error.Plus(uv_err.x); - on_uvy_error.Plus(uv_err.y); - } - } - else if ( T.best_d > 0.0 ) - { - m_results.m_off_test_count++; - - if( T.srf_d[m_func] <= T.best_d ) - { - m_results.m_off_best_count++; - uv_err.Set(0.0,0.0); - } - d_err /= T.best_d; - if ( d_err > 0.15 ) - { - m_results.m_off_wrong_count++; - } - else if ( d_err > 0.05 ) - { - m_results.m_off_sloppy_count++; - } - else - { - off_3d_error.Plus(d_err); - off_uvx_error.Plus(uv_err.x); - off_uvy_error.Plus(uv_err.y); - } - } - } - - i = on_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = on_3d_error.Total()/((double)i); - uv_err.x = on_uvx_error.Total()/((double)i); - uv_err.y = on_uvy_error.Total()/((double)i); - m_results.m_on_surface_3d_error = d_err; - m_results.m_on_surface_uv_error = uv_err; - } - - i = off_3d_error.SummandCount(); - if ( i > 0 ) - { - d_err = off_3d_error.Total()/((double)i); - uv_err.x = off_uvx_error.Total()/((double)i); - uv_err.y = off_uvy_error.Total()/((double)i); - m_results.m_off_surface_3d_error = d_err; - m_results.m_off_surface_uv_error = uv_err; - } - } - - if ( badi>=0) - { - printf("TEST POINT %d had error of = %g. This is a ClosestPointToSurface BUG.\n",badi,badd); - } -} - -void CClosestPointToSurfaceTest::Print( ON_TextLog& text_log, int test_count ) -{ - const char* format = "%s %s %5d %4.1fX (%6.3f secs) %3d%% %.1g %.1g,%.1g"; - - const char* name = 0; - if ( test_count > 0 ) - { - text_log.Print("Name Test Point Speed Accuracy\n"); - text_log.Print(" count sloth time best 3d err uv err\n"); - name = "Perfect "; - } - else - { - switch(m_func) - { - case CSurfaceTestPoint::FUNC_SRF_CLSPT_NEWON: - name = "OpenNURBS "; - break; - case CSurfaceTestPoint::FUNC_SRF_CLSPT_GOOSE: - name = "Goose "; - break; - default: - name = "Anonymous "; - break; - } - } - - - if ( test_count > 0 ) - { - text_log.Print(format, - name, - " ", - test_count, // m_results.m_test_count, - 1.0, //m_results.m_speed_factor, - 0.0, //m_results.m_elapsed_time, - 100,//test_count, //m_results.m_best_count, - 1e-18, //m_results.m_on_surface_3d_error, - 1e-18, //m_results.m_on_surface_uv_error.x, - 1e-18 //m_results.m_on_surface_uv_error.y, - ); - text_log.Print("\n"); - } - else - { - if ( m_results.m_on_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_on_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - name, - "on ", - m_results.m_on_test_count, - m_results.m_speed_factor, - m_results.m_elapsed_time, - best,//m_results.m_on_best_count, - m_results.m_on_surface_3d_error, - m_results.m_on_surface_uv_error.x, - m_results.m_on_surface_uv_error.y - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - - if( m_results.m_on_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_on_wrong_count); - if( m_results.m_on_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_on_sloppy_count); - text_log.Print("\n"); - } - - if ( m_results.m_off_test_count > 0 ) - { - int best = (int)floor(100.0*((double)m_results.m_off_best_count)/((double)m_results.m_test_count)); - text_log.Print(format, - name, - "off ", - m_results.m_off_test_count, - m_results.m_speed_factor, - m_results.m_elapsed_time, - best, //m_results.m_off_best_count, - m_results.m_off_surface_3d_error, - m_results.m_off_surface_uv_error.x, - m_results.m_off_surface_uv_error.y - ); - if( m_results.m_failure_count > 0 ) - text_log.Print(" %d FAILURES",m_results.m_failure_count); - if( m_results.m_error_count > 0 ) - text_log.Print(" %d ON_ERRORs",m_results.m_error_count); - if( m_results.m_warning_count > 0 ) - text_log.Print(" %d ON_WARNINGSs",m_results.m_warning_count); - if( m_results.m_off_wrong_count > 0 ) - text_log.Print(" %d WRONG ANSWERS",m_results.m_off_wrong_count); - if( m_results.m_off_sloppy_count > 0 ) - text_log.Print(" %d sloppys answers",m_results.m_off_sloppy_count); - text_log.Print("\n"); - } - } -} - - - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Dale's closest point -// -class C_ON_Curve_PointTest : public CClosestPointToCurveTest -{ -public: - virtual void Setup( const ON_Curve* curve ); - virtual int GetClosestPoint(ON_3dPoint P, double* t); - const ON_Curve* m_curve; -}; - -void C_ON_Curve_PointTest::Setup( const ON_Curve* curve ) -{ - m_curve = curve; - m_curve->CurveTree(); // prebuild curve tree - SetupHelper(CCurveTestPoint::FUNC_CRV_CLSPT_ON_CRV,curve); -} - -int C_ON_Curve_PointTest::GetClosestPoint( ON_3dPoint P, double* t ) -{ - return m_curve->GetClosestPoint(P,t); -} - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Dale's closest point using ON_NurbsCurve -// -class CNurbsFormCurvePointTest : public CClosestPointToCurveTest -{ -public: - virtual void Setup( const ON_Curve* curve ); - virtual int GetClosestPoint(ON_3dPoint P, double* t); - TL_NurbsCurve m_nurbs_curve; -}; - -void CNurbsFormCurvePointTest::Setup( const ON_Curve* curve ) -{ - curve->GetNurbForm(m_nurbs_curve); - m_nurbs_curve.CurveTree(); // prebuild curve tree - SetupHelper(CCurveTestPoint::FUNC_CRV_CLSPT_ON_NURBS,&m_nurbs_curve); -} - -int CNurbsFormCurvePointTest::GetClosestPoint( ON_3dPoint P, double* t ) -{ - return m_curve->GetClosestPoint(P,t); -} - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Dale's closest point using ON_CurveTree -// -class CCurveTreePointTest : public CClosestPointToCurveTest -{ -public: - virtual void Setup( const ON_Curve* curve ); - virtual int GetClosestPoint(ON_3dPoint P, double* t); - TL_NurbsCurve m_nurbs_curve; - const ON_CurveTree* m_tree; -}; - -void CCurveTreePointTest::Setup( const ON_Curve* curve ) -{ - curve->GetNurbForm(m_nurbs_curve); - m_tree = m_nurbs_curve.CurveTree(); // prebuild curve tree - SetupHelper(CCurveTestPoint::FUNC_CRV_CLSPT_ON_TREETEST,&m_nurbs_curve); -} - -int CCurveTreePointTest::GetClosestPoint( ON_3dPoint P, double* t ) -{ - m_tree->m__GetClosestPointOnCurveTree(m_tree->m_root, P, t, NULL, 0.0, NULL ); - return 1; -} - - -/////////////////////////////////////////////////////////////////////////////////////// -// -// A "hack" closest point that provides a goal -// -class CBaselineCurvePointTest : public CClosestPointToCurveTest -{ -public: - virtual void Setup( const ON_Curve* curve ); - virtual int GetClosestPoint(ON_3dPoint P, double* t); - TL_NurbsCurve m_nurbs_curve; -}; - -void CBaselineCurvePointTest::Setup( const ON_Curve* curve ) -{ - curve->GetNurbForm(m_nurbs_curve); - m_nurbs_curve.CurveTree(); - SetupHelper(CCurveTestPoint::FUNC_CRV_CLSPT_BASELINE,&m_nurbs_curve); -} - -int CBaselineCurvePointTest::GetClosestPoint( ON_3dPoint P, double* t ) -{ - // NOTE - This doesn't handle subdomains and far point global checking - // See ON_Curve::GetClosestPoint - static - EF ef; - memset(&ef,0,sizeof(ef)); - ef.d = ON_UNSET_VALUE; - ef.t = ON_UNSET_VALUE; - ef.P = P; - ef.ct = m_nurbs_curve.CurveTree(); - - bool rc = ClosestFork(ef,ON_UNSET_VALUE,ef.ct->m_root); - - if (rc) - { - *t = ef.t; - } - - return rc; -} - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Goose closest point -// - -class CGooseCurvePointTest : public CClosestPointToCurveTest -{ -public: - CGooseCurvePointTest(); - ~CGooseCurvePointTest(); - - virtual void Setup( const ON_Curve* curve ); - virtual int GetClosestPoint( ON_3dPoint P, double* t ); - - TL_NurbsCurve m_nurbs_curve; - ON_3dPoint P0, P1, P2; - TL_NURB N; - IwPoint3d Q; - IwExtent1d Interval; - IwBSplineCurve* pC; -}; - -CGooseCurvePointTest::CGooseCurvePointTest() -{ - memset(&N,0,sizeof(N)); - pC =0; -} - -CGooseCurvePointTest::~CGooseCurvePointTest() -{ - N.cv = 0; - N.knot = 0; - TL_DestroyNurb(&N); - delete pC; -} - -void CGooseCurvePointTest::Setup( const ON_Curve* curve ) -{ - curve->GetNurbForm(m_nurbs_curve); - m_nurbs_curve.CurveTree(); - SetupHelper(CCurveTestPoint::FUNC_CRV_CLSPT_GOOSE,&m_nurbs_curve); - - P0 = m_nurbs_curve.PointAtStart(); - P1 = m_nurbs_curve.PointAt(m_nurbs_curve.Domain().ParameterAt(0.5)); - P2 = m_nurbs_curve.PointAtEnd(); - - memset(&N,0,sizeof(N)); - N.dim = m_nurbs_curve.m_dim; - N.is_rat = m_nurbs_curve.m_is_rat; - N.order = m_nurbs_curve.m_order; - N.cv_count = m_nurbs_curve.m_cv_count; - N.cv = m_nurbs_curve.m_cv; - N.knot = m_nurbs_curve.m_knot; - - TL_Convert( N, pC ); - Interval = pC->GetNaturalInterval(); - IwCacheMgr::GetOrCreateObjectCache(IW_OC_CURVE,pC); -} - -int CGooseCurvePointTest::GetClosestPoint( ON_3dPoint P, double* t ) -{ - int rc; - double dist_tol, d; - IwStatus iw_rc; - - IwSolutionArray sSolutions; - - dist_tol = P.DistanceTo(P0); - d = P.DistanceTo(P1); - if ( d < dist_tol ) - dist_tol = d; - d = P.DistanceTo(P2); - if ( d < dist_tol ) - dist_tol = d; - dist_tol *= (1.0+ON_SQRT_EPSILON); - - Q.x = P.x; - Q.y = P.y; - Q.z = P.z; - - iw_rc = pC->GlobalPointSolve( - Interval, - IW_SO_MINIMIZE, - Q, - dist_tol, NULL, NULL, - IW_SR_SINGLE, - sSolutions - ); - - if ( iw_rc == IW_SUCCESS && sSolutions.GetSize() > 0) - { - *t = sSolutions[0].m_vStart[0]; - rc = 1; - } - else - { - rc = 0; - } - - return rc; -} - - - -void TestClosestPointToThisCurve( ON_TextLog& text_log, - const ON_Curve* curve, - double sample_start_distance, - double sample_stop_distance - ) -{ - CClosestPointToCurveTest* tests[20]; - int test_count = 0; - int i; - bool bSpeedTest = true; - bool bAccuracyTest = true; - - // The commented out ones are slower than newdale_test and newon_test - CBaselineCurvePointTest baseline_test; - C_ON_Curve_PointTest on_curve_test; - CNurbsFormCurvePointTest on_nurbsform_test; - CCurveTreePointTest on_tree_test; - CGooseCurvePointTest goose_test; - - baseline_test.Setup(curve); - goose_test.Setup(curve); - on_curve_test.Setup(curve); - on_nurbsform_test.Setup(curve); - on_tree_test.Setup(curve); - - tests[test_count++] = &baseline_test; - tests[test_count++] = &on_tree_test; - tests[test_count++] = &on_curve_test; - tests[test_count++] = &on_nurbsform_test; - if ( bDoGooseTests ) - tests[test_count++] = &goose_test; - - // get test points - ON_SimpleArray TP; - GetCurvePointCloud( *curve, sample_start_distance, sample_stop_distance, TP ); - CCurveTestPoint* tp = TP.Array(); - int test_point_count = TP.Count(); - - if ( 0.0 == sample_stop_distance ) - { - text_log.Print("Testing %d points exactly on the curve.\n", - test_point_count); - } - else if ( sample_start_distance == sample_stop_distance ) - { - text_log.Print("Testing %d points about %g units off of the curve.\n", - test_point_count, - sample_start_distance); - } - else - { - text_log.Print("Testing %d points from %g to %g units off of the curve.\n", - test_point_count, - sample_start_distance,sample_stop_distance); - } - - double best_time = 0.0; - - // execution time tests - if ( bSpeedTest ) - { - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->SpeedTest(test_point_count,tp); - } - - for ( i = 0; i < test_count; i++ ) - { - if ( 0.0 == best_time || (tests[i]->m_results.m_elapsed_time > 0.0 && tests[i]->m_results.m_elapsed_time < best_time )) - { - best_time = tests[i]->m_results.m_elapsed_time; - } - } - } - - if ( bAccuracyTest ) - { - for ( i = 0; i < test_count; i++ ) - { - tests[i]->AccuracyTest(test_point_count,tp); - } - } - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->CalculateResults(*curve,test_point_count,tp,best_time); - } - - // print title - tests[0]->Print(text_log,test_point_count); - - // print results for each test - for ( i = 0; i < test_count; i++ ) - { - tests[i]->Print(text_log,0); - } -} - - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Dale's new surface closest point -// -class CDaleSurfacePointTest : public CClosestPointToSurfaceTest -{ -public: - virtual void Setup( ON_NurbsSurface* nurbs_surface ); - virtual int GetClosestPoint(ON_3dPoint P, double* s, double* t); -}; - -void CDaleSurfacePointTest::Setup( ON_NurbsSurface* nurbs_surface ) -{ - SetupHelper(CSurfaceTestPoint::FUNC_SRF_CLSPT_NEWON,nurbs_surface); - nurbs_surface->SurfaceTree(); // prebuild surface tree -} - -int CDaleSurfacePointTest::GetClosestPoint( ON_3dPoint P, double* s, double* t ) -{ - return m_nurbs_surface->GetClosestPoint(P,s,t); -} - - -/////////////////////////////////////////////////////////////////////////////////////// -// -// Goose closest point -// - -class CGooseSurfacePointTest : public CClosestPointToSurfaceTest -{ -public: - CGooseSurfacePointTest(); - ~CGooseSurfacePointTest(); - - virtual void Setup( ON_NurbsSurface* nurbs_surface ); - virtual int GetClosestPoint( ON_3dPoint P, double* s, double* t ); - - ON_3dPoint srfP; // surface midpoint - TL_NURBSRF N; - IwPoint3d Q; - IwExtent2d Interval; - IwBSplineSurface* pS; -}; - -CGooseSurfacePointTest::CGooseSurfacePointTest() -{ - memset(&N,0,sizeof(N)); - pS =0; -} - -CGooseSurfacePointTest::~CGooseSurfacePointTest() -{ - N.cv = 0; - N.knot[0] = 0; - N.knot[1] = 0; - TL_DestroyNurbSrf(&N); - delete pS; -} - -void CGooseSurfacePointTest::Setup( ON_NurbsSurface* nurbs_surface ) -{ - SetupHelper(CSurfaceTestPoint::FUNC_SRF_CLSPT_GOOSE,nurbs_surface); - - srfP = nurbs_surface->PointAt(nurbs_surface->Domain(0).ParameterAt(0.5),nurbs_surface->Domain(1).ParameterAt(0.5)); - - memset(&N,0,sizeof(N)); - N.dim = nurbs_surface->m_dim; - N.is_rat = nurbs_surface->m_is_rat; - N.order[0] = nurbs_surface->m_order[0]; - N.order[1] = nurbs_surface->m_order[1]; - N.cv_count[0] = nurbs_surface->m_cv_count[0]; - N.cv_count[1] = nurbs_surface->m_cv_count[1]; - N.cv = nurbs_surface->m_cv; - N.knot[0] = nurbs_surface->m_knot[0]; - N.knot[1] = nurbs_surface->m_knot[1]; - - TL_Convert( N, pS ); - Interval = pS->GetNaturalUVDomain(); - IwCacheMgr::GetOrCreateObjectCache(IW_OC_SURFACE,pS); -} - -int CGooseSurfacePointTest::GetClosestPoint( ON_3dPoint P, double* s, double* t ) -{ - int rc; - double dist_tol; - IwStatus iw_rc; - - IwSolutionArray sSolutions; - - dist_tol = (1.0+ON_SQRT_EPSILON)*P.DistanceTo(P); - - Q.x = P.x; - Q.y = P.y; - Q.z = P.z; - - iw_rc = pS->GlobalPointSolve( - Interval, - IW_SO_MINIMIZE, - Q, - dist_tol, - NULL,// NULL, - IW_SR_SINGLE, - sSolutions - ); - - if ( iw_rc == IW_SUCCESS && sSolutions.GetSize() > 0) - { - *s = sSolutions[0].m_vStart[0]; - *t = sSolutions[0].m_vStart[1]; - rc = 1; - } - else - { - rc = 0; - } - - return rc; -} - - -void TestClosestPointToThisSurface( ON_TextLog& text_log, - ON_NurbsSurface& nurbs_surface, - double sample_start_distance, - double sample_stop_distance - ) -{ - CClosestPointToSurfaceTest* tests[20]; - int test_count = 0; - int i; - bool bSpeedTest = true; - bool bAccuracyTest = true; - - CDaleSurfacePointTest dale_test; - CGooseSurfacePointTest goose_test; - - dale_test.Setup(&nurbs_surface); - goose_test.Setup(&nurbs_surface); - - tests[test_count++] = &dale_test; - //tests[test_count++] = &goose_test; - - // get test points - ON_SimpleArray TP; - GetSurfacePointCloud( nurbs_surface, sample_start_distance, sample_stop_distance, TP ); - CSurfaceTestPoint* tp = TP.Array(); - int test_point_count = TP.Count(); - - if ( 0.0 == sample_stop_distance ) - { - text_log.Print("Testing %d points exactly on the surface.\n", - test_point_count); - } - else if ( sample_start_distance == sample_stop_distance ) - { - text_log.Print("Testing %d points about %g units off of the surface.\n", - test_point_count, - sample_start_distance); - } - else - { - text_log.Print("Testing %d points from %g to %g units off of the surface.\n", - test_point_count, - sample_start_distance,sample_stop_distance); - } - - double best_time = 0.0; - - // execution time tests - if ( bSpeedTest ) - { - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->SpeedTest(test_point_count,tp); - } - - for ( i = 0; i < test_count; i++ ) - { - if ( 0.0 == best_time || (tests[i]->m_results.m_elapsed_time > 0.0 && tests[i]->m_results.m_elapsed_time < best_time )) - { - best_time = tests[i]->m_results.m_elapsed_time; - } - } - } - - if ( bAccuracyTest ) - { - for ( i = 0; i < test_count; i++ ) - { - tests[i]->AccuracyTest(test_point_count,tp); - } - } - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->CalculateResults(nurbs_surface,test_point_count,tp,best_time); - } - - // print title - tests[0]->Print(text_log,test_point_count); - - // print results for each test - for ( i = 0; i < test_count; i++ ) - { - tests[i]->Print(text_log,0); - } -} - -void TestClosestPointToThisMesh( ON_TextLog& text_log, - const ON_Mesh& mesh, - const ON_Surface* srf, - double sample_start_distance, - double sample_stop_distance - ) -{ - CClosestPointToMeshTest* tests[20]; - int test_count = 0; - int i; - bool bSpeedTest = true; - bool bAccuracyTest = true; - - // get test points - ON_SimpleArray TP; - GetMeshPointCloud( mesh, sample_start_distance, sample_stop_distance, TP ); - CMeshTestPoint* tp = TP.Array(); - int test_point_count = TP.Count(); - - CClosestPointToMeshTest first_test; - - first_test.SetupHelper( &mesh, srf ); - - tests[test_count++] = &first_test; - - if ( 0.0 == sample_stop_distance ) - { - text_log.Print("Testing %d points exactly on the mesh.\n", - test_point_count); - } - else if ( sample_start_distance == sample_stop_distance ) - { - text_log.Print("Testing %d points about %g units off of the mesh.\n", - test_point_count, - sample_start_distance); - } - else - { - text_log.Print("Testing %d points from %g to %g units off of the mesh.\n", - test_point_count, - sample_start_distance,sample_stop_distance); - } - - double best_time = 0.0; - - // execution time tests - if ( bSpeedTest ) - { - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->SpeedTest(test_point_count,tp); - } - - } - - if ( bAccuracyTest ) - { - for ( i = 0; i < test_count; i++ ) - { - tests[i]->AccuracyTest(test_point_count,tp); - } - } - - for ( i = 0; i < test_count; i++ ) - { - tests[i]->CalculateResults(test_point_count,tp); - } - - // print title - tests[0]->Print(text_log,test_point_count); -} - -void TestCurveTree(ON_TextLog& text_log, ON_NurbsCurve& nurbs_curve) -{ - const ON_CurveTree* tree = nurbs_curve.CurveTree(); - if ( !tree->IsValid( &text_log, &nurbs_curve ) ) - { - text_log.Print("Curve tree is not valid\n"); - } - - if (true) - { - ON_CurveTreeNode* leaf = tree->FirstLeaf(); - int leaf_count=0; - double maxar = 0.0; - double maxr = 0.0; - double maxlen = 0.0; - double longest = 0.0; - double shortest = fabs(ON_UNSET_VALUE); - ON_Line axis; - int notmonocount = 0; - while (leaf) - { - if( !leaf->m_bez->m_leafbox.m_bMono ) - notmonocount++; - axis.from = leaf->m_bez->PointAt(0.0); - axis.to = leaf->m_bez->PointAt(1.0); - double len = axis.Length(); - if (len > longest ) - longest = len; - if ( len < shortest ) - shortest = len; - if ( leaf->m_bez->m_leafbox.Radius() > maxar*len ) - { - maxar = leaf->m_bez->m_leafbox.Radius()/len; - maxlen = len; - maxr = leaf->m_bez->m_leafbox.Radius(); - } - leaf_count++; - leaf = leaf->NextLeaf(); - } - if ( notmonocount > 0 ) - { - text_log.Print("ON_CurveTree: %d leaves (%d are not monotone).\n",leaf_count,notmonocount); - } - else - { - text_log.Print("ON_CurveTree: %d leaves (all are monotone).\n",leaf_count); - } - text_log.PushIndent(); - text_log.Print("Longest: %g\n",longest); - text_log.Print("Shortest: %g\n",shortest); - if ( maxar > 0.0 ) - text_log.Print("Thickest: rad/len = %g (rad = %g, len = %g)\n",maxar,maxr,maxlen); - text_log.PopIndent(); - } -} - - - -void TestSurfaceTree(ON_TextLog& text_log, ON_NurbsSurface& nurbs_surface) -{ - const ON_SurfaceTree* tree = nurbs_surface.SurfaceTree(); - if ( !tree->IsValid( &text_log, &nurbs_surface ) ) - { - text_log.Print("Surface tree is not valid.\n"); - } - - if (true) - { - ON_SurfaceTreeNode* leaf = tree->FirstLeaf(); - int leaf_count=0; - double maxar = 0.0; - double maxr = 0.0; - double maxlen = 0.0; - double longest = 0.0; - double shortest = fabs(ON_UNSET_VALUE); - ON_3dPoint C[4]; - int notmonocount = 0; - while (leaf) - { - if( !leaf->m_bez->m_leafbox.m_bMono ) - notmonocount++; - C[0] = leaf->m_bez->PointAt(0.0,0.0); - C[1] = leaf->m_bez->PointAt(1.0,0.0); - C[2] = leaf->m_bez->PointAt(1.0,1.0); - C[3] = leaf->m_bez->PointAt(0.0,1.0); - - double len = C[3].DistanceTo(C[0]); - - for ( int i = 0; i < 3; i++ ) - { - double x = C[i].DistanceTo(C[i+1]); - if ( x > len ) - len = x; - } - - if (len > longest ) - longest = len; - - if ( len < shortest ) - shortest = len; - - if ( leaf->m_bez->m_leafbox.Height() > maxar*len ) - { - maxlen = len; - maxr = leaf->m_bez->m_leafbox.Height(); - maxar = maxr/len; - } - leaf_count++; - leaf = leaf->NextLeaf(); - } - - if ( notmonocount > 0 ) - { - text_log.Print("ON_SurfaceTree: %d leaves (%d are not monotone).\n",leaf_count,notmonocount); - } - else - { - text_log.Print("ON_SurfaceTree: %d leaves (all are monotone).\n",leaf_count); - } - - text_log.PushIndent(); - text_log.Print("Longest: %g\n",longest); - text_log.Print("Shortest: %g\n",shortest); - if ( maxar > 0.0 ) - text_log.Print("Thickest: ht/len = %g (ht = %g, len = %g)\n",maxar,maxr,maxlen); - text_log.PopIndent(); - } -} - -class CTestMeshTreeHelper -{ -public: - CTestMeshTreeHelper(); - - void Test( const ON_MeshTreeNode* node, int depth ); - - void Report( ON_TextLog& text_log ) const; - - double m_tree_diagonal; - int m_one_branch_node_count; - int m_two_branch_node_count; - int m_leaf_count; - int m_max_depth; - int m_max_branched_node_fcount; - int m_min_leaf_fcount; - int m_max_leaf_fcount; - double m_min_leaf_diagonal; - double m_max_leaf_diagonal; - double m_min_diagonal_ratio; // maximum (child node diag)/(parent node diag). - double m_max_diagonal_ratio; // maximum (child node diag)/(parent node diag). -}; - -CTestMeshTreeHelper::CTestMeshTreeHelper() -{ - memset(this,0,sizeof(*this)); - m_tree_diagonal = ON_UNSET_VALUE; - m_min_leaf_diagonal = 1.0e150; - m_min_leaf_fcount = -1; - m_min_diagonal_ratio = 1.0e150; -} - - -void CTestMeshTreeHelper::Test( const ON_MeshTreeNode* node, int depth) -{ - if ( !node ) - return; - - int down_count = 0; - - const double node_diagonal = node->m_bbox.Diagonal().Length(); - - if ( ON_UNSET_VALUE == m_tree_diagonal ) - { - m_tree_diagonal = node_diagonal; - } - - if ( depth > m_max_depth ) - { - m_max_depth = depth; - } - - if ( node->m_down[0] ) - { - down_count++; - double d = node->m_down[0]->m_bbox.Diagonal().Length()/node_diagonal; - if ( d > m_max_diagonal_ratio ) - { - m_max_diagonal_ratio = d; - } - if ( d < m_min_diagonal_ratio ) - { - m_min_diagonal_ratio = d; - } - Test( node->m_down[0], depth+1 ); - } - - if ( node->m_down[1] ) - { - down_count++; - double d = node->m_down[1]->m_bbox.Diagonal().Length()/node_diagonal; - if ( d > m_max_diagonal_ratio ) - { - m_max_diagonal_ratio = d; - } - if ( d < m_min_diagonal_ratio ) - { - m_min_diagonal_ratio = d; - } - Test( node->m_down[1], depth+1 ); - } - - if ( down_count ) - { - if ( node->m_fcount > m_max_branched_node_fcount ) - { - m_max_branched_node_fcount = node->m_fcount; - } - if ( 1 == down_count ) - m_one_branch_node_count++; - else - m_two_branch_node_count++; - } - else - { - m_leaf_count++; - if ( 1 == m_leaf_count ) - { - m_max_leaf_fcount = m_min_leaf_fcount = node->m_fcount; - } - else if ( node->m_fcount > m_max_leaf_fcount ) - { - m_max_leaf_fcount = node->m_fcount; - } - else if ( node->m_fcount < m_min_leaf_fcount ) - { - m_min_leaf_fcount = node->m_fcount; - } - - if ( node_diagonal > m_max_leaf_diagonal ) - { - m_max_leaf_diagonal = node_diagonal; - } - if ( node_diagonal < m_min_leaf_diagonal ) - { - m_min_leaf_diagonal = node_diagonal; - } - } -} - - -void CTestMeshTreeHelper::Report( ON_TextLog& textlog ) const -{ - textlog.Print("%d one branch nodes\n",m_one_branch_node_count); - textlog.Print("%d two branch nodes\n",m_two_branch_node_count); - textlog.Print("%d leaf nodes\n",m_leaf_count); - textlog.Print("%d total nodes\n",m_leaf_count+m_two_branch_node_count+m_one_branch_node_count); - textlog.Print("Maximum depth: %d\n",m_max_depth); - textlog.Print("Maximum branched node face count: %d\n",m_max_branched_node_fcount); - textlog.Print("Diagonal reduction (child/parent): %g to %g\n", - m_min_diagonal_ratio, - m_max_diagonal_ratio); - textlog.Print("Leaf node face count: %d to %d\n",m_min_leaf_fcount,m_max_leaf_fcount); - textlog.Print("Leaf diagonal size: %g to %g\n",m_min_leaf_diagonal,m_max_leaf_diagonal); -} - -void TestMeshTree(ON_TextLog& text_log, const ON_Mesh& mesh) -{ - const ON_MeshTree* tree = mesh.MeshTree(); - - if ( !tree ) - { - text_log.Print("mesh.MeshTree() returned NULL.\n"); - ON_ERROR("mesh.MeshTree() returned NULL."); - return; - } - - if ( !tree->IsValid( &text_log ) ) - { - text_log.Print("Mesh tree is not valid.\n"); - ON_ERROR("mesh.MeshTree() is not valid."); - } - else - { - text_log.Print("Mesh tree is valid.\n"); - } - - if (true) - { - CTestMeshTreeHelper testmeshhelper; - testmeshhelper.Test(tree,1); - - text_log.PushIndent(); - testmeshhelper.Report(text_log); - text_log.PopIndent(); - } - -} - -void TestClosestPointToCurveHelper( ON_TextLog& text_log, const ON_Curve* curve, const wchar_t* name, const ON_SimpleArray& point_list ) -{ - TL_NurbsCurve nurbs_curve; - int pass; - double sample_start_distance = 0.0; - double sample_stop_distance = 0.0; - - if ( curve ) - { - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - - curve->GetNurbForm(nurbs_curve); - - text_log.Print(L"Curve class = %S, name = %s, degree = %d, %s, CV count=%d\n", - curve->ClassId()->ClassName(), - name, - nurbs_curve.m_order-1, - (nurbs_curve.m_is_rat ? L"rational" : L"non-rational"), - nurbs_curve.m_cv_count - ); - - TestCurveTree( text_log, nurbs_curve ); - - for ( pass = 0; pass < 3; pass++ ) - { - switch(pass) - { - case 0: - sample_start_distance = 0.0; - sample_stop_distance = 0.0; - break; - - case 1: - sample_start_distance = 1.0/pow(2.0,8); - sample_stop_distance = 1.0/pow(2.0,5); - break; - - case 2: - sample_start_distance = 0.25; - sample_stop_distance = 1.0; - break; - } - - text_log.PushIndent(); - - text_log.Print("\n"); - - TestClosestPointToThisCurve( text_log, curve, sample_start_distance, sample_stop_distance ); - - text_log.PopIndent(); - } - - text_log.Print("\n"); - } -} - - - - -void TestClosestPointToSurfaceHelper( ON_TextLog& text_log, const ON_Surface* surface, const wchar_t* name, const ON_SimpleArray& point_list ) -{ - TL_NurbsSurface nurbs_surface; - int pass; - double sample_start_distance = 0.0; - double sample_stop_distance = 0.0; - - if ( surface ) - { - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - - surface->GetNurbForm(nurbs_surface); - - text_log.Print(L"Surface name = %s, degree = (%d,%d) %s, CV count=(%d,%d)\n", - name, - nurbs_surface.m_order[0]-1,nurbs_surface.m_order[1]-1, - (nurbs_surface.m_is_rat ? L"rational" : L"non-rational"), - nurbs_surface.m_cv_count[0],nurbs_surface.m_cv_count[1] - ); - - TestSurfaceTree( text_log, nurbs_surface ); - - for ( pass = 0; pass < 3; pass++ ) - { - switch(pass) - { - case 0: - sample_start_distance = 0.0; - sample_stop_distance = 0.0; - break; - - case 1: - sample_start_distance = 1.0/pow(2.0,8); - sample_stop_distance = 1.0/pow(2.0,5); - break; - - case 2: - sample_start_distance = 0.25; - sample_stop_distance = 1.0; - break; - } - - text_log.PushIndent(); - - text_log.Print("\n"); - - TestClosestPointToThisSurface( text_log, nurbs_surface, sample_start_distance, sample_stop_distance ); - - text_log.PopIndent(); - } - - text_log.Print("\n"); - } -} - -void TestClosestPointToMeshHelper( ON_TextLog& text_log, - const ON_Mesh* mesh, - const ON_Surface* surface, - const wchar_t* name, - const ON_SimpleArray& point_list - ) -{ - int pass; - double sample_start_distance = 0.0; - double sample_stop_distance = 0.0; - - if ( mesh ) - { - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - - text_log.Print(L"Mesh name = %s\n", - name); - text_log.PushIndent(); - text_log.Print(L"vertex count = %d\n", - mesh->VertexCount() - ); - text_log.Print(L"face count = %d (%d tris, %d quads)\n", - mesh->FaceCount(), - mesh->TriangleCount(), - mesh->QuadCount() - ); - text_log.PopIndent(); - - TestMeshTree( text_log, *mesh ); - - for ( pass = 0; pass < 3; pass++ ) - { - switch(pass) - { - case 0: - sample_start_distance = 0.0; - sample_stop_distance = 0.0; - break; - - case 1: - sample_start_distance = 1.0/pow(2.0,8); - sample_stop_distance = 1.0/pow(2.0,5); - break; - - case 2: - sample_start_distance = 0.25; - sample_stop_distance = 1.0; - break; - } - - text_log.PushIndent(); - - text_log.Print("\n"); - - TestClosestPointToThisMesh( text_log, *mesh, surface, sample_start_distance, sample_stop_distance ); - - text_log.PopIndent(); - } - - text_log.Print("\n"); - } -} - - - -void TestClosestPoint( const ONX_Model& model, ON_TextLog& text_log, - bool bDoCurves, - bool bDoSurfaces, - bool bDoMeshes ) -{ - TEST_HEADER(text_log,"TestClosestPoint"); - - int i, k; - - ON_wString name; - const wchar_t* attributes_name; - - ON_SimpleArray< ON_3dPoint > points(1024); - // first do curves - if (bDoPoints) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Point* point = ON_Point::Cast(model.m_object_table[i].m_object); - if ( point ) - { - points.Append(point->point); - continue; - } - - - const ON_PointCloud* pointcloud = ON_PointCloud::Cast(model.m_object_table[i].m_object); - if ( pointcloud ) - { - points.Append( pointcloud->m_P.Count(), pointcloud->m_P.Array() ); - continue; - } - } - } - - - // first do curves - if ( bDoCurves) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Curve* curve = ON_Curve::Cast(model.m_object_table[i].m_object); - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - TestClosestPointToCurveHelper(text_log,curve,attributes_name,points); - continue; - } - - - const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( brep ) - { - for ( k = 0; k < brep->m_C3.Count(); k++ ) - { - curve = brep->m_C3[k]; - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_C3[%d]",attributes_name,k); - TestClosestPointToCurveHelper(text_log,curve,name,points); - } - } - - for ( k = 0; k < brep->m_C2.Count(); k++ ) - { - curve = brep->m_C2[k]; - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_C2[%d]",attributes_name,k); - TestClosestPointToCurveHelper(text_log,curve,name,points); - } - } - continue; - } - } - } - - // then do surfaces - if ( bDoSurfaces ) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Surface* surface = ON_Surface::Cast(model.m_object_table[i].m_object); - if ( surface ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - TestClosestPointToSurfaceHelper(text_log,surface,attributes_name,points); - continue; - } - - const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( brep ) - { - for ( k = 0; k < brep->m_S.Count(); k++ ) - { - surface = brep->m_S[k]; - if ( surface ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_S[%d]",attributes_name,k); - - TestClosestPointToSurfaceHelper(text_log,surface,model.m_object_table[i].m_attributes.m_name,points); - } - } - continue; - } - } - } - - // then do meshes - if ( bDoMeshes ) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Mesh* mesh = ON_Mesh::Cast(model.m_object_table[i].m_object); - if ( mesh ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - TestClosestPointToMeshHelper(text_log,mesh,0,attributes_name,points); - continue; - } - - const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( brep ) - { - for ( k = 0; k < brep->m_F.Count(); k++ ) - { - mesh = brep->m_F[k].Mesh( ON::render_mesh ); - if ( mesh ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_F[%d] render mesh",attributes_name,k); - - TestClosestPointToMeshHelper( - text_log, - mesh, - brep->m_F[k].SurfaceOf(), - model.m_object_table[i].m_attributes.m_name,points); - } - } - continue; - } - } - } -} - diff --git a/tests/TestCurveCurveIntersection.cpp b/tests/TestCurveCurveIntersection.cpp deleted file mode 100644 index 19871138..00000000 --- a/tests/TestCurveCurveIntersection.cpp +++ /dev/null @@ -1,709 +0,0 @@ - - -#include "Tests.h" - -class CCCXTest -{ -public: - CCCXTest() : TLX0(), TLX1() { TLX0.SetCapacity(5); TLX1.SetCapacity(5); - TLX2.SetCapacity(5); TLX3.SetCapacity(5);}; - ON_3dPoint P; // curve(t) - - ON_SimpleArray TLX0; - ON_SimpleArray TLX1; - - ON_SimpleArray TLX2; - ON_SimpleArray TLX3; - - IwSolutionArray iwX0; - IwSolutionArray iwX1; - - int i0; // Indicies of crv on the array of tranlated curves - int i1; - - double t0; // these are the parameters of an intersection point - double t1; - double d; // == 0 if P = crv(t) and > 0 otherwise - - double gregt; - double tlt; - double gooset; - - double gregd; - double tld; - double goosed; -}; - -class TestCurve{ -public: - TestCurve( const ON_Curve& orig); - TestCurve( ); - ~TestCurve(); - - void SetCurve( const ON_Curve& orig); - ON_Curve* crv; - - void MakeOthers(); // Makes the Iwbs and TL_NURB and gets trees for all three. - IwBSplineCurve* Iwbs; - - int gnfrc; //getnurbform return code - - TL_NURB Nurb; - - double t0; // base parameter value -}; - -TestCurve::TestCurve( const ON_Curve& orig){ - SetCurve( orig); - gnfrc = 0; - Iwbs = NULL; -} - -TestCurve::TestCurve(){ - crv = NULL; - Iwbs = NULL; -} - -TestCurve::~TestCurve(){ - delete crv; - delete Iwbs; -} - -void TestCurve::SetCurve( const ON_Curve& orig){ - if(crv){ - delete crv; - delete Iwbs; - Iwbs = NULL; - } - crv = orig.DuplicateCurve(); -} - - -void TestCurve::MakeOthers(){ - memset(&Nurb,0,sizeof(Nurb)); - - ON_NurbsCurve nc; - gnfrc = crv->GetNurbForm(nc); - - if(gnfrc<1) - return; - - Nurb.dim = nc.m_dim; - Nurb.is_rat = nc.m_is_rat; - Nurb.order = nc.m_order; - Nurb.cv_count = nc.m_cv_count; - Nurb.cv = nc.m_cv; - Nurb.knot = nc.m_knot; - - - TL_Convert( Nurb, Iwbs ); - - // build GSLib curve tree - IwCacheMgr::GetOrCreateObjectCache(IW_OC_CURVE,Iwbs); - - // build Greg's curve tree - crv->CurveTree(); - -} - -// Get a family of translates of the curve that all go though a supplied Base Point -// On input the array contains a single curve. -// On output the aray contains a list of translates of the original that pass through the base point. -void GetCurveTranslates( const ON_Curve& C0, ON_ClassArray< TestCurve>& C, ON_3dPoint BasePoint ) -{ - int Samples_per_span=7; //7 //4; - const int MaxSamples=150; //150?? - const int MinSamples=35; - - const int span_count = C0.SpanCount(); - if (span_count < 1 ) - { - return; - } - double* span_vector = (double*)onmalloc((span_count+1)*sizeof(*span_vector)); - if ( !C0.GetSpanVector(span_vector)) - return; - - int SpanGrouping = 1; - int SpanRemainder = 0; - if( span_count * Samples_per_span< MinSamples){ - Samples_per_span = MinSamples/span_count + 1; - } - - if( span_count * Samples_per_span> MaxSamples){ - int MaxSpans = MaxSamples/ Samples_per_span +1; - SpanGrouping = span_count/MaxSpans; - SpanRemainder = span_count - SpanGrouping*MaxSpans ; - } - - for (int i = 0; i < span_count; ) - { - int j=(i==0)?0:1; - ON_Interval span_domain(span_vector[i],span_vector[i+SpanGrouping]); - i+=SpanGrouping; - if((SpanRemainder--)>0) - span_domain[1]= span_vector[++i]; - - for ( /* j already init'd*/ ; j <= Samples_per_span; j++ ) - -// TODO: use this to avoid knots -// for ( int j = 1; j < Samples_per_span; j++ ) - { - double t = span_domain.ParameterAt(((double)j)/((double)Samples_per_span)); - - ON_3dPoint P0 = C0.PointAt(t); - ON_3dVector Del = BasePoint - P0; - - TestCurve& Ctrans = C.AppendNew(); - Ctrans.SetCurve( C0); - Ctrans.crv->Translate(Del); - Ctrans.t0 = t; - Ctrans.MakeOthers(); - } - } - - onfree(span_vector); -} - -void TestCCX( ON_TextLog& text_log, - ON_ClassArray< TestCurve > & Crv0 , - ON_ClassArray< TestCurve > & Crv1, - ON_3dPoint BasePoint) -{ - double greg_time = 0.0; - double goose_time = 0.0; - double tl_time = 0.0; - - ON_ClassArray CCX_Result; - int N0 = Crv0.Count(); - int N1 = Crv1.Count(); - int N = N0 * N1; - - CCX_Result.SetCapacity(N); - CCX_Result.SetCount(N); - - // Record expected results - int i0, i1, i; - for ( i0 = 0; i0 < N0 ; i0++ ){ - i = N1*i0; - for ( i1 = 0; i1 < N1 ; i1++, i++ ) - { - CCX_Result[i].i0 = i0; - CCX_Result[i].i1 = i1; - CCX_Result[i].t0 = Crv0[i0].t0; - CCX_Result[i].t1 = Crv1[i1].t0; - } - } - const double intersection_tolerance = .01; - - //////////////////////////////////////////// - // - // Speed Test - // - - // TL's curve/curve intersection - { - TEST_ElapsedTime(); - for ( i0 = 0; i0 < N0 ; i0++ ){ - i = N1*i0; - for ( i1 = 0; i1 < N1 ; i1++, i++ ) - { - TL_CCX( *Crv0[i0].crv, *Crv1[i1].crv, intersection_tolerance, CCX_Result[i].TLX0); - TL_CCX( *Crv1[i1].crv, *Crv0[i0].crv, intersection_tolerance, CCX_Result[i].TLX1); - } - } - tl_time = TEST_ElapsedTime(); - } - - // Gregs new's curve/curve intersection -#if 0 - { - TEST_ElapsedTime(); - for ( i0 = 0; i0 < N0 ; i0++ ){ - i = N1*i0; - for ( i1 = 0; i1 < N1 ; i1++, i++ ) - { - DaleCCX( *Crv0[i0].crv, *Crv1[i1].crv, intersection_tolerance, CCX_Result[i].TLX2); - DaleCCX( *Crv1[i1].crv, *Crv0[i0].crv, intersection_tolerance, CCX_Result[i].TLX3); - } - } - greg_time = TEST_ElapsedTime(); - } -#endif - - // Get a GSLib curve - { - IwStatus iw_rc; - IwPoint3d Q; - - TEST_ElapsedTime(); - for ( i0 = 0; i0 < N0 ; i0++ ){ - i = N1*i0; - for ( i1 = 0; i1 < N1 ; i1++, i++ ){ - - ON_Interval D= Crv0[i0].crv->Domain(); - IwExtent1d Dom0(D.m_t[0],D.m_t[1]); - D= Crv1[i1].crv->Domain(); - IwExtent1d Dom1(D.m_t[0],D.m_t[1]); - - iw_rc = Crv0[i0].Iwbs->GlobalCurveIntersect( - Dom0, - *Crv1[i1].Iwbs, - Dom1, - intersection_tolerance, - CCX_Result[i].iwX0 ); - - if ( iw_rc == IW_SUCCESS && CCX_Result[i].iwX0.GetSize() > 0) - { - //rc = (sSolutions.GetSize() > 1 ) ? TL_SUCCESS+8 : TL_SUCCESS; - //t = X.m_vStart[0]; - } - else { - TL_ERROR("GSLib GlobalCurveIntersect failed"); - } - - iw_rc = Crv1[i1].Iwbs->GlobalCurveIntersect( - Dom1, - *Crv0[i0].Iwbs, - Dom0, - intersection_tolerance, - CCX_Result[i].iwX1 ); - - if ( iw_rc == IW_SUCCESS && CCX_Result[i].iwX1.GetSize() > 0) - { - //rc = (sSolutions.GetSize() > 1 ) ? TL_SUCCESS+8 : TL_SUCCESS; - //t = X.m_vStart[0]; - } - else { - TL_ERROR("GSLib GlobalCurveIntersect failed"); - } - - - } - } - goose_time = TEST_ElapsedTime(); - } - - - //////////////////////////////////////////// - // - // Accuracy Test - // - - - ON_Interval Dom[2]; - bool IsClosed[2]; - Dom[0]= Crv0[0].crv->Domain(); - Dom[1] = Crv1[0].crv->Domain(); - IsClosed[0]=Crv0[0].crv->IsClosed()!=0; - IsClosed[1]=Crv1[0].crv->IsClosed()!=0; - - double min_time = tl_time; - - double tl_error3d =0; - int tl_int_point_cnt=0; - int tl_inoverlap_cnt=0; - - double goose_error3d =0; - int goose_int_point_cnt=0; - int goose_inoverlap_cnt=0; - - double greg_error3d =0; - int greg_int_point_cnt=0; - int greg_inoverlap_cnt=0; - - for(i=0; i=0){ - tl_error3d += bestdist0; - tl_int_point_cnt++; - } - else { - NoGoodResult = true; - } - if(TLInOverlap1 ) - tl_inoverlap_cnt++; - else if( jbest1>=0){ - tl_error3d += bestdist1; - tl_int_point_cnt++; - } - else { - NoGoodResult = true; - } - if(NoGoodResult){ - NoGoodResult = true; // break here - } - - - // Test accuracy of GregCCX results - // 3d error to BasePoint - jbest0=-1; - jbest1=-1; - bestdist1 = ON_DBL_MAX; - bool GregInOverlap0=false; // set true if the ideal intersection point is - // contained in an overlap - bool GregInOverlap1=false; // set true if the ideal intersection point is - // contained in an overlap - for( j=0; j=0){ - greg_error3d += bestdist0; - greg_int_point_cnt++; - } - else { - NoGoodResult = true; - } - if(GregInOverlap1 ) - greg_inoverlap_cnt++; - else if( jbest1>=0){ - greg_error3d += bestdist1; - greg_int_point_cnt++; - } - else { - NoGoodResult = true; - } - if(NoGoodResult){ - NoGoodResult = true; // break here - } - - bool GooseInOverlap0=false; - bool GooseInOverlap1=false; - - jbest0 = -1; - bestdist0 = ON_DBL_MAX; - dist = ON_DBL_MAX; - int count = Test.iwX0.GetSize(); - for( j=0; jPointAt(t0); - ON_3dPoint PB = Crv1[Test.i1].crv->PointAt(t1); - dist = BasePoint.DistanceTo( PA) + - BasePoint.DistanceTo( PB); - if(distPointAt(t0); - ON_3dPoint PB = Crv1[Test.i1].crv->PointAt(t1); - dist = BasePoint.DistanceTo( PA) + - BasePoint.DistanceTo( PB); - if(dist=0){ - goose_error3d += bestdist0; - goose_int_point_cnt++; - } - else - NoGoodResult = true; - - if( GooseInOverlap1) - goose_inoverlap_cnt++; - else if(jbest1>=0){ - goose_error3d += bestdist1; - goose_int_point_cnt++; - } - else - NoGoodResult = true; - - - if(NoGoodResult){ - int jjj=7777; // break here - } - } - - - if ( goose_time < min_time ) - min_time = goose_time; - if ( 0.0 == min_time ) - min_time = 1.0/((double)CLOCKS_PER_SEC); - text_log.Print("Number of global curve curve intersection tests %d\n",N); - text_log.Print("Code: Perfection TL Goose Greg\n"); - text_log.Print("Relative Time: 1.00X %5.2fX %5.2fX %5.2fX\n", tl_time/min_time, goose_time/min_time, greg_time/min_time); - text_log.Print("Absolute Time: 0.0 secs %6.3f secs %6.3f secs %6.3f secs\n", tl_time, goose_time, greg_time); - - text_log.Print("#Points/Overlap: %d/0 %d/%d %d/%d %d/%d \n", 2*N, - tl_int_point_cnt, tl_inoverlap_cnt, - goose_int_point_cnt, goose_inoverlap_cnt, - greg_int_point_cnt, greg_inoverlap_cnt ); - if(tl_int_point_cnt>0 && goose_int_point_cnt>0 && greg_int_point_cnt>0) - text_log.Print("Avg Error: 0.00 %.2g %.2g %.2g \n", tl_error3d/ tl_int_point_cnt, - goose_error3d/goose_int_point_cnt , - greg_error3d/ greg_int_point_cnt ); -} - -void TestCurveCurveIntersection( const ONX_Model& model, ON_TextLog& text_log ) -{ - TEST_HEADER(text_log,"TestCurveCurveIntersection"); - - int i; - - double sample_start_distance = 0.0; - double sample_stop_distance = 0.0; - - ON_ClassArray< ON_ClassArray< TestCurve> > Crv; - ON_ClassArray Name; // Input curve names - - // Base Point for all intersections - ON_3dPoint BasePoint(23.74,-394,15); - int ci=0; - - if ( model.IsValid() ) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Curve* curve = ON_Curve::Cast(model.m_object_table[i].m_object); - if ( curve ) - { - const wchar_t* name = model.m_object_table[i].m_attributes.m_name; - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - Name.Append(name); - - ON_ClassArray& CrvFamily = Crv.AppendNew(); - - GetCurveTranslates(*curve, CrvFamily, BasePoint); - ci++; - - } - } - } - - ON_SimpleArray permute( Name.Count() ); - permute.SetCount( Name.Count()); - Name.Sort( ON::heap_sort, permute, ON_CompareIncreasing ); - - for( int ci=0; ciDump(log); - - int si = dump.Find('\n'); - if(si>0){ - string = dump.Left(si); - dump = dump.Right( dump.Length()-si-1); - si = dump.Find('\n'); - if( si>0) - string += dump.Left(si); - } - text_log.Print(L"Curve %d: name = %s, %s\n",ci, Name[permute[ci]], - string); - text_log.Print("\n"); - } - - for(int i0=0; i0 0; n *= 2 ) - { - w *= 0.5; - for ( j = 1; j < n; j += 2 ) - { - s = j; - s *= w; - t = overlap_domain.ParameterAt(s); - C = curve->PointAt(t); - uv.Set(ON_UNSET_VALUE,ON_UNSET_VALUE); - surface->GetClosestPoint(C,&uv.x,&uv.y); - S = surface->PointAt(uv.x,uv.y); - d = C.DistanceTo(S); - if ( d > maxd ) - { - maxd = d; - } - sample_count--; - } - } - - return maxd; -} - -static -int GetGooseCurveSurfaceIntersection( - const ON_Curve* curve, - const ON_Surface* surface, - const IwBSplineCurve* goose_curve, - const IwBSplineSurface* goose_surface, - double intersection_tolerance, - double overlap_tolerance, - double test_tolerance, - ON_SimpleArray& goose_x - ) -{ - if ( !goose_curve || !goose_surface ) - return 1; - - ON_3dPoint Cpt[2], Spt[2]; - int bogus_events_from_old_csx = 0; - IwSolutionArray G( 100 ); - goose_surface->GlobalCurveIntersect( - goose_surface->GetNaturalUVDomain(), - *goose_curve, - goose_curve->GetNaturalInterval(), - intersection_tolerance, - G - ); - - unsigned int gi; - int i; - double d; - for ( gi = 0; gi < G.GetSize(); gi++ ) - { - int closest_i = -1; - double closest_d = 1.0e300; - - IwSolution& g = G[gi]; - - ON_X_EVENT goose_event; - IwSolutionType iw_xtype = g.m_eSolutionType; - IwPoint3d iwpt; - if ( iw_xtype == IW_ST_RANGE_OF_VALUES && g.m_vStart[0] >= g.m_vEnd[0] ) - { - iw_xtype = IW_ST_SINGLE_VALUE; - g.m_vEnd[0] = g.m_vStart[0]; - g.m_vEnd[1] = g.m_vStart[1]; - g.m_vEnd[2] = g.m_vStart[2]; - } - - switch ( iw_xtype ) - { - case IW_ST_SINGLE_VALUE: - // isolated intersection point - goose_event.m_type = ON_X_EVENT::csx_point; - - goose_event.m_a[0] = goose_event.m_a[1] = g.m_vStart[0]; - goose_event.m_b[0] = goose_event.m_b[2] = g.m_vStart[1]; - goose_event.m_b[1] = goose_event.m_b[3] = g.m_vStart[2]; - - goose_curve->EvaluatePoint(goose_event.m_a[0],iwpt); - goose_event.m_A[0].Set(iwpt.x,iwpt.y,iwpt.z); - goose_event.m_A[1] = goose_event.m_A[0]; - - goose_surface->EvaluatePoint(IwPoint2d(goose_event.m_b[0],goose_event.m_b[1]),iwpt); - goose_event.m_B[0].Set(iwpt.x,iwpt.y,iwpt.z); - goose_event.m_B[1] = goose_event.m_B[0]; - break; - - case IW_ST_RANGE_OF_VALUES: - // overlap region - goose_event.m_type = ON_X_EVENT::csx_overlap; - - goose_event.m_a[0] = g.m_vStart[0]; - goose_event.m_a[1] = g.m_vEnd[0]; - goose_event.m_b[0] = g.m_vStart[1]; - goose_event.m_b[1] = g.m_vStart[2]; - goose_event.m_b[2] = g.m_vEnd[1]; - goose_event.m_b[3] = g.m_vEnd[2]; - - goose_curve->EvaluatePoint(goose_event.m_a[0],iwpt); - goose_event.m_A[0].Set(iwpt.x,iwpt.y,iwpt.z); - goose_curve->EvaluatePoint(goose_event.m_a[1],iwpt); - goose_event.m_A[1].Set(iwpt.x,iwpt.y,iwpt.z); - - goose_surface->EvaluatePoint(IwPoint2d(goose_event.m_b[0],goose_event.m_b[1]),iwpt); - goose_event.m_B[0].Set(iwpt.x,iwpt.y,iwpt.z); - goose_surface->EvaluatePoint(IwPoint2d(goose_event.m_b[2],goose_event.m_b[3]),iwpt); - goose_event.m_B[1].Set(iwpt.x,iwpt.y,iwpt.z); - break; - } - for ( i = 0; i < 2; i++ ) - { - if ( i && ON_X_EVENT::csx_overlap != goose_event.m_type ) - { - goose_event.m_a[1] = goose_event.m_a[0]; - goose_event.m_b[2] = goose_event.m_b[0]; - goose_event.m_b[3] = goose_event.m_b[1]; - goose_event.m_nodeA_t[1] = goose_event.m_nodeA_t[0]; - goose_event.m_nodeB_t[2] = goose_event.m_nodeB_t[0]; - goose_event.m_nodeB_t[3] = goose_event.m_nodeB_t[1]; - } - else - { - goose_event.m_nodeA_t[i] = goose_event.m_a[i]; - curve->GetCurveParameterFromNurbFormParameter(goose_event.m_a[i],&goose_event.m_a[i]); - goose_event.m_nodeB_t[2*i] = goose_event.m_b[2*i]; - goose_event.m_nodeB_t[2*i+1] = goose_event.m_b[2*i+1]; - surface->GetSurfaceParameterFromNurbFormParameter(goose_event.m_b[2*i],goose_event.m_b[2*i+1],&goose_event.m_b[2*i],&goose_event.m_b[2*i+1]); - if ( i && goose_event.m_a[1] <= goose_event.m_a[0] ) - { - // micro overlap?? - bogus_events_from_old_csx++; - ON_X_EVENT::CopyEventPart(goose_event,0,goose_event,1); - goose_event.m_type = ON_X_EVENT::csx_point; - } - } - } - - d = goose_event.m_A[0].DistanceTo(goose_event.m_B[0]); - if ( d > test_tolerance ) - { - bogus_events_from_old_csx++; - ON_X_EVENT::CopyEventPart(goose_event,1,goose_event,0); - goose_event.m_type = ON_X_EVENT::csx_point; - } - - d = goose_event.m_A[1].DistanceTo(goose_event.m_B[1]); - if ( d > test_tolerance ) - { - bogus_events_from_old_csx++; - if ( goose_event.m_a[0] == goose_event.m_a[1] ) - continue; - ON_X_EVENT::CopyEventPart(goose_event,0,goose_event,1); - goose_event.m_type = ON_X_EVENT::csx_point; - } - - // validate goose_event - Cpt[0] = curve->PointAt(goose_event.m_a[0]); - Spt[0] = surface->PointAt(goose_event.m_b[0],goose_event.m_b[1]); - Cpt[1] = curve->PointAt(goose_event.m_a[1]); - Spt[1] = surface->PointAt(goose_event.m_b[2],goose_event.m_b[3]); - d = Cpt[0].DistanceTo(Spt[0]); - if ( d > test_tolerance ) - { - bogus_events_from_old_csx++; - ON_X_EVENT::CopyEventPart(goose_event,1,goose_event,0); - goose_event.m_type = ON_X_EVENT::csx_point; - Cpt[0] = Cpt[1]; - Spt[0] = Spt[1]; - } - - d = Cpt[1].DistanceTo(Spt[1]); - if ( d > test_tolerance ) - { - bogus_events_from_old_csx++; - if ( goose_event.m_a[0] == goose_event.m_a[1] ) - continue; - ON_X_EVENT::CopyEventPart(goose_event,0,goose_event,1); - goose_event.m_type = ON_X_EVENT::csx_point; - } - - if ( ON_X_EVENT::csx_overlap == goose_event.m_type ) - { - d = TestOverlapDistance(ON_Interval(goose_event.m_a[0],goose_event.m_a[1]), - curve,surface,120); - if ( d > test_tolerance ) - { - bogus_events_from_old_csx++; - goose_event.m_type = ON_X_EVENT::csx_point; - ON_X_EVENT& e0 = goose_x.AppendNew(); - e0 = goose_event; - ON_X_EVENT::CopyEventPart( e0, 0, e0, 1 ); - e0.m_type = ON_X_EVENT::csx_point; - ON_X_EVENT::CopyEventPart( goose_event, 1, goose_event, 0 ); - goose_event.m_type = ON_X_EVENT::csx_point; - } - } - - goose_x.Append(goose_event); - } - - return bogus_events_from_old_csx; -} - -static int TestCSXCompareWithGoose( - ON_TextLog& text_log, - CTestCurve& test_curve, - CTestSurface& test_surface, - const ON_SimpleArray& x, - int overlap_sample_count, - double intersection_tolerance, - double overlap_tolerance - ) -{ - int gi; - int j, xi; - double d; - - int missed_event_count = 0; - - intersection_tolerance = ON_X_EVENT::IntersectionTolerance(intersection_tolerance); - overlap_tolerance = ON_X_EVENT::OverlapTolerance(intersection_tolerance,overlap_tolerance); - // testing accuracy - const double test_tolerance = 1.01*intersection_tolerance; - - const ON_Curve* curve = test_curve.m_curve; - const ON_Surface* surface = test_surface.m_surface; - const IwBSplineCurve* goose_curve = test_curve.GooseCurve(); - const IwBSplineSurface* goose_surface = test_surface.GooseSurface(); - - - ON_SimpleArray goose_x(16 + x.Count()); - int bogus_events_from_old_csx = GetGooseCurveSurfaceIntersection( - curve,surface,goose_curve,goose_surface, - intersection_tolerance,overlap_tolerance,test_tolerance, - goose_x - ); - - for ( gi = 0; gi < goose_x.Count(); gi++ ) - { - ON_X_EVENT& goose_event = goose_x[gi]; - for ( j = 0; j < 2; j++ ) - { - if ( j && ON_X_EVENT::csx_overlap != goose_event.m_type) - break; - - double closest_d = 1.0e300; - int closest_i = -1; - - // find the csx event that is closest to goose_event.m_A[j] - for ( xi = 0; xi < x.Count() && closest_d > test_tolerance; xi++ ) - { - const ON_X_EVENT& e = x[xi]; - d = goose_event.m_A[j].DistanceTo(e.m_A[0]); - if ( d < closest_d ) - { - closest_d = d; - closest_i = xi; - } - - if ( ON_X_EVENT::csx_overlap == e.m_type ) - { - if ( d <= test_tolerance && 0 == j && goose_event.m_a[0] < e.m_a[0] ) - { - goose_event.m_a[0] = e.m_a[0]; - } - - d = goose_event.m_A[j].DistanceTo(e.m_A[1]); - if ( d < closest_d ) - { - closest_d = d; - closest_i = xi; - } - if ( d <= test_tolerance && 1 == j && goose_event.m_a[1] > e.m_a[1] ) - { - goose_event.m_a[1] = e.m_a[1]; - } - - if ( e.m_a[0] <= goose_event.m_a[j] && goose_event.m_a[j] <= e.m_a[1] ) - { - // goose event is inside an overlap region - d = test_tolerance; - if ( d < closest_d ) - { - closest_d = d; - closest_i = xi; - } - } - } - } - - if ( closest_d > test_tolerance ) - { - ON_ERROR("ON_Curve::IntersectSurface() missed a point"); - text_log.Print("ERROR: Missed an intersection event at curve(%g) = ",goose_event.m_a[j]); - text_log.Print(goose_event.m_A[j]); - text_log.Print("\n"); - missed_event_count++; - } - } - - if ( ON_X_EVENT::csx_overlap == goose_event.m_type && goose_event.m_a[0] < goose_event.m_a[1] ) - { - // make sure we found this overlap - for ( xi = 0; xi < x.Count(); xi++ ) - { - const ON_X_EVENT& e = x[xi]; - if ( e.m_a[0] <= goose_event.m_a[0] && goose_event.m_a[1] <= e.m_a[1] ) - { - break; - } - - if ( goose_event.m_a[1] - goose_event.m_a[0] <= 1.0e-3 - && e.m_A[0].DistanceTo( goose_event.m_A[0] ) <= test_tolerance - && e.m_A[0].DistanceTo( goose_event.m_A[1] ) <= test_tolerance - && e.m_A[0].DistanceTo( curve->PointAt(0.5*(goose_event.m_a[0]+goose_event.m_a[1])) ) <= test_tolerance - ) - { - // bogus goose micro overlap - break; - } - } - - if ( xi >= x.Count() ) - { - ON_ERROR("ON_Curve::IntersectSurface() missed an overlap."); - text_log.Print("ERROR: Missed an itersection event on curve(%g to %g) = \n",goose_event.m_a[0],goose_event.m_a[1]); - text_log.PushIndent(); - text_log.Print(goose_event.m_A[0]); text_log.Print(" to "); - text_log.Print(goose_event.m_A[1]); - text_log.PopIndent(); - text_log.Print("\n"); - missed_event_count++; - } - } - } - - if ( bogus_events_from_old_csx > 0 ) - { - ON_WARNING("Old TL_CSX had bogus events - make sure TestCSXCompareWithGoose() is working right."); - text_log.Print("ALERT Old TL_CSX had bogus events - make sure TestCSXCompareWithGoose() is working right.\n\n"); - } - - return missed_event_count; -} - -static int TestCSX( ON_TextLog& text_log, - CTestCurve& test_curve, - CTestSurface& test_surface, - int* missed_event_count - ) -{ - int i; - - const ON_Curve* curve = test_curve.m_curve; - - const ON_Surface* surface = test_surface.m_surface; - - *missed_event_count = 0; - - const int overlap_sample_count = bPurify ? 3 : 255; - - const double intersection_tolerance = 0.0; - const double overlap_tolerance = 0.0; - - const ON_CurveTree* ctree = curve->CurveTree(); - if ( !ctree ) - { - text_log.Print("ERROR - curve->CurveTree() = NULL\n"); - return 0; - } - - const ON_SurfaceTree* stree = surface->SurfaceTree(); - if ( !stree ) - { - text_log.Print("ERROR - surface->SurfaceTree() = NULL\n"); - return 0; - } - - ON_SimpleArray x(16); - curve->IntersectSurface(surface,x,intersection_tolerance,overlap_tolerance); - - text_log.Print("%d curve-surface intersection events.\n",x.Count()); - text_log.PushIndent(); - - // dump intersection information - ON_String saved_double_format; - text_log.GetDoubleFormat(saved_double_format); - text_log.SetDoubleFormat("%g"); // so diffs don't flag minute changes - for ( i = 0; i < x.Count(); i++ ) - { - text_log.Print("xevent[%d]:\n",i); - text_log.PushIndent(); - x[i].Dump(text_log); - text_log.PopIndent(); - } - text_log.SetDoubleFormat(saved_double_format); - - // data structure validation - if ( x.Count() > 0 ) - { - text_log.Print("Validating intersection events ...\n"); - text_log.PushIndent(); - bool bIsValid = ON_X_EVENT::IsValidList( - x.Count(), - x.Array(), - &text_log, - intersection_tolerance, - overlap_tolerance, - curve,0, - 0,0, - surface,0,0 - ); - text_log.PopIndent(); - if ( bIsValid ) - { - text_log.Print("... Event is list valid.\n"); - } - } - - if ( !bPurify ) - { - // Compare results with goose to see if there are any missed events. - // (This really slow's down the purify tests - so its skipped in purify builds.) - i = TestCSXCompareWithGoose( - text_log, - test_curve, - test_surface, - x, - overlap_sample_count, - intersection_tolerance, - overlap_tolerance - ); - - *missed_event_count = *missed_event_count + i; - } - - text_log.PopIndent(); - - return x.Count(); -} - -// tool for saving problem cases in file that has a single curve and surface. -bool SaveCSXTest( const char* filename, - const ON_Curve* curve, - const ON_Surface* surface - ) -{ - bool rc = false; - - if ( curve && surface && filename && filename[0] ) - { - ONX_Model model; - - ONX_Model_Object& curve_object = model.m_object_table.AppendNew(); - curve_object.m_object = curve; - curve_object.m_bDeleteObject = false; - - ONX_Model_Object& surface_object = model.m_object_table.AppendNew(); - surface_object.m_object = surface; - surface_object.m_bDeleteObject = false; - - model.Polish(); - rc = model.Write(filename); - } - - return rc; -} - - -static void TestCurveSurfaceIntersectionListObjects( CTestModel& model, ON_TextLog& text_log ) -{ - const int curve_count = model.m_curves.Count(); - const int surface_count = model.m_surfaces.Count(); - - int i; - - const wchar_t* name; - ON_UUID curve_uuid, surface_uuid; - - text_log.Print("%d curves:\n",curve_count); - text_log.PushIndent(); - for ( i = 0; i < curve_count; i++ ) - { - CTestCurve& C = model.m_curves[i]; - curve_uuid = C.m_uuid; - name = C.m_name; - if ( !name || !name[0] ) - name = L"anonymous curve"; - const ON_NurbsCurve& nurbs_curve = C.NurbsCurve(); - text_log.Print("curve[%d] %s\n",i,C.m_curve->ClassId()->ClassName()); - text_log.PushIndent(); - text_log.Print("id: "); text_log.Print(curve_uuid); text_log.Print("\n"); - text_log.Print(L"name: %s\n",name); - text_log.Print("degree = %d, %s, CV count=%d\n", - nurbs_curve.m_order-1, - (nurbs_curve.m_is_rat ? L"rational" : L"non-rational"), - nurbs_curve.m_cv_count - ); - text_log.PopIndent(); - } - text_log.PopIndent(); - - - text_log.Print("\n"); - text_log.Print("%d surfaces:\n",surface_count); - text_log.PushIndent(); - for ( i = 0; i < surface_count; i++ ) - { - CTestSurface& S = model.m_surfaces[i]; - surface_uuid = S.m_uuid; - name = S.m_name; - if ( !name || !name[0] ) - name = L"anonymous surface"; - const ON_NurbsSurface& nurbs_surface = S.NurbsSurface(); - text_log.Print("surface[%d] %s\n",i,S.m_surface->ClassId()->ClassName()); - text_log.PushIndent(); - text_log.Print("id: "); text_log.Print(surface_uuid); text_log.Print("\n"); - text_log.Print(L"name: %s\n",name); - text_log.Print(L"degree = (%d,%d), %s, CV count=(%d,%d)\n", - nurbs_surface.m_order[0]-1,nurbs_surface.m_order[1]-1, - (nurbs_surface.m_is_rat ? L"rational" : L"non-rational"), - nurbs_surface.m_cv_count[0],nurbs_surface.m_cv_count[1] - ); - text_log.PopIndent(); - - } - text_log.PopIndent(); -} - - -static int TestCurveSurfaceIntersectionAccuracy( CTestModel& model, ON_TextLog& text_log ) -{ - const int curve_count = model.m_curves.Count(); - const int surface_count = model.m_surfaces.Count(); - - ON_UUID curve_uuid, surface_uuid; - - int total_missed_event_count = 0; - int missed_event_count; - - int i, j; - - bool bSaveExample = false; - - int event_count = 0; - - - int bad_curve_index = -1; - int bad_surface_index = -1; - - // intersect every curve with every surface - for ( i = ( bad_curve_index>=0 ? bad_curve_index : 0); i < curve_count; i++ ) - { - CTestCurve& test_curve = model.m_curves[i]; - curve_uuid = test_curve.m_uuid; - - for ( j = (bad_surface_index>=0 ? bad_surface_index : 0); j < surface_count; j++ ) - { - CTestSurface& test_surface = model.m_surfaces[j]; - surface_uuid = test_surface.m_uuid; - - if ( bad_curve_index != -1 && bad_surface_index != -1 ) - { - // use debugger to set bSaveExample = true - ON_String filename; - filename.Format("C:\\csx_bug_%03d_%03d.3dm",bad_curve_index,bad_surface_index); - SaveCSXTest( filename.Array(), test_curve.m_curve, test_surface.m_surface ); - printf("Saved curve[%d] and surface[%d] in %s\n",i,j,filename.Array()); - } - - text_log.Print("curve[%d] ",i); text_log.Print(curve_uuid); text_log.Print("\n"); - text_log.Print("surface[%d] ",j); text_log.Print(surface_uuid); text_log.Print("\n"); - text_log.PushIndent(); - missed_event_count = 0; - event_count += TestCSX( text_log, test_curve, test_surface, &missed_event_count ); - total_missed_event_count += missed_event_count; - text_log.PopIndent(); - text_log.Print("\n"); - - if ( bad_surface_index == j ) - break; - } - - if ( bad_curve_index == i ) - break; - - } - - return total_missed_event_count; -} - -static void TestCurveSurfaceIntersectionSpeed( CTestModel& model, ON_TextLog& text_log ) -{ - const int curve_count = model.m_curves.Count(); - const int surface_count = model.m_surfaces.Count(); - - int i, j; - - // pre-build GSLib trees - int c_count = 0; - for( i = 0; i < curve_count; i++ ) - { - CTestCurve& C = model.m_curves[i]; - const IwBSplineCurve* goose_curve = C.GooseCurve(); - if ( goose_curve ) - { - IwCacheMgr::GetOrCreateObjectCache(IW_OC_CURVE,goose_curve); - c_count++; - } - } - - int s_count = 0; - for ( j = 0; j < surface_count; j++ ) - { - CTestSurface& S = model.m_surfaces[j]; - const IwBSplineSurface* goose_surface = S.GooseSurface(); - if (goose_surface ) - { - s_count++; - IwCacheMgr::GetOrCreateObjectCache(IW_OC_SURFACE,goose_surface); - } - } - - double intersection_tolerance = 0.001; - double dale_time = 0.0; - double goose_time = 0.0; - double min_time = 0.0; - double delta_time; - - int n_count = 0; - int dale_event_count = 0; - int goose_event_count = 0; - - if ( c_count > 0 && s_count > 0 ) - { - n_count = 1; -#if !defined(ON_DEBUG) - while ( n_count*c_count*s_count < 20000 ) - { - n_count++; - } -#endif - int n, test; - - // test 0 = dale, 1 = goose - for ( test = 0; test < 2; test++ ) - { - if ( 1==test && model.m_bPurify ) - { - n_count = 1; - goose_time = dale_time = 0.0; - break; - } - - TEST_ElapsedTime(); - for ( n = 0; n < n_count; n++ ) - { - for( i = 0; i < curve_count; i++ ) - { - CTestCurve& C = model.m_curves[i]; - const ON_Curve* curve = C.m_curve; - const IwBSplineCurve* goose_curve = C.m_goose_curve; - if ( 0 == goose_curve ) - continue; - - for ( j = 0; j < surface_count; j++ ) - { - CTestSurface& S = model.m_surfaces[j]; - const ON_Surface* surface = S.m_surface; - const IwBSplineSurface* goose_surface = S.m_goose_surface; - if ( 0 == goose_surface ) - continue; - - if (test) - { - // goose - IwSolutionArray x(16); - goose_surface->GlobalCurveIntersect( - goose_surface->GetNaturalUVDomain(), - *goose_curve, - goose_curve->GetNaturalInterval(), - intersection_tolerance, - x - ); - if ( !n ) - goose_event_count += x.GetSize(); - } - else - { - // dale - ON_SimpleArray x(16); - curve->IntersectSurface( surface, x, intersection_tolerance ); - if ( !n ) - dale_event_count += x.Count(); - } - } - } - } - delta_time = TEST_ElapsedTime(); - - switch(test) - { - case 0: - dale_time = delta_time; - break; - case 1: - goose_time = delta_time; - break; - } - } - } - - min_time = (dale_time < goose_time) ? dale_time : goose_time; - if ( min_time <= 0.0 ) - min_time = 1.0; - - text_log.Print("%d repetitions of %d intersection tests.\n",n_count,c_count*s_count); - text_log.Print("Test Dale Goose\n"); - if ( model.m_bPurify ) - { - } - else - { - text_log.Print("Seconds %6.2f %6.2f\n",dale_time,goose_time); - text_log.Print("Relative %5.2fX %5.2fX\n",dale_time/min_time,goose_time/min_time); - } - text_log.Print("Events %5d %5d\n",dale_event_count,goose_event_count); -} - -void TestCurveSurfaceIntersection( CTestModel& model, ON_TextLog& text_log ) -{ - TEST_HEADER(text_log,"TestCurveSurfaceIntersection"); - - bool bListObjects = true; - bool bAccuracyTests = true; - bool bSpeedTests = true; - - bPurify = model.m_bPurify; - -#if defined(_DEBUG) - bSpeedTests = false; -#endif; - - int total_missed_event_count = 0; - - if ( bListObjects && !bPurify ) - { - text_log.Print("\n"); - text_log.Print("\n"); - text_log.Print("Curve-Surfaces Intersection Objects:\n"); - text_log.Print("\n"); - text_log.PushIndent(); - TestCurveSurfaceIntersectionListObjects( model, text_log ); - text_log.PopIndent(); - } - - if ( bAccuracyTests ) - { - text_log.Print("\n"); - text_log.Print("\n"); - text_log.Print("Curve-Surface Intersection Accuracy Tests:\n"); - text_log.Print("\n"); - text_log.PushIndent(); - total_missed_event_count = TestCurveSurfaceIntersectionAccuracy( model, text_log ); - text_log.PopIndent(); - } - - if ( bSpeedTests && !bPurify ) - { - text_log.Print("\n"); - text_log.Print("\n"); - text_log.Print("Curve-Surface Intersection Speed Tests:\n"); - text_log.Print("\n"); - text_log.PushIndent(); - TestCurveSurfaceIntersectionSpeed(model,text_log ); - text_log.PopIndent(); - } - - if ( total_missed_event_count > 0 ) - { - text_log.Print( - "Opennurbs may have missed up to %d intersection events \n" - "and these potential misses are counted as errors below.\n", - total_missed_event_count - ); - } -} - - diff --git a/tests/TestNurbsCageEvaluate.cpp b/tests/TestNurbsCageEvaluate.cpp deleted file mode 100644 index 77346bee..00000000 --- a/tests/TestNurbsCageEvaluate.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "../opennurbs.h" -#include "../opennurbs_extensions.h" - -#include "Tests.h" - -static -bool TestNurbsCageEvaluateHelper( ON_TextLog& text_log, const ON_NurbsCage& cage ) -{ - ON_Workspace ws; - - int err_count = 0; - int pass_count = 0; - bool ok = true; - const int der_count = 3; // <= 3 - const int v_stride = 3; - ON_NurbsSurface srfst, srfrs, srfrt; - int cage_hint[3] = {0,0,0}; - int srfst_hint[2] = {0,0}; - int srfrs_hint[2] = {0,0}; - int srfrt_hint[2] = {0,0}; - ON_3dVector cageV,stV,rsV,rtV; - - ON_3dVector *cagev, *stv, *rsv, *rtv; - - cagev = (ON_3dVector*)onmalloc(sizeof(*cagev)*(der_count+1)*(der_count+2)*(der_count+3)/6); - stv = (ON_3dVector*)onmalloc(sizeof(*stv)*(der_count+1)*(der_count+2)/2); - rsv = (ON_3dVector*)onmalloc(sizeof(*rsv)*(der_count+1)*(der_count+2)/2); - rtv = (ON_3dVector*)onmalloc(sizeof(*rtv)*(der_count+1)*(der_count+2)/2); - - int i,j,k,ii,jj,kk,di,dj,dk,dc; - double r,s,t,errst,errrt,errrs,tol; - for ( i = cage.m_order[0]-2; ok&&i < cage.m_cv_count[0]-1; i++ ) - { - ON_Interval rspan(cage.m_knot[0][i],cage.m_knot[0][i+1]); - if ( rspan.Length() <= 0.0 ) - continue; - for ( ii = 0; ok && ii <= 4; ii++ ) - { - r = rspan.ParameterAt(0.25*ii); - if (!cage.IsoSurface(0,r,&srfst)) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) failed"); - ok = false; - } - - for ( j = cage.m_order[1]-2; ok && j < cage.m_cv_count[1]-1; j++ ) - { - ON_Interval sspan(cage.m_knot[1][j],cage.m_knot[1][j+1]); - if ( sspan.Length() <= 0.0 ) - continue; - for ( jj = 0; ok && jj <= 4; jj++ ) - { - s = sspan.ParameterAt(0.25*jj); - if ( !cage.IsoSurface(1,s,&srfrt) ) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) failed"); - ok = false; - } - - for ( k = cage.m_order[2]-2; ok && k < cage.m_cv_count[2]-1; k++ ) - { - ON_Interval tspan(cage.m_knot[2][k],cage.m_knot[2][k+1]); - if ( tspan.Length() <= 0.0 ) - continue; - for ( kk = 0; ok && kk <= 4; kk++ ) - { - t = tspan.ParameterAt(0.25*kk); - if( !cage.IsoSurface(2,t,&srfrs) ) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=2,...) failed"); - ok = false; - } - - if ( !cage.Evaluate(r,s,t,der_count,v_stride,&cagev[0].x,0,cage_hint)) - { - err_count++; - ON_ERROR("ON_NurbsCage::Evaluate - invalid cage"); - ok = false; - } - - if ( !srfst.Evaluate(s,t,der_count,v_stride,&stv[0].x,0,srfst_hint)) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=0,...) returned invalid surface"); - ok = false; - } - - if ( !srfrt.Evaluate(s,t,der_count,v_stride,&rtv[0].x,0,srfrt_hint)) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=1,...) returned invalid surface"); - ok = false; - } - - if ( !srfrs.Evaluate(s,t,der_count,v_stride,&rsv[0].x,0,srfrs_hint)) - { - err_count++; - ON_ERROR("ON_NurbsCage::IsoSurface(dir=2,...) returned invalid surface"); - ok = false; - } - - - for ( dc = 0; dc <= der_count; dc++ ) - { - tol = pow(10.0,dc-11); - for ( di = dc; di >= 0; di--) - { - for (dj = dc-di; dj >= 0; dj--) - { - dk = dc-di-dj; - if ( di && dj && dk ) - continue; - cageV = cagev[dc*(dc+1)*(dc+2)/6 + (dj+dk)*(dj+dk+1)/2 + dk]; - stV = (di) ? cageV : stv[(dj+dk)*(dj+dk+1)/2 + dk]; - rtV = (dj) ? cageV : stv[(di+dk)*(di+dk+1)/2 + dk]; - rsV = (dk) ? cageV : stv[(di+dj)*(di+dj+1)/2 + dj]; - errst = (cageV-stV).MaximumCoordinate(); - errrt = (cageV-rtV).MaximumCoordinate(); - errrs = (cageV-rsV).MaximumCoordinate(); - if ( errst > tol && errrt > tol && errrs > tol ) - { - err_count++; - ON_ERROR("ON_NurbsCage::Evaluate - bad value"); - if ( err_count > 20 ) - ok = false; - } - else - { - pass_count++; - } - } - } - } - } - } - } - } - } - } - - onfree(rtv); - onfree(rsv); - onfree(stv); - onfree(cagev); - - return ok; -} - -bool TestNurbsCageEvaluate( ON_TextLog& text_log ) -{ - bool ok = false; - - ONX_Model model; - const char* sFileName = "..\\TEstNurbsCageEvaluate.3dm"; - FILE* fp = ON::OpenFile( sFileName, "rb"); - - bool bModelRead = false; - bool bModelIsValid = false; - - if ( 0 != fp ) - { - ON_BinaryFile archive( ON::read3dm, fp ); - bModelRead = model.Read( archive, &text_log ); - ON::CloseFile( fp ); - } - - if ( !bModelRead ) - { - text_log.Print("TestNurbsCageEvaluate cannot read %s\n",sFileName); - } - else - { - int i; - for ( i = 0; i < model.m_object_table.Count(); i++) - { - const ONX_Model_Object& mo = model.m_object_table[i]; - const ON_NurbsCage* model_cage = ON_NurbsCage::Cast(mo.m_object); - if ( !model_cage ) - continue; - ok = TestNurbsCageEvaluateHelper( text_log, *model_cage ); - if ( !ok ) - break; - } - } - - return ok; -} - diff --git a/tests/TestPrecompiledHeader.cpp b/tests/TestPrecompiledHeader.cpp deleted file mode 100644 index 58a756e7..00000000 --- a/tests/TestPrecompiledHeader.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Tests.h" diff --git a/tests/TestQuotientRule.cpp b/tests/TestQuotientRule.cpp deleted file mode 100644 index 0e538c3d..00000000 --- a/tests/TestQuotientRule.cpp +++ /dev/null @@ -1,451 +0,0 @@ -#include "../opennurbs.h" -#include "Tests.h" - -class CF -{ -public: - CF() {r = ON_UNSET_VALUE; s = ON_UNSET_VALUE; t = ON_UNSET_VALUE;} - double r, s, t; - double f[6]; // = x/wr - double g[6]; // = y/ws - double h[6]; // = z/wt - double x[6]; - double y[6]; - double z[6]; - double wr[6]; - double ws[6]; - double wt[6]; -}; - -class CV -{ -public: - double F, X, W; -}; - -static class CV func(double r, double s, double t, - ON_3dex ijk) -{ - static CF ev; - if ( r != ev.r ) - { - ev.x[0] = tan(r); - ev.x[1] = 1.0+ev.x[0]*ev.x[0]; - ev.x[2] = 2.0*ev.x[0]*ev.x[1]; - ev.x[3] = 2.0*(ev.x[1]*ev.x[1] + ev.x[0]*ev.x[2]); - ev.x[4] = 2.0*(3.0*ev.x[1]*ev.x[2] + ev.x[0]*ev.x[3]); - ev.x[5] = 2.0*(3.0*ev.x[2]*ev.x[2] + 4.0*ev.x[1]*ev.x[3] + ev.x[0]*ev.x[4]); - ev.r = r; - - ev.wr[0] = 1.0/cos(r); - ev.wr[1] = ev.wr[0]*ev.x[0]; - ev.wr[2] = ev.wr[1]*ev.x[0] + ev.wr[0]*ev.x[1]; - ev.wr[3] = ev.wr[2]*ev.x[0] + 2.0*ev.wr[1]*ev.x[1] + ev.wr[0]*ev.x[2]; - ev.wr[4] = ev.wr[3]*ev.x[0] + 3.0*ev.wr[2]*ev.x[1] + 3.0*ev.wr[1]*ev.x[2] + ev.wr[0]*ev.x[3]; - ev.wr[5] = ev.wr[4]*ev.x[0] + 4.0*ev.wr[3]*ev.x[1] + 6.0*ev.wr[2]*ev.x[2] + 4.0*ev.wr[1]*ev.x[3] + ev.wr[0]*ev.x[4]; - - ev.f[0] = sin(r); - ev.f[1] = cos(r); - ev.f[2] = -ev.f[0]; - ev.f[3] = -ev.f[1]; - ev.f[4] = -ev.f[2]; - ev.f[5] = -ev.f[3]; - } - - if ( s != ev.s ) - { - ev.y[0] = exp(3.0*s); - ev.y[1] = 3.0*ev.y[0]; - ev.y[2] = 9.0*ev.y[0]; - ev.y[3] = 27.0*ev.y[0]; - ev.y[4] = 81.0*ev.y[0]; - ev.y[5] = 243.0*ev.y[0]; - - ev.ws[0] = exp(2.0*s); - ev.ws[1] = 2.0*ev.ws[0]; - ev.ws[2] = 4.0*ev.ws[0]; - ev.ws[3] = 8.0*ev.ws[0]; - ev.ws[4] = 16.0*ev.ws[0]; - ev.ws[5] = 32.0*ev.ws[0]; - - ev.g[0] = exp(s); - ev.g[1] = ev.g[0]; - ev.g[2] = ev.g[0]; - ev.g[3] = ev.g[0]; - ev.g[4] = ev.g[0]; - ev.g[5] = ev.g[0]; - ev.s = s; - } - - if ( t != ev.t ) - { - double t2 = t*t; - double t3 = t*t2; - double t4 = t*t3; - double t5 = t*t4; - double t6 = t*t5; - double t7 = t*t6; - - ev.z[0] = t7; - ev.z[1] = 7.0*t6; - ev.z[2] = 42.0*t5; - ev.z[3] = 210.0*t4; - ev.z[4] = 840.0*t3; - ev.z[5] = 2520.0*t2; - - ev.wt[0] = t5; - ev.wt[1] = 5.0*t4; - ev.wt[2] = 20.0*t3; - ev.wt[3] = 60.0*t2; - ev.wt[4] = 120.0*t; - ev.wt[5] = 120.0; - - ev.h[0] = t2; - ev.h[1] = 2.0*t; - ev.h[2] = 2.0; - ev.h[3] = 0.0; - ev.h[4] = 0.0; - ev.h[5] = 0.0; - ev.t = t; - } - - - CV V; - V.X = ev.x[ijk.i]*ev.y[ijk.j]*ev.z[ijk.k]; - V.W = ev.wr[ijk.i]*ev.ws[ijk.j]*ev.wt[ijk.k]; - V.F = ev.f[ijk.i]*ev.g[ijk.j]*ev.h[ijk.k]; - - return V; -} - -struct TEST_INPUT -{ - int err_count; - int pass_count; - double der_tol[6]; - int der_count; // 0 <= der_count <= 5 - int dim; // dim > 0 - int n; // 0 <= n < dim - int v_stride; // dim < v_stride <= 7 - double v[6*7*8*7]; // >= (dc+1)*(dc+2)*(dc+3)&v_stride dc = max der_count, vs = max v_stride - double a[6*7*8]; // >= (dc+1)*(dc+2)*(dc+3) - ON_3dex ijk[6*7*8]; // >= (dc+1)*(dc+2)*(dc+3) - - double maxe1; - double maxe2; - double maxe3; -}; - -static void TestQR1(double r, double s, double t, - int coord, - TEST_INPUT& TI - ) -{ - CV V; - double e; - - int err_count = 0; - - int ii = (coord==0)?1:0; - int jj = (coord==1)?1:0; - int kk = (coord==2)?1:0; - - int dc; - - for (dc = 0; dc <= TI.der_count; dc++ ) - { - TI.ijk[dc].i = ii*dc; - TI.ijk[dc].j = jj*dc; - TI.ijk[dc].k = kk*dc; - V = func(r,s,t, TI.ijk[dc]); - TI.v[dc*TI.v_stride+TI.n] = V.X; - TI.v[dc*TI.v_stride+TI.dim] = V.W; - TI.a[dc] = V.F; - } - - if ( !ON_EvaluateQuotientRule(TI.dim,TI.der_count,TI.v_stride,TI.v) ) - { - ON_ERROR("ON_EvaluateQuotientRule - error"); - TI.err_count += (TI.der_count+1); - } - else - { - for ( dc = 0; dc <= TI.der_count; dc++ ) - { - e = fabs(TI.a[dc] - TI.v[dc*TI.v_stride+TI.n]); - if ( e > TI.der_tol[dc] && e > ON_SQRT_EPSILON*fabs(TI.a[dc]) ) - { - ON_ERROR("ON_EvaluateQuotientRule - error"); - TI.err_count++; - } - else - { - if ( e > TI.maxe1 ) - TI.maxe1 = e; - TI.pass_count++; - } - } - } -} - - -static void TestQR2(double r, double s, double t, - int coord, - TEST_INPUT& TI - ) -{ - CV V; - double e; - - int imax = (coord==0)?0:1; - int jmax = (coord==1)?0:1; - int kmax = (coord==2)?0:1; - - int i=0; - int j=0; - int k=0; - int mmax=0; - int m,der_count; - - for ( der_count = 0; der_count <= TI.der_count; der_count++ ) - { - for (m = 0; m <= der_count; m++ ) - { - if ( 0 == coord ) - { - TI.ijk[mmax].i = 0; - TI.ijk[mmax].j = der_count-m; - TI.ijk[mmax].k = m; - } - else if ( 1 == coord ) - { - TI.ijk[mmax].i = der_count-m; - TI.ijk[mmax].j = 0; - TI.ijk[mmax].k = m; - } - else - { - TI.ijk[mmax].i = der_count-m; - TI.ijk[mmax].j = m; - TI.ijk[mmax].k = 0; - } - V = func(r,s,t, TI.ijk[mmax]); - TI.v[mmax*TI.v_stride+TI.n] = V.X; - TI.v[mmax*TI.v_stride+TI.dim] = V.W; - TI.a[mmax] = V.F; - mmax++; - } - } - - if ( !ON_EvaluateQuotientRule2(TI.dim,TI.der_count,TI.v_stride,TI.v) ) - { - ON_ERROR("ON_EvaluateQuotientRule2 - error"); - TI.err_count += mmax; - } - else - { - for ( m = 0; m < mmax; m++ ) - { - e = fabs(TI.a[m] - TI.v[m*TI.v_stride+TI.n]); - der_count = TI.ijk[m].i+TI.ijk[m].j+TI.ijk[m].k; - if ( e > TI.der_tol[der_count] && e > ON_SQRT_EPSILON*fabs(TI.a[m]) ) - { - ON_ERROR("ON_EvaluateQuotientRule2 - error"); - TI.err_count++; - } - else - { - if ( e > TI.maxe2 ) - TI.maxe2 = e; - TI.pass_count++; - } - } - } -} - - -static void TestQR3(double r, double s, double t, - TEST_INPUT& TI - ) -{ - CV V; - double e; - - int i=0; - int j=0; - int k=0; - int mmax=0; - int m,der_count; - - for ( der_count = 0; der_count <= TI.der_count; der_count++ ) - { - for ( i = der_count; i >= 0; i-- ) - { - for ( j = der_count-i; j >= 0; j-- ) - { - k = der_count-i-j; - TI.ijk[mmax].i = i; - TI.ijk[mmax].j = j; - TI.ijk[mmax].k = k; - V = func(r,s,t, TI.ijk[mmax]); - TI.v[mmax*TI.v_stride+TI.n] = V.X; - TI.v[mmax*TI.v_stride+TI.dim] = V.W; - TI.a[mmax] = V.F; - mmax++; - } - } - } - - if ( !ON_EvaluateQuotientRule3(TI.dim,TI.der_count,TI.v_stride,TI.v) ) - { - ON_ERROR("ON_EvaluateQuotientRule3 - error"); - TI.err_count += mmax; - } - else - { - for ( m = 0; m < mmax; m++ ) - { - e = fabs(TI.a[m] - TI.v[m*TI.v_stride+TI.n]); - der_count = TI.ijk[m].i+TI.ijk[m].j+TI.ijk[m].k; - if ( e > TI.der_tol[der_count] && e > ON_SQRT_EPSILON*fabs(TI.a[m]) ) - { - ON_ERROR("ON_EvaluateQuotientRule3 - error"); - TI.err_count++; - } - else - { - if ( e > TI.maxe3 ) - TI.maxe3 = e; - TI.pass_count++; - } - } - } -} - -bool TestQuotientRule( ON_TextLog& text_log ) -{ - - double r,s,t; - struct TEST_INPUT TI; - - memset(&TI,0,sizeof(TI)); - TI.der_tol[0] = 1.0e-12; - TI.der_tol[1] = 1.0e-11; - TI.der_tol[2] = 1.0e-10; - TI.der_tol[3] = 1.0e-9; - TI.der_tol[4] = 1.0e-8; - TI.der_tol[5] = 5.0e-7; - - TI.der_count = 0; - TI.dim = 1; - TI.n = 0; - TI.v_stride = TI.dim+1; - bool ok = true; - for (TI.der_count=0; TI.der_count<=5 && ok; TI.der_count++) - for (TI.dim = 1; TI.dim <= 4 && ok; TI.dim++ ) - for (TI.n= 0; TI.n < TI.dim && ok; TI.n++) - for (TI.v_stride=TI.dim+1; TI.v_stride<=7 && ok; TI.v_stride++) - { - memset(TI.v,0,sizeof(TI.v)); - - // one paramter tests - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( r = -ON_PI/3.0; r <= ON_PI/3.0 && ok; r += ON_PI/120.0) - { - TestQR1(r,s,t,0,TI); - if (TI.err_count > 100 ) - ok = false; - } - - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( s = -2.0; s <= 2.0 && ok; s += 0.1 ) - { - TestQR1(r,s,t,1,TI); - if (TI.err_count > 100 ) - ok = false; - } - - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( t = 0.1; t < 2.5 && ok; t += 0.1 ) - { - TestQR1(r,s,t,2,TI); - if (TI.err_count > 100 ) - ok = false; - } - - // two paramter tests - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( r = -ON_PI/3.0; r <= ON_PI/3.0 && ok; r += ON_PI/120.0) - { - for ( s = -2.0; s <= 2.0 && ok; s += 0.1 ) - { - TestQR2(r,s,t, 2, TI); - if (TI.err_count > 100 ) - ok = false; - } - } - - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( r = -ON_PI/3.0; r <= ON_PI/3.0 && ok; r += ON_PI/120.0) - { - for ( t = 0.1; t < 2.5 && ok; t += 0.1 ) - { - TestQR2(r,s,t, 1, TI); - if (TI.err_count > 100 ) - ok = false; - } - } - - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( s = -2.0; s <= 2.0 && ok; s += 0.1 ) - { - for ( t = 0.1; t < 2.5 && ok; t += 0.1 ) - { - TestQR2(r,s,t, 1, TI); - if (TI.err_count > 100 ) - ok = false; - } - } - - // three paramter tests - r = 0.25*ON_PI; - s = 0.0; - t = 1.0; - - for ( r = -ON_PI/3.0; r <= ON_PI/3.0 && ok; r += ON_PI/120.0) - { - for ( s = -2.0; s <= 2.0 && ok; s += 0.1 ) - { - for ( t = 0.1; t < 2.5 && ok; t += 0.1 ) - { - TestQR3(r,s,t, TI); - if (TI.err_count > 100 ) - ok = false; - } - } - } - } - - text_log.Print("pass_count = %d err_count = %d maxe1 = %g maxe2 = %g maxe3 = %g\n", - TI.pass_count,TI.err_count,TI.maxe1,TI.maxe2,TI.maxe3); - - return (TI.err_count == 0); -} diff --git a/tests/TestTree.cpp b/tests/TestTree.cpp deleted file mode 100644 index e15e5b0b..00000000 --- a/tests/TestTree.cpp +++ /dev/null @@ -1,647 +0,0 @@ -#include "Tests.h" - - -static const bool bPurify = false; -static const bool bDoCurves = true; -static const bool bDoSurfaces = true; - -bool TestCurveTree(ON_TextLog& text_log, const ON_Curve* curve ) -{ - if ( !curve ) - { - text_log.Print("Curve pointer is NULL.\n"); - return false; - } - - const ON_CurveTree* tree = curve->CurveTree(); - if ( !tree ) - { - text_log.Print("CurveTree() returned NULL.\n"); - return false; - } - - bool rc = tree->IsValid( &text_log, curve ); - if ( !rc ) - { - text_log.Print("Curve tree is not valid\n"); - } - - if ( tree != tree->m_root ) - { - // As of 29 March, I want tree to be = tree->m_root. - // and I'd like to get rid of the m_root field, but - // I don't know if that will work for making - // auxillary tree's over a set of trees. - text_log.Print("Curve tree != tree->m_root - please tell Dale Lear.\n"); - } - - const int span_count = curve->SpanCount(); - ON_SimpleArray t(10*(span_count+1)); - t.SetCount(span_count+1); - curve->GetSpanVector(t.Array()); - int i; - for ( i = 0; i < span_count; i++ ) - { - t.Append(0.5*(t[i]+t[i+1])); - } - - - ON_CurveTreeNode* leaf = tree->FirstLeaf(); - int leaf_count=0; - double maxar = 0.0; - double maxr = 0.0; - double maxlen = 0.0; - double longest = 0.0; - double thickest = 0.0; - double shortest = fabs(ON_UNSET_VALUE); - ON_Line axis; - int notmonocount = 0; - while (leaf) - { - if ( t.Search( leaf->m_domain[0] ) < 0 ) - t.Append(leaf->m_domain[0]); - t.Append( leaf->m_domain.ParameterAt(0.2) ); - t.Append( leaf->m_domain.ParameterAt(0.7) ); - if( !leaf->m_bez->m_leafbox.m_bMono ) - notmonocount++; - axis.from = leaf->m_bez->PointAt(0.0); - axis.to = leaf->m_bez->PointAt(1.0); - double len = axis.Length(); - if (len > longest ) - longest = len; - if ( len < shortest ) - shortest = len; - if ( leaf->m_bez->m_leafbox.m_r > thickest ) - thickest = leaf->m_bez->m_leafbox.m_r; - if ( leaf->m_bez->m_leafbox.m_r > maxar*len ) - { - maxar = leaf->m_bez->m_leafbox.m_r/len; - maxlen = len; - maxr = leaf->m_bez->m_leafbox.m_r; - } - leaf_count++; - leaf = leaf->NextLeaf(); - } - if ( notmonocount > 0 ) - { - text_log.Print("ON_CurveTree: %d spans, %d leaves (%d are not monotone).\n",span_count,leaf_count,notmonocount); - } - else - { - text_log.Print("ON_CurveTree: %d spans, %d leaves (all are monotone).\n",span_count,leaf_count); - } - - text_log.PushIndent(); - text_log.Print("Shortest: %g\n",shortest); - text_log.Print("Longest: %g\n",longest); - text_log.Print("Thickest: radius = %g\n",thickest); - text_log.Print("Fattest: rad/len = %g (rad = %g, len = %g)\n",maxar,maxr,maxlen); - text_log.PopIndent(); - - // test evaluation - const bool bAdjustParameter = tree->AdjustParameter(); - double x, y, d0, d1, tol0, tol1; - ON_3dVector X[2], Y[2], Xerr[2], Yerr[2]; - double xerr, yerr, d0err=0.0, d1err=0.0; - int error_count = 0; - int test_count = 0; - int hint = 0; - int side = 0; - const ON_CurveTreeNode* evaluation_node; - if ( 2 == curve->Dimension() ) - { - X[0].z = X[1].z = Y[0].z = Y[1].z = 0.0; - } - for ( i = 0; i < t.Count(); i++ ) - { - x = y = t[i]; - if ( i > span_count && bAdjustParameter) - { - // NOTE - the curve paramter = nurbs form paramter - // at all span vector values. - curve->GetCurveParameterFromNurbFormParameter(x,&y); - } - for ( side = -1; side < 1; side++ ) - { - test_count++; - X[0].x = -99.0; - Y[0].x = 99.0; - curve->Evaluate(y,1,3,&Y[0].x,side,&hint); - evaluation_node = tree->Evaluate(x,1,3,&X[0].x,side); - if ( !evaluation_node ) - { - error_count++; - ON_ERROR("TestCurveTree() - tree failed to evaluate."); - d0err = 1.0e100; - d1err = 1.0e100; - xerr = x; - yerr = y; - Xerr[0] = ON_UNSET_POINT; - Xerr[1] = ON_UNSET_POINT; - Yerr[0] = Y[0]; - Yerr[1] = Y[1]; - } - else - { - if ( side < 0 && x == evaluation_node->m_domain[0] ) - { - // x should be at the start of the curve's domain - // and there shouldn't be any leaves before this one. - if ( evaluation_node->PrevLeaf() || x != t[0] ) - { - ON_ERROR("TestCurveTree() - evaluation used wrong node"); - } - } - else if ( side > 0 && x == evaluation_node->m_domain[1] ) - { - // x should be at the end of the curve's domain - // and there shouldn't be any leaves after this one. - if ( evaluation_node->NextLeaf() || x != t[span_count] ) - { - ON_ERROR("TestCurveTree() - evaluation used wrong node"); - } - } - - if ( bAdjustParameter ) - { - // Different parameterizations result in derivatives - // with different lengths. - X[1].Unitize(); - Y[1].Unitize(); - } - tol0 = ON_ZERO_TOLERANCE + ON_SQRT_EPSILON*Y[0].MaximumCoordinate(); - tol1 = ON_ZERO_TOLERANCE + ON_SQRT_EPSILON*Y[1].MaximumCoordinate(); - d0 = (X[0]-Y[0]).Length(); - d1 = (X[1]-Y[1]).Length(); - if ( d0 > tol0 || d1 > tol1 ) - { - rc = false; - error_count++; - if ( d0 > d0err || (d1 > d1err && d0err < 0.01) ) - { - if ( d0 > d0err) d0err = d0; - if ( d1 > d1err) d1err = d1; - xerr = x; - yerr = y; - Xerr[0] = X[0]; - Xerr[1] = X[1]; - Yerr[0] = Y[0]; - Yerr[1] = Y[1]; - } - } - } - } - } - text_log.PushIndent(); - if ( error_count > 0 ) - { - ON_ERROR("TestCurveTree() - tree failed evaluation test."); - text_log.Print("Evaluation test at %d points had %d errors.\n",test_count,error_count); - text_log.PushIndent(); - text_log.Print("curve(%g) = (%g,%g,%g)\n",yerr,Y[0].x,Y[0].y,Y[0].z); - text_log.Print("tree(%g) = (%g,%g,%g)\n",xerr,X[0].x,X[0].y,X[0].z); - text_log.Print("curve D = (%g,%g,%g)\n",Y[1].x,Y[1].y,Y[1].z); - text_log.Print("tree D = (%g,%g,%g)\n",X[1].x,X[1].y,X[1].z); - text_log.PopIndent(); - } - else - { - text_log.Print("Evaluation test at %d points was successful.\n",test_count); - } - text_log.PopIndent(); - - return rc; -} - - -bool TestSurfaceTree(ON_TextLog& text_log, const ON_Surface* surface ) -{ - if ( !surface ) - { - text_log.Print("Surface pointer is NULL.\n"); - return false; - } - - const ON_SurfaceTree* tree = surface->SurfaceTree(); - if ( !tree ) - { - text_log.Print("SurfaceTree() returned NULL.\n"); - return false; - } - - bool rc = tree->IsValid( &text_log, surface ); - if ( !rc ) - { - text_log.Print("Surface tree is not valid.\n"); - } - - int i; - const int span_count0 = surface->SpanCount(0); - ON_SimpleArray s(10*(span_count0 + 1)); - s.SetCount(span_count0+1); - surface->GetSpanVector( 0, s.Array() ); - for ( i = 0; i < span_count0; i++ ) - { - s.Append(0.5*(s[i]+s[i+1])); - } - - int j; - const int span_count1 = surface->SpanCount(1); - ON_SimpleArray t(10*(span_count1 + 1)); - t.SetCount(span_count1+1); - surface->GetSpanVector( 1, t.Array() ); - for ( j = 0; j < span_count1; j++ ) - { - t.Append(0.5*(t[j]+t[j+1])); - } - - const int span_count = span_count0*span_count1; - - ON_SurfaceTreeNode* leaf = tree->FirstLeaf(); - int leaf_count=0; - double maxar = 0.0; - double maxr = 0.0; - double maxlen = 0.0; - double longest = 0.0; - double thickest = 0.0; - double shortest = fabs(ON_UNSET_VALUE); - ON_3dPoint C[4]; - int notmonocount = 0; - while (leaf) - { - if ( s.Search(leaf->m_domain[0][0]) < 0 ) - s.Append(leaf->m_domain[0][0]); - if ( s.Search(leaf->m_domain[0].ParameterAt(0.3)) < 0 ) - s.Append(leaf->m_domain[0].ParameterAt(0.3)); - if ( s.Search(leaf->m_domain[0].ParameterAt(0.8)) < 0 ) - s.Append(leaf->m_domain[0].ParameterAt(0.8)); - - if ( t.Search(leaf->m_domain[1][0]) < 0 ) - t.Append(leaf->m_domain[1][0]); - if ( t.Search(leaf->m_domain[1].ParameterAt(0.2)) < 0 ) - t.Append(leaf->m_domain[1].ParameterAt(0.2)); - if ( t.Search(leaf->m_domain[1].ParameterAt(0.7)) < 0 ) - t.Append(leaf->m_domain[1].ParameterAt(0.7)); - - - if( !leaf->m_bez->m_leafbox.m_bMono ) - notmonocount++; - C[0] = leaf->m_bez->PointAt(0.0,0.0); - C[1] = leaf->m_bez->PointAt(1.0,0.0); - C[2] = leaf->m_bez->PointAt(1.0,1.0); - C[3] = leaf->m_bez->PointAt(0.0,1.0); - - double len = C[3].DistanceTo(C[0]); - - for ( i = 0; i < 3; i++ ) - { - double x = C[i].DistanceTo(C[i+1]); - if ( x > len ) - len = x; - } - - if (len > longest ) - longest = len; - - if ( len < shortest ) - shortest = len; - - if ( leaf->m_bez->m_leafbox.Height() > thickest ) - thickest = leaf->m_bez->m_leafbox.Height(); - - if ( leaf->m_bez->m_leafbox.Height() > maxar*len ) - { - maxlen = len; - maxr = leaf->m_bez->m_leafbox.Height(); - maxar = maxr/len; - } - leaf_count++; - leaf = leaf->NextLeaf(); - } - - if ( notmonocount > 0 ) - { - text_log.Print("ON_SurfaceTree: %d spans, %d leaves (%d are not monotone).\n",span_count,leaf_count,notmonocount); - } - else - { - text_log.Print("ON_SurfaceTree: %d spans, %d leaves (all are monotone).\n",span_count,leaf_count); - } - - text_log.PushIndent(); - text_log.Print("Shortest: %g\n",shortest); - text_log.Print("Longest: %g\n",longest); - text_log.Print("Thickest: height = %g\n",thickest); - text_log.Print("Fattest: ht/len = %g (ht = %g, len = %g)\n",maxar,maxr,maxlen); - text_log.PopIndent(); - - // test evaluation - const bool bAdjustParameter = tree->AdjustParameter(); - ON_2dPoint x,y; - double d0, ds, dt, tol0, tol1, tol2; - ON_3dVector X[3], Y[3], Xerr[3], Yerr[3]; - ON_2dVector xerr, yerr; - double d0err=0.0, d1err=0.0; - int error_count = 0; - int test_count = 0; - int hint[2] ={0,0}; - int quadrant = 0; - const ON_SurfaceTreeNode* evaluation_node; - for ( i = 0; i < s.Count(); i++ ) - { - x.x = y.x = s[i]; - for ( j = 0; j < t.Count(); j++ ) - { - x.y = y.y = t[j]; - if (( i > span_count0 || j > span_count1) && bAdjustParameter) - { - // NOTE - the surface paramter = nurbs form paramter - // at all span vector values. - surface->GetSurfaceParameterFromNurbFormParameter(s[i],t[j],&y.x,&y.y); - } - - for (quadrant = 0; quadrant <= 4; quadrant++ ) - { - test_count++; - X[0].x = -99.0; - Y[0].x = 99.0; - surface->Evaluate(y.x,y.y,1,3,&Y[0].x,quadrant,hint); - evaluation_node = tree->Evaluate(x.x,x.y,1,3,&X[0].x,quadrant); - if ( !evaluation_node ) - { - error_count++; - ON_ERROR("TestSuraceTree() - tree failed to evaluate."); - d0err = 1.0e100; - d1err = 1.0e100; - xerr = x; - yerr = y; - Xerr[0] = ON_UNSET_POINT; - Xerr[1] = ON_UNSET_POINT; - Xerr[2] = ON_UNSET_POINT; - Yerr[0] = Y[0]; - Yerr[1] = Y[1]; - Yerr[2] = Y[2]; - } - else - { - if ( x.x == evaluation_node->m_domain[0][0] && x.x > s[0] ) - { - if ( 2 == quadrant || 3 == quadrant ) - { - ON_ERROR("TestSuraceTree() ON_SurfaceTreeNode::Evaluate() used the wrong node."); - } - } - else if ( x.x == evaluation_node->m_domain[0][1] && x.x < s[span_count0] ) - { - if ( 1 == quadrant || 4 == quadrant ) - { - ON_ERROR("TestSuraceTree() ON_SurfaceTreeNode::Evaluate() used the wrong node."); - } - } - - if ( x.y == evaluation_node->m_domain[1][0] && x.y > t[0] ) - { - if ( 3 == quadrant || 4 == quadrant ) - { - ON_ERROR("TestSuraceTree() ON_SurfaceTreeNode::Evaluate() used the wrong node."); - } - } - else if ( x.y == evaluation_node->m_domain[1][1] && x.y < t[span_count1] ) - { - if ( 1 == quadrant || 2 == quadrant ) - { - ON_ERROR("TestSuraceTree() ON_SurfaceTreeNode::Evaluate() used the wrong node."); - } - } - - - if ( bAdjustParameter ) - { - // Different parameterizations result in derivatives - // with different lengths. - if ( X[1].Length() <= ON_ZERO_TOLERANCE && Y[1].Length() <= ON_ZERO_TOLERANCE ) - { - // singular point - // Probably a place where the revolute hits the axis in a surface of revolution - X[1].Zero(); - Y[1].Zero(); - } - else - { - X[1].Unitize(); - Y[1].Unitize(); - } - if ( X[2].Length() <= ON_ZERO_TOLERANCE && Y[2].Length() <= ON_ZERO_TOLERANCE ) - { - // singular point - // Probably a place where the revolute hits the axis in a surface of revolution. - X[2].Zero(); - Y[2].Zero(); - } - else - { - X[2].Unitize(); - Y[2].Unitize(); - } - } - tol0 = ON_ZERO_TOLERANCE + ON_SQRT_EPSILON*Y[0].MaximumCoordinate(); - tol1 = ON_ZERO_TOLERANCE + ON_SQRT_EPSILON*Y[1].MaximumCoordinate(); - tol2 = ON_ZERO_TOLERANCE + ON_SQRT_EPSILON*Y[2].MaximumCoordinate(); - d0 = (X[0]-Y[0]).Length(); - ds = (X[1]-Y[1]).Length(); - dt = (X[2]-Y[2]).Length(); - if ( d0 > tol0 || ds > tol1 || dt > tol2 ) - { - rc = false; - error_count++; - if ( d0 > d0err || (ds > d1err && d0err < 0.01) || (dt > d1err && d0err < 0.01) ) - { - if ( d0 > d0err) d0err = d0; - if ( ds > d1err) d1err = ds; - if ( dt > d1err) d1err = dt; - xerr = x; - yerr = y; - Xerr[0] = X[0]; - Xerr[1] = X[1]; - Xerr[2] = X[2]; - Yerr[0] = Y[0]; - Yerr[1] = Y[1]; - Yerr[2] = Y[2]; - } - } - } - } - } - } - - text_log.PushIndent(); - if ( error_count > 0 ) - { - ON_ERROR("TestSurfaceTree() - tree failed evaluation test."); - text_log.Print("Evaluation test at %d points had %d errors.\n",test_count,error_count); - text_log.PushIndent(); - text_log.Print("surface(%g,%g) = (%g,%g,%g)\n",yerr.x,yerr.y,Y[0].x,Y[0].y,Y[0].z); - text_log.Print("tree(%g,%g) = (%g,%g,%g)\n",xerr.x,xerr.y,X[0].x,X[0].y,X[0].z); - text_log.Print("curve Ds = (%g,%g,%g)\n",Y[1].x,Y[1].y,Y[1].z); - text_log.Print("tree Ds = (%g,%g,%g)\n",X[1].x,X[1].y,X[1].z); - text_log.Print("curve Dt = (%g,%g,%g)\n",Y[2].x,Y[2].y,Y[2].z); - text_log.Print("tree Dt = (%g,%g,%g)\n",X[2].x,X[2].y,X[2].z); - text_log.PopIndent(); - } - else - { - text_log.Print("Evaluation test at %d points was successful.\n",test_count); - } - text_log.PopIndent(); - - return rc; -} - -static -void TestCurveTreeHelper( ON_TextLog& text_log, const ON_Curve* curve, const wchar_t* name ) -{ - TL_NurbsCurve nurbs_curve; - - if ( curve ) - { - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - - curve->GetNurbForm(nurbs_curve); - - text_log.Print(L"Curve class = %S, name = %s\n", - curve->ClassId()->ClassName(), - name - ); - text_log.PushIndent(); - text_log.Print(L"degree = %d, %s, CV count=%d\n", - nurbs_curve.m_order-1, - (nurbs_curve.m_is_rat ? L"rational" : L"non-rational"), - nurbs_curve.m_cv_count - ); - TestCurveTree( text_log, curve ); - text_log.PopIndent(); - } -} - -static -void TestSurfaceTreeHelper( ON_TextLog& text_log, const ON_Surface* surface, const wchar_t* name ) -{ - TL_NurbsSurface nurbs_surface; - - if ( surface ) - { - if ( 0 == name || 0 == *name) - { - name = L"anonymous"; - } - surface->GetNurbForm(nurbs_surface); - - text_log.Print(L"Surface class = %S, name = %s\n", - surface->ClassId()->ClassName(), - name - ); - text_log.PushIndent(); - text_log.Print(L"degree = (%d,%d), %s, CV count= (%d,%d)\n", - nurbs_surface.m_order[0]-1, - nurbs_surface.m_order[1]-1, - (nurbs_surface.m_is_rat ? L"rational" : L"non-rational"), - nurbs_surface.m_cv_count[0], - nurbs_surface.m_cv_count[1] - ); - TestSurfaceTree( text_log, surface ); - text_log.PopIndent(); - } -} - -void TestTree( const ONX_Model& model, ON_TextLog& text_log ) -{ - TEST_HEADER(text_log,"TestClosestPoint"); - int i, k; - - ON_wString name; - const wchar_t* attributes_name; - - // first do curves - if (bDoCurves) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Curve* curve = ON_Curve::Cast(model.m_object_table[i].m_object); - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - TestCurveTreeHelper(text_log,curve,attributes_name); - continue; - } - - - const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( brep ) - { - for ( k = 0; k < brep->m_C3.Count(); k++ ) - { - curve = brep->m_C3[k]; - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_C3[%d]",attributes_name,k); - TestCurveTreeHelper(text_log,curve,name); - } - } - - for ( k = 0; k < brep->m_C2.Count(); k++ ) - { - curve = brep->m_C2[k]; - if ( curve ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_C2[%d]",attributes_name,k); - TestCurveTreeHelper(text_log,curve,name); - } - } - continue; - } - } - } - - // then do surfaces - if ( bDoSurfaces ) - { - for ( i = 0; i < model.m_object_table.Count(); i++ ) - { - const ON_Surface* surface = ON_Surface::Cast(model.m_object_table[i].m_object); - if ( surface ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - TestSurfaceTreeHelper(text_log,surface,attributes_name); - continue; - } - - const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[i].m_object); - if ( brep ) - { - for ( k = 0; k < brep->m_S.Count(); k++ ) - { - surface = brep->m_S[k]; - if ( surface ) - { - attributes_name = model.m_object_table[i].m_attributes.m_name; - if ( !attributes_name ) - attributes_name = L"anonymous"; - name.Format(L"%s - brep.m_S[%d]",attributes_name,k); - - TestSurfaceTreeHelper(text_log,surface,model.m_object_table[i].m_attributes.m_name); - } - } - continue; - } - } - } -} \ No newline at end of file diff --git a/tests/TestZLib.cpp b/tests/TestZLib.cpp deleted file mode 100644 index 2297324b..00000000 --- a/tests/TestZLib.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* $Header: /src4/opennurbs/Tests/TestZLib.cpp 3 2/24/06 9:46p Dalelear $ */ -/* $NoKeywords: $ */ - -#include "Tests.h" -#include -#include - - -static -bool TestZLibCompressionHelper2( - const wchar_t* filename, - __int64 filesize, - ON_TextLog& text_log - ) -{ - ON_Workspace ws; - - if ( 0 == filename ) - return false; - - if ( filesize > 0xFFFFFFF0 ) - { - text_log.Print("Huge file - cannot compress this\n"); - return false; - } - - //////////////////////////////////////////////////////////////// - // - // Allocate inbuffer[] and read filename into inbuffer[] - // - const size_t insz = (size_t)filesize; - void* inbuffer = ws.GetMemory( insz ); - - if ( 0 == inbuffer ) - { - text_log.Print("onmalloc( %u ) returned NULL\n",insz); - return false; - } - - FILE* fp = _wfopen(filename,L"rb"); - if ( !fp ) - { - ON_ERROR("Unable to read file\n"); - text_log.Print(L"ERROR: wfopen(%s,L\"rb\") failed\n",filename); - return false; - } - size_t freadsz = fread(inbuffer,1,insz,fp); - fclose(fp); - fp = 0; - if ( freadsz != insz ) - { - text_log.Print(L"ERROR: fread(inbuffer,1,%u,%s) = %u\n",insz,filename,freadsz); - return false; - } - - //////////////////////////////////////////////////////////////// - // - // Compress inbuffer[] and save compressed informtion in zlibtest.tmp - // - const wchar_t* tempfile = L"C:\\Temp\\zlibtest.tmp"; - - fp = ON::OpenFile(tempfile,L"wb"); - if ( !fp ) - { - ON_ERROR("Unable to write temp file\n"); - text_log.Print(L"ERROR: ON::OpenFile(%s,L\"wb\") failed\n",tempfile); - return false; - } - - bool bWriteOk = false; - { - ON_BinaryFile file( ON::write, fp ); - bWriteOk = file.WriteCompressedBuffer( insz, inbuffer ); - } - fclose(fp); - fp = 0; - if ( !bWriteOk ) - { - text_log.Print(L"ERROR: WriteCompressedBuffer(%u,...) failed\n",insz); - return false; - } - - //////////////////////////////////////////////////////////////// - // - // Read zlibtest.tmp uncompress its contents into outbuffer[] - // - size_t outsz = 0; - void* outbuffer = 0; - - fp = ON::OpenFile(tempfile,L"rb"); - if ( !fp ) - { - ON_ERROR("Unable to read temp file\n"); - text_log.Print(L"ERROR: ON::OpenFile(%s,L\"rb\") failed\n",tempfile); - return false; - } - - int bFailedCRC = true; - bool bReadOk = false; - { - ON_BinaryFile file( ON::read, fp ); - bReadOk = file.ReadCompressedBufferSize( &outsz ); - if (bReadOk && outsz == insz) - { - outbuffer = ws.GetMemory(outsz); - if ( 0 == outbuffer ) - { - text_log.Print("onmalloc( %u ) returned NULL\n",outsz); - fclose(fp); - return false; - } - else - { - bReadOk = file.ReadCompressedBuffer( outsz, outbuffer, &bFailedCRC ); - } - } - } - fclose(fp); - fp = 0; - if ( !bReadOk ) - { - text_log.Print(L"ERROR: ReadCompressedBuffer(%u,...) failed\n",outsz); - return false; - } - - //////////////////////////////////////////////////////////////// - // - // Compare inbuffer[] and outbuffer[] - // - if ( insz != outsz || memcmp(inbuffer,outbuffer,insz) || bFailedCRC ) - { - ON_ERROR("TestZLibCompressionHelper2 compression failure"); - text_log.Print("ERROR: %s compression failure\n"); - return false; - } - - return true; -} - - -static -void TestZLibCompressionHelper1( - const wchar_t* filespec, - ON_TextLog& text_log, - int& file_counter, - int recursion_counter - ) -{ - const int max_file_count = 0x7FFFFFF0; - if ( file_counter > max_file_count ) - return; - - if ( recursion_counter > 32 ) - { - ON_ERROR("TestZLibCompressionHelper1 recursion_counter > 32"); - return; - } - - if ( 0 == recursion_counter && (0 == filespec || 0 == filespec[0]) ) - { - filespec = L"C:\\Documents and Settings\\dalelear\\My Documents"; - } - - bool bRecurse = false; - struct __stat64 fs; - - ON_wString wildcard = filespec; - ON_wString path; - if ( 0 == recursion_counter ) - { - wildcard.TrimRight(L"/\\"); - } - if ( !wildcard.IsEmpty() ) - { - memset(&fs,0,sizeof(fs)); - if ( 0 == _wstat64( wildcard, &fs ) ) - { - if ( 0 != (_S_IFDIR & fs.st_mode) ) - { - bRecurse = true; - path = wildcard; - path += '\\'; - wildcard = path; - wildcard += '*'; - filespec = wildcard; - } - } - } - - struct _wfinddata64_t fi; - memset(&fi,0,sizeof(fi)); - INT_PTR h = _wfindfirst64( filespec, &fi ); - if ( -1 == h ) - { - text_log.Print(L"ERROR: Compression test found nothing in %s\n",filespec); - return; - } - - int rc = 0; - while ( 0 == rc && file_counter < max_file_count ) - { - if ( 0 != fi.name[0] - && (fi.name[0] != '.' || (0 != fi.name[1] && wcscmp(fi.name,L".."))) - ) - { - // fi.name is not empty and is not "." or ".." - ON_wString fullpath = path; - fullpath += fi.name; - memset(&fs,0,sizeof(fs)); - if ( 0 == _wstat64( fullpath, &fs ) ) - { - bool bIsDir = (0 != (_S_IFDIR & fs.st_mode)); - bool bIsFile = (false == bIsDir && (0 != (_S_IFREG & fs.st_mode))); - if ( bIsDir && bRecurse ) - { - // recurse through subdirectory - TestZLibCompressionHelper1(fullpath,text_log,file_counter,recursion_counter+1); - } - else if ( bIsFile && fs.st_size > 0) - { - // use file for a compression test - if ( !TestZLibCompressionHelper2(fullpath,fs.st_size,text_log) ) - { - text_log.Print(L"ERROR: %s compression test failed\n",fullpath); - } - else - { - file_counter++; - if ( 0 == (file_counter % 1000) ) - { - text_log.Print(L"%6d files tested\n",file_counter); - } - } - } - } - } - rc = _wfindnext64( h, &fi ); - } - - _findclose(h); - - return; -} - -void TestZLibCompression( - const wchar_t* filespec, - ON_TextLog& text_log - ) -{ - int file_counter = 0; - TestZLibCompressionHelper1(filespec,text_log,file_counter,0); -} - diff --git a/tests/Tests.cpp b/tests/Tests.cpp deleted file mode 100644 index 179f0771..00000000 --- a/tests/Tests.cpp +++ /dev/null @@ -1,1090 +0,0 @@ -/* $Header: /src4/opennurbs/Tests/Tests.cpp 26 2/24/06 9:46p Dalelear $ */ -/* $NoKeywords: $ */ - -#include "Tests.h" - - -#pragma warning( push ) -#pragma warning( disable : 4073 ) -#pragma init_seg( lib ) -#pragma warning( pop ) - -#define ON_CRASH_TEST_STATICS -#include "../opennurbs_crashtest.h" -#undef ON_CRASH_TEST_STATICS - -static int starthere() -{ - ON::Begin(); - return 0; -} - -// 13 Nov 2007 Dale Lear - added this comment. -// the init_seg pragma and initializing this global -// force ON::Begin() to be called before main(). -// I can't remember why this was important, but I -// think it had to do with purify. -int starthere__starthere = starthere(); - -class TEST_RESULTS -{ -public: - clock_t clock0; - int error_count0; - int warning_count0; - int matherr_count0; - int fperr_count0; - - ON_TextLog* m_text_log; - - int passed_count; - int failed_count; - - bool ok; -}; - - -CTestObject::CTestObject() -{ - m_model_object_index = 0; - memset(&m_uuid,0,sizeof(m_uuid)); - memset(&m_ci,0,sizeof(m_ci)); -} - -CTestObject::~CTestObject() -{ - Destroy(); -} - -void CTestObject::Destroy() -{ - m_model_object_index = 0; - memset(&m_uuid,0,sizeof(m_uuid)); - m_name.Destroy(); - memset(&m_ci,0,sizeof(m_ci)); -} - - -CTestCurve::CTestCurve() -{ - m_curve = 0; - memset(&m_nurbcrv,0,sizeof(m_nurbcrv)); - m_goose_curve = 0; -} - -CTestCurve::~CTestCurve() -{ - Destroy(); -} - -void CTestCurve::Destroy() -{ - if ( m_goose_curve ) - { - delete m_goose_curve; - m_goose_curve = 0; - } - - if ( m_nurbcrv.cv == m_nurbs_curve.m_cv ) - { - m_nurbcrv.cv = 0; - } - if ( m_nurbcrv.knot == m_nurbs_curve.m_knot ) - { - m_nurbcrv.knot = 0; - } - TL_DestroyNurb(&m_nurbcrv); - - m_nurbs_curve.Destroy(); - - m_curve = 0; - - CTestObject::Destroy(); -} - - -const TL_NurbsCurve& CTestCurve::NurbsCurve() -{ - if ( !m_nurbs_curve.m_cv && m_curve ) - { - m_bAdjustNurbsParameter = ( m_curve->GetNurbForm(m_nurbs_curve) > 1 ); - m_nurbcrv.dim = m_nurbs_curve.m_dim; - m_nurbcrv.is_rat = m_nurbs_curve.m_is_rat; - m_nurbcrv.order = m_nurbs_curve.m_order; - m_nurbcrv.cv_count = m_nurbs_curve.m_cv_count; - m_nurbcrv.cv = m_nurbs_curve.m_cv; - m_nurbcrv.knot = m_nurbs_curve.m_knot; - } - return m_nurbs_curve; -} - -const IwBSplineCurve* CTestCurve::GooseCurve() -{ - if ( !m_goose_curve && m_curve ) - { - NurbsCurve(); - if ( m_nurbcrv.cv && m_nurbcrv.knot ) - { - TL_Convert( m_nurbcrv, m_goose_curve ); - } - } - return m_goose_curve; -} - - - -CTestSurface::CTestSurface() -{ - memset(&m_uuid,0,sizeof(m_uuid)); - m_surface = 0; - memset(&m_nurbsrf,0,sizeof(m_nurbsrf)); - m_goose_surface = 0; -} - -CTestSurface::~CTestSurface() -{ - Destroy(); -} - -void CTestSurface::Destroy() -{ - if ( m_goose_surface ) - { - delete m_goose_surface; - m_goose_surface = 0; - } - - if ( m_nurbsrf.cv == m_nurbs_surface.m_cv ) - { - m_nurbsrf.cv = 0; - } - if ( m_nurbsrf.knot[0] == m_nurbs_surface.m_knot[0] ) - { - m_nurbsrf.knot[0] = 0; - } - if ( m_nurbsrf.knot[1] == m_nurbs_surface.m_knot[1] ) - { - m_nurbsrf.knot[1] = 0; - } - TL_DestroyNurbSrf(&m_nurbsrf); - - m_nurbs_surface.Destroy(); - - m_surface = 0; - - CTestObject::Destroy(); -} - -const TL_NurbsSurface& CTestSurface::NurbsSurface() -{ - if ( !m_nurbs_surface.m_cv && m_surface ) - { - m_bAdjustNurbsParameter = ( m_surface->GetNurbForm(m_nurbs_surface) > 1 ); - m_nurbsrf.dim = m_nurbs_surface.m_dim; - m_nurbsrf.is_rat = m_nurbs_surface.m_is_rat; - m_nurbsrf.order[0] = m_nurbs_surface.m_order[0]; - m_nurbsrf.order[1] = m_nurbs_surface.m_order[1]; - m_nurbsrf.cv_count[0] = m_nurbs_surface.m_cv_count[0]; - m_nurbsrf.cv_count[1] = m_nurbs_surface.m_cv_count[1]; - m_nurbsrf.cv = m_nurbs_surface.m_cv; - m_nurbsrf.knot[0] = m_nurbs_surface.m_knot[0]; - m_nurbsrf.knot[1] = m_nurbs_surface.m_knot[1]; - } - return m_nurbs_surface; -} - -const IwBSplineSurface* CTestSurface::GooseSurface() -{ - if ( !m_goose_surface && m_surface ) - { - NurbsSurface(); - if ( m_nurbsrf.cv && m_nurbsrf.knot[0] && m_nurbsrf.knot[1] ) - { - TL_Convert( m_nurbsrf, m_goose_surface ); - } - } - return m_goose_surface; -} - - -CTestBrep::CTestBrep() -{ - m_brep = 0; -} - -CTestBrep::~CTestBrep() -{ - m_brep = 0; -} - -static int sort_model_helper(const ONX_Model_Object* a, const ONX_Model_Object* b ) -{ - // sort by uuid, then object name, then order in the file - int i = ON_UuidCompare(a->m_attributes.m_uuid,b->m_attributes.m_uuid); - if ( 0 == i ) - { - i = a->m_attributes.m_name.Compare( b->m_attributes.m_name ); - if ( 0 == i ) - { - // compare order in the model - i = ((ab) ? 1 : 0)); - } - } - return i; -} - -CTestModel::CTestModel() -{ - m_bPurify = false; -} - -void CTestModel::GetTestObjects( bool bEdgesAreCurves, bool bTrimsAreCurves ) -{ - m_curves.Destroy(); - m_surfaces.Destroy(); - m_breps.Destroy(); - m_curves.Reserve(32); - m_surfaces.Reserve(64); - m_curves.Reserve(64); - - const ON_Curve* curve; - const ON_Surface* surface; - const TL_Brep* brep; - - int i, j; - - // Sorting the model object table keeps - // the report's object order consistent - m_object_table.HeapSort(sort_model_helper); - - - for (i = 0; i < m_object_table.Count(); i++ ) - { - ONX_Model_Object& model_object = m_object_table[i]; - - curve = ON_Curve::Cast(model_object.m_object); - if ( curve ) - { - CTestCurve& C = m_curves.AppendNew(); - - C.m_uuid = model_object.m_attributes.m_uuid; - C.m_name = model_object.m_attributes.m_name; - if (C.m_name.IsEmpty()) - C.m_name = L"anonymous curve"; - C.m_model_object_index = i; - - C.m_curve = curve; - - continue; - } - - surface = ON_Surface::Cast(model_object.m_object); - if ( surface ) - { - CTestSurface& S = m_surfaces.AppendNew(); - - S.m_uuid = model_object.m_attributes.m_uuid; - S.m_name = model_object.m_attributes.m_name; - if (S.m_name.IsEmpty()) - S.m_name = L"anonymous surface"; - S.m_model_object_index = i; - - S.m_surface = surface; - - continue; - } - - brep = TL_Brep::Promote(ON_Brep::Cast(model_object.m_object)); - if ( brep ) - { - CTestBrep& B = m_breps.AppendNew(); - - B.m_uuid = model_object.m_attributes.m_uuid; - B.m_name = model_object.m_attributes.m_name; - if (B.m_name.IsEmpty()) - B.m_name = L"anonymous brep"; - B.m_model_object_index = i; - - B.m_brep = brep; - - if ( bTrimsAreCurves ) - { - for ( j = 0; j < brep->m_C2.Count(); j++ ) - { - curve = brep->m_C2[j]; - if ( !curve ) - continue; - - CTestCurve& C = m_curves.AppendNew(); - - C.m_uuid = model_object.m_attributes.m_uuid; - C.m_name.Format(L"brep[%d]->m_C2[%d] in %s",m_breps.Count()-1,j,B.m_name.Array()); - C.m_model_object_index = i; - C.m_ci.m_type = ON_COMPONENT_INDEX::brep_trim; - C.m_ci.m_index = j; - - C.m_curve = curve; - } - } - - if ( bEdgesAreCurves ) - { - for ( j = 0; j < brep->m_C3.Count(); j++ ) - { - curve = brep->m_C3[j]; - if ( !curve ) - continue; - - CTestCurve& C = m_curves.AppendNew(); - - C.m_uuid = model_object.m_attributes.m_uuid; - C.m_name.Format(L"brep[%d]->m_C3[%d] in %s",m_breps.Count()-1,j,B.m_name.Array()); - C.m_model_object_index = i; - C.m_ci.m_type = ON_COMPONENT_INDEX::brep_edge; - C.m_ci.m_index = j; - - C.m_curve = curve; - } - } - - for ( j = 0; j < brep->m_S.Count(); j++ ) - { - surface = brep->m_S[j]; - if ( !surface ) - continue; - - CTestSurface& S = m_surfaces.AppendNew(); - - S.m_uuid = model_object.m_attributes.m_uuid; - S.m_name.Format(L"brep[%d]->m_S[%d] in %s\n",m_breps.Count()-1,j,B.m_name.Array()); - S.m_model_object_index = i; - S.m_ci.m_index = j; - - S.m_surface = surface; - } - - continue; - } - } -}; - -//static void ON_TEST_BeginTest( struct tagON_TEST_RESULTS& test_results, const char* func_name ); - -//static void ON_TEST_EndTest( struct tagON_TEST_RESULTS& test_results ); - -//static bool ON_TEST_InitFPErrorHandler(void); - -class CTestList -{ -public: - - CTestList() - { - m_bTestTree = true; - m_bTestClsPtCrv = true; - m_bTestClsPtSrf = true; - m_bTestClsPtMesh = true; - m_bTestCCX = true; - m_bTestCSX = true; - m_bTestSSX = true; - m_bTestZLibCompression = false; - m_bAudit = true; - m_bDump = true; - m_bEdgesAreCurves = true; - m_bTrimsAreCurves = true; - m_bPurify = false; - m_bCrashTestDblZeroDiv = false; - m_bCrashTestDblOverflow = false; - m_bCrashTestDblInvalidOp = false; - - m__bClearTests = true; - - m_default_3dm_filename = L"\\src4\\opennurbs\\tests\\input\\MyTest.3dm"; - m_default_log_filename = L"\\src4\\opennurbs\\tests\\results\\MyResults.txt"; - m_3dm_filename = m_default_3dm_filename; - } - - bool ParseCommandLine( int argc, const char* argv[] ); - - bool m_bTestTree; - bool m_bTestClsPtCrv; - bool m_bTestClsPtSrf; - bool m_bTestClsPtMesh; - bool m_bTestCCX; - bool m_bTestCSX; - bool m_bTestSSX; - bool m_bTestZLibCompression; - bool m_bAudit; - bool m_bDump; - bool m_bPurify; - bool m_bCrashTestDblZeroDiv; - bool m_bCrashTestDblOverflow; - bool m_bCrashTestDblInvalidOp; - - bool m_bEdgesAreCurves; - bool m_bTrimsAreCurves; - - ON_wString m_3dm_filename; - ON_wString m_log_filename; - ON_wString m_zlib_filespec; - -private: - ON_String m_default_3dm_filename; - ON_String m_default_log_filename; - bool m__bClearTests; - bool GetOption( const char* arg, - const char* opt, - ON_wString& value ); - void Clear(); -}; - -void CTestList::Clear() -{ - if ( m__bClearTests ) - { - // do not clear m_bEdgesAreCurves or m_bTrimsAreCurves - m_bTestTree = false; - m_bTestClsPtCrv = false; - m_bTestClsPtSrf = false; - m_bTestClsPtMesh = false; - m_bTestCCX = false; - m_bTestCSX = false; - m_bTestSSX = false; - m_bTestZLibCompression = false; - m_bAudit = false; - m_bDump = false; - m_bCrashTestDblZeroDiv = false; - m_bCrashTestDblOverflow = false; - m_bCrashTestDblInvalidOp = false; - - m__bClearTests = false; - } -} - -bool CTestList::GetOption( const char* arg, - const char* opt, - ON_wString& value ) -{ - int i; - bool rc = false; - - value.Destroy(); - - if ( arg - && ('-' == arg[0] || '/' == arg[0]) - && arg[1] - && opt - && opt[0] - && '-' != opt[0] - && '/' != opt[0] - && ':' != opt[0] - ) - { - arg++; - for ( i = 0; arg[i]; i++ ) - { - if ( ':' == arg[i] ) - break; - } - - if ( strlen(opt) == i && 0 == _strnicmp(arg,opt,i) ) - { - rc = true; - if ( ':' == arg[i] ) - { - value = &arg[i+1]; - } - } - } - - return rc; -} - -bool CTestList::ParseCommandLine( int argc, const char* argv[] ) -{ - int argi; - for ( argi = 1; argi < argc; argi++ ) - { - ON_wString value; - - if ( GetOption(argv[argi],"log",value) ) - { - if ( value.IsEmpty() ) - { - m_log_filename = m_default_log_filename; - } - else - { - m_log_filename = value; - } - continue; - } - - if ( GetOption(argv[argi],"3dm",value) ) - { - if ( value.IsEmpty() ) - { - m_3dm_filename = m_default_3dm_filename; - } - else - { - m_3dm_filename = value; - } - continue; - } - - if ( GetOption(argv[argi],"audit",value) ) - { - Clear(); - m_bAudit = true; - continue; - } - - if ( GetOption(argv[argi],"dump",value) ) - { - Clear(); - m_bDump = true; - continue; - } - - if ( GetOption(argv[argi],"tree",value) ) - { - Clear(); - m_bTestTree = true; - continue; - } - - if ( GetOption(argv[argi],"crashtestzerodiv",value) ) - { - Clear(); - m_bCrashTestDblZeroDiv = true; - continue; - } - - if ( GetOption(argv[argi],"crashtestoverflow",value) ) - { - Clear(); - m_bCrashTestDblOverflow = true; - continue; - } - - if ( GetOption(argv[argi],"crashtestinvalidop",value) ) - { - Clear(); - m_bCrashTestDblInvalidOp = true; - continue; - } - - if ( GetOption(argv[argi],"purify",value) ) - { - Clear(); - m_bPurify = true; - continue; - } - - if ( GetOption(argv[argi],"clspt",value) ) - { - Clear(); - m_bTestClsPtCrv = true; - m_bTestClsPtSrf = true; - m_bTestClsPtMesh = true; - continue; - } - - if ( GetOption(argv[argi],"clsptcrv",value) ) - { - Clear(); - m_bTestClsPtCrv = true; - continue; - } - - if ( GetOption(argv[argi],"clsptsrf",value) ) - { - Clear(); - m_bTestClsPtSrf = true; - continue; - } - - if ( GetOption(argv[argi],"clsptmesh",value) ) - { - Clear(); - m_bTestClsPtMesh = true; - continue; - } - - if ( GetOption(argv[argi],"ccx",value) ) - { - Clear(); - m_bTestCCX = true; - continue; - } - - - if ( GetOption(argv[argi],"csx",value) ) - { - Clear(); - m_bTestCSX = true; - continue; - } - - if ( GetOption(argv[argi],"ssx",value) ) - { - Clear(); - m_bTestSSX = true; - continue; - } - - if ( GetOption(argv[argi],"zlib",value) ) - { - Clear(); - m_bTestZLibCompression = true; - m_zlib_filespec = value; - continue; - } - - if ( GetOption(argv[argi],"notrims",value) ) - { - m_bTrimsAreCurves = false; - continue; - } - - if ( GetOption(argv[argi],"noedges",value) ) - { - m_bEdgesAreCurves = false; - continue; - } - - { - printf("%s command line options\n",argv[0]); - printf(" -? print this message\n"); - printf(" -help print this message\n"); - printf(" -3dm:filename.3dm input 3dm model to test\n"); - printf(" -log:filename.txt output text file for results\n"); - printf(" -purify limited tests for dog slow purify\n"); - printf(" -audit audit 3dm model\n"); - printf(" -dump: dump 3dm model\n"); - printf(" -notrims do not include brep trims with curves\n"); - printf(" -noedge do not include brep edges with curves\n"); - printf(" -tree test trees\n"); - printf(" -clspt test closest point to anything\n"); - printf(" -clsptcrv test closest point to curve\n"); - printf(" -clsptsrf test closest point to surface\n"); - printf(" -clsptmesh test closest point to mesh\n"); - printf(" -ccx test curve-curve intersection\n"); - printf(" -csx test curve and edge-surface intersection\n"); - printf(" -ssx test surface-surface intersection\n"); - printf(" -crashtestzerodiv test 1.0/0.0 exception handling\n"); - printf(" -crashtestoverflow test 1.0e200*2.0e222 exception handling\n"); - printf(" -crashtestinvalidop test log(negative number) exception handling\n"); - printf("\n"); - printf(" If no 3dm filename is specified, then\n"); - printf(" %s is used.\n",m_default_3dm_filename.Array()); - printf(" If no filename is specified with the -log option, then\n"); - printf(" %s is used.\n",m_default_log_filename.Array()); - printf(" If no options are specified, then all tests are performed.\n"); - - return false; - } - } - - return true; -} - -class CAlphaOmega -{ -public: - CAlphaOmega(); - ~CAlphaOmega(); -}; - -CAlphaOmega::CAlphaOmega() -{ - TL_Begin(); - - // Break when error occurs - ON_EnableDebugBreak(true); - - ON_FPU_Init(); - - // Mask minor exceptions (underflow, partial loss of precision, denormal ) - // but crash on the bad exceptions (zero divide, overflow, invalid op) - ON__UINT32 bad_ex = ON_FPU_EX_ZERODIVIDE - | ON_FPU_EX_OVERFLOW - | ON_FPU_EX_INVALID; - ON_FPU_UnmaskExceptions(bad_ex); -} - -CAlphaOmega::~CAlphaOmega() -{ - TL_End(); - - // The ON::End() call cleans up runtime class - // informtion so that Purify doesn't complain about leaks. - // OpenNURBS is completely useless after this call. - ON::End(); -} - - - - -class CCheckForErrors -{ -public: - CCheckForErrors(ON_TextLog& text_log,const wchar_t* testname) - : m_text_log(text_log), - m_test_name(testname) - { - m_error_count1 = m_error_count0 = ON_GetErrorCount(); - m_warning_count1 = m_warning_count0 = ON_GetWarningCount(); - } - - ~CCheckForErrors() - { - m_error_count1 = ON_GetErrorCount()-m_error_count0; - m_warning_count1 = ON_GetWarningCount()-m_warning_count0; - - if ( m_error_count1 > 0 || m_warning_count1 > 0 ) - { - m_text_log.Print("\n"); - m_text_log.Print( L"ERRORS in %s tests: %d openurbs error(s) and %d opennurbs warning(s).\n", - m_test_name.Array(), - m_error_count1, - m_warning_count1); - } - } - - ON_TextLog& m_text_log; - ON_wString m_test_name; - int m_error_count0; - int m_error_count1; - int m_warning_count0; - int m_warning_count1; - -private: - CCheckForErrors(); -}; - - -int main( int argc, const char* argv[]) -{ - // The alpha-omega constructor/destructor handles TL and ON - // library initialization and cleanup. - CAlphaOmega alphaomega; - - // test_list controls what tests are performed. - CTestList test_list; - - // If no 3dm file is specified, you get to use whatever you have in - // your MyTest.3dm file. Do NOT check a MyTest.3dm into SourceSafe - // or you mess up everybody else. If the command line has a - // -3dm:filename option, then m_3dm_filename will be set to the - // filename specified on the command line. - - if ( !test_list.ParseCommandLine(argc,argv) ) - { - return -1; - } - - ///////////////////////////////////////////////////////////////// - // - // Set up text_log - // - FILE* log_fp = 0; // = fopen("C:\\TestResults.txt","w"); - if ( 0 == log_fp ) - { - const wchar_t* log_filename = test_list.m_log_filename; - if ( log_filename && log_filename[0] ) - { - log_fp = _wfopen(log_filename,L"w"); - if ( !log_fp ) - { - printf("Unable to open log file \"%S\".\n",log_filename); - return -1; - } - else - { - printf("Beginning tests.\n Results will be in \"%S\".\n",log_filename); - } - } - } - - ON_TextLog text_log(log_fp); - text_log.SetIndentSize(2); - - TEST_RESULTS test_results; - memset(&test_results,0,sizeof(test_results)); - int repair_count = 0; - - - if ( test_list.m_bCrashTestDblZeroDiv ) - { - CrashTestHelper(6,text_log); - } - if ( test_list.m_bCrashTestDblInvalidOp ) - { - CrashTestHelper(9,text_log); - } - if ( test_list.m_bCrashTestDblOverflow ) - { - CrashTestHelper(10,text_log); - } - - - ///////////////////////////////////////////////////////////////// - // - // zlib test's dont use a 3dm model - // - if ( test_list.m_bTestZLibCompression - //&& !test_list.m_zlib_filespec.IsEmpty() - ) - { - TestZLibCompression( test_list.m_zlib_filespec, text_log ); - } - else if ( !test_list.m_3dm_filename.IsEmpty() ) - { - //ON_TEST_InitFPErrorHandler(); - - test_results.m_text_log = &text_log; - - TestPrintHeader(text_log,argc,argv); - - CTestModel model; - model.m_bPurify = test_list.m_bPurify; - { - CCheckForErrors check_for_errors(text_log,L"read 3dm file"); - if ( !model.Read(test_list.m_3dm_filename,&text_log) ) - { - if ( log_fp ) - printf("Unable to read 3dm file \"%S\".\n",test_list.m_3dm_filename.Array()); - } - - // Sort model object table by uuid and then fill in the - // CTestModel m_curves[], m_surfaces[], and m_breps[] arrays - model.GetTestObjects( test_list.m_bEdgesAreCurves, test_list.m_bTrimsAreCurves ); - } - - if ( test_list.m_bDump ) - { - CCheckForErrors check_for_errors(text_log,L"dump 3dm file"); - model.Dump(text_log); - } - else - { - text_log.Print(L"3dm file: %s (%d objects)\n",test_list.m_3dm_filename.Array(),model.m_object_table.Count()); - } - - if ( test_list.m_bAudit ) - { - CCheckForErrors check_for_errors(text_log,L"audit 3dm file"); - model.Audit(true,&repair_count,&text_log, NULL); - } - - // Sorting the model object table keeps - // the report's object order consistent - model.m_object_table.HeapSort(sort_model_helper); - - if ( test_list.m_bTestTree ) - { - if ( log_fp ) - printf("Testing curve and surface trees.\n"); - CCheckForErrors check_for_errors(text_log,L"curve and surface Tree"); - TestTree(model,text_log); - } - - if ( test_list.m_bTestClsPtCrv ) - { - if ( log_fp ) - printf("Testing closest point to curve.\n"); - CCheckForErrors check_for_errors(text_log,L"closest point to curve"); - TestClosestPoint(model,text_log, true, false, false ); - } - - if ( test_list.m_bTestClsPtSrf ) - { - if ( log_fp ) - printf("Testing closest point to surface.\n"); - CCheckForErrors check_for_errors(text_log,L"closest point to surface"); - TestClosestPoint(model,text_log, false, true, false ); - } - - if ( test_list.m_bTestClsPtMesh ) - { - if ( log_fp ) - printf("Testing closest point to mesh.\n"); - CCheckForErrors check_for_errors(text_log,L"closest point to mesh"); - TestClosestPoint(model,text_log, false, false, true ); - } - - if ( test_list.m_bTestCCX ) - { - if ( log_fp ) - printf("Testing curve-curve intersection.\n"); - CCheckForErrors check_for_errors(text_log,L"curve-curve intersection"); - TestCurveCurveIntersection(model, text_log); - } - - if ( test_list.m_bTestCSX ) - { - if ( log_fp ) - printf("Testing curve-surface intersection.\n"); - CCheckForErrors check_for_errors(text_log,L"curve-surface intersection"); - TestCurveSurfaceIntersection(model,text_log); - } - - if ( test_list.m_bTestSSX ) - { - if ( log_fp ) - printf("Testing surface-surface intersection.\n"); - CCheckForErrors check_for_errors(text_log,L"surface-surface intersection"); - // TestSurfaceSurfaceIntersection(text_log); - text_log.Print("Surface-surface intersection tests not ready.\n"); - } - } - - if (log_fp) - { - printf("Finished tests. Results are in \"%S\".\n",test_list.m_log_filename.Array()); - fclose(log_fp); - log_fp = 0; - } - -#if (_DEBUG) - { - // This getchar() is here so the results window doesnt' vanish - // when the debugger is being used. - printf("\nPress ENTER to finish.\n"); - getchar(); - } -#endif - - return test_results.failed_count+starthere__starthere; -} - -void TestPrintHeader( ON_TextLog& text_log, int argc, const char* argv[] ) -{ - int year = 0; - int month = 1; - int date = 0; - int hour = 0; - int minute = 0; - int second = 0; - TLI_CurrentTime( &year, &month, &date, &hour, &minute, &second ); - if ( year < 1900 ) - { - year += 1900; - if ( year < 1970 ) - year += 1970; - } - char* month_name[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; - text_log.Print("Test: %s\n",argv[0]); - text_log.PushIndent(); - for ( int argi = 1; argi < argc; argi++ ) - { - text_log.Print("%s\n",argv[argi]); - } - text_log.PopIndent(); - text_log.Print("Test date: %s %2d %d %2d:%02d:%02d UCT\n",month_name[month-1],date,year,hour,minute,second); - const char* compile_time = __DATE__ " " __TIME__; - text_log.Print("Compile date: %s local time\n",compile_time); - text_log.Print("OpenNURBS version: %d\n",ON::Version()); -#if defined(_DEBUG) - text_log.Print("Build settings: Debug\n"); -#else - text_log.Print("Build settings: Release\n"); -#endif - - text_log.Print("\n"); -} - - -void TestPrintFunctionHeader( ON_TextLog& text_log, const char* function_name, const char* file_name, const char* compile_time ) -{ - int year = 0; - int month = 1; - int date = 0; - int hour = 0; - int minute = 0; - int second = 0; - TLI_CurrentTime( &year, &month, &date, &hour, &minute, &second ); - if ( year < 1900 ) - { - year += 1900; - if ( year < 1970 ) - year += 1970; - } - char* month_name[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; - text_log.Print("Test function: %s in %s\n",function_name,file_name); - text_log.Print("Test date: %s %2d %d %2d:%02d:%02d UCT\n",month_name[month-1],date,year,hour,minute,second); - text_log.Print("Compile date: %s local time\n",compile_time); - - text_log.Print("\n"); -} - -double TEST_ElapsedTime() -{ - static clock_t time0=0; - double elapsed_time; - clock_t time; - time = clock(); - elapsed_time = ((double)(time - time0))/((double)CLOCKS_PER_SEC); - time0 = time; - return elapsed_time; -} - - -/**************************************************************************** - ** - ** _matherr() ( replaces standard math libraries matherr() ) - ** Calls ON_TEST_MathError() whenever a math error occurs. - ** - ****************************************************************************/ - -int _matherr( struct _exception *ExceptStruct ) -{ - /* NOTE: This function ALWAYS returns a "1" so that the - * system's math library will not attempt to print - * some message on stderr/stdout. - */ - switch(ExceptStruct->type) /* <- Good location for a debugger breakpoint */ - { - case _DOMAIN: /* domain error */ - /* CRITICAL MATH ERROR - FIX THIS BUG */ - errno = EDOM; - ON_MathError("rhino.exe","_matherr DOMAIN exception",ExceptStruct->name); - break; - - case _SING: /* function singularity */ - /* CRITICAL MATH ERROR - FIX THIS BUG */ - errno = EDOM; - ON_MathError("rhino.exe","_matherr SING exception",ExceptStruct->name); - break; - - case _OVERFLOW: - /* CRITICAL MATH ERROR - FIX THIS BUG */ - errno = ERANGE; - ON_MathError("rhino.exe","_matherr OVERFLOW exception",ExceptStruct->name); - break; - - case _UNDERFLOW: - /* ignore underflow errors - they frequently happen */ - errno = ERANGE; - break; - - case _TLOSS: /* total loss of significance (like sin(1.0e300)) */ - errno = ERANGE; - ON_MathError("rhino.exe","_matherr TLOSS exception",ExceptStruct->name); - break; - - case _PLOSS: /* partial loss of significance */ - /* do not modify ExceptStruct->retval and hope for the best */ - errno = ERANGE; - ON_MathError("rhino.exe","_matherr PLOSS exception",ExceptStruct->name); - break; - - default: /* undocumented error */ - errno = EDOM; - ON_MathError("rhino.exe","_matherr UNDOCUMENTED ERROR",ExceptStruct->name); - break; - } - return 1; /* suppress operating system's error handling */ -} diff --git a/tests/Tests.h b/tests/Tests.h deleted file mode 100644 index 3a1b8c58..00000000 --- a/tests/Tests.h +++ /dev/null @@ -1,257 +0,0 @@ -#pragma once -#if !defined(OPENNURBS_TESTS_INC_) - -#if !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE -// Visual Studio 2005 issues a C4996 warning for lots of -// standard C runtime functions that take string pointers. -// The _CRT_SECURE_NO_DEPRECATE suppresses these warnings. -#endif - -#pragma warning( push ) -#include "../opennurbs.h" -#pragma warning( pop ) - -#pragma warning( push ) -//#include -//#include -#pragma warning( pop ) - -#pragma warning( push ) -#include "../../tl/tl.h" -#include "../../tl/tl_array.h" -#include "../../tl/tl_gslib.h" -#include "../../tl/tl_init.h" -#include "../../tl/tl_brep.h" -#include "../../tl/tl_nurbscurve.h" -#include "../../tl/tl_nurbssurface.h" -#include "../../tl/tl_tree.h" -#include "../../tl/tl_optimize.h" - -#pragma warning( pop ) - - -#define TL_GSLIB_INTERFACE_CODE -#pragma warning( push ) -#pragma warning( disable : 4267 ) -#pragma warning( disable : 4313 ) -#include "../../tl/tl_gslib_inc.h" -#pragma warning( pop ) -#undef TL_GSLIB_INTERFACE_CODE - - -#if defined(_DEBUG) - -#pragma comment(lib, "../../tl/DebugStaticLib/tl_staticlibd.lib") -#pragma comment(lib, "../../gslib/DebugStaticLib/gslib_staticlibd.lib") -#pragma comment(lib, "../DebugStaticLib/opennurbs_staticd.lib") -#pragma comment(lib, "../zlib/Debug/zlib_d.lib") -#pragma comment(lib, "msvcrtd.lib") - -#pragma comment(linker, "/disallowlib:msvcrt.lib") - -#else - -#pragma comment(lib, "../../tl/ReleaseStaticLib/tl_staticlib.lib") -#pragma comment(lib, "../../gslib/ReleaseStaticLib/gslib_staticlib.lib") -#pragma comment(lib, "../ReleaseStaticLib/opennurbs_static.lib") -#pragma comment(lib, "../zlib/Release/zlib.lib") -#pragma comment(lib, "msvcrt.lib") - -#pragma comment(linker, "/disallowlib:msvcrtd.lib") - -#endif - -#pragma comment(linker, "/disallowlib:libcd.lib") -#pragma comment(linker, "/disallowlib:libcmtd.lib") -#pragma comment(linker, "/disallowlib:libc.lib") -#pragma comment(linker, "/disallowlib:libcmt.lib") - -#pragma comment(linker, "/disallowlib:mfco42ud.lib") -#pragma comment(linker, "/disallowlib:mfcd42ud.lib") -#pragma comment(linker, "/disallowlib:mfcn42ud.lib") -#pragma comment(linker, "/disallowlib:mfc42.lib") -#pragma comment(linker, "/disallowlib:mfcs42.lib") -#pragma comment(linker, "/disallowlib:mfc42ud.lib") -#pragma comment(linker, "/disallowlib:mfcs42ud.lib") -#pragma comment(linker, "/disallowlib:mfc42u.lib") -#pragma comment(linker, "/disallowlib:mfcs42u.lib") -#pragma comment(linker, "/disallowlib:mfco42d.lib") -#pragma comment(linker, "/disallowlib:mfcd42d.lib") -#pragma comment(linker, "/disallowlib:mfcn42d.lib") -#pragma comment(linker, "/disallowlib:mfc42d.lib") -#pragma comment(linker, "/disallowlib:mfcs42d.lib") -#pragma comment(linker, "/disallowlib:mfc42ud.lib") -#pragma comment(linker, "/disallowlib:mfcs42ud.lib") -#pragma comment(linker, "/disallowlib:mfc42u.lib") -#pragma comment(linker, "/disallowlib:mfcs42u.lib") -#pragma comment(linker, "/disallowlib:mfco42d.lib") -#pragma comment(linker, "/disallowlib:mfcd42d.lib") -#pragma comment(linker, "/disallowlib:mfcn42d.lib") -#pragma comment(linker, "/disallowlib:mfc42d.lib") -#pragma comment(linker, "/disallowlib:mfcs42d.lib") -#pragma comment(linker, "/disallowlib:mfc42.lib") -#pragma comment(linker, "/disallowlib:mfcs42.lib") -#pragma comment(linker, "/disallowlib:mfc42u.lib") -#pragma comment(linker, "/disallowlib:mfcs42u.lib") -#pragma comment(linker, "/disallowlib:mfco42ud.lib") -#pragma comment(linker, "/disallowlib:mfcd42ud.lib") -#pragma comment(linker, "/disallowlib:mfcn42ud.lib") -#pragma comment(linker, "/disallowlib:mfc42d.lib") -#pragma comment(linker, "/disallowlib:mfcs42d.lib") -#pragma comment(linker, "/disallowlib:mfc42.lib") -#pragma comment(linker, "/disallowlib:mfcs42.lib") -#pragma comment(linker, "/disallowlib:mfc42ud.lib") -#pragma comment(linker, "/disallowlib:mfcs42ud.lib") - -#pragma comment(linker, "/disallowlib:nafxcwd.lib") -#pragma comment(linker, "/disallowlib:nafxcw.lib") -#pragma comment(linker, "/disallowlib:uafxcwd.lib") -#pragma comment(linker, "/disallowlib:uafxcw.lib") - -// Prohibit any future inclusion of CRTDBG.H by defining _INC_CRTDBG. -#if defined(_INC_CRTDBG) -#error Never include CRTDBG.H in these tests. It breaks purify. -#endif -#define _INC_CRTDBG - - -class CTestObject -{ -public: - CTestObject(); - ~CTestObject(); - - void Destroy(); - - int m_model_object_index; // ONX_Model m_object_table[] index - ON_UUID m_uuid; // 3dm parent object uuid - ON_wString m_name; // 3dm parent object name - ON_COMPONENT_INDEX m_ci; // index of object in parent -}; - -class CTestCurve : public CTestObject -{ -public: - CTestCurve(); - ~CTestCurve(); - - void Destroy(); - - const ON_Curve* m_curve; - - // True if curve and NURBS parameterizations differ - bool m_bAdjustNurbsParameter; - - const TL_NurbsCurve& NurbsCurve(); - - const class IwBSplineCurve* GooseCurve(); - - - TL_NurbsCurve m_nurbs_curve; - TL_NURB m_nurbcrv; - - class IwBSplineCurve* m_goose_curve; -}; - -class CTestSurface : public CTestObject -{ -public: - CTestSurface(); - ~CTestSurface(); - - void Destroy(); - - const ON_Surface* m_surface; - - // True if surface and NURBS parameterizations differ - bool m_bAdjustNurbsParameter; - - const TL_NurbsSurface& NurbsSurface(); - - const class IwBSplineSurface* GooseSurface(); - - - // call NurbsSurface() to get this surface - TL_NurbsSurface m_nurbs_surface; - TL_NURBSRF m_nurbsrf; - - // call GooseSurface() to get this surface - class IwBSplineSurface* m_goose_surface; -}; - -class CTestBrep : public CTestObject -{ -public: - CTestBrep(); - ~CTestBrep(); - - const TL_Brep* m_brep; -}; - -class CTestModel : public ONX_Model -{ -public: - CTestModel(); - - // Digs through the model and harvests curves, surfaces, - // and breps for testing and puts them in the m_curves[], - // m_surfaces[], m_breps[] arrays. - void GetTestObjects( bool bEdgesAreCurve, bool bTrimsAreCurves ); - - ON_ClassArray m_curves; - ON_ClassArray m_surfaces; - ON_ClassArray m_breps; - - bool m_bPurify; // true if tests should be limited because purify is running. -}; - - -double TEST_ElapsedTime(); -//#define ON_TEST_DECL(func) ON_TEST_BeginTest(test_results,#func); test_results->ok = func(*test_results->m_text_log); ON_TEST_EndTest(test_results); - -#define TEST_HEADER(text_log,function_name) TestPrintFunctionHeader( text_log, function_name, __FILE__, __DATE__ " " __TIME__ ); - -void TestPrintHeader( - ON_TextLog& text_log, - int argc, - const char* argv[] - ); - -void TestPrintFunctionHeader( - ON_TextLog& text_log, - const char* function_name, - const char* file_name, - const char* compile_time - ); - -void TestTree( const ONX_Model& model, ON_TextLog& text_log ); -void TestClosestPoint( const ONX_Model& model, - ON_TextLog& text_log, - bool bDoCurves, - bool bDoSurfaces, - bool bDoMeshes ); -void TestCurveCurveIntersection(const ONX_Model& model, ON_TextLog& text_log ); -void TestCurveSurfaceIntersection( CTestModel& model, ON_TextLog& text_log ); -void TestZLibCompression( - const wchar_t* filespec, - ON_TextLog& text_log - ); - - -// quick-n-dirty ccx for testing curve tree -void DaleCCX( const ON_Curve& curveA, - const ON_Curve& curveB, - double tol3d, - ON_SimpleArray& ccx - ); - - -// new FAST! ccx -void GregCCX( const ON_Curve& curveA, - const ON_Curve& curveB, - double tol3d, - ON_SimpleArray& ccx - ); - -#endif diff --git a/tests/Tests.vcproj b/tests/Tests.vcproj deleted file mode 100644 index 72d32584..00000000 --- a/tests/Tests.vcproj +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/fileio/CMakeLists.txt b/tests/fileio/CMakeLists.txt deleted file mode 100644 index 29a604e0..00000000 --- a/tests/fileio/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 3.16) -project(ON_Test) - -# GoogleTest requires at least C++14 -set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -include(FetchContent) -FetchContent_Declare( - googletest - URL https://github.com/google/googletest/archive/b10fad38c4026a29ea6561ab15fc4818170d1c10.zip -) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(googletest) - -enable_testing() - -add_subdirectory(../../../opennurbs build_opennurbs) - -add_executable( - test_ON_FileIO - test_ON_FileIO.cpp -) - -target_link_libraries( - test_ON_FileIO - GTest::gtest_main - OpenNURBS -) - -include(GoogleTest) -gtest_discover_tests(test_ON_FileIO) \ No newline at end of file diff --git a/tests/fileio/README.md b/tests/fileio/README.md deleted file mode 100644 index 364b8848..00000000 --- a/tests/fileio/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# OpenNURBS FileIO - -This is a project to test OpenNURBS FileIO. It uses GoogleTest Value Parameterized tests: http://google.github.io/googletest/advanced.html#value-parameterized-tests and is based on some of the code from example_test. - -## Associated files - -- rhino/src4/opennurbs/tests/fileio/CMakeLists.txt -- rhino/src4/opennurbs/tests/fileio/test_ON_FileIO.cpp - -## building & running - -From the example_test directory: - -- `cmake -S . -B build` -- `cmake --build build` -- `cd build && ./test_ON_FileIO` (macos) - -## TODO - -- Complete GetGileList() method to iterate over a root and return an array of all of the files to test. \ No newline at end of file diff --git a/tests/fileio/test_ON_FileIO.cpp b/tests/fileio/test_ON_FileIO.cpp deleted file mode 100644 index bd08fdf8..00000000 --- a/tests/fileio/test_ON_FileIO.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include -#include - -#include "../opennurbs_public_examples.h" - -namespace -{ - - /* - // basic list of files to start testing - std::vector GetFileList() - { - std::vector files; - //TODO - return { - new ON_String("../../../example_files/V8/v8_caps_and_joins.3dm"), - new ON_String("../../../example_files/V8/v8_section_hatch.3dm"), - new ON_String("../../../example_files/V8/v8_selective_clipping.3dm"), - - }; - } - */ - - /* - - // method to take a base folder and eventually return all of the file paths - std::vector GetFileList(const ON_String fullpath) - { - //TODO - return {}; - } - */ - - class ON_FileIO_ParameterizedTest : public testing::TestWithParam - { - protected: - // start up ON once - static void SetUpTestSuite() - { - // std::cout << "Starting OpenNURBS \n"; - ON::Begin(); - } - - // close ON once - static void TearDownTestSuite() - { - // std::cout << "Closing OpenNURBS \n"; - ON::End(); - } - }; - - // the actual test code. Open the input - TEST_P(ON_FileIO_ParameterizedTest, ReadWrite) - { - // TODO // - // GetParam() gets the ON_String file path - // std::cout << GetParam(); - bool res = false; - ON_String full_path(GetParam()); - - if (ON_FileSystem::IsFile(full_path)) - { - if (ON_FileStream::Is3dmFile(full_path, false)) - { - - FILE* fp = nullptr; - fp = ON_FileStream::Open3dmToRead(full_path); - - ON_BinaryFile source_archive(ON::archive_mode::read3dm, fp); - const ON_wString wide_full_path(full_path); - source_archive.SetArchiveFullPath(static_cast(wide_full_path)); - - ONX_ModelTest::Type test_type = ONX_ModelTest::Type::ReadWriteReadCompare; - ONX_ModelTest test; - - const ON_String text_log_3dm_file_name = ""; - ON_TextLog text_log; - const ON_wString wide_text_log_3dm_file_name(text_log_3dm_file_name); - res = test.ReadTest(source_archive, test_type, true, wide_text_log_3dm_file_name, &text_log); - - // TODO: more from example_test - - } - } - - EXPECT_TRUE(res); - } - - // TODO: Replace this with a GetFileList() method that returns an array of files to test - INSTANTIATE_TEST_SUITE_P(List, ON_FileIO_ParameterizedTest, testing::Values("../../../example_files/V8/v8_caps_and_joins.3dm", "../../../example_files/V8/v8_section_hatch.3dm", "../../../example_files/V8/v8_selective_clipping.3dm"), - [](const testing::TestParamInfo& info) { - // Can use info.param here to generate the test suffix - std::string data = static_cast(info.param); - std::string base_filename = data.substr(data.find_last_of("/\\") + 1); - std::string::size_type const p(base_filename.find_last_of('.')); - std::string name = base_filename.substr(0, p); - return name; - } - ); - - // Container of parameters - // INSTANTIATE_TEST_SUITE_P(Container, ON_FileIO_ParameterizedTest, testing::ValuesIn(GetFileList())); - -} // namespace \ No newline at end of file diff --git a/tests/test_ClassSize.cpp b/tests/test_ClassSize.cpp deleted file mode 100644 index f892ea88..00000000 --- a/tests/test_ClassSize.cpp +++ /dev/null @@ -1,2631 +0,0 @@ -#include -#include "../opennurbs_public.h" - -TEST(ONTest, ONTestClassSizeON_3dmObjectAttributes) { - - size_t sz = sizeof(ON_3dmObjectAttributes); //368 - - EXPECT_EQ(sz, 368); - -} - -TEST(ONTest, ONTestClassSizeON_3dmRevisionHistory) { - - size_t sz = sizeof(ON_3dmRevisionHistory); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_3dmNotes) { - - size_t sz = sizeof(ON_3dmNotes); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_3dmApplication) { - - size_t sz = sizeof(ON_3dmApplication); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3dmProperties) { - - size_t sz = sizeof(ON_3dmProperties); //512 - - EXPECT_EQ(sz, 512); - -} - -TEST(ONTest, ONTestClassSizeON_3dmUnitsAndTolerances) { - - size_t sz = sizeof(ON_3dmUnitsAndTolerances); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_3dmAnnotationSettings) { - - size_t sz = sizeof(ON_3dmAnnotationSettings); //104 - - EXPECT_EQ(sz, 104); - -} - -TEST(ONTest, ONTestClassSizeON_3dmConstructionPlaneGridDefaults) { - - size_t sz = sizeof(ON_3dmConstructionPlaneGridDefaults); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_3dmConstructionPlane) { - - size_t sz = sizeof(ON_3dmConstructionPlane); //168 - - EXPECT_EQ(sz, 168); - -} - -TEST(ONTest, ONTestClassSizeON_3dmViewPosition) { - - size_t sz = sizeof(ON_3dmViewPosition); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_3dmViewTraceImage) { - - size_t sz = sizeof(ON_3dmViewTraceImage); //336 - - EXPECT_EQ(sz, 336); - -} - -TEST(ONTest, ONTestClassSizeON_3dmWallpaperImage) { - - size_t sz = sizeof(ON_3dmWallpaperImage); //192 - - EXPECT_EQ(sz, 192); - -} - -TEST(ONTest, ONTestClassSizeON_3dmPageSettings) { - - size_t sz = sizeof(ON_3dmPageSettings); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_StandardDisplayModeId) { - - size_t sz = sizeof(ON_StandardDisplayModeId); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_3dmView) { - - size_t sz = sizeof(ON_3dmView); //1520 - - EXPECT_EQ(sz, 1520); - -} - -TEST(ONTest, ONTestClassSizeON_3dmRenderSettings) { - - size_t sz = sizeof(ON_3dmRenderSettings); //184 - - EXPECT_EQ(sz, 184); - -} - -TEST(ONTest, ONTestClassSizeON_EarthAnchorPoint) { - - size_t sz = sizeof(ON_EarthAnchorPoint); //152 - - EXPECT_EQ(sz, 152); - -} - -TEST(ONTest, ONTestClassSizeON_3dmIOSettings) { - - size_t sz = sizeof(ON_3dmIOSettings); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_3dmSettings) { - - size_t sz = sizeof(ON_3dmSettings); //1560 - - EXPECT_EQ(sz, 1560); - -} - -TEST(ONTest, ONTestClassSizeON_3dmAnimationProperties) { - - size_t sz = sizeof(ON_3dmAnimationProperties); //304 - - EXPECT_EQ(sz, 304); - -} - -TEST(ONTest, ONTestClassSizeON_Annotation) { - - size_t sz = sizeof(ON_Annotation); //792 - - EXPECT_EQ(sz, 792); - -} - -TEST(ONTest, ONTestClassSizeON_TextDot) { - - size_t sz = sizeof(ON_TextDot); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_Arc) { - - size_t sz = sizeof(ON_Arc); //152 - - EXPECT_EQ(sz, 152); - -} - -TEST(ONTest, ONTestClassSizeON_ArcCurve) { - - size_t sz = sizeof(ON_ArcCurve); //192 - - EXPECT_EQ(sz, 192); - -} - -TEST(ONTest, ONTestClassSizeON_Buffer) { - - size_t sz = sizeof(ON_Buffer); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_3DM_BIG_CHUNK) { - - size_t sz = sizeof(ON_3DM_BIG_CHUNK); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_UserDataItemFilter) { - - size_t sz = sizeof(ON_UserDataItemFilter); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_ComponentManifest) { - - size_t sz = sizeof(ON_ComponentManifest); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_ComponentManifestItem) { - - size_t sz = sizeof(ON_ComponentManifestItem); //80 - - EXPECT_EQ(sz, 80); - -} - -TEST(ONTest, ONTestClassSizeON_ManifestMapItem) { - - size_t sz = sizeof(ON_ManifestMapItem); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_ManifestMap) { - - size_t sz = sizeof(ON_ManifestMap); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_3dmAnnotationContext) { - - size_t sz = sizeof(ON_3dmAnnotationContext); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_3dmArchiveTableStatus) { - - size_t sz = sizeof(ON_3dmArchiveTableStatus); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_BinaryArchive) { - - size_t sz = sizeof(ON_BinaryArchive); //512 - - EXPECT_EQ(sz, 512); - -} - -TEST(ONTest, ONTestClassSizeON_3dmGoo) { - - size_t sz = sizeof(ON_3dmGoo); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_BinaryFile) { - - size_t sz = sizeof(ON_BinaryFile); //560 - - EXPECT_EQ(sz, 560); - -} - -TEST(ONTest, ONTestClassSizeON_BinaryArchiveBuffer) { - - size_t sz = sizeof(ON_BinaryArchiveBuffer); //520 - - EXPECT_EQ(sz, 520); - -} - -TEST(ONTest, ONTestClassSizeON_Read3dmBufferArchive) { - - size_t sz = sizeof(ON_Read3dmBufferArchive); //576 - - EXPECT_EQ(sz, 576); - -} - -TEST(ONTest, ONTestClassSizeON_Write3dmBufferArchive) { - - size_t sz = sizeof(ON_Write3dmBufferArchive); //592 - - EXPECT_EQ(sz, 592); - -} - -TEST(ONTest, ONTestClassSizeON_DebugWriteArchive) { - - size_t sz = sizeof(ON_DebugWriteArchive); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UuidPair) { - - size_t sz = sizeof(ON_UuidPair); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UuidList) { - - size_t sz = sizeof(ON_UuidList); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UuidIndexList) { - - size_t sz = sizeof(ON_UuidIndexList); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UuidPtrList) { - - size_t sz = sizeof(ON_UuidPtrList); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UuidPairList) { - - size_t sz = sizeof(ON_UuidPairList); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_2dexMap) { - - size_t sz = sizeof(ON_2dexMap); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_Base64EncodeStream) { - - size_t sz = sizeof(ON_Base64EncodeStream); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_DecodeBase64) { - - size_t sz = sizeof(ON_DecodeBase64); //552 - - EXPECT_EQ(sz, 552); - -} - -TEST(ONTest, ONTestClassSizeON_Extrusion) { - - size_t sz = sizeof(ON_Extrusion); //208 - - EXPECT_EQ(sz, 208); - -} - -TEST(ONTest, ONTestClassSizeON_PolynomialCurve) { - - size_t sz = sizeof(ON_PolynomialCurve); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_PolynomialSurface) { - - size_t sz = sizeof(ON_PolynomialSurface); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_BezierCurve) { - - size_t sz = sizeof(ON_BezierCurve); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_BezierSurface) { - - size_t sz = sizeof(ON_BezierSurface); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_BezierCage) { - - size_t sz = sizeof(ON_BezierCage); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_BezierCageMorph) { - - size_t sz = sizeof(ON_BezierCageMorph); //216 - - EXPECT_EQ(sz, 216); - -} - -TEST(ONTest, ONTestClassSizeON_Bitmap) { - - size_t sz = sizeof(ON_Bitmap); //328 - - EXPECT_EQ(sz, 328); - -} - -TEST(ONTest, ONTestClassSizeON_WindowsBitmap) { - - size_t sz = sizeof(ON_WindowsBitmap); //352 - - EXPECT_EQ(sz, 352); - -} - -TEST(ONTest, ONTestClassSizeON_WindowsBitmapEx) { - - size_t sz = sizeof(ON_WindowsBitmapEx); //352 - - EXPECT_EQ(sz, 352); - -} - -TEST(ONTest, ONTestClassSizeON_EmbeddedBitmap) { - - size_t sz = sizeof(ON_EmbeddedBitmap); //352 - - EXPECT_EQ(sz, 352); - -} - -TEST(ONTest, ONTestClassSizeON_BoundingBox) { - - size_t sz = sizeof(ON_BoundingBox); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_BoundingBoxAndHash) { - - size_t sz = sizeof(ON_BoundingBoxAndHash); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_BoundingBoxCache) { - - size_t sz = sizeof(ON_BoundingBoxCache); //584 - - EXPECT_EQ(sz, 584); - -} - -TEST(ONTest, ONTestClassSizeON_Box) { - - size_t sz = sizeof(ON_Box); //176 - - EXPECT_EQ(sz, 176); - -} - -TEST(ONTest, ONTestClassSizeON_BrepVertex) { - - size_t sz = sizeof(ON_BrepVertex); //88 - - EXPECT_EQ(sz, 88); - -} - -TEST(ONTest, ONTestClassSizeON_BrepEdge) { - - size_t sz = sizeof(ON_BrepEdge); //136 - - EXPECT_EQ(sz, 136); - -} - -TEST(ONTest, ONTestClassSizeON_BrepTrim) { - - size_t sz = sizeof(ON_BrepTrim); //232 - - EXPECT_EQ(sz, 232); - -} - -TEST(ONTest, ONTestClassSizeON_BrepLoop) { - - size_t sz = sizeof(ON_BrepLoop); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_BrepFaceSide) { - - size_t sz = sizeof(ON_BrepFaceSide); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_BrepRegion) { - - size_t sz = sizeof(ON_BrepRegion); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_BrepEdgeArray) { - - size_t sz = sizeof(ON_BrepEdgeArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_BrepTrimArray) { - - size_t sz = sizeof(ON_BrepTrimArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_BrepLoopArray) { - - size_t sz = sizeof(ON_BrepLoopArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_BrepFaceArray) { - - size_t sz = sizeof(ON_BrepFaceArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_BrepRegionTopology) { - - size_t sz = sizeof(ON_BrepRegionTopology); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_Brep) { - - size_t sz = sizeof(ON_Brep); //312 - - EXPECT_EQ(sz, 312); - -} - -TEST(ONTest, ONTestClassSizeON_Circle) { - - size_t sz = sizeof(ON_Circle); //136 - - EXPECT_EQ(sz, 136); - -} - -TEST(ONTest, ONTestClassSizeON_Color) { - - size_t sz = sizeof(ON_Color); //4 - - EXPECT_EQ(sz, 4); - -} - -TEST(ONTest, ONTestClassSizeON_CompressStream) { - - size_t sz = sizeof(ON_CompressStream); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_UncompressStream) { - - size_t sz = sizeof(ON_UncompressStream); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_CompressedBuffer) { - - size_t sz = sizeof(ON_CompressedBuffer); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_ComponentStatus) { - - size_t sz = sizeof(ON_ComponentStatus); //2 - - //RH-78870 - Was changed from V6 and originally 1 but because of size alignment does not break the SDK - EXPECT_EQ(sz, 2); - -} - -TEST(ONTest, ONTestClassSizeON_AggregateComponentStatus) { - - size_t sz = sizeof(ON_AggregateComponentStatus); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_UniqueTester) { - - size_t sz = sizeof(ON_UniqueTester); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Cone) { - - size_t sz = sizeof(ON_Cone); //144 - - EXPECT_EQ(sz, 144); - -} - -TEST(ONTest, ONTestClassSizeON_StopWatch) { - - size_t sz = sizeof(ON_StopWatch); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_MeshCurveParameters) { - - size_t sz = sizeof(ON_MeshCurveParameters); //80 - - EXPECT_EQ(sz, 80); - -} - -TEST(ONTest, ONTestClassSizeON_Curve) { - - size_t sz = sizeof(ON_Curve); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_CurveArray) { - - size_t sz = sizeof(ON_CurveArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_CurveOnSurface) { - - size_t sz = sizeof(ON_CurveOnSurface); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_CurveProxy) { - - size_t sz = sizeof(ON_CurveProxy); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_Cylinder) { - - size_t sz = sizeof(ON_Cylinder); //152 - - EXPECT_EQ(sz, 152); - -} - -TEST(ONTest, ONTestClassSizeON_2dex) { - - size_t sz = sizeof(ON_2dex); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_2udex) { - - size_t sz = sizeof(ON_2udex); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_3dex) { - - size_t sz = sizeof(ON_3dex); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_3udex) { - - size_t sz = sizeof(ON_3udex); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_4dex) { - - size_t sz = sizeof(ON_4dex); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_4udex) { - - size_t sz = sizeof(ON_4udex); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_COMPONENT_INDEX) { - - size_t sz = sizeof(ON_COMPONENT_INDEX); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_DetailView) { - - size_t sz = sizeof(ON_DetailView); //1608 - - EXPECT_EQ(sz, 1608); - -} - -TEST(ONTest, ONTestClassSizeON_Dimension) { - - size_t sz = sizeof(ON_Dimension); //880 - - EXPECT_EQ(sz, 880); - -} - -TEST(ONTest, ONTestClassSizeON_DimLinear) { - - size_t sz = sizeof(ON_DimLinear); //912 - - EXPECT_EQ(sz, 912); - -} - -TEST(ONTest, ONTestClassSizeON_DimAngular) { - - size_t sz = sizeof(ON_DimAngular); //944 - - EXPECT_EQ(sz, 944); - -} - -TEST(ONTest, ONTestClassSizeON_DimRadial) { - - size_t sz = sizeof(ON_DimRadial); //912 - - EXPECT_EQ(sz, 912); - -} - -TEST(ONTest, ONTestClassSizeON_DimOrdinate) { - - size_t sz = sizeof(ON_DimOrdinate); //936 - - EXPECT_EQ(sz, 936); - -} - -TEST(ONTest, ONTestClassSizeON_Centermark) { - - size_t sz = sizeof(ON_Centermark); //888 - - EXPECT_EQ(sz, 888); - -} - -TEST(ONTest, ONTestClassSizeON_Arrowhead) { - - size_t sz = sizeof(ON_Arrowhead); //20 - - EXPECT_EQ(sz, 20); - -} - -TEST(ONTest, ONTestClassSizeON_TextMask) { - - size_t sz = sizeof(ON_TextMask); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_DimStyle) { - - size_t sz = sizeof(ON_DimStyle); //1104 - - EXPECT_EQ(sz, 1104); - -} - -TEST(ONTest, ONTestClassSizeON_DimStyleContext) { - - size_t sz = sizeof(ON_DimStyleContext); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_Ellipse) { - - size_t sz = sizeof(ON_Ellipse); //144 - - EXPECT_EQ(sz, 144); - -} - -TEST(ONTest, ONTestClassSizeON_ErrorEvent) { - - size_t sz = sizeof(ON_ErrorEvent); //160 - - EXPECT_EQ(sz, 160); - -} - -TEST(ONTest, ONTestClassSizeON_ErrorLog) { - - size_t sz = sizeof(ON_ErrorLog); //5136 - - EXPECT_EQ(sz, 5136); - -} - -TEST(ONTest, ONTestClassSizeON_FileSystem) { - - size_t sz = sizeof(ON_FileSystem); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_FileSystemPath) { - - size_t sz = sizeof(ON_FileSystemPath); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_FileStream) { - - size_t sz = sizeof(ON_FileStream); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_ContentHash) { - - size_t sz = sizeof(ON_ContentHash); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_FileReference) { - - size_t sz = sizeof(ON_FileReference); //184 - - EXPECT_EQ(sz, 184); - -} - -TEST(ONTest, ONTestClassSizeON_FileIterator) { - - size_t sz = sizeof(ON_FileIterator); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_FontMetrics) { - - size_t sz = sizeof(ON_FontMetrics); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_TextBox) { - - size_t sz = sizeof(ON_TextBox); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_OutlineFigurePoint) { - - size_t sz = sizeof(ON_OutlineFigurePoint); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_OutlineFigure) { - - size_t sz = sizeof(ON_OutlineFigure); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_Outline) { - - size_t sz = sizeof(ON_Outline); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_OutlineAccumulator) { - - size_t sz = sizeof(ON_OutlineAccumulator); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_FontGlyph) { - - size_t sz = sizeof(ON_FontGlyph); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_WindowsDWriteFontInformation) { - - size_t sz = sizeof(ON_WindowsDWriteFontInformation); //856 - - //RH-78870 - Shouldn't ever be used by a client and was only in 6 for prototyping so not considered a break - EXPECT_EQ(sz, 856); - -} - -TEST(ONTest, ONTestClassSizeON_FontFaceQuartet) { - - size_t sz = sizeof(ON_FontFaceQuartet); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_Font) { - - size_t sz = sizeof(ON_Font); //192 - - EXPECT_EQ(sz, 192); - -} - -TEST(ONTest, ONTestClassSizeON_FontList) { - - size_t sz = sizeof(ON_FontList); //248 - - EXPECT_EQ(sz, 248); - -} - -TEST(ONTest, ONTestClassSizeON_2fPoint) { - - size_t sz = sizeof(ON_2fPoint); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_3fPoint) { - - size_t sz = sizeof(ON_3fPoint); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_4fPoint) { - - size_t sz = sizeof(ON_4fPoint); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_2fVector) { - - size_t sz = sizeof(ON_2fVector); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_3fVector) { - - size_t sz = sizeof(ON_3fVector); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_FixedSizePool) { - - size_t sz = sizeof(ON_FixedSizePool); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_FixedSizePoolIterator) { - - size_t sz = sizeof(ON_FixedSizePoolIterator); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_FunctionList) { - - size_t sz = sizeof(ON_FunctionList); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_Geometry) { - - size_t sz = sizeof(ON_Geometry); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Group) { - - size_t sz = sizeof(ON_Group); //144 - - EXPECT_EQ(sz, 144); - -} - -TEST(ONTest, ONTestClassSizeON_Hash32TableItem) { - - size_t sz = sizeof(ON_Hash32TableItem); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Hash32Table) { - - size_t sz = sizeof(ON_Hash32Table); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_HatchLoop) { - - size_t sz = sizeof(ON_HatchLoop); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_HatchLine) { - - size_t sz = sizeof(ON_HatchLine); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_HatchPattern) { - - size_t sz = sizeof(ON_HatchPattern); //184 - - EXPECT_EQ(sz, 184); - -} - -TEST(ONTest, ONTestClassSizeON_Hatch) { - - size_t sz = sizeof(ON_Hatch); //208 - - EXPECT_EQ(sz, 208); - -} - -TEST(ONTest, ONTestClassSizeON_CurveRegionBoundaryElement) { - - size_t sz = sizeof(ON_CurveRegionBoundaryElement); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_ReferencedComponentSettings) { - - size_t sz = sizeof(ON_ReferencedComponentSettings); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_InstanceDefinition) { - - size_t sz = sizeof(ON_InstanceDefinition); //568 - - EXPECT_EQ(sz, 568); - -} - -TEST(ONTest, ONTestClassSizeON_InstanceRef) { - - size_t sz = sizeof(ON_InstanceRef); //208 - - EXPECT_EQ(sz, 208); - -} - -TEST(ONTest, ONTestClassSizeON_2iPoint) { - - size_t sz = sizeof(ON_2iPoint); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_2iVector) { - - size_t sz = sizeof(ON_2iVector); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_2iBoundingBox) { - - size_t sz = sizeof(ON_2iBoundingBox); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_2iSize) { - - size_t sz = sizeof(ON_2iSize); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_4iRect) { - - size_t sz = sizeof(ON_4iRect); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Layer) { - - size_t sz = sizeof(ON_Layer); //232 - - EXPECT_EQ(sz, 232); - -} - -TEST(ONTest, ONTestClassSizeON_Leader) { - - size_t sz = sizeof(ON_Leader); //840 - - EXPECT_EQ(sz, 840); - -} - -TEST(ONTest, ONTestClassSizeON_Light) { - - size_t sz = sizeof(ON_Light); //240 - - EXPECT_EQ(sz, 240); - -} - -TEST(ONTest, ONTestClassSizeON_Line) { - - size_t sz = sizeof(ON_Line); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_Triangle) { - - size_t sz = sizeof(ON_Triangle); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_LineCurve) { - - size_t sz = sizeof(ON_LineCurve); //88 - - EXPECT_EQ(sz, 88); - -} - -TEST(ONTest, ONTestClassSizeON_DisplayMaterialRef) { - - size_t sz = sizeof(ON_DisplayMaterialRef); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_LinetypeSegment) { - - size_t sz = sizeof(ON_LinetypeSegment); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Linetype) { - - size_t sz = sizeof(ON_Linetype); //176 - - EXPECT_EQ(sz, 176); - -} - -TEST(ONTest, ONTestClassSizeON_Locale) { - - size_t sz = sizeof(ON_Locale); //160 - - EXPECT_EQ(sz, 160); - -} - -TEST(ONTest, ONTestClassSizeON_Lock) { - - size_t sz = sizeof(ON_Lock); //4 - - EXPECT_EQ(sz, 4); - -} - -TEST(ONTest, ONTestClassSizeON_SerialNumberMap) { - - size_t sz = sizeof(ON_SerialNumberMap); //112 - - EXPECT_EQ(sz, 112); - -} - -TEST(ONTest, ONTestClassSizeON_MappingChannel) { - - size_t sz = sizeof(ON_MappingChannel); //152 - - EXPECT_EQ(sz, 152); - -} - -TEST(ONTest, ONTestClassSizeON_MappingRef) { - - size_t sz = sizeof(ON_MappingRef); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_MaterialRef) { - - size_t sz = sizeof(ON_MaterialRef); //60 - - EXPECT_EQ(sz, 60); - -} - -TEST(ONTest, ONTestClassSizeON_Material) { - - size_t sz = sizeof(ON_Material); //312 - - EXPECT_EQ(sz, 312); - -} - -TEST(ONTest, ONTestClassSizeON_PhysicallyBasedMaterial) { - - size_t sz = sizeof(ON_PhysicallyBasedMaterial); //72 - - //RH-78870 - Not a break since a pointer to it is all that's ever returned - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_Sum) { - - size_t sz = sizeof(ON_Sum); //28736 - - EXPECT_EQ(sz, 28736); - -} - -TEST(ONTest, ONTestClassSizeON_Evaluator) { - - size_t sz = sizeof(ON_Evaluator); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_Matrix) { - - size_t sz = sizeof(ON_Matrix); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_MD5_Hash) { - - size_t sz = sizeof(ON_MD5_Hash); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_MD5) { - - size_t sz = sizeof(ON_MD5); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_MemoryAllocationTracking) { - - size_t sz = sizeof(ON_MemoryAllocationTracking); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_MeshParameters) { - - size_t sz = sizeof(ON_MeshParameters); //224 - - EXPECT_EQ(sz, 224); - -} - -TEST(ONTest, ONTestClassSizeON_MeshCurvatureStats) { - - size_t sz = sizeof(ON_MeshCurvatureStats); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_MeshFace) { - - size_t sz = sizeof(ON_MeshFace); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_MeshTriangle) { - - size_t sz = sizeof(ON_MeshTriangle); //12 - - EXPECT_EQ(sz, 12); - -} - -TEST(ONTest, ONTestClassSizeON_MeshFaceList) { - - size_t sz = sizeof(ON_MeshFaceList); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_MeshVertexFaceMap) { - - size_t sz = sizeof(ON_MeshVertexFaceMap); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_MeshNgonBuffer) { - - size_t sz = sizeof(ON_MeshNgonBuffer); //80 - - EXPECT_EQ(sz, 80); - -} - -TEST(ONTest, ONTestClassSizeON_MeshNgon) { - - size_t sz = sizeof(ON_MeshNgon); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_MeshNgonAllocator) { - - size_t sz = sizeof(ON_MeshNgonAllocator); //168 - - EXPECT_EQ(sz, 168); - -} - -TEST(ONTest, ONTestClassSizeON_MeshTopology) { - - size_t sz = sizeof(ON_MeshTopology); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_MeshPartition) { - - size_t sz = sizeof(ON_MeshPartition); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_MappingTag) { - - size_t sz = sizeof(ON_MappingTag); //152 - - EXPECT_EQ(sz, 152); - -} - -TEST(ONTest, ONTestClassSizeON_TextureCoordinates) { - - size_t sz = sizeof(ON_TextureCoordinates); //184 - - EXPECT_EQ(sz, 184); - -} - -TEST(ONTest, ONTestClassSizeON_Mesh) { - - size_t sz = sizeof(ON_Mesh); //1760 - - EXPECT_EQ(sz, 1760); - -} - -TEST(ONTest, ONTestClassSizeON_MeshCache) { - - size_t sz = sizeof(ON_MeshCache); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_MeshNgonIterator) { - - size_t sz = sizeof(ON_MeshNgonIterator); //128 - - EXPECT_EQ(sz, 128); - -} - -TEST(ONTest, ONTestClassSizeON_MeshComponentRef) { - - size_t sz = sizeof(ON_MeshComponentRef); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_ModelComponent) { - - size_t sz = sizeof(ON_ModelComponent); //144 - - EXPECT_EQ(sz, 144); - -} - -TEST(ONTest, ONTestClassSizeON_ModelComponentContentMark) { - - size_t sz = sizeof(ON_ModelComponentContentMark); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_ModelComponentTypeIterator) { - - size_t sz = sizeof(ON_ModelComponentTypeIterator); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_ModelComponentReference) { - - size_t sz = sizeof(ON_ModelComponentReference); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_ModelComponentWeakReference) { - - size_t sz = sizeof(ON_ModelComponentWeakReference); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_ModelGeometryComponent) { - - size_t sz = sizeof(ON_ModelGeometryComponent); //176 - - EXPECT_EQ(sz, 176); - -} - -TEST(ONTest, ONTestClassSizeON_NurbsCurve) { - - size_t sz = sizeof(ON_NurbsCurve); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_TensorProduct) { - - size_t sz = sizeof(ON_TensorProduct); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_NurbsSurface) { - - size_t sz = sizeof(ON_NurbsSurface); //88 - - EXPECT_EQ(sz, 88); - -} - -TEST(ONTest, ONTestClassSizeON_NurbsCage) { - - size_t sz = sizeof(ON_NurbsCage); //112 - - EXPECT_EQ(sz, 112); - -} - -TEST(ONTest, ONTestClassSizeON_MorphControl) { - - size_t sz = sizeof(ON_MorphControl); //688 - - EXPECT_EQ(sz, 688); - -} - -TEST(ONTest, ONTestClassSizeON_CageMorph) { - - size_t sz = sizeof(ON_CageMorph); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_ClassId) { - - size_t sz = sizeof(ON_ClassId); //272 - - EXPECT_EQ(sz, 272); - -} - -TEST(ONTest, ONTestClassSizeON_UserString) { - - size_t sz = sizeof(ON_UserString); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Object) { - - size_t sz = sizeof(ON_Object); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_CurveProxyHistory) { - - size_t sz = sizeof(ON_CurveProxyHistory); //344 - - EXPECT_EQ(sz, 344); - -} - -TEST(ONTest, ONTestClassSizeON_PolyEdgeHistory) { - - size_t sz = sizeof(ON_PolyEdgeHistory); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_HistoryRecord) { - - size_t sz = sizeof(ON_HistoryRecord); //264 - - EXPECT_EQ(sz, 264); - -} - -TEST(ONTest, ONTestClassSizeON_ObjRefEvaluationParameter) { - - size_t sz = sizeof(ON_ObjRefEvaluationParameter); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_ObjRef_IRefID) { - - size_t sz = sizeof(ON_ObjRef_IRefID); //400 - - EXPECT_EQ(sz, 400); - -} - -TEST(ONTest, ONTestClassSizeON_ObjRef) { - - size_t sz = sizeof(ON_ObjRef); //224 - - EXPECT_EQ(sz, 224); - -} - -TEST(ONTest, ONTestClassSizeON_BumpFunction) { - - size_t sz = sizeof(ON_BumpFunction); //80 - - EXPECT_EQ(sz, 80); - -} - -TEST(ONTest, ONTestClassSizeON_OffsetSurfaceValue) { - - size_t sz = sizeof(ON_OffsetSurfaceValue); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_OffsetSurfaceFunction) { - - size_t sz = sizeof(ON_OffsetSurfaceFunction); //104 - - EXPECT_EQ(sz, 104); - -} - -TEST(ONTest, ONTestClassSizeON_ArithmeticCalculator) { - - size_t sz = sizeof(ON_ArithmeticCalculator); //1024 - - EXPECT_EQ(sz, 1024); - -} - -TEST(ONTest, ONTestClassSizeON_LengthUnitName) { - - size_t sz = sizeof(ON_LengthUnitName); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_AngleUnitName) { - - size_t sz = sizeof(ON_AngleUnitName); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_ParseSettings) { - - size_t sz = sizeof(ON_ParseSettings); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_AerialPhotoImageFrustum) { - - size_t sz = sizeof(ON_AerialPhotoImageFrustum); //96 - - EXPECT_EQ(sz, 96); - -} - -TEST(ONTest, ONTestClassSizeON_AerialPhotoCameraPosition) { - - size_t sz = sizeof(ON_AerialPhotoCameraPosition); //304 - - EXPECT_EQ(sz, 304); - -} - -TEST(ONTest, ONTestClassSizeON_AerialPhotoImage) { - - size_t sz = sizeof(ON_AerialPhotoImage); //440 - - EXPECT_EQ(sz, 440); - -} - -TEST(ONTest, ONTestClassSizeON_Plane) { - - size_t sz = sizeof(ON_Plane); //128 - - EXPECT_EQ(sz, 128); - -} - -TEST(ONTest, ONTestClassSizeON_ClippingPlaneInfo) { - - size_t sz = sizeof(ON_ClippingPlaneInfo); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_ClippingPlane) { - - size_t sz = sizeof(ON_ClippingPlane); //184 - - EXPECT_EQ(sz, 184); - -} - -TEST(ONTest, ONTestClassSizeON_PlaneSurface) { - - size_t sz = sizeof(ON_PlaneSurface); //208 - - EXPECT_EQ(sz, 208); - -} - -TEST(ONTest, ONTestClassSizeON_ClippingPlaneSurface) { - - size_t sz = sizeof(ON_ClippingPlaneSurface); //392 - - EXPECT_EQ(sz, 392); - -} - -TEST(ONTest, ONTestClassSizeON_PlugInRef) { - - size_t sz = sizeof(ON_PlugInRef); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_Interval) { - - size_t sz = sizeof(ON_Interval); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_2dPoint) { - - size_t sz = sizeof(ON_2dPoint); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_3dPoint) { - - size_t sz = sizeof(ON_3dPoint); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_4dPoint) { - - size_t sz = sizeof(ON_4dPoint); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_2dVector) { - - size_t sz = sizeof(ON_2dVector); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_3dVector) { - - size_t sz = sizeof(ON_3dVector); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3dRay) { - - size_t sz = sizeof(ON_3dRay); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_PlaneEquation) { - - size_t sz = sizeof(ON_PlaneEquation); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_SurfaceCurvature) { - - size_t sz = sizeof(ON_SurfaceCurvature); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_2dPointArray) { - - size_t sz = sizeof(ON_2dPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_2fPointArray) { - - size_t sz = sizeof(ON_2fPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3dPointArray) { - - size_t sz = sizeof(ON_3dPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3fPointArray) { - - size_t sz = sizeof(ON_3fPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_4dPointArray) { - - size_t sz = sizeof(ON_4dPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_4fPointArray) { - - size_t sz = sizeof(ON_4fPointArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_2dVectorArray) { - - size_t sz = sizeof(ON_2dVectorArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_2fVectorArray) { - - size_t sz = sizeof(ON_2fVectorArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3dVectorArray) { - - size_t sz = sizeof(ON_3dVectorArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3fVectorArray) { - - size_t sz = sizeof(ON_3fVectorArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_3dPointListRef) { - - size_t sz = sizeof(ON_3dPointListRef); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_2dSize) { - - size_t sz = sizeof(ON_2dSize); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_4dRect) { - - size_t sz = sizeof(ON_4dRect); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_WindingNumber) { - - size_t sz = sizeof(ON_WindingNumber); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_PeriodicDomain) { - - size_t sz = sizeof(ON_PeriodicDomain); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_PointCloud) { - - size_t sz = sizeof(ON_PointCloud); //328 - - EXPECT_EQ(sz, 328); - -} - -TEST(ONTest, ONTestClassSizeON_Point) { - - size_t sz = sizeof(ON_Point); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_PointGrid) { - - size_t sz = sizeof(ON_PointGrid); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_PolyCurve) { - - size_t sz = sizeof(ON_PolyCurve); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_Polyline) { - - size_t sz = sizeof(ON_Polyline); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_PolylineCurve) { - - size_t sz = sizeof(ON_PolylineCurve); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_ProgressReporter) { - - size_t sz = sizeof(ON_ProgressReporter); //64 - - EXPECT_EQ(sz, 64); - -} - -TEST(ONTest, ONTestClassSizeON_ProgressStepCounter) { - - size_t sz = sizeof(ON_ProgressStepCounter); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_Quaternion) { - - size_t sz = sizeof(ON_Quaternion); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_RandomNumberGenerator) { - - size_t sz = sizeof(ON_RandomNumberGenerator); //2500 - - EXPECT_EQ(sz, 2500); - -} - -TEST(ONTest, ONTestClassSizeON_RenderingAttributes) { - - size_t sz = sizeof(ON_RenderingAttributes); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_ObjectRenderingAttributes) { - - size_t sz = sizeof(ON_ObjectRenderingAttributes); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_RevSurface) { - - size_t sz = sizeof(ON_RevSurface); //160 - - EXPECT_EQ(sz, 160); - -} - -TEST(ONTest, ONTestClassSizeON_RTreeMemPool) { - - size_t sz = sizeof(ON_RTreeMemPool); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_RTreeIterator) { - - size_t sz = sizeof(ON_RTreeIterator); //528 - - EXPECT_EQ(sz, 528); - -} - -TEST(ONTest, ONTestClassSizeON_RTree) { - - size_t sz = sizeof(ON_RTree); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_SHA1_Hash) { - - size_t sz = sizeof(ON_SHA1_Hash); //20 - - EXPECT_EQ(sz, 20); - -} - -TEST(ONTest, ONTestClassSizeON_SHA1) { - - size_t sz = sizeof(ON_SHA1); //128 - - EXPECT_EQ(sz, 128); - -} - -TEST(ONTest, ONTestClassSizeON_SleepLock) { - - size_t sz = sizeof(ON_SleepLock); //4 - - EXPECT_EQ(sz, 4); - -} - -TEST(ONTest, ONTestClassSizeON_SleepLockGuard) { - - size_t sz = sizeof(ON_SleepLockGuard); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Sphere) { - - size_t sz = sizeof(ON_Sphere); //136 - - EXPECT_EQ(sz, 136); - -} - -TEST(ONTest, ONTestClassSizeON_CheckSum) { - - size_t sz = sizeof(ON_CheckSum); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_StringBuffer) { - - size_t sz = sizeof(ON_StringBuffer); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_wStringBuffer) { - - size_t sz = sizeof(ON_wStringBuffer); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_String) { - - size_t sz = sizeof(ON_String); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_wString) { - - size_t sz = sizeof(ON_wString); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_NameHash) { - - size_t sz = sizeof(ON_NameHash); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_UnitSystem) { - - size_t sz = sizeof(ON_UnitSystem); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_LengthValue) { - - size_t sz = sizeof(ON_LengthValue); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_AngleValue) { - - size_t sz = sizeof(ON_AngleValue); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_ScaleValue) { - - size_t sz = sizeof(ON_ScaleValue); //128 - - EXPECT_EQ(sz, 128); - -} - -TEST(ONTest, ONTestClassSizeON_SubDVertexPtr) { - - size_t sz = sizeof(ON_SubDVertexPtr); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_SubDEdgePtr) { - - size_t sz = sizeof(ON_SubDEdgePtr); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_SubDFacePtr) { - - size_t sz = sizeof(ON_SubDFacePtr); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_SubDComponentPtr) { - - size_t sz = sizeof(ON_SubDComponentPtr); //8 - - EXPECT_EQ(sz, 8); - -} - -TEST(ONTest, ONTestClassSizeON_SubDComponentRefList) { - - size_t sz = sizeof(ON_SubDComponentRefList); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_SubDSectorType) { - - size_t sz = sizeof(ON_SubDSectorType); //40 - - EXPECT_EQ(sz, 40); - -} - -TEST(ONTest, ONTestClassSizeON_SumSurface) { - - size_t sz = sizeof(ON_SumSurface); //104 - - EXPECT_EQ(sz, 104); - -} - -TEST(ONTest, ONTestClassSizeON_Surface) { - - size_t sz = sizeof(ON_Surface); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_SurfaceProperties) { - - size_t sz = sizeof(ON_SurfaceProperties); //80 - - EXPECT_EQ(sz, 80); - -} - -TEST(ONTest, ONTestClassSizeON_SurfaceArray) { - - size_t sz = sizeof(ON_SurfaceArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_SurfaceProxy) { - - size_t sz = sizeof(ON_SurfaceProxy); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_Terminator) { - - size_t sz = sizeof(ON_Terminator); //56 - - EXPECT_EQ(sz, 56); - -} - -TEST(ONTest, ONTestClassSizeON_TextContent) { - - size_t sz = sizeof(ON_TextContent); //216 - - EXPECT_EQ(sz, 216); - -} - -TEST(ONTest, ONTestClassSizeON_TextStyle) { - - size_t sz = sizeof(ON_TextStyle); //208 - - EXPECT_EQ(sz, 208); - -} - -TEST(ONTest, ONTestClassSizeON_TextContext) { - - size_t sz = sizeof(ON_TextContext); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_TextLog) { - - size_t sz = sizeof(ON_TextLog); //120 - - EXPECT_EQ(sz, 120); - -} - -TEST(ONTest, ONTestClassSizeON_TextLogIndent) { - - size_t sz = sizeof(ON_TextLogIndent); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_TextHash) { - - size_t sz = sizeof(ON_TextHash); //480 - - EXPECT_EQ(sz, 480); - -} - -TEST(ONTest, ONTestClassSizeON_Text) { - - size_t sz = sizeof(ON_Text); //792 - - EXPECT_EQ(sz, 792); - -} - -TEST(ONTest, ONTestClassSizeON_StackedText) { - - size_t sz = sizeof(ON_StackedText); //32 - - EXPECT_EQ(sz, 32); - -} - -TEST(ONTest, ONTestClassSizeON_TextRun) { - - size_t sz = sizeof(ON_TextRun); //240 - - EXPECT_EQ(sz, 240); - -} - -TEST(ONTest, ONTestClassSizeON_TextRunArray) { - - size_t sz = sizeof(ON_TextRunArray); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_Texture) { - - size_t sz = sizeof(ON_Texture); //512 - - EXPECT_EQ(sz, 512); - -} - -TEST(ONTest, ONTestClassSizeON_TextureMapping) { - - size_t sz = sizeof(ON_TextureMapping); //560 - - EXPECT_EQ(sz, 560); - -} - -TEST(ONTest, ONTestClassSizeON_ComponentAttributes) { - - size_t sz = sizeof(ON_ComponentAttributes); //1 - - EXPECT_EQ(sz, 1); - -} - -TEST(ONTest, ONTestClassSizeON_Torus) { - - size_t sz = sizeof(ON_Torus); //144 - - EXPECT_EQ(sz, 144); - -} - -TEST(ONTest, ONTestClassSizeON_UserData) { - - size_t sz = sizeof(ON_UserData); //200 - - EXPECT_EQ(sz, 200); - -} - -TEST(ONTest, ONTestClassSizeON_UnknownUserData) { - - size_t sz = sizeof(ON_UnknownUserData); //240 - - EXPECT_EQ(sz, 240); - -} - -TEST(ONTest, ONTestClassSizeON_ObsoleteUserData) { - - size_t sz = sizeof(ON_ObsoleteUserData); //216 - - EXPECT_EQ(sz, 216); - -} - -TEST(ONTest, ONTestClassSizeON_UserStringList) { - - size_t sz = sizeof(ON_UserStringList); //224 - - EXPECT_EQ(sz, 224); - -} - -TEST(ONTest, ONTestClassSizeON_UserDataHolder) { - - size_t sz = sizeof(ON_UserDataHolder); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_DocumentUserStringList) { - - size_t sz = sizeof(ON_DocumentUserStringList); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_UuidIndex) { - - size_t sz = sizeof(ON_UuidIndex); //20 - - EXPECT_EQ(sz, 20); - -} - -TEST(ONTest, ONTestClassSizeON_UuidPtr) { - - size_t sz = sizeof(ON_UuidPtr); //24 - - EXPECT_EQ(sz, 24); - -} - -TEST(ONTest, ONTestClassSizeON_Viewport) { - - size_t sz = sizeof(ON_Viewport); //584 - - EXPECT_EQ(sz, 584); - -} - -TEST(ONTest, ONTestClassSizeON_Workspace) { - - size_t sz = sizeof(ON_Workspace); //16 - - EXPECT_EQ(sz, 16); - -} - -TEST(ONTest, ONTestClassSizeON_Xform) { - - size_t sz = sizeof(ON_Xform); //128 - - EXPECT_EQ(sz, 128); - -} - -TEST(ONTest, ONTestClassSizeON_ClippingRegion) { - - size_t sz = sizeof(ON_ClippingRegion); //784 - - EXPECT_EQ(sz, 784); - -} - -TEST(ONTest, ONTestClassSizeON_ClippingRegionPoints) { - - size_t sz = sizeof(ON_ClippingRegionPoints); //48 - - EXPECT_EQ(sz, 48); - -} - -TEST(ONTest, ONTestClassSizeON_PickPoint) { - - size_t sz = sizeof(ON_PickPoint); //72 - - EXPECT_EQ(sz, 72); - -} - -TEST(ONTest, ONTestClassSizeON_Localizer) { - - size_t sz = sizeof(ON_Localizer); //88 - - EXPECT_EQ(sz, 88); - -} - -TEST(ONTest, ONTestClassSizeON_SpaceMorph) { - - size_t sz = sizeof(ON_SpaceMorph); //32 - - EXPECT_EQ(sz, 32); - -} - - diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 89f38c83..5a905ff2 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.4) +cmake_minimum_required (VERSION 3.16) project( zlib C)