00001 #ifndef OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CONNECTED_COMPONENTS_H
00002 #define OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CONNECTED_COMPONENTS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/multi_array.hpp>
00013
00014 #include <vector>
00015
00016 namespace OpenTissue
00017 {
00018 namespace grid
00019 {
00020
00021 namespace detail
00022 {
00029 template< typename unsigned_int_container>
00030 inline void associate(size_t i, size_t j, unsigned_int_container & assoc)
00031 {
00032 if ( j == 0 || j == i )
00033 return;
00034
00035 size_t search = j;
00036 do
00037 {
00038 search = assoc[search];
00039 }
00040 while ( search != j && search != i );
00041
00042 if ( search == j )
00043 {
00044 std::swap(assoc[i],assoc[j]);
00045 }
00046 }
00047 }
00048
00061 template < typename grid_type >
00062 inline size_t connected_components(grid_type const & image, grid_type & components)
00063 {
00064 components.create(image.I(), image.J(), image.K(), 1,1,1);
00065
00066
00067
00068
00069 typedef boost::multi_array<size_t, 3> array_type;
00070 typedef array_type::index array_index;
00071
00072 size_t width = image.I()+2;
00073 size_t height = image.J()+2;
00074 size_t depth = image.K()+2;
00075
00076 array_type tmp(boost::extents[width][height][depth]);
00077 {
00078 array_index xp1, yp1, zp1;
00079 size_t x0,y0, z0;
00080 for (z0 = 0, zp1 = 1; z0 < image.K(); ++z0, ++zp1)
00081 for (y0 = 0, yp1 = 1; y0 < image.J(); ++y0, ++yp1)
00082 for (x0 = 0, xp1 = 1; x0 < image.I(); ++x0, ++xp1)
00083 tmp[xp1][yp1][zp1] = ( image(x0,y0,z0) ? 1 : 0 );
00084 }
00085
00086
00087 size_t initial_component_count = 0;
00088
00089 size_t * val = tmp.data();
00090 for (size_t i = 0; i < tmp.num_elements(); ++i, ++val)
00091 {
00092 if ( *val )
00093 {
00094 initial_component_count++;
00095 while ( *val > 0 )
00096 {
00097
00098 *val = initial_component_count;
00099 ++i;
00100 ++val;
00101 }
00102 }
00103 }
00104
00105 if ( initial_component_count == 0 )
00106 {
00107
00108 std::fill(components.begin(), components.end(), 0);
00109 return 0;
00110 }
00111
00112
00113 std::vector<size_t> assoc(initial_component_count+1,0);
00114 for (size_t i = 0; i < initial_component_count + 1; ++i)
00115 assoc[i] = i;
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 for (array_index z = 1; z < depth-1; ++z)
00126 for (array_index y = 1; y < height-1; ++y)
00127 for (array_index x = 1; x < width-1; ++x)
00128 {
00129 size_t value = tmp[x][y][z];
00130 if ( value > 0 )
00131 {
00132 detail::associate(value, tmp[x-1][y-1][z-1], assoc);
00133 detail::associate(value, tmp[x ][y-1][z-1], assoc);
00134 detail::associate(value, tmp[x+1][y-1][z-1], assoc);
00135 detail::associate(value, tmp[x-1][y ][z-1], assoc);
00136 detail::associate(value, tmp[x ][y ][z-1], assoc);
00137 detail::associate(value, tmp[x+1][y ][z-1], assoc);
00138 detail::associate(value, tmp[x-1][y+1][z-1], assoc);
00139 detail::associate(value, tmp[x ][y+1][z-1], assoc);
00140 detail::associate(value, tmp[x+1][y+1][z-1], assoc);
00141 detail::associate(value, tmp[x-1][y-1][z ], assoc);
00142 detail::associate(value, tmp[x ][y-1][z ], assoc);
00143 detail::associate(value, tmp[x+1][y-1][z ], assoc);
00144 detail::associate(value, tmp[x-1][y ][z ], assoc);
00145 }
00146 }
00147
00148
00149 size_t component_count = 0;
00150 for (size_t i = 1; i <= initial_component_count; ++i)
00151 {
00152 if ( i <= assoc[i] )
00153 {
00154 component_count++;
00155 size_t current = i;
00156 while ( assoc[current] != i )
00157 {
00158 size_t next = assoc[current];
00159 assoc[current] = component_count;
00160 current = next;
00161 }
00162 assoc[current] = component_count;
00163 }
00164 }
00165
00166
00167 {
00168 array_index xp1, yp1, zp1;
00169 size_t x0,y0,z0;
00170 for (z0 = 0, zp1 = 1; z0 < components.K(); ++z0, ++zp1)
00171 for (y0 = 0, yp1 = 1; y0 < components.J(); ++y0, ++yp1)
00172 for (x0 = 0, xp1 = 1; x0 < components.I(); ++x0, ++xp1)
00173 components(x0,y0,z0) = assoc[ tmp[xp1][yp1][zp1] ];
00174 }
00175
00176 return component_count;
00177 }
00178
00179 }
00180 }
00181
00182
00183 #endif