#include "GlobalReflectionSymmScorer.h" void GlobalReflectionSymmScorer::init() { std::vector cptsV; for ( int i = 0; i < (int) graph_->nodes.size(); ++i) { Structure::Node * n = graph_->nodes[i]; std::vector nodeCptsV; extractCpts( n, nodeCptsV, pointLevel_); Eigen::MatrixXd nodeCptsM; vectorPts2MatrixPts(nodeCptsV, nodeCptsM); nodesCpts_.push_back(nodeCptsM); nodesCenter_.push_back( Eigen::Vector3d(nodeCptsM.col(0).mean(), nodeCptsM.col(1).mean(), nodeCptsM.col(2).mean()) ); for ( std::vector::iterator it = nodeCptsV.begin(); it!= nodeCptsV.end(); ++it) { cptsV.push_back(*it); } } vectorPts2MatrixPts(cptsV, cpts_); center_= this->graph_->bbox().center();// not extract for symm //center_ = Eigen::Vector3d( cpts_.col(0).mean(), cpts_.col(1).mean(), cpts_.col(2).mean()); // bad when some parts hidden in other parts } ////////////////////// double GlobalReflectionSymmScorer::evaluate() { normal_ = findReflectPlane(this->center_); return evaluate(this->center_, normal_, 1.0); } Eigen::Vector3d GlobalReflectionSymmScorer::findReflectPlane(const Eigen::Vector3d& center) { Eigen::Vector3d rnormal; double meanScore = std::numeric_limits::max();//, maxScore; Eigen::Vector3d axis(0,0,1); Eigen::Vector3d initNormal(1,0,0), normal; double angleStep = 3.1415926*0.5; for ( int i = 0; i < (int) 2; ++i) { normal = rotatedVec(initNormal, i*angleStep, axis); double minDist, meanDist, maxDist; Eigen::MatrixXd ptsout; reflect_points3d(cpts_, center, normal, ptsout); distanceBetween(cpts_, ptsout, minDist, meanDist, maxDist); if ( meanDist < meanScore) { meanScore = meanDist; //maxScore = max_dist; rnormal = normal; } if(logLevel_>1) { logStream_ << "current plane's center: [" << center_.x() << "," << center_.y() << "," << center_.z() << "], normal: [" << normal.x() << "," << normal.y() << "," << normal.z() << "], error: " << meanDist << "\n"; } } return rnormal; } double GlobalReflectionSymmScorer::evaluate(const Eigen::Vector3d ¢er, const Eigen::Vector3d &normal, double maxGlobalSymmScore) { if(logLevel_>0) { if(bUsePart_) logStream_ << "Use part for global symm. \n"; else logStream_ << "not Use part for global symm. \n"; if (center == this->center_) logStream_ << "Use center of blended shape. \n"; else logStream_ << "Use center of source shape. \n"; } //////////////////// double maxDeviation(0.0), maxScore(0.0), deviation(0.0); int maxNo(0), maxCorresNo(0); if (bUsePart_) { for ( int i = 0; i < (int) graph_->nodes.size(); ++i) { Eigen::MatrixXd ptsout; reflect_points3d(nodesCpts_[i], center, normal, ptsout); int nodeNo; deviation = minMeanDistance(ptsout, nodeNo); if ( deviation > maxDeviation) { maxDeviation = deviation; maxNo = i; maxCorresNo = nodeNo; } if(logLevel_>1) { logStream_ << "part: " << graph_->nodes[i]->id << "'s correspond part: " << graph_->nodes[nodeNo]->id << ", deviation of symm: " << deviation << "\n"; } } } else { Eigen::MatrixXd ptsout; reflect_points3d(cpts_, center, normal, ptsout); double minDist, meanDist; distanceBetween(cpts_, ptsout, minDist, maxDeviation, meanDist); } maxDeviation = maxDeviation/this->normalizeCoef_; maxScore = 1/(1+maxDeviation); maxScore = maxScore/maxGlobalSymmScore; if(logLevel_>0) { logStream_ << "\n\n"; logStream_ << "center of reflection plane: " << center.x() << ", " << center.y() <<", " << center.z() << "\n"; logStream_ << "normal of reflection plane: " << normal.x() << ", " << normal.y() <<", " << normal.z() << "\n"; logStream_ << "max global score for normalization: " << maxGlobalSymmScore << "\n"; logStream_ << "part: " << graph_->nodes[maxNo]->id << " corresponds to part: " << graph_->nodes[maxCorresNo]->id << " with max deviation: " << maxDeviation << " leads to score: " << maxScore << "\n"; } return maxScore; } double GlobalReflectionSymmScorer::minMeanDistance(Eigen::MatrixXd& pts, int &nodeNo) { double minDist, meanDist, maxDist, minMean=std::numeric_limits::max(); for ( int i = 0; i < (int) graph_->nodes.size(); ++i) { distanceBetween(pts, nodesCpts_[i], minDist, meanDist, maxDist); if ( meanDist < minMean) { nodeNo = i; minMean = meanDist; } } return minMean; } int GlobalReflectionSymmScorer::findNearestPart(const Eigen::Vector3d &nc, const QString & type, double size, double& dist) { int no(0); dist = std::numeric_limits::max(); double tdist, size2; for ( int i = 0; i < (int) graph_->nodes.size(); ++i) { if ( graph_->nodes[i]->type() != type) continue; Eigen::Vector3d& nc1 = nodesCenter_[i]; tdist = (nc-nc1).norm(); size2 = graph_->nodes[i]->bbox().diagonal().norm(); double tmp = abs(size-size2)/(size+size2); if ( tmp < 0.7 && tdist < dist) { dist = tdist; no = i; } } return no; }