File indexing completed on 2026-04-09 07:48:57
0001 #include <array>
0002 #include <csignal>
0003
0004 #include "scuda.h"
0005 #include "squad.h"
0006 #include "stran.h"
0007 #include "ssys.h"
0008 #include "OpticksCSG.h"
0009
0010 #include "SLOG.hh"
0011
0012 #include "CSGNode.h"
0013 #include "CSGFoundry.h"
0014 #include "CSGMaker.h"
0015
0016 const plog::Severity CSGMaker::LEVEL = SLOG::EnvLevel("CSGMaker", "DEBUG" );
0017
0018 CSGMaker::CSGMaker( CSGFoundry* fd_ )
0019 :
0020 fd(fd_)
0021 {
0022 }
0023
0024 bool CSGMaker::StartsWith( const char* n, const char* q )
0025 {
0026 return strlen(q) >= strlen(n) && strncmp(q, n, strlen(n)) == 0 ;
0027 }
0028
0029
0030
0031 void CSGMaker::GetNames(std::vector<std::string>& names )
0032 {
0033 std::stringstream ss(NAMES) ;
0034 std::string name ;
0035 while (std::getline(ss, name)) if(!name.empty()) names.push_back(name);
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 bool CSGMaker::CanMake(const char* qname)
0048 {
0049 bool found = false ;
0050 std::stringstream ss(NAMES) ;
0051 std::string name ;
0052 while (!found && std::getline(ss, name)) if(!name.empty() && StartsWith(name.c_str(), qname)) found = true ;
0053
0054 return found ;
0055 }
0056
0057 const char* CSGMaker::NAMES = R"LITERAL(
0058 JustOrb
0059 BoxedSphere
0060 ZSphere
0061 Cone
0062 Hyperboloid
0063 Box3
0064 Plane
0065 Slab
0066 Cylinder
0067 OldCylinder
0068 Disc
0069 ConvexPolyhedronCube
0070 ConvexPolyhedronTetrahedron
0071 Ellipsoid
0072 UnionBoxSphere
0073 UnionListBoxSphere
0074 UnionLLBoxSphere
0075 IntersectionBoxSphere
0076 OverlapBoxSphere
0077 OverlapThreeSphere
0078 ContiguousThreeSphere
0079 DiscontiguousThreeSphere
0080 DiscontiguousTwoSphere
0081 ContiguousBoxSphere
0082 DiscontiguousBoxSphere
0083 DifferenceBoxSphere
0084 ListTwoBoxTwoSphere
0085 RotatedCylinder
0086 DifferenceCylinder
0087 InfCylinder
0088 InfPhiCut
0089 InfThetaCut
0090 InfThetaCutL
0091 BoxSubSubCylinder
0092 )LITERAL";
0093
0094
0095 CSGSolid* CSGMaker::make(const char* name)
0096 {
0097 CSGSolid* so = nullptr ;
0098 if( StartsWith("JustOrb", name)) so = makeSphere(name) ;
0099 else if(StartsWith("BoxedSphere", name)) so = makeBoxedSphere(name) ;
0100 else if(StartsWith("ZSphere", name)) so = makeZSphere(name) ;
0101 else if(StartsWith("Cone", name)) so = makeCone(name) ;
0102 else if(StartsWith("Hyperboloid", name)) so = makeHyperboloid(name) ;
0103 else if(StartsWith("Box3", name)) so = makeBox3(name) ;
0104 else if(StartsWith("Plane", name)) so = makePlane(name) ;
0105 else if(StartsWith("Slab", name)) so = makeSlab(name) ;
0106 else if(StartsWith("Cylinder", name)) so = makeCylinder(name) ;
0107 else if(StartsWith("OldCylinder", name)) so = makeOldCylinder(name) ;
0108 else if(StartsWith("Disc", name)) so = makeDisc(name) ;
0109 else if(StartsWith("ConvexPolyhedronCube", name)) so = makeConvexPolyhedronCube(name) ;
0110 else if(StartsWith("ConvexPolyhedronTetrahedron", name)) so = makeConvexPolyhedronTetrahedron(name) ;
0111 else if(StartsWith("Ellipsoid", name)) so = makeEllipsoid(name) ;
0112 else if(StartsWith("UnionBoxSphere", name)) so = makeUnionBoxSphere(name) ;
0113 else if(StartsWith("UnionListBoxSphere", name)) so = makeUnionListBoxSphere(name) ;
0114 else if(StartsWith("UnionLLBoxSphere", name)) so = makeUnionLLBoxSphere(name) ;
0115 else if(StartsWith("IntersectionBoxSphere", name)) so = makeIntersectionBoxSphere(name) ;
0116 else if(StartsWith("OverlapBoxSphere", name)) so = makeOverlapBoxSphere(name) ;
0117 else if(StartsWith("OverlapThreeSphere", name)) so = makeOverlapThreeSphere(name) ;
0118 else if(StartsWith("ContiguousThreeSphere", name)) so = makeContiguousThreeSphere(name) ;
0119 else if(StartsWith("DiscontiguousThreeSphere", name)) so = makeDiscontiguousThreeSphere(name) ;
0120 else if(StartsWith("DiscontiguousTwoSphere", name)) so = makeDiscontiguousTwoSphere(name) ;
0121 else if(StartsWith("ContiguousBoxSphere", name)) so = makeContiguousBoxSphere(name) ;
0122 else if(StartsWith("DiscontiguousBoxSphere", name)) so = makeDiscontiguousBoxSphere(name) ;
0123 else if(StartsWith("DifferenceBoxSphere", name)) so = makeDifferenceBoxSphere(name) ;
0124 else if(StartsWith("ListTwoBoxTwoSphere", name)) so = makeListTwoBoxTwoSphere(name);
0125 else if(StartsWith("RotatedCylinder", name)) so = makeRotatedCylinder(name) ;
0126 else if(StartsWith("DifferenceCylinder", name)) so = makeDifferenceCylinder(name) ;
0127 else if(StartsWith("InfCylinder", name)) so = makeInfCylinder(name) ;
0128 else if(StartsWith("InfPhiCut", name)) so = makeInfPhiCut(name) ;
0129 else if(StartsWith("InfThetaCut", name)) so = makeInfThetaCut(name) ;
0130 else if(StartsWith("InfThetaCutL", name)) so = makeInfThetaCutL(name) ;
0131 else if(StartsWith("BoxSubSubCylinder", name)) so = makeBoxSubSubCylinder(name) ;
0132 else
0133 {
0134 LOG(fatal) << "invalid name [" << name << "]" << " expecting one of the below " << std::endl << NAMES ;
0135 LOG(error) << "perhaps you intended to convert from a G4VSolid : if so see ~/opticks/GeoChain/translate.sh " ;
0136 }
0137 assert( so );
0138 return so ;
0139 }
0140
0141
0142
0143 void CSGMaker::makeDemoSolids()
0144 {
0145 makeSphere();
0146 makeZSphere();
0147 makeCone();
0148 makeHyperboloid();
0149 makeBox3();
0150 makePlane();
0151 makeSlab();
0152 makeCylinder() ;
0153 makeDisc();
0154 makeConvexPolyhedronCube();
0155 makeConvexPolyhedronTetrahedron();
0156 makeEllipsoid();
0157 makeUnionBoxSphere();
0158 makeIntersectionBoxSphere();
0159 makeDifferenceBoxSphere();
0160 makeRotatedCylinder();
0161 makeDifferenceCylinder();
0162 makeBoxSubSubCylinder();
0163 }
0164
0165 void CSGMaker::makeDemoGrid()
0166 {
0167 makeDemoSolids();
0168 unsigned num_solids = fd->getNumSolid();
0169 LOG(info) << " num_solids " << num_solids ;
0170
0171 float gridscale = 100.f ;
0172 std::array<int,9> grid = {{ -10,11,2, -10,11,2, -10,11,2 }} ;
0173
0174 unsigned count = 0 ;
0175
0176 for(int i=grid[0] ; i < grid[1] ; i+=grid[2] ){
0177 for(int j=grid[3] ; j < grid[4] ; j+=grid[5] ){
0178 for(int k=grid[6] ; k < grid[7] ; k+=grid[8] ){
0179
0180 qat4 instance ;
0181 instance.q3.f.x = float(i)*gridscale ;
0182 instance.q3.f.y = float(j)*gridscale ;
0183 instance.q3.f.z = float(k)*gridscale ;
0184
0185 unsigned ins_idx = fd->inst.size() ;
0186 unsigned gas_idx = count % num_solids ;
0187 unsigned sensor_identifier = 0 ;
0188 unsigned sensor_index = 0 ;
0189
0190 instance.setIdentity( ins_idx, gas_idx, sensor_identifier, sensor_index );
0191 fd->inst.push_back( instance );
0192
0193 count++ ;
0194 }
0195 }
0196 }
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 CSGSolid* CSGMaker::makeLayered(const char* label, float outer_radius, unsigned layers )
0225 {
0226 std::vector<float> radii ;
0227 for(unsigned i=0 ; i < layers ; i++) radii.push_back(outer_radius*float(layers-i)/float(layers)) ;
0228
0229 unsigned numPrim = layers ;
0230 CSGSolid* so = fd->addSolid(numPrim, label);
0231 so->center_extent = make_float4( 0.f, 0.f, 0.f, outer_radius ) ;
0232
0233 for(unsigned i=0 ; i < numPrim ; i++)
0234 {
0235 unsigned numNode = 1 ;
0236 int nodeOffset_ = -1 ;
0237 CSGPrim* pr = fd->addPrim(numNode, nodeOffset_ );
0238
0239 float radius = radii[i];
0240
0241 CSGNode* nd = nullptr ;
0242
0243 if(strcmp(label, "sphere") == 0)
0244 {
0245 nd = fd->addNode(CSGNode::Sphere(radius));
0246 }
0247 else if(strcmp(label, "zsphere") == 0)
0248 {
0249 nd = fd->addNode(CSGNode::ZSphere(radius, -radius/2.f , radius/2.f ));
0250 }
0251 else
0252 {
0253 assert( 0 && "layered only implemented for sphere and zsphere currently" );
0254 }
0255
0256
0257 pr->setAABB( nd->AABB() );
0258 }
0259 return so ;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284 CSGSolid* CSGMaker::makeBoxedSphere(const char* label)
0285 {
0286 float halfside = ssys::getenvfloat("CSGMaker_makeBoxedSphere_HALFSIDE", 100.f);
0287 float factor = ssys::getenvfloat("CSGMaker_makeBoxedSphere_FACTOR", 1.f);
0288
0289
0290
0291 float radius = halfside/2.f ;
0292 float box_halfside = halfside*factor ;
0293
0294
0295 unsigned numPrim = 2 ;
0296 CSGSolid* so = fd->addSolid(numPrim, label);
0297 AABB bb = {} ;
0298
0299 for(unsigned i=0 ; i < numPrim ; i++)
0300 {
0301 CSGPrim* pr = fd->addPrim(1, -1);
0302 CSGNode* nd = nullptr ;
0303 switch(i)
0304 {
0305 case 0: nd = fd->addNode(CSGNode::Box3(2.f*box_halfside)) ; break ;
0306 case 1: nd = fd->addNode(CSGNode::Sphere(radius)) ; break ;
0307 }
0308 pr->setAABB( nd->AABB() );
0309 bb.include_aabb( nd->AABB() );
0310 }
0311
0312 so->center_extent = bb.center_extent() ;
0313
0314
0315 return so ;
0316 }
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 CSGSolid* CSGMaker::makeScaled(const char* label, const char* demo_node_type, float outer_scale, unsigned layers )
0333 {
0334 std::vector<float> scales ;
0335 for(unsigned i=0 ; i < layers ; i++) scales.push_back(outer_scale*float(layers-i)/float(layers)) ;
0336
0337 unsigned numPrim = layers ;
0338 CSGSolid* so = fd->addSolid(numPrim, label);
0339 AABB bb = {} ;
0340
0341 for(unsigned i=0 ; i < numPrim ; i++)
0342 {
0343 unsigned numNode = 1 ;
0344 int nodeOffset_ = -1;
0345 CSGPrim* pr = fd->addPrim(numNode, nodeOffset_);
0346 CSGNode* nd = fd->addNode(CSGNode::MakeDemo(demo_node_type)) ;
0347
0348 float scale = scales[i];
0349 const Tran<double>* tran_scale = Tran<double>::make_scale( double(scale), double(scale), double(scale) );
0350
0351
0352
0353
0354
0355
0356
0357
0358 bool transform_node_aabb = true ;
0359 fd->addNodeTran( nd, tran_scale, transform_node_aabb );
0360
0361
0362 bb.include_aabb( nd->AABB() );
0363
0364
0365 pr->setAABB( nd->AABB() );
0366 }
0367
0368 so->center_extent = bb.center_extent() ;
0369 LOG(info) << " so->center_extent " << so->center_extent ;
0370
0371 return so ;
0372 }
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383 CSGSolid* CSGMaker::makeClustered(const char* label, int i0, int i1, int is, int j0, int j1, int js, int k0, int k1, int ks, double unit, bool inbox )
0384 {
0385 unsigned numPrim = inbox ? 1 : 0 ;
0386 for(int i=i0 ; i < i1 ; i+=is )
0387 for(int j=j0 ; j < j1 ; j+=js )
0388 for(int k=k0 ; k < k1 ; k+=ks )
0389 {
0390
0391 numPrim += 1 ;
0392 }
0393
0394 LOG(info)
0395 << " label " << label
0396 << " numPrim " << numPrim
0397 << " inbox " << inbox
0398 ;
0399
0400 CSGSolid* so = fd->addSolid(numPrim, label);
0401 unsigned idx = 0 ;
0402
0403 AABB bb = {} ;
0404
0405 for(int i=i0 ; i < i1 ; i+=is )
0406 for(int j=j0 ; j < j1 ; j+=js )
0407 for(int k=k0 ; k < k1 ; k+=ks )
0408 {
0409 unsigned numNode = 1 ;
0410 int nodeOffset_ = -1 ;
0411 CSGPrim* p = fd->addPrim(numNode, nodeOffset_);
0412 CSGNode* n = fd->addNode(CSGNode::MakeDemo(label)) ;
0413
0414 const Tran<double>* translate = Tran<double>::make_translate( double(i)*unit, double(j)*unit, double(k)*unit );
0415
0416
0417 unsigned transform_idx = 1 + fd->addTran(translate);
0418 n->setTransform(transform_idx);
0419 const qat4* t = fd->getTran(transform_idx-1u) ;
0420 t->transform_aabb_inplace( n->AABB() );
0421
0422
0423
0424
0425 bb.include_aabb( n->AABB() );
0426
0427
0428 p->setAABB( n->AABB() );
0429
0430
0431
0432 LOG(info) << " idx " << idx << " transform_idx " << transform_idx ;
0433
0434 idx += 1 ;
0435 }
0436
0437
0438 if(inbox)
0439 {
0440 float4 ce = bb.center_extent();
0441 float fullside = ce.w*2.f ;
0442
0443 unsigned numNode = 1 ;
0444 int nodeOffset_ = -1 ;
0445
0446 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
0447 CSGNode bx = CSGNode::Box3(fullside) ;
0448 CSGNode* n = fd->addNode(bx);
0449
0450
0451 const Tran<float>* to_center = Tran<float>::make_translate( float(ce.x), float(ce.y), float(ce.z) );
0452 unsigned transform_idx = 1 + fd->addTran(to_center);
0453 const qat4* t = fd->getTran(transform_idx-1u) ;
0454
0455 n->setTransform(transform_idx);
0456 t->transform_aabb_inplace( n->AABB() );
0457
0458
0459 p->setAABB( n->AABB() );
0460
0461 idx += 1 ;
0462 }
0463
0464
0465 so->center_extent = bb.center_extent() ;
0466 LOG(info) << " so->center_extent " << so->center_extent ;
0467 return so ;
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 CSGSolid* CSGMaker::makeSolid11(const char* label, CSGNode nd, const std::vector<float4>* pl, int meshIdx, const Tran<double>* tr )
0480 {
0481 unsigned numPrim = 1 ;
0482 CSGSolid* so = fd->addSolid(numPrim, label);
0483
0484 unsigned numNode = 1 ;
0485 int nodeOffset_ = -1 ;
0486 CSGPrim* p = fd->addPrim(numNode, nodeOffset_);
0487 p->setMeshIdx(meshIdx);
0488
0489 CSGNode* n = fd->addNode(nd, pl, tr );
0490 p->setAABB( n->AABB() );
0491
0492 float extent = p->extent();
0493 LOG_IF(fatal, extent == 0.f) << "FATAL : " << label << " : got zero extent " ;
0494
0495
0496 AABB bb = AABB::Make( p->AABB() );
0497 so->center_extent = bb.center_extent() ;
0498
0499 return so ;
0500 }
0501
0502 CSGSolid* CSGMaker::makeBooleanBoxSphere( const char* label, unsigned op_, float radius, float fullside, int meshIdx )
0503 {
0504 LOG(LEVEL) << " fullside " << fullside << " radius " << radius ;
0505 CSGNode bx = CSGNode::Box3(fullside) ;
0506 CSGNode sp = CSGNode::Sphere(radius);
0507 return makeBooleanTriplet(label, op_, bx, sp );
0508 }
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 CSGSolid* CSGMaker::makeBooleanTriplet( const char* label, unsigned op_, const CSGNode& left, const CSGNode& right, int meshIdx )
0529 {
0530 unsigned numPrim = 1 ;
0531 CSGSolid* so = fd->addSolid(numPrim, label);
0532
0533 unsigned numNode = 3 ;
0534 int nodeOffset_ = -1 ;
0535 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
0536 if(meshIdx > -1) p->setMeshIdx(meshIdx);
0537
0538 CSGNode op = CSGNode::BooleanOperator(op_, -1);
0539 CSGNode* n = fd->addNode(op);
0540
0541 CSGNode* root = n ;
0542
0543 root->setSubNum(numNode);
0544 root->setSubOffset(0);
0545
0546
0547 fd->addNode(left);
0548 fd->addNode(right);
0549
0550
0551 AABB bb = {} ;
0552 bb.include_aabb( left.AABB() );
0553 bb.include_aabb( right.AABB() );
0554 p->setAABB( bb.data() );
0555
0556 so->center_extent = bb.center_extent() ;
0557
0558
0559
0560 unsigned transform_idx = 1 + fd->addTran();
0561 n->setTransform(transform_idx);
0562
0563
0564
0565 return so ;
0566 }
0567
0568
0569
0570
0571
0572
0573 CSGSolid* CSGMaker::makeOverlapBoxSphere( const char* label, float radius, float fullside )
0574 {
0575 CSGNode bx = CSGNode::Box3(fullside) ;
0576 CSGNode sp = CSGNode::Sphere(radius);
0577
0578 std::vector<CSGNode> leaves ;
0579 leaves.push_back(bx);
0580 leaves.push_back(sp);
0581
0582 return makeOverlapList( label, leaves, nullptr );
0583 }
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611 CSGSolid* CSGMaker::makeListThreeSphere( const char* label, unsigned type, float radius, float side )
0612 {
0613 CSGNode s0 = CSGNode::Sphere(radius);
0614 CSGNode s1 = CSGNode::Sphere(radius);
0615 CSGNode s2 = CSGNode::Sphere(radius);
0616
0617 const Tran<double>* t0 = Tran<double>::make_translate( side, side , 0. );
0618 const Tran<double>* t1 = Tran<double>::make_translate( -side, side , 0. );
0619 const Tran<double>* t2 = Tran<double>::make_translate( 0., -side*sqrt(2.), 0. );
0620
0621
0622 std::vector<CSGNode> leaves ;
0623 leaves.push_back(s0);
0624 leaves.push_back(s1);
0625 leaves.push_back(s2);
0626
0627 std::vector<const Tran<double>*> tran ;
0628 tran.push_back(t0);
0629 tran.push_back(t1);
0630 tran.push_back(t2);
0631
0632 return makeList( label, type, leaves, &tran );
0633 }
0634
0635 CSGSolid* CSGMaker::makeOverlapThreeSphere( const char* label, float radius, float side )
0636 {
0637 return makeListThreeSphere( label, CSG_OVERLAP , radius, side );
0638 }
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662
0663 CSGSolid* CSGMaker::makeContiguousThreeSphere( const char* label, float radius, float side )
0664 {
0665 return makeListThreeSphere( label, CSG_CONTIGUOUS , radius, side );
0666 }
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 CSGSolid* CSGMaker::makeDiscontiguousThreeSphere( const char* label, float radius, float side )
0699 {
0700 return makeListThreeSphere( label, CSG_DISCONTIGUOUS , radius, side );
0701 }
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725 CSGSolid* CSGMaker::makeDiscontiguousTwoSphere( const char* label, float radius, float side )
0726 {
0727 return makeListTwoSphere( label, CSG_DISCONTIGUOUS , radius, side );
0728 }
0729
0730 CSGSolid* CSGMaker::makeListTwoSphere( const char* label, unsigned type, float radius, float side )
0731 {
0732 CSGNode s0 = CSGNode::Sphere(radius);
0733 CSGNode s1 = CSGNode::Sphere(radius);
0734
0735 const Tran<double>* t0 = Tran<double>::make_translate( side, 0.5*side , 0. );
0736 const Tran<double>* t1 = Tran<double>::make_translate( -side, 2.0*side , 0. );
0737
0738 std::vector<CSGNode> leaves ;
0739 leaves.push_back(s0);
0740 leaves.push_back(s1);
0741
0742 std::vector<const Tran<double>*> tran ;
0743 tran.push_back(t0);
0744 tran.push_back(t1);
0745
0746 return makeList( label, type, leaves, &tran );
0747 }
0748
0749
0750
0751
0752 CSGSolid* CSGMaker::makeContiguousBoxSphere( const char* label, float radius, float fullside )
0753 {
0754 CSGNode bx = CSGNode::Box3(fullside) ;
0755 CSGNode sp = CSGNode::Sphere(radius);
0756
0757 std::vector<CSGNode> leaves ;
0758 leaves.push_back(bx);
0759 leaves.push_back(sp);
0760
0761 return makeContiguousList( label, leaves, nullptr );
0762 }
0763
0764 CSGSolid* CSGMaker::makeDiscontiguousBoxSphere( const char* label, float radius, float fullside )
0765 {
0766 CSGNode bx = CSGNode::Box3(fullside) ;
0767 CSGNode sp = CSGNode::Sphere(radius);
0768
0769 const Tran<double>* bx_shift = Tran<double>::make_translate( fullside, 0., 0. ) ;
0770 const Tran<double>* sp_shift = Tran<double>::make_translate(-fullside, 0., 0. ) ;
0771
0772 std::vector<CSGNode> leaves ;
0773 leaves.push_back(bx);
0774 leaves.push_back(sp);
0775
0776 std::vector<const Tran<double>*> trans ;
0777 trans.push_back(bx_shift);
0778 trans.push_back(sp_shift);
0779
0780 return makeDiscontiguousList( label, leaves, &trans );
0781 }
0782
0783
0784
0785
0786 CSGSolid* CSGMaker::makeOverlapList( const char* label, std::vector<CSGNode>& leaves, const std::vector<const Tran<double>*>* tran )
0787 {
0788 return makeList( label, CSG_OVERLAP, leaves, tran );
0789 }
0790 CSGSolid* CSGMaker::makeContiguousList( const char* label, std::vector<CSGNode>& leaves, const std::vector<const Tran<double>*>* tran )
0791 {
0792 return makeList( label, CSG_CONTIGUOUS, leaves, tran );
0793 }
0794 CSGSolid* CSGMaker::makeDiscontiguousList( const char* label, std::vector<CSGNode>& leaves, const std::vector<const Tran<double>*>* tran )
0795 {
0796 return makeList( label, CSG_DISCONTIGUOUS, leaves, tran );
0797 }
0798
0799
0800 CSGSolid* CSGMaker::makeList( const char* label, unsigned type, std::vector<CSGNode>& leaves, const std::vector<const Tran<double>*>* tran )
0801 {
0802 unsigned numSub = leaves.size() ;
0803 unsigned numTran = tran ? tran->size() : 0 ;
0804 if( numTran > 0 ) assert( numSub == numTran );
0805
0806 unsigned numPrim = 1 ;
0807 CSGSolid* so = fd->addSolid(numPrim, label);
0808
0809 unsigned numNode = 1 + numSub ;
0810 int nodeOffset_ = -1 ;
0811 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
0812
0813 unsigned subOffset = 1 ;
0814 CSGNode hdr = CSGNode::ListHeader(type, numSub, subOffset );
0815 CSGNode* n = fd->addNode(hdr);
0816
0817 AABB bb = {} ;
0818 fd->addNodes( bb, leaves, tran );
0819 p->setAABB( bb.data() );
0820 so->center_extent = bb.center_extent() ;
0821
0822 fd->addNodeTran(n);
0823
0824
0825
0826 return so ;
0827 }
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855 CSGSolid* CSGMaker::makeUnionListBoxSphere( const char* label, float radius, float fullside )
0856 {
0857
0858 CSGNode op = CSGNode::BooleanOperator(CSG_UNION, 3);
0859 CSGNode left = CSGNode::Box3(fullside) ;
0860
0861 int subNum = 1 ;
0862 int subOffset = op.subNum() ;
0863 CSGNode right = CSGNode::ListHeader(CSG_CONTIGUOUS, subNum, subOffset );
0864 CSGNode sub = CSGNode::Sphere(radius);
0865
0866 unsigned numPrim = 1 ;
0867 CSGSolid* so = fd->addSolid(numPrim, label);
0868
0869 unsigned numNode = 3 + subNum ;
0870 int nodeOffset_ = -1 ;
0871 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
0872
0873 CSGNode* root = fd->addNode(op);
0874 CSGNode* l = fd->addNode(left);
0875 CSGNode* r = fd->addNode(right);
0876 CSGNode* s = fd->addNode(sub);
0877
0878 bool root_expect = root->typecode() == CSG_UNION ;
0879 bool l_expect = l->typecode() == CSG_BOX3 ;
0880 bool r_expect = r->typecode() == CSG_CONTIGUOUS ;
0881 bool s_expect = s->typecode() == CSG_SPHERE ;
0882 bool op_expect = op.subNum() == 3 && root->subNum() == 3 ;
0883
0884 assert( root_expect );
0885 assert( l_expect );
0886 assert( r_expect );
0887 assert( s_expect );
0888 assert( op_expect );
0889
0890 if(!root_expect) std::raise(SIGINT);
0891 if(!l_expect) std::raise(SIGINT);
0892 if(!r_expect) std::raise(SIGINT);
0893 if(!s_expect) std::raise(SIGINT);
0894 if(!op_expect) std::raise(SIGINT);
0895
0896 AABB bb = {} ;
0897 bb.include_aabb( right.AABB() );
0898 bb.include_aabb( sub.AABB() );
0899 p->setAABB( bb.data() );
0900 so->center_extent = bb.center_extent() ;
0901
0902 fd->addNodeTran(root);
0903
0904
0905 return so ;
0906 }
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920 CSGSolid* CSGMaker::makeBooleanListList( const char* label,
0921 unsigned op_,
0922 unsigned ltype,
0923 unsigned rtype,
0924 std::vector<CSGNode>& lhs,
0925 std::vector<CSGNode>& rhs,
0926 const std::vector<const Tran<double>*>* ltran,
0927 const std::vector<const Tran<double>*>* rtran
0928 )
0929 {
0930 unsigned num_left = lhs.size();
0931 unsigned num_right = rhs.size();
0932 assert( num_left > 0 && num_right > 0 );
0933
0934
0935 unsigned numNode = 3 + ( num_left == 1 ? 0 : num_left ) + ( num_right == 1 ? 0 : num_right ) ;
0936
0937 unsigned numPrim = 1 ;
0938 CSGSolid* so = fd->addSolid(numPrim, label);
0939
0940 int nodeOffset_ = -1 ;
0941 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
0942
0943 CSGNode op = CSGNode::BooleanOperator(op_, 3);
0944 CSGNode* root = fd->addNode(op);
0945
0946 unsigned subOffset = 0 ;
0947 subOffset += root->subNum() ;
0948 assert( subOffset == 3 );
0949
0950
0951 AABB bb = {} ;
0952
0953 if( num_left == 1 && num_right == 1 )
0954 {
0955 const CSGNode& left = lhs[0];
0956 const CSGNode& right = rhs[0];
0957
0958 fd->addNode(bb, left);
0959 fd->addNode(bb, right);
0960 }
0961 else if( num_left > 1 && num_right == 1 )
0962 {
0963 CSGNode left = CSGNode::ListHeader(ltype, num_left, subOffset );
0964 subOffset += num_left ;
0965
0966 const CSGNode& right = rhs[0];
0967
0968 fd->addNode(left);
0969 fd->addNode(bb, right);
0970 fd->addNodes(bb, lhs, ltran);
0971 }
0972 else if( num_left == 1 && num_right > 1 )
0973 {
0974 CSGNode left = lhs[0] ;
0975 CSGNode right = CSGNode::ListHeader(rtype, num_right, subOffset );
0976 subOffset += num_right ;
0977
0978 fd->addNode(bb, left);
0979 fd->addNode(right);
0980 fd->addNodes(bb, rhs, rtran);
0981 }
0982 else if( num_left > 1 && num_right > 1 )
0983 {
0984 CSGNode left = CSGNode::ListHeader(ltype, num_left, subOffset );
0985 subOffset += num_left ;
0986
0987 CSGNode right = CSGNode::ListHeader(rtype, num_right, subOffset );
0988 subOffset += num_right ;
0989
0990 fd->addNode(left);
0991 fd->addNode(right);
0992
0993 fd->addNodes( bb, lhs, ltran );
0994 fd->addNodes( bb, rhs, rtran );
0995 }
0996
0997
0998 p->setAABB( bb.data() );
0999 so->center_extent = bb.center_extent() ;
1000
1001 fd->addNodeTran(root);
1002
1003 return so ;
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
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047 CSGSolid* CSGMaker::makeUnionLLBoxSphere( const char* label, float radius, float fullside )
1048 {
1049 std::vector<CSGNode> lhs ;
1050 lhs.push_back( CSGNode::Sphere(radius) );
1051 lhs.push_back( CSGNode::Sphere(radius) );
1052
1053 std::vector<const Tran<double>*> ltran ;
1054 ltran.push_back(Tran<double>::make_translate( -radius/2., 0., 0. )) ;
1055 ltran.push_back(Tran<double>::make_translate( radius/2., 0., 0. )) ;
1056
1057 std::vector<CSGNode> rhs ;
1058 rhs.push_back( CSGNode::Box3(fullside) );
1059 rhs.push_back( CSGNode::Box3(fullside) );
1060
1061 std::vector<const Tran<double>*> rtran ;
1062 rtran.push_back(Tran<double>::make_translate( 0., fullside, 0. )) ;
1063 rtran.push_back(Tran<double>::make_translate( 0., -fullside, 0. )) ;
1064
1065 unsigned btype = CSG_DIFFERENCE ;
1066 unsigned ltype = CSG_CONTIGUOUS ;
1067 unsigned rtype = CSG_DISCONTIGUOUS ;
1068
1069 return makeBooleanListList(label, btype, ltype, rtype, lhs, rhs, <ran, &rtran );
1070 }
1071
1072 CSGSolid* CSGMaker::makeListTwoBoxTwoSphere( const char* label, float radius, float fullside )
1073 {
1074 std::vector<CSGNode> leaves ;
1075 leaves.push_back( CSGNode::Sphere(radius) );
1076 leaves.push_back( CSGNode::Sphere(radius) );
1077 leaves.push_back( CSGNode::Box3(fullside) );
1078 leaves.push_back( CSGNode::Box3(fullside) );
1079
1080 std::vector<const Tran<double>*> tran ;
1081 tran.push_back(Tran<double>::make_translate( -radius/2., 0., 0. )) ;
1082 tran.push_back(Tran<double>::make_translate( radius/2., 0., 0. )) ;
1083 tran.push_back(Tran<double>::make_translate( 0., fullside, 0. )) ;
1084 tran.push_back(Tran<double>::make_translate( 0., -fullside, 0. )) ;
1085
1086 unsigned type = CSG_DISCONTIGUOUS ;
1087
1088 return makeList( label, type, leaves, &tran );
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 CSGSolid* CSGMaker::makeBooleanSeptuplet(
1106 const char* label,
1107 const CSGNode& top,
1108 const CSGNode& l,
1109 const CSGNode& r,
1110 const CSGNode& ll,
1111 const CSGNode& lr,
1112 const CSGNode& rl,
1113 const CSGNode& rr,
1114 const int meshIdx )
1115 {
1116 unsigned numPrim = 1 ;
1117 CSGSolid* so = fd->addSolid(numPrim, label);
1118
1119 unsigned numNode = 7 ;
1120 int nodeOffset_ = -1 ;
1121 CSGPrim* p = fd->addPrim(numNode, nodeOffset_ );
1122 if(meshIdx > -1) p->setMeshIdx(meshIdx);
1123
1124 std::vector<CSGNode> nn = {top, l, r, ll, lr, rl, rr } ;
1125 assert( nn.size() == numNode );
1126
1127 CSGNode* tptr = nullptr ;
1128 AABB bb = {} ;
1129 for(unsigned i=0 ; i < numNode ; i++ )
1130 {
1131 const CSGNode& n = nn[i] ;
1132 CSGNode* nptr = fd->addNode(n);
1133 if(i == 0) tptr = nptr ;
1134
1135 if( n.is_primitive() && !n.is_zero() && !n.is_complement() )
1136 {
1137 bb.include_aabb( n.AABB() );
1138 }
1139 }
1140 p->setAABB( bb.data() );
1141
1142 so->center_extent = bb.center_extent() ;
1143
1144
1145
1146 unsigned transform_idx = 1 + fd->addTran();
1147 tptr->setTransform(transform_idx);
1148
1149
1150 return so ;
1151 }
1152
1153
1154 CSGSolid* CSGMaker::makeDifferenceCylinder( const char* label, float rmax, float rmin, float z1, float z2, float z_inner_factor )
1155 {
1156 assert( rmax > rmin );
1157 assert( z2 > z1 );
1158 CSGNode outer = CSGNode::Cylinder( rmax, z1, z2 );
1159 CSGNode inner = CSGNode::Cylinder( rmin, z1*z_inner_factor, z2*z_inner_factor );
1160 return makeBooleanTriplet(label, CSG_DIFFERENCE, outer, inner );
1161 }
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178 CSGSolid* CSGMaker::makeBoxSubSubCylinder( const char* label, float fullside, float rmax, float rmin, float z1, float z2, float z_inner_factor )
1179 {
1180 CSGNode t = CSGNode::BooleanOperator(CSG_DIFFERENCE, -1);
1181 CSGNode l = CSGNode::Box3(fullside) ;
1182 CSGNode r = CSGNode::BooleanOperator(CSG_DIFFERENCE, -1);
1183 CSGNode ll = CSGNode::Zero();
1184 CSGNode lr = CSGNode::Zero();
1185 CSGNode rl = CSGNode::Cylinder( rmax, z1, z2 );
1186 CSGNode rr = CSGNode::Cylinder( rmin, z1*z_inner_factor, z2*z_inner_factor );
1187 int meshIdx = -1 ;
1188 return makeBooleanSeptuplet(label, t, l, r, ll, lr, rl, rr, meshIdx );
1189 }
1190
1191
1192
1193
1194
1195 CSGSolid* CSGMaker::makeUnionBoxSphere( const char* label, float radius, float fullside ){
1196 return makeBooleanBoxSphere(label, CSG_UNION, radius, fullside, UBSP_MIDX );
1197 }
1198 CSGSolid* CSGMaker::makeIntersectionBoxSphere( const char* label, float radius, float fullside ){
1199 return makeBooleanBoxSphere(label, CSG_INTERSECTION, radius, fullside, IBSP_MIDX );
1200 }
1201 CSGSolid* CSGMaker::makeDifferenceBoxSphere( const char* label, float radius, float fullside ){
1202 return makeBooleanBoxSphere(label, CSG_DIFFERENCE, radius, fullside, DBSP_MIDX );
1203 }
1204
1205
1206
1207
1208
1209 CSGSolid* CSGMaker::makeSphere(const char* label, float radius)
1210 {
1211 CSGNode nd = CSGNode::Sphere(radius);
1212 return makeSolid11(label, nd, nullptr, SPHE_MIDX );
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224 CSGSolid* CSGMaker::makeEllipsoid( const char* label, float rx, float ry, float rz )
1225 {
1226 CSGNode nd = CSGNode::Sphere(rx);
1227
1228 double dx = double(rx) ;
1229 double dy = double(ry) ;
1230 double dz = double(rz) ;
1231
1232 double sx = double(1.) ;
1233 double sy = dy/dx ;
1234 double sz = dz/dx ;
1235
1236 const Tran<double>* tr = Tran<double>::make_scale(sx, sy, sz );
1237
1238 return makeSolid11(label, nd, nullptr, ELLI_MIDX, tr );
1239 }
1240
1241
1242 CSGSolid* CSGMaker::makeRotatedCylinder(const char* label, float px, float py, float radius, float z1, float z2, float ax, float ay, float az, float angle_deg )
1243 {
1244 assert( px == 0.f );
1245 assert( py == 0.f );
1246
1247 CSGNode nd = CSGNode::Cylinder( radius, z1, z2 );
1248 const Tran<double>* tr = Tran<double>::make_rotate(ax, ay, az, angle_deg );
1249 return makeSolid11(label, nd, nullptr, RCYL_MIDX, tr );
1250 }
1251
1252
1253 CSGSolid* CSGMaker::makeInfCylinder(const char* label, float radius, float hz )
1254 {
1255 CSGNode nd = CSGNode::InfCylinder( radius, hz );
1256 return makeSolid11(label, nd, nullptr, ICYL_MIDX );
1257 }
1258
1259 CSGSolid* CSGMaker::makeInfPhiCut(const char* label, float startPhi_pi, float deltaPhi_pi )
1260 {
1261 CSGNode nd = CSGNode::InfPhiCut(startPhi_pi, deltaPhi_pi );
1262 return makeSolid11(label, nd, nullptr, IPHI_MIDX );
1263 }
1264
1265
1266 CSGSolid* CSGMaker::makeInfThetaCut(const char* label, float startTheta_pi, float deltaTheta_pi )
1267 {
1268 CSGNode nd = CSGNode::InfThetaCut(startTheta_pi, deltaTheta_pi );
1269 return makeSolid11(label, nd, nullptr, ITHE_MIDX );
1270 }
1271 CSGSolid* CSGMaker::makeInfThetaCutL(const char* label, float startTheta_pi, float deltaTheta_pi )
1272 {
1273 CSGNode nd = CSGNode::InfThetaCut(startTheta_pi, deltaTheta_pi );
1274 return makeSolid11(label, nd, nullptr, ITHL_MIDX );
1275 }
1276
1277
1278
1279
1280
1281 CSGSolid* CSGMaker::makeZSphere(const char* label, float radius, float z1, float z2)
1282 {
1283 CSGNode nd = CSGNode::ZSphere(radius, z1, z2);
1284 return makeSolid11(label, nd, nullptr, ZSPH_MIDX );
1285 }
1286
1287 CSGSolid* CSGMaker::makeCone(const char* label, float r1, float z1, float r2, float z2)
1288 {
1289 CSGNode nd = CSGNode::Cone(r1, z1, r2, z2 );
1290 return makeSolid11(label, nd, nullptr, CONE_MIDX );
1291 }
1292
1293 CSGSolid* CSGMaker::makeHyperboloid(const char* label, float r0, float zf, float z1, float z2)
1294 {
1295 CSGNode nd = CSGNode::Hyperboloid( r0, zf, z1, z2 );
1296 return makeSolid11(label, nd, nullptr, HYPE_MIDX );
1297 }
1298
1299 CSGSolid* CSGMaker::makeBox3(const char* label, float fx, float fy, float fz )
1300 {
1301 CSGNode nd = CSGNode::Box3(fx, fy, fz);
1302 return makeSolid11(label, nd, nullptr, BOX3_MIDX );
1303 }
1304
1305 CSGSolid* CSGMaker::makePlane(const char* label, float nx, float ny, float nz, float d)
1306 {
1307 CSGNode nd = CSGNode::Plane(nx, ny, nz, d );
1308 return makeSolid11(label, nd, nullptr, PLAN_MIDX );
1309 }
1310
1311 CSGSolid* CSGMaker::makeSlab(const char* label, float nx, float ny, float nz, float d1, float d2 )
1312 {
1313 CSGNode nd = CSGNode::Slab( nx, ny, nz, d1, d1 );
1314 return makeSolid11(label, nd, nullptr, SLAB_MIDX );
1315 }
1316
1317 CSGSolid* CSGMaker::makeCylinder(const char* label, float radius, float z1, float z2)
1318 {
1319 CSGNode nd = CSGNode::Cylinder( radius, z1, z2 );
1320 return makeSolid11(label, nd, nullptr, CYLI_MIDX );
1321 }
1322
1323 CSGSolid* CSGMaker::makeOldCylinder(const char* label, float radius, float z1, float z2)
1324 {
1325 CSGNode nd = CSGNode::OldCylinder( radius, z1, z2 );
1326 return makeSolid11(label, nd, nullptr, OCYL_MIDX );
1327 }
1328
1329
1330 CSGSolid* CSGMaker::makeDisc(const char* label, float px, float py, float ir, float r, float z1, float z2)
1331 {
1332 CSGNode nd = CSGNode::Disc(px, py, ir, r, z1, z2 );
1333 return makeSolid11(label, nd, nullptr, DISC_MIDX );
1334 }
1335
1336
1337 float4 CSGMaker::TriPlane( const std::vector<float3>& v, unsigned i, unsigned j, unsigned k )
1338 {
1339
1340 float3 ij = v[j] - v[i] ;
1341 float3 ik = v[k] - v[i] ;
1342 float3 n = normalize(cross(ij, ik )) ;
1343 float di = dot( n, v[i] ) ;
1344
1345
1346
1347 float4 plane = make_float4( n, di ) ;
1348 return plane ;
1349 }
1350
1351 CSGSolid* CSGMaker::makeConvexPolyhedronCube(const char* label, float extent)
1352 {
1353 float hx = extent ;
1354 float hy = extent/2.f ;
1355 float hz = extent/3.f ;
1356
1357 std::vector<float4> pl ;
1358 pl.push_back( make_float4( 1.f, 0.f, 0.f, hx ) );
1359 pl.push_back( make_float4( -1.f, 0.f, 0.f, hx ) );
1360 pl.push_back( make_float4( 0.f, 1.f, 0.f, hy ) );
1361 pl.push_back( make_float4( 0.f, -1.f, 0.f, hy ) );
1362 pl.push_back( make_float4( 0.f, 0.f, 1.f, hz ) );
1363 pl.push_back( make_float4( 0.f, 0.f, -1.f, hz ) );
1364
1365 CSGNode nd = {} ;
1366 nd.setAABB(-hx, -hy, -hz, hx, hy, hz);
1367 return makeSolid11(label, nd, &pl, VCUB_MIDX );
1368 }
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404 CSGSolid* CSGMaker::makeConvexPolyhedronTetrahedron(const char* label, float extent)
1405 {
1406
1407 float s = extent ;
1408
1409 std::vector<float3> vtx ;
1410 vtx.push_back(make_float3( s, s, s));
1411 vtx.push_back(make_float3( s,-s,-s));
1412 vtx.push_back(make_float3(-s, s,-s));
1413 vtx.push_back(make_float3(-s,-s, s));
1414
1415 std::vector<float4> pl ;
1416 pl.push_back(TriPlane(vtx, 0, 1, 2)) ;
1417 pl.push_back(TriPlane(vtx, 1, 3, 2)) ;
1418 pl.push_back(TriPlane(vtx, 3, 0, 2)) ;
1419 pl.push_back(TriPlane(vtx, 0, 3, 1)) ;
1420
1421
1422
1423 CSGNode nd = {} ;
1424 nd.setAABB(extent);
1425 return makeSolid11(label, nd, &pl, VTET_MIDX );
1426 }
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 CSGFoundry* CSGMaker::MakeGeom(const char* geom)
1441 {
1442 CSGFoundry* fd = new CSGFoundry();
1443 CSGMaker* mk = fd->maker ;
1444 CSGSolid* so = mk->make( geom );
1445 fd->setGeom(geom);
1446
1447 fd->addTranPlaceholder();
1448 fd->addInstancePlaceholder();
1449
1450
1451 fd->addMeshName(geom);
1452 fd->addSolidMMLabel(geom);
1453 fd->setMeta<std::string>("source", "CSGFoundry::MakeGeom" );
1454
1455 assert( so );
1456
1457 LOG(info) << " so " << so ;
1458 LOG(info) << " so.desc " << so->desc() ;
1459 LOG(info) << " fd.desc " << fd->desc() ;
1460
1461 return fd ;
1462 }
1463
1464
1465
1466
1467
1468
1469
1470
1471 CSGFoundry* CSGMaker::MakeDemo()
1472 {
1473 CSGFoundry* fd = new CSGFoundry();
1474 fd->makeDemoSolids();
1475 return fd ;
1476 }
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513