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 unsigned int 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
void pluginsInitialized()
initialize the plugin
Plugin to visualize information about objects in the scene.
QString name()
Name of the Plugin.
MeshT * mesh()
return a pointer to the mesh
Type for a Meshobject containing a poly mesh.
void setDescriptions()
set scripting slot descriptions
PickTarget
What target to use for picking.
virtual QString getObjectinfo()
Get all Info for the Object as a string.
QString name() const
return the name of the object. The name defaults to NONAME if unset.
int targetCount()
Get the number of target objects.
picks faces (should be implemented for all nodes)
pick any of the prior targets (should be implemented for all nodes)
int genus(int _id)
get the genus of the given object
Type for a MeshObject containing a triangle mesh.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
bool getObject(int _identifier, BSplineCurveObject *&_object)
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
DataType supportedDataTypes()
Get data type for information requests.
int getClosestVertexInFace(MeshT *_mesh, int _face_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from a face.
int getClosestVertexFromEdge(MeshT *_mesh, int _edge_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from an edge.
VectorT< double, 3 > Vec3d
const QStringList TARGET_OBJECTS("target")
Iterable object range.
bool dataType(DataType _type) const
picks verices (may not be implemented for all nodes)
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 edges (may not be implemented for all nodes)
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
void getEdgeLengths(MeshT *_mesh, double &min, double &max, double &mean)
Get edge lengths.
int getClosestEdgeInFace(MeshT *_mesh, int _face_idx, const ACG::Vec3d &_hitPoint)
Get closest edge index from a face.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Vector cog(int _id)
get the center of gravity
void updateData(int _identifier, const UpdateType &_type, const bool deleted)
Slot that updates the visualization.
Add normals to mesh item (vertices/faces)
void slotInformationRequested(const QPoint _clickedPoint, DataType _type)
Show information dialog on clicked object.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
#define DATA_TRIANGLE_MESH
T angle(T _cos_angle, T _sin_angle)
T sane_aarg(T _aarg)
Trigonometry/angles - related.