File indexing completed on 2026-04-09 07:49:41
0001
0002 #include <iostream>
0003 #include <algorithm>
0004 #include <csignal>
0005
0006 #include "glm/glm.hpp"
0007 #include "glm/gtx/string_cast.hpp"
0008 #include <glm/gtx/transform.hpp>
0009 #include <glm/gtc/type_ptr.hpp>
0010
0011 #include "spa.h"
0012 #include "sbb.h"
0013 #include "sxf.h"
0014 #include "scanvas.h"
0015
0016 #include "OpticksCSG.h"
0017 #include "scsg.hh"
0018 #include "snd.hh"
0019 #include "sndtree.h" // using flexible sn.h
0020
0021 #include "st.h" // only st::complete_binary_tree_nodes
0022 #include "stra.h" // transform utilities based on glm
0023
0024
0025
0026 scsg* snd::POOL = nullptr ;
0027 void snd::SetPOOL( scsg* pool ){ POOL = pool ; }
0028 int snd::Level(){ return POOL ? POOL->level : -1 ; }
0029
0030 NPFold* snd::Serialize(){ return POOL ? POOL->serialize() : nullptr ; }
0031 void snd::Import(const NPFold* fold){ assert(POOL) ; POOL->import(fold) ; }
0032 std::string snd::Desc(){ return POOL ? POOL->desc() : "? NO POOL ?" ; }
0033
0034
0035
0036 std::string snd::Brief(int idx)
0037 {
0038 const snd* nd = Get(idx);
0039 return nd ? nd->brief() : "-" ;
0040 }
0041 std::string snd::Brief(const std::vector<int>& nodes)
0042 {
0043 int num_nodes = nodes.size();
0044 std::stringstream ss ;
0045 ss << "snd::Brief num_nodes " << num_nodes << std::endl ;
0046 for(int i=0 ; i < num_nodes ; i++)
0047 {
0048 int idx = nodes[i];
0049 const snd* nd = Get(idx);
0050 assert( nd );
0051 ss << std::setw(2) << i << " : " << nd->brief() << std::endl ;
0052 }
0053 std::string str = ss.str();
0054 return str ;
0055 }
0056
0057 std::string snd::Brief_(const std::vector<snd>& nodes)
0058 {
0059 int num_nodes = nodes.size();
0060 std::stringstream ss ;
0061 ss << "snd::Brief_ num_nodes " << num_nodes << std::endl ;
0062 for(int i=0 ; i < num_nodes ; i++)
0063 {
0064 const snd& nd = nodes[i] ;
0065 ss << std::setw(2) << i << " : " << nd.brief() << std::endl ;
0066 }
0067 std::string str = ss.str();
0068 return str ;
0069 }
0070
0071 const snd* snd::Get(int idx){ return POOL ? POOL->getND(idx) : nullptr ; }
0072 snd* snd::Get_(int idx){ return POOL ? POOL->getND_(idx) : nullptr ; }
0073
0074
0075 int snd::GetMaxDepth( int idx)
0076 {
0077 const snd* nd = Get(idx) ;
0078 return nd ? nd->max_depth() : -1 ;
0079 }
0080 int snd::GetNumNode( int idx)
0081 {
0082 const snd* nd = Get(idx) ;
0083 return nd ? nd->num_node() : -1 ;
0084 }
0085
0086
0087
0088
0089
0090
0091
0092 void snd::GetTypes(std::vector<int>& types, const std::vector<int>& nd_idxs )
0093 {
0094 int num_idx = nd_idxs.size();
0095 for(int i=0 ; i < num_idx ; i++)
0096 {
0097 int idx = nd_idxs[i];
0098 const snd* nd = Get(idx) ;
0099 types.push_back(nd->typecode) ;
0100 }
0101 assert( nd_idxs.size() == types.size() );
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 int snd::GetNodeXForm(int idx)
0118 {
0119 const snd* n = Get(idx);
0120 return n ? n->xform : -1 ;
0121 }
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 void snd::SetNodeXForm(int idx, const glm::tmat4x4<double>& t )
0133 {
0134 snd* nd = Get_(idx);
0135 nd->combineXF(t);
0136 }
0137 void snd::SetNodeXForm(int idx, const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v )
0138 {
0139 snd* nd = Get_(idx);
0140 nd->combineXF(t, v);
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 void snd::setXF(const glm::tmat4x4<double>& t )
0161 {
0162 glm::tmat4x4<double> v = glm::inverse(t) ;
0163 setXF(t, v);
0164 }
0165 void snd::combineXF(const glm::tmat4x4<double>& t )
0166 {
0167 glm::tmat4x4<double> v = glm::inverse(t) ;
0168 combineXF(t, v);
0169 }
0170
0171
0172 void snd::setXF(const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v )
0173 {
0174 if( xform > -1 )
0175 {
0176 if(Level()>-1) std::cout
0177 << "snd::setXF STOMPING"
0178 << " xform " << xform
0179 << std::endl
0180 << stra<double>::Desc(t,v, "t", "v")
0181 << std::endl
0182 ;
0183 }
0184
0185
0186 sxf xf ;
0187 xf.t = t ;
0188 xf.v = v ;
0189
0190 CheckPOOL("snd::setXForm") ;
0191 xform = POOL->addXF(xf) ;
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 void snd::combineXF( const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v )
0206 {
0207 sxf* current = getXF_();
0208 if(current == nullptr)
0209 {
0210 setXF(t,v);
0211 }
0212 else
0213 {
0214 glm::tmat4x4<double> tt = current->t * t ;
0215 glm::tmat4x4<double> vv = v * current->v ;
0216
0217 current->t = tt ;
0218 current->v = vv ;
0219 }
0220 }
0221
0222
0223 const sxf* snd::GetXF(int idx)
0224 {
0225 const snd* n = Get(idx);
0226 return n ? n->getXF() : nullptr ;
0227 }
0228 sxf* snd::GetXF_(int idx)
0229 {
0230 snd* n = Get_(idx);
0231 return n ? n->getXF_() : nullptr ;
0232 }
0233
0234 const sxf* snd::getXF() const
0235 {
0236 CheckPOOL("snd::getXF") ;
0237 return POOL->getXF(xform) ;
0238 }
0239 sxf* snd::getXF_()
0240 {
0241 CheckPOOL("snd::getXF_") ;
0242 return POOL->getXF_(xform) ;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256 void snd::NodeTransformProduct(int idx, glm::tmat4x4<double>& t, glm::tmat4x4<double>& v, bool reverse, std::ostream* out)
0257 {
0258 std::vector<int> nds ;
0259 Ancestors(idx, nds);
0260 nds.push_back(idx);
0261 int num_nds = nds.size();
0262
0263 if(out)
0264 {
0265 *out
0266 << std::endl
0267 << "snd::NodeTransformProduct"
0268 << " idx " << idx
0269 << " reverse " << reverse
0270 << " num_nds " << num_nds
0271 << std::endl
0272 ;
0273 }
0274
0275 glm::tmat4x4<double> tp(1.);
0276 glm::tmat4x4<double> vp(1.);
0277
0278 for(int i=0 ; i < num_nds ; i++ )
0279 {
0280 int j = num_nds - 1 - i ;
0281 int ii = nds[reverse ? j : i] ;
0282 int jj = nds[reverse ? i : j] ;
0283
0284 const sxf* ixf = GetXF(ii) ;
0285 const sxf* jxf = GetXF(jj) ;
0286
0287 if(out)
0288 {
0289 *out
0290 << " i " << i
0291 << " j " << j
0292 << " ii " << ii
0293 << " jj " << jj
0294 << " ixf " << ( ixf ? "Y" : "N" )
0295 << " jxf " << ( jxf ? "Y" : "N" )
0296 << std::endl
0297 ;
0298
0299 if(ixf) *out << stra<double>::Desc( ixf->t, ixf->v, "(ixf.t)", "(ixf.v)" ) << std::endl ;
0300 if(jxf) *out << stra<double>::Desc( jxf->t, jxf->v, "(jxf.t)", "(jxf.v)" ) << std::endl ;
0301 }
0302
0303
0304 if(ixf) tp *= ixf->t ;
0305 if(jxf) vp *= jxf->v ;
0306 }
0307 memcpy( glm::value_ptr(t), glm::value_ptr(tp), sizeof(glm::tmat4x4<double>) );
0308 memcpy( glm::value_ptr(v), glm::value_ptr(vp), sizeof(glm::tmat4x4<double>) );
0309
0310 if(out) *out << stra<double>::Desc( tp, vp , "tp", "vp" ) << std::endl ;
0311 }
0312
0313 std::string snd::DescNodeTransformProduct(int root, glm::tmat4x4<double>& t, glm::tmat4x4<double>& v, bool reverse)
0314 {
0315 std::stringstream ss ;
0316 ss << "snd::DescNodeTransformProduct" << std::endl ;
0317 NodeTransformProduct( root, t, v, reverse, &ss );
0318 std::string str = ss.str();
0319 return str ;
0320 }
0321
0322
0323 void snd::node_transform_product(glm::tmat4x4<double>& t, glm::tmat4x4<double>& v, bool reverse, std::ostream* out ) const
0324 {
0325 NodeTransformProduct(index, t, v, reverse, out);
0326 }
0327
0328
0329
0330
0331
0332
0333 void snd::SetLabel(int idx, const char* label_ )
0334 {
0335 snd* nd = Get_(idx);
0336 nd->setLabel(label_);
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 void snd::SetLVID(int idx, int lvid)
0351 {
0352 snd* nd = Get_(idx);
0353 nd->setLVID(lvid);
0354 if(nd->is_root()) nd->sibdex = 0 ;
0355
0356 int chk = nd->checktree();
0357 if( chk != 0 )
0358 {
0359 if(Level() > 0 ) std::cerr
0360 << "snd::SetLVID"
0361 << " idx " << idx
0362 << " lvid " << lvid
0363 << " checktree " << chk
0364 << std::endl
0365 << " POOL.desc "
0366 << POOL->desc()
0367 ;
0368 }
0369 assert( chk == 0 );
0370 }
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385 void snd::GetLVID( std::vector<snd>& nds, int lvid )
0386 {
0387 POOL->getLVID(nds, lvid);
0388
0389 int num_nd = nds.size();
0390 assert( num_nd > 0 );
0391 const snd& last = nds[num_nd-1] ;
0392 bool last_expect = last.is_root() ;
0393 if(!last_expect) std::cerr << "snd::GetLVID last_expect " << std::endl ;
0394 assert( last_expect );
0395 }
0396
0397
0398
0399
0400
0401
0402
0403
0404 const snd* snd::GetLVRoot( int lvid )
0405 {
0406 const snd* root = POOL->getLVRoot(lvid);
0407 return root ;
0408 }
0409
0410 int snd::GetLVNumNode( int lvid )
0411 {
0412 const snd* root = GetLVRoot(lvid);
0413 return root ? root->getLVNumNode() : -1 ;
0414 }
0415 int snd::GetLVBinNode( int lvid )
0416 {
0417 const snd* root = GetLVRoot(lvid);
0418 return root ? root->getLVBinNode() : -1 ;
0419 }
0420 int snd::GetLVSubNode( int lvid )
0421 {
0422 const snd* root = GetLVRoot(lvid);
0423 return root ? root->getLVSubNode() : -1 ;
0424 }
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 int snd::getLVNumNode() const
0440 {
0441 int bn = getLVBinNode() ;
0442 int sn = getLVSubNode() ;
0443 return bn + sn ;
0444 }
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455 int snd::getLVBinNode() const
0456 {
0457 int h = max_binary_depth();
0458 return st::complete_binary_tree_nodes( h );
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472 int snd::getLVSubNode() const
0473 {
0474 int constituents = 0 ;
0475 std::vector<int> subs ;
0476 typenodes_(subs, CSG_CONTIGUOUS, CSG_DISCONTIGUOUS, CSG_OVERLAP );
0477 int nsub = subs.size();
0478 for(int i=0 ; i < nsub ; i++)
0479 {
0480 int idx = subs[i] ;
0481 const snd* nd = Get(idx);
0482 assert( nd->typecode == CSG_CONTIGUOUS || nd->typecode == CSG_DISCONTIGUOUS );
0483 constituents += nd->num_child ;
0484 }
0485 return constituents ;
0486 }
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 void snd::GetLVNodesComplete(std::vector<const snd*>& nds, int lvid)
0501 {
0502 const snd* root = GetLVRoot(lvid);
0503 root->getLVNodesComplete(nds);
0504
0505 int level = Level();
0506
0507 if(level > 0 && nds.size() > 8 )
0508 {
0509 std::cout
0510 << "snd::GetLVNodesComplete"
0511 << " lvid " << lvid
0512 << " level " << level
0513 << std::endl
0514 << root->rbrief()
0515 << std::endl
0516 << root->render(3)
0517 ;
0518 }
0519 }
0520
0521
0522
0523
0524
0525
0526
0527
0528 void snd::getLVNodesComplete(std::vector<const snd*>& nds) const
0529 {
0530 int bn = getLVBinNode();
0531 int sn = getLVSubNode();
0532 int numParts = bn + sn ;
0533 nds.resize(numParts);
0534
0535 assert( sn == 0 );
0536
0537 GetLVNodesComplete_r( nds, this, 0 );
0538 }
0539
0540
0541 void snd::GetLVNodesComplete_r(std::vector<const snd*>& nds, const snd* nd, int idx)
0542 {
0543 assert( idx < int(nds.size()) );
0544 nds[idx] = nd ;
0545
0546 if( nd->num_child > 0 && nd->is_listnode() == false )
0547 {
0548 assert( nd->num_child == 2 ) ;
0549 int ch = nd->first_child ;
0550 for(int i=0 ; i < nd->num_child ; i++)
0551 {
0552 const snd* child = snd::Get(ch) ;
0553 assert( child->index == ch );
0554
0555 int cidx = 2*idx + 1 + i ;
0556
0557 GetLVNodesComplete_r(nds, child, cidx );
0558
0559 ch = child->next_sibling ;
0560 }
0561 }
0562 }
0563
0564
0565
0566
0567 std::string snd::Desc( int idx){ return POOL ? POOL->descND(idx) : "-" ; }
0568 std::string snd::DescParam( int idx){ return POOL ? POOL->descPA(idx) : "-" ; }
0569 std::string snd::DescXForm( int idx){ return POOL ? POOL->descXF(idx) : "-" ; }
0570 std::string snd::DescAABB( int idx){ return POOL ? POOL->descBB(idx) : "-" ; }
0571
0572
0573 int snd::Add(const snd& nd)
0574 {
0575 assert( POOL && "snd::Add MUST SET snd::SetPOOL to scsg instance first" );
0576 return POOL->addND(nd);
0577 }
0578
0579
0580 bool snd::is_listnode() const
0581 {
0582 return CSG::IsList(typecode);
0583 }
0584
0585 std::string snd::tag() const
0586 {
0587 return typecode < 0 ? "negative-typecode-ERR" : CSG::Tag(typecode) ;
0588 }
0589
0590 int snd::idx() const { return index ; }
0591
0592
0593 std::string snd::brief() const
0594 {
0595 char l0 = label[0] == '\0' ? '-' : label[0] ;
0596 int w = 5 ;
0597 std::stringstream ss ;
0598 ss
0599 << l0
0600 << " ix:" << std::setw(w) << index
0601 << " dp:" << std::setw(w) << depth
0602 << " sx:" << std::setw(w) << sibdex
0603 << " pt:" << std::setw(w) << parent
0604 << " "
0605 << " nc:" << std::setw(w) << num_child
0606 << " fc:" << std::setw(w) << first_child
0607 << " ns:" << std::setw(w) << next_sibling
0608 << " lv:" << std::setw(w) << lvid
0609 << " "
0610 << " tc:" << std::setw(w) << typecode
0611 << " pa:" << std::setw(w) << param
0612 << " bb:" << std::setw(w) << aabb
0613 << " xf:" << std::setw(w) << xform
0614 << " "
0615 << tag()
0616 ;
0617 std::string str = ss.str();
0618 return str ;
0619 }
0620
0621 std::string snd::rbrief() const
0622 {
0623 std::stringstream ss ;
0624 ss << "snd::rbrief" << std::endl ;
0625
0626 rbrief_r(ss, 0) ;
0627 std::string str = ss.str();
0628 return str ;
0629 }
0630
0631
0632 void snd::rbrief_r(std::ostream& os, int d) const
0633 {
0634 os << brief() << std::endl ;
0635 int ch = first_child ;
0636 while( ch > -1 )
0637 {
0638 snd& child = POOL->node[ch] ;
0639 child.rbrief_r(os, d+1) ;
0640 ch = child.next_sibling ;
0641 }
0642 }
0643
0644
0645
0646
0647
0648
0649 const char* snd::ERROR_NO_POOL_NOTES = R"(
0650 snd::ERROR_NO_POOL_NOTES
0651 ======================================
0652
0653 The POOL static scsg instance is nullptr
0654
0655 * MUST call snd::SetPOOL to an scsg instance before using snd
0656
0657 * stree instanciation will do this, so the preferred approach
0658 is to instanciate stree in the main prior to using any snd methods.
0659
0660 ::
0661
0662 #include "stree.h"
0663 #include "snd.hh"
0664
0665 int main(int argc, char** argv)
0666 {
0667 stree st ;
0668 int a = snd::Sphere(100.) ;
0669 return 0 ;
0670 }
0671
0672
0673 )" ;
0674
0675 void snd::CheckPOOL(const char* msg)
0676 {
0677 if(POOL) return ;
0678 std::cout << "snd::CheckPOOL " << msg << " FATAL " << std::endl ;
0679 std::cout << ERROR_NO_POOL_NOTES ;
0680 assert( POOL );
0681 }
0682
0683
0684 void snd::setParam( double x, double y, double z, double w, double z1, double z2 )
0685 {
0686 CheckPOOL("snd::setParam") ;
0687 spa o = { x, y, z, w, z1, z2 } ;
0688 param = POOL->addPA(o) ;
0689 }
0690 void snd::setAABB( double x0, double y0, double z0, double x1, double y1, double z1 )
0691 {
0692 CheckPOOL("snd::setAABB") ;
0693 sbb o = {x0, y0, z0, x1, y1, z1} ;
0694
0695 aabb = POOL->addBB(o) ;
0696 }
0697
0698 const double* snd::getParam() const
0699 {
0700 if(param == -1 ) return nullptr ;
0701 assert( param > -1 );
0702 const spa& pa = POOL->param[param] ;
0703 return pa.data() ;
0704 }
0705 const double* snd::getAABB() const
0706 {
0707 if(aabb == -1 ) return nullptr ;
0708 assert( aabb > -1 );
0709 const sbb& bb = POOL->aabb[aabb] ;
0710 return bb.cdata() ;
0711 }
0712
0713 bool snd::hasUnsetAABB() const
0714 {
0715 const double* aabb = getAABB();
0716 if(aabb == nullptr) return true ;
0717 return sbb::IsZero(aabb);
0718 }
0719 bool snd::hasAABB() const
0720 {
0721 const double* aabb = getAABB();
0722 return aabb != nullptr && !sbb::IsZero(aabb) ;
0723 }
0724
0725
0726
0727
0728
0729 void snd::setLabel( const char* label_ )
0730 {
0731
0732
0733
0734
0735
0736
0737 memset( &label[0], 0, sizeof(label) );
0738 memcpy( &label[0], label_, std::min(strlen(label_), sizeof(label)) );
0739
0740 }
0741
0742 void snd::setLVID(int lvid_)
0743 {
0744 setLVID_r(lvid_, 0);
0745 }
0746 void snd::setLVID_r(int lvid_, int d )
0747 {
0748 lvid = lvid_ ;
0749 depth = d ;
0750
0751 int ch = first_child ;
0752 while( ch > -1 )
0753 {
0754 snd& child = POOL->node[ch] ;
0755 child.setLVID_r(lvid, depth+1 );
0756 ch = child.next_sibling ;
0757 }
0758 }
0759
0760 int snd::checktree() const
0761 {
0762 int chk_D = checktree_r('D', 0);
0763 int chk_P = checktree_r('P', 0);
0764 int chk = chk_D + chk_P ;
0765
0766 if( chk > 0 )
0767 {
0768 if(Level()>0) std::cerr
0769 << "snd::checktree"
0770 << " chk_D " << chk_D
0771 << " chk_P " << chk_P
0772 << brief()
0773 << std::endl
0774 ;
0775 }
0776
0777 return chk ;
0778 }
0779 int snd::checktree_r(char code, int d ) const
0780 {
0781 int chk = 0 ;
0782 int ch = first_child ;
0783
0784 if( code == 'D' )
0785 {
0786 if(d != depth) chk += 1 ;
0787 }
0788 else if( code == 'P' )
0789 {
0790 if( depth > 0 && parent < 0 ) chk += 1 ;
0791 }
0792
0793
0794 while( ch > -1 )
0795 {
0796 snd& child = POOL->node[ch] ;
0797
0798 chk += child.checktree_r(code, d + 1 );
0799
0800 ch = child.next_sibling ;
0801 }
0802 return chk ;
0803 }
0804
0805
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822 void snd::Visit(int idx)
0823 {
0824 snd* nd = Get_(idx);
0825
0826 std::cout
0827 << "snd::Visit"
0828 << " idx " << std::setw(3) << idx
0829 << " : " << nd->brief()
0830 << std::endl
0831 ;
0832 }
0833
0834
0835 void snd::PreorderTraverse(int idx, std::function<void(int)> fn)
0836 {
0837 snd* nd = Get_(idx);
0838 nd->preorder_traverse( fn );
0839 }
0840
0841 void snd::preorder_traverse( std::function<void(int)> fn )
0842 {
0843 preorder_traverse_r(fn, 0);
0844 }
0845 void snd::preorder_traverse_r( std::function<void(int)> fn, int d)
0846 {
0847 fn(index);
0848
0849 int ch = first_child ;
0850 while( ch > -1 )
0851 {
0852 snd* child = Get_(ch) ;
0853 child->preorder_traverse_r(fn, d + 1 );
0854 ch = child->next_sibling ;
0855 }
0856 }
0857
0858
0859 void snd::PostorderTraverse(int idx, std::function<void(int)> fn )
0860 {
0861 snd* nd = Get_(idx);
0862 nd->postorder_traverse( fn );
0863 }
0864 void snd::postorder_traverse( std::function<void(int)> fn )
0865 {
0866 postorder_traverse_r(fn, 0);
0867 }
0868 void snd::postorder_traverse_r( std::function<void(int)> fn, int d)
0869 {
0870 int ch = first_child ;
0871 while( ch > -1 )
0872 {
0873 snd* child = Get_(ch) ;
0874 child->postorder_traverse_r(fn, d + 1 );
0875 ch = child->next_sibling ;
0876 }
0877
0878 fn(index);
0879
0880 }
0881
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902 int snd::max_depth() const
0903 {
0904 return max_depth_r(0);
0905 }
0906 int snd::max_depth_r(int d) const
0907 {
0908 int mx = d ;
0909 int ch = first_child ;
0910 while( ch > -1 )
0911 {
0912 snd& child = POOL->node[ch] ;
0913 mx = std::max( mx, child.max_depth_r(d + 1) ) ;
0914 ch = child.next_sibling ;
0915 }
0916 return mx ;
0917 }
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935 int snd::max_binary_depth() const
0936 {
0937 return max_binary_depth_r(0) ;
0938 }
0939 int snd::max_binary_depth_r(int d) const
0940 {
0941 int mx = d ;
0942
0943 if( is_listnode() == false )
0944 {
0945 if( num_child > 0 ) assert( num_child == 2 ) ;
0946 int ch = first_child ;
0947 for(int i=0 ; i < num_child ; i++)
0948 {
0949 snd& child = POOL->node[ch] ;
0950 assert( child.index == ch );
0951 mx = std::max( mx, child.max_binary_depth_r(d + 1) ) ;
0952 ch = child.next_sibling ;
0953 }
0954 }
0955 return mx ;
0956 }
0957
0958
0959 int snd::num_node() const
0960 {
0961 return num_node_r(0);
0962 }
0963 int snd::num_node_r(int d) const
0964 {
0965 int nn = 1 ;
0966 int ch = first_child ;
0967 while( ch > -1 )
0968 {
0969 snd& child = POOL->node[ch] ;
0970 nn += child.num_node_r(d + 1);
0971 ch = child.next_sibling ;
0972 }
0973 return nn ;
0974 }
0975
0976
0977 bool snd::is_root() const
0978 {
0979 return depth == 0 && parent == -1 ;
0980 }
0981
0982 bool snd::is_leaf() const
0983 {
0984 return num_child == 0 ;
0985 }
0986
0987 bool snd::is_binary_leaf() const
0988 {
0989 return num_child == 0 || CSG::IsList(typecode ) ;
0990 }
0991
0992 bool snd::is_sibdex(int q_sibdex) const
0993 {
0994 return sibdex == q_sibdex ;
0995 }
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031 void snd::Inorder(std::vector<int>& order, int idx )
1032 {
1033 const snd* nd = Get(idx);
1034 nd->inorder(order);
1035 }
1036
1037 void snd::inorder(std::vector<int>& order ) const
1038 {
1039 inorder_r(order, 0);
1040 }
1041
1042 void snd::inorder_r(std::vector<int>& order, int d ) const
1043 {
1044 if( num_child <= 0 )
1045 {
1046 order.push_back(index) ;
1047 }
1048 else
1049 {
1050 int split = num_child - 1 ;
1051 int ch = first_child ;
1052
1053 for(int i=0 ; i < split ; i++)
1054 {
1055 snd& child = POOL->node[ch] ;
1056 assert( child.index == ch );
1057 child.inorder_r( order, d+1 );
1058 ch = child.next_sibling ;
1059 }
1060
1061 order.push_back(index) ;
1062
1063 for(int i=split ; i < num_child ; i++)
1064 {
1065 snd& child = POOL->node[ch] ;
1066 assert( child.index == ch );
1067 child.inorder_r( order, d+1 );
1068 ch = child.next_sibling ;
1069 }
1070 }
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082 void snd::Ancestors(int idx, std::vector<int>& nodes)
1083 {
1084 const snd* nd = Get(idx) ;
1085 while( nd->parent > -1 )
1086 {
1087 nodes.push_back(nd->parent);
1088 nd = Get(nd->parent) ;
1089 }
1090 std::reverse( nodes.begin(), nodes.end() );
1091 }
1092
1093 void snd::ancestors(std::vector<int>& nodes) const
1094 {
1095 Ancestors(index, nodes);
1096 }
1097
1098
1099
1100
1101
1102
1103
1104 void snd::leafnodes( std::vector<int>& nodes ) const
1105 {
1106 leafnodes_r(nodes, 0 );
1107 }
1108
1109 void snd::leafnodes_r( std::vector<int>& nodes, int d ) const
1110 {
1111 if(is_leaf()) nodes.push_back(index);
1112
1113 int ch = first_child ;
1114 for(int i=0 ; i < num_child ; i++)
1115 {
1116 snd& child = POOL->node[ch] ;
1117 assert( child.index == ch );
1118 child.leafnodes_r(nodes, d+1 );
1119 ch = child.next_sibling ;
1120 }
1121 }
1122
1123 int snd::Find(int idx, char l0)
1124 {
1125 const snd* nd = Get(idx) ;
1126 return nd ? nd->find(l0) : -1 ;
1127 }
1128
1129 int snd::find(char l0) const
1130 {
1131 std::vector<int> nodes ;
1132 find_r(nodes, l0, 0) ;
1133 return nodes.size() == 1 ? nodes[0] : -1 ;
1134 }
1135
1136 void snd::find_r(std::vector<int>& nodes, char l0, int d) const
1137 {
1138 if(label[0] == l0) nodes.push_back(index);
1139
1140 int ch = first_child ;
1141 for(int i=0 ; i < num_child ; i++)
1142 {
1143 const snd* child = Get(ch) ;
1144 assert( child->index == ch );
1145 child->find_r(nodes, l0, d+1 );
1146 ch = child->next_sibling ;
1147 }
1148 }
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160 template<typename ... Args>
1161 void snd::typenodes_(std::vector<int>& nodes, Args ... tcs ) const
1162 {
1163 std::vector<OpticksCSG_t> types = {tcs ...};
1164 typenodes_r_(nodes, types, 0 );
1165 }
1166
1167
1168 template SYSRAP_API void snd::typenodes_(std::vector<int>& nodes, OpticksCSG_t ) const ;
1169 template SYSRAP_API void snd::typenodes_(std::vector<int>& nodes, OpticksCSG_t, OpticksCSG_t ) const ;
1170 template SYSRAP_API void snd::typenodes_(std::vector<int>& nodes, OpticksCSG_t, OpticksCSG_t, OpticksCSG_t ) const ;
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180 void snd::typenodes_r_(std::vector<int>& nodes, const std::vector<OpticksCSG_t>& types, int d) const
1181 {
1182 if(has_type(types)) nodes.push_back(index);
1183
1184 int ch = first_child ;
1185 for(int i=0 ; i < num_child ; i++)
1186 {
1187 snd& child = POOL->node[ch] ;
1188 assert( child.index == ch );
1189 child.typenodes_r_(nodes, types, d+1 );
1190 ch = child.next_sibling ;
1191 }
1192 }
1193
1194 bool snd::has_type(const std::vector<OpticksCSG_t>& types) const
1195 {
1196 return std::find( types.begin(), types.end(), typecode ) != types.end() ;
1197 }
1198
1199
1200 template<typename ... Args>
1201 std::string snd::DescType(Args ... tcs)
1202 {
1203 std::vector<OpticksCSG_t> types = {tcs ...};
1204 int num_tc = types.size();
1205
1206 std::stringstream ss ;
1207 for(int i=0 ; i < num_tc ; i++)
1208 {
1209 int tc = types[i];
1210 ss << CSG::Tag(tc) ;
1211 if(i < num_tc - 1) ss << "," ;
1212 }
1213 std::string str = ss.str();
1214 return str ;
1215 }
1216
1217 template SYSRAP_API std::string snd::DescType(OpticksCSG_t );
1218 template SYSRAP_API std::string snd::DescType(OpticksCSG_t, OpticksCSG_t );
1219 template SYSRAP_API std::string snd::DescType(OpticksCSG_t, OpticksCSG_t, OpticksCSG_t );
1220
1221
1222
1223
1224 void snd::typenodes(std::vector<int>& nodes, int tc ) const
1225 {
1226 typenodes_r(nodes, tc, 0 );
1227 }
1228 void snd::typenodes_r(std::vector<int>& nodes, int tc, int d) const
1229 {
1230 if(typecode == tc ) nodes.push_back(index);
1231
1232 int ch = first_child ;
1233 for(int i=0 ; i < num_child ; i++)
1234 {
1235 snd& child = POOL->node[ch] ;
1236 assert( child.index == ch );
1237 child.typenodes_r(nodes, tc, d+1 );
1238 ch = child.next_sibling ;
1239 }
1240 }
1241
1242
1243
1244 int snd::get_ordinal( const std::vector<int>& order ) const
1245 {
1246 int ordinal = std::distance( order.begin(), std::find(order.begin(), order.end(), index )) ;
1247 return ordinal < int(order.size()) ? ordinal : -1 ;
1248 }
1249
1250
1251 std::string snd::dump() const
1252 {
1253 std::stringstream ss ;
1254 dump_r( ss, 0 );
1255 std::string str = ss.str();
1256 return str ;
1257 }
1258
1259 void snd::dump_r( std::ostream& os, int d ) const
1260 {
1261 os << "snd::dump_r"
1262 << " d " << d
1263 << brief()
1264 << std::endl
1265 ;
1266
1267 int ch = first_child ;
1268 while( ch > -1 )
1269 {
1270 snd& child = POOL->node[ch] ;
1271 child.dump_r( os, d+1 );
1272 ch = child.next_sibling ;
1273 }
1274 }
1275
1276
1277
1278 std::string snd::dump2() const
1279 {
1280 std::stringstream ss ;
1281 dump2_r( ss, 0 );
1282 std::string str = ss.str();
1283 return str ;
1284 }
1285
1286 void snd::dump2_r( std::ostream& os, int d ) const
1287 {
1288 os << "snd::dump2_r"
1289 << " d " << d
1290 << brief()
1291 << std::endl
1292 ;
1293
1294 int ch = first_child ;
1295 for(int i=0 ; i < num_child ; i++)
1296 {
1297 snd& child = POOL->node[ch] ;
1298 child.dump2_r( os, d+1 );
1299 ch = child.next_sibling ;
1300 }
1301 }
1302
1303
1304
1305 std::string snd::Render(int idx, int mode)
1306 {
1307 const snd* n = Get(idx);
1308 return n ? n->render(mode) : "snd::Render bad idx ";
1309 }
1310
1311 std::string snd::render(int mode_) const
1312 {
1313 int width = num_node();
1314 int height = max_depth();
1315 int defmode = width > 16 ? 0 : 1 ;
1316 int mode = mode_ > -1 ? mode_ : defmode ;
1317
1318 std::vector<int> order ;
1319 inorder(order);
1320 assert( int(order.size()) == width );
1321
1322 scanvas canvas( width+1, height+2, 4, 2 );
1323 render_r(&canvas, order, mode, 0);
1324
1325 std::stringstream ss ;
1326 ss
1327 << std::endl
1328 << "snd::render"
1329 << " width " << width
1330 << " height " << height
1331 << " mode " << mode
1332 << std::endl
1333 << std::endl
1334 << canvas.c
1335 << std::endl
1336 ;
1337
1338 std::string str = ss.str();
1339 return str ;
1340 }
1341
1342 void snd::render_r(scanvas* canvas, const std::vector<int>& order, int mode, int d) const
1343 {
1344 render_v(canvas, order, mode, d);
1345
1346 int ch = first_child ;
1347 while( ch > -1 )
1348 {
1349 snd& child = POOL->node[ch] ;
1350 child.render_r( canvas, order, mode, d+1 );
1351 ch = child.next_sibling ;
1352 }
1353 }
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374 void snd::render_v( scanvas* canvas, const std::vector<int>& order, int mode, int d ) const
1375 {
1376 int ordinal = get_ordinal( order );
1377 assert( ordinal > -1 );
1378
1379
1380
1381 int ix = ordinal ;
1382 int iy = d ;
1383
1384 char l0 = label[0] ;
1385 if(l0 == '\0' ) l0 = 'o' ;
1386
1387 if( mode == 0 )
1388 {
1389 canvas->drawch( ix, iy, 0,0, l0 );
1390 }
1391 else if( mode == 1 )
1392 {
1393 canvas->draw( ix, iy, 0,0, index );
1394 }
1395 else if( mode == 2 )
1396 {
1397 canvas->draw( ix, iy, 0,0, typecode );
1398 }
1399 else if( mode == 3 )
1400 {
1401 std::string tc = tag();
1402 canvas->draw( ix, iy, 0,0, tc.c_str() );
1403 }
1404 }
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414 double snd::zmin() const
1415 {
1416 assert( CSG::CanZNudge(typecode) );
1417 assert( param > -1 );
1418 const spa& pa = POOL->param[param] ;
1419 return pa.zmin();
1420 }
1421
1422 double snd::zmax() const
1423 {
1424 assert( CSG::CanZNudge(typecode) );
1425 assert( param > -1 );
1426 const spa& pa = POOL->param[param] ;
1427 return pa.zmax();
1428 }
1429
1430 void snd::check_z() const
1431 {
1432 assert( CSG::CanZNudge(typecode) );
1433 assert( param > -1 );
1434 assert( aabb > -1 );
1435
1436 const spa& pa = POOL->param[param] ;
1437 const sbb& bb = POOL->aabb[aabb] ;
1438
1439 bool pa_expect = pa.zmin() == bb.zmin() && pa.zmax() == bb.zmax() ;
1440 if(!pa_expect) std::raise(SIGINT);
1441 assert( pa_expect );
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 void snd::decrease_zmin( double dz )
1458 {
1459 check_z();
1460
1461 spa& pa = POOL->param[param] ;
1462 sbb& bb = POOL->aabb[aabb] ;
1463
1464 pa.decrease_zmin(dz);
1465 bb.decrease_zmin(dz);
1466 }
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483 void snd::increase_zmax( double dz )
1484 {
1485 check_z();
1486
1487 spa& pa = POOL->param[param] ;
1488 sbb& bb = POOL->aabb[aabb] ;
1489
1490 pa.increase_zmax(dz) ;
1491 bb.increase_zmax(dz) ;
1492 }
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 std::string snd::ZDesc(const std::vector<int>& prims)
1509 {
1510 std::stringstream ss ;
1511 ss << "snd::ZDesc" ;
1512 ss << " prims(" ;
1513 for(unsigned i=0 ; i < prims.size() ; i++) ss << prims[i] << " " ;
1514 ss << ") " ;
1515 ss << std::endl ;
1516
1517 for(unsigned i=0 ; i < prims.size() ; i++)
1518 {
1519 int _a = prims[i];
1520 snd& a = POOL->node[_a] ;
1521 ss << std::setw(3) << _a
1522 << ":"
1523 << " " << std::setw(10) << a.zmin()
1524 << " " << std::setw(10) << a.zmax()
1525 << std::endl
1526 ;
1527 }
1528 std::string str = ss.str();
1529 return str ;
1530 }
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541 void snd::ZNudgeExpandEnds(const std::vector<int>& prims)
1542 {
1543 int level = Level();
1544 if(level > 0) std::cout
1545 << std::endl
1546 << "snd::ZNudgeExpandEnds "
1547 << std::endl
1548 << ZDesc(prims)
1549 << std::endl
1550 ;
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 }
1566
1567 void snd::ZNudgeOverlapJoints(const std::vector<int>& prims)
1568 {
1569 int level = Level();
1570 if(level > 0) std::cout
1571 << std::endl
1572 << "snd::ZNudgeOverlapJoints PLACEHOLDER "
1573 << std::endl
1574 << ZDesc(prims)
1575 << std::endl
1576 ;
1577 }
1578
1579
1580
1581
1582 std::string snd::desc() const
1583 {
1584 std::stringstream ss ;
1585 ss
1586 << "[snd::desc" << std::endl
1587 << brief() << std::endl
1588 << DescParam(param) << std::endl
1589 << DescAABB(aabb) << std::endl
1590 << DescXForm(xform) << std::endl
1591 ;
1592
1593 const snd& nd = *this ;
1594 int ch = nd.first_child ;
1595 int count = 0 ;
1596
1597 while( ch > -1 )
1598 {
1599 ss << Desc(ch) << std::endl ;
1600 const snd& child = POOL->node[ch] ;
1601
1602 bool consistent_parent_index = child.parent == nd.index ;
1603
1604 if(!consistent_parent_index) ss
1605 << "snd::desc "
1606 << " FAIL consistent_parent_index "
1607 << " ch " << ch
1608 << " count " << count
1609 << " child.parent " << child.parent
1610 << " nd.index " << nd.index
1611 << " nd.lvid " << nd.lvid
1612 << " child.index " << child.index
1613 << " child.lvid " << child.lvid
1614 << std::endl
1615 ;
1616
1617
1618 count += 1 ;
1619 ch = child.next_sibling ;
1620 }
1621
1622 bool expect_child = count == nd.num_child ;
1623
1624 if(!expect_child)
1625 {
1626 ss << std::endl << " FAIL count " << count << " num_child " << num_child << std::endl;
1627 }
1628 assert(expect_child);
1629 ss << "]snd::desc" << std::endl ;
1630 std::string str = ss.str();
1631 return str ;
1632 }
1633
1634 std::ostream& operator<<(std::ostream& os, const snd& v)
1635 {
1636 os << v.desc() ;
1637 return os;
1638 }
1639
1640
1641
1642
1643
1644
1645
1646 snd snd::Init(int tc)
1647 {
1648 snd nd = {} ;
1649 nd.init();
1650 nd.typecode = tc ;
1651 nd.num_child = 0 ;
1652 nd.complement = 0 ;
1653 return nd ;
1654 }
1655
1656
1657
1658
1659
1660
1661
1662
1663 void snd::init()
1664 {
1665 typecode = -1 ;
1666 complement = -1 ;
1667 lvid = -1 ;
1668 xform = -1 ;
1669 param = -1 ;
1670 aabb = -1 ;
1671 parent = -1 ;
1672 sibdex = -1 ;
1673 num_child = -1 ;
1674 first_child = -1 ;
1675 next_sibling = -1 ;
1676 index = -1 ;
1677 depth = -1 ;
1678 }
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695 int snd::Boolean( int op, int l, int r )
1696 {
1697 assert( l > -1 && r > -1 );
1698
1699 snd nd = Init( op );
1700 assert( nd.xform == -1 );
1701
1702 nd.num_child = 2 ;
1703 nd.first_child = l ;
1704
1705 snd* ln = Get_(l) ;
1706 snd* rn = Get_(r) ;
1707
1708 ln->next_sibling = r ;
1709 ln->sibdex = 0 ;
1710
1711 rn->next_sibling = -1 ;
1712 rn->sibdex = 1 ;
1713
1714 int idx_0 = POOL->node.size() ;
1715
1716 ln->parent = idx_0 ;
1717 rn->parent = idx_0 ;
1718
1719 int idx = Add(nd) ;
1720
1721 assert( idx_0 == idx );
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735 return idx ;
1736 }
1737
1738 int snd::Compound(int type, const std::vector<int>& prims )
1739 {
1740 assert( type == CSG_CONTIGUOUS || type == CSG_DISCONTIGUOUS );
1741
1742 int num_prim = prims.size();
1743 assert( num_prim > 0 );
1744
1745 snd nd = Init( type );
1746 nd.sibdex = 0 ;
1747 nd.num_child = num_prim ;
1748 nd.first_child = prims[0] ;
1749 int idx = Add(nd) ;
1750
1751 for(int i=0 ; i < num_prim ; i++)
1752 {
1753 int i_sib = prims[i];
1754 int p_sib = i > 0 ? prims[i-1] : -1 ;
1755
1756 snd& i_child = POOL->node[i_sib] ;
1757 i_child.sibdex = i ;
1758 i_child.parent = idx ;
1759 i_child.next_sibling = -1 ;
1760
1761
1762
1763
1764 if(i > 0)
1765 {
1766 assert( p_sib > -1 );
1767 snd& p_child = POOL->node[p_sib] ;
1768 p_child.next_sibling = i_sib ;
1769 }
1770 }
1771 return idx ;
1772 }
1773
1774
1775 int snd::UnionTree(const std::vector<int>& prims )
1776 {
1777 int idx = sndtree::CommonTree_PlaceLeaves( prims, CSG_UNION );
1778 snd* n = Get_(idx);
1779 bool n_expect = n->sibdex == 0 ;
1780 if(!n_expect) std::raise(SIGINT) ;
1781 assert( n_expect ) ;
1782 return idx ;
1783 }
1784
1785 int snd::Contiguous( const std::vector<int>& prims )
1786 {
1787 int idx = snd::Compound( CSG_CONTIGUOUS, prims );
1788 return idx ;
1789 }
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808 int snd::Collection( const std::vector<int>& prims )
1809 {
1810 int idx = -1 ;
1811 switch(VERSION)
1812 {
1813 case 0: idx = UnionTree(prims) ; break ;
1814 case 1: idx = Contiguous(prims) ; break ;
1815 }
1816 return idx ;
1817 }
1818
1819
1820 int snd::Cylinder(double radius, double z1, double z2)
1821 {
1822 assert( z2 > z1 );
1823 snd nd = Init(CSG_CYLINDER);
1824 nd.setParam( 0.f, 0.f, 0.f, radius, z1, z2) ;
1825 nd.setAABB( -radius, -radius, z1, +radius, +radius, z2 );
1826 return Add(nd) ;
1827 }
1828
1829 int snd::Cone(double r1, double z1, double r2, double z2)
1830 {
1831 assert( z2 > z1 );
1832 double rmax = fmax(r1, r2) ;
1833 snd nd = Init(CSG_CONE) ;
1834 nd.setParam( r1, z1, r2, z2, 0., 0. ) ;
1835 nd.setAABB( -rmax, -rmax, z1, rmax, rmax, z2 );
1836 return Add(nd) ;
1837 }
1838
1839 int snd::Sphere(double radius)
1840 {
1841 assert( radius > zero );
1842 snd nd = Init(CSG_SPHERE) ;
1843 nd.setParam( zero, zero, zero, radius, zero, zero );
1844 nd.setAABB( -radius, -radius, -radius, radius, radius, radius );
1845 return Add(nd) ;
1846 }
1847
1848 int snd::ZSphere(double radius, double z1, double z2)
1849 {
1850 assert( radius > zero );
1851 assert( z2 > z1 );
1852 snd nd = Init(CSG_ZSPHERE) ;
1853 nd.setParam( zero, zero, zero, radius, z1, z2 );
1854 nd.setAABB( -radius, -radius, z1, radius, radius, z2 );
1855 return Add(nd) ;
1856 }
1857
1858 int snd::Box3(double fullside)
1859 {
1860 return Box3(fullside, fullside, fullside);
1861 }
1862 int snd::Box3(double fx, double fy, double fz )
1863 {
1864 assert( fx > 0. );
1865 assert( fy > 0. );
1866 assert( fz > 0. );
1867
1868 snd nd = Init(CSG_BOX3) ;
1869 nd.setParam( fx, fy, fz, 0.f, 0.f, 0.f );
1870 nd.setAABB( -fx*0.5 , -fy*0.5, -fz*0.5, fx*0.5 , fy*0.5, fz*0.5 );
1871 return Add(nd) ;
1872 }
1873
1874 int snd::Zero(double x, double y, double z, double w, double z1, double z2)
1875 {
1876 snd nd = Init(CSG_ZERO);
1877 nd.setParam( x, y, z, w, z1, z2 );
1878 return Add(nd) ;
1879 }
1880
1881 int snd::Zero()
1882 {
1883 snd nd = Init(CSG_ZERO);
1884 return Add(nd) ;
1885 }
1886
1887