triskele/include/ArrayTree/ArrayTreeBuilder.tpp
Git Merciol 300bfd965d modifié : MakefileNoOTB
modifié :         include/Appli/Option.hpp
	modifié :         include/ArrayTree/ArrayTreeBuilder.hpp
	modifié :         include/ArrayTree/ArrayTreeBuilder.tpp
	modifié :         include/AttributeProfiles.hpp
	modifié :         include/AttributeProfiles.tpp
	modifié :         include/Attributes/AreaAttributes.hpp
	modifié :         include/Attributes/AreaAttributes.tpp
	modifié :         include/Attributes/MoIAttributes.hpp
	modifié :         include/Attributes/MoIAttributes.tpp
	modifié :         include/Attributes/SDAttributes.hpp
	modifié :         include/Attributes/SDAttributes.tpp
	modifié :         include/CompAttribute.hpp
	modifié :         include/CompAttribute.tpp
	modifié :         src/Appli/Option.cpp
	modifié :         src/testMain.cpp
2018-02-20 16:39:24 +01:00

772 lines
27 KiB
C++

#ifndef _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP
#define _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP
// ========================================
template<typename WeightT, typename PixelT>
inline
ArrayTreeBuilder<WeightT, PixelT>::ArrayTreeBuilder (Raster<PixelT> &raster, const GraphWalker &graphWalker,
const TreeType &treeType, const bool &countingSort) :
coreCount (boost::thread::hardware_concurrency ()),
raster (raster),
graphWalker (graphWalker),
type (treeType),
countingFlag (countingSort),
compWeights (nullptr),
childCountRec (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);
childCountRec = childCount+2;
newCompId = leaders.getLeaders ();
compWeights = weightAttributes.getValues ();
switch (type) {
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;
default:
cerr << "*** unknown tree type: " << type << endl;
}
weightAttributes.setWeightBounds (tree);
leaders.free ();
newCompId = nullptr;
buildChildren ();
childCountRec = nullptr;
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::setAttributProfiles (AttributeProfiles<PixelT> &attributeProfiles) {
DEF_LOG ("ArrayTreeBuilder::setAttributProfiles", "");
attributeProfiles.updateTranscient ();
switch (type) {
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;
default:
cerr << "*** unknown tree type: " << type << 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<Edge<WeightT> *> tileEdges (tileCount);
vector<DimImg> compBases (tileCount);
vector<DimImg> compTops (tileCount);
DimImg compBase = 0;
Edge<WeightT> *edgeBase = &allEdges[0];
for (unsigned int i = 0; i < tileCount; ++i) {
tileEdges [i] = edgeBase;
Size zoneSize (tiles[i].width, tiles[i].height);
edgeBase += graphWalker.edgeMaxCount (zoneSize);
compBases [i] = compBase;
compTops [i] = compBase;
compBase += graphWalker.vertexMaxCount (zoneSize); /* -1, but prety LOG */
}
dealThreadRange (tileCount, coreCount, [this, &tileEdges, &weightFunct, &tiles, &compTops] (DimImg threadId) {
buildParents (tileEdges [threadId], weightFunct, tiles [threadId], compTops [threadId]);
});
// merge sub-tree
DimImg compCount = compTops [0];
DimImg *topC = NULL;
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);
});
}
// compress
DimImg maxUsed = max (compTops[tileCount-1], topC != NULL ? *topC : 0);
dealThreadFill_n (maxUsed, coreCount, newCompId, DimImg_MAX);
compCount = updateNewId (compBases, compTops, weightFunct);
compress (maxUsed);
leaders.free ();
setNodeCount (tree, leafCount+compCount);
LOG ("nodeCount:" << tree.getNodeCount());
DimEdge root = compCount-1;
compParents[root] = root;
}
// ========================================
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>::fillAPTree (PixelT *leafAPTree, const WeightFunct &weightFunct) {
// DEF_LOG ("ArrayTreeBuilder::fillLeafAPTree", "");
// dealThreadBound (leafCount, coreCount, [&weightFunct, &leafAPTree] (const DimImg &minVal, const DimImg &maxVal) {
// weightFunct.copyPixelsBound (leafAPTree, minVal, maxVal);
// });
// PixelT *compAPTree = leafAPTree+leafCount;
// dealThreadBound (getCompCount (), coreCount, [this, &weightFunct, &compAPTree] (const DimImg &minVal, const DimImg &maxVal) {
// weightFunct.weight2valueBound (compAPTree, 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) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::buildParents", " tile:" << tile << " topParent:" << topParent << " counting:" << countingFlag);
#endif
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 = leafParents [la];
DimImg rb = leafParents [lb];
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);
#ifdef SMART_LOG
LOG (" w:" << curEdge.weight << " pa:" << pa << " pb:" << pb << " la:" << la << " lb:" << lb << " ra:" << ra << " rb:" << rb);
#endif
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);
leader = lb;
} else if (compWeights[ra] == compWeights [rb]) {
// ra.weight = rb.weight // XXX ?= curEdge.weight
if (childCountRec [ra] < childCountRec [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);
#ifdef SMART_LOG
LOG (" leader:" << leader << " w:" << compWeights [leader] << " c:" << childCountRec [leader]);
#endif
}
#ifdef SMART_LOG
LOG ("topParent:" << topParent);
#endif
}
// ========================================
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) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::connectLeaf", "a:" << a << " b:" << b << " weight:" << weight);
#endif
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], weightFunct);
DimImg parB = findTopComp (leafParents[b], weightFunct);
if (parA == DimImg_MAX) {
swap (a, b);
swap (parA, parB);
}
if (parB == DimImg_MAX) {
// parA = parB = DimImg_MAX
createParent (parCount, weight, leafParents [a], leafParents [b]);
return;
}
if (parA == DimImg_MAX) {
// parA = DimImg_MAX & parB != DimImg_MAX
parB = findTopComp (parB, weight, weightFunct);
if (!weightFunct.isWeightInf (compWeights[parB], weight)) {
leafParents[a] = parB;
++childCountRec[parB];
return;
}
parA = findTopComp (compParents[parB], weightFunct);
if (parA == DimImg_MAX) {
createParent (parCount, weight, leafParents [a], compParents [parB]);
return;
}
createParent (parCount, weight, leafParents [a], compParents [parB]);
compParents[leafParents [a]] = parA;
return;
}
BOOST_ASSERT (parA < leafCount);
BOOST_ASSERT (parB < leafCount);
if (parA == parB)
return;
if (weightFunct.isWeightInf (compWeights[parA], compWeights[parB])) {
swap (a, b);
swap (parA, parB);
}
if (weightFunct.isWeightInf (weight, compWeights[parB])) {
// 1
BOOST_ASSERT (weightFunct.isWeightInf (weight, compWeights[parA]));
--childCountRec [parA];
--childCountRec [parB];
#ifdef SMART_LOG
LOG ("connect leaf a:" << a << " b:" << b << " np:" << parCount << " (2)");
#endif
// XXX newParent = leafParents[a] => return ?
createParent (parCount, weight, leafParents [a], leafParents [b]);
connectComp (leafParents [a], parA, parB, weightFunct);
return;
}
if (weightFunct.isWeightInf (weight, compWeights[parA])) {
// 2
--childCountRec [parA];
parB = findTopComp (parB, weight, weightFunct);
BOOST_ASSERT (parB < leafCount);
if (weight == compWeights[parB]) {
// 2a
++childCountRec[parB];
leafParents[a] = parB;
#ifdef SMART_LOG
LOG ("connect leaf a:" << a << " p:" << parB << " (" << childCountRec[parB] << ")");
#endif
connectComp (parA, parB, weightFunct);
return;
}
// 2b compWeights[parB] < weight
BOOST_ASSERT (weightFunct.isWeightInf (compWeights[parB], weight));
DimImg grandParB = findTopComp (compParents[parB], weightFunct);
--childCountRec [grandParB];
#ifdef SMART_LOG
LOG ("connect leaf a:" << a << " pb:" << parB << " np:" << parCount << " (2)");
#endif
// XXX newParent = leafParents[a] => return ?
createParent (parCount, weight, leafParents [a], compParents [parB]);
connectComp (leafParents [a], grandParB, parA, weightFunct);
return;
}
parA = findTopComp (parA, weight, weightFunct);
parB = findTopComp (parB, weight, weightFunct);
BOOST_ASSERT (parA < leafCount);
BOOST_ASSERT (parB < leafCount);
if (weightFunct.isWeightInf (compWeights[parA], compWeights[parB]))
swap (parA, parB);
if (weightFunct.isWeightInf (compWeights[parA], weight)) {
// 3
BOOST_ASSERT (!weightFunct.isWeightInf (weight, compWeights[parA]));
//BOOST_ASSERT (compParents[parA] < leafCount); // XXX pas sur !!!
//BOOST_ASSERT (compParents[parB] < leafCount); // XXX pas sur !!!
DimImg grandParA = findTopComp (compParents[parA], weightFunct);
DimImg grandParB = findTopComp (compParents[parB], weightFunct);
if (grandParA != DimImg_MAX)
--childCountRec [grandParA];
if (grandParB != DimImg_MAX)
--childCountRec [grandParB];
#ifdef SMART_LOG
LOG ("connect leaf pa:" << parA << " pb:" << parB << " np:" << parCount << " (2)");
#endif
// XXX newParent = compParents [parA] => return ?
createParent (parCount, weight, compParents [parA], compParents [parB]);
connectComp (compParents [parA], grandParA, grandParB, weightFunct);
return;
}
// 4
connectComp (parA, parB, weightFunct);
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::connectComp (DimImg newComp, DimImg topA, DimImg topB, const WeightFunct &weightFunct) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::connectComp", "newComp:" << newComp << " topA:" << topA << " topB:" << topB);
#endif
if (topB == DimImg_MAX)
swap (topA, topB);
BOOST_ASSERT (topB != DimImg_MAX);
if (topA != DimImg_MAX && weightFunct.isWeightInf (compWeights[topA], compWeights[topB]))
swap (topA, topB);
BOOST_ASSERT (findTopComp (topB, weightFunct) == topB);
compParents[newComp] = topB;
++childCountRec[topB];
#ifdef SMART_LOG
LOG ("connect comp nc:" << newComp << " tb:" << topB << " (" << childCountRec[topB] << ")");
#endif
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) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::connectComp", "topA:" << topA << " topB:" << topB);
#endif
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]) {
if (childCountRec[topA] < childCountRec[topB])
swap (topA, topB);
DimImg parB = findTopComp (compParents[topB], weightFunct);
if (parB != DimImg_MAX)
--childCountRec[parB];
childCountRec [topA] += childCountRec[topB];
childCountRec[topB] = 0;
compParents[topB] = topA;
#ifdef SMART_LOG
LOG ("connect comp topB:" << topB << " topA:" << topA << " (" << childCountRec [topA] << ")");
#endif
topB = topA;
topA = findTopComp (parB, compWeights[topA], weightFunct);
continue;
}
DimImg parB = findTopComp (compParents[topB], weightFunct);
++childCountRec[topA];
compParents[topB] = topA;
#ifdef SMART_LOG
LOG ("connect comp topB:" << topB << " topA:" << topA << " (" << childCountRec [topA] << ")");
#endif
if (parB == DimImg_MAX)
return;
--childCountRec[parB];
topB = findTopComp (topA, compWeights[parB], weightFunct);
topA = parB;
}
}
// ----------------------------------------
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 = findCompMultiChild (curComp);
if (curComp != top) {
// 0 => merge || no more child
// 1 => unnecessary node
BOOST_ASSERT (curComp != DimImg_MAX);
DimImg newTopIdx = newCompId[top];
if (newTopIdx == DimImg_MAX) {
newTopIdx = newCompId[top] = compCount++;
if (top == DimImg_MAX)
// XXX arbres non-connexe ?
cerr << "coucou top: " << curComp << endl;
else if (compParents[top] == leafCount)
// XXX arbres non-connexe ?
cerr << "coucou ptop-top: " << curComp << endl;
else if (compParents[top] == DimImg_MAX)
// XXX arbres non-connexe ?
cerr << "coucou ptop-max: " << curComp << endl;
}
const DimNodeId &newTopChildCountRec = childCountRec[top];
const DimImg &newTopCompParent = compParents[top];
const WeightT &newTopWeight = compWeights[top]; // only in case of unnecessary comp
for (DimImg sibling = curComp; sibling != top; ) {
DimImg nextSibling = compParents[sibling];
newCompId[sibling] = newTopIdx;
childCountRec[sibling] = newTopChildCountRec;
compParents[sibling] = newTopCompParent;
// only in case of unnecessary comp
compWeights[sibling] = newTopWeight;
sibling = nextSibling;
}
return;
}
newCompId[curComp] = compCount++;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::compress (const DimImg &compTop) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::compress", " compTop:" << compTop);
#endif
dealThreadRange (leafCount, coreCount, [this] (const DimImg &leaf) {
DimImg old = leafParents[leaf];
if (old != DimImg_MAX)
leafParents[leaf] = newCompId[old];
});
dealThreadRange (compTop, coreCount, [this] (const DimImg &curComp) {
DimImg old = compParents[curComp];
if (old != DimImg_MAX)
compParents[curComp] = 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;
}
#ifdef SMART_LOG
LOG ("comp curComp:" << curComp << " newIdxComp:" << newIdxComp);
#endif
swap (compParents[curComp], compParents[newIdxComp]);
swap (compWeights[curComp], compWeights[newIdxComp]);
swap (childCountRec[curComp], childCountRec[newIdxComp]);
swap (newCompId[curComp], newCompId[newIdxComp]);
}
// XXX YYY curComp ? compTop ?
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::createParent (DimImg &topParent, const WeightT &weight, DimImg &childA, DimImg &childB) {
childCountRec [topParent] = 2;
compWeights [topParent] = weight;
childA = childB = topParent;
++topParent;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::addChild (const DimImg &parent, DimImg &child) {
++childCountRec [parent];
child = parent;
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::addChildren (const DimImg &parent, const DimImg &sibling) {
childCountRec [parent] += childCountRec [sibling];
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) {
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>::findCompMultiChild (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 (childCountRec[comp] > 1 && compWeights[comp] != compWeights[parent])
return comp;
comp = parent;
}
}
// ========================================
template<typename WeightT, typename PixelT>
inline void
ArrayTreeBuilder<WeightT, PixelT>::buildChildren () {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::buildChildren", "");
#endif
BOOST_ASSERT (childCount[0] == 0);
BOOST_ASSERT (childCount[1] == 0);
DimImg compCount = getCompCount ();
partial_sum (childCountRec, childCountRec+compCount, childCountRec);
// set
DimNodeId *childGetOrder = childCount+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 (childCount[0] == 0);
}
// ----------------------------------------
template<typename WeightT, typename PixelT>
template<typename WeightFunct>
inline void
ArrayTreeBuilder<WeightT, PixelT>::initWeights (const GraphWalker &graphWalker, const WeightFunct &weightFunct) {
#ifdef SMART_LOG
DEF_LOG ("ArrayTreeBuilder::initCompWeights", "leafCount:" << leafCount);
dealThreadFill_n (leafCount, coreCount, compWeights, 0);
#endif
// graphWalker.forEachVertexIdx ([this, &weightFunct] (const DimImg &compIdx){
// mapWeights[compIdx] = weightFunct.getWeight (compIdx);
// });
}
// ========================================
// #ifdef ENABLE_LOG
// template<typename WeightT, typename PixelT>
// inline void
// ArrayTreeBuilder<WeightT, PixelT>::printTree (const Size &size, const bool &rec) {
// cout << "tree weight parent " << (rec ? "countRec" : "count children") << endl;
// Size doubleSize (size.width, 2*size.height);
// triskele::printMap (cout, compWeights, size, (DimNodeId) getCompCount ()) << endl;
// triskele::printMap (cout, leafParents, doubleSize) << endl;
// triskele::printMap (cout, rec ? childCountRec : childCount, size) << endl;
// if (!rec)
// printMap (cout, children, doubleSize, nodeCount) << endl << endl;
// }
// template<typename WeightT, typename PixelT>
// inline void
// ArrayTreeBuilder<WeightT, PixelT>::printLeaders (const Size &size) {
// cout << "leaders" << endl;
// triskele::printMap (cout, newCompId, size) << endl;
// }
// template<typename WeightT, typename PixelT>
// inline void
// ArrayTreeBuilder<WeightT, PixelT>::printNewCompId (const Size &size) {
// cout << "newCompId" << endl;
// triskele::printMap (cout, newCompId, size) << endl;
// }
// #endif
#endif // _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP