#include "PairRelationDetector.h" #pragma warning(disable:4100 4101) void PairRelationDetector::pushToOtherPairs(QVector& prs, QString type) { for (QVector::iterator it = prs.begin(); it != prs.end(); ++it) { if ( it->tag) { it->type = type; otherPairs_.push_back(*it); } } } double PairRelationDetector::ConnectedPairModifier::operator() (Structure::Node *n1, Eigen::MatrixXd& m1, Structure::Node *n2, Eigen::MatrixXd& m2) { double deviation(-1.0),mean_dist, max_dist; if ( n1->id == n2->id) return deviation; Structure::Link* link = RelationDetector::findLink(n1, n2, this->graph_); if ( link == 0) return deviation; if ( this->bUseLink_) deviation = RelationDetector::computeDeviationByLink(link); else { distanceBetween(m1, m2, deviation, mean_dist, max_dist); } deviation = deviation/this->normalizeCoef_; if ( deviation > this->maxAllowDeviation_) { this->maxAllowDeviation_ = deviation; } return deviation; } double PairRelationDetector::TransPairModifier::operator() (Structure::Node *n1, Eigen::MatrixXd& m1, Structure::Node *n2, Eigen::MatrixXd& m2) { double deviation(-1.0), min_dist, mean_dist, max_dist; if ( n1->id == n2->id) return deviation; Eigen::Vector3d transVec = n1->center() - n2->center(); Eigen::Matrix4d transMat = create_translation3d(transVec); Eigen::MatrixXd newverts2 = transform_point3d(m2, transMat); distanceBetween(m1, newverts2, min_dist, mean_dist, max_dist); deviation = 2 * mean_dist / (n1->bbox().diagonal().norm() + n2->bbox().diagonal().norm()); if ( deviation > maxAllowDeviation_) { maxAllowDeviation_ = deviation; } return deviation; } double PairRelationDetector::RefPairModifier::operator() (Structure::Node *n1, Eigen::MatrixXd& m1, Structure::Node *n2, Eigen::MatrixXd& m2) { double deviation(-1.0), min_dist, mean_dist, max_dist; if ( n1->id == n2->id) return deviation; Eigen::Vector3d refCenter = (n1->center() + n2->center())*0.5; Eigen::Vector3d refNormal = n1->center() - n2->center(); refNormal.normalize(); Eigen::MatrixXd newverts2; reflect_points3d(m2, refCenter, refNormal, newverts2); distanceBetween(m1, newverts2, min_dist, mean_dist, max_dist); deviation = 2 * mean_dist / (n1->bbox().diagonal().norm() + n2->bbox().diagonal().norm()); if ( deviation > maxAllowDeviation_) { maxAllowDeviation_ = deviation; } return deviation; } ////////////////////////////////////////////////////// PairRelationDetector::PairRelationDetector(Structure::Graph* g, int ith, double normalizeCoef, bool bUseLink, bool bModifyDeviation, int logLevel) :RelationDetector(g, "PairRelationDetector-", ith, normalizeCoef, 1, logLevel) { bSource_ = ith == 0; bUseLink_ = bUseLink; bModifyDeviation_ = bModifyDeviation; if ( this->logLevel_ > 0) { logStream_ << "Point level: " << pointLevel_ << "\n"; logStream_ << "Radius Radio: " << thRadiusRadio_ << "\n"; logStream_ << "Trans Radio: " << thTransRadio_ << "\n"; logStream_ << "Ref Radio: " << thRefRadio_ << "\n"; logStream_ << "Axis deviation Radio: " << thAxisDeviationRadio_ << "\n"; if ( this->bUseLink_) { logStream_ << "Connected pairs use link distance \n"; } else { logStream_ << "Connected pairs use skeleton distance \n"; } } 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()) ); nodesDiameter_.push_back(n->bbox().diagonal().norm()); } } Eigen::MatrixXd& PairRelationDetector::findCptsByNodeId(Structure::Node* node) { for ( int i = 0; i < (int) graph_->nodes.size(); ++i) { Structure::Node * n = graph_->nodes[i]; if (node == n) { return nodesCpts_[i]; } } return nodesCpts_[0]; } void PairRelationDetector::detectConnectedPairs(Structure::Graph* g, QVector &corres) { QVector pairs; double deviation, mean_dist, max_dist;; int tmp1 = graph_->edges.size(); for ( int i = 0; i < tmp1; ++i) { Structure::Link *link = graph_->edges[i]; if ( this->bUseLink_) deviation = RelationDetector::computeDeviationByLink(link); else { Eigen::MatrixXd& ptsi = findCptsByNodeId(link->n1); Eigen::MatrixXd& ptsj = findCptsByNodeId(link->n2); distanceBetween(ptsi, ptsj, deviation, mean_dist, max_dist); } PairRelation prb(link->n1,link->n2); prb.deviation = deviation/this->normalizeCoef_; pairs.push_back(prb); } if (bModifyDeviation_) { if ( this->logLevel_ > 0) { logStream_ << "\nConnected pairs, modify deviation, normalize coeff is: " << this->normalizeCoef_ << "\n"; } modifyPairsDegree(pairs, ConnectedPairModifier(g, normalizeCoef_, bUseLink_, pointLevel_), g, corres, "Connected pairs"); } else { if ( this->logLevel_ > 0) { logStream_ << "\nConnected pairs, not modify deviation, normalize coeff is: " << this->normalizeCoef_ << "\n"; int i(0),j(0); double tmp(0.0); for ( QVector::iterator it = pairs.begin(); it != pairs.end(); ++it, ++i) { logStream_ << i << " " << *it << "\n"; if (it->deviation > tmp) { tmp = it->deviation; j = i; } } this->logStream_ << "pair " << j << " with max deviation: " << tmp << "\n\n"; } } connectedPairs_.clear(); for (QVector::iterator it = pairs.begin(); it != pairs.end(); ++it) { if (it->tag) { it->type = CONNECTED; connectedPairs_.push_back(*it); } } if( logLevel_ >0 ) { logStream_ << connectedPairs_.size() << " pairs used in tracing!" << "\n\n\n"; } } void PairRelationDetector::detectOtherPairs(Structure::Graph* g, QVector &corres) { transPairs_.clear(); refPairs_.clear(); otherPairs_.clear(); int nNodes = graph_->nodes.size(); for (int i=0; inodes[i]; double diam1 = n1->bbox().diagonal().norm(); for (int j=i+1; jnodes[j]; double diam2 = n2->bbox().diagonal().norm(); bool hasTrans(false),hasRef(false); // compare radius // whether 2 part could be symmetry coarsely if ( n1->type() == n2->type() ) { if ( (diam1/diam2) < thRadiusRadio_ && (diam2/diam1) < thRadiusRadio_ ) { hasTrans = has_trans_relation(i,j);// if ( !hasTrans) hasRef = has_ref_relation(i, j); } } } } // otherPairs_.clear(); //if (bModifyDeviation_) //{ //modifyPairsDegree(transPairs_, TransPairModifier(pointLevel_), g, corres, "Trans pairs"); //modifyPairsDegree(refPairs_, RefPairModifier(pointLevel_), g, corres, "Reflection pairs"); //} pushToOtherPairs(transPairs_, TRANS); pushToOtherPairs(refPairs_, REF); } void PairRelationDetector::detect(Structure::Graph* g, QVector &corres) { detectConnectedPairs(g, corres); detectOtherPairs(g,corres); } bool PairRelationDetector::has_trans_relation(int id1, int id2) { Eigen::Vector3d transVec = nodesCenter_[id1] - nodesCenter_[id2]; Eigen::Matrix4d transMat = create_translation3d(transVec); Eigen::MatrixXd newverts2 = transform_point3d(nodesCpts_[id2], transMat); double min_dist, mean_dist, max_dist; distanceBetween(nodesCpts_[id1], newverts2, min_dist, mean_dist, max_dist); double error = 2 * mean_dist / (nodesDiameter_[id1] + nodesDiameter_[id2]); double nerror = fixDeviationByPartName(graph_->nodes[id1]->id, graph_->nodes[id2]->id, error); if (nerror < thTransRadio_) { PairRelation pr(graph_->nodes[id1], graph_->nodes[id2]); pr.trans_vec = transVec; pr.diameter = computePairDiameter(pr); pr.deviation = error; pr.tag = true; transPairs_.push_back(pr); return true; } else return false; } bool PairRelationDetector::has_ref_relation(int id1, int id2) { Eigen::Vector3d refCenter = (nodesCenter_[id1] + nodesCenter_[id2])*0.5; Eigen::Vector3d refNormal = nodesCenter_[id1] - nodesCenter_[id2]; refNormal.normalize(); Eigen::MatrixXd newverts2; reflect_points3d(nodesCpts_[id2], refCenter, refNormal, newverts2); double min_dist, mean_dist, max_dist; distanceBetween(nodesCpts_[id1], newverts2, min_dist, mean_dist, max_dist); double error = 2 * mean_dist / (nodesDiameter_[id1] + nodesDiameter_[id2]); double nerror = fixDeviationByPartName(graph_->nodes[id1]->id, graph_->nodes[id2]->id, error); ///////////// if( logLevel_ >1 ) { logStream_ <<"<(" << graph_->nodes[id1]->id <<", " << graph_->nodes[id2]->id <<"), ref)> center: " << refCenter[0] << ", " << refCenter[1] <<", "<< refCenter[2] << "\n" <<"normal: " << refNormal[0] <<", " << refNormal[1] << ", " << refNormal[2] << "\n"; logStream_ << "deviation : " << error << "\n"; logStream_ << "\n"; } if ( nerror < thRefRadio_) { PairRelation pr(graph_->nodes[id1], graph_->nodes[id2]); pr.diameter = computePairDiameter(pr); pr.deviation = error; pr.tag = true; refPairs_.push_back(pr); return true; } else { return false; } } //bool PairRelationDetector::has_rot_relation(int id1, int id2) //{ // Structure::Node * n1 = graph_->nodes[id1]; // Structure::Node * n2 = graph_->nodes[id2]; // if ( Structure::SHEET == n1->type() || Structure::SHEET == n2->type()) // jjcao todo, check planes have rot relation // return false; // Line_3 l1 = curve2line(n1); // Line_3 l2 = curve2line(n2); // Object result = intersection(l1, l2); // if (const Point_3 *ipoint = object_cast >(&result)) // { // Eigen::Vector3d center(ipoint->x(), ipoint->y(), ipoint->z()); // // Vector_3 v1 = l1; // Vector_3 v2 = l2; // Eigen::Vector3d vec1(v1.x(), v1.y(), v1.z()); // Eigen::Vector3d vec2(v2.x(), v2.y(), v2.z()); // vec1.normalize(); vec2.normalize(); // Eigen::Vector3d direction = vec1.cross(vec2); // ////////////////////////// // double angle = asin( vec1.cross(vec2).norm() ); // double error; // Structure::Node * n; // if ( vec1.dot(vec2) > 0) // { // n = n2->clone(); // rotNodeCpts(n, center, direction, angle); // error = distanceBetweenTransNodes(n1, n); // } // else // { // n = n1->clone(); // rotNodeCpts(n, center, direction, angle); // error = distanceBetweenTransNodes(n2, n); // } // // ////////////////////////////// // if (error < thRot_) // { // PairRelation pairRel; // pairRel.type = ROT; // if ( vec1.dot(vec2) > 0) // { // pairRel.id1 = n1->id; // pairRel.id2 = n2->id; // } // else // { // pairRel.id1 = n2->id; // pairRel.id2 = n1->id; // } ///* pairRel.center = center; // pairRel.direction = direction;*/ // pairRelations_.push_back(pairRel); // return true; // } // // } // else // { // return false; // } //}