triskele/include/ArrayTree/ArrayTreeBuilder.tpp
Git Merciol caa6e85da2 modifié : MakefileNoOTB
modifié :         include/ArrayTree/ArrayTreeBuilder.hpp
	modifié :         include/ArrayTree/ArrayTreeBuilder.tpp
	modifié :         include/TreeStats.hpp
	modifié :         include/TreeStats.tpp
	modifié :         src/TreeStats.cpp
2018-03-14 14:27:59 +01:00

751 lines
27 KiB
C++

#ifndef _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP
#define _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP
using namespace boost::chrono;
// ========================================
template<typename WeightT, typename PixelT>
inline
ArrayTreeBuilder<WeightT, PixelT>::ArrayTreeBuilder (const Raster<PixelT> &raster, const GraphWalker &graphWalker,
const TreeType &treeType, const bool &countingSort) :
coreCount (boost::thread::hardware_concurrency ()),
raster (raster),
graphWalker (graphWalker),
treeType (treeType),
countingFlag (countingSort),
compWeights (nullptr),
childCount (nullptr),
newCompId (nullptr)
{
DEF_LOG ("ArrayTreeBuilder::ArrayTreeBuilder", "");
}
template<typename WeightT, typename PixelT>
inline
ArrayTreeBuilder<WeightT, PixelT>::~ArrayTreeBuilder () {
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::buildTree (Tree &tree, WeightAttributes<WeightT> &weightAttributes) {
DEF_LOG ("ArrayTreeBuilder::buildTree", "size:" << graphWalker.vertexMaxCount ());
setTreeSize (tree, graphWalker.size);
weightAttributes.updateTranscient ();
if (!leafCount)
return;
leaders.book (leafCount);
childCount = childrenStart+2;
newCompId = leaders.getLeaders ();
compWeights = weightAttributes.getValues ();
SMART_LOG_EXPR (dealThreadFill_n (leafCount-1, coreCount, compWeights, 0));
auto start = high_resolution_clock::now ();
switch (treeType) {
case MIN:
buildTree (tree, MinWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
case MAX:
buildTree (tree, MaxWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
case TOS:
buildTree (tree, MedianWeight<PixelT, WeightT> (raster.getPixels (), graphWalker));
break;
case ALPHA:
buildTree (tree, DiffWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
default:
cerr << "*** unknown tree type: " << treeType << endl;
}
globalTreeStats.addTime (buildTreeStats, duration_cast<duration<double> > (high_resolution_clock::now ()-start).count ());
globalTreeStats.addDim (treeType, leafCount, nodeCount-leafCount);
weightAttributes.setWeightBounds (tree);
leaders.free ();
newCompId = nullptr;
buildChildren ();
childCount = nullptr;
SMART_LOG (tree.printTree ());
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::setAttributProfiles (AttributeProfiles<PixelT> &attributeProfiles) {
DEF_LOG ("ArrayTreeBuilder::setAttributProfiles", "");
attributeProfiles.updateTranscient ();
switch (treeType) {
case MIN:
setAttributProfiles (attributeProfiles, MinWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
case MAX:
setAttributProfiles (attributeProfiles, MaxWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
case TOS:
setAttributProfiles (attributeProfiles, MedianWeight<PixelT, WeightT> (raster.getPixels (), graphWalker));
break;
case ALPHA:
setAttributProfiles (attributeProfiles, DiffWeight<PixelT, WeightT> (raster.getPixels (), raster.getSize ()));
break;
default:
cerr << "*** unknown tree type: " << treeType << endl;
}
}
// ========================================
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::buildTree (Tree &tree, const WeightFunct &weightFunct) {
DEF_LOG ("ArrayTreeBuilder::buildTree", "");
coreCount = tree.getCoreCount ();
// buildParents
vector<Edge<WeightT> > allEdges (graphWalker.edgeMaxCount ());
vector<Rect> tiles;
vector<Rect> boundaries;
vector<bool> verticalBoundaries;
const Size &size (graphWalker.size);
graphWalker.setTiles (coreCount, Rect (NullPoint, size), tiles, boundaries, verticalBoundaries);
unsigned int tileCount = tiles.size ();
unsigned int boundCount = boundaries.size ();
vector<DimImg> vertexMaxBounds;
vector<DimImg> edgesMaxBounds;
graphWalker.setMaxBounds (tiles, vertexMaxBounds, edgesMaxBounds);
vector<Edge<WeightT> *> tileEdges (tileCount);
vector<DimImg> compBases (tileCount);
vector<DimImg> compTops (tileCount);
Edge<WeightT> *edgeBase = &allEdges[0];
for (unsigned int i = 0; i < tileCount; ++i) {
tileEdges [i] = &allEdges[edgesMaxBounds[i]];
compBases [i] = compTops [i] = vertexMaxBounds [i];
}
dealThreadRange (tileCount, coreCount, [this, &tileEdges, &weightFunct, &tiles, &compTops] (DimImg threadId) {
buildParents (tileEdges [threadId], weightFunct, tiles [threadId], compTops [threadId]);
});
SMART_LOG ("leaders:" << endl
<< printMap (leaders.getLeaders (), size, 0) << endl << endl
<< "compWeights:" << endl
<< printMap (compWeights, size, 0) << endl << endl
<< tree.printTree (2*leafCount-1));
// merge sub-tree
DimImg compCount = compTops [0];
DimImg *topC = NULL;
DimImg compBase = vertexMaxBounds[tileCount];
if (boundCount) {
vector<Edge<WeightT> *> edgeBounds (boundCount);
vector<DimImg> edgeCounts (boundCount);
Edge<WeightT> *allBoundEdges = edgeBase;
for (unsigned int i = 0; i < boundCount; ++i) {
edgeBounds [i] = edgeBase;
DimImg borderDim = verticalBoundaries [i] ? boundaries[i].height : boundaries[i].width;
edgeBase += graphWalker.edgeBoundaryMaxCount (borderDim);
}
dealThreadRange (boundCount, coreCount, [this, &edgeCounts, &boundaries, &verticalBoundaries, &edgeBounds, &weightFunct] (DimImg id) {
edgeCounts [id] = graphWalker.getSortedEdges (boundaries [id], verticalBoundaries [id] ?
Vertical : Horizontal, edgeBounds [id], weightFunct);
});
LOG ("edgeBounds: " << edgeBase-allBoundEdges);
unsigned int rangeIdx = 0;
DimImg maxC = 0;
callOnSortedSets<DimImg, WeightT> (edgeCounts,
[&edgeBounds] (const DimImg &vectId, const DimImg &itemId) {
return edgeBounds [vectId][itemId].weight;
},
weightFunct.isWeightInf,
[this, &edgeBounds, &topC, &maxC, &rangeIdx, &tileCount, &compBases, &compBase, &compTops, &size, &weightFunct] (const DimImg &vectId, const DimImg &itemId) {
Edge<WeightT> *edge = &edgeBounds [vectId][itemId];
if (topC == NULL || *topC >= maxC)
for ( ; rangeIdx < tileCount; ++rangeIdx) {
maxC = rangeIdx == tileCount-1 ? leafCount : compBases[rangeIdx+1];
if (compTops[rangeIdx] < maxC) {
compBase = compTops[rangeIdx];
compBases.push_back (compBase);
compTops.push_back (compBase);
topC = &compTops[compTops.size ()-1];
break;
}
}
connectLeaf (point2idx (size, edge->points[0]), point2idx (size, edge->points[1]), edge->weight, *topC, weightFunct);
});
}
SMART_LOG ("compWeights:" << endl
<< printMap (compWeights, size, 0) << endl << endl
<< tree.printTree (2*leafCount-1));
// compress
DimImg maxUsed = max (compTops[tileCount-1], topC != NULL ? *topC : 0);
dealThreadFill_n (maxUsed, coreCount, newCompId, DimImg_MAX);
SMART_LOG ("reuse leaders:" << endl
<< printMap (newCompId, size, 0) << endl << endl);
compCount = updateNewId (compBases, compTops, weightFunct);
SMART_LOG ("updateNewId:" << endl
<< printMap (newCompId, size, 0) << endl << endl);
compress (maxUsed);
SMART_LOG ("compress:" << endl
<< printMap (newCompId, size, 0) << endl << endl);
leaders.free ();
while (compCount > 1 && childCount[compCount-1] == 1) {
--compCount;
compParents [compCount-1] = DimImg_MAX;
SMART_LOG ("reduce lonely root:" << printComp (compCount) << endl);
}
setNodeCount (tree, leafCount+compCount);
LOG ("nodeCount:" << tree.getNodeCount());
// DimEdge root = compCount-1;
// compParents[root] = root;
SMART_LOG ("compWeights:" << endl
<< printMap (compWeights, size, 0) << endl << endl);
}
// ========================================
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::setAttributProfiles (AttributeProfiles<PixelT> &attributeProfiles, const WeightFunct &weightFunct) {
PixelT *leafAP = attributeProfiles.getValues ();
dealThreadBound (leafCount, coreCount, [&weightFunct, &leafAP] (const DimImg &minVal, const DimImg &maxVal) {
weightFunct.copyPixelsBound (leafAP, minVal, maxVal);
});
PixelT *compAP = leafAP+leafCount;
dealThreadBound (getCompCount (), coreCount, [this, &weightFunct, &compAP] (const DimImg &minVal, const DimImg &maxVal) {
weightFunct.weight2valueBound (compAP, compWeights, minVal, maxVal);
});
}
// ========================================
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::buildParents (Edge<WeightT> *edges, const WeightFunct &weightFunct,
const Rect &tile, DimImg &topParent) {
SMART_DEF_LOG ("ArrayTreeBuilder::buildParents", " tile:" << tile << " topParent:" << topParent << " counting:" << countingFlag);
DimEdge edgeCount = (sizeof (WeightT) < 3 || countingFlag) ?
graphWalker.getCountingSortedEdges<WeightT, WeightFunct> (tile, Surface, edges, weightFunct) :
graphWalker.getSortedEdges (tile, Surface, edges, weightFunct);
const Size &size = graphWalker.size;
for (DimEdge edgeIdx = 0; edgeIdx < edgeCount; ++edgeIdx) {
Edge<WeightT> &curEdge = edges[edgeIdx];
DimImg pa = point2idx (size, curEdge.points[0]);
DimImg pb = point2idx (size, curEdge.points[1]);
DimImg la = leaders.find (pa);
DimImg lb = leaders.find (pb);
DimImg ra = findRoot (leafParents [la]); // for alphaTree
DimImg rb = findRoot (leafParents [lb]); // for alphaTree
BOOST_ASSERT (pa < leafCount);
BOOST_ASSERT (pb < leafCount);
BOOST_ASSERT (la < leafCount);
BOOST_ASSERT (lb < leafCount);
BOOST_ASSERT (ra < leafCount || ra == DimImg_MAX);
BOOST_ASSERT (rb < leafCount || rb == DimImg_MAX);
BOOST_ASSERT (ra == DimImg_MAX || compParents [ra] == DimImg_MAX);
BOOST_ASSERT (rb == DimImg_MAX || compParents [rb] == DimImg_MAX);
SMART_LOG (" e:" << printEdge (curEdge, size));
SMART_LOG ("pa:" << pa << " pb:" << pb << " la:" << la << " lb:" << lb);
SMART_LOG ("ra:" << printComp (ra) << " rb:" << printComp (rb));
if (la == lb)
continue;
if (ra == DimImg_MAX) {
swap (la, lb);
swap (ra, rb);
}
DimImg leader = DimImg_MAX;
if (ra == DimImg_MAX) {
// ra = rb = DimImg_MAX
createParent (topParent, curEdge.weight, leafParents [la], leafParents [lb]);
if (weightFunct.isWeightInf (weightFunct.getWeight(la), weightFunct.getWeight(lb)))
swap (la, lb);
leader = la;
} else if (rb == DimImg_MAX) {
if (curEdge.weight == compWeights[ra]) {
// rb.weight <= curEdge.weight = ra.weight
addChild (ra, leafParents [lb]);
leader = la;
} else {
// ra.weight < curEdge.weight = rb.weight
createParent (topParent, curEdge.weight, compParents [ra], leafParents [lb]);
leader = lb;
}
} else if (ra == rb) {
// XXX
BOOST_ASSERT (false);
continue;
} else if (compWeights[ra] == compWeights [rb]) {
// ra.weight = rb.weight // XXX ?= curEdge.weight
if (childCount [ra] < childCount [rb]) {
swap (la, lb);
swap (ra, rb);
}
addChildren (ra, rb);
leader = la;
} else {
if (weightFunct.isWeightInf (compWeights[ra], compWeights[rb])) {
swap (la, lb);
swap (ra, rb);
}
leader = la;
if (compWeights[ra] == curEdge.weight)
// rb.weight <= ra.weight = curEdge.weight
addChild (ra, compParents [rb]);
else
// ra.weight & rb.weight < curEdge.weight
createParent (topParent, curEdge.weight, compParents [ra], compParents [rb]);
}
BOOST_ASSERT (leader != DimImg_MAX);
leaders.link (pa, leader);
leaders.link (pb, leader);
SMART_LOG (" leader:" << leader << " ra:" << printComp (ra) << " rb:" << printComp (rb));
}
SMART_LOG ("topParent:" << topParent);
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::unlinkParent (const DimImg &par) {
SMART_DEF_LOG ("ArrayTreeBuilder::unlinkParent", "par: " << printComp (par));
if (par == DimImg_MAX)
return;
BOOST_ASSERT (childCount [par]);
--childCount [par];
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::connectLeaf (DimImg a, DimImg b, const WeightT &weight, DimImg &parCount, const WeightFunct &weightFunct) {
SMART_DEF_LOG ("ArrayTreeBuilder::connectLeaf", "a:" << a << " b:" << b << " weight:" << weight);
BOOST_ASSERT (a < leafCount);
BOOST_ASSERT (b < leafCount);
BOOST_ASSERT (leafParents[a] < leafCount || leafParents[a] == DimImg_MAX);
BOOST_ASSERT (leafParents[b] < leafCount || leafParents[b] == DimImg_MAX);
DimImg parA = findTopComp (leafParents[a], weight, weightFunct);
DimImg parB = findTopComp (leafParents[b], weight, weightFunct);
SMART_LOG ("parA: " << printComp (parA) << " parB: " << printComp (parB));
// upW0 : no parent(s)
// Border case if parX == DimImg_MAX
if (parA == parB) {
if (parA == DimImg_MAX) {
SMART_LOG ("upW0: no parents");
createParent (parCount, weight, leafParents [a], leafParents [b]);
SMART_LOG ("createParent: " << printComp (leafParents[a]));
}
SMART_LOG ("same parents for: " << a << ", " << b);
return;
}
if (parA == DimImg_MAX) {
swap (a, b);
swap (parA, parB);
SMART_LOG ("swap: " << printComp (parA) << " " << printComp (parB));
}
if ((parA == DimImg_MAX || weightFunct.isWeightInf (weight, compWeights[parA])) &&
weightFunct.isWeightInf (weight, compWeights[parB])) {
// upW1 & upW2 : upper
SMART_LOG ("upW1 | upW2: upper");
unlinkParent (parA);
unlinkParent (parB);
SMART_LOG ("parA: " << printComp (parA) << " parB: " << printComp (parB));
DimImg newComp = createParent (parCount, weight, leafParents [a], leafParents [b]);
SMART_LOG ("createParent: " << printComp (newComp));
connect3Comp (newComp, parA, parB, weightFunct);
return;
}
if (parA != DimImg_MAX && weightFunct.isWeightInf (compWeights[parA], compWeights[parB])) {
swap (a, b);
swap (parA, parB);
SMART_LOG ("swap: " << printComp (parA) << " " << printComp (parB));
}
if (weightFunct.isWeightInf (compWeights[parB], weight) &&
(parA == DimImg_MAX ||
weightFunct.isWeightInf (compWeights[parA], weight) ||
weightFunct.isWeightInf (weight, compWeights[parA]))) {
// loW0 | loW1 | loW2 : lower
SMART_LOG ("loW0 | loW1 | loW2");
if (weightFunct.isWeightInf (compWeights[parA], weight)) {
swap (a, b);
swap (parA, parB);
SMART_LOG ("swap: " << printComp (parA) << " " << printComp (parB));
}
DimImg grandParB = findTopComp (compParents[parB], weightFunct);
unlinkParent (grandParB);
SMART_LOG ("grandParB: " << printComp (grandParB));
if (parA == DimImg_MAX || weightFunct.isWeightInf (weight, compWeights[parA])) {
// loW1 | loW2
SMART_LOG ("loW1 | loW2: lower");
unlinkParent (parA);
SMART_LOG ("parA: " << printComp (parA));
DimImg newComp = createParent (parCount, weight, leafParents [a], compParents [parB]);
SMART_LOG ("createParent: " << printComp (newComp));
connect3Comp (newComp, parA, grandParB, weightFunct);
return;
}
// loW0
SMART_LOG ("loW0: lower");
DimImg grandParA = findTopComp (compParents[parA], weightFunct);
unlinkParent (grandParA);
SMART_LOG ("grandParA: " << printComp (grandParA));
DimImg newComp = createParent (parCount, weight, compParents [parA], compParents [parB]);
SMART_LOG ("createParent: " << printComp (newComp));
connect3Comp (newComp, grandParA, grandParB, weightFunct);
return;
}
// eqW0 | eqW1 | eqW2 : no creation
if (parA == DimImg_MAX || weightFunct.isWeightInf (weight, compWeights[parA])) {
// eqW1 | eqW2
SMART_LOG ("eqW1 | eqW2: incr leaf");
unlinkParent (parA);
++childCount[parB];
leafParents[a] = parB;
SMART_LOG ("parA: " << printComp (parA) << " parB: " << printComp (parB));
}
// eqW0 | eqW1 | eqW2
SMART_LOG ("eqW0 | eqW1 | eqW2: connect");
connectComp (parA, parB, weightFunct);
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::connect3Comp (DimImg newComp, DimImg topA, DimImg topB, const WeightFunct &weightFunct) {
SMART_DEF_LOG ("ArrayTreeBuilder::connect3Comp", "newComp:" << newComp << " topA:" << topA << " topB:" << topB);
BOOST_ASSERT (newComp != DimImg_MAX);
if (topB == DimImg_MAX)
swap (topA, topB);
if (topB == DimImg_MAX)
return;
BOOST_ASSERT (topB != DimImg_MAX);
if (topA != DimImg_MAX && weightFunct.isWeightInf (compWeights[topA], compWeights[topB]))
swap (topA, topB);
BOOST_ASSERT (findTopComp (topB, weightFunct) == topB);
BOOST_ASSERT (weightFunct.isWeightInf (compWeights[newComp], compWeights[topB]));
compParents[newComp] = topB;
++childCount[topB];
SMART_LOG ("topB: " << printComp (topB));
connectComp (topA, topB, weightFunct);
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::connectComp (DimImg topA, DimImg topB, const WeightFunct &weightFunct) {
SMART_DEF_LOG ("ArrayTreeBuilder::connectComp", "topA:" << topA << " topB:" << topB);
for (;;) {
if (topA == DimImg_MAX || topB == DimImg_MAX)
return;
BOOST_ASSERT (findTopComp (topA, weightFunct) == topA);
BOOST_ASSERT (findTopComp (topB, weightFunct) == topB);
if (weightFunct.isWeightInf (compWeights[topA], compWeights[topB]))
swap (topA, topB);
topB = findTopComp (topB, compWeights[topA], weightFunct);
if (topA == topB)
return;
if (compWeights[topA] == compWeights[topB] &&
childCount[topA] < childCount[topB])
swap (topA, topB);
DimImg grandParB = findTopComp (compParents[topB], weightFunct);
if (compWeights[topA] == compWeights[topB]) {
childCount[topA] += childCount[topB];
childCount[topB] = 0;
} else
++childCount[topA];
compParents[topB] = topA;
SMART_LOG ("topA: " << printComp (topA) << " topB: " << printComp (topB));
if (grandParB == DimImg_MAX)
return;
BOOST_ASSERT (childCount [grandParB]);
--childCount[grandParB];
SMART_LOG ("grandParB: " << printComp (grandParB));
topB = topA;
topA = findTopComp (grandParB, compWeights[topA], weightFunct);
}
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::updateNewId (const vector<DimImg> &compBases, const vector<DimImg> &compTops,
const WeightFunct &weightFunct) {
// DEF_LOG ("ArrayTreeBuilder::updateNewId", "");
DimImg compCount = compBases[0];
vector<DimImg> sizes (compBases.size ());
for (DimImg i = 0; i < sizes.size (); ++i)
sizes [i] = compTops [i] - compBases [i];
// XXX non parallèle
callOnSortedSets<DimImg, WeightT> (sizes,
[this, &compBases] (const DimImg &vectId, const DimImg &itemId) {
return compWeights[compBases[vectId]+itemId]; },
weightFunct.isWeightInf,
[this, &compBases, &compCount] (const DimImg &vectId, const DimImg &itemId) {
updateNewId (compBases[vectId]+itemId, compCount); });
return compCount;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::updateNewId (const DimImg curComp, DimImg &compCount) {
if (newCompId[curComp] != DimImg_MAX)
// top already set
return;
const DimImg &top = findMultiChildrenTop (curComp);
BOOST_ASSERT (top != DimImg_MAX);
BOOST_ASSERT (childCount[top]);
if (childCount[top] < 2 && compParents[top] != DimImg_MAX) {
// mark lonely nodes
// XXX todo: mark curComp => top
newCompId[curComp] = 0;
return;
}
if (curComp != top) {
BOOST_ASSERT (curComp != DimImg_MAX);
DimImg newTopIdx = newCompId[top];
if (newTopIdx == DimImg_MAX)
newTopIdx = newCompId[top] = compCount++;
const DimNodeId &newTopChildCount = childCount[top];
const DimImg &newTopCompParent = compParents[top];
//const WeightT &newTopWeight = compWeights[top];
for (DimImg sibling = curComp; sibling != top; ) {
DimImg nextSibling = compParents[sibling];
newCompId[sibling] = newTopIdx;
childCount[sibling] = newTopChildCount;
compParents[sibling] = newTopCompParent;
// compWeights[sibling] = newTopWeight;
sibling = nextSibling;
}
return;
}
newCompId[curComp] = compCount++;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::compress (const DimImg &compTop) {
SMART_DEF_LOG ("ArrayTreeBuilder::compress", " compTop:" << compTop);
dealThreadRange (compTop, coreCount, [this] (const DimImg &curComp) {
if (newCompId[curComp] || childCount[curComp] > 1)
return;
// reduce lonely nodes (newCompId == 0)
const DimImg &top = findNotLonelyTop (curComp);
BOOST_ASSERT (top == DimImg_MAX || compParents[top] == DimImg_MAX || childCount[top] > 1);
BOOST_ASSERT (curComp != top);
childCount[curComp] = childCount[top];
compParents[curComp] = compParents[top]; // XXX pb if //
newCompId[curComp] = newCompId[top];
compWeights[curComp] = compWeights[top];
});
dealThreadRange (compTop, coreCount, [this] (const DimImg &curComp) {
DimImg old = compParents[curComp];
if (old != DimImg_MAX)
compParents[curComp] = newCompId[old];
});
dealThreadRange (leafCount, coreCount, [this] (const DimImg &leaf) {
DimImg old = leafParents[leaf];
if (old != DimImg_MAX)
leafParents[leaf] = newCompId[old];
});
// XXX non parallèle
for (DimImg curComp = 0; curComp < compTop; ) {
DimImg newIdxComp = newCompId[curComp];
if (newIdxComp == curComp || newIdxComp == DimImg_MAX || newCompId[newIdxComp] == newIdxComp) {
++curComp;
continue;
}
SMART_LOG ("comp curComp:" << curComp << " newIdxComp:" << newIdxComp);
swap (compParents[curComp], compParents[newIdxComp]);
swap (compWeights[curComp], compWeights[newIdxComp]);
swap (childCount[curComp], childCount[newIdxComp]);
swap (newCompId[curComp], newCompId[newIdxComp]);
}
// XXX YYY curComp ? compTop ?
}
// ========================================
template<typename WeightT, typename PixelT>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::createParent (DimImg &topParent, const WeightT &weight, DimImg &parentChildA, DimImg &parentChildB) {
childCount [topParent] = 2;
compWeights [topParent] = weight;
return parentChildA = parentChildB = topParent++;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::addChild (const DimImg &parent, DimImg &child) {
++childCount [parent];
child = parent;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::addChildren (const DimImg &parent, const DimImg &sibling) {
childCount [parent] += childCount [sibling];
childCount [sibling] = 0;
compParents [sibling] = parent;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::findRoot (DimImg comp) {
if (comp == DimImg_MAX)
return comp;
for (;;) {
DimImg p = compParents [comp];
if (p == DimImg_MAX)
return comp;
comp = p;
}
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::findTopComp (const DimImg &comp, const WeightFunct &weightFunct) {
if (comp == DimImg_MAX)
return DimImg_MAX;
DimImg result = findTopComp (comp, compWeights[comp], weightFunct);
BOOST_ASSERT (result < leafCount);
// XXX pas pour TOS ! BOOST_ASSERT (compWeights[result] == compWeights[comp]);
return result;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::findTopComp (DimImg comp, const WeightT &weight, const WeightFunct &weightFunct) {
if (comp == DimImg_MAX)
return DimImg_MAX;
if (weightFunct.isWeightInf (weight, compWeights [comp]))
return findTopComp (comp, compWeights [comp], weightFunct);
DimImg last = comp;
for (;;) {
if (comp == DimImg_MAX)
return last;
if (weightFunct.isWeightInf (weight, compWeights [comp]))
return last;
last = comp;
comp = compParents[comp];
}
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::findNotLonelyTop (DimImg comp) {
BOOST_ASSERT (comp != DimImg_MAX);
for (;;) {
if (childCount[comp] > 1)
return comp;
const DimImg &parent = compParents[comp];
if (parent == DimImg_MAX)
return comp;
comp = parent;
}
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline DimImg
ArrayTreeBuilder<WeightT, PixelT>::findMultiChildrenTop (DimImg comp) {
BOOST_ASSERT (comp != DimImg_MAX);
for (;;) {
if (newCompId [comp] != DimImg_MAX)
return comp;
const DimImg &parent = compParents[comp];
if (parent == DimImg_MAX)
return comp;
if (compWeights[comp] != compWeights[parent]) {
BOOST_ASSERT (childCount[comp] > 0);
return comp;
}
BOOST_ASSERT (!childCount[comp]);
comp = parent;
}
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::buildChildren () {
SMART_DEF_LOG ("ArrayTreeBuilder::buildChildren", "");
BOOST_ASSERT (childrenStart[0] == 0);
BOOST_ASSERT (childrenStart[1] == 0);
DimImg compCount = getCompCount ();
partial_sum (childCount, childCount+compCount, childCount);
// set
DimNodeId *childGetOrder = childrenStart+1;
for (DimNodeId i = 0; i < nodeCount-1; ++i) {
if (leafParents[i] == DimImg_MAX)
continue;
BOOST_ASSERT (leafParents[i] < compCount);
children[childGetOrder[leafParents[i]]++] = i;
}
BOOST_ASSERT (childrenStart[0] == 0);
}
// ========================================
template<typename WeightT, typename PixelT>
ArrayTreeBuilder<WeightT, PixelT>::CPrintComp::CPrintComp (const ArrayTreeBuilder &atb, const DimImg &compId)
: atb (atb), compId (compId) {
}
template<typename WeightT, typename PixelT>
inline ostream &
ArrayTreeBuilder<WeightT, PixelT>::CPrintComp::print (ostream &out) const {
if (compId == DimImg_MAX)
return out << "M(-/-)";
return out << compId << "(" << atb.childCount[compId] << "/" << atb.compWeights [compId] << ")";
}
// template<typename WeightT, typename PixelT>
// inline ArrayTreeBuilder<WeightT, PixelT>::CPrintComp
// ArrayTreeBuilder<WeightT, PixelT>::printComp (const DimImg &compId) const {
// return ArrayTreeBuilder<WeightT, PixelT>::CPrintComp (*this, compId);
// }
// template<typename WeightT, typename PixelT>
// inline ostream&
// operator << (ostream& out, const ArrayTreeBuilder<WeightT, PixelT>::CPrintComp &lc) {
// return lc.print (out);
// }
// ========================================
#endif // _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP