File indexing completed on 2026-04-09 07:48:57
0001 #include <csignal>
0002
0003 #include "SLOG.hh"
0004 #include "ssys.h"
0005 #include "spath.h"
0006 #include "sdirectory.h"
0007 #include "scuda.h"
0008 #include "squad.h"
0009 #include "sc4u.h"
0010
0011 #include "SCenterExtentGenstep.hh"
0012 #include "NP.hh"
0013
0014 #include "CSGQuery.h"
0015 #include "CSGDraw.h"
0016 #include "CSGFoundry.h"
0017 #include "CSGMaker.h"
0018 #include "CSGGeometry.h"
0019 #include "CSGRecord.h"
0020 #include "CSGGrid.h"
0021
0022 const plog::Severity CSGGeometry::LEVEL = SLOG::EnvLevel("CSGGeometry", "DEBUG") ;
0023
0024
0025 void CSGGeometry::operator()()
0026 {
0027 LOG(info) ;
0028
0029 bool dump_ = ssys::getenvbool("DUMP");
0030 if(dump_)
0031 {
0032 LOG(info) << " dump " ;
0033 dump();
0034 LOG(info) << desc();
0035
0036 }
0037 else
0038 {
0039 LOG(info) << " centerExtentGenstepIntersect " ;
0040 centerExtentGenstepIntersect();
0041 }
0042 }
0043
0044
0045 const char* CSGGeometry::OutDir(const char* cfbase, const char* geom, const char* sopr)
0046 {
0047 if(cfbase == nullptr )
0048 {
0049 LOG(LEVEL) << " require CFBASE to control output dir " ;
0050 return nullptr ;
0051 }
0052
0053 const char* reldir = geom ? geom : sopr ;
0054
0055 if(reldir == nullptr )
0056 {
0057 LOG(fatal) << " require geom or sopr to control reldir included in output dir " ;
0058 return nullptr ;
0059 }
0060
0061 const char* outdir = spath::Resolve(cfbase, "CSGIntersectSolidTest", reldir );
0062 sdirectory::MakeDirs(outdir);
0063
0064 return outdir ;
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 CSGGeometry::CSGGeometry(const char* default_cfbase, const CSGFoundry* fd_)
0081 :
0082 default_geom(nullptr),
0083 default_sopr(nullptr),
0084 geom(ssys::getenvvar("CSGGeometry_GEOM", default_geom)),
0085 sopr(ssys::getenvvar("SOPR", default_sopr)),
0086 cfbase(ssys::getenvvar("CFBASE", default_cfbase)),
0087 outdir(OutDir(cfbase,geom,sopr)),
0088 name(nullptr),
0089 fd(fd_),
0090 q(nullptr),
0091 ce(nullptr),
0092 d(nullptr),
0093 sxyzw(ssys::getenvintvec("SXYZW",',')),
0094 sxyz(ssys::getenvintvec("SXYZ",',')),
0095 no_selection(sxyzw == nullptr && sxyz == nullptr),
0096 sx(0),
0097 sy(0),
0098 sz(0),
0099 sw(0),
0100 rc(0)
0101 {
0102 init();
0103 }
0104
0105 void CSGGeometry::init()
0106 {
0107 LOG(LEVEL) << " CSGGeometry_GEOM " << geom ;
0108 init_fd();
0109
0110 if(fd == nullptr)
0111 {
0112 LOG(fatal) << " ABORT " ;
0113 rc = 101 ;
0114 return ;
0115 }
0116
0117 q = new CSGQuery(fd);
0118 q->dumpPrim("CSGGeometry::init");
0119 ce = new float4(q->select_prim->ce()) ;
0120 d = new CSGDraw(q, 'Z') ;
0121 init_selection();
0122 }
0123
0124 void CSGGeometry::init_fd()
0125 {
0126 if( fd == nullptr )
0127 {
0128 if( geom != nullptr && cfbase == nullptr)
0129 {
0130 name = strdup(geom);
0131 LOG(info) << "init from GEOM " << geom << " name " << name ;
0132 fd = CSGMaker::MakeGeom(geom) ;
0133 }
0134 else if(cfbase != nullptr)
0135 {
0136 name = spath::Basename(cfbase);
0137 LOG(info) << "init from CFBASE " << cfbase << " name " << name ;
0138 fd = CSGFoundry::Load(cfbase, "CSGFoundry");
0139 LOG(info) << " fd.meta\n" << ( fd->hasMeta() ? fd->meta : " NO meta " ) ;
0140 }
0141 else
0142 {
0143 LOG(fatal) << " neither GEOM or CFBASE envvars are defined and fd pointer not provided : ABORT " ;
0144
0145 }
0146 }
0147 else
0148 {
0149 LOG(LEVEL) << " booting from provided CSGFoundry pointer " ;
0150 cfbase = fd->getCFBase();
0151 }
0152 }
0153
0154 void CSGGeometry::init_selection()
0155 {
0156 if(sxyz)
0157 {
0158 bool sxyz_expect = sxyz->size() == 3 ;
0159 if(!sxyz_expect)
0160 {
0161 LOG(fatal) << "SXYZ envvar is provided but with size: " << sxyz->size() << " when 3 is expected" ;
0162 assert(0);
0163 }
0164 sx = (*sxyz)[0] ;
0165 sy = (*sxyz)[1] ;
0166 sz = (*sxyz)[2] ;
0167
0168 LOG(info) << "SXYZ (sx,sy,sz) " << "(" << sx << "," << sy << "," << sz << ")" ;
0169 }
0170 else if(sxyzw)
0171 {
0172 bool sxyzw_expect = sxyzw->size() == 4 ;
0173 if(!sxyzw_expect)
0174 {
0175 LOG(fatal) << "SXYZW envvar is provided but with size: " << sxyzw->size() << " when 4 is expected" ;
0176 assert(0);
0177 }
0178 sx = (*sxyzw)[0] ;
0179 sy = (*sxyzw)[1] ;
0180 sz = (*sxyzw)[2] ;
0181 sw = (*sxyzw)[3] ;
0182 LOG(info) << "SXYZW (sx,sy,sz,sw) " << "(" << sx << "," << sy << "," << sz << "," << sw << ")" ;
0183 }
0184 else
0185 {
0186 LOG(LEVEL) << " no SXYZ or SXYZW selection " ;
0187 }
0188 }
0189
0190
0191
0192 void CSGGeometry::saveSignedDistanceField() const
0193 {
0194 LOG_IF(error, q == nullptr ) << " q null : ABORT " ;
0195 if(!q) return ;
0196
0197 int resolution = ssys::getenvint("RESOLUTION", 25) ;
0198 LOG(info) << " name " << name << " RESOLUTION " << resolution ;
0199
0200 q->dumpPrim();
0201
0202 const CSGGrid* grid = q->scanPrim(resolution);
0203 assert( grid );
0204 grid->save(name);
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 void CSGGeometry::centerExtentGenstepIntersect()
0219 {
0220 const char* path = ssys::getenvvar("SELECTED_ISECT");
0221 if(path == nullptr)
0222 {
0223 float t_min = ssys::getenvfloat("TMIN", 0.f );
0224 saveCenterExtentGenstepIntersect(t_min);
0225 }
0226 else
0227 {
0228 intersectSelected(path);
0229 }
0230
0231 LOG(info) << desc() ;
0232 }
0233
0234
0235 void CSGGeometry::saveCenterExtentGenstepIntersect(float t_min) const
0236 {
0237
0238 SCenterExtentGenstep* cegs = new SCenterExtentGenstep(ce) ;
0239 const std::vector<quad4>& pp = cegs->pp ;
0240 std::vector<quad4>& ii = cegs->ii ;
0241
0242 LOG(info) << "[ pp.size " << pp.size() << " t_min " << std::fixed << std::setw(10) << std::setprecision(4) << t_min ;
0243
0244 C4U gsid ;
0245 quad4 isect ;
0246 unsigned num_ray(0);
0247
0248 for(unsigned i=0 ; i < pp.size() ; i++)
0249 {
0250 const quad4& p = pp[i];
0251 gsid.u = p.q3.u.w ;
0252
0253 int ix = gsid.c4.x ;
0254 int iy = gsid.c4.y ;
0255 int iz = gsid.c4.z ;
0256 int iw = gsid.c4.w ;
0257
0258 if( sxyz == nullptr && sxyzw == nullptr )
0259 {
0260 num_ray += 1 ;
0261 if(q->intersect(isect, t_min, p )) ii.push_back(isect);
0262 }
0263 else if( sxyz && ix == sx && iy == sy && iz == sz )
0264 {
0265 num_ray += 1 ;
0266 if(q->intersect(isect, t_min, p )) ii.push_back(isect);
0267 }
0268 else if( sxyzw && ix == sx && iy == sy && iz == sz && iw == sw )
0269 {
0270 num_ray += 1 ;
0271 LOG(info) << "[ single photon selected" ;
0272 bool valid_isect = q->intersect(isect, t_min, p ) ;
0273 if(valid_isect) ii.push_back(isect);
0274 LOG(info) << std::endl << CSGQuery::Desc(isect, "single photon selected", &valid_isect ) ;
0275
0276 #ifdef DEBUG_RECORD
0277 std::string gsid_name = C4U_name( gsid.u , "gsid", '_' );
0278 const char* dir = spath::Resolve(outdir, "saveCenterExtentGenstepIntersect", gsid_name.c_str() );
0279 sdirectory::MakeDirs(dir,0);
0280
0281 LOG(info) << " DEBUG_RECORD saving to " << dir ;
0282 CSGRecord::Save(dir);
0283 CSGRecord::Dump(dir);
0284 CSGRecord::Clear();
0285 #else
0286 LOG(info) << " DEBUG_RECORD flag not enabled " ;
0287 #endif
0288 LOG(info) << "] single photon selected " ;
0289 }
0290 }
0291
0292 unsigned num_isect = ii.size() ;
0293 LOG(info)
0294 << " pp.size " << pp.size()
0295 << " num_ray " << num_ray
0296 << " ii.size " << num_isect
0297 << ( num_isect == 0 ? " WARNING : NO INTERSECTS " : " " )
0298 ;
0299
0300 if( no_selection )
0301 {
0302 LOG(info) << " saving to outdir " << outdir ;
0303 cegs->save(outdir);
0304 }
0305 else
0306 {
0307 LOG(info) << " NOT saving as an SXYZ or SXYZW selection is in use " ;
0308
0309 }
0310
0311 LOG(info) << "]" ;
0312 }
0313
0314 void CSGGeometry::intersectSelected(const char* path)
0315 {
0316 NP* a = NP::Load(path);
0317 LOG_IF(fatal, a == nullptr) << " FAILED to load from path " << path ;
0318 if( a == nullptr ) return ;
0319
0320 bool expected_shape = a->has_shape(-1,4,4) ;
0321 assert(expected_shape);
0322 if(!expected_shape) std::raise(SIGINT);
0323
0324 LOG(info) << " load SELECTED_ISECT from " << path << " a.sstr " << a->sstr() ;
0325
0326 unsigned num_isect = a->shape[0] ;
0327 std::vector<quad4> isects(num_isect) ;
0328 memcpy( isects.data(), a->bytes(), sizeof(float)*16 );
0329
0330 for(unsigned i=0 ; i < num_isect ; i++)
0331 {
0332 const quad4& prev_isect = isects[i] ;
0333
0334 int4 gsid ;
0335 C4U_decode(gsid, prev_isect.q3.u.w );
0336
0337 quad4 isect ;
0338 bool valid_intersect = q->intersect_again(isect, prev_isect );
0339
0340 std::string gsid_name = C4U_name(gsid, "gsid", '_' );
0341
0342 #ifdef DEBUG_RECORD
0343 const char* dir = spath::Resolve(outdir, "intersectSelected", gsid_name.c_str() );
0344 sdirectory::MakeDirs(dir,0);
0345
0346 CSGRecord::Save(dir);
0347 if(i == 0) CSGRecord::Dump(dir);
0348 CSGRecord::Clear();
0349 #endif
0350
0351 std::cout
0352 << " gsid " << C4U_desc(gsid)
0353 << " gsid_name " << gsid_name
0354 << " valid_intersect " << valid_intersect
0355 << " t:prev_isect.q0.f.w "
0356 << std::setw(10) << std::fixed << std::setprecision(4) << prev_isect.q0.f.w
0357 << " t:isect.q0.f.w "
0358 << std::setw(10) << std::fixed << std::setprecision(4) << isect.q0.f.w
0359 << std::endl
0360 ;
0361 }
0362 }
0363
0364 void CSGGeometry::dump(const char* msg) const
0365 {
0366 LOG_IF(fatal, !fd ) << " fd null : ABORT " ;
0367 if(!fd) return ;
0368
0369 LOG(error) << "fd.dumpSolid" ;
0370 fd->dumpSolid();
0371 LOG(error) << "fd.dumpPrim" ;
0372 fd->dumpPrim();
0373 LOG(error) << "fd.dumpNode" ;
0374 fd->dumpNode();
0375 LOG(error) << "q.dump" ;
0376 q->dump(msg);
0377 }
0378
0379
0380 std::string CSGGeometry::desc()
0381 {
0382 return d ? d->desc() : "ERROR-d-null" ;
0383 }
0384
0385 std::string CSGGeometry::Desc( const CSGFoundry* fd )
0386 {
0387 CSGGeometry cg(nullptr, fd);
0388 return cg.desc();
0389 }
0390