
modifié : include/ArrayTree/ArrayTreeBuilder.tpp supprimé : include/Attributes/AreaAttribute.hpp modifié : include/TreeBuilder.hpp supprimé : src/Attributes/AreaAttribute.cpp modifié : src/Tree.cpp modifié : src/testMain.cpp
771 lines
27 KiB
C++
771 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 (const unsigned int &coreCount,
|
|
Raster<PixelT> &raster, const GraphWalker &graphWalker,
|
|
const TreeType &treeType, const bool &countingSort) :
|
|
coreCount (coreCount),
|
|
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;
|
|
// XXX msg
|
|
}
|
|
leaders.free ();
|
|
newCompId = nullptr;
|
|
buildChildren ();
|
|
childCountRec = nullptr;
|
|
}
|
|
|
|
// ========================================
|
|
template<typename WeightT, typename PixelT>
|
|
inline void
|
|
ArrayTreeBuilder<WeightT, PixelT>::setAttributProfiles (AttributeProfiles<PixelT> &attributeProfiles, const Raster<PixelT> &raster) {
|
|
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 (), raster.getSize ()));
|
|
break;
|
|
// XXX msg
|
|
}
|
|
}
|
|
|
|
// ========================================
|
|
template<typename WeightT, typename PixelT>
|
|
template<typename WeightFunct>
|
|
inline void
|
|
ArrayTreeBuilder<WeightT, PixelT>::buildTree (Tree &tree, const WeightFunct &weightFunct) {
|
|
DEF_LOG ("ArrayTreeBuilder::buildTree", "");
|
|
|
|
//XXX initWeights (graphWalker, weightFunct);
|
|
|
|
// 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
|