60 #include "MeshObjectInfoPlugin.hh"
62 #include <MeshTools/MeshInfoT.hh>
64 #include <Math_Tools/Math_Tools.hh>
66 #include "ValenceHistogramDialog.hh"
68 #if QT_VERSION >= 0x050000
76 InfoMeshObjectPlugin::InfoMeshObjectPlugin() :
80 lastPickedObjectId_(-1)
84 InfoMeshObjectPlugin::~InfoMeshObjectPlugin() {
90 void InfoMeshObjectPlugin::initializePlugin() {
100 if ( OpenFlipper::Options::gui()) {
108 connect(info_->valenceHistograms_pb, SIGNAL( clicked() ),
109 this, SLOT( slotShowHistogram() ));
112 info_->pickMode->setCurrentIndex(0);
114 emit addWidgetToStatusbar(infoBar_);
115 infoBar_->hideCounts();
128 template<
class MeshT >
129 void InfoMeshObjectPlugin::printMeshInfo( MeshT* _mesh ,
int _id,
unsigned int _index,
ACG::Vec3d& _hitPoint ) {
135 int closestVertexIndex = -1;
136 int closestEdgeIndex = -1;
138 switch (info_->pickMode->currentIndex() ) {
146 closestEdgeIndex = _index;
150 closestVertexIndex = _index;
154 emit log(
LOGERR,
"Error: unknown picking mode in printMeshInfo");
165 info_->generalBox->setTitle( tr(
"General object information for %1").arg( obj->
name() ) );
168 info_->id->setText( locale.toString(_id) );
170 info_->vertices->setText( locale.toString( qulonglong(_mesh->n_vertices() ) ) );
172 info_->faces->setText( locale.toString( qulonglong( _mesh->n_faces() ) ) );
174 info_->edges->setText( locale.toString( qulonglong( _mesh->n_edges() ) ) );
179 info_->closestFaceLabel->setText( tr(
"Picked Face:") );
180 info_->closestFaceLabel->show();
181 info_->faceHandle->setText( locale.toString( _index ) );
182 info_->faceHandle->show();
185 info_->closestVertexLabel->setText( tr(
"Closest Vertex:") );
186 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
189 info_->closestEdgeLabel->setText( tr(
"Closest Edge:") );
190 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
191 info_->closestEdgeLabel->show();
192 info_->edgeHandle->show();
195 info_->edgeLengthLabel->setText( tr(
"Closest Edge Length:") );
196 info_->edgeLengthLabel->show();
197 const typename MeshT::Point from = _mesh->point(_mesh->from_vertex_handle( _mesh->halfedge_handle( _mesh->edge_handle(closestEdgeIndex),0 ) ));
198 const typename MeshT::Point to = _mesh->point(_mesh->to_vertex_handle( _mesh->halfedge_handle( _mesh->edge_handle(closestEdgeIndex),0 ) ));
199 info_->edgeLength->setText( locale.toString( (to - from).norm() ) );
200 info_->edgeLength->show();
203 typename MeshT::FaceHandle fh = _mesh->face_handle(_index);
205 typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(fh);
206 QString adjacentVertices;
208 if ( fv_it.is_valid() ){
209 adjacentVertices = QString::number( fv_it->idx() );
213 while( fv_it.is_valid() ){
214 adjacentVertices +=
"; " + QString::number( fv_it->idx() );
218 info_->adjVertexHandles->setText( adjacentVertices );
219 info_->adjVertexHandles->show();
220 info_->adjacentVertexLabel->show();
223 info_->normalLabel->setText(tr(
"Normal of picked face:"));
224 info_->normalX->setText( QString::number( _mesh->normal(fh)[0],
'f' ) );
225 info_->normalY->setText( QString::number( _mesh->normal(fh)[1],
'f' ) );
226 info_->normalZ->setText( QString::number( _mesh->normal(fh)[2],
'f' ) );
227 info_->normalLabel->show();
228 info_->normalLeft->show();
229 info_->normalX->show();
230 info_->normalY->show();
231 info_->normalZ->show();
232 info_->normalRight->show();
235 info_->closestVertexPosLabel->setText(tr(
"Closest Vertex on the mesh:"));
240 info_->closestFaceLabel->setText( tr(
"Adjacent Faces:") );
241 info_->closestFaceLabel->show();
242 typename MeshT::HalfedgeHandle he1 = _mesh->halfedge_handle(_mesh->edge_handle(_index),0);
243 typename MeshT::HalfedgeHandle he2 = _mesh->halfedge_handle(_mesh->edge_handle(_index),1);
245 int fh1 = _mesh->face_handle(he1).idx();
246 int fh2 = _mesh->face_handle(he2).idx();
248 info_->faceHandle->setText( locale.toString( fh1 ) +
";" + locale.toString( fh2 ) );
249 info_->faceHandle->show();
252 info_->adjVertexHandles->setText(QString::number( _mesh->from_vertex_handle(he1).idx() ) +
";" + QString::number( _mesh->to_vertex_handle(he1).idx() ));
253 info_->adjVertexHandles->show();
254 info_->adjacentVertexLabel->show();
257 info_->closestVertexLabel->setText( tr(
"Closest Vertex:") );
258 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
261 info_->closestEdgeLabel->setText( tr(
"Picked Edge:") );
262 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
263 info_->closestEdgeLabel->show();
264 info_->edgeHandle->show();
267 info_->edgeLengthLabel->setText( tr(
"Edge Length:") );
268 info_->edgeLengthLabel->show();
269 const typename MeshT::Point from = _mesh->point(_mesh->from_vertex_handle( _mesh->halfedge_handle( _mesh->edge_handle(closestEdgeIndex),0 ) ));
270 const typename MeshT::Point to = _mesh->point(_mesh->to_vertex_handle( _mesh->halfedge_handle( _mesh->edge_handle(closestEdgeIndex),0 ) ));
271 info_->edgeLength->setText( locale.toString( (to - from).norm() ) );
272 info_->edgeLength->show();
275 info_->normalLabel->hide();
276 info_->normalLeft->hide();
277 info_->normalX->hide();
278 info_->normalY->hide();
279 info_->normalZ->hide();
280 info_->normalRight->hide();
283 info_->closestVertexPosLabel->setText(tr(
"Closest Vertex on the mesh:"));
288 info_->closestFaceLabel->hide();
289 info_->faceHandle->hide();
292 info_->adjVertexHandles->hide();
293 info_->adjacentVertexLabel->hide();
296 info_->closestVertexLabel->setText( tr(
"Picked Vertex:") );
297 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
300 info_->closestEdgeLabel->hide();
301 info_->edgeHandle->hide();
304 info_->edgeLengthLabel->hide();
305 info_->edgeLength->hide();
308 typename MeshT::VertexHandle vh = _mesh->vertex_handle(_index);
309 info_->normalLabel->setText(tr(
"Normal of picked vertex:"));
310 info_->normalX->setText( QString::number( _mesh->normal(vh)[0],
'f' ) );
311 info_->normalY->setText( QString::number( _mesh->normal(vh)[1],
'f' ) );
312 info_->normalZ->setText( QString::number( _mesh->normal(vh)[2],
'f' ) );
313 info_->normalLabel->show();
314 info_->normalLeft->show();
315 info_->normalX->show();
316 info_->normalY->show();
317 info_->normalZ->show();
318 info_->normalRight->show();
321 info_->closestVertexPosLabel->setText(tr(
"Picked Vertex on the mesh:"));
324 info_->closestFaceLabel->setText( tr(
"Adjacent Edges:") );
325 info_->closestFaceLabel->show();
329 typename MeshT::VertexEdgeIter ve_it = _mesh->ve_iter(vh);
330 QString adjacentEdges;
332 if ( ve_it.is_valid() ){
333 adjacentEdges = QString::number( ve_it->idx() );
337 while( ve_it.is_valid() ){
338 adjacentEdges +=
"; " + QString::number( ve_it->idx() );
342 info_->faceHandle->setText( adjacentEdges );
343 info_->faceHandle->show();
347 info_->vertexX->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[0],
'f' ) );
348 info_->vertexY->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[1],
'f' ) );
349 info_->vertexZ->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[2],
'f' ) );
353 int compo_count = MeshInfo::componentCount(_mesh);
354 info_->components->setText( locale.toString(compo_count));
356 int boundary_count = MeshInfo::boundaryCount(_mesh);
357 info_->boundaries->setText( locale.toString(boundary_count) );
359 int chi = _mesh->n_vertices();
360 chi -= _mesh->n_edges();
361 chi += _mesh->n_faces();
363 float genus = compo_count - 0.5*(chi + boundary_count);
364 if(compo_count == 1 && boundary_count == 0)
365 info_->genus->setText( QString::number(genus) );
366 else if(compo_count != 1)
367 info_->genus->setText(
"(multiple components)" );
369 info_->genus->setText(
"(not manifold)" );
372 typename MeshT::VertexIter v_it;
373 typename MeshT::VertexIter v_end = _mesh->vertices_end();
375 float maxX = FLT_MIN;
376 float minX = FLT_MAX;
378 float maxY = FLT_MIN;
379 float minY = FLT_MAX;
381 float maxZ = FLT_MIN;
382 float minZ = FLT_MAX;
387 float maxE = FLT_MIN;
388 float minE = FLT_MAX;
392 for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it){
393 typename MeshT::Point p = _mesh->point( *v_it );
394 if (p[0] < minX) minX = p[0];
395 if (p[0] > maxX) maxX = p[0];
397 if (p[1] < minY) minY = p[1];
398 if (p[1] > maxY) maxY = p[1];
400 if (p[2] < minZ) minZ = p[2];
401 if (p[2] > maxZ) maxZ = p[2];
408 typename MeshT::VertexVertexIter vv_it;
410 for (vv_it=_mesh->vv_iter( *v_it ); vv_it.is_valid(); ++vv_it){
413 typename MeshT::Point p2 = _mesh->point( *vv_it );
414 typename MeshT::Scalar len = (p2 - p).norm();
416 if (len < minE) minE = len;
417 if (len > maxE) maxE = len;
421 if (valence < minV) minV = valence;
422 if (valence > maxV) maxV = valence;
428 info_->valenceMin->setText( QString::number(minV) );
429 info_->valenceMean->setText( QString::number( sumV / (
float)_mesh->n_vertices(),
'f' ) );
430 info_->valenceMax->setText( QString::number(maxV) );
433 info_->edgeMin->setText( QString::number(minE,
'f') );
434 info_->edgeMean->setText( QString::number( sumE / (_mesh->n_edges()*2),
'f' ) );
435 info_->edgeMax->setText( QString::number(maxE,
'f') );
439 typename MeshT::FaceIter f_it;
440 typename MeshT::FaceIter f_end = _mesh->faces_end();
442 float maxA = FLT_MIN;
443 float minA = FLT_MAX;
445 float maxI = FLT_MIN;
446 float minI = FLT_MAX;
448 float maxD = FLT_MIN;
449 float minD = FLT_MAX;
452 unsigned int maxFValence = std::numeric_limits<unsigned int>::min();
453 unsigned int minFValence = std::numeric_limits<unsigned int>::max();
454 size_t sumFValence = 0;
457 for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it){
458 typename MeshT::ConstFaceVertexIter cfv_it = _mesh->cfv_iter(*f_it);
460 const typename MeshT::Point v0 = _mesh->point( *cfv_it );
462 const typename MeshT::Point v1 = _mesh->point( *cfv_it );
464 const typename MeshT::Point v2 = _mesh->point( *cfv_it );
468 if (aspect < minA) minA = aspect;
469 if (aspect > maxA) maxA = aspect;
474 double angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v0) | MathTools::sane_normalized(v1 - v0) )));
476 if (angle < minI) minI = angle;
477 if (angle > maxI) maxI = angle;
480 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v1) | MathTools::sane_normalized(v0 - v1) )));
482 if (angle < minI) minI = angle;
483 if (angle > maxI) maxI = angle;
486 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v1 - v2) | MathTools::sane_normalized(v0 - v2) )));
488 if (angle < minI) minI = angle;
489 if (angle > maxI) maxI = angle;
493 typename MeshT::FaceFaceIter ff_it;
496 for (ff_it = _mesh->ff_iter(*f_it); ff_it.is_valid(); ++ff_it){
500 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(n1) | MathTools::sane_normalized(n2) )));
502 if (angle < minD) minD = angle;
503 if (angle > maxD) maxD = angle;
508 const unsigned int valence = _mesh->valence(*f_it);
509 minFValence = std::min(minFValence, valence);
510 maxFValence = std::max(maxFValence, valence);
511 sumFValence += valence;
514 info_->aspectMin->setText( QString::number(minA,
'f') );
515 info_->aspectMean->setText( QString::number( sumA / _mesh->n_faces(),
'f' ) );
516 info_->aspectMax->setText( QString::number(maxA,
'f') );
518 info_->angleMin->setText( QString::number(minI,
'f') );
519 info_->angleMean->setText(
"-" );
520 info_->angleMax->setText( QString::number(maxI,
'f') );
522 info_->faceValenceMin->setText(trUtf8(
"%1").arg(minFValence));
523 info_->faceValenceMax->setText(trUtf8(
"%1").arg(maxFValence));
524 info_->faceValenceMean->setText(trUtf8(
"%1").arg(
525 static_cast<float>(sumFValence) / _mesh->n_faces()));
528 if ( _mesh->n_faces() > 1 ) {
529 info_->dihedralMin->setText( QString::number(minD,
'f') );
530 info_->dihedralMean->setText( QString::number( sumD / numD,
'f' ) );
531 info_->dihedralMax->setText( QString::number(maxD,
'f') );
533 info_->dihedralMin->setText(
"-" );
534 info_->dihedralMean->setText(
"-" );
535 info_->dihedralMax->setText(
"-" );
541 MeshInfo::getBoundingBox(_mesh, min, max);
546 info_->bbMinX->setText( QString::number(min[0],
'f') );
547 info_->bbMinY->setText( QString::number(min[1],
'f') );
548 info_->bbMinZ->setText( QString::number(min[2],
'f') );
550 info_->bbMaxX->setText( QString::number(max[0],
'f') );
551 info_->bbMaxY->setText( QString::number(max[1],
'f') );
552 info_->bbMaxZ->setText( QString::number(max[2],
'f') );
554 info_->bbSizeX->setText( QString::number(diff[0],
'f') );
555 info_->bbSizeY->setText( QString::number(diff[1],
'f') );
556 info_->bbSizeZ->setText( QString::number(diff[2],
'f') );
561 info_->cogX->setText( QString::number(cog[0],
'f') );
562 info_->cogY->setText( QString::number(cog[1],
'f') );
563 info_->cogZ->setText( QString::number(cog[2],
'f') );
566 info_->pointX->setText( QString::number( _hitPoint[0],
'f' ) );
567 info_->pointY->setText( QString::number( _hitPoint[1],
'f' ) );
568 info_->pointZ->setText( QString::number( _hitPoint[2],
'f' ) );
570 info_->setWindowFlags(info_->windowFlags() | Qt::WindowStaysOnTopHint);
587 template <
class MeshT>
590 typename MeshT::FaceVertexIter fv_it;
592 int closest_v_idx = 0;
593 double dist = DBL_MAX;
596 typename MeshT::Point p;
598 for (fv_it = _mesh->fv_iter(_mesh->face_handle(_face_idx)); fv_it.is_valid(); ++fv_it){
600 p = _mesh->point( *fv_it );
604 const double temp_dist = (vTemp - _hitPoint).length();
606 if (temp_dist < dist) {
608 closest_v_idx = fv_it->idx();
612 return closest_v_idx;
626 template <
class MeshT>
629 typename MeshT::ConstFaceHalfedgeIter fh_it;
630 typename MeshT::VertexHandle v1, v2;
631 typename MeshT::Point p1, p2;
634 double dist = DBL_MAX;
635 int closest_e_handle = 0;
637 for (fh_it = _mesh->fh_iter(_mesh->face_handle(_face_idx)); fh_it.is_valid(); ++fh_it){
639 v1 = _mesh->from_vertex_handle(*fh_it);
640 v2 = _mesh->to_vertex_handle(*fh_it);
642 p1 = _mesh->point(v1);
643 p2 = _mesh->point(v2);
648 const ACG::Vec3d e = (vp2 - vp1).normalized();
650 const double x = g | e;
652 const double temp_dist = (_hitPoint - (vp1 + x * e)).length();
654 if (temp_dist < dist) {
659 return closest_e_handle;
673 template <
class MeshT>
676 ACG::Vec3d toVertex = _mesh->point( _mesh->to_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 )) );
677 ACG::Vec3d fromVertex = _mesh->point( _mesh->from_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 )) );
679 double distTo = (_hitPoint - toVertex ).norm();
680 double distFrom = (_hitPoint - fromVertex).norm();
682 if ( distTo > distFrom )
683 return _mesh->from_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 ) ).idx();
685 return _mesh->to_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 ) ).idx();
700 size_t node_idx, target_idx;
703 if (info_->isHidden())
720 if (mesh->n_faces() != 0)
721 info_->pickMode->setCurrentIndex(0);
722 else if (mesh->n_edges() != 0)
723 info_->pickMode->setCurrentIndex(1);
725 info_->pickMode->setCurrentIndex(2);
730 if (mesh->n_faces() != 0)
731 info_->pickMode->setCurrentIndex(0);
732 else if (mesh->n_edges() != 0)
733 info_->pickMode->setCurrentIndex(1);
735 info_->pickMode->setCurrentIndex(2);
740 if (info_->pickMode->currentIndex() == 1 )
742 else if (info_->pickMode->currentIndex() == 2 )
752 lastPickedObject_ = object;
753 lastPickedObjectId_ =
object->id();
761 lastPickedObject_ = 0;
767 emit log(
LOGERR , tr(
"Unable to pick object.") );
773 template<
class MeshT >
776 typename MeshT::ConstEdgeIter e_it(_mesh->edges_sbegin()),
777 e_end(_mesh->edges_end());
782 for (; e_it!=e_end; ++e_it)
784 typename MeshT::Scalar len = (_mesh->point(_mesh->to_vertex_handle(_mesh->halfedge_handle(*e_it, 0))) -
785 _mesh->point(_mesh->to_vertex_handle(_mesh->halfedge_handle(*e_it, 1)))).norm ();
786 if (len < min) min = len;
787 if (len > max) max = len;
791 mean /= _mesh->n_edges();
803 emit log(
LOGERR, tr(
"Unable to get object"));
811 emit log(
LOGERR,tr(
"Unable to get mesh"));
822 emit log(
LOGERR,tr(
"Unable to get mesh"));
844 if (_identifier == lastPickedObjectId_ && _deleted) {
845 lastPickedObject_ = 0;
846 lastPickedObjectId_ = -1;
851 infoBar_->hideCounts();
864 if (
object && !object->
target() ) {
866 if ( !_deleted || ( o_it->id() != _identifier ) ) {
874 if (
object && object->
target() ) {
880 infoBar_->vertices->setText( QLocale::system().toString( qulonglong(mesh->n_vertices()) ) );
881 infoBar_->edges->setText( QLocale::system().toString( qulonglong(mesh->n_edges()) ) );
882 infoBar_->faces->setText( QLocale::system().toString( qulonglong(mesh->n_faces()) ) );
884 infoBar_->showCounts();
893 infoBar_->vertices->setText( QLocale::system().toString( qulonglong(mesh->n_vertices()) ) );
894 infoBar_->edges->setText( QLocale::system().toString( qulonglong(mesh->n_edges()) ) );
895 infoBar_->faces->setText( QLocale::system().toString( qulonglong(mesh->n_faces()) ) );
897 infoBar_->showCounts();
903 infoBar_->hideCounts();
908 if ( _deleted && object->
target() ) {
914 infoBar_->hideCounts();
921 void InfoMeshObjectPlugin::slotObjectUpdated(
int _identifier ,
const UpdateType& _type){
929 void InfoMeshObjectPlugin::slotObjectSelectionChanged(
int _identifier ){
935 void InfoMeshObjectPlugin::objectDeleted(
int _identifier ){
942 void InfoMeshObjectPlugin::slotAllCleared(){
944 infoBar_->hideCounts();
948 void InfoMeshObjectPlugin::slotShowHistogram() {
949 if (!lastPickedObject_)
return;
966 dialog->setAttribute(Qt::WA_DeleteOnClose,
true);
971 #if QT_VERSION < 0x050000
QString name() const
return the name of the object. The name defaults to NONAME if unset.
bool dataType(DataType _type) const
T angle(T _cos_angle, T _sin_angle)
void pluginsInitialized()
initialize the plugin
Vector cog(int _id)
get the center of gravity
void getEdgeLengths(MeshT *_mesh, double &min, double &max, double &mean)
Get edge lengths.
virtual QString getObjectinfo()
Get all Info for the Object as a string.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
picks edges (may not be implemented for all nodes)
bool getObject(int _identifier, BSplineCurveObject *&_object)
void slotInformationRequested(const QPoint _clickedPoint, DataType _type)
Show information dialog on clicked object.
Add normals to mesh item (vertices/faces)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Type for a MeshObject containing a triangle mesh.
pick any of the prior targets (should be implemented for all nodes)
Type for a Meshobject containing a poly mesh.
Plugin to visualize information about objects in the scene.
void updateData(int _identifier, const UpdateType &_type, const bool deleted)
Slot that updates the visualization.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Scalar aspectRatio(const VectorT< Scalar, N > &_v0, const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
return aspect ratio (length/height) of triangle
picks faces (should be implemented for all nodes)
int getClosestVertexFromEdge(MeshT *_mesh, int _edge_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from an edge.
#define DATA_TRIANGLE_MESH
void setDescriptions()
set scripting slot descriptions
int genus(int _id)
get the genus of the given object
int getClosestEdgeInFace(MeshT *_mesh, int _face_idx, const ACG::Vec3d &_hitPoint)
Get closest edge index from a face.
int getClosestVertexInFace(MeshT *_mesh, int _face_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from a face.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
QString name()
Name of the Plugin.
T sane_aarg(T _aarg)
Trigonometry/angles - related.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
PickTarget
What target to use for picking.
DataType supportedDataTypes()
Get data type for information requests.
VectorT< double, 3 > Vec3d
const QStringList TARGET_OBJECTS("target")
Iterable object range.
MeshT * mesh()
return a pointer to the mesh
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
picks verices (may not be implemented for all nodes)
int targetCount()
Get the number of target objects.