mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-08 16:55:53 +08:00
Co-authored-by: Bozo <bozo@mcneel.com> Co-authored-by: croudyj <croudyj@gmail.com> Co-authored-by: Dale Fugier <dale@mcneel.com> Co-authored-by: Dale Lear <dalelear@mcneel.com> Co-authored-by: Joshua Kennedy <joshuakennedy102@gmail.com> Co-authored-by: Jussi Aaltonen <jussi@mcneel.com> Co-authored-by: kike-garbo <kike@mcneel.com> Co-authored-by: Luis Fraguada <luis@mcneel.com> Co-authored-by: piac <giulio@mcneel.com> Co-authored-by: Pierre Cuvilliers <pierre@mcneel.com>
817 lines
24 KiB
C++
817 lines
24 KiB
C++
/* $Header: /src4/opennurbs/Tests/TestCurveSurfaceIntersection.cpp 21 6/16/05 3:40p Dalelear $ */
|
|
/* $NoKeywords: $ */
|
|
|
|
#include "Tests.h"
|
|
|
|
static bool bPurify = false;
|
|
|
|
static double TestOverlapDistance(
|
|
ON_Interval overlap_domain,
|
|
const ON_Curve* curve,
|
|
const ON_Surface* surface,
|
|
int sample_count
|
|
)
|
|
{
|
|
int n, j;
|
|
double w, s, t, d;
|
|
ON_2dPoint uv;
|
|
ON_3dPoint C, S;
|
|
w = 1.0;
|
|
if (sample_count < 1 )
|
|
sample_count = 1;
|
|
|
|
double maxd = 0.0;
|
|
|
|
for ( n = 2; sample_count > 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<ON_X_EVENT>& 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<ON_X_EVENT>& 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<ON_X_EVENT> 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<ON_X_EVENT> 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<ON_X_EVENT> 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
|
|
);
|
|
}
|
|
}
|
|
|
|
|