Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #if defined(__CUDACC__) || defined(__CUDABE__)
0002 #else
0003 
0004 #include <iostream>
0005 #include <sstream>
0006 #include <iomanip>
0007 
0008 #include "scuda.h"
0009 #include "sgeomtools.h"
0010 #include "SThetaCut.hh"
0011 #include "SPhiCut.hh"
0012 #include "OpticksCSG.h"
0013 #include "SLOG.hh"
0014 
0015 #include "CSGNode.h"
0016 
0017 
0018 //const float CSGNode::UNBOUNDED_DEFAULT_EXTENT = 100.f ;
0019 const float CSGNode::UNBOUNDED_DEFAULT_EXTENT = 0.f ;
0020 
0021 
0022 bool CSGNode::IsDiff( const CSGNode& a , const CSGNode& b )  // static
0023 {
0024     return false ;
0025 }
0026 
0027 std::string CSGNode::Addr(unsigned repeatIdx, unsigned primIdx, unsigned partIdxRel ) // static
0028 {
0029     int wid = 10 ;
0030     std::stringstream ss ;
0031     ss
0032         << std::setw(2) << std::setfill('0') << repeatIdx
0033         << "/"
0034         << std::setw(3) << std::setfill('0') << primIdx
0035         << "/"
0036         << std::setw(3) << std::setfill('0') << partIdxRel
0037         ;
0038     std::string s = ss.str();
0039     std::stringstream tt ;
0040     tt << std::setw(wid) << s ;
0041     std::string t = tt.str();
0042     return t ;
0043 }
0044 
0045 std::string CSGNode::Desc(const float* fval, int numval, int wid, int prec ) // static
0046 {
0047     std::stringstream ss ;
0048     for(int p=0 ; p < numval ; p++)
0049         ss << std::fixed << std::setw(wid) << std::setprecision(prec) << *(fval+p) << " "  ;
0050     std::string s = ss.str();
0051     return s ;
0052 }
0053 
0054 std::string CSGNode::desc() const
0055 {
0056     const float* aabb = AABB();
0057     unsigned trIdx = gtransformIdx();
0058     bool compound = is_compound();
0059 
0060     int subNum_ = compound ? subNum() : -1  ;
0061     int subOffset_ = compound ? subOffset() : -1  ;
0062 
0063     std::stringstream ss ;
0064     ss
0065         << "CSGNode "
0066         << std::setw(5) << index()
0067         << " "
0068         << brief()
0069         << " aabb: " << Desc( aabb, 6, 7, 1 )
0070         << " trIdx: " << std::setw(5) << trIdx
0071         << " subNum: " << std::setw(3) << subNum_
0072         << " subOffset:: " << std::setw(3) << subOffset_
0073         ;
0074 
0075     std::string s = ss.str();
0076     return s ;
0077 }
0078 
0079 std::string CSGNode::tag() const
0080 {
0081     return CSG::Tag((OpticksCSG_t)typecode()) ;
0082 }
0083 
0084 
0085 std::string CSGNode::brief() const
0086 {
0087     std::stringstream ss ;
0088     ss
0089         << ( is_complement() ? "!" : " " )
0090         << tag()
0091         ;
0092     std::string s = ss.str();
0093     return s ;
0094 }
0095 
0096 
0097 
0098 void CSGNode::Dump(const CSGNode* n_, unsigned ni, const char* label)
0099 {
0100     std::cout << "CSGNode::Dump ni " << ni << " " ;
0101     if(label) std::cout << label ;
0102     std::cout << std::endl ;
0103 
0104     for(unsigned i=0 ; i < ni ; i++)
0105     {
0106         const CSGNode* n = n_ + i ;
0107         std::cout << "(" << i << ")" << std::endl ;
0108         std::cout
0109             << " node.q0.f.xyzw ( "
0110             << std::setw(10) << std::fixed << std::setprecision(3) << n->q0.f.x
0111             << std::setw(10) << std::fixed << std::setprecision(3) << n->q0.f.y
0112             << std::setw(10) << std::fixed << std::setprecision(3) << n->q0.f.z
0113             << std::setw(10) << std::fixed << std::setprecision(3) << n->q0.f.w
0114             << " ) "
0115             << std::endl
0116             << " node.q1.f.xyzw ( "
0117             << std::setw(10) << std::fixed << std::setprecision(3) << n->q1.f.x
0118             << std::setw(10) << std::fixed << std::setprecision(3) << n->q1.f.y
0119             << std::setw(10) << std::fixed << std::setprecision(3) << n->q1.f.z
0120             << std::setw(10) << std::fixed << std::setprecision(3) << n->q1.f.w
0121             << " ) "
0122             << std::endl
0123             << " node.q2.f.xyzw ( "
0124             << std::setw(10) << std::fixed << std::setprecision(3) << n->q2.f.x
0125             << std::setw(10) << std::fixed << std::setprecision(3) << n->q2.f.y
0126             << std::setw(10) << std::fixed << std::setprecision(3) << n->q2.f.z
0127             << std::setw(10) << std::fixed << std::setprecision(3) << n->q2.f.w
0128             << " ) "
0129             << std::endl
0130             << " node.q3.f.xyzw ( "
0131             << std::setw(10) << std::fixed << std::setprecision(3) << n->q3.f.x
0132             << std::setw(10) << std::fixed << std::setprecision(3) << n->q3.f.y
0133             << std::setw(10) << std::fixed << std::setprecision(3) << n->q3.f.z
0134             << std::setw(10) << std::fixed << std::setprecision(3) << n->q3.f.w
0135             << " ) "
0136             << std::endl
0137             ;
0138 
0139         std::cout
0140             << " node.q0.i.xyzw ( "
0141             << std::setw(10) << n->q0.i.x
0142             << std::setw(10) << n->q0.i.y
0143             << std::setw(10) << n->q0.i.z
0144             << std::setw(10) << n->q0.i.w
0145             << " ) "
0146             << std::endl
0147             << " node.q1.i.xyzw ( "
0148             << std::setw(10) << n->q1.i.x
0149             << std::setw(10) << n->q1.i.y
0150             << std::setw(10) << n->q1.i.z
0151             << std::setw(10) << n->q1.i.w
0152             << " ) "
0153             << std::endl
0154             << " node.q2.i.xyzw ( "
0155             << std::setw(10) << n->q2.i.x
0156             << std::setw(10) << n->q2.i.y
0157             << std::setw(10) << n->q2.i.z
0158             << std::setw(10) << n->q2.i.w
0159             << " ) "
0160             << std::endl
0161             << " node.q3.i.xyzw ( "
0162             << std::setw(10) << n->q3.i.x
0163             << std::setw(10) << n->q3.i.y
0164             << std::setw(10) << n->q3.i.z
0165             << std::setw(10) << n->q3.i.w
0166             << " ) "
0167             << std::endl
0168             ;
0169     }
0170 }
0171 
0172 
0173 
0174 CSGNode CSGNode::Union(){         return CSGNode::BooleanOperator(CSG_UNION,-1) ; }  // static
0175 CSGNode CSGNode::Intersection(){  return CSGNode::BooleanOperator(CSG_INTERSECTION,-1) ; }
0176 CSGNode CSGNode::Difference(){    return CSGNode::BooleanOperator(CSG_DIFFERENCE,-1) ; }
0177 
0178 /**
0179 CSGNode::BooleanOperator
0180 -------------------------
0181 
0182 * num_sub is normally -1, for standard boolean trees
0183 * num_sub > 0 is used for compound "list" nodes : a more efficient approach
0184   avoid tree overheads used for some complex solids
0185 
0186 **/
0187 
0188 CSGNode CSGNode::BooleanOperator(unsigned op, int num_sub)   // static
0189 {
0190     assert( CSG::IsOperator((OpticksCSG_t)op) );
0191     CSGNode nd = {} ;
0192     nd.setTypecode(op) ;
0193     if( num_sub > 0 )
0194     {
0195         nd.setSubNum(num_sub);
0196     }
0197     return nd ;
0198 }
0199 
0200 CSGNode CSGNode::Overlap(      int num_sub, int sub_offset){ return CSGNode::ListHeader( CSG_OVERLAP, num_sub, sub_offset ); }
0201 CSGNode CSGNode::Contiguous(   int num_sub, int sub_offset){ return CSGNode::ListHeader( CSG_CONTIGUOUS, num_sub, sub_offset ); }
0202 CSGNode CSGNode::Discontiguous(int num_sub, int sub_offset){ return CSGNode::ListHeader( CSG_DISCONTIGUOUS, num_sub, sub_offset ); }
0203 
0204 CSGNode CSGNode::ListHeader(unsigned type, int num_sub, int sub_offset )   // static
0205 {
0206     CSGNode nd = {} ;
0207     switch(type)
0208     {
0209         case CSG_OVERLAP:       nd.setTypecode(CSG_OVERLAP)       ; break ;
0210         case CSG_CONTIGUOUS:    nd.setTypecode(CSG_CONTIGUOUS)    ; break ;
0211         case CSG_DISCONTIGUOUS: nd.setTypecode(CSG_DISCONTIGUOUS) ; break ;
0212         default:   assert(0)  ;
0213     }
0214     if(num_sub > 0)
0215     {
0216         nd.setSubNum(num_sub);
0217     }
0218     if(sub_offset > 0)
0219     {
0220         nd.setSubOffset(sub_offset);
0221     }
0222     return nd ;
0223 }
0224 
0225 
0226 
0227 bool CSGNode::is_compound() const
0228 {
0229     return CSG::IsCompound((OpticksCSG_t)typecode()) ;
0230 }
0231 bool CSGNode::is_operator() const
0232 {
0233     unsigned tc = typecode();
0234     return CSG::IsOperator((OpticksCSG_t)tc) ;
0235 }
0236 bool CSGNode::is_intersection() const
0237 {
0238     unsigned tc = typecode();
0239     return CSG::IsIntersection((OpticksCSG_t)tc) ;
0240 }
0241 bool CSGNode::is_union() const
0242 {
0243     unsigned tc = typecode();
0244     return CSG::IsUnion((OpticksCSG_t)tc) ;
0245 }
0246 bool CSGNode::is_difference() const
0247 {
0248     unsigned tc = typecode();
0249     return CSG::IsDifference((OpticksCSG_t)tc) ;
0250 }
0251 bool CSGNode::is_zero() const
0252 {
0253     unsigned tc = typecode();
0254     return CSG::IsZero((OpticksCSG_t)tc)  ;
0255 }
0256 bool CSGNode::is_primitive() const
0257 {
0258     unsigned tc = typecode();
0259     return CSG::IsPrimitive((OpticksCSG_t)tc)  ;
0260 }
0261 bool CSGNode::is_complemented_primitive() const
0262 {
0263     return is_complement() && is_primitive() ;
0264 }
0265 
0266 
0267 
0268 
0269 
0270 
0271 
0272 /**
0273 CSGNode::AncestorTypeMask
0274 ---------------------------
0275 
0276 *partIdxRel* is the zero based node index, zero corresponding to root
0277 
0278 This iterates up the node tree starting from the parent
0279 of the node identified by *partIdxRel* using complete binary tree arithemetic.
0280 The bitwise-or of the typemasks of the ancestors is returned.
0281 When starting from a leaf node this will return the bitwise-or of its
0282 ancestors operator types.
0283 
0284 Note that as this only goes upwards in the tree it can be used
0285 during tree creation/convertion, eg from CSG_GGeo_Convert::convertPrim.
0286 Of course the CSGNode identified by *partIdxRel* MUST already exist.
0287 
0288 **/
0289 
0290 unsigned CSGNode::AncestorTypeMask( const CSGNode* root,  unsigned partIdxRel, bool dump  ) // static
0291 {
0292     unsigned atm = 0u ;
0293 
0294     int parentIdxRel = ((partIdxRel + 1) >> 1) - 1 ;   // make 1-based, bitshift up tree, return to 0-based
0295 
0296     while( parentIdxRel > -1 )
0297     {
0298         const CSGNode* p = root + parentIdxRel ;
0299 
0300         atm |= p->typemask() ;  // NB typemask NOT typecode to allow meaningful bitwise-ORing
0301 
0302         if(dump) std::cout << std::setw(3) << parentIdxRel << " " << p->desc() << std::endl ;
0303 
0304         parentIdxRel = ((parentIdxRel + 1) >> 1) - 1 ;
0305     }
0306 
0307     return atm ;
0308 }
0309 
0310 
0311 /**
0312 CSGNode::Depth
0313 ----------------
0314 
0315 Return complete binary tree depth from 0-based node index (aka *partIdxRel*) see CSGNodeTest/test_Depth::
0316 
0317      partIdxRel    0 partIdxRel+1 (dec)    1 (bin) 00000000000000000000000000000001 depth    0
0318      partIdxRel    1 partIdxRel+1 (dec)    2 (bin) 00000000000000000000000000000010 depth    1
0319      partIdxRel    2 partIdxRel+1 (dec)    3 (bin) 00000000000000000000000000000011 depth    1
0320      partIdxRel    3 partIdxRel+1 (dec)    4 (bin) 00000000000000000000000000000100 depth    2
0321      partIdxRel    4 partIdxRel+1 (dec)    5 (bin) 00000000000000000000000000000101 depth    2
0322      partIdxRel    5 partIdxRel+1 (dec)    6 (bin) 00000000000000000000000000000110 depth    2
0323      partIdxRel    6 partIdxRel+1 (dec)    7 (bin) 00000000000000000000000000000111 depth    2
0324      partIdxRel    7 partIdxRel+1 (dec)    8 (bin) 00000000000000000000000000001000 depth    3
0325      partIdxRel    8 partIdxRel+1 (dec)    9 (bin) 00000000000000000000000000001001 depth    3
0326      partIdxRel    9 partIdxRel+1 (dec)   10 (bin) 00000000000000000000000000001010 depth    3
0327      partIdxRel   10 partIdxRel+1 (dec)   11 (bin) 00000000000000000000000000001011 depth    3
0328      partIdxRel   11 partIdxRel+1 (dec)   12 (bin) 00000000000000000000000000001100 depth    3
0329      partIdxRel   12 partIdxRel+1 (dec)   13 (bin) 00000000000000000000000000001101 depth    3
0330      partIdxRel   13 partIdxRel+1 (dec)   14 (bin) 00000000000000000000000000001110 depth    3
0331      partIdxRel   14 partIdxRel+1 (dec)   15 (bin) 00000000000000000000000000001111 depth    3
0332      partIdxRel   15 partIdxRel+1 (dec)   16 (bin) 00000000000000000000000000010000 depth    4
0333      partIdxRel   16 partIdxRel+1 (dec)   17 (bin) 00000000000000000000000000010001 depth    4
0334      partIdxRel   17 partIdxRel+1 (dec)   18 (bin) 00000000000000000000000000010010 depth    4
0335 
0336 **/
0337 
0338 unsigned CSGNode::Depth( unsigned partIdxRel ) // static
0339 {
0340     int parentIdxRel = ((partIdxRel + 1) >> 1) - 1 ;   // make 1-based, bitshift up tree, return to 0-based
0341     unsigned depth = 0 ;
0342     while( parentIdxRel > -1 )
0343     {
0344         parentIdxRel = ((parentIdxRel + 1) >> 1) - 1 ;
0345         depth += 1 ;
0346     }
0347     return depth ;
0348 }
0349 
0350 
0351 
0352 
0353 bool CSGNode::IsOnlyUnionMask( unsigned atm )  // static
0354 {
0355      return atm == CSG::Mask(CSG_UNION) ;
0356 }
0357 
0358 bool CSGNode::IsOnlyIntersectionMask( unsigned atm )  // static
0359 {
0360      return atm == CSG::Mask(CSG_INTERSECTION) ;
0361 }
0362 
0363 bool CSGNode::IsOnlyDifferenceMask( unsigned atm )  // static
0364 {
0365      return atm == CSG::Mask(CSG_DIFFERENCE) ;
0366 }
0367 
0368 void CSGNode::getYRange(float& y0, float& y1) const
0369 {
0370     unsigned tc = typecode();
0371     if( tc == CSG_BOX3 )
0372     {
0373         float fx, fy, fz, a, b, c ;
0374         getParam( fx, fy, fz, a, b, c );
0375 
0376         y0 = -fy*0.5f ;
0377         y1 =  fy*0.5f ;
0378     }
0379 }
0380 
0381 
0382 /**
0383 CSGNode::setAABBLocal
0384 ----------------------
0385 
0386 CAUTION : currently this is near duplicated in sn::setAABB_LeafFrame
0387 The duplication is because need the bbox for general nudging in sn.h
0388 and also needed for CSGCopy::copyNode
0389 
0390 **/
0391 
0392 void CSGNode::setAABBLocal()
0393 {
0394     unsigned tc = typecode();
0395     if(tc == CSG_SPHERE)
0396     {
0397         float r = radius();
0398         setAABB(  -r, -r, -r,  r, r, r  );
0399     }
0400     else if(tc == CSG_ZSPHERE)
0401     {
0402         float r = radius();
0403         float z1_ = z1();
0404         float z2_ = z2();
0405         assert( z2_ > z1_ );
0406         setAABB(  -r, -r, z1_,  r, r, z2_  );
0407     }
0408     else if( tc == CSG_CONE )
0409     {
0410         float r1, z1, r2, z2, a, b ;
0411         getParam( r1, z1, r2, z2, a, b );
0412         float rmax = fmaxf(r1, r2) ;
0413         setAABB( -rmax, -rmax, z1, rmax, rmax, z2 );
0414     }
0415     else if( tc == CSG_BOX3 )
0416     {
0417         float fx, fy, fz, a, b, c ;
0418         getParam( fx, fy, fz, a, b, c );
0419         setAABB( -fx*0.5f , -fy*0.5f, -fz*0.5f, fx*0.5f , fy*0.5f, fz*0.5f );
0420     }
0421     else if( tc == CSG_CYLINDER || tc == CSG_OLDCYLINDER )
0422     {
0423         float px, py, a, radius, z1, z2 ;
0424         getParam( px, py, a, radius, z1, z2) ;
0425         setAABB( px-radius, py-radius, z1, px+radius, py+radius, z2 );
0426     }
0427     else if( tc == CSG_DISC )
0428     {
0429         float px, py, ir, r, z1, z2 ;
0430         getParam( px, py, ir, r, z1, z2 );
0431         setAABB( px - r , py - r , z1, px + r, py + r, z2 );
0432     }
0433     else if( tc == CSG_HYPERBOLOID )
0434     {
0435         float r0, zf, z1, z2, a, b ;
0436         getParam(r0, zf, z1, z2, a, b ) ;
0437 
0438         assert( z1 < z2 );
0439         const float rr0 = r0*r0 ;
0440         const float z1s = z1/zf ;
0441         const float z2s = z2/zf ;
0442 
0443         const float rr1 = rr0 * ( z1s*z1s + 1.f ) ;
0444         const float rr2 = rr0 * ( z2s*z2s + 1.f ) ;
0445         const float rmx = sqrtf(fmaxf( rr1, rr2 )) ;
0446 
0447         setAABB(  -rmx,  -rmx,  z1,  rmx, rmx, z2 );
0448     }
0449     else if( tc == CSG_TORUS )
0450     {
0451         // ELV selection of torus node needs this despite force triangulation ?
0452         double rmin, rmax, rtor, startPhi_deg, deltaPhi_deg, zero ;
0453         getParam_(rmin, rmax, rtor, startPhi_deg, deltaPhi_deg, zero) ;
0454 
0455         double rext = rtor+rmax ;
0456         double rint = rtor-rmax ;
0457         double startPhi = startPhi_deg/180.*M_PI ;
0458         double deltaPhi = deltaPhi_deg/180.*M_PI ;
0459         double2 pmin ;
0460         double2 pmax ;
0461         sgeomtools::DiskExtent(rint, rext, startPhi, deltaPhi, pmin, pmax );
0462 
0463         setAABB( pmin.x, pmin.y, -rmax, pmax.x, pmax.y, +rmax );
0464 
0465     }
0466     else if( tc == CSG_UNION || tc == CSG_INTERSECTION || tc == CSG_DIFFERENCE )
0467     {
0468         setAABB( 0.f );
0469     }
0470     else if( tc == CSG_CONTIGUOUS || tc == CSG_DISCONTIGUOUS )
0471     {
0472         // cannot define bbox of list header nodes without combining bbox of all the subs
0473         // so have to defer setting the bbox until all the subs are converted
0474         setAABB( 0.f );
0475     }
0476     else if( tc == CSG_NOTSUPPORTED )
0477     {
0478         setAABB( 0.f );
0479         // HMM: NEED TO USE THE TRIANGLES TO SET THE AABB ?
0480     }
0481     else if( tc == CSG_HALFSPACE )
0482     {
0483         setAABB( 0.f );
0484     }
0485     else if( tc == CSG_CUTCYLINDER )
0486     {
0487         setAABB( UNBOUNDED_DEFAULT_EXTENT );
0488     }
0489     else if( tc == CSG_ZERO )
0490     {
0491         setAABB( UNBOUNDED_DEFAULT_EXTENT );
0492     }
0493     else if( tc == CSG_PHICUT )
0494     {
0495         setAABB( UNBOUNDED_DEFAULT_EXTENT );
0496     }
0497     else if( tc == CSG_THETACUT )
0498     {
0499         setAABB( UNBOUNDED_DEFAULT_EXTENT );
0500     }
0501     else
0502     {
0503         LOG(fatal) << " not implemented for tc " << tc << " CSG::Name(tc) " << CSG::Name(tc) ;
0504         assert(0);
0505         setAABB( 0.f );
0506     }
0507 }
0508 
0509 
0510 
0511 CSGNode CSGNode::Zero()  // static
0512 {
0513     CSGNode nd = {} ;
0514     nd.setAABB(  -0.f, -0.f, -0.f,  0.f, 0.f, 0.f  );   // HMM: is negated zero -0.f ever used for anything ?
0515     nd.setTypecode(CSG_ZERO) ;
0516     return nd ;
0517 }
0518 CSGNode CSGNode::Sphere(float radius)  // static
0519 {
0520     assert( radius > 0.f);
0521     CSGNode nd = {} ;
0522     nd.setParam( 0.f, 0.f, 0.f, radius,  0.f,  0.f );
0523     nd.setAABB(  -radius, -radius, -radius,  radius, radius, radius  );
0524     nd.setTypecode(CSG_SPHERE) ;
0525     return nd ;
0526 }
0527 CSGNode CSGNode::ZSphere(float radius, float z1, float z2)  // static
0528 {
0529     assert( radius > 0.f);
0530     assert( z2 > z1 );
0531     CSGNode nd = {} ;
0532     nd.setParam( 0.f, 0.f, 0.f, radius, z1, z2 );
0533     nd.setAABB(  -radius, -radius, z1,  radius, radius, z2  );
0534     nd.setTypecode(CSG_ZSPHERE) ;
0535     return nd ;
0536 }
0537 
0538 CSGNode CSGNode::Cone(float r1, float z1, float r2, float z2)  // static
0539 {
0540     assert( z2 > z1 );
0541     float rmax = fmaxf(r1, r2) ;
0542     CSGNode nd = {} ;
0543     nd.setParam( r1, z1, r2, z2, 0.f, 0.f ) ;
0544     nd.setAABB( -rmax, -rmax, z1, rmax, rmax, z2 );
0545     nd.setTypecode(CSG_CONE) ;
0546     return nd ;
0547 }
0548 CSGNode CSGNode::OldCone(float r1, float z1, float r2, float z2)  // static
0549 {
0550     CSGNode nd = Cone(r1,z1,r2,z2);
0551     nd.setTypecode(CSG_OLDCONE) ;
0552     return nd ;
0553 }
0554 
0555 
0556 CSGNode CSGNode::Box3(float fullside)  // static
0557 {
0558     return Box3(fullside, fullside, fullside);
0559 }
0560 CSGNode CSGNode::Box3(float fx, float fy, float fz )  // static
0561 {
0562     assert( fx > 0.f );
0563     assert( fy > 0.f );
0564     assert( fz > 0.f );
0565 
0566     CSGNode nd = {} ;
0567     nd.setParam( fx, fy, fz, 0.f, 0.f, 0.f );
0568     nd.setAABB( -fx*0.5f , -fy*0.5f, -fz*0.5f, fx*0.5f , fy*0.5f, fz*0.5f );
0569     nd.setTypecode(CSG_BOX3) ;
0570     return nd ;
0571 }
0572 
0573 CSGNode CSGNode::Cylinder(float radius, float z1, float z2)
0574 {
0575     assert( z2 > z1 );
0576     CSGNode nd = {} ;
0577     nd.setParam( 0.f, 0.f, 0.f, radius, z1, z2)  ;
0578     nd.setAABB( -radius, -radius, z1, +radius, +radius, z2 );
0579     nd.setTypecode(CSG_CYLINDER);
0580     return nd ;
0581 }
0582 
0583 CSGNode CSGNode::OldCylinder(float radius, float z1, float z2)
0584 {
0585     float px = 0.f ;
0586     float py = 0.f ;
0587     CSGNode nd = {} ;
0588     nd.setParam( px, py, 0.f, radius, z1, z2)  ;
0589     nd.setAABB( px-radius, py-radius, z1, px+radius, py+radius, z2 );
0590     nd.setTypecode(CSG_OLDCYLINDER);
0591     return nd ;
0592 }
0593 
0594 CSGNode CSGNode::InfCylinder(float radius, float hz)
0595 {
0596     assert( hz > 0.f );  // need to bound it ?
0597     CSGNode nd = {} ;
0598     nd.setParam( 0.f, 0.f, 0.f, radius, 0.f,0.f)  ;
0599     nd.setAABB( -radius, -radius, -hz,  radius, radius, hz );
0600     nd.setTypecode(CSG_INFCYLINDER);
0601     return nd ;
0602 }
0603 
0604 CSGNode CSGNode::InfPhiCut(float startPhi_pi, float deltaPhi_pi )
0605 {
0606     CSGNode nd = {} ;
0607     SPhiCut::PrepareParam( nd.q0 ,  startPhi_pi, deltaPhi_pi );
0608     nd.setAABB( -100.f,-100.f,-100.f, 100.f, 100.f, 100.f );      // placeholder, hmm how to avoid ?
0609     nd.setTypecode(CSG_PHICUT);
0610     return nd ;
0611 }
0612 
0613 CSGNode CSGNode::InfThetaCut(float startTheta_pi, float deltaTheta_pi )
0614 {
0615     CSGNode nd = {} ;
0616     SThetaCut::PrepareParam( nd.q0, nd.q1, startTheta_pi, deltaTheta_pi );
0617     nd.setAABB( -100.f,-100.f,-100.f, 100.f, 100.f, 100.f );    // HMM: adhoc ?
0618     nd.setTypecode(CSG_THETACUT);
0619     return nd ;
0620 }
0621 
0622 
0623 CSGNode CSGNode::Disc(float px, float py, float ir, float r, float z1, float z2)
0624 {
0625     CSGNode nd = {} ;
0626     nd.setParam( px, py, ir, r, z1, z2 );
0627     nd.setAABB( px - r , py - r , z1, px + r, py + r, z2 );
0628     nd.setTypecode(CSG_DISC);
0629     return nd ;
0630 }
0631 
0632 CSGNode CSGNode::Hyperboloid(float r0, float zf, float z1, float z2) // static
0633 {
0634     assert( z1 < z2 );
0635     const float rr0 = r0*r0 ;
0636     const float z1s = z1/zf ;
0637     const float z2s = z2/zf ;
0638 
0639     const float rr1 = rr0 * ( z1s*z1s + 1.f ) ;
0640     const float rr2 = rr0 * ( z2s*z2s + 1.f ) ;
0641     const float rmx = sqrtf(fmaxf( rr1, rr2 )) ;
0642 
0643     CSGNode nd = {} ;
0644     nd.setParam(r0, zf, z1, z2, 0.f, 0.f ) ;
0645     nd.setAABB(  -rmx,  -rmx,  z1,  rmx, rmx, z2 );
0646     nd.setTypecode(CSG_HYPERBOLOID) ;
0647     return nd ;
0648 }
0649 
0650 
0651 CSGNode CSGNode::Plane(float nx, float ny, float nz, float d)
0652 {
0653     CSGNode nd = {} ;
0654     nd.setParam(nx, ny, nz, d, 0.f, 0.f ) ;
0655     nd.setTypecode(CSG_PLANE) ;
0656     nd.setAABB( UNBOUNDED_DEFAULT_EXTENT );
0657     return nd ;
0658 }
0659 
0660 CSGNode CSGNode::Slab(float nx, float ny, float nz, float d1, float d2 )
0661 {
0662     CSGNode nd = {} ;
0663     nd.setParam( nx, ny, nz, 0.f, d1, d2 );
0664     nd.setTypecode(CSG_SLAB) ;
0665     nd.setAABB( UNBOUNDED_DEFAULT_EXTENT );
0666     return nd ;
0667 }
0668 
0669 CSGNode CSGNode::HalfSpace(float nx, float ny, float nz, float nw )
0670 {
0671     CSGNode nd = {} ;
0672     nd.setParam( nx, ny, nz, nw, 0, 0 );
0673     nd.setTypecode(CSG_HALFSPACE ) ;
0674     nd.setAABB( 0.f );
0675     return nd ;
0676 }
0677 
0678 CSGNode* CSGNode::HalfCylinder(float nx, float ny, float nz, float nw, float radius, float z0, float z1 )
0679 {
0680     int subNum = 3 ;
0681     CSGNode* nd = new CSGNode[subNum] ;
0682     nd[0] = CSGNode::Intersection() ;
0683     nd[1] = CSGNode::HalfSpace(nx,ny,nz,nw);
0684     nd[2] = CSGNode::Cylinder(radius,z0,z1);
0685     nd[0].setSubNum(subNum);
0686     return nd ;
0687 }
0688 CSGNode* CSGNode::HalfCylinder()
0689 {
0690     float v = 1.f/sqrtf(2.f);
0691     return HalfCylinder(v,v,0.f,0.f,  100.f, -50.f, 50.f);
0692 }
0693 
0694 
0695 /**
0696 CSGNode::MakeDemo
0697 -------------------
0698 
0699 Only the first four chars of the name are used to select the type of node.
0700 
0701 * see CSGMaker for more extensive test node/prim/solid creation
0702 
0703 **/
0704 
0705 CSGNode CSGNode::MakeDemo(const char* name) // static
0706 {
0707     if(strncmp(name, "sphe", 4) == 0) return CSGNode::Sphere(100.f) ;
0708     if(strncmp(name, "zsph", 4) == 0) return CSGNode::ZSphere(100.f, -50.f, 50.f) ;
0709     if(strncmp(name, "cone", 4) == 0) return CSGNode::Cone(150.f, -150.f, 50.f, -50.f) ;
0710     if(strncmp(name, "hype", 4) == 0) return CSGNode::Hyperboloid(100.f, 50.f, -50.f, 50.f) ;
0711     if(strncmp(name, "box3", 4) == 0) return CSGNode::Box3(100.f, 100.f, 100.f) ;
0712     if(strncmp(name, "plan", 4) == 0) return CSGNode::Plane(1.f, 0.f, 0.f, 0.f) ;
0713     if(strncmp(name, "slab", 4) == 0) return CSGNode::Slab(1.f, 0.f, 0.f, -10.f, 10.f ) ;
0714     if(strncmp(name, "cyli", 4) == 0) return CSGNode::Cylinder(   100.f, -50.f, 50.f ) ;
0715     if(strncmp(name, "ocyl", 4) == 0) return CSGNode::OldCylinder(100.f, -50.f, 50.f ) ;
0716     if(strncmp(name, "disc", 4) == 0) return CSGNode::Disc(    0.f, 0.f, 50.f, 100.f, -2.f, 2.f ) ;
0717     if(strncmp(name, "iphi", 4) == 0) return CSGNode::InfPhiCut(0.25f, 0.10f) ;
0718     if(strncmp(name, "ithe", 4) == 0) return CSGNode::InfThetaCut(0.25f, 0.10f ) ;
0719     LOG(fatal) << " not implemented for name " << name ;
0720     assert(0);
0721     return CSGNode::Sphere(1.0);
0722 }
0723 
0724 /**
0725 CSGNode::Make
0726 --------------
0727 
0728 Primary use from CSG_GGeo_Convert::convertNode
0729 
0730 NB not easy to expand to more than 6 params as q1.u.z q1.u.w are otherwise engaged
0731 
0732 **/
0733 
0734 CSGNode CSGNode::Make(unsigned typecode ) // static
0735 {
0736     CSGNode nd = {} ;
0737     nd.setTypecode(typecode) ;
0738     return nd ;
0739 }
0740 
0741 /**
0742 CSGNode::Make
0743 ----------------
0744 
0745 Thought for a while that had a bug causing stray int32 in param6[0]
0746 on compound root nodes... but they are in fact subNum for
0747 the generalized CSG handling.  Nevertheless its still
0748 a good idea to only pass in the float param6 and aabb for primitives.
0749 HMM: EXTERNAL BBOX MAY REQUIRE TO RECONSIDER THIS
0750 
0751 **/
0752 
0753 CSGNode CSGNode::Make(unsigned typecode, const float* param6, const float* aabb ) // static
0754 {
0755     CSGNode nd = {} ;
0756     nd.setTypecode(typecode) ;
0757     if(CSG::IsPrimitive(typecode))
0758     {
0759         if(param6) nd.setParam( param6 );
0760         if(aabb)   nd.setAABB( aabb );
0761     }
0762     return nd ;
0763 }
0764 CSGNode CSGNode::MakeNarrow(unsigned typecode, const double* param6, const double* aabb ) // static
0765 {
0766     CSGNode nd = {} ;
0767     nd.setTypecode(typecode) ;
0768     if(param6) nd.setParam_Narrow( param6 );
0769     if(aabb)   nd.setAABB_Narrow( aabb );
0770     return nd ;
0771 }
0772 
0773 
0774 
0775 
0776 
0777 
0778 
0779 
0780 
0781 
0782 #endif
0783