nouveau fichier : include/ArrayTree/GraphWalker.tpp

nouveau fichier : include/ArrayTree/Leader.tpp
	nouveau fichier : include/ArrayTree/triskeleArrayTreeBase.tpp
	nouveau fichier : include/Tree.tpp
	nouveau fichier : src/triskeleBase.cpp
This commit is contained in:
Git Merciol 2017-11-28 04:32:46 +01:00
parent 273f7d6647
commit e5643b9d54
5 changed files with 431 additions and 0 deletions

View File

@ -0,0 +1,308 @@
#ifndef _OTB_TRISKELE_ARRAY_TREE_GRAPHWALKER_TPP
#define _OTB_TRISKELE_ARRAY_TREE_GRAPHWALKER_TPP
// ========================================
inline DimImg
GraphWalker::vertexMaxCount () const {
return vertexMaxCount (size);
}
// ----------------------------------------
inline DimImg
GraphWalker::vertexMaxCount (const Size &tileSize) const {
return DimImg (tileSize.width)*DimImg (tileSize.height);
}
// ----------------------------------------
inline DimEdge
GraphWalker::edgeMaxCount () const {
return edgeMaxCount (size);
}
// ----------------------------------------
inline DimEdge
GraphWalker::edgeMaxCount (const Size &tileSize) const {
if (!tileSize.width || !tileSize.height)
return 0;
DimEdge miniSquare = DimImg (tileSize.width)*DimImg (tileSize.height-1) + DimImg (tileSize.width-1)*DimImg (tileSize.height);
switch (connectivity) {
case Connectivity::C4 :
return miniSquare;
case Connectivity::C6N :
case Connectivity::C6P :
return miniSquare + DimImg (tileSize.width-1)*DimImg (tileSize.height-1);
default :
BOOST_ASSERT (connectivity == Connectivity::C8);
return miniSquare + 2*DimImg (tileSize.width-1)*DimImg (tileSize.height-1);
};
}
// ----------------------------------------
inline DimEdge
GraphWalker::edgeBoundaryMaxCount (const DimSideImg &side) const {
if (!side)
return 0;
switch (connectivity) {
case Connectivity::C4 :
return side;
case Connectivity::C6N :
case Connectivity::C6P :
return side+side-1;
default :
BOOST_ASSERT (connectivity == Connectivity::C8);
return 3*side-2;
};
}
// ========================================
inline void
GraphWalker::setTiles (const unsigned int &coreCount, const Rect &tile,
std::vector<Rect> &tiles, std::vector<Rect> &boundaries, std::vector<bool> &verticalBoundaries) const {
BOOST_ASSERT (coreCount);
DEF_LOG ("GraphWalker::setTiles", "coreCount:" << coreCount << " tile:" << tile);
if (coreCount < 2 || max (tile.width, tile.height) < 4 || min (tile.width, tile.height) < 3) {
LOG ("tile:" << tile);
tiles.push_back (tile);
return;
}
bool vertical = tile.width > tile.height;
bool odd = coreCount & 0x1;
DimImg thin = (vertical ? tile.width : tile.height) / (odd ? coreCount : 2);
Rect tileA (tile);
Rect tileB (tile);
if (vertical) {
tileA.width = thin;
tileB.x += thin;
tileB.width -= thin;
} else {
tileA.height = thin;
tileB.y += thin;
tileB.height -= thin;
}
setTiles ((odd ? 1 : coreCount/2), tileA, tiles, boundaries, verticalBoundaries);
boundaries.push_back (tileB);
verticalBoundaries.push_back (vertical);
setTiles ((odd ? coreCount-1 : coreCount/2), tileB, tiles, boundaries, verticalBoundaries);
}
// ========================================
template<typename Funct>
inline DimImg
GraphWalker::forEachVertexIdx (const Funct &lambda /*lambda (idx)*/) const {
DimImg maxCount = vertexMaxCount ();
DimImg vertexCount = 0;
for (DimSideImg idx = 0; idx < maxCount; ++idx)
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (idx));
return vertexCount;
}
template<typename Funct>
inline DimImg
GraphWalker::forEachVertexIdx (const Rect &rect, const Funct &lambda /*lambda (idx)*/) const {
DimImg vertexCount = 0;
DimSideImg const lastX = rect.x+rect.width;
DimSideImg const lastY = rect.y+rect.height;
for (DimSideImg y = rect.y; y < lastY; ++y)
for (DimSideImg x = rect.x; x < lastX; ++x) {
const Point p (x, y);
DimImg idx = point2idx (size, p);
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (idx));
}
return vertexCount;
}
template<typename Funct>
inline DimImg
GraphWalker::forEachVertexPt (const Rect &rect, const Funct &lambda /*lambda (p)*/) const {
DimImg vertexCount = 0;
DimSideImg const lastX = rect.x+rect.width;
DimSideImg const lastY = rect.y+rect.height;
for (DimSideImg y = rect.y; y < lastY; ++y)
for (DimSideImg x = rect.x; x < lastX; ++x) {
const Point p (x, y);
DimImg idx = point2idx (size, p);
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (p));
}
return vertexCount;
}
// ========================================
template<typename Funct>
inline DimEdge
GraphWalker::forEachEdgePt (const Rect &rect, TileItem tileItem, const Funct &lambda /*lambda (p0, p1)*/) const {
DimImg edgeCount = 0;
if (!rect.width || !rect.height)
return edgeCount;
const DimSideImg firstX = rect.x, endX = rect.x+rect.width;
const DimSideImg firstY = rect.y, endY = rect.y+rect.height;
switch (tileItem) {
case Surface:
{
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point pha1 (x-1, firstY), pha2 (x, firstY);
GRAPHWALKER_CALL_LAMBDA_PTS (pha1, pha2, edgeCount, lambda (pha1, pha2));
}
for (DimSideImg y = firstY+1; y < endY; ++y) {
Point pva1 (firstX, y-1), pva2 (firstX, y);
GRAPHWALKER_CALL_LAMBDA_PTS (pva1, pva2, edgeCount, lambda (pva1, pva2));
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point ph1 (x-1, y), pv1 (x, y-1), p2 (x, y);
GRAPHWALKER_CALL_LAMBDA_PTS (ph1, p2, edgeCount, lambda (ph1, p2));
GRAPHWALKER_CALL_LAMBDA_PTS (pv1, p2, edgeCount, lambda (pv1, p2));
}
}
if (connectivity & Connectivity::C6P)
for (DimSideImg y = firstY+1; y < endY; ++y)
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point p1 (x-1, y-1), p2 (x, y);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
if (connectivity & Connectivity::C6N)
for (DimSideImg y = firstY+1; y < endY; ++y)
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point p1 (x-1, y), p2 (x, y-1);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
}
break;
case Horizontal:
{
const DimSideImg y1 = rect.y-1, y2 = rect.y;
for (DimSideImg x = firstX; x < endX; ++x) {
Point p1 (x, y1), p2 (x, y2);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
if (connectivity & Connectivity::C6P)
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point p1 (x-1, y1), p2 (x, y2);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
if (connectivity & Connectivity::C6N)
for (DimSideImg x = firstX+1; x < endX; ++x) {
Point p1 (x, y1), p2 (x-1, y2);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
}
break;
case Vertical:
{
const DimSideImg x1 = rect.x-1, x2 = rect.x;
for (DimSideImg y = firstY; y < endY; ++y) {
Point p1 (x1, y), p2 (x2, y);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
if (connectivity & Connectivity::C6P)
for (DimSideImg y = firstY+1; y < endY; ++y) {
Point p1 (x1, y-1), p2 (x2, y);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
if (connectivity & Connectivity::C6N)
for (DimSideImg y = firstY+1; y < endY; ++y) {
Point p1 (x1, y), p2 (x2, y-1);
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
}
}
break;
default:
BOOST_ASSERT (false);
}
return edgeCount;
}
// ========================================
template <typename WeightT, typename EdgeWeightFunction>
inline WeightT
GraphWalker::getMedian (const EdgeWeightFunction &ef /*ef.getValue (idx)*/) const {
int bits = 8*sizeof (WeightT);
BOOST_ASSERT (bits < 17);
DimEdge dim = 1UL << bits;
std::vector<DimImg> indices (dim+1, 0);
DimImg *histogram = &indices[1];
forEachVertexIdx ([&histogram, &ef] (const DimImg &idx) {
++histogram[(size_t) ef.getValue (idx)];
});
std::partial_sum (histogram, histogram+dim, histogram);
return lower_bound (indices.begin (), indices.end (), indices[dim] >> 1) - indices.begin ();
}
// ========================================
template <typename WeightT, typename EdgeWeightFunction>
inline DimEdge
GraphWalker::getEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const {
BOOST_ASSERT (rect.width);
BOOST_ASSERT (rect.height);
BOOST_ASSERT (edges);
DimEdge edgeCount = 0;
forEachEdgePt (rect, tileItem,
[&edges, &edgeCount, &ef] (Point const &a, Point const &b) {
Edge<WeightT> &edge = edges[edgeCount++];
edge.points[0] = a;
edge.points[1] = b;
edge.weight = ef.getWeight (a, b);
});
return edgeCount;
}
// ----------------------------------------
template <typename WeightT, typename EdgeWeightFunction>
inline DimEdge
GraphWalker::getSortedEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1) ef.sort ()*/) const {
DimEdge edgeCount = getEdges (rect, tileItem, edges, ef);
ef.sort (edges, edgeCount);
return edgeCount;
}
template <typename WeightT, typename EdgeWeightFunction>
// template DimImg
inline DimEdge
GraphWalker::getCountingSortedEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const {
int bits = 8*sizeof (WeightT);
BOOST_ASSERT (bits < 17);
DimEdge dim = 1UL << bits;
DimImg *indices = new DimImg [dim+1];
DimImg *histogram = indices+1;
DimImg sum = 0;
::std::fill_n (histogram, dim, 0);
forEachEdgePt (rect, tileItem,
[&histogram, &ef] (Point const &a, Point const &b) {
++histogram[(size_t) ef.getWeight (a, b)];
});
// get indices by prefix sum
std::partial_sum (histogram, histogram+dim, histogram);
sum = indices[dim];
if (ef.getDecr ()) {
for (size_t i = 0; i < dim; ++i)
histogram[i] = sum - histogram[i];
indices++;
} else
indices[0] = 0;
// extract edges
forEachEdgePt (rect, tileItem,
[
#ifdef SMART_LOG
this,
#endif
&ef, &edges, &indices] (Point const &a, Point const &b) {
WeightT weight = ef.getWeight (a, b);
Edge<WeightT> &edge = edges[indices[(size_t) weight]++];
edge.points[0] = a;
edge.points[1] = b;
edge.weight = weight;
#ifdef SMART_LOG
printEdge (cerr, edge, size) << endl;
#endif
});
#ifdef SMART_LOG
cerr << endl;
for (int i = 0; i < sum; ++i)
printEdge (cerr, edges[i], size) << endl;
#endif
delete [] (histogram-1);
return sum;
}
#endif // _OTB_TRISKELE_ARRAY_TREE_GRAPHWALKER_TPP

View File

@ -0,0 +1,77 @@
#ifndef _OTB_TRISKELE_ARRAY_TREE_LEADER_TPP
#define _OTB_TRISKELE_ARRAY_TREE_LEADER_TPP
// ========================================
inline DimImg
Leader::find (DimImg a) const {
BOOST_ASSERT (a < size);
for (;;) {
// On recherche le leader de a dans le tableau
DimImg p = leaders[a];
// Si p est size, p n'a pas de leader donc p était le leader de a
if (p == DimImg_MAX)
break;
a = p;
}
BOOST_ASSERT (a < size);
return a;
}
// ----------------------------------------
inline void
Leader::link (DimImg a, const DimImg &r) {
BOOST_ASSERT (a < size);
BOOST_ASSERT (r < size);
for (; a != r;) {
// On affecte une variable "temporaire" qui joue le rôle du leader de a
DimImg p = leaders[a];
//
leaders[a] = r;
if (p == DimImg_MAX)
return;
a = p;
}
}
// ========================================
inline void
Leader::book (DimImg vertexCount) {
#ifdef SMART_LOG
DEF_LOG ("Leader::book", "vertexCount:" << vertexCount);
#endif
if (vertexCount == size) {
reset ();
return;
}
free ();
if (!vertexCount)
return;
size = vertexCount;
leaders = new DimImg [vertexCount];
reset ();
}
// ---------------------------------------
inline void
Leader::reset () {
if (!size)
return;
// XXX dealThreadFill_n
std::fill_n (leaders, size, DimImg_MAX);
}
// ---------------------------------------
inline void
Leader::free () {
#ifdef SMART_LOG
DEF_LOG ("Leader::free", "");
#endif
if (leaders)
delete [] leaders;
leaders = NULL;
size = 0;
}
// ========================================
#endif // _OTB_TRISKELE_ARRAY_TREE_LEADER_TPP

27
include/Tree.tpp Normal file
View File

@ -0,0 +1,27 @@
#ifndef _OTB_TRISKELE_TREE_TPP
#define _OTB_TRISKELE_TREE_TPP
template<typename FuncToApply>
void
Tree::forEachLeaf (const FuncToApply &f /* f (DimNodeId leafId) */) const {
for (DimNodeId leafId = 0; leafId < leafCount; ++leafId)
f (leafId);
}
template<typename FuncToApply>
void
Tree::forEachComp (const FuncToApply &f /* f (DimNodeId compId) */) const {
DimNodeId compCount = nodeCount - leafCount;
for (DimNodeId compId = 0; compId < compCount; ++compId)
f (compId);
}
template<typename FuncToApply>
void
Tree::forEachChild (const DimNodeId &parentId, const FuncToApply &f /* f (DimNodeId childId) */) const {
DimNodeId minChild = childCount[parentId], maxChild = childCount[parentId+1];
for (DimNodeId childId = minChild; childId < maxChild; ++childId)
f (children[childId]);
}
#endif // _OTB_TRISKELE_TREE_TPP

19
src/triskeleBase.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "triskeleBase.hpp"
using namespace triskele;
int
triskele::bitCount [] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
Point triskele::NullPoint;
Size triskele::NullSize;
Rect triskele::NullRect;