Too Many Ridx Instances ========================= Initial simple instancing criteria from NScene::labelTree_r of "num_mesh_instances > 4" is yielding 117 distinct types of geometry, that is an order of magnitude more than desired. The very simple instancing criteria based on mesh instance counts alone yields many more instances than optimal as it is unaware of the containment relations within the node tree. Using containment relations allow "vertical" combination in the node tree not just the current "horizontal" combinations. NScene now does repeat candidate finding similar to GTreeCheck/GNode progeny digests within NScene. Can siblings be grouped into added subtrees in crowded nodes ? ---------------------------------------------------------------- * repeat candidate finding only works for subtrees (not siblings), so would be better to unflatten the node tree for crowded nodes into groups, allowing the progeny digest and repeat candidiate finding/labelling machinery to be used as is ... * eg would want the PMT Collar to be grouped together with the PMT subtree, but its unscalable to write geometry specific code to do this : need a general way Where to implement sibling grouping ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * needs only the mesh_id and transforms for the node tree, so could be done at python level * seems that it is possible to duplicate transform digests (for identity transforms anyhow) in python (see sysrap/tests/SDigestTest.py) ... hmm but dont want to duplicate the polar decomposition py side, but dont need to : just adjust to digesting the basis transform Finding nodes with lots of children ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: simon:opticks blyth$ tgltf-;tgltf-gdml-rip # starting from 3153 In [20]: map(lambda n:(n,len(target.find_nodes_nchild(n))), range(23) ) Out[20]: [(0, 532), (1, 269), (2, 228), (3, 29), (4, 25), (5, 13), (6, 6), (7, 6), (8, 6), (9, 6), (10, 6), (11, 2), (12, 2), (13, 2), (14, 2), (15, 2), (16, 2), (17, 2), (18, 2), (19, 2), (20, 2), (21, 2), (22, 2)] In [21]: nn = target.find_nodes_nchild(22) In [24]: len(nn[0].children) Out[24]: 520 In [25]: len(nn[1].children) Out[25]: 35 In [29]: nn[0].lv.name Out[29]: '/dd/Geometry/AD/lvOIL0xbf5e0b8' In [30]: nn[1].lv.name Out[30]: '/dd/Geometry/AD/lvLSO0xc403e40' In [45]: txf = [c.pv.transform for c in oil.children] In [46]: len(oil.children) Out[46]: 520 In [47]: len(txf) Out[47]: 520 In [52]: tt = np.vstack(txf).reshape(-1,4,4) In [53]: len(tt) Out[53]: 520 In [54]: tt[0] Out[54]: array([[ -1., 0., 0., 0.], [ -0., -1., 0., 0.], [ 0., 0., 1., 0.], [ 0., 0., -49., 1.]], dtype=float32) In [55]: tt[1] Out[55]: array([[ 0. , -0. , 1. , 0. ], [ 0.1305, -0.9914, -0. , 0. ], [ 0.9914, 0.1305, 0. , 0. ], [-2304.6135, -303.4081, -1750. , 1. ]], dtype=float32) In [56]: tt[2] Out[56]: array([[ 0. , -0. , 1. , 0. ], [ 0.1305, -0.9914, -0. , 0. ], [ 0.9914, 0.1305, 0. , 0. ], [-2249.0928, -296.0987, -1750. , 1. ]], dtype=float32) In [57]: tt[3] Out[57]: array([[ 0. , -0. , 1. , 0. ], [ 0.3827, -0.9239, -0. , 0. ], [ 0.9239, 0.3827, 0. , 0. ], [-2147.5579, -889.5477, -1750. , 1. ]], dtype=float32) In [58]: tt[4] Out[58]: array([[ 0. , -0. , 1. , 0. ], [ 0.3827, -0.9239, -0. , 0. ], [ 0.9239, 0.3827, 0. , 0. ], [-2095.8208, -868.1174, -1750. , 1. ]], dtype=float32) In [64]: len(unique2D_subarray(tt)) ## all transforms are unique Out[64]: 520 In [71]: rr = tt[:,:3,:3] In [72]: rr Out[72]: array([[[-1. , 0. , 0. ], [-0. , -1. , 0. ], [ 0. , 0. , 1. ]], [[ 0. , -0. , 1. ], [ 0.1305, -0.9914, -0. ], [ 0.9914, 0.1305, 0. ]], [[ 0. , -0. , 1. ], [ 0.1305, -0.9914, -0. ], [ 0.9914, 0.1305, 0. ]], ..., [[ 0. , -0. , -1. ], [ 0.866 , -0.5 , 0. ], [-0.5 , -0.866 , 0. ]], [[ 0. , -0. , -1. ], [ 0.866 , -0.5 , 0. ], [-0.5 , -0.866 , 0. ]], [[ 0. , -0. , -1. ], [ 0.866 , -0.5 , 0. ], [-0.5 , -0.866 , 0. ]]], dtype=float32) In [73]: len(rr) Out[73]: 520 In [74]: unique2D_subarray(rr) Out[74]: array([[[ 1. , 0. , 0. ], [ 0. , 1. , 0. ], [ 0. , 0. , 1. ]], [[-1. , 0. , 0. ], [-0. , -1. , 0. ], [ 0. , 0. , 1. ]], [[ 0. , 0. , 1. ], ... In [75]: len(unique2D_subarray(rr)) ## only 68 distinct rotations Out[75]: 68 General Sibling grouping --------------------------- For crowded nodes like oil and ls, counting lv occurrence and looking for groups with equal counts will yield candidate groupings... then need to analyse the transforms to pair the appropriate ones together. They should have equal transforms (or at least equal rotation and z-shift) Also need way to verify that the intended added groups would actually have same progeny digests before going to trouble of editing the node tree... :: In [1]: tree.analyse_crowds() /dd/Geometry/RPC/lvNearRPCRoof0xbf40030 54 54 : /dd/Geometry/RPC/lvRPCMod0xbf54e60 /dd/Geometry/RPCSupport/lvNearHbeamSmallUnit0xc5bef70 72 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSpanHbeam0xc21f438 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSideShortHbeam0xc2b1dd0 8 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagSquareIron0xc358910 8 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagAngleIron0xc12bb90 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearPentagonIron0xc35a0b0 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSquareIron0xc2484c0 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartLongAngleIron0xc21e000 /dd/Geometry/RPCSupport/lvNearHbeamBigUnit0xbf3a988 178 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSideLongHbeam0xbf3b550 4 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSpanHbeam0xc21f438 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagSquareIron0xc358910 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagAngleIron0xc12bb90 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartShortAngleIron0xbf3dbf0 32 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearPentagonIron0xc35a0b0 36 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartLongAngleIron0xc21e000 54 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSquareIron0xc2484c0 /dd/Geometry/RPCSupport/lvNearHbeamBigUnit0xbf3a988 178 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSideLongHbeam0xbf3b550 4 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSpanHbeam0xc21f438 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagSquareIron0xc358910 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagAngleIron0xc12bb90 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartShortAngleIron0xbf3dbf0 32 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearPentagonIron0xc35a0b0 36 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartLongAngleIron0xc21e000 54 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSquareIron0xc2484c0 /dd/Geometry/RPCSupport/lvNearHbeamBigUnit0xbf3a988 178 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSideLongHbeam0xbf3b550 4 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSpanHbeam0xc21f438 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagSquareIron0xc358910 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagAngleIron0xc12bb90 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartShortAngleIron0xbf3dbf0 32 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearPentagonIron0xc35a0b0 36 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartLongAngleIron0xc21e000 54 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSquareIron0xc2484c0 /dd/Geometry/RPCSupport/lvNearHbeamBigUnit0xbf3a988 178 2 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSideLongHbeam0xbf3b550 4 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSpanHbeam0xc21f438 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagSquareIron0xc358910 16 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearDiagAngleIron0xc12bb90 18 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartShortAngleIron0xbf3dbf0 32 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearPentagonIron0xc35a0b0 36 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearThwartLongAngleIron0xc21e000 54 : /dd/Geometry/RPCSupport/TrivialComponents/lvNearSquareIron0xc2484c0 /dd/Geometry/Pool/lvNearPoolOWS0xbf93840 2938 1 : /dd/Geometry/Pool/lvNearPoolCurtain0xc2ceef0 1 : /dd/Geometry/PoolDetails/lvOutInWaterPipeNearTub0xce594c0 1 : /dd/Geometry/PoolDetails/lvOutOutWaterPipeNearTub0xce58ca0 2 : /dd/Geometry/PoolDetails/lvTopShortCableTray0xce58200 4 : /dd/Geometry/PoolDetails/lvTopCornerCableTray0xce56ff8 8 : /dd/Geometry/PoolDetails/lvLegInOWSTub0xcced348 8 : /dd/Geometry/PoolDetails/lvVertiCableTray0xc0e08a0 16 : /dd/Geometry/PoolDetails/lvShortParRib20xcd56b40 16 : /dd/Geometry/PoolDetails/lvLongParRib20xc3b4910 16 : /dd/Geometry/PoolDetails/lvShortParRib10xcd55e48 16 : /dd/Geometry/PoolDetails/lvLongParRib10xc3b3eb8 32 : /dd/Geometry/PoolDetails/lvCornerParRib10xc0e2430 32 : /dd/Geometry/PoolDetails/lvCornerParRib20xc0f2040 92 : /dd/Geometry/PoolDetails/lvBotVertiRib0xbf63800 167 : /dd/Geometry/PMT/lvPmtTee0xc011648 167 : /dd/Geometry/PMT/lvPmtHemi0xc133740 167 : /dd/Geometry/PMT/lvPmtTopRing0xc3486f0 167 : /dd/Geometry/PMT/lvPmtBaseRing0xc00f400 ### this would be a juicy instance 192 : /dd/Geometry/PoolDetails/lvCrossRib0xcd570b8 330 : /dd/Geometry/PoolDetails/lvSidVertiRib0xc5e6fa0 501 : /dd/Geometry/PMT/lvMountRib10xc3a4cb0 501 : /dd/Geometry/PMT/lvMountRib20xc012500 501 : /dd/Geometry/PMT/lvMountRib30xc00d350 ### maybe this too /dd/Geometry/Pool/lvNearPoolIWS0xc28bc60 1619 1 : /dd/Geometry/PoolDetails/lvInnInWaterPipeNearTub0xbf29660 1 : /dd/Geometry/PoolDetails/lvInnOutWaterPipeNearTub0xc0d7c30 2 : /dd/Geometry/PoolDetails/lvInnShortParCableTray0xc95a730 2 : /dd/Geometry/AD/lvADE0xc2a78c0 2 : /dd/Geometry/PoolDetails/lvTablePanel0xc0101d8 2 : /dd/Geometry/PoolDetails/lvInnVertiCableTray0xbf28e40 4 : /dd/Geometry/PoolDetails/lvSupportRib50xc0d8bb8 8 : /dd/Geometry/PoolDetails/lvLegInIWSTub0xc400e40 8 : /dd/Geometry/PoolDetails/lvSlopeRib10xc0d8b50 8 : /dd/Geometry/PoolDetails/lvSupportRib10xc0d8868 8 : /dd/Geometry/PoolDetails/lvSlopeRib50xc0d8db0 121 : /dd/Geometry/PMT/lvPmtTee0xc011648 121 : /dd/Geometry/PMT/lvPmtTopRing0xc3486f0 121 : /dd/Geometry/PMT/lvPmtBaseRing0xc00f400 121 : /dd/Geometry/PMT/lvPmtHemi0xc133740 ### another juicy one if can be grouped into identical mesh-transform-digest subtrees 363 : /dd/Geometry/PMT/lvMountRib20xc012500 363 : /dd/Geometry/PMT/lvMountRib30xc00d350 363 : /dd/Geometry/PMT/lvMountRib10xc3a4cb0 ### perhaps /dd/Geometry/AD/lvOIL0xbf5e0b8 520 1 : /dd/Geometry/AdDetails/lvSstTopHub0xc2644f0 1 : /dd/Geometry/AdDetails/lvOcrGdsLsoPrt0xc104a90 1 : /dd/Geometry/AdDetails/lvOcrCalLsoPrt0xc1077c8 1 : /dd/Geometry/AdDetails/lvSstBotHub0xc1760f0 1 : /dd/Geometry/AdDetails/lvTopReflector0xbf9be68 1 : /dd/Geometry/AdDetails/lvCtrLsoOflInOil0xc183248 1 : /dd/Geometry/AdDetails/lvOcrGdsLsoOfl0xc1052d0 1 : /dd/Geometry/AdDetails/lvOcrCalLso0xc17e288 1 : /dd/Geometry/AdDetails/lvBotReflector0xc3cd4c0 1 : /dd/Geometry/AD/lvOAV0xbf1c760 1 : /dd/Geometry/AdDetails/lvOavTopHub0xbf366d0 3 : /dd/Geometry/AdDetails/lvCtrLsoOflTopClp0xc26f5a0 3 : /dd/Geometry/CalibrationSources/lvWallLedSourceAssy0xc3a9f40 3 : /dd/Geometry/AdDetails/lvCtrLsoOflTfb0xc3a2ab0 4 : /dd/Geometry/AdDetails/lvBotRefRadialShortRib0xbf339c8 4 : /dd/Geometry/AdDetails/lvBotRefRadialLongRib0xbf32988 6 : /dd/Geometry/PMT/lvHeadonPmtAssy0xbf9fb20 6 : /dd/Geometry/PMT/lvHeadonPmtMount0xc02d380 8 : /dd/Geometry/AdDetails/lvSstInnVerRibBase0xbf31748 8 : /dd/Geometry/AdDetails/lvSstBotRib0xc26c650 8 : /dd/Geometry/AdDetails/lvSstTopTshapeRib0xc2629f0 8 : /dd/Geometry/AdDetails/lvSstTopRadiusRib0xc2716c0 8 : /dd/Geometry/AdDetails/lvSstBotCirRibBase0xc26e220 8 : /dd/Geometry/AdDetails/lvOavTopRib0xbf7bce8 8 : /dd/Geometry/AdDetails/lvSstTopCirRibBase0xc2649f0 8 : /dd/Geometry/AdDetails/lvBotRefCircleRib0xbf34468 32 : /dd/Geometry/AdDetails/lvRadialShieldUnit0xc3d7ec0 192 : /dd/Geometry/PMT/lvAdPmtCollar0xbf21fb0 192 : /dd/Geometry/PMT/lvPmtHemi0xc133740 ### obvious one /dd/Geometry/AD/lvLSO0xc403e40 35 1 : /dd/Geometry/AD/lvIAV0xc404ee8 1 : /dd/Geometry/AdDetails/lvIavTopHub0xc129d88 1 : /dd/Geometry/AdDetails/lvCtrGdsOflInLso0xc28cc88 1 : /dd/Geometry/AdDetails/lvIavBotHub0xc355b80 1 : /dd/Geometry/AdDetails/lvCtrGdsOflTfbInLso0xbfa0728 1 : /dd/Geometry/AdDetails/lvOcrGdsPrt0xc352630 1 : /dd/Geometry/AdDetails/lvOavBotHub0xc3550d8 1 : /dd/Geometry/AdDetails/lvOcrGdsTfbInLso0xc3529c0 1 : /dd/Geometry/AdDetails/lvOcrGdsInLso0xc353990 2 : /dd/Geometry/AdDetails/lvCtrGdsOflBotClp0xc407eb0 8 : /dd/Geometry/AdDetails/lvIavBotRib0xc355990 8 : /dd/Geometry/AdDetails/lvOavBotRib0xc353d30 8 : /dd/Geometry/AdDetails/lvIavTopRib0xbf8e280 /dd/Geometry/AD/lvOIL0xbf5e0b8 520 1 : /dd/Geometry/AdDetails/lvSstTopHub0xc2644f0 1 : /dd/Geometry/AdDetails/lvOcrGdsLsoPrt0xc104a90 1 : /dd/Geometry/AdDetails/lvOcrCalLsoPrt0xc1077c8 1 : /dd/Geometry/AdDetails/lvSstBotHub0xc1760f0 1 : /dd/Geometry/AdDetails/lvTopReflector0xbf9be68 1 : /dd/Geometry/AdDetails/lvCtrLsoOflInOil0xc183248 1 : /dd/Geometry/AdDetails/lvOcrGdsLsoOfl0xc1052d0 1 : /dd/Geometry/AdDetails/lvOcrCalLso0xc17e288 1 : /dd/Geometry/AdDetails/lvBotReflector0xc3cd4c0 1 : /dd/Geometry/AD/lvOAV0xbf1c760 1 : /dd/Geometry/AdDetails/lvOavTopHub0xbf366d0 3 : /dd/Geometry/AdDetails/lvCtrLsoOflTopClp0xc26f5a0 3 : /dd/Geometry/CalibrationSources/lvWallLedSourceAssy0xc3a9f40 3 : /dd/Geometry/AdDetails/lvCtrLsoOflTfb0xc3a2ab0 4 : /dd/Geometry/AdDetails/lvBotRefRadialShortRib0xbf339c8 4 : /dd/Geometry/AdDetails/lvBotRefRadialLongRib0xbf32988 6 : /dd/Geometry/PMT/lvHeadonPmtAssy0xbf9fb20 6 : /dd/Geometry/PMT/lvHeadonPmtMount0xc02d380 8 : /dd/Geometry/AdDetails/lvSstInnVerRibBase0xbf31748 8 : /dd/Geometry/AdDetails/lvSstBotRib0xc26c650 8 : /dd/Geometry/AdDetails/lvSstTopTshapeRib0xc2629f0 8 : /dd/Geometry/AdDetails/lvSstTopRadiusRib0xc2716c0 8 : /dd/Geometry/AdDetails/lvSstBotCirRibBase0xc26e220 8 : /dd/Geometry/AdDetails/lvOavTopRib0xbf7bce8 8 : /dd/Geometry/AdDetails/lvSstTopCirRibBase0xc2649f0 8 : /dd/Geometry/AdDetails/lvBotRefCircleRib0xbf34468 32 : /dd/Geometry/AdDetails/lvRadialShieldUnit0xc3d7ec0 192 : /dd/Geometry/PMT/lvAdPmtCollar0xbf21fb0 ### from the other AD 192 : /dd/Geometry/PMT/lvPmtHemi0xc133740 /dd/Geometry/AD/lvLSO0xc403e40 35 1 : /dd/Geometry/AD/lvIAV0xc404ee8 1 : /dd/Geometry/AdDetails/lvIavTopHub0xc129d88 1 : /dd/Geometry/AdDetails/lvCtrGdsOflInLso0xc28cc88 1 : /dd/Geometry/AdDetails/lvIavBotHub0xc355b80 1 : /dd/Geometry/AdDetails/lvCtrGdsOflTfbInLso0xbfa0728 1 : /dd/Geometry/AdDetails/lvOcrGdsPrt0xc352630 1 : /dd/Geometry/AdDetails/lvOavBotHub0xc3550d8 1 : /dd/Geometry/AdDetails/lvOcrGdsTfbInLso0xc3529c0 1 : /dd/Geometry/AdDetails/lvOcrGdsInLso0xc353990 2 : /dd/Geometry/AdDetails/lvCtrGdsOflBotClp0xc407eb0 8 : /dd/Geometry/AdDetails/lvIavBotRib0xc355990 8 : /dd/Geometry/AdDetails/lvOavBotRib0xc353d30 8 : /dd/Geometry/AdDetails/lvIavTopRib0xbf8e280 Initial Approach ------------------- :: 252 unsigned NScene::deviseRepeatIndex(nd* n) 253 { 254 unsigned mesh_idx = n->mesh ; 255 unsigned num_mesh_instances = getNumInstances(mesh_idx) ; 256 257 unsigned ridx = 0 ; // <-- global default ridx 258 259 bool make_instance = num_mesh_instances > 4 ; 260 261 if(make_instance) 262 { 263 if(m_mesh2ridx.count(mesh_idx) == 0) 264 m_mesh2ridx[mesh_idx] = m_mesh2ridx.size() + 1 ; 265 266 ridx = m_mesh2ridx[mesh_idx] ; 267 268 // ridx is a 1-based contiguous index tied to the mesh_idx 269 // using trivial things like "mesh_idx + 1" causes 270 // issue downstream which expects a contiguous range of ridx 271 // when using partial geometries 272 } 273 return ridx ; 274 } 275 276 void NScene::labelTree_r(nd* n) 277 { 278 unsigned ridx = deviseRepeatIndex(n); 279 280 n->repeatIdx = ridx ; 281 282 if(m_repeat_count.count(ridx) == 0) m_repeat_count[ridx] = 0 ; 283 m_repeat_count[ridx]++ ; 284 285 286 for(nd* c : n->children) labelTree_r(c) ; 287 } :: tgltf-;tgltf-gdml 2017-05-24 12:22:23.820 INFO [2974756] [*GScene::createVolumeTree@131] GScene::createVolumeTree DONE num_nodes: 12229 2017-05-24 12:22:23.851 INFO [2974756] [GScene::makeMergedMeshAndInstancedBuffers@269] GScene::makeMergedMeshAndInstancedBuffers num_repeats 117 START 2017-05-24 12:22:54.614 WARN [2974756] [GMesh::allocate@614] GMesh::allocate EMPTY numVertices 0 numFaces 0 numSolids 1 2017-05-24 12:22:54.683 WARN [2974756] [GMesh::allocate@614] GMesh::allocate EMPTY numVertices 0 numFaces 0 numSolids 1 2017-05-24 12:22:55.255 WARN [2974756] [GMesh::allocate@614] GMesh::allocate EMPTY numVertices 0 numFaces 0 numSolids 11 2017-05-24 12:22:55.334 WARN [2974756] [GMesh::allocate@614] GMesh::allocate EMPTY numVertices 0 numFaces 0 numSolids 15 2017-05-24 12:22:55.483 WARN [2974756] [GMesh::allocate@614] GMesh::allocate EMPTY numVertices 0 numFaces 0 numSolids 33 2017-05-24 12:22:56.197 INFO [2974756] [GScene::makeMergedMeshAndInstancedBuffers@319] GScene::makeMergedMeshAndInstancedBuffers DONE num_repeats 117 nmm_created 117 nmm 117 Assertion failed: (0 && "early exit for gltf==4"), function loadFromGLTF, file /Users/blyth/opticks/ggeo/GGeo.cc, line 660. GTreeCheck triangulated approach ----------------------------------------- :: 027 GTreeCheck::GTreeCheck(GGeo* ggeo) 28 : 29 m_ggeo(ggeo), 30 m_geolib(ggeo->getGeoLib()), 31 m_repeat_min(120), 32 m_vertex_min(300), // aiming to include leaf? sStrut and sFasteners 33 m_root(NULL), 34 m_count(0), 35 m_labels(0), 36 m_digest_count(new Counts("progenyDigest")) 37 { 38 } 87 void GTreeCheck::traverse() 88 { 89 m_root = m_ggeo->getSolid(0); 90 assert(m_root); 91 92 // count occurences of distinct progeny digests (relative sub-tree identities) in m_digest_count 93 traverse_r(m_root, 0); 94 95 m_digest_count->sort(false); // descending count order, ie most common subtrees first 96 //m_digest_count->dump(); 97 98 // minrep 120 removes repeats from headonPMT, calibration sources and RPC leaving just PMTs 99 100 // collect digests of repeated pieces of geometry into m_repeat_candidates 101 findRepeatCandidates(m_repeat_min, m_vertex_min); 102 dumpRepeatCandidates(); 103 } 104 105 void GTreeCheck::traverse_r( GNode* node, unsigned int depth) 106 { 107 std::string& pdig = node->getProgenyDigest(); 108 m_digest_count->add(pdig.c_str()); 109 m_count++ ; 110 111 for(unsigned int i = 0; i < node->getNumChildren(); i++) traverse_r(node->getChild(i), depth + 1 ); 112 } 155 void GTreeCheck::findRepeatCandidates(unsigned int repeat_min, unsigned int vertex_min) 156 { 157 unsigned int nall = m_digest_count->size() ; ... 166 // over distinct subtrees (ie progeny digests) 167 for(unsigned int i=0 ; i < nall ; i++) 168 { 169 std::pair& kv = m_digest_count->get(i) ; 170 171 std::string& pdig = kv.first ; 172 unsigned int ndig = kv.second ; // number of occurences of the progeny digest 173 174 GNode* node = m_root->findProgenyDigest(pdig) ; // first node that matches the progeny digest 175 176 // suspect problem with allowing leaf repeaters is that digesta are not-specific enough, 177 // so get bad matching 178 // 179 // allowing leaf repeaters results in too many, so place vertex count reqirement too 180 181 182 unsigned int nprog = node->getProgenyCount() ; // includes self when GNode.m_selfdigest is true 183 unsigned int nvert = node->getProgenyNumVertices() ; // includes self when GNode.m_selfdigest is true 184 185 // hmm: maybe selecting based on ndig*nvert 186 // but need to also require ndig > smth as dont want to repeat things like the world 187 188 bool select = ndig > repeat_min && nvert > vertex_min ; 189 190 if(i < 15) LOG(info) 191 << ( select ? "**" : " " ) 192 << " i " << std::setw(3) << i 193 << " pdig " << std::setw(32) << pdig 194 << " ndig " << std::setw(6) << ndig 195 << " nprog " << std::setw(6) << nprog 196 << " nvert " << std::setw(6) << nvert 197 << " n " << node->getName() 198 ; 199 200 if(select) m_repeat_candidates.push_back(pdig); 201 } 202 203 // erase repeats that are enclosed within other repeats 204 // ie that have an ancestor which is also a repeat candidate 205 206 m_repeat_candidates.erase( 207 std::remove_if(m_repeat_candidates.begin(), m_repeat_candidates.end(), *this ), 208 m_repeat_candidates.end() 209 ); 210 211 212 } 213 214 bool GTreeCheck::operator()(const std::string& dig) 215 { 216 bool cr = isContainedRepeat(dig, 3); 217 218 if(cr) LOG(info) 219 << "GTreeCheck::operator() " 220 << " pdig " << std::setw(32) << dig 221 << " disallowd as isContainedRepeat " 222 ; 223 224 return cr ; 225 } 226 227 bool GTreeCheck::isContainedRepeat( const std::string& pdig, unsigned int levels ) const 228 { 229 // for the first node that matches the *pdig* progeny digest 230 // look back *levels* ancestors to see if any of the immediate ancestors 231 // are also repeat candidates, if they are then this is a contained repeat 232 // and is thus disallowed in favor of the ancestor that contains it 233 234 GNode* node = m_root->findProgenyDigest(pdig) ; 235 std::vector& ancestors = node->getAncestors(); 236 unsigned int asize = ancestors.size(); 237 238 for(unsigned int i=0 ; i < std::min(levels, asize) ; i++) 239 { 240 GNode* a = ancestors[asize - 1 - i] ; 241 std::string& adig = a->getProgenyDigest(); 242 if(std::find(m_repeat_candidates.begin(), m_repeat_candidates.end(), adig ) != m_repeat_candidates.end()) 243 { 244 return true ; 245 } 246 } 247 return false ; 248 } 015 class GGEO_API GNode { ... 148 private: 149 std::string m_local_digest ; 150 std::string m_progeny_digest ; 151 std::vector m_progeny ; 152 std::vector m_ancestors ; 024 GNode::GNode(unsigned int index, GMatrixF* transform, GMesh* mesh) 25 : 26 m_selfdigest(true), 442 std::string& GNode::getProgenyDigest() 443 { 444 if(m_progeny_digest.empty()) 445 { 446 std::vector& progeny = getProgeny(); 447 m_progeny_count = progeny.size(); 448 GNode* extra = m_selfdigest ? this : NULL ; 449 m_progeny_digest = GNode::localDigest(progeny, extra) ; 450 } 451 return m_progeny_digest ; 452 } 283 std::vector& GNode::getProgeny() 284 { 285 if(m_progeny.size() == 0) 286 { 287 // call on children, as wish to avoid collecting self 288 for(unsigned int i = 0; i < getNumChildren(); i++) getChild(i)->collectProgeny(m_progeny); 289 } 290 return m_progeny ; 291 } 292 293 void GNode::collectProgeny(std::vector& progeny) 294 { 295 progeny.push_back(this); 296 for(unsigned int i = 0; i < getNumChildren(); i++) getChild(i)->collectProgeny(progeny); 297 }