Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:28

0001 /*
0002  * Copyright (c) 2019 Opticks Team. All Rights Reserved.
0003  *
0004  * This file is part of Opticks
0005  * (see https://bitbucket.org/simoncblyth/opticks).
0006  *
0007  * Licensed under the Apache License, Version 2.0 (the "License");
0008  * you may not use this file except in compliance with the License.
0009  * You may obtain a copy of the License at
0010  *
0011  *   http://www.apache.org/licenses/LICENSE-2.0
0012  *
0013  * Unless required by applicable law or agreed to in writing, software
0014  * distributed under the License is distributed on an "AS IS" BASIS,
0015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016  * See the License for the specific language governing permissions and
0017  * limitations under the License.
0018  */
0019 
0020 #pragma once
0021 
0022 typedef enum {
0023     CSG_ZERO=0,
0024     CSG_OFFSET_LIST=4,
0025     CSG_OFFSET_LEAF=7,
0026 
0027     CSG_TREE=1,
0028         CSG_UNION=1,
0029         CSG_INTERSECTION=2,
0030         CSG_DIFFERENCE=3,
0031 
0032     CSG_NODE=11,
0033     CSG_LIST=11,
0034         CSG_CONTIGUOUS=11,
0035         CSG_DISCONTIGUOUS=12,
0036         CSG_OVERLAP=13,
0037 
0038     CSG_LEAF=101,
0039         CSG_SPHERE=101,
0040         CSG_BOX=102,
0041         CSG_ZSPHERE=103,
0042         CSG_TUBS=104,
0043         CSG_CYLINDER=105,
0044         CSG_SLAB=106,
0045         CSG_PLANE=107,
0046         CSG_CONE=108,
0047         CSG_EXBB=109,
0048         CSG_BOX3=110,
0049         CSG_TRAPEZOID=111,
0050         CSG_CONVEXPOLYHEDRON=112,
0051         CSG_DISC=113,
0052         CSG_SEGMENT=114,
0053         CSG_ELLIPSOID=115,
0054         CSG_TORUS=116,
0055         CSG_HYPERBOLOID=117,
0056         CSG_CUBIC=118,
0057         CSG_INFCYLINDER=119,
0058         CSG_OLDCYLINDER=120,
0059         CSG_PHICUT=121,
0060         CSG_THETACUT=122,
0061         CSG_OLDCONE=123,
0062         CSG_CUTCYLINDER=124,
0063         CSG_HALFSPACE=125,
0064         CSG_NOTSUPPORTED=126,
0065         CSG_UNDEFINED=127,
0066 
0067     CSG_OBSOLETE=1000,
0068         CSG_PARTLIST=1001,
0069         CSG_FLAGPARTLIST=1002,
0070         CSG_FLAGNODETREE=1003,
0071         CSG_FLAGINVISIBLE=1004,
0072         CSG_PMT=1005,
0073         CSG_ZLENS=1006,
0074         CSG_PRISM=1007,
0075         CSG_LAST=1008
0076 
0077 } OpticksCSG_t ;
0078 
0079 
0080 
0081 
0082 /*
0083 * keep CSG_SPHERE as 1st primitive
0084 * keep CSG_UNDEFINED as one beyond the last primitive
0085 * regenerate the derived python e-n-u-m-e-r-a-t-i-o-n classes with sysrap-csg-generate
0086 * CAUTION : the text of this header is parsed for the generation,
0087   some words are not allowed and avoid semi-colons
0088 
0089 
0090 TODO: stick these in a struct
0091 
0092 
0093 */
0094 
0095 #ifndef __CUDACC__
0096 
0097 #include <string>
0098 #include <sstream>
0099 #include <cstring>
0100 #include <cassert>
0101 
0102 #include <vector>
0103 #include <sstream>
0104 
0105 
0106 static const char* CSG_ZERO_          = "zero" ;
0107 
0108 
0109 //static const char* CSG_TREE_          = "tree" ;
0110 static const char* CSG_INTERSECTION_  = "intersection" ;
0111 static const char* CSG_UNION_         = "union" ;
0112 static const char* CSG_DIFFERENCE_    = "difference" ;
0113 
0114 //static const char* CSG_NODE_           = "node" ;
0115 static const char* CSG_CONTIGUOUS_     = "contiguous" ;
0116 static const char* CSG_DISCONTIGUOUS_  = "discontiguous" ;
0117 static const char* CSG_OVERLAP_        = "overlap" ;
0118 
0119 static const char* _CSG_CONTIGUOUS     = "CSG_CONTIGUOUS" ;
0120 static const char* _CSG_DISCONTIGUOUS  = "CSG_DISCONTIGUOUS" ;
0121 static const char* _CSG_OVERLAP        = "CSG_OVERLAP" ;
0122 static const char* _CSG_EXBB           = "CSG_EXBB" ;
0123 
0124 
0125 //static const char* CSG_LEAF_          = "leaf" ;
0126 static const char* CSG_SPHERE_        = "sphere" ;
0127 static const char* CSG_BOX_           = "box" ;
0128 static const char* CSG_ZSPHERE_       = "zsphere" ;
0129 static const char* CSG_TUBS_          = "tubs" ;
0130 static const char* CSG_CYLINDER_      = "cylinder" ;
0131 static const char* CSG_CUTCYLINDER_   = "cutcylinder" ;
0132 static const char* CSG_SLAB_          = "slab" ;
0133 static const char* CSG_PLANE_         = "plane" ;
0134 static const char* CSG_CONE_          = "cone" ;
0135 static const char* CSG_OLDCONE_       = "oldcone" ;
0136 static const char* CSG_BOX3_          = "box3" ;
0137 static const char* CSG_TRAPEZOID_     = "trapezoid" ;
0138 static const char* CSG_CONVEXPOLYHEDRON_ = "convexpolyhedron" ;
0139 static const char* CSG_DISC_          = "disc" ;
0140 static const char* CSG_SEGMENT_       = "segment" ;
0141 static const char* CSG_ELLIPSOID_     = "ellipsoid" ;
0142 static const char* CSG_TORUS_          = "torus" ;
0143 static const char* CSG_HYPERBOLOID_    = "hyperboloid" ;
0144 static const char* CSG_CUBIC_          = "cubic" ;
0145 static const char* CSG_INFCYLINDER_   = "infcylinder" ;
0146 static const char* CSG_OLDCYLINDER_   = "oldcylinder" ;
0147 static const char* CSG_PHICUT_        = "phicut" ;
0148 static const char* CSG_THETACUT_      = "thetacut" ;
0149 static const char* CSG_HALFSPACE_     = "halfspace" ;
0150 static const char* CSG_NOTSUPPORTED_  = "notsupported" ;
0151 static const char* CSG_UNDEFINED_     = "ERROR_undefined" ;
0152 static const char* CSG_EXBB_          = "externalbb" ;
0153 
0154 
0155 static const char* CSG_OBSOLETE_      = "obsolete" ;
0156 static const char* CSG_PARTLIST_      = "partlist" ;
0157 static const char* CSG_FLAGPARTLIST_  = "flagpartlist" ;
0158 static const char* CSG_FLAGNODETREE_  = "flagnodetree" ;
0159 static const char* CSG_FLAGINVISIBLE_ = "flaginvisible" ;
0160 static const char* CSG_PMT_           = "pmt" ;
0161 static const char* CSG_ZLENS_         = "zlens" ;
0162 static const char* CSG_PRISM_         = "prism" ;
0163 static const char* CSG_LAST_          = "last" ;
0164 
0165 
0166 
0167 struct CSG
0168 {
0169     static int BooleanOperator(char op)
0170     {
0171         int typecode = CSG_ZERO ;
0172         switch(op)
0173         {
0174            case 'U':  typecode = CSG_UNION         ; break ;
0175            case 'I':  typecode = CSG_INTERSECTION  ; break ;
0176            case 'D':  typecode = CSG_DIFFERENCE    ; break ;
0177         }
0178         assert( typecode != CSG_ZERO );
0179         return typecode ;
0180     }
0181 
0182     static int TypeCode(const char* nodename)
0183     {
0184         int tc = CSG_UNDEFINED ;
0185         if(     strcmp(nodename, CSG_ZERO_) == 0)           tc = CSG_ZERO ;
0186         else if(strcmp(nodename, CSG_BOX_) == 0)            tc = CSG_BOX ;
0187         else if(strcmp(nodename, CSG_BOX3_) == 0)           tc = CSG_BOX3 ;
0188         else if(strcmp(nodename, CSG_SPHERE_) == 0)         tc = CSG_SPHERE ;
0189         else if(strcmp(nodename, CSG_ZSPHERE_) == 0)        tc = CSG_ZSPHERE ;
0190         else if(strcmp(nodename, CSG_ZLENS_) == 0)          tc = CSG_ZLENS ;
0191         else if(strcmp(nodename, CSG_PMT_) == 0)            tc = CSG_PMT ;  // not operational
0192         else if(strcmp(nodename, CSG_PRISM_) == 0)          tc = CSG_PRISM ;
0193         else if(strcmp(nodename, CSG_TUBS_) == 0)           tc = CSG_TUBS ;
0194         else if(strcmp(nodename, CSG_CYLINDER_) == 0)       tc = CSG_CYLINDER ;
0195         else if(strcmp(nodename, CSG_CUTCYLINDER_) == 0)    tc = CSG_CUTCYLINDER ;
0196         else if(strcmp(nodename, CSG_INFCYLINDER_) == 0)    tc = CSG_INFCYLINDER ;
0197         else if(strcmp(nodename, CSG_OLDCYLINDER_) == 0)    tc = CSG_OLDCYLINDER ;
0198         else if(strcmp(nodename, CSG_DISC_) == 0)           tc = CSG_DISC ;
0199         else if(strcmp(nodename, CSG_SLAB_) == 0)           tc = CSG_SLAB ;
0200         else if(strcmp(nodename, CSG_PLANE_) == 0)          tc = CSG_PLANE ;
0201         else if(strcmp(nodename, CSG_CONE_) == 0)           tc = CSG_CONE ;
0202         else if(strcmp(nodename, CSG_OLDCONE_) == 0)        tc = CSG_OLDCONE ;
0203         else if(strcmp(nodename, CSG_TRAPEZOID_) == 0)      tc = CSG_TRAPEZOID ;
0204         else if(strcmp(nodename, CSG_ELLIPSOID_) == 0)      tc = CSG_ELLIPSOID ;
0205         else if(strcmp(nodename, CSG_TORUS_) == 0)          tc = CSG_TORUS ;
0206         else if(strcmp(nodename, CSG_HYPERBOLOID_) == 0)    tc = CSG_HYPERBOLOID ;
0207         else if(strcmp(nodename, CSG_CUBIC_) == 0)          tc = CSG_CUBIC ;
0208         else if(strcmp(nodename, CSG_SEGMENT_) == 0)        tc = CSG_SEGMENT ;
0209         else if(strcmp(nodename, CSG_PHICUT_) == 0)         tc = CSG_PHICUT ;
0210         else if(strcmp(nodename, CSG_THETACUT_) == 0)       tc = CSG_THETACUT ;
0211         else if(strcmp(nodename, CSG_HALFSPACE_) == 0)      tc = CSG_HALFSPACE ;
0212         else if(strcmp(nodename, CSG_NOTSUPPORTED_) == 0)    tc = CSG_NOTSUPPORTED ;
0213         else if(strcmp(nodename, CSG_DISCONTIGUOUS_) == 0)   tc = CSG_DISCONTIGUOUS ;
0214         else if(strcmp(nodename, CSG_CONTIGUOUS_) == 0)      tc = CSG_CONTIGUOUS ;
0215         else if(strcmp(nodename, CSG_OVERLAP_) == 0)         tc = CSG_OVERLAP ;
0216         else if(strcmp(nodename, CSG_CONVEXPOLYHEDRON_) == 0) tc = CSG_CONVEXPOLYHEDRON ;
0217         else if(strcmp(nodename, CSG_INTERSECTION_) == 0)   tc = CSG_INTERSECTION ;
0218         else if(strcmp(nodename, CSG_UNION_) == 0)          tc = CSG_UNION ;
0219         else if(strcmp(nodename, CSG_DIFFERENCE_) == 0)     tc = CSG_DIFFERENCE ;
0220         else if(strcmp(nodename, CSG_PARTLIST_) == 0)       tc = CSG_PARTLIST ;
0221         else if(strcmp(nodename, CSG_FLAGPARTLIST_) == 0)   tc = CSG_FLAGPARTLIST ;
0222         else if(strcmp(nodename, CSG_FLAGNODETREE_) == 0)   tc = CSG_FLAGNODETREE ;
0223         else if(strcmp(nodename, CSG_FLAGINVISIBLE_) == 0)  tc = CSG_FLAGINVISIBLE ;
0224         return tc ;
0225     }
0226 
0227     static void TypeCodeVec(std::vector<int>& typecode, const char* names, char delim=',' )
0228     {
0229         std::stringstream nn;
0230         nn.str(names)  ;
0231         std::string n ;
0232         while (std::getline(nn, n, delim))
0233         {
0234             int tc = TypeCode(n.c_str());
0235             if( tc == CSG_UNDEFINED ) continue ;
0236             typecode.push_back( tc );
0237         }
0238     }
0239 
0240     static int DeMorganSwap( int type )
0241     {
0242         int t = CSG_ZERO ;
0243         switch(type)
0244         {
0245             case CSG_INTERSECTION:  t = CSG_UNION         ; break ;
0246             case CSG_UNION:         t = CSG_INTERSECTION  ; break ;
0247             default:                t = CSG_ZERO          ; break ;
0248         }
0249         assert( t != CSG_ZERO );
0250         return t ;
0251     }
0252 
0253     static const char* Name( int type )
0254     {
0255         const char* s = NULL ;
0256         switch(type)
0257         {
0258             case CSG_ZERO:          s = CSG_ZERO_          ; break ;
0259 
0260             //case CSG_TREE:          s = CSG_TREE_          ; break ;   CSG_TREE has same value as CSG_UNION it is used for grouping
0261             case CSG_UNION:         s = CSG_UNION_         ; break ;
0262             case CSG_INTERSECTION:  s = CSG_INTERSECTION_  ; break ;
0263             case CSG_DIFFERENCE:    s = CSG_DIFFERENCE_    ; break ;
0264 
0265             //case CSG_NODE:          s = CSG_NODE_          ; break ;    CSG_NODE has same value as CSG_CONTIGUOUS it is used for grouping
0266             case CSG_CONTIGUOUS:    s = CSG_CONTIGUOUS_    ; break ;
0267             case CSG_DISCONTIGUOUS: s = CSG_DISCONTIGUOUS_ ; break ;
0268             case CSG_OVERLAP:       s = CSG_OVERLAP_       ; break ;
0269 
0270             //case CSG_LEAF:          s = CSG_LEAF_          ; break ;    CSG_LEAF has same value as CSG_SPHERE
0271             case CSG_SPHERE:        s = CSG_SPHERE_        ; break ;
0272             case CSG_BOX:           s = CSG_BOX_           ; break ;
0273             case CSG_ZSPHERE:       s = CSG_ZSPHERE_       ; break ;
0274             case CSG_TUBS:          s = CSG_TUBS_          ; break ;
0275             case CSG_CYLINDER:      s = CSG_CYLINDER_      ; break ;
0276             case CSG_CUTCYLINDER:   s = CSG_CUTCYLINDER_   ; break ;
0277             case CSG_SLAB:          s = CSG_SLAB_          ; break ;
0278             case CSG_PLANE:         s = CSG_PLANE_         ; break ;
0279             case CSG_CONE:          s = CSG_CONE_          ; break ;
0280             case CSG_OLDCONE:       s = CSG_OLDCONE_       ; break ;
0281             case CSG_BOX3:          s = CSG_BOX3_          ; break ;
0282             case CSG_TRAPEZOID:     s = CSG_TRAPEZOID_     ; break ;
0283             case CSG_CONVEXPOLYHEDRON: s = CSG_CONVEXPOLYHEDRON_ ; break ;
0284             case CSG_DISC:          s = CSG_DISC_          ; break ;
0285             case CSG_SEGMENT:       s = CSG_SEGMENT_       ; break ;
0286             case CSG_ELLIPSOID:     s = CSG_ELLIPSOID_     ; break ;
0287             case CSG_TORUS:         s = CSG_TORUS_         ; break ;
0288             case CSG_HYPERBOLOID:   s = CSG_HYPERBOLOID_   ; break ;
0289             case CSG_CUBIC:         s = CSG_CUBIC_         ; break ;
0290             case CSG_INFCYLINDER:   s = CSG_INFCYLINDER_   ; break ;
0291             case CSG_OLDCYLINDER:   s = CSG_OLDCYLINDER_   ; break ;
0292             case CSG_PHICUT:        s = CSG_PHICUT_        ; break ;
0293             case CSG_THETACUT:      s = CSG_THETACUT_      ; break ;
0294             case CSG_HALFSPACE:     s = CSG_HALFSPACE_     ; break ;
0295             case CSG_NOTSUPPORTED:  s = CSG_NOTSUPPORTED_  ; break ;
0296             case CSG_UNDEFINED:     s = CSG_UNDEFINED_     ; break ;
0297 
0298             case CSG_EXBB:          s = CSG_EXBB_          ; break ;
0299             case CSG_OBSOLETE:      s = CSG_OBSOLETE_      ; break ;
0300             case CSG_PARTLIST:      s = CSG_PARTLIST_      ; break ;
0301             case CSG_FLAGPARTLIST:  s = CSG_FLAGPARTLIST_  ; break ;
0302             case CSG_FLAGNODETREE:  s = CSG_FLAGNODETREE_  ; break ;
0303             case CSG_FLAGINVISIBLE: s = CSG_FLAGINVISIBLE_ ; break ;
0304             case CSG_PMT:           s = CSG_PMT_           ; break ;
0305             case CSG_ZLENS:         s = CSG_ZLENS_         ; break ;
0306             case CSG_PRISM:         s = CSG_PRISM_         ; break ;
0307             case CSG_LAST:          s = CSG_LAST_          ; break ;
0308             default:                s = CSG_UNDEFINED_     ; break ;
0309         }
0310         return s ;
0311     }
0312 
0313     static std::string Tag(int type)
0314     {
0315         assert( type > -1 );
0316         const char* name = Name(type);
0317         assert(strlen(name) > 2 );
0318         std::string s(name, name+2) ;
0319         return s ;
0320     }
0321     static std::string Tag(int type, bool complement)
0322     {
0323         std::stringstream ss ;
0324         ss << ( complement ? "!" : "" ) << Tag(type);
0325         std::string str = ss.str();
0326         return str ;
0327     }
0328 
0329 
0330     static bool Exists(int type ) { return Name(type) != NULL ; }
0331 
0332 
0333 
0334     static bool IsTree(int type) {      return (type == CSG_INTERSECTION || type == CSG_UNION || type == CSG_DIFFERENCE) ; }
0335     static bool IsOperator(int type) { return  (type == CSG_INTERSECTION || type == CSG_UNION || type == CSG_DIFFERENCE) ; }
0336 
0337     static bool IsList(int type){ return  (type == CSG_CONTIGUOUS || type == CSG_DISCONTIGUOUS || type == CSG_OVERLAP ) ; }
0338     static bool IsCompound(int type){      return  type < CSG_LEAF && type > CSG_ZERO ; }
0339     static bool IsPrimitive(int type){     return  type >= CSG_LEAF ; }
0340     static bool IsLeaf(int type){          return  type >= CSG_LEAF ; }
0341     static bool IsUnion(int type) {        return  type == CSG_UNION  ; }
0342     static bool IsIntersection(int type) { return  type == CSG_INTERSECTION  ; }
0343     static bool IsDifference(int type) {   return  type == CSG_DIFFERENCE  ; }
0344     static bool IsZero(int type) {         return  type == CSG_ZERO ; }
0345     static bool IsNotsupported(int type) { return  type == CSG_NOTSUPPORTED ; }
0346 
0347 
0348 
0349     static bool ExpectExternalBBox(int type)
0350     {
0351         return  type == CSG_CONVEXPOLYHEDRON || type == CSG_CONTIGUOUS || type == CSG_DISCONTIGUOUS || type == CSG_OVERLAP ;
0352     }
0353 
0354     static bool IsUnbounded(int type)
0355     {
0356         return  type == CSG_PHICUT || type == CSG_THETACUT || type == CSG_INFCYLINDER  || type == CSG_PLANE || type == CSG_SLAB || type == CSG_HALFSPACE ;
0357     }
0358     static bool CanZNudge(int type)
0359     {
0360         return type == CSG_CYLINDER || type == CSG_CONE || type == CSG_DISC || type == CSG_ZSPHERE ;
0361     }
0362 
0363     static bool IsPositiveMask( unsigned mask )
0364     {
0365         return ( mask & Mask(CSG_DIFFERENCE) ) == 0 ;
0366     }
0367 
0368     /**
0369     CSG::OffsetType
0370     ---------------
0371 
0372     +----------------------+------------+-------------------------------+-----------------------------------+
0373     |  typeName            | typeValue  |   CSG::OffsetType(typeValue)  |                                   |
0374     +======================+============+===============================+===================================+
0375     |  CSG_ZERO            |    0       |            0                  |                                   |
0376     +----------------------+------------+-------------------------------+-----------------------------------+
0377     |  CSG_UNION           |    1       |            1                  |                                   |
0378     +----------------------+------------+-------------------------------+-----------------------------------+
0379     |  CSG_INTERSECTION    |    2       |            2                  |                                   |
0380     +----------------------+------------+-------------------------------+-----------------------------------+
0381     |  CSG_DIFFERENCE      |    3       |            3                  |                                   |
0382     +----------------------+------------+-------------------------------+-----------------------------------+
0383     |  CSG_LIST            |   11       |            4                  |   type - CSG_LIST + 4 = 4         |
0384     +----------------------+------------+-------------------------------+-----------------------------------+
0385     |  CSG_CONTIGUOUS      |   11       |            4                  |                                   |
0386     +----------------------+------------+-------------------------------+-----------------------------------+
0387     |  CSG_DISCONTIGUOUS   |   12       |            5                  |                                   |
0388     +----------------------+------------+-------------------------------+-----------------------------------+
0389     |  CSG_OVERLAP         |   13       |            6                  |                                   |
0390     +----------------------+------------+-------------------------------+-----------------------------------+
0391     |  CSG_LEAF            |   101      |            7                  |   type - CSG_LEAF + 7 = 7         |
0392     +----------------------+------------+-------------------------------+-----------------------------------+
0393     |  CSG_SPHERE          |   101      |            7                  |                                   |
0394     +----------------------+------------+-------------------------------+-----------------------------------+
0395     |  CSG_BOX             |   102      |            8                  |                                   |
0396     +----------------------+------------+-------------------------------+-----------------------------------+
0397     |  CSG_THETACUT        |   121      |    121 - 101 + 7 = 27         |                                   |
0398     +----------------------+------------+-------------------------------+-----------------------------------+
0399 
0400     **/
0401 
0402     static int OffsetType(int type)
0403     {
0404         int offset_type = CSG_ZERO ;
0405         if(      type == CSG_ZERO  ) offset_type = type  ;
0406         else if( CSG::IsTree(type) ) offset_type = type  ;
0407         else if( CSG::IsList(type) ) offset_type = type - CSG_LIST + CSG_OFFSET_LIST  ;   // -11 + 4  = -7
0408         else if( CSG::IsLeaf(type) ) offset_type = type - CSG_LEAF + CSG_OFFSET_LEAF  ;   // -101 +7  =
0409         return offset_type ;
0410     }
0411 
0412     static int TypeFromOffsetType( int offsetType )
0413     {
0414         int type = CSG_ZERO ;
0415         if( offsetType < CSG_OFFSET_LIST )
0416         {
0417             type = offsetType ;
0418         }
0419         else if( offsetType < CSG_OFFSET_LEAF )
0420         {
0421             type = offsetType - CSG_OFFSET_LIST + CSG_LIST ;
0422         }
0423         else
0424         {
0425             type = offsetType - CSG_OFFSET_LEAF + CSG_LEAF ;
0426         }
0427         return type ;
0428     }
0429 
0430     static unsigned Mask(int type)
0431     {
0432         // offsets aim to fold a range greater than 32 to fit within 32  without overlapping
0433         int offset_type = OffsetType(type);
0434         assert( offset_type < 32 );
0435         unsigned mask = 0x1 << offset_type  ;
0436         return mask ;
0437     }
0438 
0439     static std::string TypeMask( unsigned mask )
0440     {
0441          std::stringstream ss ;
0442          if((mask & Mask(CSG_UNION))        != 0) ss << Tag(CSG_UNION) << " " ;
0443          if((mask & Mask(CSG_INTERSECTION)) != 0) ss << Tag(CSG_INTERSECTION) << " " ;
0444          if((mask & Mask(CSG_DIFFERENCE))   != 0) ss << Tag(CSG_DIFFERENCE) << " " ;
0445          std::string s = ss.str();
0446          return s ;
0447     }
0448 
0449     static std::string MaskString(unsigned qmask)
0450     {
0451         std::stringstream ss ;
0452         for(unsigned i=0 ; i < 32 ; i++)
0453         {
0454             int type = TypeFromOffsetType(i) ;
0455             unsigned typemask = Mask(type);
0456 
0457             if((qmask & typemask) != 0 )
0458             {
0459                 ss << CSG::Name(type) << " " ;
0460             }
0461         }
0462         return ss.str();
0463     }
0464 
0465 
0466     static bool HasPlanes(int type) // huh ? what happened to the planes array ?
0467     {
0468         return (type == CSG_TRAPEZOID || type == CSG_CONVEXPOLYHEDRON || type == CSG_SEGMENT ) ;
0469     }
0470 
0471 
0472     static int HintCode(const char* name)
0473     {
0474         int hintcode = CSG_ZERO ;
0475         if(     strstr(name, _CSG_CONTIGUOUS)    != nullptr) hintcode = CSG_CONTIGUOUS ;
0476         else if(strstr(name, _CSG_DISCONTIGUOUS) != nullptr) hintcode = CSG_DISCONTIGUOUS ;
0477         else if(strstr(name, _CSG_OVERLAP)       != nullptr) hintcode = CSG_OVERLAP ;
0478         else if(strstr(name, _CSG_EXBB)          != nullptr) hintcode = CSG_EXBB ;
0479         return hintcode ;
0480     }
0481     static std::string MaskDesc( unsigned mask )
0482     {
0483         std::stringstream ss ;
0484         if( mask & Mask(CSG_UNION))        ss << "union " ;
0485         if( mask & Mask(CSG_INTERSECTION)) ss << "intersection " ;
0486         if( mask & Mask(CSG_DIFFERENCE ))  ss << "difference " ;
0487         return ss.str()  ;
0488     }
0489 
0490     /**
0491     CSG::MonoOperator
0492     ------------------
0493 
0494     For masks corresponding to a single UNION or INTERSECTION operator return
0495     the CSG code of the operator, otherwise return CSG_ZERO.
0496     **/
0497 
0498     static int MonoOperator( unsigned mask )
0499     {
0500         int op = CSG_ZERO ;
0501         if(      Mask(CSG_UNION)        == mask ) op = CSG_UNION ;
0502         else if( Mask(CSG_INTERSECTION) == mask ) op = CSG_INTERSECTION ;
0503         else if( Mask(CSG_DIFFERENCE)   == mask ) op = CSG_ZERO  ;   // difference is unusable for tree manipulation so give zero
0504         return op ;
0505     }
0506 
0507 
0508 };
0509 
0510 
0511 #endif
0512