File indexing completed on 2026-04-09 07:48:56
0001 #include <iostream>
0002 #include <iomanip>
0003 #include <array>
0004 #include <vector>
0005 #include <set>
0006 #include <algorithm>
0007 #include <cstring>
0008 #include <csignal>
0009 #include <cstdlib>
0010
0011 #include <glm/glm.hpp>
0012 #include <glm/gtx/string_cast.hpp>
0013 #include <glm/gtc/type_ptr.hpp>
0014
0015 #include "sstr.h"
0016 #include "ssys.h"
0017 #include "sproc.h"
0018 #include "SProf.hh"
0019
0020 #include "smeta.h"
0021 #include "SSim.hh"
0022 #include "SStr.hh"
0023
0024
0025 #include "SPath.hh"
0026
0027 #include "s_time.h"
0028 #include "SBitSet.h"
0029
0030 #include "SEventConfig.hh"
0031 #include "SGeoConfig.hh"
0032 #include "NP.hh"
0033
0034 #include "SEvt.hh"
0035 #include "SSim.hh"
0036 #include "SLOG.hh"
0037
0038 #include "scuda.h"
0039 #include "sqat4.h"
0040 #include "sframe.h"
0041 #include "SLabel.h"
0042 #include "SScene.h"
0043
0044
0045 #include "OpticksCSG.h"
0046 #include "CSGSolid.h"
0047
0048 #include "CU.h"
0049
0050 #include "CSGFoundry.h"
0051 #include "SName.h"
0052 #include "CSGTarget.h"
0053 #include "CSGMaker.h"
0054 #include "CSGImport.h"
0055 #include "CSGCopy.h"
0056
0057 const unsigned CSGFoundry::IMAX = 50000 ;
0058
0059 const plog::Severity CSGFoundry::LEVEL = SLOG::EnvLevel("CSGFoundry", "DEBUG" );
0060 const int CSGFoundry::VERBOSE = ssys::getenvint("VERBOSE", 0);
0061
0062 std::string CSGFoundry::descComp() const
0063 {
0064 std::stringstream ss ;
0065 ss << "CSGFoundry::descComp"
0066 << " sim " << ( sim ? sim->desc() : "" )
0067 ;
0068 std::string s = ss.str();
0069 return s ;
0070 }
0071
0072
0073 void CSGFoundry::setPrimBoundary(unsigned primIdx, const char* bname )
0074 {
0075 assert( sim );
0076 int bidx = sim->getBndIndex(bname);
0077 assert( bidx > -1 );
0078 setPrimBoundary(primIdx, bidx);
0079 }
0080
0081 CSGFoundry* CSGFoundry::INSTANCE = nullptr ;
0082 CSGFoundry* CSGFoundry::Get(){ return INSTANCE ; }
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 CSGFoundry::CSGFoundry()
0102 :
0103 d_prim(nullptr),
0104 d_node(nullptr),
0105 d_plan(nullptr),
0106 d_itra(nullptr),
0107 sim(SSim::Get()),
0108 import(new CSGImport(this)),
0109 id(new SName(meshname)),
0110 target(new CSGTarget(this)),
0111 maker(new CSGMaker(this)),
0112 deepcopy_everynode_transform(true),
0113 last_added_solid(nullptr),
0114 last_added_prim(nullptr),
0115 mtime(s_time::EpochSeconds()),
0116 meta(),
0117 fold(nullptr),
0118 cfbase(nullptr),
0119 geom(nullptr),
0120 loaddir(nullptr),
0121 origin(nullptr),
0122 elv(nullptr),
0123 save_opt(ssys::getenvvar(SAVE_OPT))
0124 {
0125 LOG_IF(fatal, sim == nullptr) << "must SSim::Create before CSGFoundry::CSGFoundry " ;
0126 assert(sim);
0127
0128 init();
0129 INSTANCE = this ;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 void CSGFoundry::init()
0141 {
0142 solid.reserve(IMAX);
0143 prim.reserve(IMAX);
0144 node.reserve(IMAX);
0145 plan.reserve(IMAX);
0146 tran.reserve(IMAX);
0147 itra.reserve(IMAX);
0148 inst.reserve(IMAX);
0149
0150 smeta::Collect(meta, "CSGFoundry::init");
0151 }
0152
0153
0154
0155 std::string CSGFoundry::brief() const
0156 {
0157 std::stringstream ss ;
0158 ss << "CSGFoundry::brief " << ( loaddir ? loaddir : "-" ) ;
0159 return ss.str();
0160 }
0161 std::string CSGFoundry::desc() const
0162 {
0163 std::stringstream ss ;
0164 ss << "CSGFoundry "
0165 << " num_total " << getNumSolidTotal()
0166 << " num_solid " << solid.size()
0167 << " num_prim " << prim.size()
0168 << " num_node " << node.size()
0169 << " num_plan " << plan.size()
0170 << " num_tran " << tran.size()
0171 << " num_itra " << itra.size()
0172 << " num_inst " << inst.size()
0173 << " gas " << gas.size()
0174
0175
0176
0177
0178
0179 << " meshname " << meshname.size()
0180 << " mmlabel " << mmlabel.size()
0181 << " mtime " << mtime
0182 << " mtimestamp " << s_time::Format(mtime)
0183 << " sim " << ( sim ? "Y" : "N" )
0184 ;
0185 return ss.str();
0186 }
0187
0188
0189
0190
0191
0192 std::string CSGFoundry::descSolid() const
0193 {
0194 unsigned num_total = getNumSolidTotal();
0195 unsigned num_standard = getNumSolid(STANDARD_SOLID);
0196 unsigned num_oneprim = getNumSolid(ONE_PRIM_SOLID);
0197 unsigned num_onenode = getNumSolid(ONE_NODE_SOLID);
0198 unsigned num_deepcopy = getNumSolid(DEEP_COPY_SOLID);
0199 unsigned num_kludgebbox = getNumSolid(KLUDGE_BBOX_SOLID);
0200
0201 std::stringstream ss ;
0202 ss << "CSGFoundry "
0203 << " total solids " << num_total
0204 << " STANDARD " << num_standard
0205 << " ONE_PRIM " << num_oneprim
0206 << " ONE_NODE " << num_onenode
0207 << " DEEP_COPY " << num_deepcopy
0208 << " KLUDGE_BBOX " << num_kludgebbox
0209 ;
0210 return ss.str();
0211 }
0212
0213
0214 std::string CSGFoundry::descMeshName() const
0215 {
0216 std::stringstream ss ;
0217
0218 ss << "CSGFoundry::descMeshName"
0219 << " meshname.size " << meshname.size()
0220 << std::endl ;
0221 for(unsigned i=0 ; i < meshname.size() ; i++)
0222 ss << std::setw(5) << i << " : " << meshname[i] << std::endl ;
0223
0224 std::string s = ss.str();
0225 return s ;
0226 }
0227
0228
0229 unsigned CSGFoundry::getNumMeshes() const
0230 {
0231 return meshname.size() ;
0232 }
0233 unsigned CSGFoundry::getNumMeshName() const
0234 {
0235 return meshname.size() ;
0236 }
0237
0238
0239 unsigned CSGFoundry::getNumSolidLabel() const
0240 {
0241 return mmlabel.size() ;
0242 }
0243
0244
0245 int CSGFoundry::findSolidWithLabel(const char* q_mml) const
0246 {
0247 return SLabel::FindIdxWithLabel(mmlabel, q_mml) ;
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 bool CSGFoundry::isSolidTrimesh_posthoc_kludge(int gas_idx) const
0281 {
0282 const char* ls = SGeoConfig::SolidTrimesh() ;
0283 if(ls == nullptr) return false ;
0284 return SLabel::IsIdxLabelListed( mmlabel, gas_idx, ls, ',' );
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 bool CSGFoundry::isSolidTrimesh(int gas_idx) const
0297 {
0298 char intent = getSolidIntent(gas_idx);
0299 bool trimesh = intent == 'T' ;
0300 assert( intent == 'R' || intent == 'F' || intent == 'T' || intent == '\0' );
0301 return trimesh ;
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 void CSGFoundry::CopyNames( CSGFoundry* dst, const CSGFoundry* src )
0318 {
0319 CopyMeshName( dst, src );
0320 dst->mtime = src->mtime ;
0321 }
0322
0323 void CSGFoundry::CopyMeshName( CSGFoundry* dst, const CSGFoundry* src )
0324 {
0325 assert( dst->meshname.size() == 0);
0326 src->getMeshName(dst->meshname);
0327 assert( src->meshname.size() == dst->meshname.size() );
0328 }
0329
0330 void CSGFoundry::getMeshName( std::vector<std::string>& mname ) const
0331 {
0332 for(unsigned i=0 ; i < meshname.size() ; i++)
0333 {
0334 const std::string& mn = meshname[i];
0335 mname.push_back(mn);
0336 }
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 void CSGFoundry::getPrimName( std::vector<std::string>& pname ) const
0352 {
0353 unsigned num_prim = prim.size();
0354 for(unsigned i=0 ; i < num_prim ; i++)
0355 {
0356 const CSGPrim& pr = prim[i] ;
0357 unsigned midx = num_prim == 1 ? 0 : pr.meshIdx();
0358
0359 if(midx == UNDEFINED)
0360 {
0361 pname.push_back("err-midx-undefined");
0362 }
0363 else
0364 {
0365 const char* mname = getMeshName(midx);
0366 LOG(debug) << " primIdx " << std::setw(4) << i << " midx " << midx << " mname " << mname ;
0367 pname.push_back(mname);
0368 }
0369 }
0370 }
0371
0372 const char* CSGFoundry::getMeshName(unsigned midx) const
0373 {
0374 bool in_range = midx < meshname.size() ;
0375
0376 LOG_IF(fatal, !in_range) << " not in range midx " << midx << " meshname.size() " << meshname.size() ;
0377 assert(in_range);
0378
0379 return meshname[midx].c_str() ;
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 int CSGFoundry::findMeshIndex(const char* qname) const
0413 {
0414 unsigned count = 0 ;
0415 int max_count = 1 ;
0416 int midx = id->findIndex(qname, count, max_count);
0417 return midx ;
0418 }
0419
0420
0421
0422
0423
0424
0425
0426
0427 int CSGFoundry::getMeshIndexWithName(const char* qname, bool startswith) const
0428 {
0429 return id->findIndexWithName(qname, startswith) ;
0430 }
0431
0432
0433 int CSGFoundry::lookup_mtline(int mtindex) const
0434 {
0435 assert(sim);
0436 return sim->lookup_mtline(mtindex) ;
0437 }
0438 std::string CSGFoundry::desc_mt() const
0439 {
0440 assert(sim);
0441 return sim->desc_mt() ;
0442 }
0443
0444
0445
0446
0447
0448
0449 stree* CSGFoundry::getTree() const
0450 {
0451 return sim ? sim->tree : nullptr ;
0452 }
0453
0454
0455
0456
0457
0458
0459 SScene* CSGFoundry::getScene() const
0460 {
0461 return sim ? sim->get_scene() : nullptr ;
0462 }
0463
0464 void CSGFoundry::setOverrideScene(SScene* _scene)
0465 {
0466 assert( sim);
0467 const_cast<SSim*>(sim)->set_override_scene(_scene);
0468 }
0469
0470
0471 const std::string CSGFoundry::descELV2(const SBitSet* elv) const
0472 {
0473 unsigned num_bits = elv->num_bits ;
0474 unsigned num_name = id->getNumName() ;
0475 assert( num_bits == num_name );
0476
0477 std::stringstream ss ;
0478 ss << "CSGFoundry::descELV2"
0479 << " elv.num_bits " << num_bits
0480 << " id.getNumName " << num_name
0481 << std::endl
0482 ;
0483
0484 for(int p=0 ; p < 2 ; p++)
0485 {
0486 for(unsigned i=0 ; i < num_bits ; i++)
0487 {
0488 bool is_set = elv->is_set(i);
0489 const char* n = id->getName(i);
0490 if( is_set == bool(p) )
0491 {
0492 ss << std::setw(3) << i << " "
0493 << ( is_set ? "Y" : "N" )
0494 << " [" << ( n ? n : "-" ) << "] "
0495 << std::endl
0496 ;
0497 }
0498 }
0499 }
0500 std::string str = ss.str();
0501 return str ;
0502 }
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 const std::string CSGFoundry::descELV(const SBitSet* elv) const
0515 {
0516 std::vector<unsigned> include_pos ;
0517 std::vector<unsigned> exclude_pos ;
0518 elv->get_pos(include_pos, true );
0519 elv->get_pos(exclude_pos, false);
0520
0521 unsigned num_include = include_pos.size() ;
0522 unsigned num_exclude = exclude_pos.size() ;
0523 unsigned num_bits = elv->num_bits ;
0524 assert( num_bits == num_include + num_exclude );
0525 bool is_all_set = elv->is_all_set();
0526
0527 std::stringstream ss ;
0528 ss << "CSGFoundry::descELV"
0529 << " elv.num_bits " << num_bits
0530 << " num_include " << num_include
0531 << " num_exclude " << num_exclude
0532 << " is_all_set " << is_all_set
0533 << std::endl
0534 ;
0535
0536 ss << "INCLUDE:" << num_include << std::endl << std::endl ;
0537 for(unsigned i=0 ; i < num_include ; i++)
0538 {
0539 const unsigned& p = include_pos[i] ;
0540 const char* mn = getMeshName(p) ;
0541 int midx = findMeshIndex(mn);
0542
0543
0544 ss
0545 << "p:" << std::setw(3) << p << ":"
0546 << "midx:" << std::setw(3) << midx << ":"
0547 << "mn:" << mn << std::endl
0548 ;
0549 }
0550
0551 ss << "EXCLUDE:" << exclude_pos.size() << std::endl << std::endl ;
0552 for(unsigned i=0 ; i < exclude_pos.size() ; i++)
0553 {
0554 const unsigned& p = exclude_pos[i] ;
0555 const char* mn = getMeshName(p) ;
0556 int midx = findMeshIndex(mn);
0557
0558
0559 ss
0560 << "p:" << std::setw(3) << p << ":"
0561 << "midx:" << std::setw(3) << midx << ":"
0562 << "mn:" << mn << std::endl
0563 ;
0564 }
0565
0566 std::string str = ss.str();
0567 return str ;
0568 }
0569
0570
0571
0572 void CSGFoundry::addMeshName(const char* name)
0573 {
0574 meshname.push_back(name);
0575 }
0576
0577 void CSGFoundry::addSolidMMLabel(const char* label)
0578 {
0579 mmlabel.push_back(label);
0580 }
0581
0582
0583 const std::string& CSGFoundry::getSolidMMLabel(unsigned gas_idx) const
0584 {
0585 assert( gas_idx < mmlabel.size() );
0586 return mmlabel[gas_idx] ;
0587 }
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 int CSGFoundry::Compare( const CSGFoundry* a, const CSGFoundry* b )
0603 {
0604 int mismatch = 0 ;
0605 mismatch += CompareVec( "solid", a->solid, b->solid );
0606 mismatch += CompareVec( "prim" , a->prim , b->prim );
0607 mismatch += CompareVec( "node" , a->node , b->node );
0608 mismatch += CompareVec( "plan" , a->plan , b->plan );
0609 mismatch += CompareVec( "tran" , a->tran , b->tran );
0610 mismatch += CompareVec( "itra" , a->itra , b->itra );
0611 mismatch += CompareVec( "inst" , a->inst , b->inst );
0612 mismatch += CompareVec( "gas" , a->gas , b->gas );
0613 LOG_IF(fatal, mismatch != 0 ) << " mismatch FAIL ";
0614
0615 mismatch += SSim::Compare( a->sim, b->sim );
0616
0617 return mismatch ;
0618 }
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628 int CSGFoundry::WIP_CompareStruct( const CSGFoundry* a, const CSGFoundry* b )
0629 {
0630 int mismatch = 0 ;
0631 mismatch += CompareStruct( "solid", a->solid, b->solid );
0632 mismatch += CompareStruct( "prim" , a->prim , b->prim );
0633 mismatch += CompareStruct( "node" , a->node , b->node );
0634 mismatch += CompareFloat4( "plan" , a->plan , b->plan );
0635 mismatch += CompareStruct( "tran" , a->tran , b->tran );
0636 mismatch += CompareStruct( "itra" , a->itra , b->itra );
0637 mismatch += CompareStruct( "inst" , a->inst , b->inst );
0638 mismatch += CompareVec( "gas" , a->gas , b->gas );
0639 LOG_IF(fatal, mismatch != 0 ) << " mismatch FAIL ";
0640
0641 mismatch += SSim::Compare( a->sim, b->sim );
0642
0643 return mismatch ;
0644 }
0645
0646
0647
0648
0649
0650 std::string CSGFoundry::DescCompare( const CSGFoundry* a, const CSGFoundry* b )
0651 {
0652 std::stringstream ss ;
0653 ss << "CSGFoundry::DescCompare" << std::endl ;
0654 int mismatch = 0 ;
0655 int cv = 0 ;
0656 cv = CompareVec( "solid", a->solid, b->solid ); mismatch += cv ;
0657 ss << "CompareVec.solid " << cv << std::endl ;
0658 cv = CompareVec( "prim", a->prim, b->prim ); mismatch += cv ;
0659 ss << "CompareVec.prim " << cv << std::endl ;
0660 cv = CompareVec( "node" , a->node , b->node ); mismatch += cv ;
0661 ss << "CompareVec.node " << cv << std::endl ;
0662 cv = CompareVec( "plan" , a->plan , b->plan ); mismatch += cv ;
0663 ss << "CompareVec.plan " << cv << std::endl ;
0664 cv = CompareVec( "tran" , a->tran , b->tran ); mismatch += cv ;
0665 ss << "CompareVec.tran " << cv << std::endl ;
0666 cv = CompareVec( "itra" , a->itra , b->itra ); mismatch += cv ;
0667 ss << "CompareVec.itra " << cv << std::endl ;
0668 cv = CompareVec( "inst" , a->inst , b->inst ); mismatch += cv ;
0669 ss << "CompareVec.inst " << cv << std::endl ;
0670 cv = CompareVec( "gas" , a->gas , b->gas ); mismatch += cv ;
0671 ss << "CompareVec.gas " << cv << std::endl ;
0672 cv = SSim::Compare( a->sim, b->sim ) ; mismatch += cv ;
0673 ss << "SSim::Compare " << cv << std::endl ;
0674 ss << SSim::DescCompare( a->sim, b->sim ) << std::endl ;
0675 ss << " mismatch " << mismatch << std::endl ;
0676 std::string s = ss.str();
0677 return s ;
0678 }
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691 template<typename T>
0692 int CSGFoundry::CompareVec( const char* name, const std::vector<T>& a, const std::vector<T>& b )
0693 {
0694 int mismatch = 0 ;
0695
0696 bool size_match = a.size() == b.size() ;
0697 LOG_IF(info, !size_match) << name << " size_match FAIL " << a.size() << " vs " << b.size() ;
0698 if(!size_match) mismatch += 1 ;
0699 if(!size_match) return mismatch ;
0700
0701 int data_match = memcmp( a.data(), b.data(), a.size()*sizeof(T) ) ;
0702 LOG_IF(info, data_match != 0) << name << " sizeof(T) " << sizeof(T) << " data_match FAIL " ;
0703 if(data_match != 0) mismatch += 1 ;
0704
0705 int byte_match = CompareBytes( a.data(), b.data(), a.size()*sizeof(T) ) ;
0706 LOG_IF(info, byte_match != 0) << name << " sizeof(T) " << sizeof(T) << " byte_match FAIL " ;
0707 if(byte_match != 0) mismatch += 1 ;
0708
0709 LOG_IF(fatal, mismatch != 0) << " mismatch FAIL for " << name ;
0710 if( mismatch != 0 ) std::cout
0711 << " mismatch FAIL for " << name
0712 << " a.size " << a.size()
0713 << " b.size " << b.size()
0714 << std::endl
0715 ;
0716 return mismatch ;
0717 }
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731 template<typename T>
0732 int CSGFoundry::CompareStruct( const char* name, const std::vector<T>& aa, const std::vector<T>& bb )
0733 {
0734 int mismatch = 0 ;
0735
0736 bool size_match = aa.size() == bb.size() ;
0737 LOG_IF(info, !size_match) << name << " size_match FAIL " << aa.size() << " vs " << bb.size() ;
0738 if(!size_match) mismatch += 1 ;
0739 if(!size_match) return mismatch ;
0740
0741 int num_struct = aa.size();
0742 int num_diff = 0 ;
0743 for(int i=0 ; i < num_struct ; i++)
0744 {
0745 const T& a = aa[i] ;
0746 const T& b = bb[i] ;
0747 bool is_diff = T::IsDiff( a, b );
0748 if( is_diff ) num_diff += 1 ;
0749 }
0750 if(num_diff != 0 ) mismatch += 1 ;
0751
0752 LOG_IF(fatal, mismatch != 0) << " mismatch FAIL for " << name ;
0753 if( mismatch != 0 ) std::cout
0754 << " mismatch FAIL for " << name
0755 << " aa.size " << aa.size()
0756 << " bb.size " << bb.size()
0757 << " num_diff " << num_diff
0758 << " mismatch " << mismatch
0759 << std::endl
0760 ;
0761 return mismatch ;
0762 }
0763
0764 int CSGFoundry::CompareFloat4( const char* name, const std::vector<float4>& aa, const std::vector<float4>& bb )
0765 {
0766 int mismatch = 0 ;
0767 bool size_match = aa.size() == bb.size() ;
0768 LOG_IF(info, !size_match) << name << " size_match FAIL " << aa.size() << " vs " << bb.size() ;
0769 if(!size_match) mismatch += 1 ;
0770 if(!size_match) return mismatch ;
0771
0772 int num_struct = aa.size();
0773 int num_diff = 0 ;
0774 for(int i=0 ; i < num_struct ; i++)
0775 {
0776 const float4& a = aa[i] ;
0777 const float4& b = bb[i] ;
0778 bool is_diff = Float4_IsDiff( a, b );
0779 if( is_diff ) num_diff += 1 ;
0780 }
0781 if(num_diff != 0 ) mismatch += 1 ;
0782
0783 LOG_IF(fatal, mismatch != 0) << " mismatch FAIL for " << name ;
0784 if( mismatch != 0 ) std::cout
0785 << " mismatch FAIL for " << name
0786 << " aa.size " << aa.size()
0787 << " bb.size " << bb.size()
0788 << " num_diff " << num_diff
0789 << " mismatch " << mismatch
0790 << std::endl
0791 ;
0792 return mismatch ;
0793 }
0794
0795 bool CSGFoundry::Float4_IsDiff( const float4& a , const float4& b )
0796 {
0797 return false ;
0798 }
0799
0800
0801 int CSGFoundry::CompareBytes(const void* a, const void* b, unsigned num_bytes)
0802 {
0803 const char* ca = (const char*)a ;
0804 const char* cb = (const char*)b ;
0805 int mismatch = 0 ;
0806 for(int i=0 ; i < int(num_bytes) ; i++ ) if( ca[i] != cb[i] ) mismatch += 1 ;
0807 return mismatch ;
0808 }
0809
0810
0811 template int CSGFoundry::CompareVec(const char*, const std::vector<CSGSolid>& a, const std::vector<CSGSolid>& b ) ;
0812 template int CSGFoundry::CompareVec(const char*, const std::vector<CSGPrim>& a, const std::vector<CSGPrim>& b ) ;
0813 template int CSGFoundry::CompareVec(const char*, const std::vector<CSGNode>& a, const std::vector<CSGNode>& b ) ;
0814 template int CSGFoundry::CompareVec(const char*, const std::vector<float4>& a, const std::vector<float4>& b ) ;
0815 template int CSGFoundry::CompareVec(const char*, const std::vector<qat4>& a, const std::vector<qat4>& b ) ;
0816 template int CSGFoundry::CompareVec(const char*, const std::vector<unsigned>& a, const std::vector<unsigned>& b ) ;
0817
0818
0819 void CSGFoundry::summary(const char* msg ) const
0820 {
0821 LOG(info) << msg << std::endl << descSolids() ;
0822 }
0823
0824 std::string CSGFoundry::descSolids() const
0825 {
0826 unsigned num_solids = getNumSolid();
0827 std::stringstream ss ;
0828 ss
0829 << "CSGFoundry::descSolids"
0830 << " num_solids " << num_solids
0831 << std::endl
0832 ;
0833
0834 for(unsigned i=0 ; i < num_solids ; i++)
0835 {
0836 const CSGSolid* so = getSolid(i);
0837 ss << " " << so->desc() << std::endl ;
0838 }
0839 std::string s = ss.str();
0840 return s ;
0841 }
0842
0843 std::string CSGFoundry::descInstance() const
0844 {
0845 std::vector<int>* idxs = ssys::getenv_vec<int>("IDX", nullptr, ',');
0846
0847 std::stringstream ss ;
0848 if(idxs == nullptr)
0849 {
0850 ss << " no IDX " << std::endl ;
0851 }
0852 else
0853 {
0854 for(unsigned i=0 ; i < idxs->size() ; i++)
0855 {
0856 int idx = (*idxs)[i] ;
0857 ss << descInstance(idx) ;
0858 }
0859 }
0860 std::string s = ss.str();
0861 return s ;
0862 }
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875 std::string CSGFoundry::descInstance(unsigned idx) const
0876 {
0877 std::stringstream ss ;
0878 ss << "CSGFoundry::descInstance"
0879 << " idx " << std::setw(7) << idx
0880 << " inst.size " << std::setw(7) << inst.size()
0881 ;
0882
0883 if(idx >= inst.size() )
0884 {
0885 ss << " idx OUT OF RANGE " ;
0886 }
0887 else
0888 {
0889 const qat4& q = inst[idx] ;
0890 int ins_idx, gas_idx, sensor_identifier, sensor_index ;
0891 q.getIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0892
0893
0894 const CSGSolid* so = getSolid(gas_idx);
0895
0896 ss << " idx " << std::setw(7) << idx
0897 << " ins " << std::setw(5) << ins_idx
0898 << " gas " << std::setw(2) << gas_idx
0899 << " s_ident " << std::setw(7) << sensor_identifier
0900 << " s_index " << std::setw(5) << sensor_index
0901 << " so " << so->desc()
0902 ;
0903 }
0904 ss << std::endl ;
0905 std::string s = ss.str();
0906 return s ;
0907 }
0908
0909
0910 std::string CSGFoundry::descInst(unsigned ias_idx_, unsigned long long emm ) const
0911 {
0912 std::stringstream ss ;
0913 for(unsigned i=0 ; i < inst.size() ; i++)
0914 {
0915 const qat4& q = inst[i] ;
0916 int ins_idx, gas_idx, sensor_identifier, sensor_index ;
0917 q.getIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0918
0919 bool gas_enabled = emm == 0ull ? true : ( emm & (0x1ull << gas_idx)) ;
0920 if( gas_enabled )
0921 {
0922 const CSGSolid* so = getSolid(gas_idx);
0923 ss
0924 << " i " << std::setw(5) << i
0925 << " ins " << std::setw(5) << ins_idx
0926 << " gas " << std::setw(2) << gas_idx
0927 << " s_identifier " << std::setw(7) << sensor_identifier
0928 << " s_index " << std::setw(5) << sensor_index
0929 << " so " << so->desc()
0930 << std::endl
0931 ;
0932 }
0933 }
0934 std::string s = ss.str();
0935 return s ;
0936 }
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954 AABB CSGFoundry::iasBB(unsigned ias_idx_, unsigned long long emm ) const
0955 {
0956 AABB bb = {} ;
0957 std::vector<float3> corners ;
0958 for(unsigned i=0 ; i < inst.size() ; i++)
0959 {
0960 const qat4& q = inst[i] ;
0961
0962 int ins_idx, gas_idx, sensor_identifier, sensor_index ;
0963 q.getIdentity(ins_idx, gas_idx, sensor_identifier, sensor_index );
0964
0965
0966 bool gas_enabled = emm == 0ull ? true : ( emm & (0x1ull << gas_idx)) ;
0967 if( gas_enabled )
0968 {
0969 const CSGSolid* so = getSolid(gas_idx);
0970 corners.clear();
0971 AABB::cube_corners(corners, so->center_extent);
0972 q.right_multiply_inplace( corners, 1.f );
0973 for(int i=0 ; i < int(corners.size()) ; i++) bb.include_point(corners[i]) ;
0974 }
0975 }
0976 return bb ;
0977 }
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990 float CSGFoundry::getMaxExtent(const std::vector<unsigned>& solid_selection) const
0991 {
0992 float mxe = 0.f ;
0993 for(unsigned i=0 ; i < solid_selection.size() ; i++)
0994 {
0995 unsigned gas_idx = solid_selection[i] ;
0996 const CSGSolid* so = getSolid(gas_idx);
0997 float4 ce = so->center_extent ;
0998 if(ce.w > mxe) mxe = ce.w ;
0999 LOG(info) << " gas_idx " << std::setw(3) << gas_idx << " ce " << ce << " mxe " << mxe ;
1000 }
1001 return mxe ;
1002 }
1003
1004 std::string CSGFoundry::descSolids(const std::vector<unsigned>& solid_selection) const
1005 {
1006 std::stringstream ss ;
1007 ss << "CSGFoundry::descSolids solid_selection " << solid_selection.size() << std::endl ;
1008 for(unsigned i=0 ; i < solid_selection.size() ; i++)
1009 {
1010 unsigned gas_idx = solid_selection[i] ;
1011 const CSGSolid* so = getSolid(gas_idx);
1012
1013
1014 ss << so->desc() << std::endl ;
1015 }
1016 std::string s = ss.str();
1017 return s ;
1018 }
1019
1020 void CSGFoundry::gasCE(float4& ce, unsigned gas_idx ) const
1021 {
1022 const CSGSolid* so = getSolid(gas_idx);
1023 ce.x = so->center_extent.x ;
1024 ce.y = so->center_extent.y ;
1025 ce.z = so->center_extent.z ;
1026 ce.w = so->center_extent.w ;
1027 }
1028
1029 void CSGFoundry::gasCE(float4& ce, const std::vector<unsigned>& gas_idxs ) const
1030 {
1031 unsigned middle = gas_idxs.size()/2 ;
1032 unsigned gas_idx = gas_idxs[middle];
1033
1034 const CSGSolid* so = getSolid(gas_idx);
1035 ce.x = so->center_extent.x ;
1036 ce.y = so->center_extent.y ;
1037 ce.z = so->center_extent.z ;
1038 ce.w = so->center_extent.w ;
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053 void CSGFoundry::iasCE(float4& ce, unsigned ias_idx_, unsigned long long emm ) const
1054 {
1055 AABB bb = iasBB(ias_idx_, emm);
1056 bb.center_extent(ce) ;
1057 }
1058
1059 float4 CSGFoundry::iasCE(unsigned ias_idx_, unsigned long long emm ) const
1060 {
1061 float4 ce = make_float4( 0.f, 0.f, 0.f, 0.f );
1062 iasCE(ce, ias_idx_, emm );
1063 return ce ;
1064 }
1065
1066
1067 void CSGFoundry::dump() const
1068 {
1069 LOG(info) << "[" ;
1070 dumpPrim();
1071 dumpNode();
1072
1073 LOG(info) << "]" ;
1074 }
1075
1076 void CSGFoundry::dumpSolid() const
1077 {
1078 unsigned num_solid = getNumSolid();
1079 for(unsigned solidIdx=0 ; solidIdx < num_solid ; solidIdx++)
1080 {
1081 dumpSolid(solidIdx);
1082 }
1083 }
1084
1085 void CSGFoundry::dumpSolid(unsigned solidIdx) const
1086 {
1087 const CSGSolid* so = solid.data() + solidIdx ;
1088 int primOffset = so->primOffset ;
1089 int numPrim = so->numPrim ;
1090
1091 std::cout
1092 << " solidIdx " << std::setw(3) << solidIdx
1093 << so->desc()
1094 << " primOffset " << std::setw(5) << primOffset
1095 << " numPrim " << std::setw(5) << numPrim
1096 << std::endl
1097 ;
1098
1099 for(int primIdx=so->primOffset ; primIdx < primOffset + numPrim ; primIdx++)
1100 {
1101 const CSGPrim* pr = prim.data() + primIdx ;
1102 int nodeOffset = pr->nodeOffset() ;
1103 int numNode = pr->numNode() ;
1104
1105 std::cout
1106 << " primIdx " << std::setw(3) << primIdx << " "
1107 << pr->desc()
1108 << " nodeOffset " << std::setw(4) << nodeOffset
1109 << " numNode " << std::setw(4) << numNode
1110 << std::endl
1111 ;
1112
1113 for(int nodeIdx=nodeOffset ; nodeIdx < nodeOffset + numNode ; nodeIdx++)
1114 {
1115 const CSGNode* nd = node.data() + nodeIdx ;
1116 std::cout << nd->desc() << std::endl ;
1117 }
1118 }
1119 }
1120
1121
1122 int CSGFoundry::findSolidIdx(const char* label) const
1123 {
1124 int idx = -1 ;
1125 if( label == nullptr ) return idx ;
1126 for(unsigned i=0 ; i < solid.size() ; i++)
1127 {
1128 const CSGSolid& so = solid[i];
1129 if(strcmp(so.label, label) == 0) idx = i ;
1130 }
1131 return idx ;
1132 }
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148 void CSGFoundry::findSolidIdx(std::vector<unsigned>& solid_idx, const char* label) const
1149 {
1150 if( label == nullptr ) return ;
1151
1152 std::vector<unsigned>& ss = solid_idx ;
1153
1154 std::vector<std::string> elem ;
1155 SStr::Split(label, ',', elem );
1156
1157 for(unsigned i=0 ; i < elem.size() ; i++)
1158 {
1159 const std::string& ele = elem[i] ;
1160 for(unsigned j=0 ; j < solid.size() ; j++)
1161 {
1162 const CSGSolid& so = solid[j];
1163
1164 bool match = SStr::SimpleMatch(so.label, ele.c_str()) ;
1165 unsigned count = std::count(ss.begin(), ss.end(), j );
1166 if(match && count == 0) ss.push_back(j) ;
1167 }
1168 }
1169
1170 }
1171
1172 std::string CSGFoundry::descSolidIdx( const std::vector<unsigned>& solid_idx )
1173 {
1174 std::stringstream ss ;
1175 ss << "(" ;
1176 for(int i=0 ; i < int(solid_idx.size()) ; i++) ss << solid_idx[i] << " " ;
1177 ss << ")" ;
1178 std::string s = ss.str() ;
1179 return s ;
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 void CSGFoundry::dumpPrim() const
1189 {
1190 std::string s = descPrim();
1191 LOG(info) << s ;
1192 }
1193
1194 std::string CSGFoundry::descPrim() const
1195 {
1196 std::stringstream ss ;
1197 for(unsigned idx=0 ; idx < solid.size() ; idx++) ss << descPrim(idx);
1198 std::string s = ss.str();
1199 return s ;
1200 }
1201
1202 std::string CSGFoundry::descPrim(unsigned solidIdx) const
1203 {
1204 const CSGSolid* so = getSolid(solidIdx);
1205 assert(so);
1206
1207 std::stringstream ss ;
1208 ss << std::endl << so->desc() << std::endl ;
1209
1210 for(int primIdx=so->primOffset ; primIdx < so->primOffset+so->numPrim ; primIdx++)
1211 {
1212 const CSGPrim* pr = getPrim(primIdx) ;
1213 assert(pr) ;
1214 ss << " primIdx " << std::setw(5) << primIdx << " : " << pr->desc() << std::endl ;
1215 }
1216
1217 std::string s = ss.str();
1218 return s ;
1219 }
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229 std::string CSGFoundry::detailPrim() const
1230 {
1231 std::stringstream ss ;
1232 int numPrim = getNumPrim() ;
1233 assert( int(prim.size()) == numPrim );
1234 for(int primIdx=0 ; primIdx < std::min(10000, numPrim) ; primIdx++) ss << detailPrim(primIdx) << std::endl ;
1235 std::string s = ss.str();
1236 return s ;
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250 int CSGFoundry::getPrimBoundary(unsigned primIdx) const
1251 {
1252 const CSGPrim* pr = getPrim(primIdx);
1253 return getPrimBoundary_(pr) ;
1254 }
1255
1256 int CSGFoundry::getPrimBoundary_( const CSGPrim* pr ) const
1257 {
1258 int nodeOffset = pr->nodeOffset() ;
1259 int numNode = pr->numNode() ;
1260 std::set<unsigned> bnd ;
1261 for(int nodeIdx=nodeOffset ; nodeIdx < nodeOffset + numNode ; nodeIdx++)
1262 {
1263 const CSGNode* nd = getNode(nodeIdx);
1264 bnd.insert(nd->boundary());
1265 }
1266 assert( bnd.size() == 1 );
1267 int boundary = bnd.begin() == bnd.end() ? -1 : *bnd.begin() ;
1268 return boundary ;
1269 }
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290 void CSGFoundry::setPrimBoundary(unsigned primIdx, unsigned boundary )
1291 {
1292 const CSGPrim* pr = getPrim(primIdx);
1293 assert( pr );
1294 for(int nodeIdx=pr->nodeOffset() ; nodeIdx < pr->nodeOffset() + pr->numNode() ; nodeIdx++)
1295 {
1296 CSGNode* nd = getNode_(nodeIdx);
1297 nd->setBoundary(boundary);
1298 }
1299 }
1300
1301
1302
1303
1304
1305 std::string CSGFoundry::detailPrim(unsigned primIdx) const
1306 {
1307 const CSGPrim* pr = getPrim(primIdx);
1308 unsigned gasIdx = pr->repeatIdx();
1309 unsigned meshIdx = pr->meshIdx();
1310 unsigned pr_primIdx = pr->primIdx();
1311 const char* meshName = id->getName(meshIdx);
1312
1313 int numNode = pr->numNode() ;
1314 int nodeOffset = pr->nodeOffset() ;
1315 int boundary = getPrimBoundary(primIdx);
1316 const char* bndName = sim ? sim->getBndName(boundary) : "-bd" ;
1317
1318 float4 ce = pr->ce();
1319
1320 std::stringstream ss ;
1321 ss
1322 << std::setw(10) << SStr::Format(" pri:%d", primIdx )
1323 << std::setw(10) << SStr::Format(" lpr:%d", pr_primIdx )
1324 << std::setw(8) << SStr::Format(" gas:%d", gasIdx )
1325 << std::setw(8) << SStr::Format(" msh:%d", meshIdx)
1326 << std::setw(8) << SStr::Format(" bnd:%d", boundary)
1327 << std::setw(8) << SStr::Format(" nno:%d", numNode )
1328 << std::setw(10) << SStr::Format(" nod:%d", nodeOffset )
1329 << " ce "
1330 << "(" << std::setw(10) << std::fixed << std::setprecision(2) << ce.x
1331 << "," << std::setw(10) << std::fixed << std::setprecision(2) << ce.y
1332 << "," << std::setw(10) << std::fixed << std::setprecision(2) << ce.z
1333 << "," << std::setw(10) << std::fixed << std::setprecision(2) << ce.w
1334 << ")"
1335 << " meshName " << std::setw(15) << ( meshName ? meshName : "-" )
1336 << " bndName " << std::setw(15) << ( bndName ? bndName : "-" )
1337 ;
1338
1339 std::string s = ss.str();
1340 return s ;
1341 }
1342
1343
1344
1345
1346 std::string CSGFoundry::descPrimSpec() const
1347 {
1348 unsigned num_solids = getNumSolid();
1349 std::stringstream ss ;
1350 ss
1351 << "CSGFoundry::descPrimSpec"
1352 << " num_solids " << num_solids
1353 << std::endl
1354 ;
1355
1356 for(unsigned i=0 ; i < num_solids ; i++) ss << descPrimSpec(i) << std::endl ;
1357
1358 std::string s = ss.str();
1359 return s ;
1360 }
1361
1362 std::string CSGFoundry::descPrimSpec(unsigned solidIdx) const
1363 {
1364 unsigned gas_idx = solidIdx ;
1365 SCSGPrimSpec ps = getPrimSpec(gas_idx);
1366 return ps.desc() ;
1367 }
1368
1369
1370
1371
1372
1373
1374 void CSGFoundry::dumpPrim(unsigned solidIdx) const
1375 {
1376 std::string s = descPrim(solidIdx);
1377 LOG(info) << std::endl << s ;
1378 }
1379
1380
1381 void CSGFoundry::getNodePlanes(std::vector<float4>& planes, const CSGNode* nd) const
1382 {
1383 unsigned tc = nd->typecode();
1384 bool has_planes = CSG::HasPlanes(tc) ;
1385 if(has_planes)
1386 {
1387 for(unsigned planIdx=nd->planeIdx() ; planIdx < nd->planeIdx() + nd->planeNum() ; planIdx++)
1388 {
1389 const float4* pl = getPlan(planIdx);
1390 planes.push_back(*pl);
1391 }
1392 }
1393 }
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405 const CSGPrim* CSGFoundry::getSolidPrim(unsigned solidIdx, unsigned primIdxRel) const
1406 {
1407 const CSGSolid* so = getSolid(solidIdx);
1408 LOG_IF(fatal, so == nullptr) << "Failed to getSolid solidIdx " << solidIdx ;
1409 assert(so);
1410
1411 unsigned primIdx = so->primOffset + primIdxRel ;
1412 const CSGPrim* pr = getPrim(primIdx);
1413 LOG_IF(fatal, pr == nullptr) << "Failed to getPrim primIdxRel " << primIdxRel ;
1414 assert(pr);
1415
1416 return pr ;
1417 }
1418
1419
1420
1421
1422
1423
1424
1425
1426 void CSGFoundry::dumpNode() const
1427 {
1428 LOG(info) << std::endl << descNode();
1429 }
1430
1431 void CSGFoundry::dumpNode(unsigned solidIdx) const
1432 {
1433 LOG(info) << std::endl << descNode(solidIdx);
1434 }
1435
1436 std::string CSGFoundry::descNode() const
1437 {
1438 std::stringstream ss ;
1439 for(unsigned idx=0 ; idx < solid.size() ; idx++) ss << descNode(idx) << std::endl ;
1440 std::string s = ss.str();
1441 return s ;
1442 }
1443
1444 std::string CSGFoundry::descNode(unsigned solidIdx) const
1445 {
1446 const CSGSolid* so = solid.data() + solidIdx ;
1447
1448
1449
1450 std::stringstream ss ;
1451 ss << std::endl << so->desc() << std::endl ;
1452
1453 for(int primIdx=so->primOffset ; primIdx < so->primOffset+so->numPrim ; primIdx++)
1454 {
1455 const CSGPrim* pr = prim.data() + primIdx ;
1456 int numNode = pr->numNode() ;
1457 for(int nodeIdx=pr->nodeOffset() ; nodeIdx < pr->nodeOffset()+numNode ; nodeIdx++)
1458 {
1459 const CSGNode* nd = node.data() + nodeIdx ;
1460 ss << " nodeIdx " << std::setw(5) << nodeIdx << " : " << nd->desc() << std::endl ;
1461 }
1462 }
1463
1464 std::string s = ss.str();
1465 return s ;
1466 }
1467
1468 std::string CSGFoundry::descTran(unsigned solidIdx) const
1469 {
1470 const CSGSolid* so = solid.data() + solidIdx ;
1471
1472
1473
1474 std::stringstream ss ;
1475 ss << std::endl << so->desc() << std::endl ;
1476
1477 for(int primIdx=so->primOffset ; primIdx < so->primOffset+so->numPrim ; primIdx++)
1478 {
1479 const CSGPrim* pr = prim.data() + primIdx ;
1480 int numNode = pr->numNode() ;
1481 for(int nodeIdx=pr->nodeOffset() ; nodeIdx < pr->nodeOffset()+numNode ; nodeIdx++)
1482 {
1483 const CSGNode* nd = node.data() + nodeIdx ;
1484 unsigned tranIdx = nd->gtransformIdx();
1485
1486 const qat4* tr = tranIdx > 0 ? getTran(tranIdx-1) : nullptr ;
1487 const qat4* it = tranIdx > 0 ? getItra(tranIdx-1) : nullptr ;
1488 ss << " tranIdx " << std::setw(5) << tranIdx << " : " << ( tr ? tr->desc('t') : "" ) << std::endl ;
1489 ss << " tranIdx " << std::setw(5) << tranIdx << " : " << ( it ? it->desc('i') : "" ) << std::endl ;
1490 }
1491 }
1492 std::string s = ss.str();
1493 return s ;
1494 }
1495
1496
1497
1498 const CSGNode* CSGFoundry::getSolidPrimNode(unsigned solidIdx, unsigned primIdxRel, unsigned nodeIdxRel) const
1499 {
1500 const CSGPrim* pr = getSolidPrim(solidIdx, primIdxRel);
1501 assert(pr);
1502 unsigned nodeIdx = pr->nodeOffset() + nodeIdxRel ;
1503 const CSGNode* nd = getNode(nodeIdx);
1504 assert(nd);
1505 return nd ;
1506 }
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542 SCSGPrimSpec CSGFoundry::getPrimSpec(unsigned solidIdx) const
1543 {
1544 SCSGPrimSpec ps = d_prim ? getPrimSpecDevice(solidIdx) : getPrimSpecHost(solidIdx) ;
1545 LOG_IF(info, ps.device == false) << "WARNING using host PrimSpec, upload first " ;
1546 return ps ;
1547 }
1548 SCSGPrimSpec CSGFoundry::getPrimSpecHost(unsigned solidIdx) const
1549 {
1550 const CSGSolid* so = solid.data() + solidIdx ;
1551 SCSGPrimSpec ps = CSGPrim::MakeSpec( prim.data(), so->primOffset, so->numPrim ); ;
1552 ps.device = false ;
1553 return ps ;
1554 }
1555 SCSGPrimSpec CSGFoundry::getPrimSpecDevice(unsigned solidIdx) const
1556 {
1557 assert( d_prim );
1558 const CSGSolid* so = solid.data() + solidIdx ;
1559 SCSGPrimSpec ps = CSGPrim::MakeSpec( d_prim, so->primOffset, so->numPrim ); ;
1560 ps.device = true ;
1561 return ps ;
1562 }
1563
1564 void CSGFoundry::checkPrimSpec(unsigned solidIdx) const
1565 {
1566 SCSGPrimSpec ps = getPrimSpec(solidIdx);
1567 LOG(info) << "[ solidIdx " << solidIdx ;
1568 ps.downloadDump();
1569 LOG(info) << "] solidIdx " << solidIdx ;
1570 }
1571
1572 void CSGFoundry::checkPrimSpec() const
1573 {
1574 for(unsigned solidIdx = 0 ; solidIdx < getNumSolid() ; solidIdx++)
1575 {
1576 checkPrimSpec(solidIdx);
1577 }
1578 }
1579
1580 const char* CSGFoundry::getSolidLabel_(int ridx) const
1581 {
1582 const CSGSolid* so = getSolid(ridx);
1583 assert(so);
1584 return so ? so->label : nullptr ;
1585 }
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 char CSGFoundry::getSolidIntent(int ridx) const
1596 {
1597 const CSGSolid* so = getSolid(ridx);
1598 assert(so);
1599 return so ? so->getIntent() : '\0' ;
1600 }
1601
1602
1603 std::string CSGFoundry::descSolidIntent() const
1604 {
1605 unsigned num_solid = getNumSolid() ;
1606 std::stringstream ss ;
1607 ss << "CSGFoundry::descSolidIntent num_solid " << num_solid << "\n" ;
1608 for(unsigned i=0 ; i < num_solid ; i++)
1609 {
1610 char slpx = getSolidIntent(i);
1611 const char* sl = getSolidLabel_(i);
1612 const std::string& smml = getSolidMMLabel(i) ;
1613 ss
1614 << " i " << std::setw(4) << i
1615 << " getSolidIntent " << std::setw(2) << slpx
1616 << " getSolidLabel_ " << std::setw(10) << ( sl ? sl : "-" )
1617 << " getSolidMMLabel " << smml
1618 << "\n"
1619 ;
1620 }
1621 std::string str = ss.str();
1622 return str ;
1623 }
1624
1625
1626
1627 unsigned CSGFoundry::getNumSolid(int type_) const
1628 {
1629 unsigned count = 0 ;
1630 for(unsigned i=0 ; i < solid.size() ; i++)
1631 {
1632 const CSGSolid* so = getSolid(i);
1633 if(so && so->type == type_ ) count += 1 ;
1634 }
1635 return count ;
1636 }
1637
1638
1639
1640 unsigned CSGFoundry::getNumSolid() const { return getNumSolid(STANDARD_SOLID); }
1641 unsigned CSGFoundry::getNumSolidTotal() const { return solid.size(); }
1642
1643
1644
1645 unsigned CSGFoundry::getNumPrim() const { return prim.size(); }
1646 unsigned CSGFoundry::getNumNode() const { return node.size(); }
1647 unsigned CSGFoundry::getNumPlan() const { return plan.size(); }
1648 unsigned CSGFoundry::getNumTran() const { return tran.size(); }
1649 unsigned CSGFoundry::getNumItra() const { return itra.size(); }
1650 unsigned CSGFoundry::getNumInst() const { return inst.size(); }
1651
1652 const CSGSolid* CSGFoundry::getSolid(unsigned solidIdx) const { return solidIdx < solid.size() ? solid.data() + solidIdx : nullptr ; }
1653 const CSGPrim* CSGFoundry::getPrim(unsigned primIdx) const { return primIdx < prim.size() ? prim.data() + primIdx : nullptr ; }
1654 const CSGNode* CSGFoundry::getNode(unsigned nodeIdx) const { return nodeIdx < node.size() ? node.data() + nodeIdx : nullptr ; }
1655 CSGNode* CSGFoundry::getNode_(unsigned nodeIdx) { return nodeIdx < node.size() ? node.data() + nodeIdx : nullptr ; }
1656
1657 const float4* CSGFoundry::getPlan(unsigned planIdx) const { return planIdx < plan.size() ? plan.data() + planIdx : nullptr ; }
1658 const qat4* CSGFoundry::getTran(unsigned tranIdx) const { return tranIdx < tran.size() ? tran.data() + tranIdx : nullptr ; }
1659 const qat4* CSGFoundry::getItra(unsigned itraIdx) const { return itraIdx < itra.size() ? itra.data() + itraIdx : nullptr ; }
1660 const qat4* CSGFoundry::getInst(unsigned instIdx) const { return instIdx < inst.size() ? inst.data() + instIdx : nullptr ; }
1661
1662
1663
1664
1665
1666
1667 const CSGSolid* CSGFoundry::getSolid_(int solidIdx_) const {
1668 unsigned solidIdx = solidIdx_ < 0 ? unsigned(solid.size() + solidIdx_) : unsigned(solidIdx_) ;
1669 return getSolid(solidIdx);
1670 }
1671
1672 const CSGSolid* CSGFoundry::getSolidByName(const char* name) const
1673 {
1674 unsigned missing = ~0u ;
1675 unsigned idx = missing ;
1676 for(unsigned i=0 ; i < solid.size() ; i++) if(strcmp(solid[i].label, name) == 0) idx = i ;
1677 assert( idx != missing );
1678 return getSolid(idx) ;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689 unsigned CSGFoundry::getSolidIdx(const CSGSolid* so) const
1690 {
1691 unsigned idx = ~0u ;
1692 for(unsigned i=0 ; i < solid.size() ; i++)
1693 {
1694 const CSGSolid* s = solid.data() + i ;
1695 LOG(info) << " i " << i << " s " << s << " so " << so ;
1696 if(s == so) idx = i ;
1697 }
1698 assert( idx != ~0u );
1699 return idx ;
1700 }
1701
1702
1703
1704
1705 void CSGFoundry::makeDemoSolids()
1706 {
1707 maker->makeDemoSolids();
1708 }
1709 CSGSolid* CSGFoundry::make(const char* name)
1710 {
1711 return maker->make(name);
1712 }
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 void CSGFoundry::importSim()
1725 {
1726 assert(sim);
1727 import->import();
1728 }
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752 int CSGFoundry::addNode_solidLocalNodeIdx() const
1753 {
1754 LOG_IF(fatal, !last_added_solid) << "must addSolid prior to addPrim and addNode " ;
1755 assert( last_added_solid );
1756
1757 unsigned primOffset = last_added_solid->primOffset ;
1758 const CSGPrim* first_prim_of_last_added_solid = prim.data() + primOffset ;
1759 assert( first_prim_of_last_added_solid ) ;
1760 int nodeOffset = first_prim_of_last_added_solid->nodeOffset() ;
1761
1762 int globalNodeIdx = node.size();
1763 int solidLocalNodeIdx = globalNodeIdx - nodeOffset ;
1764
1765 return solidLocalNodeIdx ;
1766 }
1767
1768
1769 CSGNode* CSGFoundry::addNode(CSGNode nd)
1770 {
1771 LOG_IF(fatal, !last_added_prim) << "must addPrim prior to addNode" ;
1772 assert( last_added_prim );
1773
1774 unsigned globalNodeIdx = node.size() ;
1775
1776 unsigned nodeOffset = last_added_prim->nodeOffset();
1777 unsigned numNode = last_added_prim->numNode();
1778 unsigned localNodeIdx = globalNodeIdx - nodeOffset ;
1779
1780 bool ok_localNodeIdx = localNodeIdx < numNode ;
1781 LOG_IF(fatal, !ok_localNodeIdx)
1782 << " TOO MANY addNode FOR Prim "
1783 << " localNodeIdx " << localNodeIdx
1784 << " numNode " << numNode
1785 << " globalNodeIdx " << globalNodeIdx
1786 << " (must addNode only up to the declared numNode from the addPrim call) "
1787 ;
1788 assert( ok_localNodeIdx );
1789
1790 bool ok_globalNodeIdx = globalNodeIdx < IMAX ;
1791 LOG_IF(fatal, !ok_globalNodeIdx)
1792 << " FATAL : OUT OF RANGE "
1793 << " globalNodeIdx " << globalNodeIdx
1794 << " IMAX " << IMAX
1795 ;
1796 assert( ok_globalNodeIdx );
1797
1798
1799 int solidLocalNodeIdx = addNode_solidLocalNodeIdx() ;
1800
1801 node.push_back(nd);
1802 last_added_node = node.data() + globalNodeIdx ;
1803
1804 last_added_node->setIndex( solidLocalNodeIdx );
1805
1806 return last_added_node ;
1807 }
1808
1809
1810 CSGNode* CSGFoundry::addNode()
1811 {
1812 CSGNode nd = CSGNode::Zero() ;
1813 return addNode(nd);
1814 }
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832 CSGNode* CSGFoundry::addNode(CSGNode nd, const std::vector<float4>* pl, const Tran<double>* tr )
1833 {
1834 CSGNode* n = addNode(nd) ;
1835 unsigned num_planes = pl ? pl->size() : 0 ;
1836 if(num_planes > 0)
1837 {
1838 n->setTypecode(CSG_CONVEXPOLYHEDRON) ;
1839 n->setPlaneIdx(plan.size());
1840 n->setPlaneNum(num_planes);
1841 for(unsigned i=0 ; i < num_planes ; i++) addPlan((*pl)[i]);
1842 }
1843 if(tr)
1844 {
1845 unsigned trIdx = 1u + addTran(tr);
1846 n->setTransform(trIdx);
1847 }
1848 return n ;
1849 }
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867 CSGNode* CSGFoundry::addNodes(const std::vector<CSGNode>& nds )
1868 {
1869 unsigned idx = node.size() ;
1870 for(unsigned i=0 ; i < nds.size() ; i++)
1871 {
1872 const CSGNode& nd = nds[i];
1873 idx = node.size() ;
1874 assert( idx < IMAX );
1875 node.push_back(nd);
1876 }
1877 return node.data() + idx ;
1878 }
1879
1880 CSGNode* CSGFoundry::addNode(AABB& bb, CSGNode nd )
1881 {
1882 CSGNode* n = addNode(nd);
1883 bb.include_aabb( n->AABB() );
1884 return n ;
1885 }
1886
1887 CSGNode* CSGFoundry::addNodes(AABB& bb, std::vector<CSGNode>& nds, const std::vector<const Tran<double>*>* trs )
1888 {
1889 if( trs == nullptr ) return addNodes(nds);
1890
1891 unsigned num_nd = nds.size() ;
1892 unsigned num_tr = trs ? trs->size() : 0 ;
1893 if( num_tr > 0 ) assert( num_nd == num_tr );
1894
1895 CSGNode* n = nullptr ;
1896 for(unsigned i=0 ; i < num_nd ; i++)
1897 {
1898 CSGNode& nd = nds[i];
1899 const Tran<double>* tr = trs ? (*trs)[i] : nullptr ;
1900 n = addNode(nd);
1901 if(tr)
1902 {
1903 bool transform_node_aabb = true ;
1904 addNodeTran(n, tr, transform_node_aabb );
1905 }
1906 bb.include_aabb( n->AABB() );
1907 }
1908 return n ;
1909 }
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924 CSGPrim* CSGFoundry::addPrimNodes(AABB& bb, const std::vector<CSGNode>& nds, const std::vector<const Tran<double>*>* trs )
1925 {
1926 unsigned num_nd = nds.size();
1927 unsigned num_tr = trs ? trs->size() : 0 ;
1928 if( num_tr > 0 ) assert( num_nd == num_tr );
1929
1930 int nodeOffset = -1 ;
1931 CSGPrim* pr = addPrim(num_nd, nodeOffset ) ;
1932
1933 for(unsigned i=0 ; i < num_nd ; i++)
1934 {
1935 const CSGNode& nd = nds[i] ;
1936 const Tran<double>* tr = trs ? (*trs)[i] : nullptr ;
1937 CSGNode* n = addNode(nd);
1938 if(tr)
1939 {
1940 bool transform_node_aabb = true ;
1941 addNodeTran(n, tr, transform_node_aabb );
1942 }
1943 bb.include_aabb( n->AABB() );
1944 }
1945 return pr ;
1946 }
1947
1948
1949
1950
1951
1952
1953
1954 float4* CSGFoundry::addPlan(const float4& pl )
1955 {
1956 unsigned idx = plan.size();
1957 assert( idx < IMAX );
1958 plan.push_back(pl);
1959 return plan.data() + idx ;
1960 }
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972 template<typename T>
1973 unsigned CSGFoundry::addTran( const Tran<T>* tr )
1974 {
1975 return tr == nullptr ? addTran() : addTran_(tr);
1976 }
1977 template unsigned CSGFoundry::addTran<float>(const Tran<float>* ) ;
1978 template unsigned CSGFoundry::addTran<double>(const Tran<double>* ) ;
1979
1980
1981
1982 template<typename T>
1983 unsigned CSGFoundry::addTran_( const Tran<T>* tr )
1984 {
1985 qat4 t(glm::value_ptr(tr->t));
1986 qat4 v(glm::value_ptr(tr->v));
1987 unsigned idx = addTran(&t, &v);
1988 return idx ;
1989 }
1990
1991 template unsigned CSGFoundry::addTran_<float>(const Tran<float>* ) ;
1992 template unsigned CSGFoundry::addTran_<double>(const Tran<double>* ) ;
1993
1994 unsigned CSGFoundry::addTran( const qat4* tr, const qat4* it )
1995 {
1996 unsigned idx = tran.size();
1997 assert( tran.size() == itra.size()) ;
1998 tran.push_back(*tr);
1999 itra.push_back(*it);
2000 return idx ;
2001 }
2002
2003
2004
2005
2006
2007
2008
2009
2010 unsigned CSGFoundry::addTran()
2011 {
2012 qat4 t ;
2013 t.init();
2014 qat4 v ;
2015 v.init();
2016 unsigned idx = addTran(&t, &v);
2017 return idx ;
2018 }
2019
2020
2021
2022
2023
2024
2025
2026
2027 void CSGFoundry::addTranPlaceholder()
2028 {
2029 unsigned idx = tran.size();
2030 assert( tran.size() == itra.size()) ;
2031 if( idx == 0 )
2032 {
2033 addTran();
2034 }
2035 }
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053 template<typename T>
2054 const qat4* CSGFoundry::addNodeTran( CSGNode* nd, const Tran<T>* tr, bool transform_node_aabb )
2055 {
2056 unsigned transform_idx = 1 + addTran(tr);
2057 nd->setTransform(transform_idx);
2058 const qat4* q = getTran(transform_idx-1u) ;
2059
2060 if( transform_node_aabb )
2061 {
2062 q->transform_aabb_inplace( nd->AABB() );
2063 }
2064 return q ;
2065 }
2066
2067
2068 template const qat4* CSGFoundry::addNodeTran<float>( CSGNode* nd, const Tran<float>* , bool ) ;
2069 template const qat4* CSGFoundry::addNodeTran<double>( CSGNode* nd, const Tran<double>*, bool ) ;
2070
2071
2072 void CSGFoundry::addNodeTran(CSGNode* nd )
2073 {
2074 unsigned transform_idx = 1 + addTran();
2075 nd->setTransform(transform_idx);
2076 }
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098 void CSGFoundry::addInstance(const float* tr16, int gas_idx, int sensor_identifier, int sensor_index, bool firstcall )
2099 {
2100 int sensor_identifier_u = 0 ;
2101
2102 if( firstcall )
2103 {
2104 assert( sensor_identifier >= -1 );
2105 sensor_identifier_u = sensor_identifier + 1 ;
2106 }
2107 else
2108 {
2109 assert( sensor_identifier >= 0 );
2110 sensor_identifier_u = sensor_identifier ;
2111 }
2112 assert( sensor_identifier_u >= 0 );
2113
2114
2115 qat4 instance(tr16) ;
2116 int ins_idx = int(inst.size()) ;
2117
2118 instance.setIdentity( ins_idx, gas_idx, sensor_identifier_u, sensor_index );
2119
2120 LOG(debug)
2121 << " firstcall " << ( firstcall ? "YES" : "NO " )
2122 << " ins_idx " << ins_idx
2123 << " gas_idx " << gas_idx
2124 << " sensor_identifier " << sensor_identifier
2125 << " sensor_identifier_u " << sensor_identifier_u
2126 << " sensor_index " << sensor_index
2127 ;
2128
2129 inst.push_back( instance );
2130 }
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154 void CSGFoundry::addInstanceVector( const std::vector<glm::tmat4x4<float>>& v_inst_f4 )
2155 {
2156 assert( inst.size() == 0 );
2157 int num_inst = v_inst_f4.size() ;
2158
2159 for(int i=0 ; i < num_inst ; i++)
2160 {
2161 const glm::tmat4x4<float>& inst_f4 = v_inst_f4[i] ;
2162 const float* tr16 = glm::value_ptr(inst_f4) ;
2163 qat4 instance(tr16) ;
2164 instance.incrementSensorIdentifier() ;
2165 inst.push_back( instance );
2166 }
2167 }
2168
2169
2170
2171 void CSGFoundry::addInstancePlaceholder()
2172 {
2173 const float* tr16 = nullptr ;
2174 int gas_idx = 0 ;
2175 int sensor_identifier = -1 ;
2176 int sensor_index = -1 ;
2177 bool firstcall = true ;
2178
2179
2180
2181
2182 addInstance(tr16, gas_idx, sensor_identifier, sensor_index, firstcall );
2183 }
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194 int CSGFoundry::addPrim_solidLocalPrimIdx() const
2195 {
2196 LOG_IF(fatal, !last_added_solid) << "must addSolid prior to addPrim" ;
2197 assert( last_added_solid );
2198
2199 unsigned primOffset = last_added_solid->primOffset ;
2200 unsigned globalPrimIdx = prim.size();
2201 unsigned localPrimIdx = globalPrimIdx - primOffset ;
2202 return localPrimIdx ;
2203 }
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224 CSGPrim* CSGFoundry::addPrim(int num_node, int nodeOffset_ )
2225 {
2226 LOG_IF(fatal, !last_added_solid) << "must addSolid prior to addPrim" ;
2227 assert( last_added_solid );
2228
2229 unsigned primOffset = last_added_solid->primOffset ;
2230 unsigned numPrim = last_added_solid->numPrim ;
2231
2232 unsigned globalPrimIdx = prim.size();
2233 unsigned localPrimIdx = globalPrimIdx - primOffset ;
2234 int nodeOffset = nodeOffset_ < 0 ? int(node.size()) : nodeOffset_ ;
2235
2236 bool in_global_range = globalPrimIdx < IMAX ;
2237 bool in_local_range = localPrimIdx < numPrim ;
2238
2239 LOG_IF(fatal, !in_global_range )
2240 << " TOO MANY addPrim CALLS "
2241 << " globalPrimIdx " << globalPrimIdx
2242 << " IMAX " << IMAX
2243 << " in_global_range " << in_global_range
2244 ;
2245 assert( in_global_range );
2246
2247 LOG_IF(fatal, !in_local_range)
2248 << " TOO MANY addPrim FOR SOLID "
2249 << " localPrimIdx " << localPrimIdx
2250 << " numPrim " << numPrim
2251 << " globalPrimIdx " << globalPrimIdx
2252 << " in_local_range " << in_local_range
2253 << " (must addPrim only up to to the declared numPrim from the prior addSolid call) "
2254 ;
2255 assert( in_local_range );
2256
2257
2258 CSGPrim pr = {} ;
2259
2260 pr.setNumNode(num_node) ;
2261 pr.setNodeOffset(nodeOffset);
2262 pr.setSbtIndexOffset(localPrimIdx) ;
2263 pr.setMeshIdx(-1) ;
2264
2265 pr.setTranOffset(tran.size());
2266 pr.setPlanOffset(plan.size());
2267
2268 pr.setGlobalPrimIdx(globalPrimIdx);
2269
2270
2271
2272
2273 prim.push_back(pr);
2274
2275 last_added_prim = prim.data() + globalPrimIdx ;
2276 last_added_node = nullptr ;
2277
2278 return last_added_prim ;
2279 }
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289 void CSGFoundry::getMeshPrimCopies(std::vector<CSGPrim>& select_prim, unsigned mesh_idx ) const
2290 {
2291 CSGPrim::select_prim_mesh(prim, select_prim, mesh_idx);
2292 }
2293
2294 void CSGFoundry::getMeshPrimPointers(std::vector<const CSGPrim*>& select_prim, unsigned mesh_idx ) const
2295 {
2296 CSGPrim::select_prim_pointers_mesh(prim, select_prim, mesh_idx);
2297 }
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313 const CSGPrim* CSGFoundry::getMeshPrim( unsigned midx, unsigned mord ) const
2314 {
2315 std::vector<const CSGPrim*> select_prim ;
2316 getMeshPrimPointers(select_prim, midx );
2317
2318 bool mord_in_range = mord < select_prim.size() ;
2319 if(!mord_in_range)
2320 {
2321 LOG(error) << " midx " << midx << " mord " << mord << " select_prim.size " << select_prim.size() << " mord_in_range " << mord_in_range ;
2322 return nullptr ;
2323 }
2324
2325 const CSGPrim* pr = select_prim[mord] ;
2326 return pr ;
2327 }
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339 unsigned CSGFoundry::getNumMeshPrim(unsigned mesh_idx ) const
2340 {
2341 return CSGPrim::count_prim_mesh(prim, mesh_idx);
2342 }
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358 unsigned CSGFoundry::getNumSelectedPrimInSolid(const CSGSolid* solid, const SBitSet* elv ) const
2359 {
2360 unsigned num_selected_prim = 0 ;
2361 for(int primIdx=solid->primOffset ; primIdx < solid->primOffset+solid->numPrim ; primIdx++)
2362 {
2363 const CSGPrim* pr = getPrim(primIdx);
2364 unsigned meshIdx = pr->meshIdx() ;
2365 bool selected = elv == nullptr ? true : elv->is_set(meshIdx) ;
2366 num_selected_prim += int(selected) ;
2367 }
2368 return num_selected_prim ;
2369 }
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400 std::string CSGFoundry::descMeshPrim() const
2401 {
2402 std::stringstream ss ;
2403 unsigned numName = id->getNumName();
2404 ss
2405 << "CSGFoundry::descMeshPrim id.numName " << numName << std::endl
2406 << std::setw(4) << "midx"
2407 << " "
2408 << std::setw(12) << "numMeshPrim"
2409 << " "
2410 << "meshName"
2411 << std::endl
2412 ;
2413
2414 for(unsigned midx=0 ; midx < numName ; midx++)
2415 {
2416 const char* meshName = id->getName(midx);
2417 unsigned numMeshPrim = getNumMeshPrim(midx);
2418 ss
2419 << std::setw(4) << midx
2420 << " "
2421 << std::setw(12) << numMeshPrim
2422 << " "
2423 << meshName
2424 << std::endl
2425 ;
2426 }
2427 return ss.str();
2428 }
2429
2430 std::string CSGFoundry::descPrimRange() const
2431 {
2432 int num_solid = solid.size();
2433 std::stringstream ss ;
2434 ss << "[CSGFoundry::descPrimRange" << " num_solid " << std::setw(2) << num_solid << "\n" ;
2435 for(int i=0 ; i < num_solid ; i++ ) ss << descPrimRange(i) ;
2436 ss << "[CSGFoundry::descPrimRange" << " num_solid " << std::setw(2) << num_solid << "\n" ;
2437 std::string str = ss.str() ;
2438 return str ;
2439 }
2440
2441
2442
2443
2444 std::string CSGFoundry::descPrimRange(int solidIdx) const
2445 {
2446 const CSGSolid& so = solid[solidIdx];
2447 std::string dr = CSGPrim::DescRange(prim.data(), so.primOffset, so.numPrim, &meshname) ;
2448 if(strlen(dr.c_str()) == 0) return "" ;
2449
2450 std::stringstream ss ;
2451 ss
2452 << "[CSGFoundry::descPrimRange" << " solidIdx " << std::setw(2) << solidIdx
2453 << " so.primOffset " << std::setw(5) << so.primOffset
2454 << " so.numPrim " << std::setw(5) << so.numPrim
2455 << "\n"
2456 << dr
2457 << "\n"
2458 << "]CSGFoundry::descPrimRange" << " solidIdx " << std::setw(2) << solidIdx
2459 << "\n"
2460 ;
2461
2462 std::string str = ss.str() ;
2463 return str ;
2464 }
2465
2466
2467 std::string CSGFoundry::comparePrimRange(int solidIdx, const SMeshGroup* mg) const
2468 {
2469 const CSGSolid& so = solid[solidIdx];
2470 std::stringstream ss ;
2471 ss
2472 << "[CSGFoundry::comparePrimRange" << " solidIdx " << std::setw(2) << solidIdx
2473 << " so.primOffset " << std::setw(5) << so.primOffset
2474 << " so.numPrim " << std::setw(5) << so.numPrim
2475 << " mg " << ( mg ? "YES" : "NO " )
2476 << "\n"
2477 ;
2478
2479 ss << CSGPrim::DescRange(prim.data(), so.primOffset, so.numPrim, &meshname, mg );
2480
2481 ss << "]CSGFoundry::comparePrimRange" << " solidIdx " << std::setw(2) << solidIdx
2482 << "\n"
2483 ;
2484
2485 std::string str = ss.str() ;
2486 return str ;
2487 }
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525 CSGSolid* CSGFoundry::addSolid(unsigned numPrim, const char* label, int primOffset_ )
2526 {
2527 unsigned idx = solid.size();
2528
2529 assert( idx < IMAX );
2530
2531 int primOffset = primOffset_ < 0 ? prim.size() : primOffset_ ;
2532
2533 CSGSolid so = CSGSolid::Make( label, numPrim , primOffset );
2534
2535 solid.push_back(so);
2536
2537 last_added_solid = solid.data() + idx ;
2538 last_added_prim = nullptr ;
2539 last_added_node = nullptr ;
2540
2541 return last_added_solid ;
2542 }
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561 CSGSolid* CSGFoundry::addDeepCopySolid(unsigned solidIdx, const char* label )
2562 {
2563 std::string cso_label = label ? label : CSGSolid::MakeLabel('d', solidIdx) ;
2564
2565 LOG(info) << " cso_label " << cso_label ;
2566 std::cout << " cso_label " << cso_label << std::endl ;
2567
2568 const CSGSolid* oso = getSolid(solidIdx);
2569 unsigned numPrim = oso->numPrim ;
2570
2571 AABB solid_bb = {} ;
2572 CSGSolid* cso = addSolid(numPrim, cso_label.c_str());
2573 cso->type = DEEP_COPY_SOLID ;
2574
2575 for(int primIdx=oso->primOffset ; primIdx < oso->primOffset+oso->numPrim ; primIdx++)
2576 {
2577 const CSGPrim* opr = prim.data() + primIdx ;
2578
2579 unsigned numNode = opr->numNode() ;
2580 int nodeOffset_ = -1 ;
2581
2582 AABB prim_bb = {} ;
2583 CSGPrim* cpr = addPrim(numNode, nodeOffset_ );
2584
2585 cpr->setMeshIdx(opr->meshIdx());
2586 cpr->setRepeatIdx(opr->repeatIdx());
2587 cpr->setPrimIdx(opr->primIdx());
2588 cpr->setGlobalPrimIdx(opr->globalPrimIdx());
2589
2590 for(int nodeIdx=opr->nodeOffset() ; nodeIdx < opr->nodeOffset()+opr->numNode() ; nodeIdx++)
2591 {
2592 const CSGNode* ond = node.data() + nodeIdx ;
2593 unsigned o_tranIdx = ond->gtransformIdx();
2594
2595 CSGNode cnd = {} ;
2596 CSGNode::Copy(cnd, *ond );
2597
2598 const qat4* tra = nullptr ;
2599 const qat4* itr = nullptr ;
2600 unsigned c_tranIdx = 0u ;
2601
2602 if( o_tranIdx > 0 )
2603 {
2604 tra = getTran(o_tranIdx-1u) ;
2605 itr = getItra(o_tranIdx-1u) ;
2606 }
2607 else if( deepcopy_everynode_transform )
2608 {
2609 tra = new qat4 ;
2610 itr = new qat4 ;
2611 }
2612
2613 if( tra && itr )
2614 {
2615 c_tranIdx = 1 + addTran(tra, itr);
2616 std::cout
2617 << " o_tranIdx " << o_tranIdx
2618 << " c_tranIdx " << c_tranIdx
2619 << " deepcopy_everynode_transform " << deepcopy_everynode_transform
2620 << std::endl
2621 ;
2622 std::cout << " tra " << tra->desc('t') << std::endl ;
2623 std::cout << " itr " << itr->desc('i') << std::endl ;
2624 }
2625
2626
2627
2628 bool c0 = cnd.is_complement();
2629
2630
2631
2632 cnd.setTransformComplement(c_tranIdx, c0);
2633
2634 unsigned c_tranIdx2 = cnd.gtransformIdx() ;
2635
2636 bool match = c_tranIdx2 == c_tranIdx ;
2637 if(!match) std::cout << "set/get transform fail c_tranIdx " << c_tranIdx << " c_tranIdx2 " << c_tranIdx2 << std::endl ;
2638 assert(match);
2639
2640
2641 cnd.setAABBLocal() ;
2642 if(tra)
2643 {
2644 tra->transform_aabb_inplace( cnd.AABB() );
2645 }
2646 prim_bb.include_aabb( cnd.AABB() );
2647 addNode(cnd);
2648 }
2649
2650 cpr->setAABB(prim_bb.data());
2651 solid_bb.include_aabb(prim_bb.data()) ;
2652 }
2653
2654 cso->center_extent = solid_bb.center_extent() ;
2655 return cso ;
2656 }
2657
2658
2659 void CSGFoundry::DumpAABB(const char* msg, const float* aabb)
2660 {
2661 int w = 4 ;
2662 LOG(info) << msg << " " ;
2663 LOG(info) << " | " ;
2664 for(int l=0 ; l < 3 ; l++) LOG(info) << std::setw(w) << *(aabb+l) << " " ;
2665 LOG(info) << " | " ;
2666 for(int l=0 ; l < 3 ; l++) LOG(info) << std::setw(w) << *(aabb+l+3) << " " ;
2667 LOG(info) << " | " ;
2668 for(int l=0 ; l < 3 ; l++) LOG(info) << std::setw(w) << *(aabb+l+3) - *(aabb+l) << " " ;
2669 LOG(info) ;
2670 }
2671
2672
2673 const char* CSGFoundry::BASE = "$DefaultGeometryDir" ;
2674 const char* CSGFoundry::RELDIR = "CSGFoundry" ;
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685 const char* CSGFoundry::getBaseDir(bool create) const
2686 {
2687 const char* cfbase_default = SPath::Resolve(BASE, create ? DIRPATH : NOOP );
2688 const char* cfbase = ssys::getenvvar("CFBASE", cfbase_default );
2689 return cfbase ? strdup(cfbase) : nullptr ;
2690 }
2691
2692 void CSGFoundry::save() const
2693 {
2694 const char* cfbase = getBaseDir(true) ;
2695 if( cfbase == nullptr )
2696 {
2697 LOG(fatal) << "cannot save unless CFBASE envvar defined or geom has been set " ;
2698 return ;
2699 }
2700 LOG(LEVEL) << " cfbase " << cfbase ;
2701 save(cfbase, RELDIR );
2702 }
2703
2704
2705
2706
2707 void CSGFoundry::save(const char* base, const char* rel) const
2708 {
2709 if(rel == nullptr) rel = RELDIR ;
2710 std::stringstream ss ;
2711 ss << base << "/" << rel ;
2712 std::string dir = ss.str();
2713 save_(dir.c_str());
2714 }
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727 void CSGFoundry::saveAlt() const
2728 {
2729 const char* _path = "$CFBASE_ALT" ;
2730 const char* path = spath::Resolve(_path);
2731 bool unresolved = spath::LooksUnresolved( path, _path );
2732
2733 LOG(LEVEL)
2734 << " _path[" << ( _path ? _path : "-" )
2735 << " path[" << ( path ? path : "-" )
2736 << " unresolved " << ( unresolved ? "YES" : "NO " )
2737 ;
2738
2739 LOG_IF(fatal, unresolved) << "cannot saveAlt as CFBASE_ALT unresolved" ;
2740 if(unresolved) return ;
2741
2742 const char* cfbase_alt = path ;
2743 LOG(info)
2744 << " cfbase " << ( cfbase ? cfbase : "-" )
2745 << " cfbase_alt " << ( cfbase_alt ? cfbase_alt : "-" )
2746 ;
2747
2748 save(cfbase_alt, RELDIR);
2749 }
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766 void CSGFoundry::save_(const char* dir_) const
2767 {
2768 const char* dir = SPath::Resolve(dir_, DIRPATH);
2769 LOG(LEVEL) << dir ;
2770
2771 if(meshname.size() > 0 && save__("meshname")) NP::WriteNames( dir, "meshname.txt", meshname );
2772
2773 std::vector<std::string> primname ;
2774 getPrimName(primname);
2775 if(primname.size() > 0 && save__("primname")) NP::WriteNames( dir, "primname.txt", primname );
2776
2777 if(mmlabel.size() > 0 && save__("mmlabel")) NP::WriteNames( dir, "mmlabel.txt", mmlabel );
2778 if(hasMeta() && save__("meta")) U::WriteString( dir, "meta.txt", meta.c_str() );
2779
2780 if(solid.size() > 0 && save__("solid")) NP::Write(dir, "solid.npy", (int*)solid.data(), solid.size(), 3, 4 );
2781 if(prim.size() > 0 && save__("prim")) NP::Write(dir, "prim.npy", (float*)prim.data(), prim.size(), 4, 4 );
2782 if(node.size() > 0 && save__("node")) NP::Write(dir, "node.npy", (float*)node.data(), node.size(), 4, 4 );
2783 if(plan.size() > 0 && save__("plan")) NP::Write(dir, "plan.npy", (float*)plan.data(), plan.size(), 1, 4 );
2784 if(tran.size() > 0 && save__("tran")) NP::Write(dir, "tran.npy", (float*)tran.data(), tran.size(), 4, 4 );
2785 if(itra.size() > 0 && save__("itra")) NP::Write(dir, "itra.npy", (float*)itra.data(), itra.size(), 4, 4 );
2786 if(inst.size() > 0 && save__("inst")) NP::Write(dir, "inst.npy", (float*)inst.data(), inst.size(), 4, 4 );
2787
2788
2789 if(sim && save__("SSim"))
2790 {
2791 LOG(LEVEL) << " SSim::save " << dir ;
2792 const_cast<SSim*>(sim)->save(dir, SSim::RELDIR );
2793 }
2794 else
2795 {
2796 LOG(LEVEL) << " CANNOT SSim::save AS sim null " ;
2797 }
2798 }
2799
2800
2801 bool CSGFoundry::save__(const char* elem) const
2802 {
2803 return save_opt == nullptr ? true : ( strstr(save_opt, elem) != nullptr ) ;
2804 }
2805
2806 void CSGFoundry::setSaveOpt(const char* save_opt_)
2807 {
2808 save_opt = save_opt_ ? strdup(save_opt_) : nullptr ;
2809 }
2810 const char* CSGFoundry::getSaveOpt() const
2811 {
2812 return save_opt ;
2813 }
2814
2815
2816
2817 template <typename T> void CSGFoundry::setMeta( const char* key, T value ){ NP::SetMeta(meta, key, value ); }
2818
2819 template void CSGFoundry::setMeta<int>(const char*, int );
2820 template void CSGFoundry::setMeta<unsigned>(const char*, unsigned );
2821 template void CSGFoundry::setMeta<float>(const char*, float );
2822 template void CSGFoundry::setMeta<double>(const char*, double );
2823 template void CSGFoundry::setMeta<std::string>(const char*, std::string );
2824
2825 template <typename T> T CSGFoundry::getMeta( const char* key, T fallback){ return NP::GetMeta(meta, key, fallback ); }
2826
2827 template int CSGFoundry::getMeta<int>(const char*, int );
2828 template unsigned CSGFoundry::getMeta<unsigned>(const char*, unsigned );
2829 template float CSGFoundry::getMeta<float>(const char*, float );
2830 template double CSGFoundry::getMeta<double>(const char*, double );
2831 template std::string CSGFoundry::getMeta<std::string>(const char*, std::string );
2832
2833 bool CSGFoundry::hasMeta() const { return meta.empty() == false ; }
2834
2835
2836 void CSGFoundry::load()
2837 {
2838 const char* cfbase = getBaseDir(false) ;
2839 if( cfbase == nullptr )
2840 {
2841 LOG(fatal) << "cannot load unless CFBASE envvar defined or geom has been set " ;
2842 return ;
2843 }
2844 load(cfbase, RELDIR );
2845 }
2846
2847
2848
2849
2850 const char* CSGFoundry::load_FAIL_base_null_NOTES = R"(
2851 CSGFoundry::load_FAIL_base_null_NOTES
2852 ======================================
2853
2854 You appear to be attempting to load a geometry folder that does not exist.
2855 Perhaps this is due to incorrect envvars or the folder really does not exist.
2856 Scripts that can create geometry folders include:
2857
2858 * CSG/CSGMakerTest.sh
2859
2860 CSGMaker saves a CSGFoundry geometry that was authored directly in CSG.
2861
2862 Attempting to run an executable directly rather than the script
2863 that sets up the environment can cause such errors.
2864
2865 This error can also happen when attempting to load event+geometry
2866 that was previously written to directories below /tmp
2867 but has subsequently been "cleaned" leaving the directory structure
2868 but with all the directories emptied.
2869
2870 Relevant envvars : CFBASE and GEOM
2871
2872 )" ;
2873 const char* CSGFoundry::LoadFailNotes(){ return load_FAIL_base_null_NOTES ; }
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887 void CSGFoundry::load(const char* base_, const char* rel)
2888 {
2889 LOG_IF(error, base_ == nullptr) << load_FAIL_base_null_NOTES ;
2890 assert(base_);
2891 bool conventional = strcmp( rel, RELDIR) == 0 ;
2892 LOG_IF(fatal, !conventional) << "Convention is for rel to be named [" << RELDIR << "] not: [" << rel << "]" ;
2893 assert(conventional);
2894
2895 const char* base = SPath::Resolve(base_, NOOP);
2896 setCFBase(base);
2897
2898 std::stringstream ss ;
2899 ss << base << "/" << rel ;
2900 std::string dir = ss.str();
2901
2902 load(dir.c_str());
2903 }
2904
2905 void CSGFoundry::setCFBase( const char* cfbase_ )
2906 {
2907 cfbase = strdup(cfbase_);
2908 }
2909 const char* CSGFoundry::getCFBase() const
2910 {
2911 return cfbase ;
2912 }
2913 const char* CSGFoundry::getOriginCFBase() const
2914 {
2915
2916
2917
2918
2919 LOG(LEVEL) << " CAUTION HOW YOU USE THIS : MISUSE CAN EASILY LEAD TO INCONSISTENCY BETWEEN RESULTS AND GEOMETRY " ;
2920 return origin ? origin->cfbase : cfbase ;
2921 }
2922
2923
2924
2925 std::string CSGFoundry::descBase() const
2926 {
2927 const char* cfb = getCFBase();
2928 const char* ocfb = getOriginCFBase();
2929 std::stringstream ss ;
2930 ss << "[CSGFoundry.descBase \n"
2931 << " CFBase " << ( cfb ? cfb : "-" ) << "\n"
2932 << " OriginCFBase " << ( ocfb ? ocfb : "-" ) << "\n"
2933 << "]CSGFoundry.descBase \n"
2934 ;
2935 return ss.str();
2936 }
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947 const char* CSGFoundry::LOAD_FAIL_NOTES = R"LITERAL(
2948 CSGFoundry::LOAD_FAIL_NOTES
2949 ==============================
2950
2951 The CSGFoundry directory does not exist. To create it you probably need to
2952 run one of several CSGFoundry creating scripts. Which one to use depends on
2953 what the geometry is that you want to create. Some of the scripts require
2954 export the GEOM envvar within $HOME/.opticks/GEOM/GEOM.sh to pick between
2955 different geometries.
2956
2957 CSG/CSGMakerTest.sh
2958 CSG level creation of simple test CSGFoundry
2959
2960 G4CX/G4CXTest.sh
2961 Creates Geant4 geometry translates and saves into CSGFoundry
2962
2963
2964 )LITERAL" ;
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975 void CSGFoundry::load( const char* dir_ )
2976 {
2977 const char* dir = spath::Resolve(dir_);
2978 bool readable = spath::is_readable(dir);
2979
2980 LOG_IF(fatal, !readable )
2981 << " dir-not-readable "
2982 << " dir_ [" << ( dir_ ? dir_ : "-" ) << "]"
2983 << " dir [" << ( dir ? dir : "-" ) << "]"
2984 << "\n"
2985 << LOAD_FAIL_NOTES
2986 ;
2987
2988 assert(readable) ;
2989 if( !readable ) return ;
2990
2991 loaddir = strdup(dir) ;
2992 LOG(LEVEL) << "[ loaddir " << loaddir ;
2993
2994 NP::ReadNames( dir, "meshname.txt", meshname );
2995 NP::ReadNames( dir, "mmlabel.txt", mmlabel );
2996
2997 const char* meta_str = U::ReadString( dir, "meta.txt" ) ;
2998 if(meta_str)
2999 {
3000 meta = meta_str ;
3001 }
3002 else
3003 {
3004 LOG(warning) << " no meta.txt at " << dir ;
3005 }
3006
3007 loadArray( solid , dir, "solid.npy" );
3008 loadArray( prim , dir, "prim.npy" );
3009 loadArray( node , dir, "node.npy" );
3010 loadArray( tran , dir, "tran.npy" );
3011 loadArray( itra , dir, "itra.npy" );
3012 loadArray( inst , dir, "inst.npy" );
3013 loadArray( plan , dir, "plan.npy" , true );
3014
3015
3016
3017 mtime = MTime(dir, "solid.npy");
3018
3019 LOG(LEVEL) << "] loaddir " << loaddir ;
3020 }
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031 NP* CSGFoundry::loadAux(const char* auxrel ) const
3032 {
3033 const char* auxpath = cfbase ? SPath::Join(cfbase, auxrel ) : nullptr ;
3034 NP* aux = auxpath && NP::Exists(auxpath) ? NP::Load(auxpath) : nullptr ;
3035 return aux ;
3036 }
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046 int CSGFoundry::MTime(const char* dir, const char* fname_)
3047 {
3048 const char* fname = fname_ ? fname_ : "solid.npy" ;
3049 const char* path = SPath::Resolve(dir, fname, NOOP);
3050 return SPath::mtime(path);
3051 }
3052
3053
3054
3055
3056
3057 void CSGFoundry::setGeom(const char* geom_)
3058 {
3059 geom = geom_ ? strdup(geom_) : nullptr ;
3060 }
3061 void CSGFoundry::setOrigin(const CSGFoundry* origin_)
3062 {
3063 origin = origin_ ;
3064 }
3065 void CSGFoundry::setElv(const SBitSet* elv_)
3066 {
3067 elv = elv_ ;
3068 }
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082 const char* CSGFoundry::descELV() const
3083 {
3084 std::string str = SBitSet::Brief(elv, id );
3085 return strdup(str.c_str()) ;
3086 }
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101 CSGFoundry* CSGFoundry::CreateFromSim()
3102 {
3103 assert(SSim::Get() != nullptr);
3104 CSGFoundry* fd = new CSGFoundry ;
3105 fd->importSim();
3106 return fd ;
3107 }
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135 bool CSGFoundry::Load_saveAlt = ssys::getenvbool("CSGFoundry_Load_saveAlt") ;
3136
3137 CSGFoundry* CSGFoundry::Load()
3138 {
3139 SProf::Add("CSGFoundry__Load_HEAD");
3140
3141
3142
3143 LOG(LEVEL) << "[ argumentless " ;
3144 CSGFoundry* src = CSGFoundry::Load_() ;
3145 if(src == nullptr) return nullptr ;
3146
3147 SGeoConfig::GeometrySpecificSetup(src->id);
3148
3149
3150 const SBitSet* elv = SGeoConfig::ELV(src->id);
3151
3152
3153 CSGFoundry* dst = elv ? CSGFoundry::CopySelect(src, elv) : src ;
3154
3155
3156 if(elv)
3157 {
3158 LOG(LEVEL) << " apply ELV selection to triangulated SScene " ;
3159 SScene* src_sc = dst->sim->scene ;
3160 SScene* dst_sc = src_sc->copy(elv);
3161 const_cast<SSim*>(dst->sim)->set_override_scene(dst_sc);
3162 }
3163
3164
3165 if( elv != nullptr && Load_saveAlt)
3166 {
3167 LOG(error) << " non-standard dynamic selection CSGFoundry_Load_saveAlt " ;
3168 dst->saveAlt() ;
3169 }
3170
3171
3172
3173
3174 LOG(LEVEL) << "] argumentless " ;
3175 SProf::Add("CSGFoundry__Load_TAIL");
3176 return dst ;
3177 }
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203 CSGFoundry* CSGFoundry::CopySelect(const CSGFoundry* src, const SBitSet* elv )
3204 {
3205 LOG(LEVEL) << "[" ;
3206 assert(elv);
3207 LOG(LEVEL) << elv->desc() << std::endl ;
3208 LOG(LEVEL) << src->descELV(elv) ;
3209 LOG(LEVEL) << src->descELV2(elv) ;
3210
3211 CSGFoundry* dst = CSGCopy::Select(src, elv );
3212 dst->setOrigin(src);
3213 dst->setElv(elv);
3214 dst->setOverrideSim(src->sim);
3215
3216 LOG(LEVEL) << "]" ;
3217 return dst ;
3218 }
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231 const char* CSGFoundry::ResolveCFBase()
3232 {
3233 const char* cfbase = spath::CFBaseFromGEOM();
3234 bool readable = spath::is_readable(cfbase, "CSGFoundry" );
3235 LOG_IF(fatal, !readable) << " cfbase/CSGFoundry directory [" << cfbase << "]/CSGFoundry" << " IS NOT READABLE " ;
3236 return readable ? cfbase : nullptr ;
3237 }
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263 CSGFoundry* CSGFoundry::Load_()
3264 {
3265 const char* cfbase = ResolveCFBase() ;
3266 if(ssys::getenvbool(_Load_DUMP)) std::cout << "CSGFoundry::Load_[" << cfbase << "]\n" ;
3267
3268 LOG(LEVEL) << "[ SSim::Load cfbase " << ( cfbase ? cfbase : "-" ) ;
3269 SSim* sim = SSim::Load(cfbase, "CSGFoundry/SSim");
3270 LOG(LEVEL) << "] SSim::Load " ;
3271
3272 LOG_IF(fatal, sim==nullptr ) << " sim(SSim) required before CSGFoundry::Load " ;
3273 assert(sim);
3274
3275 CSGFoundry* fd = Load(cfbase, "CSGFoundry");
3276 return fd ;
3277 }
3278
3279
3280
3281 CSGFoundry* CSGFoundry::Load(const char* base, const char* rel)
3282 {
3283 if(base == nullptr) return nullptr ;
3284 CSGFoundry* fd = new CSGFoundry();
3285 fd->load(base, rel);
3286 return fd ;
3287 }
3288
3289
3290 void CSGFoundry::setOverrideSim( const SSim* override_sim )
3291 {
3292 sim = override_sim ;
3293 }
3294 const SSim* CSGFoundry::getSim() const
3295 {
3296 return sim ;
3297 }
3298
3299
3300
3301 void CSGFoundry::setFold(const char* fold_)
3302 {
3303 const char* rel = SPath::Basename(fold_);
3304
3305 bool rel_expect = strcmp( rel, "CSGFoundry" ) == 0 ;
3306 assert( rel_expect );
3307 if(!rel_expect) std::raise(SIGINT);
3308
3309 fold = strdup(fold_);
3310 cfbase = SPath::Dirname(fold_) ;
3311 }
3312
3313 const char* CSGFoundry::getFold() const
3314 {
3315 return fold ;
3316 }
3317
3318
3319
3320
3321 template<typename T>
3322 void CSGFoundry::loadArray( std::vector<T>& vec, const char* dir, const char* name, bool optional )
3323 {
3324 bool exists = NP::Exists(dir, name);
3325 if(optional && !exists ) return ;
3326
3327 NP* a = NP::Load(dir, name);
3328 if(a == nullptr)
3329 {
3330 LOG(fatal) << "FAIL to load non-optional array " << dir << "/" << name ;
3331 LOG(fatal) << "convert geocache into CSGFoundry model using CSG_GGeo/run.sh " ;
3332
3333 assert(0);
3334 }
3335 else
3336 {
3337 assert( a->shape.size() == 3 );
3338 unsigned ni = a->shape[0] ;
3339 unsigned nj = a->shape[1] ;
3340 unsigned nk = a->shape[2] ;
3341
3342 LOG(LEVEL) << " ni " << std::setw(5) << ni << " nj " << std::setw(1) << nj << " nk " << std::setw(1) << nk << " " << name ;
3343
3344 vec.clear();
3345 vec.resize(ni);
3346 memcpy( vec.data(), a->bytes(), sizeof(T)*ni );
3347 }
3348 }
3349
3350 template void CSGFoundry::loadArray( std::vector<CSGSolid>& , const char* , const char*, bool );
3351 template void CSGFoundry::loadArray( std::vector<CSGPrim>& , const char* , const char* , bool );
3352 template void CSGFoundry::loadArray( std::vector<CSGNode>& , const char* , const char* , bool );
3353 template void CSGFoundry::loadArray( std::vector<float4>& , const char* , const char* , bool );
3354 template void CSGFoundry::loadArray( std::vector<qat4>& , const char* , const char* , bool );
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375 void CSGFoundry::upload()
3376 {
3377 inst_find_unique();
3378
3379
3380
3381 assert( tran.size() == itra.size() );
3382
3383
3384 bool is_uploaded_0 = isUploaded();
3385 LOG_IF(fatal, is_uploaded_0) << "HAVE ALREADY UPLOADED : THIS CANNOT BE DONE MORE THAN ONCE " ;
3386 assert(is_uploaded_0 == false);
3387
3388
3389 d_prim = prim.size() > 0 ? CU::UploadArray<CSGPrim>(prim.data(), prim.size() ) : nullptr ;
3390 d_node = node.size() > 0 ? CU::UploadArray<CSGNode>(node.data(), node.size() ) : nullptr ;
3391 d_plan = plan.size() > 0 ? CU::UploadArray<float4>(plan.data(), plan.size() ) : nullptr ;
3392 d_itra = itra.size() > 0 ? CU::UploadArray<qat4>(itra.data(), itra.size() ) : nullptr ;
3393
3394 bool is_uploaded_1 = isUploaded();
3395 LOG_IF(fatal, !is_uploaded_1) << "FAILED TO UPLOAD" ;
3396 assert(is_uploaded_1 == true);
3397
3398 }
3399
3400 bool CSGFoundry::isUploaded() const
3401 {
3402 return d_prim != nullptr && d_node != nullptr ;
3403 }
3404
3405
3406 void CSGFoundry::inst_find_unique()
3407 {
3408 qat4::find_unique_gas( inst, gas );
3409
3410 }
3411
3412 unsigned CSGFoundry::getNumUniqueGAS() const
3413 {
3414 return gas.size();
3415 }
3416 unsigned CSGFoundry::getNumUniqueIAS() const
3417 {
3418 return 1 ;
3419 }
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430 unsigned CSGFoundry::getNumInstancesIAS(int ias_idx, unsigned long long emm) const
3431 {
3432 return qat4::count_ias(inst, ias_idx, emm );
3433 }
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448 void CSGFoundry::getInstanceTransformsIAS(std::vector<qat4>& select_inst, int ias_idx, unsigned long long emm ) const
3449 {
3450 qat4::select_instances_ias(inst, select_inst, ias_idx, emm ) ;
3451 }
3452
3453
3454 unsigned CSGFoundry::getNumInstancesGAS(int gas_idx) const
3455 {
3456 return qat4::count_gas(inst, gas_idx );
3457 }
3458
3459 void CSGFoundry::getInstanceTransformsGAS(std::vector<qat4>& select_qv, int gas_idx ) const
3460 {
3461 qat4::select_instances_gas(inst, select_qv, gas_idx ) ;
3462 }
3463
3464 void CSGFoundry::getInstancePointersGAS(std::vector<const qat4*>& select_qi, int gas_idx ) const
3465 {
3466 qat4::select_instance_pointers_gas(inst, select_qi, gas_idx ) ;
3467 }
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483 int CSGFoundry::getInstanceIndex(int gas_idx_ , unsigned ordinal) const
3484 {
3485 return qat4::find_instance_gas(inst, gas_idx_, ordinal);
3486 }
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499 const qat4* CSGFoundry::getInstance_with_GAS_ordinal(int gas_idx_ , unsigned ordinal) const
3500 {
3501 int index = getInstanceIndex(gas_idx_, ordinal);
3502 return index > -1 ? &inst[index] : nullptr ;
3503 }
3504
3505 std::string CSGFoundry::descGAS() const
3506 {
3507 std::stringstream ss ;
3508 ss << desc() << std::endl ;
3509 for(unsigned i=0 ; i < gas.size() ; i++)
3510 {
3511 int gas_idx = gas[i];
3512 unsigned num_inst_gas = getNumInstancesGAS(gas_idx);
3513 ss << std::setw(5) << gas_idx << ":" << std::setw(8) << num_inst_gas << std::endl ;
3514 }
3515 std::string s = ss.str();
3516 return s ;
3517 }
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539 void CSGFoundry::parseMOI(int& midx, int& mord, int& iidx, const char* moi) const
3540 {
3541 id->parseMOI(midx, mord, iidx, moi );
3542 }
3543 const char* CSGFoundry::getName(unsigned midx) const
3544 {
3545 return id->getName(midx);
3546 }
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559 const char* CSGFoundry::getFrame_NOTES = R"(
3560 CSGFoundry::getFrame_NOTES
3561 ===========================
3562
3563 When CSGFoundry::getFrame fails due to the MOI/FRS string used to target
3564 a volume of the geometry failing to find the targetted volume
3565 it is usually due to the spec not being appropriate for the geometry.
3566
3567 First thing to check is the configured GEOM envvar using GEOM bash function.
3568
3569 With simple test geometries the lack of frames can be worked around
3570 using special cased MOI in some cases, for example::
3571
3572 MOI=EXTENT:200 ~/o/cxr_min.sh
3573
3574
3575 When using U4VolumeMaker it is sometimes possible to
3576 debug the bad specification string by rerunning with the below
3577 envvars set in order to dump PV/LV/SO names from the full and sub trees.::
3578
3579 export U4VolumeMaker_PVG_WriteNames=1
3580 export U4VolumeMaker_PVG_WriteNames_Sub=1
3581
3582 This writes the names for the full volume tree to eg::
3583
3584 /tmp/$USER/opticks/U4VolumeMaker_PVG_WriteNames
3585 /tmp/$USER/opticks/U4VolumeMaker_PVG_WriteNames_Sub
3586
3587 Grab these from remote with::
3588
3589 u4
3590 ./U4VolumeMaker.sh grab
3591
3592
3593 )" ;
3594
3595
3596 sframe CSGFoundry::getFrame() const
3597 {
3598 const char* moi_or_iidx = ssys::getenvvar("MOI",sframe::DEFAULT_FRS);
3599 return getFrame(moi_or_iidx);
3600 }
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617 sframe CSGFoundry::getFrame(const char* q_spec) const
3618 {
3619 sframe fr = {} ;
3620
3621 #ifdef FRAME_TRANSITION
3622 stree* tree = getTree();
3623 assert(tree);
3624 sfr f = tree->get_frame(q_spec);
3625 fr.populate(f);
3626 #else
3627 const char* arg = frs ? frs : sframe::DEFAULT_FRS ;
3628 int rc = getFrame(fr, arg );
3629 LOG_IF(error, rc != 0) << " arg" << arg << std::endl << getFrame_NOTES ;
3630 if(rc != 0) std::raise(SIGINT);
3631 #endif
3632 fr.prepare();
3633
3634 return fr ;
3635 }
3636
3637
3638
3639 #ifndef FRAME_TRANSITION
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685 int CSGFoundry::getFrame(sframe& fr, const char* frs ) const
3686 {
3687
3688 bool VERBOSE = ssys::getenvbool(getFrame_VERBOSE) ;
3689 LOG(LEVEL) << "[" << getFrame_VERBOSE << "] " << VERBOSE ;
3690
3691 int rc = 0 ;
3692
3693 bool looks_like_axis = sstr::StartsWith(frs,stree::AXIS_PFX) ;
3694 bool looks_like_raw = strstr(frs,",") ;
3695 bool looks_like_moi = sstr::StartsWithLetterAZaz(frs) || strstr(frs, ":") || strcmp(frs,"-1") == 0 ;
3696
3697 LOG_IF(info, VERBOSE)
3698 << "[" << getFrame_VERBOSE << "] " << ( VERBOSE ? "YES" : "NO " )
3699 << " frs " << ( frs ? frs : "-" )
3700 << " looks_like_moi " << ( looks_like_moi ? "YES" : "NO " )
3701 << " looks_like_raw " << ( looks_like_raw ? "YES" : "NO " )
3702 ;
3703
3704 if(looks_like_axis)
3705 {
3706
3707
3708
3709
3710
3711 sfr lf = sfr::MakeFromAxis<float>(frs + strlen(stree::AXIS_PFX), ',');
3712 fr.populate(lf);
3713 }
3714 else if(looks_like_raw)
3715 {
3716 rc = sframe::PopulateFromRaw(fr, frs, ',' );
3717 }
3718 else if(looks_like_moi)
3719 {
3720 int midx, mord, gord ;
3721 parseMOI(midx, mord, gord, frs );
3722
3723 rc = getFrame(fr, midx, mord, gord);
3724
3725
3726 LOG_IF(info, VERBOSE)
3727 << "[" << getFrame_VERBOSE << "] " << ( VERBOSE ? "YES" : "NO " )
3728 << " frs " << ( frs ? frs : "-" )
3729 << " looks_like_moi " << ( looks_like_moi ? "YES" : "NO " )
3730 << " midx " << midx
3731 << " mord " << mord
3732 << " gord " << gord
3733 << " rc " << rc
3734 ;
3735
3736 }
3737 else
3738 {
3739 int inst_idx = SName::ParseIntString(frs, 0) ;
3740 rc = getFrame(fr, inst_idx);
3741
3742 LOG_IF(info, VERBOSE)
3743 << "[" << getFrame_VERBOSE << "] " << ( VERBOSE ? "YES" : "NO " )
3744 << " frs " << ( frs ? frs : "-" )
3745 << " looks_like_moi " << ( looks_like_moi ? "YES" : "NO " )
3746 << " inst_idx " << inst_idx
3747 << " rc " << rc
3748 ;
3749 }
3750
3751 fr.set_propagate_epsilon( SEventConfig::PropagateEpsilon() );
3752 fr.frs = strdup(frs);
3753 fr.prepare();
3754
3755 LOG_IF(info, VERBOSE)
3756 << "[" << getFrame_VERBOSE << "] " << ( VERBOSE ? "YES" : "NO " )
3757 << "[fr.desc\n"
3758 << fr.desc()
3759 << "]fr.desc\n"
3760 ;
3761
3762 LOG_IF(error, rc != 0) << "Failed to lookup frame with frs [" << frs << "] looks_like_moi " << looks_like_moi ;
3763 return rc ;
3764 }
3765 #endif
3766
3767
3768 int CSGFoundry::getFrame(sframe& fr, int inst_idx) const
3769 {
3770 return target->getFrame( fr, inst_idx );
3771 }
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790 int CSGFoundry::getFrame(sframe& fr, int midx, int mord, int gord) const
3791 {
3792 int rc = 0 ;
3793 if( midx == -1 )
3794 {
3795 unsigned ias_idx = 0 ;
3796 unsigned long long emm = 0ull ;
3797 iasCE(fr.ce, ias_idx, emm);
3798 }
3799 else
3800 {
3801 rc = target->getFrame( fr, midx, mord, gord );
3802 }
3803 return rc ;
3804 }
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842 sframe CSGFoundry::getFrameE() const
3843 {
3844 bool VERBOSE = ssys::getenvbool(getFrameE_VERBOSE) ;
3845 LOG(LEVEL) << "[" << getFrameE_VERBOSE << "] " << VERBOSE ;
3846
3847 sframe fr = {} ;
3848
3849 if(ssys::getenvbool("INST"))
3850 {
3851 int INST = ssys::getenvint("INST", 0);
3852 LOG_IF(info, VERBOSE) << " INST " << INST ;
3853 getFrame(fr, INST ) ;
3854
3855 fr.set_ekv("INST");
3856 }
3857 else if(ssys::getenvbool("MOI"))
3858 {
3859 const char* MOI = ssys::getenvvar("MOI", nullptr) ;
3860 LOG_IF(info, VERBOSE) << " MOI " << MOI ;
3861 fr = getFrame() ;
3862 fr.set_ekv("MOI");
3863 }
3864 else
3865 {
3866 const char* ipf_ = SEventConfig::InputPhotonFrame();
3867 const char* ipf = ipf_ ? ipf_ : "0" ;
3868 LOG_IF(info, VERBOSE) << " ipf " << ipf ;
3869 fr = getFrame(ipf);
3870
3871 fr.set_ekv(SEventConfig::kInputPhotonFrame, ipf );
3872 }
3873
3874
3875 SSim::AnnotateFrame(fr, elv, "CSGFoundry::getFrameE" );
3876
3877 return fr ;
3878 }
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908 void CSGFoundry::AfterLoadOrCreate()
3909 {
3910 assert(0 && "DONT USE THIS : THIS PREP DONE BY SSim::afterLoadOrCreate " );
3911
3912 CSGFoundry* fd = CSGFoundry::Get();
3913 if(!fd) return ;
3914
3915 #ifdef WITH_OLD_FRAME
3916 SEvt::CreateOrReuse() ;
3917
3918 sframe fr = fd->getFrameE() ;
3919 LOG(LEVEL) << fr ;
3920 SEvt::SetFrame(fr);
3921 #endif
3922
3923 }
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953 int CSGFoundry::getCenterExtent(float4& ce, int midx, int mord, int gord, qat4* m2w, qat4* w2m ) const
3954 {
3955 int rc = 0 ;
3956 if( midx == -1 )
3957 {
3958 unsigned long long emm = 0ull ;
3959 iasCE(ce, emm);
3960 }
3961 else
3962 {
3963 rc = target->getFrameComponents(ce, midx, mord, gord, m2w, w2m );
3964 }
3965
3966 if( rc != 0 )
3967 {
3968 LOG(error) << " non-zero RC from CSGTarget::getCenterExtent " ;
3969 }
3970 return rc ;
3971 }
3972
3973
3974 int CSGFoundry::getTransform(qat4& q, int midx, int mord, int gord) const
3975 {
3976 return target->getTransform(q, midx, mord, gord);
3977 }
3978
3979
3980
3981
3982
3983
3984
3985
3986 void CSGFoundry::kludgeScalePrimBBox( const char* label, float dscale )
3987 {
3988 std::vector<unsigned> solidIdx ;
3989 findSolidIdx(solidIdx, label);
3990
3991 for(int i=0 ; i < int(solidIdx.size()) ; i++)
3992 {
3993 unsigned soIdx = solidIdx[i];
3994 kludgeScalePrimBBox( soIdx, dscale );
3995 }
3996 }
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006 void CSGFoundry::kludgeScalePrimBBox( unsigned solidIdx, float dscale )
4007 {
4008 CSGSolid* so = solid.data() + solidIdx ;
4009 so->type = KLUDGE_BBOX_SOLID ;
4010
4011 unsigned primOffset = so->primOffset ;
4012 unsigned numPrim = so->numPrim ;
4013
4014 for(unsigned primIdx=0 ; primIdx < numPrim ; primIdx++)
4015 {
4016
4017
4018
4019
4020 float scale = 1.f + dscale*float(numPrim - 1u - primIdx) ;
4021 LOG(info) << " primIdx " << std::setw(2) << primIdx << " scale " << scale ;
4022 std::cout
4023 << "CSGFoundry::kludgeScalePrimBBox"
4024 << " primIdx " << std::setw(2) << primIdx
4025 << " numPrim " << std::setw(2) << numPrim
4026 << " scale " << scale
4027 << std::endl
4028 ;
4029 CSGPrim* pr = prim.data() + primOffset + primIdx ;
4030 pr->scaleAABB_(scale);
4031 }
4032 }
4033
4034
4035
4036