File indexing completed on 2026-04-09 07:49:41
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #include <map>
0043 #include <set>
0044 #include <vector>
0045 #include <sstream>
0046 #include <iomanip>
0047 #include <cassert>
0048 #include <csignal>
0049 #include <cstdint>
0050 #include <functional>
0051 #include <algorithm>
0052
0053 #include "ssys.h"
0054 #include "OpticksCSG.h"
0055 #include "scanvas.h"
0056 #include "s_pa.h"
0057 #include "s_bb.h"
0058 #include "s_tv.h"
0059 #include "s_pool.h"
0060
0061
0062 #include "st.h" // complete binary tree math
0063 #include "stra.h" // glm transform utilities
0064 #include "sgeomtools.h"
0065
0066 #include "NPFold.h"
0067
0068 struct _sn
0069 {
0070 int typecode ;
0071 int complement ;
0072 int lvid ;
0073 int xform ;
0074 int param ;
0075 int aabb ;
0076 int parent ;
0077
0078 #ifdef WITH_CHILD
0079 int sibdex ;
0080 int num_child ;
0081 int first_child ;
0082 int next_sibling ;
0083 int index ;
0084 int depth ;
0085 int note ;
0086 int coincide ;
0087 char label[16] ;
0088 static constexpr const char* ITEM = "19" ;
0089 #else
0090 int left ;
0091 int right ;
0092 int index ;
0093 int depth ;
0094 int note ;
0095 int coincide ;
0096 char label[16] ;
0097 static constexpr const char* ITEM = "17" ;
0098 #endif
0099
0100 std::string desc() const ;
0101 bool is_root() const ;
0102 };
0103
0104 inline std::string _sn::desc() const
0105 {
0106 std::stringstream ss ;
0107 ss << "_sn::desc "
0108 << " typecode " << std::setw(4) << typecode
0109 << " complement " << std::setw(1) << complement
0110 << " lvid " << std::setw(4) << lvid
0111 << " xform " << std::setw(4) << xform
0112 << " param " << std::setw(4) << param
0113 << " aabb " << std::setw(4) << aabb
0114 << " parent " << std::setw(4) << parent
0115 #ifdef WITH_CHILD
0116 << " sx " << std::setw(4) << sibdex
0117 << " nc " << std::setw(4) << num_child
0118 << " fc " << std::setw(4) << first_child
0119 << " ns " << std::setw(4) << next_sibling
0120 #else
0121 << " left " << std::setw(4) << left
0122 << " right " << std::setw(4) << right
0123 #endif
0124 << " is_root " << ( is_root() ? "YES" : "NO " )
0125 ;
0126 std::string str = ss.str();
0127 return str ;
0128 }
0129
0130
0131
0132
0133
0134
0135
0136
0137 inline bool _sn::is_root() const
0138 {
0139 return parent == -1 ;
0140 }
0141
0142 #include "SYSRAP_API_EXPORT.hh"
0143 struct SYSRAP_API sn
0144 {
0145 typedef std::array<double,6> BB ;
0146 typedef std::vector<BB> VBB ;
0147 typedef glm::tmat4x4<double> TR ;
0148 typedef std::vector<TR> VTR ;
0149
0150 static int Check_LEAK(const char* msg, int i=-1);
0151
0152
0153 int typecode ;
0154 int complement ;
0155 int lvid ;
0156 s_tv* xform ;
0157 s_pa* param ;
0158 s_bb* aabb ;
0159 sn* parent ;
0160
0161 #ifdef WITH_CHILD
0162 std::vector<sn*> child ;
0163 #else
0164 sn* left ;
0165 sn* right ;
0166 #endif
0167 int depth ;
0168 int note ;
0169 int coincide ;
0170 char label[16] ;
0171
0172
0173 int pid ;
0174 int subdepth ;
0175
0176
0177 typedef s_pool<sn,_sn> POOL ;
0178 static POOL* pool ;
0179 static constexpr const int VERSION = 0 ;
0180 static constexpr const char* NAME = "sn.npy" ;
0181 static constexpr const double zero = 0. ;
0182 static constexpr const double Z_EPSILON = 1e-3 ;
0183 static constexpr const double UNBOUNDED_DEFAULT_EXTENT = 0. ;
0184
0185 static void SetPOOL( POOL* pool_ );
0186 static int level();
0187 static std::string Desc();
0188 static void PrepareToSerialize();
0189 void prepare_to_serialize();
0190
0191
0192 template<typename N> static std::string Desc(N* n);
0193 template<typename N> static std::string DescXform(N* n);
0194 template<typename N> static std::string DescXformFull(N* n);
0195 template<typename N> static std::string DescPrim(N* n);
0196
0197 template<typename N> static std::string Desc(const std::vector<N*>& nds, bool reverse=false);
0198 template<typename N> static std::string DescXform(const std::vector<N*>& nds, bool reverse=false);
0199 template<typename N> static std::string DescXformFull(const std::vector<N*>& nds, bool reverse=false);
0200 template<typename N> static std::string DescPrim(const std::vector<N*>& nds, bool reverse=false);
0201
0202 template<typename N> static std::string Brief(const std::vector<N*>& nds, bool reverse=false);
0203
0204
0205 static int Index(const sn* n);
0206
0207 int idx() const ;
0208 int index() const ;
0209 int parent_index() const ;
0210
0211 bool is_root() const ;
0212
0213 int num_child() const ;
0214 sn* first_child() const ;
0215 sn* last_child() const ;
0216 sn* get_child(int ch) const ;
0217 sn* get_left() const ;
0218 sn* get_right() const ;
0219
0220 int total_siblings() const ;
0221 int child_index( const sn* ch ) ;
0222 int sibling_index() const ;
0223 const sn* get_sibling(int sx) const ;
0224 const sn* next_sibling() const ;
0225
0226 static void Serialize( _sn& p, const sn* o );
0227 static sn* Import( const _sn* p, const std::vector<_sn>& buf );
0228 static sn* Import_r(const _sn* p, const std::vector<_sn>& buf, int d );
0229
0230 static constexpr const bool LEAK = false ;
0231
0232
0233 sn(int typecode, sn* left, sn* right);
0234 #ifdef WITH_CHILD
0235 void add_child( sn* ch );
0236 #endif
0237
0238 ~sn();
0239
0240
0241 void disown_child(sn* ch) ;
0242 sn* deepcopy() const ;
0243 sn* deepcopy_r(int d) const ;
0244
0245 sn* deepcopy_excluding_leaf(const sn* l) const ;
0246 sn* deepcopy_excluding_leaf_r(int d, const sn* l) const ;
0247
0248
0249 sn* copy() const ;
0250
0251 static void DeepCopy(std::vector<sn*>& p1, const std::vector<sn*>& p0) ;
0252
0253 void set_child( int ix, sn* ch, bool copy );
0254 void set_child_leaking_prior( int ix, sn* ch, bool copy );
0255
0256
0257 void set_left( sn* left, bool copy );
0258 void set_right( sn* right, bool copy );
0259
0260 bool is_primitive() const ;
0261 bool is_complement() const ;
0262 bool is_complement_primitive() const ;
0263 bool is_bileaf() const ;
0264 bool is_operator() const ;
0265 bool is_zero() const ;
0266
0267 bool is_lrzero() const ;
0268 bool is_rzero() const ;
0269 bool is_lzero() const ;
0270
0271 int num_node() const ;
0272 int num_node_r(int d) const ;
0273
0274 int num_notsupported_node() const ;
0275 int num_notsupported_node_r(int d) const ;
0276
0277
0278 int num_leaf() const ;
0279 int num_leaf_r(int d) const ;
0280
0281 int maxdepth() const ;
0282 int maxdepth_r(int d) const ;
0283
0284 void labeltree();
0285
0286 int labeltree_maxdepth() ;
0287 int labeltree_maxdepth_r(int d) ;
0288
0289 void labeltree_subdepth() ;
0290 void labeltree_subdepth_r(int d);
0291
0292 int checktree() const ;
0293 int checktree_r(char code, int d ) const ;
0294
0295 unsigned operators(int minsubdepth) const ;
0296 void operators_v(unsigned& mask, int minsubdepth) const ;
0297 void operators_r(unsigned& mask, int minsubdepth) const ;
0298
0299 void typecodes(std::set<int>& tcs, int minsubdepth=0 ) const ;
0300 void typecodes_r(std::set<int>& tcs, int minsubdepth ) const ;
0301 std::string desc_typecodes() const ;
0302 int typecodes_count(const std::vector<int>& tcq, int minsubdepth=0 ) const ;
0303 std::string desc_typecodes_count() const ;
0304
0305
0306 bool is_positive_form() const ;
0307 bool is_listnode() const ;
0308 std::string tag() const ;
0309
0310 void preorder( std::vector<const sn*>& order ) const ;
0311 void inorder( std::vector<const sn*>& order ) const ;
0312 void postorder(std::vector<const sn*>& order ) const ;
0313
0314 void preorder_r( std::vector<const sn*>& order, int d ) const ;
0315 void inorder_r( std::vector<const sn*>& order, int d ) const ;
0316 void postorder_r(std::vector<const sn*>& order, int d ) const ;
0317
0318 void inorder_(std::vector<sn*>& order ) ;
0319 void inorder_r_(std::vector<sn*>& order, int d );
0320
0321
0322
0323
0324 std::string desc_order(const std::vector<const sn*>& order ) const ;
0325 std::string desc() const ;
0326 std::string desc_xform() const ;
0327 std::string desc_xform_full() const ;
0328 std::string desc_prim() const ;
0329 std::string desc_prim_all(bool reverse) const ;
0330
0331 std::string id() const ;
0332 std::string brief() const ;
0333 std::string desc_child() const ;
0334 std::string desc_this() const ;
0335
0336 std::string desc_r() const ;
0337 void desc_r(int d, std::stringstream& ss) const ;
0338
0339 std::string detail_r() const ;
0340 void detail_r(int d, std::stringstream& ss) const ;
0341 std::string detail() const ;
0342
0343
0344 std::string render() const ;
0345 std::string render_typetag() const ;
0346 std::string render_parent() const ;
0347 std::string rdr() const ;
0348 std::string render(int mode) const ;
0349
0350 enum { MINIMAL, TYPECODE, DEPTH, SUBDEPTH, TYPETAG, PID, NOTE, PARENT, IDX, NUM_MODE=9 } ;
0351
0352 static constexpr const char* MODE_MINIMAL = "MINIMAL" ;
0353 static constexpr const char* MODE_TYPECODE = "TYPECODE" ;
0354 static constexpr const char* MODE_DEPTH = "DEPTH" ;
0355 static constexpr const char* MODE_SUBDEPTH = "SUBDEPTH" ;
0356 static constexpr const char* MODE_TYPETAG = "TYPETAG" ;
0357 static constexpr const char* MODE_PID = "PID" ;
0358 static constexpr const char* MODE_NOTE = "NOTE" ;
0359 static constexpr const char* MODE_PARENT = "PARENT" ;
0360 static constexpr const char* MODE_IDX = "IDX" ;
0361
0362 static const char* rendermode(int mode);
0363
0364 void render_r(scanvas* canvas, std::vector<const sn*>& order, int mode, int d) const ;
0365
0366
0367 static int BinaryTreeHeight(int num_leaves);
0368 static int BinaryTreeHeight_1(int num_leaves);
0369
0370 static sn* ZeroTree_r(int elevation, int op);
0371 static sn* ZeroTree(int num_leaves, int op );
0372
0373 static sn* CommonOperatorTypeTree( std::vector<int>& leaftypes, int op );
0374
0375 void populate_leaftypes(std::vector<int>& leaftypes );
0376 void populate_leaves( std::vector<sn*>& leaves );
0377
0378
0379 void prune();
0380 void prune_r(int d) ;
0381 bool has_dangle() const ;
0382
0383 void positivize() ;
0384 void positivize_r(bool negate, int d) ;
0385 void flip_complement();
0386 void flip_complement_child();
0387
0388
0389
0390 void zero_label();
0391 void set_label( const char* label_ );
0392 void set_lvid(int lvid_);
0393 void set_lvid_r(int lvid_, int d);
0394 int check_idx(const char* msg) const ;
0395 int check_idx_r(int d, const char* msg) const ;
0396
0397
0398 void setPA( double x, double y, double z, double w, double z1, double z2 );
0399 const double* getPA_data() const ;
0400 void copyPA_data(double* dst) const ;
0401
0402 void setBB( double x0, double y0, double z0, double x1, double y1, double z1 );
0403 void setBB( double x0 );
0404
0405 const double* getBB_data() const ;
0406 void copyBB_data(double* dst) const ;
0407
0408 double getBB_xmin() const ;
0409 double getBB_ymin() const ;
0410 double getBB_zmin() const ;
0411
0412 double getBB_xmax() const ;
0413 double getBB_ymax() const ;
0414 double getBB_zmax() const ;
0415
0416 double getBB_xavg() const ;
0417 double getBB_yavg() const ;
0418 double getBB_zavg() const ;
0419
0420 static double AABB_XMin( const sn* n );
0421 static double AABB_YMin( const sn* n );
0422 static double AABB_ZMin( const sn* n );
0423
0424 static double AABB_XMax( const sn* n );
0425 static double AABB_YMax( const sn* n );
0426 static double AABB_ZMax( const sn* n );
0427
0428 static double AABB_XAvg( const sn* n );
0429 static double AABB_YAvg( const sn* n );
0430 static double AABB_ZAvg( const sn* n );
0431
0432
0433
0434
0435 bool hasXF() const ;
0436 void setXF();
0437 void setXF( const glm::tmat4x4<double>& t );
0438 void setXF( const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v ) ;
0439 void combineXF( const glm::tmat4x4<double>& t );
0440 void combineXF( const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v ) ;
0441 std::string descXF() const ;
0442
0443 static sn* Cylinder(double radius, double z1, double z2) ;
0444 static sn* CutCylinder(
0445 double R,
0446 double dz,
0447 double _pz_nrm_x,
0448 double _pz_nrm_y,
0449 double _pz_nrm_z,
0450 double _nz_nrm_x,
0451 double _nz_nrm_y,
0452 double _nz_nrm_z
0453 );
0454
0455 static void CutCylinderZRange(
0456 double& zmin,
0457 double& zmax,
0458 double R,
0459 double dz,
0460 double pz_nrm_x,
0461 double pz_nrm_y,
0462 double pz_nrm_z,
0463 double nz_nrm_x,
0464 double nz_nrm_y,
0465 double nz_nrm_z
0466 );
0467
0468 static sn* Cone(double r1, double z1, double r2, double z2);
0469 static sn* Sphere(double radius);
0470 static sn* ZSphere(double radius, double z1, double z2);
0471 static sn* Box3(double fullside);
0472 static sn* Box3(double fx, double fy, double fz );
0473 static sn* Torus(double rmin, double rmax, double rtor, double startPhi_deg, double deltaPhi_deg );
0474
0475 static constexpr const char* sn__PhiCut_PACMAN_ALLOWED = "sn__PhiCut_PACMAN_ALLOWED" ;
0476 static sn* PhiCut(double phi0, double phi1);
0477 static sn* HalfSpace(double x, double y, double z, double w);
0478 static sn* Notsupported();
0479
0480 static sn* Zero(double x, double y, double z, double w, double z1, double z2);
0481 static sn* Zero();
0482 static sn* Prim(int typecode) ;
0483 static sn* Create(int typecode, sn* left=nullptr, sn* right=nullptr );
0484 static sn* Boolean( int op, sn* l, sn* r );
0485
0486 static void ZNudgeExpandEnds( int lvid, std::vector<sn*>& prims, bool enable);
0487 static void ZNudgeOverlapJoints(int lvid, std::vector<sn*>& prims, bool enable);
0488 static void ZNudgeOverlapJoint(int lvid, int i, sn* lower, sn* upper, bool enable, std::ostream* out );
0489
0490 bool can_znudge() const ;
0491 static bool CanZNudgeAll(std::vector<sn*>& prims);
0492
0493
0494 enum {
0495 NOTE_INCREASE_ZMAX = 0x1 << 0,
0496 NOTE_DECREASE_ZMIN = 0x1 << 1,
0497 HINT_LISTNODE_PRIM_DISCONTIGUOUS = 0x1 << 2,
0498 HINT_LISTNODE_PRIM_CONTIGUOUS = 0x1 << 3
0499 };
0500
0501 static unsigned NameHint(const char* name);
0502 static constexpr const char* _HINT_LISTNODE_PRIM_DISCONTIGUOUS = "HINT_LISTNODE_PRIM_DISCONTIGUOUS" ;
0503 static constexpr const char* _HINT_LISTNODE_PRIM_CONTIGUOUS = "HINT_LISTNODE_PRIM_CONTIGUOUS" ;
0504 void set_hint_note(unsigned hint);
0505 void set_hint_listnode_prim_discontiguous();
0506 void set_hint_listnode_prim_contiguous();
0507 bool is_hint_listnode_prim_discontiguous() const ;
0508 bool is_hint_listnode_prim_contiguous() const ;
0509
0510 void increase_zmax( double dz );
0511 void decrease_zmin( double dz );
0512
0513 void increase_zmax_( double dz );
0514 void decrease_zmin_( double dz );
0515
0516 void increase_zmax_cone( double dz );
0517 void decrease_zmin_cone( double dz );
0518
0519
0520
0521
0522 double zmin() const ;
0523 double zmax() const ;
0524 void set_zmin(double zmin_) ;
0525 void set_zmax(double zmax_) ;
0526
0527 double rperp_at_zmax() const ;
0528 void set_rperp_at_zmax(double rperp_) const ;
0529
0530 double rperp_at_zmin() const ;
0531 void set_rperp_at_zmin(double rperp_) const ;
0532
0533
0534 static double Sphere_RPerp_At_Z(double r, double z);
0535 double rperp_at_zmin_zsphere() const ;
0536 double rperp_at_zmax_zsphere() const ;
0537
0538
0539
0540
0541 static std::string ZDesc(const std::vector<sn*>& prims);
0542
0543 void getParam_(double& p0, double& p1, double& p2, double& p3, double& p4, double& p5 ) const ;
0544 const double* getParam() const ;
0545 const double* getAABB() const ;
0546 bool hasAABB() const ;
0547
0548
0549 static sn* Collection( std::vector<sn*>& prims );
0550 static sn* UnionTree( std::vector<sn*>& prims );
0551 static sn* Contiguous( std::vector<sn*>& prims );
0552 static sn* Discontiguous( std::vector<sn*>& prims );
0553 static sn* Compound( std::vector<sn*>& prims, int typecode_ );
0554
0555 static sn* Buggy_CommonOperatorTree( std::vector<sn*>& leaves , int op );
0556 static sn* BuildCommonTypeTree_Unbalanced( const std::vector<sn*>& leaves, int typecode );
0557
0558 static void GetLVListnodes( std::vector<const sn*>& lns, int lvid );
0559 static int GetChildTotal( const std::vector<const sn*>& nds );
0560
0561 static void GetLVNodes( std::vector<sn*>& nds, int lvid );
0562 static void GetLVNodes_( std::vector<const sn*>& nds, int lvid );
0563 void getLVNodes( std::vector<sn*>& nds ) const ;
0564 static bool Includes(const std::vector<sn*>& nds, sn* nd );
0565
0566 static sn* Get(int idx);
0567 static void FindLVRootNodes( std::vector<sn*>& nds, int lvid );
0568 static sn* GetLVRoot( int lvid );
0569
0570 std::string rbrief() const ;
0571 void rbrief_r(std::ostream& os, int d) const ;
0572
0573 bool has_type(const std::vector<OpticksCSG_t>& types) const ;
0574 template<typename ... Args>
0575 void typenodes_(std::vector<const sn*>& nds, Args ... tcs ) const ;
0576 void typenodes_r_(std::vector<const sn*>& nds, const std::vector<OpticksCSG_t>& types, int d) const ;
0577
0578 int max_binary_depth() const ;
0579 int max_binary_depth_r(int d) const ;
0580
0581 uint64_t getLVBinNode() const ;
0582 uint64_t getLVSubNode() const ;
0583 uint64_t getLVNumNode() const ;
0584
0585 static void GetLVNodesComplete(std::vector<const sn*>& nds, int lvid);
0586 void getLVNodesComplete(std::vector<const sn*>& nds) const ;
0587 static void GetLVNodesComplete_r(std::vector<const sn*>& nds, const sn* nd, int idx);
0588
0589 static void SelectListNode(std::vector<const sn*>& lns, const std::vector<const sn*>& nds);
0590
0591 void ancestors(std::vector<const sn*>& nds) const ;
0592
0593 void connectedtype_ancestors(std::vector<const sn*>& nds ) const ;
0594 static void ConnectedTypeAncestors(const sn* n, std::vector<const sn*>& nds, int q_typecode);
0595
0596 void collect_progeny( std::vector<const sn*>& progeny, int exclude_typecode ) const ;
0597 static void CollectProgeny_r( const sn* n, std::vector<const sn*>& progeny, int exclude_typecode );
0598
0599 void collect_prim( std::vector<const sn*>& prim ) const ;
0600 void collect_prim_r( std::vector<const sn*>& prim, int d ) const ;
0601
0602 bool has_note(int q_note) const ;
0603 void collect_prim_note( std::vector<sn*>& prim, int q_note );
0604 void collect_prim_note_r( std::vector<sn*>& prim, int q_note, int d );
0605
0606 sn* find_joint_to_candidate_listnode( std::vector<sn*>& prim, int q_note ) ;
0607 sn* find_joint_to_candidate_listnode_r( int d, std::vector<sn*>& prim, int q_note );
0608 bool has_candidate_listnode(int q_note);
0609 bool has_candidate_listnode_discontiguous() ;
0610 bool has_candidate_listnode_contiguous() ;
0611
0612 static sn* CreateSmallerTreeWithListNode(sn* root0, int q_note);
0613 static sn* CreateSmallerTreeWithListNode_discontiguous(sn* root0);
0614 static sn* CreateSmallerTreeWithListNode_contiguous( sn* root0);
0615 static int TypeFromNote(int q_note);
0616
0617 void collect_monogroup( std::vector<const sn*>& monogroup ) const ;
0618
0619 static bool AreFromSameMonogroup(const sn* a, const sn* b, int op);
0620 static bool AreFromSameUnion(const sn* a, const sn* b);
0621
0622
0623
0624
0625 static void NodeTransformProduct(
0626 int idx,
0627 glm::tmat4x4<double>& t,
0628 glm::tmat4x4<double>& v,
0629 bool reverse,
0630 std::ostream* out,
0631 VTR* t_stack );
0632
0633 static std::string DescNodeTransformProduct(
0634 int idx,
0635 glm::tmat4x4<double>& t,
0636 glm::tmat4x4<double>& v,
0637 bool reverse );
0638
0639 void getNodeTransformProduct(
0640 glm::tmat4x4<double>& t,
0641 glm::tmat4x4<double>& v,
0642 bool reverse,
0643 std::ostream* out,
0644 VTR* t_stack ) const ;
0645
0646 std::string desc_getNodeTransformProduct(
0647 glm::tmat4x4<double>& t,
0648 glm::tmat4x4<double>& v,
0649 bool reverse) const ;
0650
0651 double radius_sphere() const ;
0652
0653 void setAABB_LeafFrame() ;
0654 void setAABB_LeafFrame_All() ;
0655
0656 void setAABB_TreeFrame_All() ;
0657
0658
0659
0660 void postconvert(int lvid);
0661
0662 template<typename N>
0663 static void OrderPrim( std::vector<N*>& prim, std::function<double(N* p)> fn, bool ascending );
0664
0665
0666
0667
0668 static void Transform_Leaf2Tree( glm::tvec3<double>& xyz, const sn* leaf, std::ostream* out );
0669
0670 void uncoincide() ;
0671 void uncoincide_( bool enable, std::ostream* out);
0672 void uncoincide_zminmax( int i, sn* lower, sn* upper, bool enable, std::ostream* out ) ;
0673
0674
0675 };
0676
0677
0678
0679 inline int sn::Check_LEAK(const char* msg, int i)
0680 {
0681
0682 const char* spacer = "" ;
0683
0684 std::stringstream ss ;
0685 ss << "sn::Check_LEAK[" << std::setw(3) << i << "] " << std::setw(30) << ( msg ? msg : "-" ) << " " << sn::pool->brief() << spacer << std::endl ;
0686 std::string str = ss.str();
0687 std::cout << str ;
0688
0689 if(!sn::LEAK)
0690 {
0691 assert( sn::pool->size() == 0 );
0692 }
0693
0694 if(!s_tv::LEAK)
0695 {
0696 assert( s_tv::pool->size() == 0 );
0697 }
0698
0699 if(!s_pa::LEAK)
0700 {
0701 assert( s_pa::pool->size() == 0 );
0702 }
0703
0704 if(!s_bb::LEAK)
0705 {
0706 assert( s_bb::pool->size() == 0 );
0707 }
0708
0709 return 0 ;
0710 }
0711
0712
0713
0714
0715
0716
0717
0718
0719 inline void sn::SetPOOL( POOL* pool_ ){ pool = pool_ ; }
0720 inline int sn::level() { return ssys::getenvint("sn__level",-1) ; }
0721
0722
0723 inline void sn::PrepareToSerialize()
0724 {
0725 pool->prepare_to_serialize();
0726 }
0727
0728 inline void sn::prepare_to_serialize()
0729 {
0730 if(!hasXF()) setXF();
0731 }
0732
0733
0734 inline std::string sn::Desc(){ return pool ? pool->desc() : "-" ; }
0735
0736
0737
0738
0739
0740 template<typename N>
0741 inline std::string sn::Desc(N* n)
0742 {
0743 return n ? n->desc() : "(null)" ;
0744 }
0745
0746 template<typename N>
0747 inline std::string sn::DescXform(N* n)
0748 {
0749 return n ? n->desc_xform() : "(null)" ;
0750 }
0751
0752 template<typename N>
0753 inline std::string sn::DescXformFull(N* n)
0754 {
0755 return n ? n->desc_xform_full() : "(null)" ;
0756 }
0757
0758 template<typename N>
0759 inline std::string sn::DescPrim(N* n)
0760 {
0761 return n ? n->desc_prim() : "(null)" ;
0762 }
0763
0764
0765 template<typename N>
0766 inline std::string sn::Desc(const std::vector<N*>& nds, bool reverse)
0767 {
0768 int num_nd = nds.size() ;
0769 std::stringstream ss ;
0770 ss << "sn::Desc num_nd " << num_nd << ( reverse ? " DESC ORDER REVERSED " : "-" ) << std::endl ;
0771 for(int i=0 ; i < num_nd ; i++) ss << Desc(nds[reverse ? num_nd - 1 - i : i]) << std::endl ;
0772 std::string str = ss.str();
0773 return str ;
0774 }
0775
0776 template<typename N>
0777 inline std::string sn::DescXform(const std::vector<N*>& nds, bool reverse)
0778 {
0779 int num_nd = nds.size() ;
0780 std::stringstream ss ;
0781 ss << "sn::DescXform num_nd " << num_nd << ( reverse ? " DESC ORDER REVERSED " : "-" ) << std::endl ;
0782 for(int i=0 ; i < num_nd ; i++) ss << DescXform(nds[reverse ? num_nd - 1 - i : i]) << std::endl ;
0783 std::string str = ss.str();
0784 return str ;
0785 }
0786
0787 template<typename N>
0788 inline std::string sn::DescXformFull(const std::vector<N*>& nds, bool reverse)
0789 {
0790 int num_nd = nds.size() ;
0791 std::stringstream ss ;
0792 ss << "sn::DescXformFull num_nd " << num_nd << ( reverse ? " DESC ORDER REVERSED " : "-" ) << std::endl ;
0793 for(int i=0 ; i < num_nd ; i++) ss << DescXformFull(nds[reverse ? num_nd - 1 - i : i]) << std::endl ;
0794 std::string str = ss.str();
0795 return str ;
0796 }
0797
0798
0799 template<typename N>
0800 inline std::string sn::DescPrim(const std::vector<N*>& nds, bool reverse)
0801 {
0802 int num_nd = nds.size() ;
0803 std::stringstream ss ;
0804 ss << "sn::DescPrim num_nd " << num_nd << ( reverse ? " DESC ORDER REVERSED " : "-" ) << std::endl ;
0805 for(int i=0 ; i < num_nd ; i++) ss << DescPrim(nds[reverse ? num_nd - 1 - i : i]) << std::endl ;
0806 std::string str = ss.str();
0807 return str ;
0808 }
0809
0810
0811 template<typename N>
0812 inline std::string sn::Brief(const std::vector<N*>& nds, bool reverse)
0813 {
0814 int num_nd = nds.size() ;
0815 std::stringstream ss ;
0816 ss << "sn::Brief num_nd " << num_nd << ( reverse ? " DESC ORDER REVERSED " : "-" ) << std::endl ;
0817 for(int i=0 ; i < num_nd ; i++) ss << Desc(nds[reverse ? num_nd - 1 - i : i]) << std::endl ;
0818 std::string str = ss.str();
0819 return str ;
0820 }
0821
0822
0823
0824 inline int sn::Index(const sn* n){ return pool ? pool->index(n) : -1 ; }
0825 inline int sn::idx() const { return Index(this); }
0826 inline int sn::index() const { return Index(this); }
0827 inline int sn::parent_index() const { return parent ? Index(parent) : -2 ; }
0828 inline bool sn::is_root() const { return parent == nullptr ; }
0829
0830
0831
0832 inline int sn::num_child() const
0833 {
0834 #ifdef WITH_CHILD
0835 return int(child.size());
0836 #else
0837 return left && right ? 2 : 0 ;
0838 #endif
0839 }
0840
0841 inline sn* sn::first_child() const
0842 {
0843 #ifdef WITH_CHILD
0844 return child.size() > 0 ? child[0] : nullptr ;
0845 #else
0846 return left ;
0847 #endif
0848 }
0849 inline sn* sn::last_child() const
0850 {
0851 #ifdef WITH_CHILD
0852 return child.size() > 0 ? child[child.size()-1] : nullptr ;
0853 #else
0854 return right ;
0855 #endif
0856 }
0857 inline sn* sn::get_child(int ch) const
0858 {
0859 #ifdef WITH_CHILD
0860 return ch > -1 && ch < int(child.size()) ? child[ch] : nullptr ;
0861 #else
0862 switch(ch)
0863 {
0864 case 0: return left ; break ;
0865 case 1: return right ; break ;
0866 }
0867 return nullptr ;
0868 #endif
0869 }
0870
0871
0872 inline sn* sn::get_left() const
0873 {
0874 sn* l = nullptr ;
0875 #ifdef WITH_CHILD
0876 assert( child.size() == 2 );
0877 l = child[0] ;
0878 #else
0879 l = left ;
0880 #endif
0881 return l ;
0882 }
0883
0884 inline sn* sn::get_right() const
0885 {
0886 sn* r = nullptr ;
0887 #ifdef WITH_CHILD
0888 assert( child.size() == 2 );
0889 r = child[1] ;
0890 #else
0891 r = right ;
0892 #endif
0893 return r ;
0894 }
0895
0896
0897
0898
0899
0900
0901 inline int sn::total_siblings() const
0902 {
0903 #ifdef WITH_CHILD
0904 return parent ? int(parent->child.size()) : 1 ;
0905 #else
0906 if(parent == nullptr) return 1 ;
0907 return ( parent->left && parent->right ) ? 2 : -1 ;
0908 #endif
0909 }
0910
0911 inline int sn::child_index( const sn* ch )
0912 {
0913 #ifdef WITH_CHILD
0914 size_t idx = std::distance( child.begin(), std::find( child.begin(), child.end(), ch )) ;
0915 return idx < child.size() ? idx : -1 ;
0916 #else
0917 int idx = -1 ;
0918 if( ch == left ) idx = 0 ;
0919 else if( ch == right ) idx = 1 ;
0920 return idx ;
0921 #endif
0922 }
0923
0924 inline int sn::sibling_index() const
0925 {
0926 int tot_sib = total_siblings() ;
0927 int sibdex = parent == nullptr ? 0 : parent->child_index(this) ;
0928
0929 if(level() > 1) std::cout << "sn::sibling_index"
0930 << " tot_sib " << tot_sib
0931 << " sibdex " << sibdex
0932 << std::endl
0933 ;
0934
0935 assert( sibdex < tot_sib );
0936 return sibdex ;
0937 }
0938
0939 inline const sn* sn::get_sibling(int sx) const
0940 {
0941 #ifdef WITH_CHILD
0942 assert( sx < total_siblings() );
0943 return parent ? parent->child[sx] : this ;
0944 #else
0945 const sn* sib = nullptr ;
0946 switch(sx)
0947 {
0948 case 0: sib = parent ? parent->left : nullptr ; break ;
0949 case 1: sib = parent ? parent->right : nullptr ; break ;
0950 }
0951 return sib ;
0952 #endif
0953 }
0954
0955 inline const sn* sn::next_sibling() const
0956 {
0957 int next_sib = 1+sibling_index() ;
0958 int tot_sib = total_siblings() ;
0959
0960 if(level() > 1) std::cout << "sn::next_sibling"
0961 << " tot_sib " << tot_sib
0962 << " next_sib " << next_sib
0963 << std::endl
0964 ;
0965
0966 return next_sib < tot_sib ? get_sibling(next_sib) : nullptr ;
0967 }
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985 inline void sn::Serialize(_sn& n, const sn* x)
0986 {
0987 if(level() > 1) std::cout
0988 << "sn::Serialize ["
0989 << std::endl
0990 ;
0991
0992 assert( pool && "sn::pool is required for sn::Serialize" );
0993 assert( s_tv::pool && "s_tv::pool is required for sn::Serialize" );
0994 assert( s_pa::pool && "s_pa::pool is required for sn::Serialize" );
0995 assert( s_bb::pool && "s_bb::pool is required for sn::Serialize" );
0996
0997 n.typecode = x->typecode ;
0998 n.complement = x->complement ;
0999 n.lvid = x->lvid ;
1000
1001 n.xform = s_tv::pool->index(x->xform) ;
1002 n.param = s_pa::pool->index(x->param) ;
1003 n.aabb = s_bb::pool->index(x->aabb) ;
1004 n.parent = pool->index(x->parent);
1005
1006 #ifdef WITH_CHILD
1007 n.sibdex = x->sibling_index();
1008 n.num_child = x->num_child() ;
1009 n.first_child = pool->index(x->first_child());
1010 n.next_sibling = pool->index(x->next_sibling());
1011 #else
1012 n.left = pool->index(x->left);
1013 n.right = pool->index(x->right);
1014 #endif
1015
1016 n.index = pool->index(x) ;
1017 n.depth = x->depth ;
1018 n.note = x->note ;
1019 n.coincide = x->coincide ;
1020
1021 assert( sizeof(n.label) == sizeof(x->label) );
1022 strncpy( &n.label[0], x->label, sizeof(n.label) );
1023
1024
1025 if(level() > 1) std::cout
1026 << "sn::Serialize ]"
1027 << std::endl
1028 << "(sn)x"
1029 << std::endl
1030 << x->desc()
1031 << std::endl
1032 << "(_sn)n"
1033 << std::endl
1034 << n.desc()
1035 << std::endl
1036 ;
1037
1038
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 inline sn* sn::Import( const _sn* p, const std::vector<_sn>& buf )
1053 {
1054 if(level() > 0) std::cout << "sn::Import" << std::endl ;
1055 return p->is_root() ? Import_r(p, buf, 0) : nullptr ;
1056 }
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 inline sn* sn::Import_r(const _sn* _n, const std::vector<_sn>& buf, int d)
1068 {
1069 assert( s_tv::pool && "s_tv::pool is required for sn::Import_r " );
1070 if(level() > 0) std::cout << "sn::Import_r d " << d << " " << ( _n ? _n->desc() : "(null)" ) << std::endl ;
1071 if(_n == nullptr) return nullptr ;
1072
1073 #ifdef WITH_CHILD
1074 sn* n = Create( _n->typecode , nullptr, nullptr );
1075 n->complement = _n->complement ;
1076 n->lvid = _n->lvid ;
1077 n->xform = s_tv::pool->getbyidx(_n->xform) ;
1078 n->param = s_pa::pool->getbyidx(_n->param) ;
1079 n->aabb = s_bb::pool->getbyidx(_n->aabb) ;
1080
1081 const _sn* _child = _n->first_child > -1 ? &buf[_n->first_child] : nullptr ;
1082
1083 while( _child )
1084 {
1085 sn* ch = Import_r( _child, buf, d+1 );
1086 n->add_child(ch);
1087 _child = _child->next_sibling > -1 ? &buf[_child->next_sibling] : nullptr ;
1088 }
1089 #else
1090 const _sn* _l = _n->left > -1 ? &buf[_n->left] : nullptr ;
1091 const _sn* _r = _n->right > -1 ? &buf[_n->right] : nullptr ;
1092 sn* l = Import_r( _l, buf, d+1 );
1093 sn* r = Import_r( _r, buf, d+1 );
1094 sn* n = Create( _n->typecode, l, r );
1095 n->complement = _n->complement ;
1096 n->lvid = _n->lvid ;
1097 n->xform = s_tv::pool->getbyidx(_n->xform) ;
1098 n->param = s_pa::pool->getbyidx(_n->param) ;
1099 n->aabb = s_bb::pool->getbyidx(_n->aabb) ;
1100 #endif
1101 return n ;
1102 }
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115 inline sn::sn(int typecode_, sn* left_, sn* right_)
1116 :
1117 typecode(typecode_),
1118 complement(0),
1119 lvid(-1),
1120 xform(nullptr),
1121 param(nullptr),
1122 aabb(nullptr),
1123 parent(nullptr),
1124 #ifdef WITH_CHILD
1125 #else
1126 left(left_),
1127 right(right_),
1128 #endif
1129 depth(0),
1130 note(0),
1131 coincide(0),
1132 pid(pool ? pool->add(this) : -1),
1133 subdepth(0)
1134 {
1135 if(level() > 1) std::cout << "[ sn::sn " << id() << "\n" ;
1136 zero_label();
1137
1138 #ifdef WITH_CHILD
1139 if(left_ && right_)
1140 {
1141 add_child(left_);
1142 add_child(right_);
1143 }
1144 #else
1145 if(left && right)
1146 {
1147 left->parent = this ;
1148 right->parent = this ;
1149 }
1150 #endif
1151
1152 if(level() > 1) std::cout << "] sn::sn " << id() << "\n" ;
1153 }
1154
1155 #ifdef WITH_CHILD
1156 inline void sn::add_child( sn* ch )
1157 {
1158 assert(ch);
1159 ch->parent = this ;
1160 child.push_back(ch) ;
1161 }
1162 #endif
1163
1164
1165
1166
1167
1168
1169 inline sn::~sn()
1170 {
1171 if(level() > 1) std::cout << "[ sn::~sn " << id() << "\n" ;
1172
1173 delete xform ;
1174 delete param ;
1175 delete aabb ;
1176
1177
1178
1179 #ifdef WITH_CHILD
1180 for(int i=0 ; i < int(child.size()) ; i++)
1181 {
1182 sn* ch = child[i] ;
1183 delete ch ;
1184 }
1185 #else
1186 delete left ;
1187 delete right ;
1188 #endif
1189
1190 if(pool) pool->remove(this);
1191
1192 if(level() > 1) std::cout << "] sn::~sn " << id() << "\n" ;
1193 }
1194
1195
1196
1197
1198
1199
1200
1201 #ifdef WITH_CHILD
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220 inline void sn::disown_child(sn* ch)
1221 {
1222 typedef std::vector<sn*>::iterator IT ;
1223 IT it = std::find(child.begin(), child.end(), ch );
1224 if(it != child.end() ) child.erase(it) ;
1225 }
1226 #endif
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241 inline sn* sn::deepcopy() const
1242 {
1243 return deepcopy_r(0);
1244 }
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258 inline sn* sn::deepcopy_r(int d) const
1259 {
1260 sn* n = copy();
1261
1262 #ifdef WITH_CHILD
1263 for(int i=0 ; i < int(child.size()) ; i++)
1264 {
1265 sn* ch = child[i] ;
1266 n->disown_child( ch ) ;
1267 sn* deep_ch = ch->deepcopy_r(d+1) ;
1268 n->child.push_back( deep_ch );
1269 }
1270 #else
1271
1272
1273 assert( n->left == left );
1274 assert( n->right == right );
1275
1276 n->left = left ? left->deepcopy_r(d+1) : nullptr ;
1277 n->right = right ? right->deepcopy_r(d+1) : nullptr ;
1278 #endif
1279
1280 return n ;
1281 }
1282
1283
1284
1285 inline sn* sn::deepcopy_excluding_leaf(const sn* l) const
1286 {
1287 return deepcopy_excluding_leaf_r(0, l );
1288 }
1289
1290 inline sn* sn::deepcopy_excluding_leaf_r(int d, const sn* l) const
1291 {
1292 if(this == l) return nullptr ;
1293
1294 sn* n = copy();
1295
1296 #ifdef WITH_CHILD
1297 for(int i=0 ; i < int(child.size()) ; i++)
1298 {
1299 sn* ch = child[i] ;
1300 n->disown_child( ch ) ;
1301 sn* deep_ch = ch->deepcopy_excluding_leaf_r(d+1, l ) ;
1302 n->child.push_back( deep_ch );
1303 }
1304 #else
1305
1306
1307 assert( n->left == left );
1308 assert( n->right == right );
1309
1310 n->left = left ? left->deepcopy_excluding_leaf_r(d+1) : nullptr ;
1311 n->right = right ? right->deepcopy_excluding_leaf_r(d+1) : nullptr ;
1312 #endif
1313 return n ;
1314 }
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335 inline sn* sn::copy() const
1336 {
1337 sn* n = new sn(*this) ;
1338
1339 n->pid = pool ? pool->add(n) : -1 ;
1340 n->parent = nullptr ;
1341 n->xform = xform ? xform->copy() : nullptr ;
1342 n->param = param ? param->copy() : nullptr ;
1343 n->aabb = aabb ? aabb->copy() : nullptr ;
1344
1345 return n ;
1346 }
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 inline void sn::DeepCopy(std::vector<sn*>& p1, const std::vector<sn*>& p0)
1358 {
1359 for(unsigned i=0 ; i < p0.size() ; i++) p1.push_back(p0[i]->deepcopy());
1360 }
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390 inline void sn::set_child( int ix, sn* ch, bool copy )
1391 {
1392 sn* new_ch = copy ? ch->deepcopy() : ch ;
1393 new_ch->parent = this ;
1394
1395 #ifdef WITH_CHILD
1396 assert( ix < int(child.size()) );
1397 sn*& target = child[ix] ;
1398 if(!LEAK) delete target ;
1399 target = new_ch ;
1400 #else
1401 sn** target = ix == 0 ? &left : &right ;
1402 if(!LEAK) delete *target ;
1403 *target = new_ch ;
1404 #endif
1405
1406 }
1407
1408
1409 inline void sn::set_child_leaking_prior( int ix, sn* ch, bool copy )
1410 {
1411 sn* new_ch = copy ? ch->deepcopy() : ch ;
1412 new_ch->parent = this ;
1413
1414 #ifdef WITH_CHILD
1415 assert( ix < int(child.size()) );
1416 sn*& target = child[ix] ;
1417 target = new_ch ;
1418 #else
1419 sn** target = ix == 0 ? &left : &right ;
1420 *target = new_ch ;
1421 #endif
1422
1423 }
1424
1425
1426
1427
1428 inline void sn::set_left( sn* ch, bool copy )
1429 {
1430 set_child(0, ch, copy );
1431 }
1432 inline void sn::set_right( sn* ch, bool copy )
1433 {
1434 set_child(1, ch, copy );
1435 }
1436
1437
1438
1439
1440
1441
1442
1443
1444 inline bool sn::is_primitive() const
1445 {
1446 #ifdef WITH_CHILD
1447 return child.size() == 0 ;
1448 #else
1449 return left == nullptr && right == nullptr ;
1450 #endif
1451
1452 }
1453
1454 inline bool sn::is_complement() const { return complement == 1 ; }
1455 inline bool sn::is_complement_primitive() const { return is_complement() && is_primitive() ; }
1456
1457
1458 inline bool sn::is_bileaf() const
1459 {
1460 #ifdef WITH_CHILD
1461 int num_ch = int(child.size()) ;
1462 int num_prim = 0 ;
1463 for(int i=0 ; i < num_ch ; i++) if(child[i]->is_primitive()) num_prim += 1 ;
1464 bool all_prim = num_prim == num_ch ;
1465 return !is_primitive() && all_prim ;
1466 #else
1467 return !is_primitive() && left->is_primitive() && right->is_primitive() ;
1468 #endif
1469 }
1470 inline bool sn::is_operator() const
1471 {
1472 #ifdef WITH_CHILD
1473 return child.size() == 2 ;
1474 #else
1475 return left != nullptr && right != nullptr ;
1476 #endif
1477 }
1478 inline bool sn::is_zero() const
1479 {
1480 return typecode == 0 ;
1481 }
1482 inline bool sn::is_lrzero() const
1483 {
1484 #ifdef WITH_CHILD
1485 int num_ch = int(child.size()) ;
1486 int num_zero = 0 ;
1487 for(int i=0 ; i < num_ch ; i++) if(child[i]->is_zero()) num_zero += 1 ;
1488 bool all_zero = num_zero == num_ch ;
1489 return is_operator() && all_zero ;
1490 #else
1491 return is_operator() && left->is_zero() && right->is_zero() ;
1492 #endif
1493 }
1494 inline bool sn::is_rzero() const
1495 {
1496 #ifdef WITH_CHILD
1497 return is_operator() && !child[0]->is_zero() && child[1]->is_zero() ;
1498 #else
1499 return is_operator() && !left->is_zero() && right->is_zero() ;
1500 #endif
1501 }
1502 inline bool sn::is_lzero() const
1503 {
1504 #ifdef WITH_CHILD
1505 return is_operator() && child[0]->is_zero() && !child[1]->is_zero() ;
1506 #else
1507 return is_operator() && left->is_zero() && !right->is_zero() ;
1508 #endif
1509 }
1510
1511
1512
1513
1514
1515
1516
1517 inline int sn::num_node() const
1518 {
1519 return num_node_r(0);
1520 }
1521 inline int sn::num_node_r(int d) const
1522 {
1523 int nn = 1 ;
1524 #ifdef WITH_CHILD
1525 for(int i=0 ; i < int(child.size()) ; i++) nn += child[i]->num_node_r(d+1) ;
1526 #else
1527 nn += left ? left->num_node_r(d+1) : 0 ;
1528 nn += right ? right->num_node_r(d+1) : 0 ;
1529 #endif
1530 return nn ;
1531 }
1532
1533
1534 inline int sn::num_notsupported_node() const
1535 {
1536 return num_notsupported_node_r(0);
1537 }
1538
1539 inline int sn::num_notsupported_node_r(int d) const
1540 {
1541 int nn = typecode == CSG_NOTSUPPORTED ? 1 : 0 ;
1542 #ifdef WITH_CHILD
1543 for(int i=0 ; i < int(child.size()) ; i++) nn += child[i]->num_notsupported_node_r(d+1) ;
1544 #else
1545 nn += left ? left->num_notsupported_node_r(d+1) : 0 ;
1546 nn += right ? right->num_notsupported_node_r(d+1) : 0 ;
1547 #endif
1548 return nn ;
1549 }
1550
1551
1552
1553
1554 inline int sn::num_leaf() const
1555 {
1556 return num_leaf_r(0);
1557 }
1558 inline int sn::num_leaf_r(int d) const
1559 {
1560 int nl = is_primitive() ? 1 : 0 ;
1561 #ifdef WITH_CHILD
1562 for(int i=0 ; i < int(child.size()) ; i++) nl += child[i]->num_leaf_r(d+1) ;
1563 #else
1564 nl += left ? left->num_leaf_r(d+1) : 0 ;
1565 nl += right ? right->num_leaf_r(d+1) : 0 ;
1566 #endif
1567 return nl ;
1568 }
1569
1570
1571 inline int sn::maxdepth() const
1572 {
1573 return maxdepth_r(0);
1574 }
1575 inline int sn::maxdepth_r(int d) const
1576 {
1577 #ifdef WITH_CHILD
1578 if( child.size() == 0 ) return d ;
1579 int mx = 0 ;
1580 for(int i=0 ; i < int(child.size()) ; i++) mx = std::max( mx, child[i]->maxdepth_r(d+1) ) ;
1581 return mx ;
1582 #else
1583 return left && right ? std::max( left->maxdepth_r(d+1), right->maxdepth_r(d+1)) : d ;
1584 #endif
1585 }
1586
1587
1588
1589 inline void sn::labeltree()
1590 {
1591 labeltree_maxdepth();
1592 labeltree_subdepth();
1593 }
1594
1595 inline int sn::labeltree_maxdepth()
1596 {
1597 return labeltree_maxdepth_r(0);
1598 }
1599 inline int sn::labeltree_maxdepth_r(int d)
1600 {
1601 depth = d ;
1602
1603 int nc = num_child();
1604 if(nc == 0) return d ;
1605
1606 int mx = 0 ;
1607 for(int i=0 ; i < nc ; i++)
1608 {
1609 sn* ch = get_child(i) ;
1610 mx = std::max(mx, ch->labeltree_maxdepth_r(d+1) ) ;
1611 }
1612 return mx ;
1613 }
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641 inline void sn::labeltree_subdepth()
1642 {
1643 labeltree_subdepth_r(0);
1644 }
1645 inline void sn::labeltree_subdepth_r(int d)
1646 {
1647 subdepth = maxdepth() ;
1648 for(int i=0 ; i < num_child() ; i++)
1649 {
1650 sn* ch = get_child(i) ;
1651 ch->labeltree_subdepth_r(d+1) ;
1652 }
1653 }
1654
1655
1656 inline int sn::checktree() const
1657 {
1658 int chk_D = checktree_r('D', 0);
1659 int chk_P = checktree_r('P', 0);
1660 int chk = chk_D + chk_P ;
1661
1662 if( chk > 0 )
1663 {
1664 if(level()>0) std::cout
1665 << "sn::checktree"
1666 << " chk_D " << chk_D
1667 << " chk_P " << chk_P
1668 << desc()
1669 << std::endl
1670 ;
1671 }
1672 return chk ;
1673 }
1674
1675
1676 inline int sn::checktree_r(char code, int d ) const
1677 {
1678 int chk = 0 ;
1679
1680 if( code == 'D' )
1681 {
1682 if(d != depth) chk += 1 ;
1683 }
1684 else if( code == 'P' )
1685 {
1686 if( depth > 0 && parent == nullptr ) chk += 1 ;
1687 }
1688
1689 for(int i=0 ; i < num_child() ; i++)
1690 {
1691 sn* ch = get_child(i) ;
1692 ch->checktree_r(code, d+1) ;
1693 }
1694
1695 return chk ;
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717 inline unsigned sn::operators(int minsubdepth) const
1718 {
1719 unsigned mask = 0 ;
1720 operators_r(mask, minsubdepth);
1721 return mask ;
1722 }
1723
1724
1725 inline void sn::operators_v(unsigned& mask, int minsubdepth) const
1726 {
1727 if( subdepth >= minsubdepth )
1728 {
1729 switch( typecode )
1730 {
1731 case CSG_UNION : mask |= CSG::Mask(CSG_UNION) ; break ;
1732 case CSG_INTERSECTION : mask |= CSG::Mask(CSG_INTERSECTION) ; break ;
1733 case CSG_DIFFERENCE : mask |= CSG::Mask(CSG_DIFFERENCE) ; break ;
1734 default : mask |= 0 ; break ;
1735 }
1736 }
1737 }
1738
1739
1740 inline void sn::operators_r(unsigned& mask, int minsubdepth) const
1741 {
1742 #ifdef WITH_CHILD
1743 if(child.size() >= 2) operators_v(mask, minsubdepth) ;
1744 for(int i=0 ; i < int(child.size()) ; i++) child[i]->operators_r(mask, minsubdepth ) ;
1745 #else
1746 if(left && right )
1747 {
1748 operators_v(mask, minsubdepth );
1749 left->operators_r( mask, minsubdepth );
1750 right->operators_r( mask, minsubdepth );
1751 }
1752 #endif
1753
1754 }
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767 inline void sn::typecodes(std::set<int>& tcs, int minsubdepth ) const
1768 {
1769 typecodes_r(tcs, minsubdepth);
1770 }
1771
1772 inline void sn::typecodes_r(std::set<int>& tcs, int minsubdepth ) const
1773 {
1774 if(subdepth >= minsubdepth) tcs.insert(typecode);
1775 #ifdef WITH_CHILD
1776 for(int i=0 ; i < int(child.size()) ; i++) child[i]->typecodes_r(tcs, minsubdepth ) ;
1777 #else
1778 if(left && right )
1779 {
1780 left->typecodes_r( tcs, minsubdepth );
1781 right->typecodes_r( tcs, minsubdepth );
1782 }
1783 #endif
1784 }
1785
1786
1787 inline std::string sn::desc_typecodes() const
1788 {
1789 std::stringstream ss ;
1790
1791 std::set<int> tcs ;
1792 int minsubdepth = 0;
1793 typecodes(tcs, minsubdepth );
1794
1795 ss << "[sn::desc_typecodes\n" ;
1796 for (int tc : tcs) ss << CSG::Name(tc) << "\n" ;
1797 ss << "]sn::desc_typecodes\n" ;
1798
1799 std::string str = ss.str();
1800 return str ;
1801 }
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812 inline int sn::typecodes_count(const std::vector<int>& tcq, int minsubdepth) const
1813 {
1814 std::set<int> tcs ;
1815 typecodes(tcs, minsubdepth );
1816
1817 int count = 0;
1818 for (int value : tcq) if (tcs.count(value)) ++count;
1819 return count;
1820 }
1821
1822 inline std::string sn::desc_typecodes_count() const
1823 {
1824 std::vector<int> tcq = {CSG_TORUS, CSG_NOTSUPPORTED, CSG_CUTCYLINDER } ;
1825
1826 int minsubdepth = 0;
1827 int count = typecodes_count(tcq, minsubdepth );
1828
1829 std::stringstream ss ;
1830 ss << "[sn::desc_typecodes_count [" << count << "]\n" ;
1831 for (int tc : tcq) ss << CSG::Name(tc) << "\n" ;
1832 ss << "]sn::desc_typecodes_count [" << count << "]\n" ;
1833
1834 std::string str = ss.str();
1835 return str ;
1836 }
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847 inline bool sn::is_positive_form() const
1848 {
1849 unsigned ops = operators(0);
1850 return (ops & CSG::Mask(CSG_DIFFERENCE)) == 0 ;
1851 }
1852
1853 inline bool sn::is_listnode() const { return CSG::IsList(typecode); }
1854 inline std::string sn::tag() const { return CSG::Tag(typecode) ; }
1855
1856
1857
1858 inline void sn::preorder(std::vector<const sn*>& order ) const
1859 {
1860 preorder_r(order, 0);
1861 }
1862 inline void sn::inorder(std::vector<const sn*>& order ) const
1863 {
1864 inorder_r(order, 0);
1865 }
1866 inline void sn::postorder(std::vector<const sn*>& order ) const
1867 {
1868 postorder_r(order, 0);
1869 }
1870
1871
1872 inline void sn::preorder_r(std::vector<const sn*>& order, int d ) const
1873 {
1874 order.push_back(this);
1875 #ifdef WITH_CHILD
1876 for(int i=0 ; i < int(child.size()) ; i++) child[i]->preorder_r(order, d+1) ;
1877 #else
1878 if(left) left->preorder_r(order, d+1) ;
1879 if(right) right->preorder_r(order, d+1) ;
1880 #endif
1881 }
1882
1883
1884
1885
1886
1887
1888
1889 inline void sn::inorder_r(std::vector<const sn*>& order, int d ) const
1890 {
1891 #ifdef WITH_CHILD
1892 int nc = int(child.size()) ;
1893 if( nc > 0 )
1894 {
1895 int split = nc - 1 ;
1896 for(int i=0 ; i < split ; i++) child[i]->inorder_r(order, d+1) ;
1897 order.push_back(this);
1898 for(int i=split ; i < nc ; i++) child[i]->inorder_r(order, d+1) ;
1899 }
1900 else
1901 {
1902 order.push_back(this);
1903 }
1904 #else
1905 if(left) left->inorder_r(order, d+1) ;
1906 order.push_back(this);
1907 if(right) right->inorder_r(order, d+1) ;
1908 #endif
1909 }
1910 inline void sn::postorder_r(std::vector<const sn*>& order, int d ) const
1911 {
1912 #ifdef WITH_CHILD
1913 for(int i=0 ; i < int(child.size()) ; i++) child[i]->postorder_r(order, d+1) ;
1914 #else
1915 if(left) left->postorder_r(order, d+1) ;
1916 if(right) right->postorder_r(order, d+1) ;
1917 #endif
1918 order.push_back(this);
1919 }
1920
1921
1922 inline void sn::inorder_(std::vector<sn*>& order )
1923 {
1924 inorder_r_(order, 0);
1925 }
1926 inline void sn::inorder_r_(std::vector<sn*>& order, int d )
1927 {
1928 #ifdef WITH_CHILD
1929 int nc = int(child.size()) ;
1930 if( nc > 0 )
1931 {
1932 int split = nc - 1 ;
1933 for(int i=0 ; i < split ; i++) child[i]->inorder_r_(order, d+1) ;
1934 order.push_back(this);
1935 for(int i=split ; i < nc ; i++) child[i]->inorder_r_(order, d+1) ;
1936 }
1937 else
1938 {
1939 order.push_back(this);
1940 }
1941 #else
1942 if(left) left->inorder_r_(order, d+1) ;
1943 order.push_back(this);
1944 if(right) right->inorder_r_(order, d+1) ;
1945 #endif
1946 }
1947
1948
1949 inline std::string sn::desc_order(const std::vector<const sn*>& order ) const
1950 {
1951 std::stringstream ss ;
1952 ss << "sn::desc_order [" ;
1953 for(int i=0 ; i < int(order.size()) ; i++)
1954 {
1955 const sn* n = order[i] ;
1956 ss << n->pid << " " ;
1957 }
1958 ss << "]" ;
1959 std::string str = ss.str();
1960 return str ;
1961 }
1962
1963
1964 inline std::string sn::desc() const
1965 {
1966 std::stringstream ss ;
1967 ss << "sn::desc"
1968 << " pid " << std::setw(4) << pid
1969 << " idx " << std::setw(4) << index()
1970 << " typecode " << std::setw(3) << typecode
1971 << " num_node " << std::setw(3) << num_node()
1972 << " num_leaf " << std::setw(3) << num_leaf()
1973 << " maxdepth " << std::setw(2) << maxdepth()
1974 << " is_positive_form " << ( is_positive_form() ? "Y" : "N" )
1975 << " lvid " << std::setw(3) << lvid
1976 << " xform " << ( xform ? "Y" : "N" )
1977 << " tag " << tag()
1978 ;
1979 std::string str = ss.str();
1980 return str ;
1981 }
1982
1983 inline std::string sn::desc_xform() const
1984 {
1985 std::stringstream ss ;
1986 ss << "sn::desc_xform"
1987 << " pid " << std::setw(4) << pid
1988 << " idx " << std::setw(4) << index()
1989 << " lvid " << std::setw(3) << lvid
1990 << " tag " << tag()
1991 << " xform " << ( xform ? "Y" : "N" )
1992 << " " << ( xform ? xform->desc() : "-" )
1993 ;
1994 std::string str = ss.str();
1995 return str ;
1996 }
1997
1998
1999 inline std::string sn::desc_xform_full() const
2000 {
2001 std::stringstream ss ;
2002 ss << "sn::desc_xform_full"
2003 << " pid " << std::setw(4) << pid
2004 << " idx " << std::setw(4) << index()
2005 << " lvid " << std::setw(3) << lvid
2006 << " tag " << tag()
2007 << " xform " << ( xform ? "Y" : "N" )
2008 << " " << ( xform ? xform->desc_full() : "-" )
2009 ;
2010 std::string str = ss.str();
2011 return str ;
2012 }
2013
2014
2015
2016 inline std::string sn::desc_prim() const
2017 {
2018 bool hint_lnprd = is_hint_listnode_prim_discontiguous();
2019 bool hint_lnprc = is_hint_listnode_prim_contiguous();
2020
2021 std::stringstream ss ;
2022 ss
2023 << " idx " << std::setw(4) << index()
2024 << " lvid " << std::setw(3) << lvid
2025 << " " << tag()
2026 << ( aabb ? aabb->desc() : "-" )
2027 << " " << ( hint_lnprd ? "HINT_LNPRD" : "" )
2028 << " " << ( hint_lnprc ? "HINT_LNPRC" : "" )
2029 ;
2030
2031 std::string str = ss.str();
2032 return str ;
2033 }
2034
2035 inline std::string sn::desc_prim_all(bool reverse) const
2036 {
2037 std::vector<const sn*> prim ;
2038 collect_prim(prim);
2039 bool ascending = true ;
2040 OrderPrim<const sn>(prim, sn::AABB_ZMin, ascending );
2041
2042 return DescPrim(prim, reverse);
2043 }
2044
2045
2046 inline std::string sn::id() const
2047 {
2048 std::stringstream ss ;
2049 ss << "sn::id"
2050 << " pid " << pid
2051 << " idx " << idx()
2052 ;
2053 std::string str = ss.str();
2054 return str ;
2055 }
2056
2057 inline std::string sn::brief() const
2058 {
2059 std::stringstream ss ;
2060 ss << "sn::brief"
2061 << " tc " << std::setw(4) << typecode
2062 << " cm " << std::setw(2) << complement
2063 << " lv " << std::setw(3) << lvid
2064 << " xf " << std::setw(1) << ( xform ? "Y" : "N" )
2065 << " pa " << std::setw(1) << ( param ? "Y" : "N" )
2066 << " bb " << std::setw(1) << ( aabb ? "Y" : "N" )
2067 << " pt " << std::setw(1) << ( parent ? "Y" : "N" )
2068 #ifdef WITH_CHILD
2069 << " nc " << std::setw(2) << child.size()
2070 #else
2071 << " l " << std::setw(1) << ( left ? "Y" : "N" )
2072 << " r " << std::setw(1) << ( right ? "Y" : "N" )
2073 #endif
2074 << " dp " << std::setw(2) << depth
2075 << " tg " << tag()
2076 << " bb.desc " << ( aabb ? aabb->desc() : "-" )
2077 ;
2078 std::string str = ss.str();
2079 return str ;
2080 }
2081
2082
2083 inline std::string sn::desc_child() const
2084 {
2085 std::stringstream ss ;
2086 ss << "sn::desc_child num " << num_child() << std::endl ;
2087 for( int i=0 ; i < num_child() ; i++)
2088 {
2089 const sn* ch = get_child(i) ;
2090 ss << " i " << std::setw(2) << i << " 0x" << std::hex << uint64_t(ch) << std::dec << std::endl ;
2091 }
2092 std::string str = ss.str();
2093 return str ;
2094 }
2095
2096 inline std::string sn::desc_this() const
2097 {
2098 std::stringstream ss ;
2099 ss << " 0x" << std::hex << uint64_t(this) << " " << std::dec ;
2100 std::string str = ss.str();
2101 return str ;
2102 }
2103
2104
2105 inline std::string sn::desc_r() const
2106 {
2107 std::stringstream ss ;
2108 ss << "sn::desc_r" << std::endl ;
2109 desc_r(0, ss);
2110 std::string str = ss.str();
2111 return str ;
2112 }
2113 inline void sn::desc_r(int d, std::stringstream& ss) const
2114 {
2115 ss << std::setw(3) << d << ":" << desc_this() << desc() << std::endl ;
2116 #ifdef WITH_CHILD
2117 for(int i=0 ; i < int(child.size()) ; i++) child[i]->desc_r(d+1, ss ) ;
2118 #else
2119 if( left && right )
2120 {
2121 left->desc_r(d+1, ss);
2122 right->desc_r(d+1, ss);
2123 }
2124 #endif
2125 }
2126
2127
2128 inline std::string sn::detail_r() const
2129 {
2130 std::stringstream ss ;
2131 ss << "sn::detail_r" << std::endl ;
2132 detail_r(0, ss);
2133 std::string str = ss.str();
2134 return str ;
2135 }
2136 inline void sn::detail_r(int d, std::stringstream& ss) const
2137 {
2138 ss << std::setw(3) << d << ":" << desc_this() << detail() << std::endl ;
2139 for(int i=0 ; i < int(child.size()) ; i++) child[i]->detail_r(d+1, ss ) ;
2140 }
2141
2142 inline std::string sn::detail() const
2143 {
2144 std::stringstream ss ;
2145 ss << descXF() ;
2146 std::string str = ss.str();
2147 return str ;
2148 }
2149
2150
2151
2152
2153
2154 inline std::string sn::render() const
2155 {
2156 std::stringstream ss ;
2157 for(int mode=0 ; mode < NUM_MODE ; mode++) ss << render(mode) << std::endl ;
2158 std::string str = ss.str();
2159 return str ;
2160 }
2161
2162 inline std::string sn::render_typetag() const { return render(TYPETAG); }
2163 inline std::string sn::render_parent() const { return render(PARENT); }
2164
2165 inline std::string sn::rdr() const { return render_typetag(); }
2166
2167 inline std::string sn::render(int mode) const
2168 {
2169 int nn = num_node();
2170
2171 std::vector<const sn*> pre ;
2172 preorder(pre);
2173 assert( int(pre.size()) == nn );
2174
2175 std::vector<const sn*> in ;
2176 inorder(in);
2177 assert( int(in.size()) == nn );
2178
2179 std::vector<const sn*> post ;
2180 postorder(post);
2181 assert( int(post.size()) == nn );
2182
2183
2184 int width = nn ;
2185 int height = maxdepth();
2186
2187 int xscale = 3 ;
2188 int yscale = 2 ;
2189
2190 scanvas canvas( width+1, height+2, xscale, yscale );
2191 render_r(&canvas, in, mode, 0);
2192
2193 std::stringstream ss ;
2194 ss << std::endl ;
2195 ss << desc() << std::endl ;
2196 ss << "sn::render mode " << mode << " " << rendermode(mode) << std::endl ;
2197 ss << canvas.c << std::endl ;
2198
2199 if(mode == MINIMAL || mode == PID)
2200 {
2201 ss << "preorder " << desc_order(pre) << std::endl ;
2202 ss << "inorder " << desc_order(in) << std::endl ;
2203 ss << "postorder " << desc_order(post) << std::endl ;
2204
2205 unsigned ops = operators(0);
2206 bool pos = is_positive_form() ;
2207
2208 ss << " ops = operators(0) " << ops << std::endl ;
2209 ss << " CSG::MaskDesc(ops) : " << CSG::MaskDesc(ops) << std::endl ;
2210 ss << " is_positive_form() : " << ( pos ? "YES" : "NO" ) << std::endl ;
2211 }
2212
2213 std::string str = ss.str();
2214 return str ;
2215 }
2216
2217 inline const char* sn::rendermode(int mode)
2218 {
2219 const char* md = nullptr ;
2220 switch(mode)
2221 {
2222 case MINIMAL: md = MODE_MINIMAL ; break ;
2223 case TYPECODE: md = MODE_TYPECODE ; break ;
2224 case DEPTH: md = MODE_DEPTH ; break ;
2225 case SUBDEPTH: md = MODE_SUBDEPTH ; break ;
2226 case TYPETAG: md = MODE_TYPETAG ; break ;
2227 case PID: md = MODE_PID ; break ;
2228 case NOTE: md = MODE_NOTE ; break ;
2229 case PARENT: md = MODE_PARENT ; break ;
2230 case IDX: md = MODE_IDX ; break ;
2231 }
2232 return md ;
2233 }
2234
2235 inline void sn::render_r(scanvas* canvas, std::vector<const sn*>& order, int mode, int d) const
2236 {
2237 int ordinal = std::distance( order.begin(), std::find(order.begin(), order.end(), this )) ;
2238 assert( ordinal < int(order.size()) );
2239
2240 int ix = ordinal ;
2241 int iy = d ;
2242 std::string tag = CSG::Tag(typecode, complement == 1);
2243
2244 switch(mode)
2245 {
2246 case MINIMAL : canvas->drawch( ix, iy, 0,0, 'o' ) ; break ;
2247 case TYPECODE : canvas->draw( ix, iy, 0,0, typecode ) ; break ;
2248 case DEPTH : canvas->draw( ix, iy, 0,0, depth ) ; break ;
2249 case SUBDEPTH : canvas->draw( ix, iy, 0,0, subdepth ) ; break ;
2250 case TYPETAG : canvas->draw( ix, iy, 0,0, tag.c_str()) ; break ;
2251 case PID : canvas->draw( ix, iy, 0,0, pid ) ; break ;
2252 case NOTE : canvas->draw( ix, iy, 0,0, note ) ; break ;
2253 case PARENT : canvas->draw( ix, iy, 0,0, parent_index()) ; break ;
2254 case IDX : canvas->draw( ix, iy, 0,0, idx()) ; break ;
2255 }
2256
2257 #ifdef WITH_CHILD
2258 for(int i=0 ; i < int(child.size()) ; i++) child[i]->render_r(canvas, order, mode, d+1) ;
2259 #else
2260 if(left) left->render_r( canvas, order, mode, d+1 );
2261 if(right) right->render_r( canvas, order, mode, d+1 );
2262 #endif
2263 }
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288 inline int sn::BinaryTreeHeight(int q_leaves )
2289 {
2290 int h = 0 ;
2291 while( (1 << h) < q_leaves ) h += 1 ;
2292 return h ;
2293 }
2294
2295 inline int sn::BinaryTreeHeight_1(int q_leaves )
2296 {
2297 int height = -1 ;
2298 for(int h=0 ; h < 10 ; h++ )
2299 {
2300 int tprim = 1 << h ;
2301 if( tprim >= q_leaves )
2302 {
2303 height = h ;
2304 break ;
2305 }
2306 }
2307 return height ;
2308 }
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321 inline sn* sn::ZeroTree_r( int elevation, int op )
2322 {
2323 sn* l = elevation > 1 ? ZeroTree_r( elevation - 1 , op ) : sn::Zero() ;
2324 sn* r = elevation > 1 ? ZeroTree_r( elevation - 1 , op ) : sn::Zero() ;
2325 sn* lr = sn::Create(op, l, r ) ;
2326 return lr ;
2327 }
2328 inline sn* sn::ZeroTree( int num_leaves, int op )
2329 {
2330 int height = BinaryTreeHeight(num_leaves) ;
2331 if(level() > 0 ) std::cout << "[sn::ZeroTree num_leaves " << num_leaves << " height " << height << std::endl;
2332 sn* root = ZeroTree_r( height, op );
2333 if(level() > 0) std::cout << "]sn::ZeroTree " << std::endl ;
2334 return root ;
2335 }
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347 inline sn* sn::CommonOperatorTypeTree( std::vector<int>& leaftypes, int op )
2348 {
2349 int num_leaves = leaftypes.size();
2350 sn* root = nullptr ;
2351 if( num_leaves == 1 )
2352 {
2353 root = sn::Prim(leaftypes[0]) ;
2354 }
2355 else
2356 {
2357 root = ZeroTree(num_leaves, op );
2358
2359 if(level() > 0) std::cout << "sn::CommonOperatorTypeTree ZeroTree num_leaves " << num_leaves << std::endl ;
2360 if(level() > 1) std::cout << root->render(5) ;
2361
2362 root->populate_leaftypes(leaftypes);
2363
2364 if(level() > 0) std::cout << "sn::CommonOperatorTypeTree populated num_leaves " << num_leaves << std::endl ;
2365 if(level() > 1) std::cout << root->render(5) ;
2366
2367 root->prune();
2368
2369 if(level() > 0) std::cout << "sn::CommonOperatorTypeTree pruned num_leaves " << num_leaves << std::endl ;
2370 if(level() > 1) std::cout << root->render(5) ;
2371 }
2372 return root ;
2373 }
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387 inline void sn::populate_leaftypes(std::vector<int>& leaftypes )
2388 {
2389 int num_leaves = leaftypes.size();
2390 int num_leaves_placed = 0 ;
2391
2392 std::vector<sn*> order ;
2393 inorder_(order) ;
2394
2395 int num_nodes = order.size();
2396
2397 if(level() > 0) std::cout
2398 << "sn::populate_leaftypes"
2399 << " num_leaves " << num_leaves
2400 << " num_nodes " << num_nodes
2401 << std::endl
2402 ;
2403
2404 for(int i=0 ; i < num_nodes ; i++)
2405 {
2406 sn* n = order[i];
2407 if(level() > 1) std::cout
2408 << "sn::populate_leaftypes " << std::setw(3) << i
2409 << " n.desc " << n->desc()
2410 << std::endl
2411 ;
2412 }
2413
2414 for(int i=0 ; i < num_nodes ; i++)
2415 {
2416 sn* n = order[i];
2417
2418 #ifdef WITH_CHILD
2419 if(level() > 1) std::cout
2420 << "sn::populate_leaftypes"
2421 << " WITH_CHILD "
2422 << " i " << i
2423 << " n.is_operator " << n->is_operator()
2424 << " n.child.size " << n->child.size()
2425 << " num_leaves_placed " << num_leaves_placed
2426 << std::endl
2427 ;
2428
2429 if(n->is_operator())
2430 {
2431 assert( n->child.size() == 2 );
2432 for(int j=0 ; j < 2 ; j++)
2433 {
2434 sn* ch = n->child[j] ;
2435 if(level() > 1 ) std::cout
2436 << "sn::populate_leaftypes"
2437 << " ch.desc " << ch->desc()
2438 << std::endl
2439 ;
2440
2441 if( ch->is_zero() && num_leaves_placed < num_leaves )
2442 {
2443 n->set_child(j, sn::Prim(leaftypes[num_leaves_placed]), false) ;
2444 num_leaves_placed += 1 ;
2445 }
2446 }
2447 }
2448 #else
2449 if(n->is_operator())
2450 {
2451 if(n->left->is_zero() && num_leaves_placed < num_leaves)
2452 {
2453 n->set_left( sn::Prim(leaftypes[num_leaves_placed]), false ) ;
2454 num_leaves_placed += 1 ;
2455 }
2456 if(n->right->is_zero() && num_leaves_placed < num_leaves)
2457 {
2458 n->set_right(sn::Prim(leaftypes[num_leaves_placed]), false ) ;
2459 num_leaves_placed += 1 ;
2460 }
2461 }
2462 #endif
2463 }
2464 assert( num_leaves_placed == num_leaves );
2465 }
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479 inline void sn::populate_leaves(std::vector<sn*>& leaves )
2480 {
2481 int num_leaves = leaves.size();
2482 int num_leaves_placed = 0 ;
2483
2484 std::vector<sn*> order ;
2485 inorder_(order) ;
2486
2487 int num_nodes = order.size();
2488
2489 if(level() > 0) std::cout
2490 << "sn::populate_leaves"
2491 << " num_leaves " << num_leaves
2492 << " num_nodes " << num_nodes
2493 << std::endl
2494 ;
2495
2496 for(int i=0 ; i < num_nodes ; i++)
2497 {
2498 sn* n = order[i];
2499 if(level() > 1) std::cout
2500 << "sn::populate_leaves " << std::setw(3) << i
2501 << " n.desc " << n->desc()
2502 << std::endl
2503 ;
2504 }
2505
2506 for(int i=0 ; i < num_nodes ; i++)
2507 {
2508 sn* n = order[i];
2509
2510 #ifdef WITH_CHILD
2511 if(level() > 1) std::cout
2512 << "sn::populate_leaves"
2513 << " WITH_CHILD "
2514 << " i " << i
2515 << " n.is_operator " << n->is_operator()
2516 << " n.child.size " << n->child.size()
2517 << " num_leaves_placed " << num_leaves_placed
2518 << std::endl
2519 ;
2520
2521 if(n->is_operator())
2522 {
2523 assert( n->child.size() == 2 );
2524 for(int j=0 ; j < 2 ; j++)
2525 {
2526 sn* ch = n->child[j] ;
2527 if(level() > 1 ) std::cout
2528 << "sn::populate_leaves"
2529 << " ch.desc " << ch->desc()
2530 << std::endl
2531 ;
2532
2533 if( ch->is_zero() && num_leaves_placed < num_leaves )
2534 {
2535 n->set_child(j, leaves[num_leaves_placed], false) ;
2536 num_leaves_placed += 1 ;
2537 }
2538 }
2539 }
2540 #else
2541 if(n->is_operator())
2542 {
2543 if(n->left->is_zero() && num_leaves_placed < num_leaves)
2544 {
2545 n->set_left( leaves[num_leaves_placed], false ) ;
2546 num_leaves_placed += 1 ;
2547 }
2548 if(n->right->is_zero() && num_leaves_placed < num_leaves)
2549 {
2550 n->set_right( leaves[num_leaves_placed], false ) ;
2551 num_leaves_placed += 1 ;
2552 }
2553 }
2554 #endif
2555 }
2556 assert( num_leaves_placed == num_leaves );
2557 }
2558
2559
2560
2561 inline void sn::prune()
2562 {
2563 prune_r(0);
2564
2565 if(has_dangle())
2566 {
2567 if(level() > -1) std::cout << "sn::prune ERROR root still has dangle " << std::endl ;
2568 }
2569
2570 }
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611 inline void sn::prune_r(int d)
2612 {
2613 if(!is_operator()) return ;
2614
2615 sn* l = get_left();
2616 sn* r = get_right();
2617
2618 l->prune_r(d+1);
2619 r->prune_r(d+1);
2620
2621
2622
2623 if( l->is_lrzero() )
2624 {
2625 set_left(sn::Zero(), false) ;
2626 }
2627 else if( l->is_rzero() )
2628 {
2629 sn* ll = l->get_left();
2630 set_left( ll, true );
2631 }
2632
2633 if(r->is_lrzero())
2634 {
2635 set_right(sn::Zero(), false) ;
2636 }
2637 else if( r->is_rzero() )
2638 {
2639 sn* rl = r->get_left() ;
2640 set_right(rl, true) ;
2641 }
2642 }
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658 inline bool sn::has_dangle() const
2659 {
2660 #ifdef WITH_CHILD
2661 int num_zero = 0 ;
2662 for(int i=0 ; i < int(child.size()) ; i++) if(child[i]->is_zero()) num_zero += 1 ;
2663 return num_zero > 0 ;
2664 #else
2665 return is_operator() && ( right->is_zero() || left->is_zero()) ;
2666 #endif
2667 }
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694 inline void sn::positivize()
2695 {
2696 positivize_r(false, 0);
2697 }
2698 inline void sn::positivize_r(bool negate, int d)
2699 {
2700 if(is_primitive() || is_listnode())
2701 {
2702 if(negate)
2703 {
2704 if(is_primitive())
2705 {
2706 flip_complement();
2707 }
2708 else if(is_listnode())
2709 {
2710 flip_complement_child();
2711 }
2712 }
2713 }
2714 else
2715 {
2716 bool left_negate = false ;
2717 bool right_negate = false ;
2718
2719 if(typecode == CSG_INTERSECTION || typecode == CSG_UNION)
2720 {
2721 if(negate)
2722 {
2723 typecode = CSG::DeMorganSwap(typecode) ;
2724 left_negate = true ;
2725 right_negate = true ;
2726 }
2727 else
2728 {
2729 left_negate = false ;
2730 right_negate = false ;
2731 }
2732 }
2733 else if(typecode == CSG_DIFFERENCE)
2734 {
2735 if(negate)
2736 {
2737 typecode = CSG_UNION ;
2738 left_negate = true ;
2739 right_negate = false ;
2740 }
2741 else
2742 {
2743 typecode = CSG_INTERSECTION ;
2744 left_negate = false ;
2745 right_negate = true ;
2746 }
2747 }
2748
2749 #ifdef WITH_CHILD
2750 assert( child.size() == 2 );
2751 sn* left = child[0] ;
2752 sn* right = child[1] ;
2753 #endif
2754 left->positivize_r(left_negate, d+1);
2755 right->positivize_r(right_negate, d+1);
2756 }
2757 }
2758
2759
2760 inline void sn::flip_complement()
2761 {
2762 switch(complement)
2763 {
2764 case 0: complement = 1 ; break ;
2765 case 1: complement = 0 ; break ;
2766 default: assert(0) ; break ;
2767 }
2768 }
2769 inline void sn::flip_complement_child()
2770 {
2771 for(int i=0 ; i < num_child() ; i++)
2772 {
2773 sn* ch = get_child(i) ;
2774 ch->flip_complement() ;
2775 }
2776 }
2777
2778
2779 inline void sn::zero_label()
2780 {
2781 for(int i=0 ; i < int(sizeof(label)) ; i++) label[i] = '\0' ;
2782 }
2783
2784 inline void sn::set_label( const char* label_ )
2785 {
2786 strncpy( &label[0], label_, sizeof(label) );
2787 }
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803 inline void sn::set_lvid(int lvid_)
2804 {
2805 set_lvid_r(lvid_, 0);
2806
2807 int chk = checktree();
2808 if( chk != 0 )
2809 {
2810 if(level() > 0 ) std::cout
2811 << "sn::set_lvid"
2812 << " lvid " << lvid_
2813 << " checktree " << chk
2814 << std::endl
2815 ;
2816 }
2817 assert( chk == 0 );
2818 }
2819 inline void sn::set_lvid_r(int lvid_, int d)
2820 {
2821 lvid = lvid_ ;
2822 depth = d ;
2823
2824 for(int i=0 ; i < num_child() ; i++)
2825 {
2826 sn* ch = get_child(i) ;
2827 ch->set_lvid_r(lvid_, d+1 );
2828
2829 if(ch->parent == nullptr)
2830 {
2831 ch->parent = this ;
2832 }
2833 else
2834 {
2835 assert( ch->parent == this ) ;
2836 }
2837 }
2838 }
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850 inline int sn::check_idx(const char* msg) const
2851 {
2852 return check_idx_r(0, msg);
2853 }
2854 inline int sn::check_idx_r(int d, const char* msg) const
2855 {
2856 int idx_ = idx();
2857 const sn* chk = Get(idx_);
2858
2859 bool expect = chk == this ;
2860 if(!expect) std::cerr
2861 << "sn::check_idx_r"
2862 << " ERROR Get(idx()) != this ? "
2863 << " idx_ " << idx_
2864 << " msg " << ( msg ? msg : "-" )
2865 << "\n"
2866 << " this.desc " << desc() << "\n"
2867 << " chk.desc " << ( chk ? chk->desc() : "-" ) << "\n"
2868 ;
2869
2870 int rc = expect ? 0 : 1 ;
2871
2872
2873 for(int i=0 ; i < num_child() ; i++) rc += get_child(i)->check_idx_r(d+1, msg);
2874 return rc ;
2875 }
2876
2877
2878
2879
2880
2881 inline void sn::setPA( double x0, double y0, double z0, double w0, double x1, double y1 )
2882 {
2883 if( param == nullptr ) param = new s_pa ;
2884 param->x0 = x0 ;
2885 param->y0 = y0 ;
2886 param->z0 = z0 ;
2887 param->w0 = w0 ;
2888 param->x1 = x1 ;
2889 param->y1 = y1 ;
2890 }
2891
2892
2893 inline const double* sn::getPA_data() const
2894 {
2895 return param ? param->data() : nullptr ;
2896 }
2897
2898 inline void sn::copyPA_data(double* dst) const
2899 {
2900 const double* src = getPA_data() ;
2901 for(int i=0 ; i < 6 ; i++) dst[i] = src[i] ;
2902 }
2903
2904
2905
2906
2907
2908 inline void sn::setBB( double x0, double y0, double z0, double x1, double y1, double z1 )
2909 {
2910 bool bad_bbox = x0 >= x1 || y0 >= y1 || z0 >= z1 ;
2911 if(bad_bbox) std::cerr
2912 << "sn::setBB BAD BOUNDING BOX "
2913 << "\n"
2914 << " x0 " << x0
2915 << " x1 " << x1
2916 << "\n"
2917 << " y0 " << y0
2918 << " y1 " << y1
2919 << "\n"
2920 << " z0 " << z0
2921 << " z1 " << z1
2922 << "\n"
2923 ;
2924
2925 assert(!bad_bbox);
2926
2927
2928 if( aabb == nullptr ) aabb = new s_bb ;
2929 aabb->x0 = x0 ;
2930 aabb->y0 = y0 ;
2931 aabb->z0 = z0 ;
2932 aabb->x1 = x1 ;
2933 aabb->y1 = y1 ;
2934 aabb->z1 = z1 ;
2935 }
2936
2937 inline void sn::setBB( double x0 )
2938 {
2939 if( aabb == nullptr ) aabb = new s_bb ;
2940 aabb->x0 = -x0 ;
2941 aabb->y0 = -x0 ;
2942 aabb->z0 = -x0 ;
2943 aabb->x1 = +x0 ;
2944 aabb->y1 = +x0 ;
2945 aabb->z1 = +x0 ;
2946 }
2947
2948 inline const double* sn::getBB_data() const
2949 {
2950 return aabb ? aabb->data() : nullptr ;
2951 }
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971 inline void sn::copyBB_data(double* dst) const
2972 {
2973 const double* src = getBB_data() ;
2974 for(int i=0 ; i < 6 ; i++) dst[i] = src[i] ;
2975 }
2976
2977
2978
2979 inline double sn::getBB_xmin() const { return aabb ? aabb->x0 : 0. ; }
2980 inline double sn::getBB_ymin() const { return aabb ? aabb->y0 : 0. ; }
2981 inline double sn::getBB_zmin() const { return aabb ? aabb->z0 : 0. ; }
2982
2983 inline double sn::getBB_xmax() const { return aabb ? aabb->x1 : 0. ; }
2984 inline double sn::getBB_ymax() const { return aabb ? aabb->y1 : 0. ; }
2985 inline double sn::getBB_zmax() const { return aabb ? aabb->z1 : 0. ; }
2986
2987 inline double sn::getBB_xavg() const { return ( getBB_xmin() + getBB_xmax() )/2. ; }
2988 inline double sn::getBB_yavg() const { return ( getBB_ymin() + getBB_ymax() )/2. ; }
2989 inline double sn::getBB_zavg() const { return ( getBB_zmin() + getBB_zmax() )/2. ; }
2990
2991
2992 inline double sn::AABB_XMin( const sn* n ){ return n ? n->getBB_xmin() : 0. ; }
2993 inline double sn::AABB_YMin( const sn* n ){ return n ? n->getBB_ymin() : 0. ; }
2994 inline double sn::AABB_ZMin( const sn* n ){ return n ? n->getBB_zmin() : 0. ; }
2995
2996 inline double sn::AABB_XMax( const sn* n ){ return n ? n->getBB_xmax() : 0. ; }
2997 inline double sn::AABB_YMax( const sn* n ){ return n ? n->getBB_ymax() : 0. ; }
2998 inline double sn::AABB_ZMax( const sn* n ){ return n ? n->getBB_zmax() : 0. ; }
2999
3000 inline double sn::AABB_XAvg( const sn* n ){ return n ? n->getBB_xavg() : 0. ; }
3001 inline double sn::AABB_YAvg( const sn* n ){ return n ? n->getBB_yavg() : 0. ; }
3002 inline double sn::AABB_ZAvg( const sn* n ){ return n ? n->getBB_zavg() : 0. ; }
3003
3004
3005 inline bool sn::hasXF() const
3006 {
3007 return xform != nullptr ;
3008 }
3009 inline void sn::setXF()
3010 {
3011 glm::tmat4x4<double> id(1.);
3012 setXF(id,id);
3013 }
3014 inline void sn::setXF( const glm::tmat4x4<double>& t )
3015 {
3016 glm::tmat4x4<double> v = glm::inverse(t) ;
3017 setXF(t, v);
3018 }
3019 inline void sn::combineXF( const glm::tmat4x4<double>& t )
3020 {
3021 glm::tmat4x4<double> v = glm::inverse(t) ;
3022 combineXF(t, v);
3023 }
3024 inline void sn::setXF( const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v )
3025 {
3026 if( xform == nullptr ) xform = new s_tv ;
3027 xform->t = t ;
3028 xform->v = v ;
3029 }
3030 inline void sn::combineXF( const glm::tmat4x4<double>& t, const glm::tmat4x4<double>& v )
3031 {
3032 if( xform == nullptr )
3033 {
3034 xform = new s_tv ;
3035 xform->t = t ;
3036 xform->v = v ;
3037 }
3038 else
3039 {
3040 glm::tmat4x4<double> tt = xform->t * t ;
3041 glm::tmat4x4<double> vv = v * xform->v ;
3042 xform->t = tt ;
3043 xform->v = vv ;
3044 }
3045 }
3046
3047 inline std::string sn::descXF() const
3048 {
3049 std::stringstream ss ;
3050 ss << "sn::descXF (s_tv)xform " << ( xform ? xform->desc() : "-" ) ;
3051 std::string str = ss.str();
3052 return str ;
3053 }
3054
3055
3056
3057 inline sn* sn::Cylinder(double radius, double z1, double z2)
3058 {
3059 assert( z2 > z1 );
3060 sn* nd = Create(CSG_CYLINDER);
3061 nd->setPA( 0.f, 0.f, 0.f, radius, z1, z2) ;
3062 nd->setBB( -radius, -radius, z1, +radius, +radius, z2 );
3063 return nd ;
3064 }
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078 inline sn* sn::CutCylinder(
3079 double R,
3080 double dz,
3081 double _pz_nrm_x,
3082 double _pz_nrm_y,
3083 double _pz_nrm_z,
3084 double _nz_nrm_x,
3085 double _nz_nrm_y,
3086 double _nz_nrm_z )
3087 {
3088 assert( _pz_nrm_z > 0. );
3089 assert( _nz_nrm_z < 0. );
3090
3091 assert( _pz_nrm_y == 0. );
3092 assert( _nz_nrm_y == 0. );
3093
3094 double pz_nrm = std::sqrt( _pz_nrm_x*_pz_nrm_x + _pz_nrm_y*_pz_nrm_y + _pz_nrm_z*_pz_nrm_z );
3095 double pz_nrm_x = _pz_nrm_x/pz_nrm ;
3096 double pz_nrm_y = _pz_nrm_y/pz_nrm ;
3097 double pz_nrm_z = _pz_nrm_z/pz_nrm ;
3098
3099 double nz_nrm = std::sqrt( _nz_nrm_x*_nz_nrm_x + _nz_nrm_y*_nz_nrm_y + _nz_nrm_z*_nz_nrm_z );
3100 double nz_nrm_x = _nz_nrm_x/nz_nrm ;
3101 double nz_nrm_y = _nz_nrm_y/nz_nrm ;
3102 double nz_nrm_z = _nz_nrm_z/nz_nrm ;
3103
3104
3105 double zmin, zmax ;
3106 CutCylinderZRange(zmin, zmax, R, dz, pz_nrm_x, pz_nrm_y, pz_nrm_z, nz_nrm_x, nz_nrm_y, nz_nrm_z );
3107
3108
3109 bool dump = false ;
3110 if(dump) std::cout
3111 << "sn::CutCylinder\n"
3112 << " R " << std::setw(10) << std::fixed << std::setprecision(6) << R << "\n"
3113 << " dz " << std::setw(10) << std::fixed << std::setprecision(6) << dz << "\n"
3114 << " _pz_nrm_x " << std::setw(10) << std::fixed << std::setprecision(6) << _pz_nrm_x << "\n"
3115 << " _pz_nrm_y " << std::setw(10) << std::fixed << std::setprecision(6) << _pz_nrm_y << "\n"
3116 << " _pz_nrm_z " << std::setw(10) << std::fixed << std::setprecision(6) << _pz_nrm_z << "\n"
3117 << "\n"
3118 << " pz_nrm_x " << std::setw(10) << std::fixed << std::setprecision(6) << pz_nrm_x << "\n"
3119 << " pz_nrm_y " << std::setw(10) << std::fixed << std::setprecision(6) << pz_nrm_y << "\n"
3120 << " pz_nrm_z " << std::setw(10) << std::fixed << std::setprecision(6) << pz_nrm_z << "\n"
3121 << "\n"
3122 << " _nz_nrm_x " << std::setw(10) << std::fixed << std::setprecision(6) << _nz_nrm_x << "\n"
3123 << " _nz_nrm_y " << std::setw(10) << std::fixed << std::setprecision(6) << _nz_nrm_y << "\n"
3124 << " _nz_nrm_z " << std::setw(10) << std::fixed << std::setprecision(6) << _nz_nrm_z << "\n"
3125 << "\n"
3126 << " nz_nrm_x " << std::setw(10) << std::fixed << std::setprecision(6) << nz_nrm_x << "\n"
3127 << " nz_nrm_y " << std::setw(10) << std::fixed << std::setprecision(6) << nz_nrm_y << "\n"
3128 << " nz_nrm_z " << std::setw(10) << std::fixed << std::setprecision(6) << nz_nrm_z << "\n"
3129 << "\n"
3130 << " zmax " << std::setw(10) << std::fixed << std::setprecision(6) << zmax << "\n"
3131 << " zmin " << std::setw(10) << std::fixed << std::setprecision(6) << zmin << "\n"
3132 << "\n"
3133 ;
3134
3135 sn* nd = Create(CSG_CUTCYLINDER);
3136 nd->setPA( R, dz, pz_nrm_x, pz_nrm_z, nz_nrm_x, nz_nrm_z) ;
3137 nd->setBB( -R, -R, zmin, +R, +R, zmax );
3138
3139 return nd ;
3140 }
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196 inline void sn::CutCylinderZRange(
3197 double& zmin,
3198 double& zmax,
3199 double R,
3200 double dz,
3201 double pz_nrm_x,
3202 double pz_nrm_y,
3203 double pz_nrm_z,
3204 double nz_nrm_x,
3205 double nz_nrm_y,
3206 double nz_nrm_z )
3207 {
3208 double pdz = R*std::abs(-pz_nrm_x)/(pz_nrm_z) ;
3209 assert( pdz > 0. );
3210 zmax = dz + pdz ;
3211
3212 double ndz = R*std::abs(nz_nrm_x)/(-nz_nrm_z) ;
3213 assert( ndz > 0. );
3214 zmin = -dz -ndz ;
3215 }
3216
3217
3218
3219 inline sn* sn::Cone(double r1, double z1, double r2, double z2)
3220 {
3221 assert( z2 > z1 );
3222 double rmax = fmax(r1, r2) ;
3223 sn* nd = Create(CSG_CONE) ;
3224 nd->setPA( r1, z1, r2, z2, 0., 0. ) ;
3225 nd->setBB( -rmax, -rmax, z1, rmax, rmax, z2 );
3226 return nd ;
3227 }
3228 inline sn* sn::Sphere(double radius)
3229 {
3230 assert( radius > zero );
3231 sn* nd = Create(CSG_SPHERE) ;
3232 nd->setPA( zero, zero, zero, radius, zero, zero );
3233 nd->setBB( -radius, -radius, -radius, radius, radius, radius );
3234 return nd ;
3235 }
3236 inline sn* sn::ZSphere(double radius, double z1, double z2)
3237 {
3238 assert( radius > zero );
3239 assert( z2 > z1 );
3240 sn* nd = Create(CSG_ZSPHERE) ;
3241 nd->setPA( zero, zero, zero, radius, z1, z2 );
3242 nd->setBB( -radius, -radius, z1, radius, radius, z2 );
3243 return nd ;
3244 }
3245 inline sn* sn::Box3(double fullside)
3246 {
3247 return Box3(fullside, fullside, fullside);
3248 }
3249 inline sn* sn::Box3(double fx, double fy, double fz )
3250 {
3251 assert( fx > 0. );
3252 assert( fy > 0. );
3253 assert( fz > 0. );
3254
3255 sn* nd = Create(CSG_BOX3) ;
3256 nd->setPA( fx, fy, fz, 0., 0., 0. );
3257 nd->setBB( -fx*0.5 , -fy*0.5, -fz*0.5, fx*0.5 , fy*0.5, fz*0.5 );
3258 return nd ;
3259 }
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304 inline sn* sn::Torus(double rmin, double rmax, double rtor, double startPhi_deg, double deltaPhi_deg )
3305 {
3306 double rext = rtor+rmax ;
3307 double rint = rtor-rmax ;
3308
3309 double startPhi = startPhi_deg/180.*M_PI ;
3310 double deltaPhi = deltaPhi_deg/180.*M_PI ;
3311 double2 pmin ;
3312 double2 pmax ;
3313 sgeomtools::DiskExtent(rint, rext, startPhi, deltaPhi, pmin, pmax );
3314
3315 sn* nd = Create(CSG_TORUS) ;
3316 nd->setPA( rmin, rmax, rtor, startPhi_deg, deltaPhi_deg, 0. );
3317 nd->setBB( pmin.x, pmin.y, -rmax, pmax.x, pmax.y, +rmax );
3318
3319 return nd ;
3320 }
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350 inline sn* sn::PhiCut(double phi0, double phi1)
3351 {
3352 sn* nd = Create(CSG_PHICUT) ;
3353 bool expect_phi = phi1 > phi0 ;
3354
3355 double cos_phi0 = cos(phi0);
3356 double sin_phi0 = sin(phi0);
3357 double cos_phi1 = cos(phi1);
3358 double sin_phi1 = sin(phi1);
3359
3360 double cross_product = cos_phi0*sin_phi1 - cos_phi1*sin_phi0 ;
3361 bool is_wedge = cross_product > 0. ;
3362 bool is_pacman = cross_product < 0. ;
3363
3364 int PACMAN_ALLOWED = ssys::getenvint(sn__PhiCut_PACMAN_ALLOWED, 0) ;
3365 bool expect_cross_product = PACMAN_ALLOWED ? true : is_wedge ;
3366 bool expect = expect_phi && expect_cross_product ;
3367
3368 if(!expect) std::cerr
3369 << "sn::PhiCut"
3370 << " phi0 " << phi0
3371 << " phi1 " << phi1
3372 << " expect " << ( expect ? "YES" : "NO " )
3373 << " expect_phi " << ( expect_phi ? "YES" : "NO " )
3374 << " expect_cross_product " << ( expect_cross_product ? "YES" : "NO " )
3375 << " cross_product " << cross_product
3376 << " is_wedge " << ( is_wedge ? "YES" : "NO " )
3377 << " is_pacman " << ( is_pacman ? "YES" : "NO " )
3378 << " PACMAN_ALLOWED [" << sn__PhiCut_PACMAN_ALLOWED << "] " << PACMAN_ALLOWED
3379 << "\n"
3380 ;
3381
3382 assert( expect_phi );
3383 assert( expect_cross_product );
3384 assert( expect );
3385
3386 nd->setPA( cos_phi0, sin_phi0, cos_phi1, sin_phi1, zero, zero );
3387 return nd ;
3388 }
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417 inline sn* sn::HalfSpace(double x, double y, double z, double w)
3418 {
3419 glm::tvec3<double> _normal(x,y,z);
3420 glm::tvec3<double> normal = glm::normalize(_normal);
3421 double plane_distance = w ;
3422
3423 sn* nd = Create(CSG_HALFSPACE) ;
3424 nd->setPA( normal.x, normal.y, normal.z, plane_distance, zero, zero );
3425 return nd ;
3426 }
3427
3428
3429 inline sn* sn::Notsupported()
3430 {
3431 sn* nd = Create(CSG_NOTSUPPORTED);
3432 return nd ;
3433 }
3434
3435
3436 inline sn* sn::Zero(double x, double y, double z, double w, double z1, double z2)
3437 {
3438 sn* nd = Create(CSG_ZERO);
3439 nd->setPA( x, y, z, w, z1, z2 );
3440 return nd ;
3441 }
3442 inline sn* sn::Zero()
3443 {
3444 sn* nd = Create(CSG_ZERO);
3445 return nd ;
3446 }
3447 inline sn* sn::Prim(int typecode_)
3448 {
3449 return new sn(typecode_, nullptr, nullptr) ;
3450 }
3451 inline sn* sn::Create(int typecode_, sn* left_, sn* right_)
3452 {
3453 sn* nd = new sn(typecode_, left_, right_) ;
3454 return nd ;
3455 }
3456 inline sn* sn::Boolean(int typecode_, sn* left_, sn* right_)
3457 {
3458 sn* nd = Create(typecode_, left_, right_);
3459 return nd ;
3460 }
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484 inline void sn::ZNudgeExpandEnds(int lvid, std::vector<sn*>& prims, bool enable)
3485 {
3486 int num_prim = prims.size() ;
3487
3488 sn* lower = prims[0] ;
3489 sn* upper = prims[prims.size()-1] ;
3490 bool can_znudge_ends = lower->can_znudge() && upper->can_znudge() ;
3491 assert( can_znudge_ends );
3492
3493 double lower_zmin = lower->zmin() ;
3494 double upper_zmax = upper->zmax() ;
3495 bool z_expect = upper_zmax > lower_zmin ;
3496
3497 if(level() > 0) std::cout
3498 << std::endl
3499 << "sn::ZNudgeExpandEnds "
3500 << " lvid " << lvid
3501 << " num_prim " << num_prim
3502 << " enable " << ( enable ? "YES" : "NO " )
3503 << " level " << level()
3504 << " can_znudge_ends " << ( can_znudge_ends ? "YES" : "NO " )
3505 << " lower_zmin " << lower_zmin
3506 << " upper_zmax " << upper_zmax
3507 << " z_expect " << ( z_expect ? "YES" : "NO " )
3508 << std::endl
3509 << ZDesc(prims)
3510 << std::endl
3511 ;
3512
3513 if(!enable) return ;
3514 assert( z_expect );
3515
3516 double dz = 1. ;
3517 lower->decrease_zmin(dz);
3518 upper->increase_zmax(dz);
3519 }
3520
3521
3522
3523
3524
3525
3526 inline void sn::ZNudgeOverlapJoints(int lvid, std::vector<sn*>& prims, bool enable )
3527 {
3528 int num_prim = prims.size() ;
3529 assert( num_prim > 1 && "one prim has no joints" );
3530
3531 bool dump = level() > 0 ;
3532
3533 std::stringstream ss ;
3534 std::ostream* out = dump ? &ss : nullptr ;
3535
3536 if(out) *out
3537 << std::endl
3538 << "sn::ZNudgeOverlapJoints "
3539 << " lvid " << lvid
3540 << " num_prim " << num_prim
3541 << " enable " << ( enable ? "YES" : "NO " )
3542 << " level " << level()
3543 << std::endl
3544 << ZDesc(prims)
3545 << std::endl
3546 ;
3547
3548 for(int i=1 ; i < num_prim ; i++)
3549 {
3550 sn* lower = prims[i-1] ;
3551 sn* upper = prims[i] ;
3552 ZNudgeOverlapJoint(lvid, i, lower, upper, enable, out );
3553 }
3554
3555 if(out)
3556 {
3557 std::string str = ss.str();
3558 std::cout << str ;
3559 }
3560 }
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623 inline void sn::ZNudgeOverlapJoint(int lvid, int i, sn* lower, sn* upper, bool enable, std::ostream* out )
3624 {
3625 bool can_znudge_ = lower->can_znudge() && upper->can_znudge() ;
3626 if(!can_znudge_) std::raise(SIGINT) ;
3627 assert( can_znudge_ );
3628
3629 double dz = 1. ;
3630 double lower_zmax = lower->zmax();
3631 double upper_zmin = upper->zmin() ;
3632 bool z_coincident_joint = std::abs( lower_zmax - upper_zmin ) < Z_EPSILON ;
3633
3634 double upper_rperp_at_zmin = upper->rperp_at_zmin() ;
3635 double lower_rperp_at_zmax = lower->rperp_at_zmax() ;
3636
3637 if(out) *out
3638 << "sn::ZNudgeOverlapJoint"
3639 << " ("<< i-1 << "," << i << ") "
3640 << " lower_zmax " << lower_zmax
3641 << " upper_zmin " << upper_zmin
3642 << " z_coincident_joint " << ( z_coincident_joint ? "YES" : "NO " )
3643 << " enable " << ( enable ? "YES" : "NO " )
3644 << " upper_rperp_at_zmin " << upper_rperp_at_zmin
3645 << " lower_rperp_at_zmax " << lower_rperp_at_zmax
3646 << std::endl
3647 ;
3648
3649 if(!z_coincident_joint) return ;
3650
3651 if( lower_rperp_at_zmax > upper_rperp_at_zmin )
3652 {
3653 upper->decrease_zmin( dz );
3654 if(out) *out
3655 << "sn::ZNudgeOverlapJoint"
3656 << " lvid " << lvid
3657 << " lower_rperp_at_zmax > upper_rperp_at_zmin : upper->decrease_zmin( dz ) "
3658 << " : expand upper down into bigger lower "
3659 << std::endl
3660 ;
3661 }
3662 else
3663 {
3664 lower->increase_zmax( dz );
3665 if(out) *out
3666 << "sn::ZNudgeOverlapJoints"
3667 << " lvid " << lvid
3668 << " !(lower_rperp_at_zmax > upper_rperp_at_zmin) : lower->increase_zmax( dz ) "
3669 << " : expand lower up into bigger upper "
3670 << std::endl
3671 ;
3672 }
3673 }
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691 inline bool sn::can_znudge() const
3692 {
3693 return param && CSG::CanZNudge(typecode) ;
3694 }
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704 inline bool sn::CanZNudgeAll(std::vector<sn*>& prims)
3705 {
3706 int num_prim = prims.size() ;
3707 int count = 0 ;
3708 for(int i=0 ; i < num_prim ; i++) if(prims[i]->can_znudge()) count += 1 ;
3709 return count == num_prim ;
3710 }
3711
3712
3713 inline unsigned sn::NameHint(const char* name)
3714 {
3715 unsigned hint = 0 ;
3716 if( strstr(name, _HINT_LISTNODE_PRIM_DISCONTIGUOUS) != nullptr) hint = HINT_LISTNODE_PRIM_DISCONTIGUOUS ;
3717 else if(strstr(name, _HINT_LISTNODE_PRIM_CONTIGUOUS) != nullptr) hint = HINT_LISTNODE_PRIM_CONTIGUOUS ;
3718 return hint ;
3719 }
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730 inline void sn::set_hint_note(unsigned hint)
3731 {
3732 if(hint == 0u) return ;
3733 if( (hint & HINT_LISTNODE_PRIM_DISCONTIGUOUS) != 0 ) note |= HINT_LISTNODE_PRIM_DISCONTIGUOUS ;
3734 else if( (hint & HINT_LISTNODE_PRIM_CONTIGUOUS) != 0 ) note |= HINT_LISTNODE_PRIM_CONTIGUOUS ;
3735 }
3736
3737 inline void sn::set_hint_listnode_prim_discontiguous(){ set_hint_note( HINT_LISTNODE_PRIM_DISCONTIGUOUS ); }
3738 inline void sn::set_hint_listnode_prim_contiguous(){ set_hint_note( HINT_LISTNODE_PRIM_CONTIGUOUS ); }
3739
3740 inline bool sn::is_hint_listnode_prim_discontiguous() const { return ( note & HINT_LISTNODE_PRIM_DISCONTIGUOUS ) != 0 ; }
3741 inline bool sn::is_hint_listnode_prim_contiguous() const { return ( note & HINT_LISTNODE_PRIM_CONTIGUOUS ) != 0 ; }
3742
3743
3744
3745
3746
3747 inline void sn::increase_zmax( double dz )
3748 {
3749 if(typecode == CSG_CONE)
3750 {
3751 increase_zmax_cone( dz );
3752 }
3753 else
3754 {
3755 increase_zmax_( dz );
3756 }
3757 note |= NOTE_INCREASE_ZMAX ;
3758 }
3759
3760 inline void sn::decrease_zmin( double dz )
3761 {
3762 if(typecode == CSG_CONE)
3763 {
3764 decrease_zmin_cone( dz );
3765 }
3766 else
3767 {
3768 decrease_zmin_( dz );
3769 }
3770 note |= NOTE_DECREASE_ZMIN ;
3771 }
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790 inline void sn::increase_zmax_( double dz )
3791 {
3792 assert( dz > 0. );
3793 double _zmax = zmax();
3794 double new_zmax = _zmax + dz ;
3795
3796 std::cout
3797 << "sn::increase_zmax_"
3798 << " lvid " << lvid
3799 << " _zmax " << std::fixed << std::setw(7) << std::setprecision(2) << _zmax
3800 << " dz " << std::fixed << std::setw(7) << std::setprecision(2) << dz
3801 << " new_zmax " << std::fixed << std::setw(7) << std::setprecision(2) << new_zmax
3802 << std::endl
3803 ;
3804
3805 set_zmax(new_zmax);
3806 }
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825 inline void sn::decrease_zmin_( double dz )
3826 {
3827 assert( dz > 0. );
3828 double _zmin = zmin();
3829 double new_zmin = _zmin - dz ;
3830
3831 std::cout
3832 << "sn::decrease_zmin_"
3833 << " lvid " << lvid
3834 << " _zmin " << std::fixed << std::setw(7) << std::setprecision(2) << _zmin
3835 << " dz " << std::fixed << std::setw(7) << std::setprecision(2) << dz
3836 << " new_zmin " << std::fixed << std::setw(7) << std::setprecision(2) << new_zmin
3837 << std::endl
3838 ;
3839
3840 set_zmin(new_zmin);
3841 }
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
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
3909 inline void sn::increase_zmax_cone( double dz )
3910 {
3911 double r1 = param->value(0) ;
3912 double z1 = param->value(1) ;
3913 double r2 = param->value(2) ;
3914 double z2 = param->value(3) ;
3915
3916 double new_z2 = z2 + dz ;
3917 double new_r2 = r1 + (r2 - r1)*( new_z2 - z1 )/(z2 - z1) ;
3918
3919 std::cout
3920 << "sn::increase_zmax_cone"
3921 << " lvid " << lvid
3922 << " z2 " << z2
3923 << " r2 " << r2
3924 << " dz " << dz
3925 << " new_z2 " << new_z2
3926 << " new_r2 " << new_r2
3927 << std::endl
3928 ;
3929
3930 set_zmax(new_z2);
3931 set_rperp_at_zmax(new_r2 < 0. ? 0. : new_r2);
3932 }
3933
3934
3935 inline void sn::decrease_zmin_cone( double dz )
3936 {
3937 double r1 = param->value(0) ;
3938 double z1 = param->value(1) ;
3939 double r2 = param->value(2) ;
3940 double z2 = param->value(3) ;
3941
3942 double new_z1 = z1 - dz ;
3943 double new_r1 = r2 + (r2 - r1)*(new_z1 - z2) /(z2 - z1 ) ;
3944
3945 std::cout
3946 << "sn::decrease_zmin_cone"
3947 << " lvid " << lvid
3948 << " z1 " << z1
3949 << " r1 " << r1
3950 << " dz " << dz
3951 << " new_z1 " << new_z1
3952 << " new_r1 " << new_r1
3953 << std::endl
3954 ;
3955
3956 set_zmin(new_z1);
3957 set_rperp_at_zmin(new_r1 < 0. ? 0. : new_r1);
3958
3959 }
3960
3961
3962
3963
3964
3965
3966
3967 inline double sn::zmin() const
3968 {
3969 assert( can_znudge() );
3970 double v = 0. ;
3971 switch(typecode)
3972 {
3973 case CSG_CYLINDER: v = param->value(4) ; break ;
3974 case CSG_ZSPHERE: v = param->value(4) ; break ;
3975 case CSG_CONE: v = param->value(1) ; break ;
3976 }
3977 return v ;
3978 }
3979
3980 inline void sn::set_zmin(double zmin_)
3981 {
3982 assert( can_znudge() );
3983 switch(typecode)
3984 {
3985 case CSG_CYLINDER: param->set_value(4, zmin_) ; break ;
3986 case CSG_ZSPHERE: param->set_value(4, zmin_) ; break ;
3987 case CSG_CONE: param->set_value(1, zmin_) ; break ;
3988 }
3989 }
3990
3991 inline double sn::zmax() const
3992 {
3993 assert( can_znudge() );
3994 double v = 0. ;
3995 switch(typecode)
3996 {
3997 case CSG_CYLINDER: v = param->value(5) ; break ;
3998 case CSG_ZSPHERE: v = param->value(5) ; break ;
3999 case CSG_CONE: v = param->value(3) ; break ;
4000 }
4001 return v ;
4002 }
4003 inline void sn::set_zmax(double zmax_)
4004 {
4005 assert( can_znudge() );
4006 switch(typecode)
4007 {
4008 case CSG_CYLINDER: param->set_value(5, zmax_) ; break ;
4009 case CSG_ZSPHERE: param->set_value(5, zmax_) ; break ;
4010 case CSG_CONE: param->set_value(3, zmax_) ; break ;
4011 }
4012 }
4013
4014 inline double sn::rperp_at_zmax() const
4015 {
4016 assert( can_znudge() );
4017 double v = 0. ;
4018 switch(typecode)
4019 {
4020 case CSG_CYLINDER: v = param->value(3) ; break ;
4021 case CSG_ZSPHERE: v = rperp_at_zmax_zsphere() ; break ;
4022 case CSG_CONE: v = param->value(2) ; break ;
4023 }
4024 return v ;
4025 }
4026
4027 inline void sn::set_rperp_at_zmax(double rperp_) const
4028 {
4029 assert( can_znudge() );
4030 switch(typecode)
4031 {
4032 case CSG_CYLINDER: param->set_value(3, rperp_) ; break ;
4033 case CSG_CONE: param->set_value(2, rperp_) ; break ;
4034 }
4035 }
4036
4037 inline double sn::rperp_at_zmin() const
4038 {
4039 assert( can_znudge() );
4040 double v = 0. ;
4041 switch(typecode)
4042 {
4043 case CSG_CYLINDER: v = param->value(3) ; break ;
4044 case CSG_ZSPHERE: v = rperp_at_zmin_zsphere() ; break ;
4045 case CSG_CONE: v = param->value(0) ; break ;
4046 }
4047 return v ;
4048 }
4049
4050
4051
4052
4053
4054 inline void sn::set_rperp_at_zmin(double rperp_) const
4055 {
4056 assert( can_znudge() );
4057 switch(typecode)
4058 {
4059 case CSG_CYLINDER: param->set_value(3, rperp_) ; break ;
4060 case CSG_CONE: param->set_value(0, rperp_) ; break ;
4061 }
4062 }
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086 inline double sn::Sphere_RPerp_At_Z(double r, double z)
4087 {
4088 assert( std::abs(z) <= r );
4089 return sqrt(r*r - z*z ) ;
4090 }
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110 inline double sn::rperp_at_zmin_zsphere() const
4111 {
4112 double r = radius_sphere() ;
4113 double z = zmin();
4114 double p = Sphere_RPerp_At_Z( r, z );
4115 return p ;
4116 }
4117 inline double sn::rperp_at_zmax_zsphere() const
4118 {
4119 double r = radius_sphere() ;
4120 double z = zmax();
4121 double p = Sphere_RPerp_At_Z( r, z );
4122 return p ;
4123 }
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141 inline std::string sn::ZDesc(const std::vector<sn*>& prims)
4142 {
4143 int num_prim = prims.size() ;
4144 std::stringstream ss ;
4145 ss << "sn::ZDesc" ;
4146 ss << " prims(" ;
4147 for(int i=0 ; i < num_prim ; i++) ss << prims[i]->index() << " " ;
4148 ss << ") " ;
4149 ss << std::endl ;
4150
4151 for(int i=0 ; i < num_prim ; i++)
4152 {
4153 sn* a = prims[i];
4154 ss << " idx " << std::setw(3) << a->index()
4155 << " tag " << std::setw(3) << a->tag()
4156 << " zmin " << std::setw(10) << a->zmin()
4157 << " zmax " << std::setw(10) << a->zmax()
4158 << " rperp_at_zmin " << std::setw(10) << a->rperp_at_zmin()
4159 << " rperp_at_zmax " << std::setw(10) << a->rperp_at_zmax()
4160 << std::endl
4161 ;
4162 }
4163 std::string str = ss.str();
4164 return str ;
4165 }
4166
4167
4168 inline void sn::getParam_(double& p0, double& p1, double& p2, double& p3, double& p4, double& p5 ) const
4169 {
4170 const double* d = param ? param->data() : nullptr ;
4171 p0 = d ? d[0] : 0. ;
4172 p1 = d ? d[1] : 0. ;
4173 p2 = d ? d[2] : 0. ;
4174 p3 = d ? d[3] : 0. ;
4175 p4 = d ? d[4] : 0. ;
4176 p5 = d ? d[5] : 0. ;
4177 }
4178 inline const double* sn::getParam() const { return param ? param->data() : nullptr ; }
4179 inline const double* sn::getAABB() const { return aabb ? aabb->data() : nullptr ; }
4180
4181 inline bool sn::hasAABB() const
4182 {
4183 const double* aabb = getAABB();
4184 return aabb != nullptr && !s_bb::AllZero(aabb) ;
4185 }
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205 inline sn* sn::Collection(std::vector<sn*>& prims )
4206 {
4207 sn* n = nullptr ;
4208 switch(VERSION)
4209 {
4210 case 0: n = UnionTree(prims) ; break ;
4211 case 1: n = Contiguous(prims) ; break ;
4212 }
4213 return n ;
4214 }
4215
4216 inline sn* sn::UnionTree(std::vector<sn*>& prims )
4217 {
4218
4219 sn* n = BuildCommonTypeTree_Unbalanced(prims, CSG_UNION );
4220 return n ;
4221 }
4222 inline sn* sn::Contiguous(std::vector<sn*>& prims )
4223 {
4224 sn* n = Compound( prims, CSG_CONTIGUOUS );
4225 return n ;
4226 }
4227 inline sn* sn::Discontiguous(std::vector<sn*>& prims )
4228 {
4229 sn* n = Compound( prims, CSG_DISCONTIGUOUS );
4230 return n ;
4231 }
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242 inline sn* sn::Compound(std::vector<sn*>& prims, int typecode_ )
4243 {
4244 assert( typecode_ == CSG_CONTIGUOUS || typecode_ == CSG_DISCONTIGUOUS );
4245
4246 int num_prim = prims.size();
4247 assert( num_prim > 0 );
4248
4249 sn* nd = Create( typecode_ );
4250
4251 for(int i=0 ; i < num_prim ; i++)
4252 {
4253 sn* pr = prims[i] ;
4254 #ifdef WITH_CHILD
4255 nd->add_child(pr) ;
4256 #else
4257 assert(0 && "sn::Compound requires WITH_CHILD " );
4258 assert(num_prim == 2 );
4259 if(i==0) nd->set_left(pr, false) ;
4260 if(i==1) nd->set_right(pr, false) ;
4261 #endif
4262 }
4263 return nd ;
4264 }
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292 inline sn* sn::Buggy_CommonOperatorTree( std::vector<sn*>& leaves, int op )
4293 {
4294 int num_leaves = leaves.size();
4295 sn* root = nullptr ;
4296 if( num_leaves == 1 )
4297 {
4298 root = leaves[0] ;
4299 }
4300 else
4301 {
4302 root = ZeroTree(num_leaves, op );
4303
4304 if(level() > 0) std::cout
4305 << "sn::CommonOperatorTree after ZeroTree"
4306 << " num_leaves " << num_leaves
4307 << " level " << level()
4308 << std::endl
4309 ;
4310 if(level() > 1) std::cout << root->render(5) ;
4311
4312 root->populate_leaves(leaves);
4313
4314 if(level() > 0) std::cout
4315 << "sn::CommonOperatorTree after populate_leaves"
4316 << " num_leaves " << num_leaves
4317 << " level " << level()
4318 << std::endl
4319 ;
4320 if(level() > 1) std::cout << root->render(5) ;
4321
4322 root->prune();
4323
4324 if(level() > 0) std::cout
4325 << "sn::CommonOperatorTree after prun"
4326 << " num_leaves " << num_leaves
4327 << " level " << level()
4328 << std::endl
4329 ;
4330 if(level() > 1) std::cout << root->render(5) ;
4331 }
4332 return root ;
4333 }
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377 inline sn* sn::BuildCommonTypeTree_Unbalanced( const std::vector<sn*>& leaves, int typecode )
4378 {
4379 int num_leaves = leaves.size() ;
4380 int num_leaves_placed = 0 ;
4381 if(num_leaves == 0) return nullptr ;
4382
4383 sn* root = leaves[num_leaves_placed] ;
4384 num_leaves_placed += 1 ;
4385
4386 while( num_leaves_placed < num_leaves )
4387 {
4388 root = Create(typecode, root, leaves[num_leaves_placed]);
4389 num_leaves_placed += 1 ;
4390 }
4391 return root ;
4392 }
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404 inline void sn::GetLVListnodes( std::vector<const sn*>& lns, int lvid )
4405 {
4406 std::vector<const sn*> nds ;
4407 GetLVNodes_(nds, lvid );
4408
4409 int num_nd = nds.size();
4410 for(int i=0 ; i < num_nd ; i++)
4411 {
4412 const sn* n = nds[i];
4413 if(n->is_listnode()) lns.push_back(n) ;
4414 }
4415 }
4416
4417 inline int sn::GetChildTotal( const std::vector<const sn*>& nds )
4418 {
4419 int child_total = 0 ;
4420 int num_nd = nds.size();
4421 for(int i=0 ; i < num_nd ; i++)
4422 {
4423 const sn* n = nds[i];
4424 child_total += ( n ? n->num_child() : 0 ) ;
4425 }
4426 return child_total ;
4427 }
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438 struct sn_find_lvid
4439 {
4440 int lvid ;
4441 sn_find_lvid(int q_lvid) : lvid(q_lvid) {}
4442 bool operator()(const sn* n){ return lvid == n->lvid ; }
4443 };
4444
4445 inline void sn::GetLVNodes( std::vector<sn*>& nds, int lvid )
4446 {
4447 sn_find_lvid flv(lvid);
4448 pool->find(nds, flv );
4449 }
4450
4451
4452 inline void sn::GetLVNodes_( std::vector<const sn*>& nds, int lvid )
4453 {
4454 sn_find_lvid flv(lvid);
4455 pool->find_(nds, flv );
4456 }
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472 inline void sn::getLVNodes( std::vector<sn*>& nds ) const
4473 {
4474 GetLVNodes(nds, lvid );
4475 assert( Includes(nds, const_cast<sn*>(this) ) );
4476 }
4477
4478 inline bool sn::Includes( const std::vector<sn*>& nds, sn* nd )
4479 {
4480 return std::find(nds.begin(), nds.end(), nd ) != nds.end() ;
4481 }
4482
4483 inline sn* sn::Get(int idx)
4484 {
4485 return pool->getbyidx(idx) ;
4486 }
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497 struct sn_find_lvid_root
4498 {
4499 int lvid ;
4500 sn_find_lvid_root(int q_lvid) : lvid(q_lvid) {}
4501 bool operator()(const sn* n){ return lvid == n->lvid && n->is_root() ; }
4502 };
4503
4504
4505 inline void sn::FindLVRootNodes( std::vector<sn*>& nds, int lvid )
4506 {
4507 sn_find_lvid_root flvr(lvid);
4508 pool->find(nds, flvr );
4509 }
4510
4511
4512 inline sn* sn::GetLVRoot( int lvid )
4513 {
4514 std::vector<sn*> nds ;
4515 FindLVRootNodes( nds, lvid );
4516
4517 int count = nds.size() ;
4518 bool expect = count == 0 || count == 1 ;
4519
4520 const char* _DUMP = "sn__GetLVRoot_DUMP" ;
4521 bool DUMP = ssys::getenvbool(_DUMP) ;
4522 if(DUMP || !expect) std::cout
4523 << _DUMP << ":" << ( DUMP ? "YES" : "NO " ) << "\n"
4524 << "Desc(nds)\n"
4525 << Desc(nds)
4526 << "\n"
4527 << " nds.size " << count
4528 << " expect " << ( expect ? "YES" : "NO " )
4529 << "\n"
4530 ;
4531
4532 assert(expect);
4533 return count == 1 ? nds[0] : nullptr ;
4534 }
4535
4536
4537
4538 inline std::string sn::rbrief() const
4539 {
4540 std::stringstream ss ;
4541 ss << "sn::rbrief" << std::endl ;
4542
4543 rbrief_r(ss, 0) ;
4544 std::string str = ss.str();
4545 return str ;
4546 }
4547
4548 inline void sn::rbrief_r(std::ostream& os, int d) const
4549 {
4550 os << std::setw(3) << d << " : " << brief() << std::endl ;
4551 for(int i=0 ; i < num_child() ; i++) get_child(i)->rbrief_r(os, d+1) ;
4552 }
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564 inline bool sn::has_type(const std::vector<OpticksCSG_t>& types) const
4565 {
4566 return std::find( types.begin(), types.end(), typecode ) != types.end() ;
4567 }
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577 template<typename ... Args>
4578 inline void sn::typenodes_(std::vector<const sn*>& nds, Args ... tcs ) const
4579 {
4580 std::vector<OpticksCSG_t> types = {tcs ...};
4581 typenodes_r_(nds, types, 0 );
4582 }
4583
4584
4585 template SYSRAP_API void sn::typenodes_(std::vector<const sn*>& nds, OpticksCSG_t ) const ;
4586 template SYSRAP_API void sn::typenodes_(std::vector<const sn*>& nds, OpticksCSG_t, OpticksCSG_t ) const ;
4587 template SYSRAP_API void sn::typenodes_(std::vector<const sn*>& nds, OpticksCSG_t, OpticksCSG_t, OpticksCSG_t ) const ;
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597 inline void sn::typenodes_r_(std::vector<const sn*>& nds, const std::vector<OpticksCSG_t>& types, int d) const
4598 {
4599 if(has_type(types)) nds.push_back(this);
4600 for(int i=0 ; i < num_child() ; i++) get_child(i)->typenodes_r_(nds, types, d+1 ) ;
4601 }
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624 inline int sn::max_binary_depth() const
4625 {
4626 return max_binary_depth_r(0) ;
4627 }
4628 inline int sn::max_binary_depth_r(int d) const
4629 {
4630 int mx = d ;
4631 if( is_listnode() == false )
4632 {
4633 int nc = num_child() ;
4634 if( nc > 0 ) assert( nc == 2 ) ;
4635 for(int i=0 ; i < nc ; i++)
4636 {
4637 sn* ch = get_child(i) ;
4638 mx = std::max( mx, ch->max_binary_depth_r(d + 1) ) ;
4639 }
4640 }
4641 return mx ;
4642 }
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658 inline uint64_t sn::getLVBinNode() const
4659 {
4660 int h = max_binary_depth();
4661 uint64_t n = st::complete_binary_tree_nodes( h );
4662 if(false) std::cout
4663 << "sn::getLVBinNode"
4664 << " h " << h
4665 << " n " << n
4666 << "\n"
4667 ;
4668 return n ;
4669 }
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683 inline uint64_t sn::getLVSubNode() const
4684 {
4685 int constituents = 0 ;
4686 std::vector<const sn*> subs ;
4687 typenodes_(subs, CSG_CONTIGUOUS, CSG_DISCONTIGUOUS, CSG_OVERLAP );
4688 int nsub = subs.size();
4689 for(int i=0 ; i < nsub ; i++)
4690 {
4691 const sn* nd = subs[i] ;
4692 assert( nd->typecode == CSG_CONTIGUOUS || nd->typecode == CSG_DISCONTIGUOUS );
4693 constituents += nd->num_child() ;
4694 }
4695 return constituents ;
4696 }
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709 inline uint64_t sn::getLVNumNode() const
4710 {
4711 uint64_t bn = getLVBinNode() ;
4712 uint64_t sn = getLVSubNode() ;
4713 return bn + sn ;
4714 }
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731 inline void sn::GetLVNodesComplete(std::vector<const sn*>& nds, int lvid)
4732 {
4733 const sn* root = GetLVRoot(lvid);
4734 assert(root);
4735 root->getLVNodesComplete(nds);
4736
4737 if(level() > 0 && nds.size() > 8 )
4738 {
4739 std::cout
4740 << "sn::GetLVNodesComplete"
4741 << " lvid " << lvid
4742 << " level " << level()
4743 << std::endl
4744 << root->rbrief()
4745 << std::endl
4746 << root->render(SUBDEPTH)
4747 ;
4748 }
4749 }
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767 inline void sn::getLVNodesComplete(std::vector<const sn*>& nds) const
4768 {
4769 uint64_t bn = getLVBinNode();
4770 uint64_t ns = getLVSubNode();
4771 uint64_t numParts = bn + ns ;
4772
4773
4774 nds.resize(bn);
4775
4776 if(false) std::cout
4777 << "sn::getLVNodesComplete"
4778 << " bn " << bn
4779 << " ns " << ns
4780 << " numParts " << numParts
4781 << "\n"
4782 ;
4783
4784
4785
4786
4787 GetLVNodesComplete_r( nds, this, 0 );
4788 }
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801 inline void sn::GetLVNodesComplete_r(std::vector<const sn*>& nds, const sn* nd, int idx)
4802 {
4803 assert( idx < int(nds.size()) );
4804 nds[idx] = nd ;
4805
4806 int nc = nd->num_child() ;
4807
4808 if( nc > 0 && nd->is_listnode() == false )
4809 {
4810 assert( nc == 2 ) ;
4811 for(int i=0 ; i < nc ; i++)
4812 {
4813 const sn* child = nd->get_child(i) ;
4814
4815 int cidx = 2*idx + 1 + i ;
4816
4817 GetLVNodesComplete_r(nds, child, cidx );
4818 }
4819 }
4820 }
4821
4822
4823
4824 inline void sn::SelectListNode(std::vector<const sn*>& lns, const std::vector<const sn*>& nds)
4825 {
4826 for(unsigned i=0 ; i < nds.size() ; i++)
4827 {
4828 const sn* nd = nds[i] ;
4829 if(nd->is_listnode()) lns.push_back(nd);
4830 }
4831 }
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847 inline void sn::ancestors(std::vector<const sn*>& nds) const
4848 {
4849 const sn* nd = this ;
4850 while( nd && nd->parent )
4851 {
4852 nds.push_back(nd->parent);
4853 nd = nd->parent ;
4854 }
4855 std::reverse( nds.begin(), nds.end() );
4856 }
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870 inline void sn::connectedtype_ancestors(std::vector<const sn*>& nds ) const
4871 {
4872 if(!parent) return ;
4873 ConnectedTypeAncestors( parent, nds, parent->typecode );
4874 }
4875 inline void sn::ConnectedTypeAncestors(const sn* n, std::vector<const sn*>& nds, int q_typecode)
4876 {
4877 while(n && n->typecode == q_typecode)
4878 {
4879 nds.push_back(n);
4880 n = n->parent ;
4881 }
4882 }
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896 inline void sn::collect_progeny( std::vector<const sn*>& progeny, int exclude_typecode ) const
4897 {
4898 for(int i=0 ; i < num_child() ; i++)
4899 {
4900 const sn* ch = get_child(i);
4901 CollectProgeny_r(ch, progeny, exclude_typecode );
4902 }
4903 }
4904 inline void sn::CollectProgeny_r( const sn* n, std::vector<const sn*>& progeny, int exclude_typecode )
4905 {
4906 if(n->typecode != exclude_typecode || exclude_typecode == CSG_ZERO)
4907 {
4908 if(std::find(progeny.begin(), progeny.end(), n) == progeny.end()) progeny.push_back(n);
4909 }
4910
4911 for(int i=0 ; i < n->num_child() ; i++)
4912 {
4913 const sn* ch = n->get_child(i);
4914 CollectProgeny_r(ch, progeny, exclude_typecode );
4915 }
4916 }
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934 inline void sn::collect_prim( std::vector<const sn*>& prim ) const
4935 {
4936 collect_prim_r(prim, 0);
4937 }
4938 inline void sn::collect_prim_r( std::vector<const sn*>& prim, int d ) const
4939 {
4940 if(is_primitive()) prim.push_back(this);
4941 for(int i=0 ; i < num_child() ; i++) get_child(i)->collect_prim_r(prim, d+1) ;
4942 }
4943
4944
4945 inline bool sn::has_note( int q_note ) const
4946 {
4947 return ( note & q_note ) != 0 ;
4948 }
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960 inline void sn::collect_prim_note( std::vector<sn*>& prim, int q_note )
4961 {
4962 collect_prim_note_r(prim, q_note, 0);
4963 }
4964 inline void sn::collect_prim_note_r( std::vector<sn*>& prim, int q_note, int d )
4965 {
4966 if(is_primitive() && has_note(q_note)) prim.push_back(this);
4967 for(int i=0 ; i < num_child() ; i++) get_child(i)->collect_prim_note_r(prim, q_note, d+1) ;
4968 }
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016 inline sn* sn::find_joint_to_candidate_listnode(std::vector<sn*>& prim, int q_note )
5017 {
5018 sn* j = find_joint_to_candidate_listnode_r(0, prim, q_note );
5019 return j ;
5020 }
5021
5022 inline sn* sn::find_joint_to_candidate_listnode_r( int d, std::vector<sn*>& prim, int q_note )
5023 {
5024 if( d == 0 )
5025 {
5026 prim.clear();
5027 collect_prim_note(prim, q_note);
5028 }
5029 if(prim.size()==0) return nullptr ;
5030
5031 sn* joint = nullptr ;
5032 if(num_child() != 2) return nullptr ;
5033
5034
5035 std::vector<sn*> l_prim ;
5036 std::vector<sn*> r_prim ;
5037 get_child(0)->collect_prim_note(l_prim, q_note);
5038 get_child(1)->collect_prim_note(r_prim, q_note);
5039
5040 if(r_prim.size() == 1 && l_prim.size() == 0 )
5041 {
5042 joint = this ;
5043 }
5044 else
5045 {
5046 for(int i=0 ; i < num_child() ; i++)
5047 {
5048 joint = get_child(i)->find_joint_to_candidate_listnode_r(d+1, prim, q_note ) ;
5049 if(joint) break ;
5050 }
5051 }
5052 return joint ;
5053 }
5054
5055 inline bool sn::has_candidate_listnode(int q_note)
5056 {
5057 std::vector<sn*> prim ;
5058 sn* j = find_joint_to_candidate_listnode(prim, q_note);
5059 return j != nullptr && prim.size() > 0 ;
5060 }
5061
5062 inline bool sn::has_candidate_listnode_discontiguous(){ return has_candidate_listnode( HINT_LISTNODE_PRIM_DISCONTIGUOUS ) ; }
5063 inline bool sn::has_candidate_listnode_contiguous(){ return has_candidate_listnode( HINT_LISTNODE_PRIM_CONTIGUOUS ) ; }
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129 inline sn* sn::CreateSmallerTreeWithListNode(sn* root0, int q_note )
5130 {
5131 std::cerr << "[sn::CreateSmallerTreeWithListNode\n" ;
5132
5133 std::vector<sn*> prim0 ;
5134 sn* j0 = root0->find_joint_to_candidate_listnode(prim0, q_note);
5135 if(j0 == nullptr) return nullptr ;
5136
5137 std::vector<sn*> prim1 ;
5138 sn::DeepCopy(prim1, prim0);
5139
5140 sn* ln = sn::Compound( prim1, TypeFromNote(q_note) );
5141
5142 sn* j1 = j0->deepcopy();
5143
5144 j1->set_right( ln, false );
5145
5146
5147
5148
5149
5150 std::cerr << "]sn::CreateSmallerTreeWithListNode\n" ;
5151 return j1 ;
5152 }
5153
5154 inline sn* sn::CreateSmallerTreeWithListNode_discontiguous(sn* root0)
5155 {
5156 return CreateSmallerTreeWithListNode( root0, HINT_LISTNODE_PRIM_DISCONTIGUOUS ) ;
5157 }
5158 inline sn* sn::CreateSmallerTreeWithListNode_contiguous(sn* root0)
5159 {
5160 return CreateSmallerTreeWithListNode( root0, HINT_LISTNODE_PRIM_CONTIGUOUS ) ;
5161 }
5162
5163 inline int sn::TypeFromNote(int q_note)
5164 {
5165 int type = CSG_ZERO ;
5166 switch(q_note)
5167 {
5168 case HINT_LISTNODE_PRIM_DISCONTIGUOUS: type = CSG_DISCONTIGUOUS ; break ;
5169 case HINT_LISTNODE_PRIM_CONTIGUOUS: type = CSG_CONTIGUOUS ; break ;
5170 }
5171 assert( type != CSG_ZERO ) ;
5172 return type ;
5173 }
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196 inline void sn::collect_monogroup( std::vector<const sn*>& monogroup ) const
5197 {
5198 if(!parent) return ;
5199
5200 std::vector<const sn*> connectedtype ;
5201 connectedtype_ancestors(connectedtype);
5202 int num_connectedtype = connectedtype.size() ;
5203
5204 int exclude_typecode = parent->typecode ;
5205
5206 for(int i=0 ; i < num_connectedtype ; i++)
5207 {
5208 const sn* ca = connectedtype[i];
5209 ca->collect_progeny( monogroup, exclude_typecode );
5210 }
5211 }
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229 inline bool sn::AreFromSameMonogroup(const sn* a, const sn* b, int op)
5230 {
5231 if(!a->parent || !b->parent || a->parent->typecode != op || b->parent->typecode != op) return false ;
5232
5233 std::vector<const sn*> monogroup ;
5234 a->collect_monogroup(monogroup);
5235
5236 return std::find(monogroup.begin(), monogroup.end(), b ) != monogroup.end() ;
5237 }
5238
5239
5240 inline bool sn::AreFromSameUnion(const sn* a, const sn* b)
5241 {
5242 return AreFromSameMonogroup(a,b, CSG_UNION );
5243 }
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257 inline void sn::NodeTransformProduct(
5258 int idx,
5259 glm::tmat4x4<double>& t,
5260 glm::tmat4x4<double>& v,
5261 bool reverse,
5262 std::ostream* out,
5263 VTR* t_stack)
5264 {
5265 sn* nd = Get(idx);
5266 assert(nd);
5267 nd->getNodeTransformProduct(t,v,reverse,out,t_stack) ;
5268 }
5269
5270 inline std::string sn::DescNodeTransformProduct(
5271 int idx,
5272 glm::tmat4x4<double>& t,
5273 glm::tmat4x4<double>& v,
5274 bool reverse )
5275 {
5276 std::stringstream ss ;
5277 ss << "sn::DescNodeTransformProduct" << std::endl ;
5278 NodeTransformProduct( idx, t, v, reverse, &ss, nullptr );
5279 std::string str = ss.str();
5280 return str ;
5281 }
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303 inline void sn::getNodeTransformProduct(
5304 glm::tmat4x4<double>& t,
5305 glm::tmat4x4<double>& v,
5306 bool reverse,
5307 std::ostream* out,
5308 VTR* t_stack ) const
5309 {
5310 if(out) *out << "\nsn::getNodeTransformProduct.HEAD\n" ;
5311
5312 std::vector<const sn*> nds ;
5313 ancestors(nds);
5314 nds.push_back(this);
5315
5316 int num_nds = nds.size();
5317
5318 if(out)
5319 {
5320 for(int i=0 ; i < num_nds ; i++) *out << "sn::getNodeTransformProduct.nd[" << i << "] " << nds[i]->desc() << "\n" ;
5321 *out
5322 << std::endl
5323 << "sn::getNodeTransformProduct"
5324 << " idx " << idx()
5325 << " reverse " << reverse
5326 << " num_nds " << num_nds
5327 << std::endl
5328 ;
5329 }
5330
5331 glm::tmat4x4<double> tp(1.);
5332 glm::tmat4x4<double> vp(1.);
5333
5334 for(int i=0 ; i < num_nds ; i++ )
5335 {
5336 int j = num_nds - 1 - i ;
5337 const sn* ii = nds[reverse ? j : i] ;
5338 const sn* jj = nds[reverse ? i : j] ;
5339
5340 int itc = ii->typecode ;
5341 int jtc = jj->typecode ;
5342
5343 const s_tv* ixf = ii->xform ;
5344 const s_tv* jxf = jj->xform ;
5345
5346 if(out)
5347 {
5348 *out
5349 << " i " << i
5350 << " j " << j
5351 << " ii.idx " << ii->idx()
5352 << " jj.idx " << jj->idx()
5353 << " ixf " << ( ixf ? "Y" : "N" )
5354 << " jxf " << ( jxf ? "Y" : "N" )
5355 << " itc " << itc
5356 << " jtc " << jtc
5357 << std::endl
5358 ;
5359
5360 if(ixf) *out << stra<double>::Desc( ixf->t, ixf->v, "(ixf.t)", "(ixf.v)" ) << std::endl ;
5361 if(jxf) *out << stra<double>::Desc( jxf->t, jxf->v, "(jxf.t)", "(jxf.v)" ) << std::endl ;
5362 }
5363
5364 if(t_stack && ixf) t_stack->push_back(ixf->t);
5365 if(ixf) tp *= ixf->t ;
5366 if(jxf) vp *= jxf->v ;
5367
5368 }
5369 memcpy( glm::value_ptr(t), glm::value_ptr(tp), sizeof(glm::tmat4x4<double>) );
5370 memcpy( glm::value_ptr(v), glm::value_ptr(vp), sizeof(glm::tmat4x4<double>) );
5371
5372 if(out) *out << stra<double>::Desc( tp, vp , "tp", "vp" ) << std::endl ;
5373 if(out) *out << "\nsn::getNodeTransformProduct.TAIL\n" ;
5374 }
5375
5376 inline std::string sn::desc_getNodeTransformProduct(
5377 glm::tmat4x4<double>& t,
5378 glm::tmat4x4<double>& v,
5379 bool reverse) const
5380 {
5381 std::stringstream ss ;
5382 ss << "sn::desc_getNodeTransformProduct" << std::endl ;
5383 getNodeTransformProduct( t, v, reverse, &ss, nullptr );
5384 std::string str = ss.str();
5385 return str ;
5386 }
5387
5388
5389
5390 inline double sn::radius_sphere() const
5391 {
5392 double cx, cy, cz, r, z1, z2 ;
5393 getParam_(cx, cy, cz, r, z1, z2 );
5394 assert( cx == 0. && cy == 0. && cz == 0. ) ;
5395 return r ;
5396 }
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413 inline void sn::setAABB_LeafFrame()
5414 {
5415 if(typecode == CSG_SPHERE)
5416 {
5417 double cx, cy, cz, r, a, b ;
5418 getParam_(cx, cy, cz, r, a, b );
5419 assert( cx == 0. && cy == 0. && cz == 0. );
5420 assert( a == 0. && b == 0. );
5421 setBB( -r, -r, -r, r, r, r );
5422 }
5423 else if(typecode == CSG_ZSPHERE)
5424 {
5425 double cx, cy, cz, r, z1, z2 ;
5426 getParam_(cx, cy, cz, r, z1, z2 );
5427 assert( cx == 0. && cy == 0. && cz == 0. ) ;
5428 assert( z1 == zmin());
5429 assert( z2 == zmax());
5430 assert( z2 > z1 );
5431 setBB( -r, -r, z1, r, r, z2 );
5432 }
5433 else if( typecode == CSG_CONE )
5434 {
5435 double r1, z1, r2, z2, a, b ;
5436 getParam_(r1, z1, r2, z2, a, b );
5437 assert( a == 0. && b == 0. );
5438 double rmax = fmaxf(r1, r2) ;
5439 setBB( -rmax, -rmax, z1, rmax, rmax, z2 );
5440 }
5441 else if( typecode == CSG_BOX3 )
5442 {
5443 double fx, fy, fz, a, b, c ;
5444 getParam_(fx, fy, fz, a, b, c );
5445 assert( a == 0. && b == 0. && c == 0. );
5446 setBB( -fx*0.5 , -fy*0.5, -fz*0.5, fx*0.5 , fy*0.5, fz*0.5 );
5447 }
5448 else if( typecode == CSG_CYLINDER || typecode == CSG_OLDCYLINDER )
5449 {
5450 double px, py, a, radius, z1, z2 ;
5451 getParam_(px, py, a, radius, z1, z2 ) ;
5452 assert( px == 0. && py == 0. && a == 0. );
5453 setBB( px-radius, py-radius, z1, px+radius, py+radius, z2 );
5454 }
5455 else if( typecode == CSG_CUTCYLINDER )
5456 {
5457 double R, dz, pz_nrm_x, pz_nrm_z, nz_nrm_x, nz_nrm_z ;
5458 getParam_( R, dz, pz_nrm_x, pz_nrm_z, nz_nrm_x, nz_nrm_z );
5459
5460 double pz_nrm_y = 0. ;
5461 double nz_nrm_y = 0. ;
5462
5463 double zmin = 0. ;
5464 double zmax = 0. ;
5465 CutCylinderZRange(zmin, zmax, R, dz, pz_nrm_x, pz_nrm_y, pz_nrm_z, nz_nrm_x, nz_nrm_y, nz_nrm_z );
5466
5467 setBB( -R, -R, zmin, +R, +R, zmax );
5468 }
5469 else if( typecode == CSG_DISC )
5470 {
5471 double px, py, ir, r, z1, z2 ;
5472 getParam_(px, py, ir, r, z1, z2);
5473 assert( px == 0. && py == 0. && ir == 0. );
5474 setBB( px - r , py - r , z1, px + r, py + r, z2 );
5475 }
5476 else if( typecode == CSG_HYPERBOLOID )
5477 {
5478 double r0, zf, z1, z2, a, b ;
5479 getParam_(r0, zf, z1, z2, a, b ) ;
5480 assert( a == 0. && b == 0. );
5481 assert( z1 < z2 );
5482 const double rr0 = r0*r0 ;
5483 const double z1s = z1/zf ;
5484 const double z2s = z2/zf ;
5485
5486 const double rr1 = rr0 * ( z1s*z1s + 1. ) ;
5487 const double rr2 = rr0 * ( z2s*z2s + 1. ) ;
5488 const double rmx = sqrtf(fmaxf( rr1, rr2 )) ;
5489
5490 setBB( -rmx, -rmx, z1, rmx, rmx, z2 );
5491 }
5492 else if( typecode == CSG_TORUS )
5493 {
5494 double rmin, rmax, rtor, startPhi_deg, deltaPhi_deg, zero ;
5495 getParam_(rmin, rmax, rtor, startPhi_deg, deltaPhi_deg, zero) ;
5496
5497 double rext = rtor+rmax ;
5498 double rint = rtor-rmax ;
5499 double startPhi = startPhi_deg/180.*M_PI ;
5500 double deltaPhi = deltaPhi_deg/180.*M_PI ;
5501 double2 pmin ;
5502 double2 pmax ;
5503 sgeomtools::DiskExtent(rint, rext, startPhi, deltaPhi, pmin, pmax );
5504
5505 setBB( pmin.x, pmin.y, -rmax, pmax.x, pmax.y, +rmax );
5506
5507 }
5508 else if( typecode == CSG_UNION || typecode == CSG_INTERSECTION || typecode == CSG_DIFFERENCE )
5509 {
5510 setBB( 0. );
5511 }
5512 else if( typecode == CSG_CONTIGUOUS || typecode == CSG_DISCONTIGUOUS )
5513 {
5514
5515
5516 setBB( 0. );
5517 }
5518 else if( typecode == CSG_NOTSUPPORTED )
5519 {
5520 setBB( 0. );
5521 }
5522 else if( typecode == CSG_ZERO )
5523 {
5524 setBB( UNBOUNDED_DEFAULT_EXTENT );
5525 }
5526 else if( typecode == CSG_PHICUT || typecode == CSG_HALFSPACE )
5527 {
5528
5529 setBB( 0. );
5530 }
5531 else if( typecode == CSG_THETACUT )
5532 {
5533 setBB( UNBOUNDED_DEFAULT_EXTENT );
5534 }
5535 else if( typecode == CSG_SEGMENT )
5536 {
5537 setBB( 0. );
5538
5539
5540 }
5541 else
5542 {
5543 std::cout
5544 << "sn::setAABB_LeafFrame : FATAL NOT IMPLEMENTED : "
5545 << " typecode " << typecode
5546 << " CSG::Name(typecode) " << CSG::Name(typecode)
5547 << std::endl
5548 ;
5549 assert(0);
5550 setBB( 0. );
5551 }
5552 }
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566 inline void sn::setAABB_LeafFrame_All()
5567 {
5568 std::vector<const sn*> prim ;
5569 collect_prim(prim);
5570 int num_prim = prim.size() ;
5571 for(int i=0 ; i < num_prim ; i++)
5572 {
5573 const sn* p = prim[i] ;
5574 sn* _p = const_cast<sn*>(p) ;
5575 _p->setAABB_LeafFrame() ;
5576 }
5577 }
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592 inline void sn::setAABB_TreeFrame_All()
5593 {
5594 std::vector<const sn*> prim ;
5595 collect_prim(prim);
5596 int num_prim = prim.size() ;
5597
5598 for(int i=0 ; i < num_prim ; i++)
5599 {
5600 const sn* p = prim[i] ;
5601 sn* _p = const_cast<sn*>(p) ;
5602 _p->setAABB_LeafFrame() ;
5603
5604 glm::tmat4x4<double> t(1.) ;
5605 glm::tmat4x4<double> v(1.) ;
5606
5607 bool reverse = false ;
5608 std::ostream* out = nullptr ;
5609 VTR* t_stack = nullptr ;
5610 p->getNodeTransformProduct(t, v, reverse, out, t_stack );
5611
5612 const double* pbb = _p->getBB_data() ;
5613 stra<double>::Transform_AABB_Inplace( const_cast<double*>(pbb), t );
5614 }
5615 }
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638 inline void sn::postconvert(int lvid)
5639 {
5640 set_lvid(lvid);
5641
5642 positivize() ;
5643
5644 setAABB_TreeFrame_All();
5645
5646 uncoincide();
5647
5648 setAABB_LeafFrame_All();
5649 }
5650
5651 struct sn_compare
5652 {
5653 std::function<double(const sn* p)>& fn ;
5654 bool ascending ;
5655
5656 sn_compare( std::function<double(const sn* p)>& fn_ , bool ascending_ )
5657 :
5658 fn(fn_),
5659 ascending(ascending_)
5660 {}
5661 bool operator()(const sn* a, const sn* b)
5662 {
5663 bool cmp = fn(a) < fn(b) ;
5664 return ascending ? cmp : !cmp ;
5665 }
5666 };
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678 template<typename N>
5679 inline void sn::OrderPrim( std::vector<N*>& prim, std::function<double(N* p)> fn, bool ascending )
5680 {
5681 sn_compare cmp(fn, ascending) ;
5682 std::sort( prim.begin(), prim.end(), cmp );
5683 }
5684
5685
5686 inline void sn::Transform_Leaf2Tree( glm::tvec3<double>& xyz, const sn* leaf, std::ostream* out )
5687 {
5688 glm::tvec4<double> pos0 ;
5689 pos0.x = xyz.x ;
5690 pos0.y = xyz.y ;
5691 pos0.z = xyz.z ;
5692 pos0.w = 1. ;
5693
5694 glm::tmat4x4<double> t(1.) ;
5695 glm::tmat4x4<double> v(1.) ;
5696 bool reverse = false ;
5697 VTR* t_stack = nullptr ;
5698 leaf->getNodeTransformProduct(t, v, reverse, nullptr, t_stack );
5699
5700 glm::tvec4<double> pos = t * pos0 ;
5701
5702 xyz.x = pos.x ;
5703 xyz.y = pos.y ;
5704 xyz.z = pos.z ;
5705
5706 if(out) *out
5707 << "sn::Transform_Leaf2Tree"
5708 << std::endl
5709 << " pos0 " << stra<double>::Desc(pos0)
5710 << std::endl
5711 << " pos " << stra<double>::Desc(pos)
5712 << std::endl
5713 ;
5714 }
5715
5716
5717 inline void sn::uncoincide()
5718 {
5719 int uncoincide_dump_lvid = ssys::getenvint("sn__uncoincide_dump_lvid", 107) ;
5720 bool dump = lvid == std::abs(uncoincide_dump_lvid) ;
5721 bool enable = true ;
5722
5723 std::stringstream ss ;
5724 if(dump) ss
5725 << "sn::uncoincide"
5726 << " sn__uncoincide_dump_lvid " << uncoincide_dump_lvid
5727 << " lvid " << lvid
5728 << std::endl
5729 ;
5730
5731 uncoincide_( enable, dump ? &ss : nullptr );
5732
5733 if( dump )
5734 {
5735 std::string str = ss.str() ;
5736 std::cout << str << std::endl ;
5737 }
5738 }
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748 inline void sn::uncoincide_(bool enable, std::ostream* out)
5749 {
5750 std::vector<const sn*> prim ;
5751 collect_prim(prim);
5752 int num_prim = prim.size() ;
5753
5754 bool ascending = true ;
5755 OrderPrim<const sn>(prim, AABB_ZAvg, ascending ) ;
5756
5757 if(out) *out
5758 << "sn::uncoincide_"
5759 << " lvid " << lvid
5760 << " num_prim " << num_prim
5761 << std::endl
5762 ;
5763
5764 for(int i=1 ; i < num_prim ; i++)
5765 {
5766 const sn* lower = prim[i-1] ;
5767 const sn* upper = prim[i] ;
5768 sn* _lower = const_cast<sn*>( lower );
5769 sn* _upper = const_cast<sn*>( upper );
5770 uncoincide_zminmax( i, _lower, _upper, enable, out );
5771 }
5772
5773 if(out) *out
5774 << "sn::uncoincide_"
5775 << " lvid " << lvid
5776 << " num_prim " << num_prim
5777 << " coincide " << coincide
5778 << std::endl
5779 ;
5780 }
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791 inline void sn::uncoincide_zminmax( int i, sn* lower, sn* upper, bool enable, std::ostream* out )
5792 {
5793 bool can_znudge = lower->can_znudge() && upper->can_znudge() ;
5794 bool same_union = AreFromSameUnion(lower, upper) ;
5795 double lower_zmax = lower->getBB_zmax() ;
5796 double upper_zmin = upper->getBB_zmin() ;
5797 bool z_minmax_coincide = std::abs( lower_zmax - upper_zmin ) < Z_EPSILON ;
5798 bool fixable_coincide = z_minmax_coincide && can_znudge && same_union ;
5799
5800 if(out && z_minmax_coincide) *out
5801 << "sn::uncoincide_zminmax"
5802 << " lvid " << lvid
5803 << " ("<< i-1 << "," << i << ") "
5804 << " lower_zmax " << lower_zmax
5805 << " upper_zmin " << upper_zmin
5806 << " lower_tag " << lower->tag()
5807 << " upper_tag " << upper->tag()
5808 << " can_znudge " << ( can_znudge ? "YES" : "NO " )
5809 << " same_union " << ( same_union ? "YES" : "NO " )
5810 << " z_minmax_coincide " << ( z_minmax_coincide ? "YES" : "NO " )
5811 << " fixable_coincide " << ( fixable_coincide ? "YES" : "NO " )
5812 << " enable " << ( enable ? "YES" : "NO " )
5813 << std::endl
5814 ;
5815
5816 if(!fixable_coincide) return ;
5817
5818 coincide += 1 ;
5819
5820 double upper_rperp_at_zmin = upper->rperp_at_zmin() ;
5821 double lower_rperp_at_zmax = lower->rperp_at_zmax() ;
5822
5823
5824 glm::tvec3<double> upper_pos( upper->rperp_at_zmin(), upper->rperp_at_zmin(), upper->zmin() );
5825 glm::tvec3<double> lower_pos( lower->rperp_at_zmax(), lower->rperp_at_zmax(), lower->zmax() );
5826
5827
5828 Transform_Leaf2Tree( upper_pos, upper, nullptr );
5829 Transform_Leaf2Tree( lower_pos, lower, nullptr );
5830
5831 bool upper_lower_pos_z_equal = std::abs( upper_pos.z - lower_pos.z) < Z_EPSILON ;
5832 bool rperp_equal = std::abs( lower_pos.x - upper_pos.x ) < Z_EPSILON ;
5833 bool upper_rperp_smaller = lower_pos.x > upper_pos.x ;
5834 bool upper_shape_smaller = upper->typecode == CSG_ZSPHERE && lower->typecode == CSG_CYLINDER ;
5835 bool upper_decrease_zmin = rperp_equal ? upper_shape_smaller : upper_rperp_smaller ;
5836
5837 double dz = 1. ;
5838 if( upper_decrease_zmin ) upper->decrease_zmin( dz );
5839 else lower->increase_zmax( dz );
5840
5841
5842 if(out) *out
5843 << "sn::uncoincide_zminmax"
5844 << " lvid " << lvid
5845 << " ("<< i-1 << "," << i << ") "
5846 << " lower_rperp_at_zmax " << lower_rperp_at_zmax
5847 << " upper_rperp_at_zmin " << upper_rperp_at_zmin
5848 << " (leaf frame) "
5849 << std::endl
5850 << " upper_pos " << stra<double>::Desc(upper_pos) << " (tree frame) "
5851 << std::endl
5852 << " lower_pos " << stra<double>::Desc(lower_pos) << " (tree frame) "
5853 << std::endl
5854 << " rperp_equal " << ( rperp_equal ? "YES" : "NO " )
5855 << " upper_rperp_smaller " << ( upper_rperp_smaller ? "YES" : "NO " )
5856 << " upper_shape_smaller " << ( upper_shape_smaller ? "YES" : "NO " )
5857 << " upper_decrease_zmin " << ( upper_decrease_zmin ? "YES" : "NO " )
5858 << " upper_lower_pos_z_equal " << ( upper_lower_pos_z_equal ? "YES" : "NO " )
5859 << std::endl
5860 << ( upper_decrease_zmin ?
5861 " upper->decrease_zmin( dz ) : expand upper down into bigger lower "
5862 :
5863 " lower->increase_zmax( dz ) : expand lower up into bigger upper "
5864 )
5865 << " coincide " << coincide
5866 << std::endl
5867 ;
5868
5869 assert( upper_lower_pos_z_equal && "EXPECTED upper_lower_pos_z_equal FOR COINCIDENT " );
5870
5871 }
5872
5873
5874