#ifndef _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP #define _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP using namespace boost::chrono; // ======================================== template inline ArrayTreeBuilder::ArrayTreeBuilder (Raster &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 inline ArrayTreeBuilder::~ArrayTreeBuilder () { } // ======================================== template inline void ArrayTreeBuilder::buildTree (Tree &tree, WeightAttributes &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 (raster.getPixels (), raster.getSize ())); break; case MAX: buildTree (tree, MaxWeight (raster.getPixels (), raster.getSize ())); break; case TOS: buildTree (tree, MedianWeight (raster.getPixels (), graphWalker)); break; case ALPHA: buildTree (tree, DiffWeight (raster.getPixels (), raster.getSize ())); break; default: cerr << "*** unknown tree type: " << treeType << endl; } globalTreeStats.addTime (buildTreeStats, duration_cast > (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 inline void ArrayTreeBuilder::setAttributProfiles (AttributeProfiles &attributeProfiles) { DEF_LOG ("ArrayTreeBuilder::setAttributProfiles", ""); attributeProfiles.updateTranscient (); switch (treeType) { case MIN: setAttributProfiles (attributeProfiles, MinWeight (raster.getPixels (), raster.getSize ())); break; case MAX: setAttributProfiles (attributeProfiles, MaxWeight (raster.getPixels (), raster.getSize ())); break; case TOS: setAttributProfiles (attributeProfiles, MedianWeight (raster.getPixels (), graphWalker)); break; case ALPHA: setAttributProfiles (attributeProfiles, DiffWeight (raster.getPixels (), raster.getSize ())); break; default: cerr << "*** unknown tree type: " << treeType << endl; } } // ======================================== template template inline void ArrayTreeBuilder::buildTree (Tree &tree, const WeightFunct &weightFunct) { DEF_LOG ("ArrayTreeBuilder::buildTree", ""); coreCount = tree.getCoreCount (); // buildParents vector > allEdges (graphWalker.edgeMaxCount ()); vector tiles; vector boundaries; vector 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 vertexMaxBounds; vector edgesMaxBounds; graphWalker.setMaxBounds (tiles, vertexMaxBounds, edgesMaxBounds); vector *> tileEdges (tileCount); vector compBases (tileCount); vector compTops (tileCount); Edge *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 *> edgeBounds (boundCount); vector edgeCounts (boundCount); Edge *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 (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 *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 template inline void ArrayTreeBuilder::setAttributProfiles (AttributeProfiles &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 template inline void ArrayTreeBuilder::buildParents (Edge *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 (tile, Surface, edges, weightFunct) : graphWalker.getSortedEdges (tile, Surface, edges, weightFunct); const Size &size = graphWalker.size; for (DimEdge edgeIdx = 0; edgeIdx < edgeCount; ++edgeIdx) { Edge &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 inline void ArrayTreeBuilder::unlinkParent (const DimImg &par) { SMART_DEF_LOG ("ArrayTreeBuilder::unlinkParent", "par: " << printComp (par)); if (par == DimImg_MAX) return; BOOST_ASSERT (childCount [par]); --childCount [par]; } // ---------------------------------------- template template inline void ArrayTreeBuilder::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 template inline void ArrayTreeBuilder::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 template inline void ArrayTreeBuilder::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 template inline DimImg ArrayTreeBuilder::updateNewId (const vector &compBases, const vector &compTops, const WeightFunct &weightFunct) { // DEF_LOG ("ArrayTreeBuilder::updateNewId", ""); DimImg compCount = compBases[0]; vector sizes (compBases.size ()); for (DimImg i = 0; i < sizes.size (); ++i) sizes [i] = compTops [i] - compBases [i]; // XXX non parallèle callOnSortedSets (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 inline void ArrayTreeBuilder::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 inline void ArrayTreeBuilder::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 inline DimImg ArrayTreeBuilder::createParent (DimImg &topParent, const WeightT &weight, DimImg &parentChildA, DimImg &parentChildB) { childCount [topParent] = 2; compWeights [topParent] = weight; return parentChildA = parentChildB = topParent++; } // ---------------------------------------- template inline void ArrayTreeBuilder::addChild (const DimImg &parent, DimImg &child) { ++childCount [parent]; child = parent; } // ---------------------------------------- template inline void ArrayTreeBuilder::addChildren (const DimImg &parent, const DimImg &sibling) { childCount [parent] += childCount [sibling]; childCount [sibling] = 0; compParents [sibling] = parent; } // ---------------------------------------- template inline DimImg ArrayTreeBuilder::findRoot (DimImg comp) { if (comp == DimImg_MAX) return comp; for (;;) { DimImg p = compParents [comp]; if (p == DimImg_MAX) return comp; comp = p; } } // ---------------------------------------- template template inline DimImg ArrayTreeBuilder::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 template inline DimImg ArrayTreeBuilder::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 inline DimImg ArrayTreeBuilder::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 inline DimImg ArrayTreeBuilder::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 inline void ArrayTreeBuilder::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 ArrayTreeBuilder::CPrintComp::CPrintComp (const ArrayTreeBuilder &atb, const DimImg &compId) : atb (atb), compId (compId) { } template inline ostream & ArrayTreeBuilder::CPrintComp::print (ostream &out) const { if (compId == DimImg_MAX) return out << "M(-/-)"; return out << compId << "(" << atb.childCount[compId] << "/" << atb.compWeights [compId] << ")"; } // template // inline ArrayTreeBuilder::CPrintComp // ArrayTreeBuilder::printComp (const DimImg &compId) const { // return ArrayTreeBuilder::CPrintComp (*this, compId); // } // template // inline ostream& // operator << (ostream& out, const ArrayTreeBuilder::CPrintComp &lc) { // return lc.print (out); // } // ======================================== #endif // _OTB_TRISKELE_ARRAY_TREE_BUILDER_TPP