54#include "MeshObjectInfoPlugin.hh"
56#include <MeshTools/MeshInfoT.hh>
58#include <Math_Tools/Math_Tools.hh>
60#include "ValenceHistogramDialog.hh"
66InfoMeshObjectPlugin::InfoMeshObjectPlugin() :
70 lastPickedObjectId_(-1)
74InfoMeshObjectPlugin::~InfoMeshObjectPlugin() {
80void InfoMeshObjectPlugin::initializePlugin() {
90 if ( OpenFlipper::Options::gui()) {
98 connect(info_->valenceHistograms_pb, SIGNAL( clicked() ),
99 this, SLOT( slotShowHistogram() ));
102 info_->pickMode->setCurrentIndex(0);
104 emit addWidgetToStatusbar(infoBar_);
105 infoBar_->hideCounts();
118template<
class MeshT >
119void InfoMeshObjectPlugin::printMeshInfo(
MeshT* _mesh ,
int _id,
unsigned int _index,
ACG::Vec3d& _hitPoint ) {
125 int closestVertexIndex = -1;
126 int closestEdgeIndex = -1;
128 switch (info_->pickMode->currentIndex() ) {
136 closestEdgeIndex = _index;
140 closestVertexIndex = _index;
144 emit log(
LOGERR,
"Error: unknown picking mode in printMeshInfo");
155 info_->generalBox->setTitle( tr(
"General object information for %1").arg( obj->
name() ) );
158 info_->id->setText( locale.toString(_id) );
160 info_->vertices->setText( locale.toString( qulonglong(_mesh->
n_vertices() ) ) );
162 info_->faces->setText( locale.toString( qulonglong( _mesh->
n_faces() ) ) );
164 info_->edges->setText( locale.toString( qulonglong( _mesh->
n_edges() ) ) );
169 info_->closestFaceLabel->setText( tr(
"Picked Face:") );
170 info_->closestFaceLabel->show();
171 info_->faceHandle->setText( locale.toString( _index ) );
172 info_->faceHandle->show();
175 info_->closestVertexLabel->setText( tr(
"Closest Vertex:") );
176 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
179 info_->closestEdgeLabel->setText( tr(
"Closest Edge:") );
180 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
181 info_->closestEdgeLabel->show();
182 info_->edgeHandle->show();
185 info_->edgeLengthLabel->setText( tr(
"Closest Edge Length:") );
186 info_->edgeLengthLabel->show();
189 info_->edgeLength->setText( locale.toString( (to - from).norm() ) );
190 info_->edgeLength->show();
195 QString adjacentVertices(
"");
198 for (
auto fv_it : fh.vertices() ) {
199 adjacentVertices += QString::number( fv_it.idx() )+
";";
203 adjacentVertices.chop(1);
206 info_->adjVertexHandles->setText( adjacentVertices );
207 info_->adjVertexHandles->show();
208 info_->adjacentVertexLabel->show();
211 info_->normalLabel->setText(tr(
"Normal of picked face:"));
212 info_->normalX->setText( QString::number( _mesh->
normal(fh)[0],
'f' ) );
213 info_->normalY->setText( QString::number( _mesh->
normal(fh)[1],
'f' ) );
214 info_->normalZ->setText( QString::number( _mesh->
normal(fh)[2],
'f' ) );
215 info_->normalLabel->show();
216 info_->normalLeft->show();
217 info_->normalX->show();
218 info_->normalY->show();
219 info_->normalZ->show();
220 info_->normalRight->show();
223 info_->closestVertexPosLabel->setText(tr(
"Closest Vertex on the mesh:"));
228 info_->closestFaceLabel->setText( tr(
"Adjacent Faces:") );
229 info_->closestFaceLabel->show();
234 int fh1 = _mesh->face_handle(he1).idx();
235 int fh2 = _mesh->face_handle(he2).idx();
237 info_->faceHandle->setText( locale.toString( fh1 ) +
";" + locale.toString( fh2 ) );
238 info_->faceHandle->show();
242 info_->adjVertexHandles->show();
243 info_->adjacentVertexLabel->show();
246 info_->closestVertexLabel->setText( tr(
"Closest Vertex:") );
247 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
250 info_->closestEdgeLabel->setText( tr(
"Picked Edge:") );
251 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
252 info_->closestEdgeLabel->show();
253 info_->edgeHandle->show();
256 info_->edgeLengthLabel->setText( tr(
"Edge Length:") );
257 info_->edgeLengthLabel->show();
262 info_->edgeLength->setText( locale.toString( (to - from).norm() ) );
263 info_->edgeLength->show();
266 info_->normalLabel->hide();
267 info_->normalLeft->hide();
268 info_->normalX->hide();
269 info_->normalY->hide();
270 info_->normalZ->hide();
271 info_->normalRight->hide();
274 info_->closestVertexPosLabel->setText(tr(
"Closest Vertex on the mesh:"));
279 info_->closestFaceLabel->hide();
280 info_->faceHandle->hide();
283 info_->adjVertexHandles->hide();
284 info_->adjacentVertexLabel->hide();
287 info_->closestVertexLabel->setText( tr(
"Picked Vertex:") );
288 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
291 info_->closestEdgeLabel->hide();
292 info_->edgeHandle->hide();
295 info_->edgeLengthLabel->hide();
296 info_->edgeLength->hide();
300 info_->normalLabel->setText(tr(
"Normal of picked vertex:"));
301 info_->normalX->setText( QString::number( _mesh->
normal(vh)[0],
'f' ) );
302 info_->normalY->setText( QString::number( _mesh->
normal(vh)[1],
'f' ) );
303 info_->normalZ->setText( QString::number( _mesh->
normal(vh)[2],
'f' ) );
304 info_->normalLabel->show();
305 info_->normalLeft->show();
306 info_->normalX->show();
307 info_->normalY->show();
308 info_->normalZ->show();
309 info_->normalRight->show();
312 info_->closestVertexPosLabel->setText(tr(
"Picked Vertex on the mesh:"));
315 info_->closestFaceLabel->setText( tr(
"Adjacent Edges:") );
316 info_->closestFaceLabel->show();
318 QString adjacentEdges(
"");
321 for (
auto ve_it : vh.edges() ) {
322 adjacentEdges += QString::number( ve_it.idx() )+
";";
326 adjacentEdges.chop(1);
328 info_->faceHandle->setText( adjacentEdges );
329 info_->faceHandle->show();
333 info_->vertexX->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[0],
'f' ) );
334 info_->vertexY->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[1],
'f' ) );
335 info_->vertexZ->setText( QString::number( _mesh->point( _mesh->vertex_handle(closestVertexIndex) )[2],
'f' ) );
339 int compo_count = MeshInfo::componentCount(_mesh);
340 info_->components->setText( locale.toString(compo_count));
342 int boundary_count = MeshInfo::boundaryCount(_mesh);
343 info_->boundaries->setText( locale.toString(boundary_count) );
349 double genus = compo_count - 0.5*(chi + boundary_count);
350 if(compo_count == 1 && boundary_count == 0)
351 info_->genus->setText( QString::number(
genus) );
352 else if(compo_count != 1)
353 info_->genus->setText(
"(multiple components)" );
355 info_->genus->setText(
"(not manifold)" );
359 auto maxX = -std::numeric_limits<double>::infinity();
360 auto minX = std::numeric_limits<double>::infinity();
362 auto maxY = -std::numeric_limits<double>::infinity();
363 auto minY = std::numeric_limits<double>::infinity();
365 auto maxZ = -std::numeric_limits<double>::infinity();
366 auto minZ = std::numeric_limits<double>::infinity();
368 auto minV = std::numeric_limits<int>::max();
371 auto maxE = -std::numeric_limits<double>::infinity();
372 auto minE = std::numeric_limits<double>::infinity();
376 for (
auto v_it : _mesh->vertices()) {
377 typename MeshT::Point p = _mesh->point( v_it );
378 if (p[0] < minX) minX = p[0];
379 if (p[0] > maxX) maxX = p[0];
381 if (p[1] < minY) minY = p[1];
382 if (p[1] > maxY) maxY = p[1];
384 if (p[2] < minZ) minZ = p[2];
385 if (p[2] > maxZ) maxZ = p[2];
393 for (
auto vv_it : v_it.vertices()) {
396 typename MeshT::Point p2 = _mesh->point( vv_it );
397 typename MeshT::Scalar len = (p2 - p).norm();
399 if (len < minE) minE = len;
400 if (len > maxE) maxE = len;
404 if (valence < minV) minV = valence;
405 if (valence > maxV) maxV = valence;
412 info_->valenceMin->setText( QString::number(minV) );
413 info_->valenceMean->setText( QString::number( sumV / (
double)_mesh->
n_vertices(),
'f' ) );
414 info_->valenceMax->setText( QString::number(maxV) );
420 info_->edgeMin->setText( QString::number(minE,
'f') );
421 info_->edgeMean->setText( QString::number( sumE / (_mesh->
n_edges()*2),
'f' ) );
422 info_->edgeMax->setText( QString::number(maxE,
'f') );
424 info_->edgeMin->setText(
"-" );
425 info_->edgeMean->setText(
"-" );
426 info_->edgeMax->setText(
"-" );
435 auto maxA = -std::numeric_limits<double>::infinity();
436 auto minA = std::numeric_limits<double>::infinity();
438 auto maxI = -std::numeric_limits<double>::infinity();
439 auto minI = std::numeric_limits<double>::infinity();
441 auto maxD = -std::numeric_limits<double>::infinity();
442 auto minD = std::numeric_limits<double>::infinity();
445 unsigned int maxFValence = std::numeric_limits<unsigned int>::min();
446 unsigned int minFValence = std::numeric_limits<unsigned int>::max();
447 size_t sumFValence = 0;
450 for (
auto f_it : _mesh->faces()) {
451 typename MeshT::ConstFaceVertexIter cfv_it = _mesh->cfv_iter(f_it);
453 const typename MeshT::Point v0 = _mesh->point( *cfv_it );
455 const typename MeshT::Point v1 = _mesh->point( *cfv_it );
457 const typename MeshT::Point v2 = _mesh->point( *cfv_it );
461 if (aspect < minA) minA = aspect;
462 if (aspect > maxA) maxA = aspect;
467 double angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v0) | MathTools::sane_normalized(v1 - v0) )));
469 if (angle < minI) minI =
angle;
470 if (angle > maxI) maxI =
angle;
473 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v1) | MathTools::sane_normalized(v0 - v1) )));
475 if (angle < minI) minI =
angle;
476 if (angle > maxI) maxI =
angle;
479 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(v1 - v2) | MathTools::sane_normalized(v0 - v2) )));
481 if (angle < minI) minI =
angle;
482 if (angle > maxI) maxI =
angle;
486 const typename MeshT::Normal n1 = _mesh->
normal(f_it);
488 for (
auto ff_it : f_it.faces()) {
490 const typename MeshT::Normal n2 = _mesh->
normal(ff_it);
492 angle = OpenMesh::rad_to_deg(acos(
OpenMesh::sane_aarg( MathTools::sane_normalized(n1) | MathTools::sane_normalized(n2) )));
494 if (angle < minD) minD =
angle;
495 if (angle > maxD) maxD =
angle;
500 const unsigned int valence = _mesh->
valence(f_it);
501 minFValence = std::min(minFValence, valence);
502 maxFValence = std::max(maxFValence, valence);
503 sumFValence += valence;
506 info_->aspectMin->setText( QString::number(minA,
'f') );
507 info_->aspectMean->setText( QString::number( sumA / _mesh->
n_faces(),
'f' ) );
508 info_->aspectMax->setText( QString::number(maxA,
'f') );
511 info_->angleMin->setText( QString::number(minI,
'f') );
512 info_->angleMean->setText(
"-" );
513 info_->angleMax->setText( QString::number(maxI,
'f') );
515 info_->faceValenceMin->setText(tr(
"%1").arg(minFValence));
516 info_->faceValenceMax->setText(tr(
"%1").arg(maxFValence));
517 info_->faceValenceMean->setText(tr(
"%1").arg(
static_cast<double>(sumFValence) / _mesh->
n_faces()));
520 info_->dihedralMin->setText( QString::number(minD,
'f') );
521 info_->dihedralMean->setText( QString::number( sumD / numD,
'f' ) );
522 info_->dihedralMax->setText( QString::number(maxD,
'f') );
524 info_->dihedralMin->setText(
"-" );
525 info_->dihedralMean->setText(
"-" );
526 info_->dihedralMax->setText(
"-" );
531 info_->aspectMin->setText(
"-" );
532 info_->aspectMean->setText(
"-" );
533 info_->aspectMax->setText(
"-" );
536 info_->angleMin->setText(
"-" );
537 info_->angleMean->setText(
"-" );
538 info_->angleMax->setText(
"-" );
540 info_->faceValenceMin->setText(
"-");
541 info_->faceValenceMax->setText(
"-");
542 info_->faceValenceMean->setText(
"-");
544 info_->dihedralMin->setText(
"-" );
545 info_->dihedralMean->setText(
"-" );
546 info_->dihedralMax->setText(
"-" );
553 MeshInfo::getBoundingBox(_mesh, min, max);
558 info_->bbMinX->setText( QString::number(min[0],
'f') );
559 info_->bbMinY->setText( QString::number(min[1],
'f') );
560 info_->bbMinZ->setText( QString::number(min[2],
'f') );
562 info_->bbMaxX->setText( QString::number(max[0],
'f') );
563 info_->bbMaxY->setText( QString::number(max[1],
'f') );
564 info_->bbMaxZ->setText( QString::number(max[2],
'f') );
566 info_->bbSizeX->setText( QString::number(diff[0],
'f') );
567 info_->bbSizeY->setText( QString::number(diff[1],
'f') );
568 info_->bbSizeZ->setText( QString::number(diff[2],
'f') );
573 info_->cogX->setText( QString::number(
cog[0],
'f') );
574 info_->cogY->setText( QString::number(
cog[1],
'f') );
575 info_->cogZ->setText( QString::number(
cog[2],
'f') );
578 info_->pointX->setText( QString::number( _hitPoint[0],
'f' ) );
579 info_->pointY->setText( QString::number( _hitPoint[1],
'f' ) );
580 info_->pointZ->setText( QString::number( _hitPoint[2],
'f' ) );
582 info_->setWindowFlags(info_->windowFlags() | Qt::WindowStaysOnTopHint);
599template <
class MeshT>
602 int closest_v_idx = 0;
603 double dist = DBL_MAX;
609 const typename MeshT::Point p = _mesh->point( fv_it );
611 const double temp_dist = (vTemp - _hitPoint).length();
613 if (temp_dist < dist) {
615 closest_v_idx = fv_it.idx();
619 return closest_v_idx;
633template <
class MeshT>
636 typename MeshT::VertexHandle v1, v2;
637 typename MeshT::Point p1, p2;
640 double dist = DBL_MAX;
641 int closest_e_handle = 0;
648 p1 = _mesh->point(v1);
649 p2 = _mesh->point(v2);
654 const ACG::Vec3d e = (vp2 - vp1).normalized();
656 const double x = g | e;
658 const double temp_dist = (_hitPoint - (vp1 + x * e)).
length();
660 if (temp_dist < dist) {
661 closest_e_handle = fh_it.edge().idx();
666 return closest_e_handle;
680template <
class MeshT>
686 double distTo = (_hitPoint - toVertex ).norm();
687 double distFrom = (_hitPoint - fromVertex).norm();
689 if ( distTo > distFrom )
707 size_t node_idx, target_idx;
710 if (info_->isHidden())
727 if (mesh->n_faces() != 0)
728 info_->pickMode->setCurrentIndex(0);
729 else if (mesh->n_edges() != 0)
730 info_->pickMode->setCurrentIndex(1);
732 info_->pickMode->setCurrentIndex(2);
737 if (mesh->n_faces() != 0)
738 info_->pickMode->setCurrentIndex(0);
739 else if (mesh->n_edges() != 0)
740 info_->pickMode->setCurrentIndex(1);
742 info_->pickMode->setCurrentIndex(2);
746 if (info_->pickMode->currentIndex() == 1 )
748 else if (info_->pickMode->currentIndex() == 2 )
760 lastPickedObject_ = object;
761 lastPickedObjectId_ =
object->id();
769 lastPickedObject_ = 0;
775 emit log(
LOGERR , tr(
"Unable to pick object.") );
781template<
class MeshT >
785 min = std::numeric_limits<double>::infinity();
786 max = -std::numeric_limits<double>::infinity();
789 for (
auto e_it : _mesh->edges())
791 typename MeshT::Scalar len = (_mesh->point(e_it.h0().to()) -
792 _mesh->point(e_it.h1().to())).norm ();
793 if (len < min) min = len;
794 if (len > max) max = len;
810 emit log(
LOGERR, tr(
"Unable to get object"));
818 emit log(
LOGERR,tr(
"Unable to get mesh"));
829 emit log(
LOGERR,tr(
"Unable to get mesh"));
851 if (_identifier == lastPickedObjectId_ && _deleted) {
852 lastPickedObject_ = 0;
853 lastPickedObjectId_ = -1;
858 infoBar_->hideCounts();
871 if (
object && !object->
target() ) {
873 if ( !_deleted || ( o_it->id() != _identifier ) ) {
881 if (
object && object->
target() ) {
887 infoBar_->vertices->setText( QLocale::system().toString( qulonglong(mesh->n_vertices()) ) );
888 infoBar_->edges->setText( QLocale::system().toString( qulonglong(mesh->n_edges()) ) );
889 infoBar_->faces->setText( QLocale::system().toString( qulonglong(mesh->n_faces()) ) );
891 infoBar_->showCounts();
900 infoBar_->vertices->setText( QLocale::system().toString( qulonglong(mesh->n_vertices()) ) );
901 infoBar_->edges->setText( QLocale::system().toString( qulonglong(mesh->n_edges()) ) );
902 infoBar_->faces->setText( QLocale::system().toString( qulonglong(mesh->n_faces()) ) );
904 infoBar_->showCounts();
910 infoBar_->hideCounts();
915 if ( _deleted && object->
target() ) {
921 infoBar_->hideCounts();
928void InfoMeshObjectPlugin::slotObjectUpdated(
int _identifier ,
const UpdateType& _type){
936void InfoMeshObjectPlugin::slotObjectSelectionChanged(
int _identifier ){
942void InfoMeshObjectPlugin::objectDeleted(
int _identifier ){
949void InfoMeshObjectPlugin::slotAllCleared(){
951 infoBar_->hideCounts();
955void InfoMeshObjectPlugin::slotShowHistogram() {
956 if (!lastPickedObject_)
return;
973 dialog->setAttribute(Qt::WA_DeleteOnClose,
true);
#define DATA_TRIANGLE_MESH
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.
bool dataType(DataType _type) const
int genus(int _id)
get the genus of the given object
void slotInformationRequested(const QPoint _clickedPoint, DataType _type)
Show information dialog on clicked object.
void setDescriptions()
set scripting slot descriptions
int getClosestVertexFromEdge(MeshT *_mesh, int _edge_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from an edge.
void updateData(int _identifier, const UpdateType &_type, const bool deleted)
Slot that updates the visualization.
int getClosestEdgeInFace(MeshT *_mesh, int _face_idx, const ACG::Vec3d &_hitPoint)
Get closest edge index from a face.
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.
QString name()
Name of the Plugin.
void getEdgeLengths(MeshT *_mesh, double &min, double &max, double &mean)
Get edge lengths.
Vector cog(int _id)
get the center of gravity
void pluginsInitialized()
initialize the plugin
MeshT * mesh()
return a pointer to the mesh
int idx() const
Get the underlying index of this handle.
auto length() const -> decltype(std::declval< VectorT< S, DIM > >().norm())
compute squared euclidean norm
PointT normal(HalfFaceHandle _hfh) const
size_t valence(VertexHandle _vh) const
Get valence of vertex (number of incident edges)
size_t n_vertices() const override
Get number of vertices in mesh.
size_t n_faces() const override
Get number of faces in mesh.
size_t n_edges() const override
Get number of edges in mesh.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
Type for a Meshobject containing a poly mesh.
Type for a MeshObject containing a triangle mesh.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
Scalar aspectRatio(const VectorT< Scalar, N > &_v0, const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
return aspect ratio (length/height) of triangle
PickTarget
What target to use for picking.
@ PICK_EDGE
picks edges (may not be implemented for all nodes)
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
@ PICK_FACE
picks faces (should be implemented for all nodes)
@ PICK_VERTEX
picks verices (may not be implemented for all nodes)
VectorT< double, 3 > Vec3d
T angle(T _cos_angle, T _sin_angle)
T sane_aarg(T _aarg)
Trigonometry/angles - related.
int targetCount()
Get the number of target objects.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool getPickedObject(const size_t _node_idx, BaseObjectData *&_object)
Get the picked mesh.
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
ObjectRange objects(IteratorRestriction _restriction, DataType _dataType)
Iterable object range.
SmartHalfedgeHandle h1() const
Shorthand for halfedge(1)
SmartHalfedgeHandle h0() const
Shorthand for halfedge(0)
PolyConnectivity::ConstFaceVertexRange vertices() const
Returns a range of vertices incident to the face (PolyConnectivity::fv_range())
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const
Returns a range of halfedges of the face (PolyConnectivity::fh_range())
SmartVertexHandle from() const
Returns vertex at start of halfedge.
SmartVertexHandle to() const
Returns vertex pointed to by halfedge.
Smart version of VertexHandle contains a pointer to the corresponding mesh and allows easier access t...