Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:48:53

0001 /**
0002 CSGIntersectComparisonTest.cc
0003 ===============================
0004 
0005 Compare intersects onto two implementations of a CSGNode 
0006 
0007 ::
0008 
0009     METHOD=intersect RAYORI=90,0,0 RAYDIR=1,0,0 TMIN=9 CSGIntersectComparisonTest
0010 
0011 **/
0012 
0013 
0014 #include "OPTICKS_LOG.hh"
0015 #include <cmath>
0016 #include <vector>
0017 #include <map>
0018 
0019 #include "scuda.h"
0020 #include "squad.h"
0021 #include "sqat4.h"
0022 #include "ssincos.h"
0023 
0024 #include "SSys.hh"
0025 #include "SRng.hh"
0026 #include "SPath.hh"
0027 #include "NP.hh"
0028 
0029 //#define DEBUG 1 
0030 #include "csg_intersect_leaf.h"
0031 
0032 #include "CSGNode.h"
0033 
0034 enum { X, Y, Z } ; 
0035 
0036 
0037 struct CSGIntersectComparisonTest
0038 {
0039     static constexpr const char* FOLD = "$TMP/CSGIntersectComparisonTest" ; 
0040 
0041     const char* METHOD ; 
0042     bool FULL ; 
0043     const char* RERUN ; 
0044     NP* rerun ; 
0045     const quad4* rr ; 
0046 
0047     const char* AXES ; 
0048     unsigned h ; 
0049     unsigned v ; 
0050     unsigned o ; 
0051 
0052     const CSGNode* a ; 
0053     const CSGNode* b ; 
0054     float3 a_mn ; 
0055     float3 a_mx ; 
0056     float3 b_mn ; 
0057     float3 b_mx ; 
0058     const float* mn ; 
0059     const float* mx ; 
0060 
0061     float4 a_isect ; 
0062     float4 b_isect ; 
0063     bool a_valid_isect ; 
0064     bool b_valid_isect ; 
0065     int  status ; 
0066     float epsilon ; 
0067     bool expected ; 
0068 
0069     float4 zero4 ; 
0070     float3 zero3 ; 
0071     float3 a_pos ; 
0072     float3 b_pos ; 
0073     float  a_sd ; 
0074     float  b_sd ; 
0075     unsigned sd_winner ; 
0076     std::map<unsigned, unsigned> sd_winner_stats ; 
0077 
0078     float t_min ; 
0079     float3 ray_origin ; 
0080     float3 ray_direction ; 
0081     float* oo ; 
0082     float* vv ; 
0083 
0084     unsigned seed ; 
0085     SRng<double> rng ; 
0086     float margin ; 
0087 
0088     float x0 ; 
0089     float x1 ; 
0090     float y0 ; 
0091     float y1 ; 
0092     float z0 ; 
0093     float z1 ; 
0094 
0095     float h0 ; 
0096     float h1 ; 
0097     float v0 ; 
0098     float v1 ; 
0099     float o0 ; 
0100     float o1 ; 
0101 
0102     unsigned num ; 
0103 
0104     std::vector<quad4> a_simtrace ;  
0105     std::vector<quad4> b_simtrace ;  
0106 
0107 
0108     CSGIntersectComparisonTest( const CSGNode* a, const CSGNode* b ); 
0109     void init(); 
0110     std::string descStats() const ; 
0111 
0112     static void Zero(float4& v); 
0113     static void Zero(float3& v); 
0114     void zero(); 
0115 
0116     void intersect(); 
0117     unsigned smaller_sd() const ; 
0118 
0119     static void LoadSimtrace( const quad4& st, float& t_min, float3& ori, float3& dir ); 
0120     static void FormSimtrace( quad4& st, const float4& isect, const float3& pos, float t_min, const float3& ori, const float3& dir ); 
0121     void save(); 
0122 
0123     bool is_expected() const ; 
0124 
0125     float dpos() const ; 
0126     float ddis() const ; 
0127     float dnrm() const ; 
0128     float dmax() const ; 
0129     std::string descDiff() const ; 
0130 
0131     void scan(int axis); 
0132 
0133     static unsigned OtherAxis(unsigned h, unsigned v); 
0134 
0135     void random2D(); 
0136     void random2D_ray_origin();
0137     void random2D_ray_direction(); 
0138 
0139     void random2D_fixed_origin(); 
0140  
0141     void random3D(); 
0142     void random3D_ray_origin();
0143     void random3D_ray_direction(); 
0144 
0145 
0146     void loaded(); 
0147 
0148     void expected_miss(); 
0149     void expected_hit(); 
0150     void attempt_to_tickle_axial_issue(); 
0151 
0152     bool match(const char* q) const ; 
0153     void method(); 
0154     bool is_intersect() const ; 
0155 
0156 
0157     std::string descGeom() const ; 
0158     std::string descRay() const ; 
0159     std::string descA() const ; 
0160     std::string descB() const ; 
0161     std::string descFull() const ; 
0162     std::string desc_() const ; 
0163     std::string desc() const ; 
0164 
0165     static std::string DescRay(const float3& o, const float3& v, const float t_min ); 
0166     static std::string DescIsect(const float4& isect, const float3& pos, const float sd ); 
0167     static std::string Desc(const float& v); 
0168     static std::string Desc(const float3& v); 
0169     static std::string Desc(const float4& v); 
0170 }; 
0171 
0172 CSGIntersectComparisonTest::CSGIntersectComparisonTest( const CSGNode* a_, const CSGNode* b_ ) 
0173     : 
0174     METHOD(SSys::getenvvar("METHOD", "loaded")),
0175     FULL(SSys::getenvbool("FULL")),
0176     RERUN(SSys::getenvvar("RERUN", "/tmp/simtrace.npy")),
0177     rerun( NP::LoadIfExists(RERUN) ),
0178     rr( rerun ? (const quad4*)rerun->values<float>() : nullptr ),
0179     AXES(SSys::getenvvar("AXES", "XZ")),
0180     h( strlen(AXES) > 0 ? AXES[0] - 'X' : ~0u ),
0181     v( strlen(AXES) > 1 ? AXES[1] - 'X' : ~0u ),
0182     o( OtherAxis(h,v) ),
0183     a(a_), 
0184     b(b_),
0185     a_mn(a->mn()),
0186     a_mx(a->mx()),
0187     b_mn(b->mn()),
0188     b_mx(b->mx()),
0189     mn((const float*)&a_mn),
0190     mx((const float*)&a_mx),
0191     a_isect( make_float4(0.f, 0.f, 0.f, 0.f) ),
0192     b_isect( make_float4(0.f, 0.f, 0.f, 0.f) ),
0193     a_valid_isect(false),
0194     b_valid_isect(false),
0195     status(-1),
0196     epsilon(SSys::getenvfloat("EPSILON", 1e-5)),
0197     expected(true),
0198     zero4( make_float4( 0.f, 0.f, 0.f, 0.f )), 
0199     zero3( make_float3( 0.f, 0.f, 0.f )), 
0200     a_pos( make_float3( 0.f, 0.f, 0.f )),
0201     b_pos( make_float3( 0.f, 0.f, 0.f )),
0202     a_sd(0.f),
0203     b_sd(0.f),
0204     sd_winner(0u),
0205     t_min(SSys::getenvint("TMIN",0.f)),
0206     ray_origin(   SSys::getenvfloat3("RAYORI","0,0,0")), 
0207     ray_direction(SSys::getenvfloat3norm("RAYDIR","0,0,1")),
0208     oo((float*)&ray_origin),
0209     vv((float*)&ray_direction),
0210     seed(SSys::getenvunsigned("SEED", 1u)),
0211     rng(seed),
0212     margin(SSys::getenvfloat("MARGIN",1.2f)),
0213     x0(mn[X]*margin),
0214     x1(mx[X]*margin),
0215     y0(mn[Y]*margin),
0216     y1(mx[Y]*margin),
0217     z0(mn[Z]*margin),
0218     z1(mx[Z]*margin),
0219     h0(mn[h]*margin), 
0220     h1(mx[h]*margin), 
0221     v0(mn[v]*margin), 
0222     v1(mx[v]*margin), 
0223     o0(mn[o]*margin), 
0224     o1(mx[o]*margin), 
0225     num(SSys::getenvunsigned("NUM", 1000))
0226 {
0227     init(); 
0228 }
0229 
0230 void CSGIntersectComparisonTest::init()
0231 { 
0232     assert( a_mn.x == b_mn.x ); 
0233     assert( a_mn.y == b_mn.y ); 
0234     assert( a_mn.z == b_mn.z );
0235 
0236     assert( a_mx.x == b_mx.x ); 
0237     assert( a_mx.y == b_mx.y ); 
0238     assert( a_mx.z == b_mx.z );
0239 
0240     sd_winner_stats[0u] = 0u ; 
0241     sd_winner_stats[1u] = 0u ; 
0242     sd_winner_stats[2u] = 0u ; 
0243 }
0244 
0245 std::string CSGIntersectComparisonTest::descStats() const 
0246 {
0247     std::vector<std::string> labels = {{
0248         "sd_winner_stats[0u] A=B (draw  )", 
0249         "sd_winner_stats[1u] A<B (A wins)",
0250         "sd_winner_stats[2u] A>B (B wins)",
0251         "                         TOTAL: "
0252         }} ; 
0253 
0254 
0255     unsigned total = 0u ;   
0256     for(unsigned i=0 ; i < 3 ; i++ ) total += sd_winner_stats.at(i) ; 
0257 
0258     std::stringstream ss ; 
0259     ss << "descStats" << std::endl  ; 
0260 
0261     for(unsigned i=0 ; i < 3 ; i++)
0262     {
0263         ss << std::setw(30) << labels[i] 
0264            << std::setw(10) << sd_winner_stats.at(i)
0265            << std::fixed << std::setw(10) << std::setprecision(4) << float(sd_winner_stats.at(i))/float(total) 
0266            << std::endl
0267            ; 
0268     }
0269     ss << std::setw(30) << labels[3]
0270        << std::setw(10) << total 
0271        << std::endl 
0272        ; 
0273 
0274     std::string s = ss.str(); 
0275     return s ; 
0276 }
0277 
0278 void CSGIntersectComparisonTest::Zero(float4& v)
0279 {
0280     v.x = 0.f ; 
0281     v.y = 0.f ; 
0282     v.z = 0.f ; 
0283     v.w = 0.f ; 
0284 }
0285 void CSGIntersectComparisonTest::Zero(float3& v)
0286 {
0287     v.x = 0.f ; 
0288     v.y = 0.f ; 
0289     v.z = 0.f ; 
0290 }
0291 void CSGIntersectComparisonTest::zero()
0292 {
0293     Zero(a_isect); 
0294     Zero(b_isect);
0295     Zero(a_pos);  
0296     Zero(b_pos);  
0297 }
0298 
0299 unsigned CSGIntersectComparisonTest::smaller_sd() const
0300 {
0301     float abs_a = std::abs(a_sd) ; 
0302     float abs_b = std::abs(b_sd) ; 
0303     return abs_a == abs_b ? 0u : ( abs_a < abs_b ? 1u : 2u ) ; 
0304 } 
0305 
0306 void CSGIntersectComparisonTest::intersect()
0307 {
0308     zero(); 
0309 
0310     bool dump = false ; 
0311     a_valid_isect = false ; 
0312     intersect_leaf( a_valid_isect, a_isect, a , nullptr, nullptr, t_min, ray_origin, ray_direction, dump ); 
0313     b_valid_isect = false ; 
0314     intersect_leaf( b_valid_isect, b_isect, b , nullptr, nullptr, t_min, ray_origin, ray_direction, dump ); 
0315 
0316     status = ( int(a_valid_isect) << 1 ) | int(b_valid_isect) ; 
0317 
0318     // 0: A_MISS B_MISS  
0319     // 1: A_MISS B_HIT  
0320     // 2: A_HIT  B_MISS   
0321     // 3: A_HIT  B_HIT
0322 
0323     a_pos = a_valid_isect ? ray_origin + a_isect.w*ray_direction : zero3 ;  
0324     b_pos = b_valid_isect ? ray_origin + b_isect.w*ray_direction : zero3 ;  
0325 
0326     a_sd = a_valid_isect ? distance_leaf(a_pos, a, nullptr, nullptr ) : -1.f ;  
0327     b_sd = b_valid_isect ? distance_leaf(b_pos, b, nullptr, nullptr ) : -1.f ;  
0328     sd_winner = smaller_sd() ;  
0329     if( a_valid_isect && b_valid_isect ) sd_winner_stats[sd_winner] += 1u ;
0330 
0331     expected = is_expected();   // needs a_pos b_pos
0332     if(expected == false || is_intersect()) std::cout << desc() << std::endl; 
0333 
0334 
0335     quad4 sta ; 
0336     FormSimtrace(sta, a_isect, a_pos, t_min, ray_origin, ray_direction ); 
0337     a_simtrace.push_back(sta); 
0338 
0339     quad4 stb ; 
0340     FormSimtrace(stb, b_isect, b_pos, t_min, ray_origin, ray_direction ); 
0341     b_simtrace.push_back(stb); 
0342 
0343 }
0344 
0345 void CSGIntersectComparisonTest::save()
0346 {
0347     LOG(info) << std::endl << descGeom() ; 
0348     LOG(info) << std::endl << descStats() ; 
0349 
0350     const char* fold = SPath::Resolve(FOLD, DIRPATH); 
0351     LOG(info) << fold ; 
0352     NP::Write(fold, "a_simtrace.npy",  (float*)a_simtrace.data(), a_simtrace.size(), 4, 4 ); 
0353     NP::Write(fold, "b_simtrace.npy",  (float*)b_simtrace.data(), b_simtrace.size(), 4, 4 ); 
0354 }
0355 
0356 
0357 void CSGIntersectComparisonTest::LoadSimtrace( const quad4& st, float& tmin, float3& ori, float3& dir )
0358 {
0359     tmin = st.q1.f.w ; 
0360     ori.x = st.q2.f.x ; 
0361     ori.y = st.q2.f.y ; 
0362     ori.z = st.q2.f.z ; 
0363 
0364     dir.x = st.q3.f.x ; 
0365     dir.y = st.q3.f.y ; 
0366     dir.z = st.q3.f.z ; 
0367 }
0368 
0369 void CSGIntersectComparisonTest::FormSimtrace( quad4& st, const float4& isect, const float3& pos, float tmin, const float3& ori, const float3& dir )
0370 {
0371     st.q0.f = isect ; 
0372 
0373     st.q1.f.x = pos.x ; 
0374     st.q1.f.y = pos.y ; 
0375     st.q1.f.z = pos.z ;
0376     st.q1.f.w = tmin ;
0377 
0378     st.q2.f.x = ori.x ; 
0379     st.q2.f.y = ori.y ; 
0380     st.q2.f.z = ori.z ;
0381     st.q2.f.w = 0.f ;
0382 
0383     st.q3.f.x = dir.x ; 
0384     st.q3.f.y = dir.y ; 
0385     st.q3.f.z = dir.z ;
0386     st.q3.f.w = 0.f ;
0387 }
0388 
0389 
0390 bool CSGIntersectComparisonTest::is_expected() const
0391 {
0392     float dm = dmax(); 
0393     bool expected_status = status == 0 || status == 3 ; 
0394     bool expected_diff   = status == 3 ? fabs(dm) < epsilon : true  ; 
0395     return expected_status && expected_diff ; 
0396 }
0397 
0398 float CSGIntersectComparisonTest::dpos() const
0399 {
0400     float3 d_pos = a_pos - b_pos ; 
0401     return fmaxf(d_pos) ;  
0402 }
0403 float CSGIntersectComparisonTest::ddis() const
0404 {
0405     return a_isect.w - b_isect.w  ;  
0406 }
0407 float CSGIntersectComparisonTest::dnrm() const
0408 {
0409     float4 d_isect = a_isect - b_isect ; 
0410     float3* nrm = (float3*)&d_isect ; 
0411     return fmaxf(*nrm)  ;  
0412 }
0413 float CSGIntersectComparisonTest::dmax() const
0414 {
0415     float3 dm = make_float3( dpos(), ddis(), dnrm() ); 
0416     return fmaxf(dm); 
0417 }
0418 std::string CSGIntersectComparisonTest::descDiff() const
0419 {
0420     float dp = dpos(); 
0421     float dt = ddis(); 
0422     float dn = dnrm(); 
0423     float dm = dmax(); 
0424     std::stringstream ss ; 
0425     ss << " status " << status ; 
0426     ss << " dpos " << std::scientific << dp ;  
0427     ss << " ddis " << std::scientific << dt ;  
0428     ss << " dnrm " << std::scientific << dn ;  
0429     ss << " dmax " << std::scientific << dm ;  
0430     std::string s = ss.str();
0431     return s ; 
0432 }
0433 
0434 std::string CSGIntersectComparisonTest::descGeom() const 
0435 {
0436     std::stringstream ss ; 
0437     ss << " A " << a->desc() << std::endl ; 
0438     ss << " B " << b->desc() << std::endl ; 
0439     ss << " a_mn " << Desc(a_mn) << std::endl ; 
0440     ss << " b_mn " << Desc(b_mn) << std::endl ; 
0441     ss << " a_mx " << Desc(a_mx) << std::endl ; 
0442     ss << " b_mx " << Desc(b_mx) << std::endl ; 
0443     std::string s = ss.str();
0444     return s ; 
0445 }
0446 std::string CSGIntersectComparisonTest::descRay() const 
0447 {
0448     return DescRay(ray_origin, ray_direction, t_min) ; 
0449 }
0450 std::string CSGIntersectComparisonTest::descA() const 
0451 {
0452     std::stringstream ss ; 
0453     ss << " A " << ( a_valid_isect ? DescIsect(a_isect, a_pos, a_sd) : "MISS" ) ;     
0454     std::string s = ss.str();
0455     return s ; 
0456 }
0457 std::string CSGIntersectComparisonTest::descB() const 
0458 {
0459     std::stringstream ss ; 
0460     ss << " B " << ( b_valid_isect ? DescIsect(b_isect, b_pos, b_sd) : "MISS" ) ;     
0461     std::string s = ss.str();
0462     return s ; 
0463 }
0464 std::string CSGIntersectComparisonTest::descFull() const
0465 {
0466     std::stringstream ss ; 
0467     ss << descRay() << std::endl 
0468        << descA() << std::endl 
0469        << descB() << std::endl 
0470        << descDiff() ; 
0471     std::string s = ss.str();
0472     return s ; 
0473 }
0474 
0475 std::string CSGIntersectComparisonTest::desc_() const
0476 {
0477     std::stringstream ss ; 
0478     ss << descRay() << descA() << descDiff() ; 
0479     std::string s = ss.str();
0480     return s ; 
0481 }
0482 std::string CSGIntersectComparisonTest::desc() const
0483 {
0484     return FULL ? descFull() : desc_() ; 
0485 }
0486 
0487 
0488 std::string CSGIntersectComparisonTest::Desc(const float& v) // static 
0489 {
0490     std::stringstream ss ; 
0491     ss <<  " " << std::fixed << std::setw(7) << std::setprecision(2) << v ; 
0492     std::string s = ss.str();
0493     return s ; 
0494 }
0495 std::string CSGIntersectComparisonTest::DescRay(const float3& o, const float3& v, const float t_min ) // static 
0496 {
0497     std::stringstream ss ; 
0498     ss 
0499        << "("
0500        << Desc(o.x) 
0501        << Desc(o.y) 
0502        << Desc(o.z)
0503        << ";"
0504        << Desc(v.x) 
0505        << Desc(v.y) 
0506        << Desc(v.z)
0507        << ";"
0508        << Desc(t_min)
0509        << ")"
0510        ;
0511     std::string s = ss.str();
0512     return s ; 
0513 }
0514 std::string CSGIntersectComparisonTest::DescIsect(const float4& isect, const float3& pos, const float sd ) // static 
0515 {
0516     std::stringstream ss ; 
0517     ss 
0518        << "("
0519        << Desc(isect.x) 
0520        << Desc(isect.y) 
0521        << Desc(isect.z)
0522        << Desc(isect.w)
0523        << ";"
0524        << Desc(pos.x) 
0525        << Desc(pos.y) 
0526        << Desc(pos.z)
0527        << ";"
0528        << std::scientific << sd 
0529        << ")"
0530        ;
0531     std::string s = ss.str();
0532     return s ; 
0533 }
0534 std::string CSGIntersectComparisonTest::Desc(const float3& v) // static 
0535 {
0536     std::stringstream ss ; 
0537     ss 
0538        << "("
0539        << Desc(v.x) 
0540        << Desc(v.y) 
0541        << Desc(v.z) 
0542        << ")"
0543        ;
0544     std::string s = ss.str();
0545     return s ; 
0546 }
0547 std::string CSGIntersectComparisonTest::Desc(const float4& v) // static 
0548 {
0549     std::stringstream ss ; 
0550     ss 
0551        << "("
0552        << Desc(v.x) 
0553        << Desc(v.y) 
0554        << Desc(v.z) 
0555        << Desc(v.w) 
0556        << ")"
0557        ;
0558     std::string s = ss.str();
0559     return s ; 
0560 }
0561 void CSGIntersectComparisonTest::scan(int axis)
0562 {
0563     float a_mn = mn[axis]*1.2f ; 
0564     float a_mx = mx[axis]*1.2f ; 
0565     float a_st = (a_mx - a_mn)/float(num) ;   
0566 
0567     for(float a=a_mn ; a <= a_mx ; a += a_st )
0568     {
0569         oo[axis] = a ; 
0570         intersect(); 
0571     }
0572 }
0573 
0574 unsigned CSGIntersectComparisonTest::OtherAxis(unsigned h, unsigned v) // static
0575 {
0576     assert( h != v ); 
0577     assert( h < 3 ); 
0578     assert( v < 3 ); 
0579     // identify the other axis 
0580     unsigned o = 0u ; 
0581     if( h == 0u && v == 1u ) o = 2u ; 
0582     if( h == 0u && v == 2u ) o = 1u ; 
0583     if( h == 1u && v == 2u ) o = 0u ; 
0584     if( v == 0u && h == 1u ) o = 2u ; 
0585     if( v == 0u && h == 2u ) o = 1u ; 
0586     if( v == 1u && h == 2u ) o = 0u ; 
0587     return o ; 
0588 }
0589 
0590 void CSGIntersectComparisonTest::random2D()
0591 {
0592     for(unsigned i=0 ; i < num ; i++ )
0593     {
0594         random2D_ray_origin();
0595         random2D_ray_direction();
0596         intersect(); 
0597     }
0598 }
0599 void CSGIntersectComparisonTest::random2D_fixed_origin()
0600 {
0601     for(unsigned i=0 ; i < num ; i++ )
0602     {
0603         random2D_ray_direction();
0604         intersect(); 
0605     }
0606 }
0607 
0608 void CSGIntersectComparisonTest::random2D_ray_origin()
0609 {
0610     double u0 = rng() ; 
0611     double u1 = rng() ; 
0612     float ah = h0 + u0*(h1 - h0 ); 
0613     float av = v0 + u1*(v1 - v0 ); 
0614     float ao = (o0 + o1)/2.f  ; 
0615     oo[h] = ah ; 
0616     oo[v] = av ; 
0617     oo[o] = ao ; 
0618 }
0619 void CSGIntersectComparisonTest::random2D_ray_direction()
0620 {
0621     double phi, sinPhi, cosPhi ; 
0622 
0623     double u2 = rng() ; 
0624     phi = 2.*M_PIf*u2 ;     // azimuthal 0->2pi 
0625     ssincos(phi,sinPhi,cosPhi);  
0626 
0627     vv[h] = cosPhi ; 
0628     vv[v] = sinPhi ; 
0629     vv[o] = 0.f ; 
0630 }
0631 
0632 
0633 void CSGIntersectComparisonTest::random3D()
0634 {
0635     for(unsigned i=0 ; i < num ; i++ )
0636     {
0637         random3D_ray_origin();
0638         random3D_ray_direction();
0639         intersect(); 
0640     }
0641 }
0642 
0643 void CSGIntersectComparisonTest::loaded()
0644 {
0645     assert( rerun ); 
0646     LOG(info) << " rerun " << rerun->sstr() ; 
0647     num = rerun->shape[0] ; 
0648     for(unsigned i=0 ; i < num ; i++ )
0649     {
0650         const quad4& st = rr[i] ; 
0651         LoadSimtrace( st, t_min, ray_origin, ray_direction ); 
0652         intersect(); 
0653     }
0654 }
0655 
0656 void CSGIntersectComparisonTest::random3D_ray_origin()
0657 {
0658     double u0 = rng() ; 
0659     double u1 = rng() ; 
0660     double u2 = rng() ; 
0661 
0662     oo[X] = x0 + u0*(x1 - x0 ); 
0663     oo[Y] = y0 + u1*(y1 - y0 );
0664     oo[Z] = z0 + u2*(z1 - z0 );
0665 }
0666 void CSGIntersectComparisonTest::random3D_ray_direction()
0667 {
0668     double phi, sinPhi, cosPhi  ;
0669     double cosTheta, sinTheta ;  
0670 
0671     double u3 = rng() ; 
0672     double u4 = rng() ; 
0673 
0674     cosTheta = u3 ; 
0675     sinTheta = sqrtf(1.0-cosTheta*cosTheta);
0676 
0677     phi = 2.*M_PIf*u4 ;     // azimuthal 0->2pi 
0678     ssincos(phi,sinPhi,cosPhi);  
0679 
0680     vv[X] = sinTheta * cosPhi  ; 
0681     vv[Y] = sinTheta * sinPhi  ; 
0682     vv[Z] = cosTheta  ; 
0683 }
0684 
0685 void CSGIntersectComparisonTest::expected_miss()
0686 {
0687     ray_origin = make_float3( 110.f, 0.f, 40.f ); 
0688     ray_direction = normalize(make_float3(0.993f,0.f, 0.119f)) ; 
0689     t_min = 0.f ; 
0690     intersect(); 
0691 }
0692 void CSGIntersectComparisonTest::expected_hit()
0693 {
0694     ray_origin    = make_float3( 0.f, 0.f, 0.f ); 
0695     ray_direction = normalize(make_float3( 1.f, 1.f, 1.f) ); 
0696     intersect(); 
0697 }
0698 void CSGIntersectComparisonTest::attempt_to_tickle_axial_issue()
0699 {
0700     ray_origin.z = -100.f ; 
0701     ray_origin.x = -264.f ; 
0702     random2D_fixed_origin() ; 
0703 }
0704 
0705 bool CSGIntersectComparisonTest::match(const char* q) const 
0706 {
0707     return strcmp(METHOD, q) == 0 ; 
0708 }
0709 void CSGIntersectComparisonTest::method()
0710 {
0711     LOG(info) << " METHOD " << METHOD ; 
0712 
0713     if(match("scanX"))         scan(X) ; 
0714     if(match("scanY"))         scan(Y) ; 
0715     if(match("scanZ"))         scan(Z) ; 
0716     if(match("random2D"))      random2D() ; 
0717     if(match("random3D"))      random3D() ; 
0718     if(match("expected_miss")) expected_miss() ; 
0719     if(match("expected_hit"))  expected_hit() ; 
0720     if(match("loaded"))        loaded() ; 
0721     if(match("intersect"))     intersect() ; 
0722 }
0723 
0724 bool CSGIntersectComparisonTest::is_intersect() const 
0725 {
0726     return match("intersect") ; 
0727 }
0728 
0729 
0730 int main(int argc, char** argv)
0731 {
0732     OPTICKS_LOG(argc, argv); 
0733 
0734     float radius = SSys::getenvfloat("RADIUS", 264.f)  ; 
0735     float hz = SSys::getenvfloat("HZ", 0.15f ); 
0736     float z2 = hz ; 
0737     float z1 = -hz ; 
0738     CSGNode a_nd = CSGNode::OldCylinder( radius, z1, z2 ) ; 
0739     CSGNode b_nd = CSGNode::Cylinder(    radius, z1, z2 ) ; 
0740     CSGNode* a = &a_nd ; 
0741     CSGNode* b = &b_nd ; 
0742 
0743 
0744     CSGIntersectComparisonTest t(a, b); 
0745     if(t.rerun == nullptr) return 0 ; 
0746 
0747     t.method();     
0748     t.save(); 
0749 
0750     return 0 ; 
0751 }
0752 
0753 
0754