Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • adfc2e5
  • /
  • ScorerLib
  • /
  • PairRelationDetector.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge Iframe embedding
swh:1:cnt:2d6610b54fe601321cc9072dc3694b9414b158d1
directory badge Iframe embedding
swh:1:dir:c635832c07bb0f28337c2b5951f21be98346eb63

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
PairRelationDetector.cpp
#include "PairRelationDetector.h"
#pragma warning(disable:4100 4101)

void PairRelationDetector::pushToOtherPairs(QVector<PairRelation>& prs, QString type)
{
	for (QVector<PairRelation>::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<Eigen::Vector3d> 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<PART_LANDMARK> &corres)
{
	QVector<PairRelation> 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<PairRelation>::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<PairRelation>::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<PART_LANDMARK> &corres)
{
	transPairs_.clear();    refPairs_.clear();
	otherPairs_.clear();

    int nNodes = graph_->nodes.size();
    for (int i=0; i<nNodes; ++i)
    {
		Structure::Node *n1 = graph_->nodes[i];
        double diam1 = n1->bbox().diagonal().norm();        
        for (int j=i+1; j<nNodes; ++j)
        {
			Structure::Node *n2 = graph_->nodes[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<PART_LANDMARK> &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<Kernel> *ipoint = object_cast<Point_3<Kernel> >(&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;
//	}
//}

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API