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.
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
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
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.
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<unsigned>("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<std::string,unsigned int>& 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<GNode*>& 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<GNode*> m_progeny ;
152 std::vector<GNode*> 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<GNode*>& 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*>& 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<GNode*>& progeny)
294 {
295 progeny.push_back(this);
296 for(unsigned int i = 0; i < getNumChildren(); i++) getChild(i)->collectProgeny(progeny);
297 }