RelationDetector.h
#pragma once
#include "transform3d.h"
#include "Geometry.h"
#include "StructureGraph.h"
#include "GraphCorresponder.h"
static QString TRANS = "TRANS";
static QString REF = "REF";
static QString PARALLEL = "PARALLEL";
static QString ORTHOGONAL = "ORTHOGONAL";
static QString COPLANAR = "COPLANAR";
static QString CONNECTED = "CONNECTED"; // for all connected pairs
static QString NONE = "NONE";
class PairRelation
{
public:
PairRelation():n1(0),n2(0),tag(true),type(NONE){}
PairRelation(Structure::Node* node1, Structure::Node* node2):n1(node1),n2(node2){}
bool isDegenerated(){return n1==0 || n2==0;}
Structure::Node* n1;
Structure::Node* n2;
QString type;
//for connected pair, deviation is: mini distance between the skeleton' s control points of n1 & n2. has been normalized by graph->bbox().diagonal().norm()
//for translation pair, deviation is: mean distance between the skeleton' s control points of n1 & that of n2 after translation. has been normalized by n1 & n2's diameters
double deviation;
bool tag;
double diameter; // diameter of the pair
Eigen::Vector3d trans_vec;// for TRANS
//Eigen::Vector3d normal; // for coplanar
//Eigen::Vector3d point; // for coplanar
friend QTextStream& operator<<(QTextStream& os, const PairRelation& pr);
};
static QString TRANS_SYMMETRY = "TRANS_SYMMETRY"; // build from Trans pair, except AXIS_SYMMETRY
static QString AXIS_SYMMETRY = "AXIS_SYMMETRY";
static QString REF_SYMMETRY = "REF_SYMMETRY";
struct GroupRelation
{
GroupRelation():deviation(0.0){}
QVector<QString> ids; //QSet<QString> ids;
QString type;
QString note;// from trans or ref pair
double diameter; // group diameter
double deviation; // absolute mean deviation
bool tag;
Point_3 center; // for AXIS_SYMMETRY
Vector_3 direction; // normalized. line direction for AXIS_SYMMETRY
Eigen::Vector3d normal;// normalized. for coplanar & REF_SYMMETRY group
Eigen::Vector3d point;// for coplanar group & REF_SYMMETRY group
bool equal(GroupRelation& gr);
friend QTextStream& operator<<(QTextStream& os, const GroupRelation& gr);
};
bool isTaged(const PairRelation &pr);
bool isTagedGr(const GroupRelation &gr);
void saveToFile(QString filename, QVector<PairRelation>& prs);
void saveToFile(QString filename, QVector<GroupRelation>& grs);
template<class T>
int countByType(QVector<T>& prs, QString& type)
{
int i(0);
foreach(T pr, prs)
{
if ( 0 == type.compare(pr.type))
++i;
}
return i;
}
class RelationDetector
{
public:
RelationDetector(Structure::Graph* g, const QString& logprefix, int ith, double normalizeCoef, int pointLevel=1, int logLevel=0);
~RelationDetector(){logFile_.close();}
//////////////////////////////////////////////////
// find nodes in the source or target shape
// bSource == true means that the id is from target shape, & we want to find its corresponded node in source shape, then graph should be source
std::vector<Structure::Node*> findNodesInST(QString id, Structure::Graph *graph, QVector<PART_LANDMARK> &corres, bool bSource);
// find nodes in a blended shape, all returned nodes are not degenerated.
// bSource == true means that the id is from source shape
std::vector<Structure::Node*> findNodesInB(QString id, Structure::Graph *graph, QVector<PART_LANDMARK> &corres, bool bSource);
/////////////////////////////////////////////////
Eigen::MatrixXd node2matrix(Structure::Node* node, int pointLevel);
int extractCpts( Structure::Node * n, std::vector<Eigen::Vector3d>& mcpts, int pointsLevel);
void vectorPts2MatrixPts(const std::vector<Eigen::Vector3d>& ptsin, Eigen::MatrixXd& ptsout);
std::vector<Eigen::Vector3d> matrixPts2VectorPts(Eigen::MatrixXd& ptsin);
////////////////////////////////////////////////
static Segment_3 curve2segment(Structure::Node * n);
static Line_3 curve2line(Structure::Node * n);
static Eigen::Vector3d curve2vectorNormalized(Structure::Node * n);
static std::vector<Point_3> sheet2rect(Structure::Node * n);
static void sheet2plane(Structure::Sheet * s, Vector3& point, Vector3& normal);
// normalized
static bool node2direction(Structure::Node * n, Vector_3& result);
// output:
// point
// normal
// only work for two curve node
void createPlane(Structure::Node *n1,Structure::Node *n2, Eigen::Vector3d& point, Eigen::Vector3d& normal);
//////////////////////////////////////////////////
double computePairDiameter(PairRelation& pr);
// relative to the diameter of the graph, i.e. model
double computeGroupDiameter(GroupRelation& gr);
void computeGroupCenter(GroupRelation& gr);
void findRefPlane(Structure::Node* n1, Structure::Node* n2, Eigen::Vector3d& center,Eigen::Vector3d& normal);
double fixDeviationByPartName(const QString& s1, const QString& s2, double deviation, double times=0.5);
// we do not order part in a group by ref plane
// return mean deviation of the group
// precondition: none
double computeRefSymmetryGroupDeviation(GroupRelation& gr, int pointLevel);
// order part in a group by angle around the axis
// return mean deviation of the group
// precondition: center & direction of gr is known.
double computeAxisSymmetryGroupDeviationSortParts(GroupRelation& gr, int pointLevel);
// return mean deviation of the group
// precondition 1: center & direction of gr is known.
// precondition 2: order of parts is determined
double computeAxisSymmetryGroupDeviation(const GroupRelation& gr, int pointLevel);
// compute the center and direction of the group
void computeTransGroupInfo(GroupRelation &gr, QSet<QString>& ids);
static Structure::Link* findLink(Structure::Node *n1, Structure::Node *n2, Structure::Graph * graph);
static double computeDeviationByLink(Structure::Link* link);
protected:
Eigen::Vector3d computeCptsCenter(Structure::Node* nn);
double errorOfRefSymmGroup(std::vector<Structure::Node*> &nodes, Eigen::Vector3d& center, Eigen::Vector3d& normal, int pointLevel);
public:
double thRadiusRadio_;
double thTransRadio_;
double thRefRadio_;
double thParal_;
double thOthog_;
double thCopla_;
double thRefGroup_;
double thAxisGroup_;
double thAxisDeviationRadio_;
double thCoplaGroup_;
Structure::Graph* graph_;
double normalizeCoef_;
int pointLevel_;// 0 for main control points, 1 for all control points, 2 for all points.
protected:
QFile logFile_;
QTextStream logStream_;
int logLevel_; // 0 for no log; 1 for coarse log; 2 for detailed log
};