00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <structureColoring/histograms/SphereUniformSampling.h>
00037
00038 SphereUniformSampling::SphereUniformSampling(unsigned int phi_resolution, bool halfSphereFlip)
00039 :mPhi_resolution(phi_resolution), mHalfSphereFlip(halfSphereFlip){
00040 mData.resize(mPhi_resolution);
00041 mRatioToNextData.resize(mPhi_resolution - 1);
00042 for(unsigned int i=0; i<mPhi_resolution; i++){
00043 unsigned int uisize = 2 * mPhi_resolution * sin (M_PI * (float)i / (float)mPhi_resolution) + 1.5;
00044 mData[i].reserve(uisize);
00045 for(unsigned int j=0; j<uisize; j++){
00046 mData[i].push_back(SphereUniformSampling::NormalEntry(i, j, mPhi_resolution));
00047 }
00048 if(i>0)mRatioToNextData[i-1] = uisize / mData[i-1].size();
00049 }
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 void SphereUniformSampling::getHistogramIndicesFromAngles(unsigned int& i, unsigned int& j, const float phi, const float theta, const unsigned int phi_resolution){
00073 float phi_corrected = phi;
00074 if (phi_corrected > M_PI){
00075 phi_corrected = M_PI;
00076 ROS_ERROR("getHistogramIndicesFromAngles: phi (%f) > PI", phi);
00077 }
00078 i = ((phi_corrected/(M_PI)) * phi_resolution)+0.5;
00079
00080 float theta_corrected = theta;
00081 if (theta_corrected >= 2.f * M_PI){
00082 theta_corrected = 0;
00083 ROS_ERROR("getHistogramIndicesFromAngles: theta (%f) > 2 * PI", theta);
00084 }
00085 unsigned int uisize = 2 * phi_resolution * sin (M_PI * (float)i / (float)phi_resolution) + 1.5;
00086 j = ((theta_corrected / (2.f * M_PI)) * uisize)+0.5;
00087 }
00088
00089 void SphereUniformSampling::getAnglesFromHistogramIndices(float& phi, float& theta, const unsigned int i, const unsigned int j, const unsigned int phi_resolution){
00090 unsigned int uisize = 2 * phi_resolution * sin (M_PI * (float)i / (float)phi_resolution) + 1.5;
00091 if((i==(unsigned int)-1)||(j==(unsigned int)-1)){
00092 phi = -M_PI;
00093 theta = -M_PI;
00094 } else {
00095 phi = (float)i * M_PI / (float)phi_resolution;
00096 theta = 2.f * M_PI * ((float)(j) / ((float)uisize));
00097 }
00098 if (phi > M_PI){
00099 if (phi < M_PI +0.01){
00100 phi = M_PI - 0.0001;
00101 } else {
00102 ROS_ERROR("getAnglesFromHistogramIndices: phi (%f) > PI", phi);
00103 phi = M_PI;
00104 }
00105 }
00106 if (theta >= 2 * M_PI){
00107 if (theta < 2 * M_PI +0.01){
00108 theta = 2 * M_PI - 0.0001;
00109 } else {
00110 ROS_ERROR("getAnglesFromHistogramIndices: theta (%f) >= 2 * PI", theta);
00111 theta = 0;
00112 }
00113 }
00114 }
00115
00116 void SphereUniformSampling::getPointsAngle(std::list<int>& points, const float phi, const float theta, const float max_angle) const{
00117 points.clear();
00118 std::list<int> nPoints;
00119 if((phi >= 0)&&(theta >= 0)){
00120 std::vector<Pair2ui> neighbors;
00121 getAllAngleNeighbors(neighbors, phi, theta, max_angle);
00122 for(unsigned int n=0; n<neighbors.size(); n++){
00123 nPoints = mData[neighbors[n].first][neighbors[n].second].getPoints();
00124 points.merge(nPoints);
00125 }
00126 }
00127 }
00128
00129 void SphereUniformSampling::getPoints(std::vector<int>& points, const unsigned int i, const unsigned int j, std::vector<float>* weights) const{
00130 points.clear();
00131 if ((i < mData.size()) && (j < mData[i].size())){
00132 const std::list<int>& points_list = mData[i][j].getPoints();
00133 for(std::list<int>::const_reverse_iterator list_it=points_list.rbegin(); list_it != points_list.rend(); ++list_it){
00134 points.push_back(*list_it);
00135 }
00136 if (weights != NULL){
00137 const std::list<float>& weights_list = mData[i][j].getWeights();
00138 for(std::list<float>::const_reverse_iterator list_it=weights_list.rbegin(); list_it != weights_list.rend(); ++list_it){
00139 weights->push_back(*list_it);
00140 }
00141 }
00142 }
00143 }
00144
00145 float SphereUniformSampling::getMaximumAngle(float& phi, float& theta, const float max_angle) const{
00146 float max_weight=-1.f, phi_ij, theta_ij;
00147 unsigned int max_i=-1, max_j=-1;
00148 for(unsigned int i=0; i<mData.size(); i++){
00149 for(unsigned int j=0; j<mData[i].size(); j++){
00150 mData[i][j].getAngles(phi_ij, theta_ij);
00151 float tmp_weight = getWeightAngle(phi_ij, theta_ij, max_angle);
00152 if (tmp_weight > max_weight){
00153 max_weight = tmp_weight;
00154 max_i = i;
00155 max_j = j;
00156 }
00157 }
00158 }
00159 mData[max_i][max_j].getAngles(phi, theta);
00160 return max_weight;
00161 }
00162
00163 float SphereUniformSampling::getMaximumIndices(unsigned int& idx_i, unsigned int& idx_j, const float max_angle) const{
00164 float max_weight=-1.f, phi_ij, theta_ij;
00165 unsigned int max_i=-1, max_j=-1;
00166 for(unsigned int i=0; i<mData.size(); i++){
00167 for(unsigned int j=0; j<mData[i].size(); j++){
00168 mData[i][j].getAngles(phi_ij, theta_ij);
00169 float tmp_weight = getWeightAngle(phi_ij, theta_ij, max_angle);
00170 if (tmp_weight > max_weight){
00171 max_weight = tmp_weight;
00172 max_i = i;
00173 max_j = j;
00174 }
00175 }
00176 }
00177 idx_i = max_i;
00178 idx_j = max_j;
00179 return max_weight;
00180 }
00181
00182 float SphereUniformSampling::getMaximum(unsigned int& imax, unsigned int& jmax) const{
00183 imax = 0; jmax = 0;
00184 float wmax = 0.f;
00185 for (unsigned int i=0; i<mData.size(); i++){
00186 for(unsigned int j=0; j<mData[i].size(); j++){
00187 float w = mData[i][j].getWeight();
00188 if(w > wmax){
00189 imax = i;
00190 jmax = j;
00191 wmax = w;
00192 }
00193 }
00194 }
00195 return wmax;
00196 }
00197
00198 void SphereUniformSampling::getAllAngleNeighbors(std::vector<Pair2ui>& neighbors, const float phi, const float theta, const float max_angle) const{
00199 float dotProduct = 0.f, max_angle_cos = cos(max_angle);
00200 neighbors.clear();
00201 Eigen::Vector3f pointNormal(0, 0, 0);
00202 Eigen::Vector3f binNormal;
00203 pointNormal.z() = cos(phi);
00204 pointNormal.y() = sin(theta) * sin(phi);
00205 pointNormal.x() = cos(theta) * sin(phi);
00206 for(unsigned int i=0; i<mData.size(); i++){
00207 for(unsigned int j=0; j<mData[i].size(); j++){
00208 binNormal = mData[i][j].getNormal();
00209 dotProduct = binNormal.dot(pointNormal);
00210 if(mHalfSphereFlip) dotProduct = fabsf(dotProduct);
00211 if (dotProduct >= max_angle_cos){
00212 neighbors.push_back(std::make_pair(i, j));
00213 }
00214 }
00215 }
00216 }
00217
00218 void SphereUniformSampling::getAllAngleNeighbors(std::vector<Pair2ui>& neighbors, const Eigen::Vector3f& pointNormal, const float max_angle) const{
00219 float dotProduct = 0.f, max_angle_cos = cos(max_angle);
00220 neighbors.clear();
00221 Eigen::Vector3f binNormal;
00222 for(unsigned int i=0; i<mData.size(); i++){
00223 for(unsigned int j=0; j<mData[i].size(); j++){
00224 binNormal = mData[i][j].getNormal();
00225 dotProduct = binNormal.dot(pointNormal);
00226 if(mHalfSphereFlip) dotProduct = fabsf(dotProduct);
00227 if (dotProduct >= max_angle_cos){
00228 neighbors.push_back(std::make_pair(i, j));
00229 }
00230 }
00231 }
00232 }
00233
00234 void SphereUniformSampling::getHistogramAsPointCloud(pcl::PointCloud<pcl::PointXYZRGB>& histogramCloud, const float scale, const Eigen::Vector3f& translation) const{
00235 pcl::PointXYZRGB binNormal;
00236 unsigned int imax=0, jmax=0;
00237 getMaximum(imax, jmax);
00238 float maxWeight = mData[imax][jmax].getWeight();
00239 for (unsigned int i=0; i<mData.size(); i++){
00240 for (unsigned int j=0; j<mData[i].size(); j++){
00241 Eigen::Vector3f normal = mData[i][j].getNormal();
00242 binNormal.x = normal.x() * scale + translation.x();
00243 binNormal.y = normal.y() * scale + translation.y();
00244 binNormal.z = normal.z() * scale + translation.z();
00245
00246 unsigned int rgb = 0x000000;
00247
00248
00249 unsigned int w = (unsigned int)(255 * mData[i][j].getWeight() / maxWeight);
00250 if(w > 0xff) w = 0xff;
00251 unsigned int col = (w<<8) + (w<<16) + w;
00252 if(col > 0xffffff)col = 0xffffff;
00253
00254 rgb += col;
00255
00256 binNormal.rgb = *(float*)&rgb;
00257 histogramCloud.points.push_back(binNormal);
00258 }
00259 }
00260 }
00261
00262 void SphereUniformSampling::addPointNoNeighbors(std::list<int>::iterator& points_it, std::list<float>::iterator& weights_it, const unsigned int i, const unsigned int j, const int index, const float weight){
00263 if ((i<mData.size()) && (j<mData[i].size()))
00264 mData[i][j].addIndex(points_it, weights_it, index, weight);
00265 }
00266
00267 void SphereUniformSampling::deletePointsAtAngle(const float phi, const float theta, const float max_angle){
00268 std::vector<Pair2ui> neighbors;
00269 getAllAngleNeighbors(neighbors, phi, theta, max_angle);
00270 for(unsigned int n=0; n<neighbors.size(); n++){
00271 deleteEntry(neighbors[n].first, neighbors[n].second);
00272 }
00273 }
00274
00275 void SphereUniformSampling::deletePointNWeightAt(const std::list<int>::iterator points_it, const std::list<float>::iterator weights_it, const unsigned int i, const unsigned int j){
00276 if ((i<mData.size()) && (j<mData[i].size())){
00277 mData[i][j].deletePointNWeight(points_it, weights_it);
00278 }
00279 }
00280
00281 float SphereUniformSampling::getWeightAngle(const float phi, const float theta, const float max_angle) const{
00282 float ret_weight=0.f;
00283 std::vector<Pair2ui> neighbors;
00284 getAllAngleNeighbors(neighbors, phi, theta, max_angle);
00285 for(unsigned int n=0; n<neighbors.size(); n++){
00286 ret_weight += mData[neighbors[n].first][neighbors[n].second].getWeight();
00287 }
00288 return ret_weight;
00289 }
00290
00291 float SphereUniformSampling::getPlanarAngle(const float phi1, const float theta1, const float phi2, const float theta2) const{
00292 Eigen::Vector3f normal1(cos(phi1)*sin(theta1),sin(phi1)*sin(theta1),cos(theta1));
00293 Eigen::Vector3f normal2(cos(phi2)*sin(theta2),sin(phi2)*sin(theta2),cos(theta2));
00294 return acos(normal1.dot(normal2));
00295 }
00296
00297 void SphereUniformSampling::deleteEntry(unsigned int i, unsigned int j){
00298 if ((i < mData.size()) && (j < mData[i].size())){
00299 mData[i][j].deleteEntry();
00300 }
00301 }
00302
00303 SphereUniformSampling::NormalEntry::NormalEntry(const unsigned int i, const unsigned int j, const unsigned int phi_resolution){
00304 SphereUniformSampling::getAnglesFromHistogramIndices(mPhi, mTheta, i, j, phi_resolution);
00305 getNormalFromAngles(mNormal, mPhi, mTheta);
00306 mWeight = 0;
00307 }
00308
00309 void SphereUniformSampling::NormalEntry::addIndex(std::list<int>::iterator& points_it, std::list<float>::iterator& weights_it, const int idx, const float w){
00310 mWeight+=w;
00311 mPoints.push_back(idx);
00312 mWeights.push_back(w);
00313 points_it = mPoints.end();
00314 points_it--;
00315 weights_it = mWeights.end();
00316 weights_it--;
00317 }
00318
00319 void SphereUniformSampling::NormalEntry::deletePointNWeight(const std::list<int>::iterator points_it, const std::list<float>::iterator weights_it){
00320 mPoints.erase(points_it);
00321 mWeight -= *weights_it;
00322 mWeights.erase(weights_it);
00323 }
00324
00325 void SphereUniformSampling::NormalEntry::getNormalFromAngles(Eigen::Vector3f& normal, const float phi, const float theta){
00326 normal.z() = cos(phi);
00327 normal.y() = sin(theta) * sin(phi);
00328 normal.x() = cos(theta) * sin(phi);
00329 }