File indexing completed on 2026-04-09 07:48:58
0001
0002
0003 import os, sys, logging, codecs, numpy as np
0004 from opticks.sysrap.OpticksCSG import CSG_ as CSG
0005 from complete_binary_tree import layout_tree
0006
0007
0008 log = logging.getLogger(__name__)
0009
0010 class BB(object):
0011 """
0012
0013 +--------+
0014 | |
0015 z1 +--------+ |
0016 | | | |
0017 | +--|-----+ y1
0018 | |
0019 z0 +--------+ y0
0020 x0 x1
0021 """
0022 def __init__(self, bb=[-0.,-0.,-0.,0.,0.,0.]):
0023 self.x0 = bb[0]
0024 self.y0 = bb[1]
0025 self.z0 = bb[2]
0026 self.x1 = bb[3]
0027 self.y1 = bb[4]
0028 self.z1 = bb[5]
0029 self.data = bb
0030
0031 def __repr__(self):
0032 fmt = "%10.3f "
0033 fmt = fmt * 6
0034 return fmt % tuple(self.data)
0035
0036 def include(self, other):
0037 if other.x0 < self.x0: self.x0 = other.x0
0038 if other.y0 < self.y0: self.y0 = other.y0
0039 if other.z0 < self.z0: self.z0 = other.z0
0040
0041 if other.x1 > self.x1: self.x1 = other.x1
0042 if other.y1 > self.y1: self.y1 = other.y1
0043 if other.z1 > self.z1: self.z1 = other.z1
0044
0045
0046
0047 class Tran(object):
0048 def __init__(self, idx, tr, it):
0049 self.idx = idx
0050 self.tr = tr
0051 self.it = it
0052 def __repr__(self):
0053 return "\n".join([str(self.idx), repr(self.tr)])
0054
0055 class Node(object):
0056 """
0057
0058 1
0059 10 11
0060 100 101 110 111
0061 1000 1001 1100 1101 1100 1101 1110 1111
0062
0063
0064 """
0065 def __init__(self, item, fd):
0066 self.fd = fd
0067 self.tc = item[3,2].view(np.int32)
0068 self.tyd = CSG.desc(self.tc)
0069 self.ty = self.tyd[:2]
0070 self.idx = item[1,3].view(np.int32)
0071 self.depth = len("{0:b}".format(self.idx+1)) - 1
0072 self.tref = item[3,3].view(np.int32) & 0x7fffffff
0073 self.tidx = self.tref - 1
0074 self.cm = bool(item[3,3].view(np.uint32) & 0x80000000 >> 31)
0075 self.bb = BB(item[2:4].ravel()[:6])
0076 self.pa = item[0:2].ravel()[:6]
0077 self.tr = self.fd.tran[self.tidx] if self.tref > 0 else None
0078 self.it = self.fd.itra[self.tidx] if self.tref > 0 else None
0079 self.tran = Tran(self.tidx, self.tr, self.it) if self.tidx > -1 else None
0080 self.scm = "!" if self.cm else ":"
0081 self.label = "%s%s%s" % (1+self.idx,self.scm, self.ty)
0082
0083 def __repr__(self):
0084 return "Node %2d%s%2s tidx:%5d cm:%1d bb %30s pa %30s " % (1+self.idx,self.scm,self.ty, self.tidx, self.cm, str(self.bb), str(self.pa))
0085 def __str__(self):
0086 return self.label
0087
0088
0089 class Prim(object):
0090 def __init__(self, item, fd):
0091 self.fd = fd
0092 self.numNode = item[0,0].view(np.int32)
0093 self.nodeOffset = item[0,1].view(np.int32)
0094 self.bb = BB(item[2:4].ravel()[:6])
0095
0096 self.midx = item[1,1].view(np.uint32)
0097 self.ridx = item[1,2].view(np.uint32)
0098 self.pidx = item[1,3].view(np.uint32)
0099 self.mname = self.fd.getName(self.midx)
0100
0101 levelorder = list(map(lambda item:Node(item, fd), self.fd.node[self.nodeOffset:self.nodeOffset+self.numNode]))
0102 self.node = levelorder
0103
0104 def __repr__(self):
0105 return "Prim %3d %5d %30s : %s" % (self.numNode, self.nodeOffset, str(self.bb), self.mname)
0106
0107 def __str__(self):
0108 return "\n".join([repr(self)]+list(map(repr, self.node))+list(map(lambda n:repr(n.tran), self.node)))
0109
0110 def __getitem__(self, nodeIdx):
0111 return self.node[nodeIdx]
0112
0113 class Solid(object):
0114 @classmethod
0115 def DecodeLabel(cls, item):
0116 return item.tobytes()[:16].split(b'\0')[0].decode("utf-8")
0117
0118 def __init__(self, item, fd):
0119 self.item = item
0120 self.fd = fd
0121 self.label = self.DecodeLabel(item)
0122 self.numPrim = item[1,0].view(np.int32)
0123 self.primOffset = item[1,1].view(np.int32)
0124 self.prim = list(map(lambda item:Prim(item, fd), self.fd.prim[self.primOffset:self.primOffset+self.numPrim]))
0125 self.ce = item[2].view(np.float32)
0126
0127 def __repr__(self):
0128 return "Solid %10s : %4d %5d ce %35s " % (self.label, self.numPrim, self.primOffset, str(self.ce))
0129
0130 def __str__(self):
0131 return "\n".join([repr(self)]+list(map(repr, self.prim)))
0132
0133 def __getitem__(self, primIdx):
0134 return self.prim[primIdx]
0135
0136
0137 class Foundry(object):
0138 BASE = "$TMP/CSG_GGeo/CSGFoundry"
0139 NAMES = "solid prim node tran itra inst".split()
0140 def __init__(self, base=None):
0141 if base is None: base = self.BASE
0142 base = os.path.expandvars(base)
0143 for n in self.NAMES+["plan"]:
0144 path = os.path.join(base, "%s.npy" % n)
0145 if not os.path.exists(path): continue
0146 setattr( self, n, np.load(path))
0147 pass
0148 self.name = np.loadtxt(os.path.join(base, "name.txt"), dtype=np.object)
0149 self.label = list(map(Solid.DecodeLabel, self.solid))
0150 self.solids = list(map(lambda item:Solid(item,self), self.solid))
0151
0152 def __repr__(self):
0153 return "\n".join(["Foundry"] + list(map(lambda n:"%10s : %s " % (n,repr(getattr(self, n).shape)), self.NAMES)))
0154
0155 def __str__(self):
0156 return "\n".join(["Foundry"]+ list(map(repr, self.solids)))
0157
0158 def getName(self, midx):
0159 return self.name[midx]
0160
0161 def index(self, solid_label):
0162 return self.label.index(solid_label)
0163
0164 def gt(self):
0165 return self.node.view(np.int32)[:,3,3] & 0x7fffffff
0166 def cm(self):
0167 return (self.node.view(np.int32)[:,3,3] & 0x80000000) >> 31
0168
0169
0170 def midx(self):
0171 return self.prim.view(np.uint32)[:,1,1]
0172 def ridx(self):
0173 return self.prim.view(np.uint32)[:,1,2]
0174 def pidx(self):
0175 return self.prim.view(np.uint32)[:,1,3]
0176
0177
0178
0179
0180 def __getitem__(self, arg):
0181 """
0182 Access solids nodes prims via string specification::
0183
0184 fd["d1"] # solid with label "d1"
0185 fd["d1/0"] # 1st prim
0186 fd["d1/0/0"] # 1st node of 1st prim
0187
0188 """
0189 ret = None
0190 elem = arg.split("/")
0191
0192 solid_label = elem[0] if len(elem) > 0 else None
0193 primIdx = int(elem[1]) if len(elem) > 1 else None
0194 nodeIdx = int(elem[2]) if len(elem) > 2 else None
0195
0196 solidIdx = self.index(solid_label) if not solid_label is None else None
0197
0198 so = None
0199 pr = None
0200 nd = None
0201
0202 if not solidIdx is None:
0203 so = self.solids[solidIdx]
0204 pass
0205 if not so is None and not primIdx is None:
0206 pr = so[primIdx]
0207 pass
0208 if not pr is None and not nodeIdx is None:
0209 nd = pr[nodeIdx]
0210 pass
0211
0212 if not nd is None:
0213 return nd
0214 elif not pr is None:
0215 return pr
0216 elif not so is None:
0217 return so
0218 else:
0219 return None
0220 pass
0221 return None
0222
0223
0224
0225 if __name__ == '__main__':
0226 logging.basicConfig(level=logging.INFO)
0227 fd = Foundry("$TMP/CSG_GGeo/CSGFoundry")
0228 print(repr(fd))
0229
0230 args = sys.argv[1:] if len(sys.argv) > 1 else "r8/0".split()
0231
0232 p = None
0233 n = None
0234 s = None
0235
0236 for arg in args:
0237 obj = fd[arg]
0238 print(arg)
0239 print(obj)
0240
0241 if type(obj) is Prim:
0242 p = obj
0243 elif type(obj) is Node:
0244 n = obj
0245 elif type(obj) is Solid:
0246 s = obj
0247 else:
0248 pass
0249 pass
0250 pass
0251
0252 if not p is None:
0253
0254 t = layout_tree(p.node)
0255 print("layout_tree")
0256 print(t)
0257 pass
0258
0259