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.
VectorT< Scalar, DIM > min(const VectorT< Scalar, DIM > &_v1, const VectorT< Scalar, DIM > &_v2)
VectorT< Scalar, DIM > max(const VectorT< Scalar, DIM > &_v1, const VectorT< Scalar, DIM > &_v2)
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)
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...