Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MeshObjectInfoPlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50 //=============================================================================
51 //
52 // CLASS InfoMeshObjectPlugin - IMPLEMENTATION
53 //
54 //=============================================================================
55
56
57 //== INCLUDES =================================================================
58
59
60 #include "MeshObjectInfoPlugin.hh"
61
62 #include <MeshTools/MeshInfoT.hh>
63
64 #include <Math_Tools/Math_Tools.hh>
65
66 #include "ValenceHistogramDialog.hh"
67
68 #if QT_VERSION >= 0x050000
69 #else
70 #include <QtGui>
71 #endif
72
73 //== IMPLEMENTATION ==========================================================
74
75
76 InfoMeshObjectPlugin::InfoMeshObjectPlugin() :
77 info_(0),
78 infoBar_(0),
79 lastPickedObject_(0),
80 lastPickedObjectId_(-1)
81 {
82 }
83
84 InfoMeshObjectPlugin::~InfoMeshObjectPlugin() {
85
86 //Info bar and dialog will be deleted by core widget
87 }
88
89
90 void InfoMeshObjectPlugin::initializePlugin() {
91
92 }
93
95 void InfoMeshObjectPlugin::pluginsInitialized() {
96
97 //set the slot descriptions
98 setDescriptions();
99
100 if ( OpenFlipper::Options::gui()) {
101
102 // Create info bar
103 infoBar_ = new InfoBar();
104
105 // Create info dialog
106 info_ = new InfoDialog();
107
108 connect(info_->valenceHistograms_pb, SIGNAL( clicked() ),
109 this, SLOT( slotShowHistogram() ));
110
111 // Set default pick mode in dialog box
112 info_->pickMode->setCurrentIndex(0); // PICK_FACES
113
114 emit addWidgetToStatusbar(infoBar_);
115 infoBar_->hideCounts();
116 }
117
118 }
119
120 //-----------------------------------------------------------------------------
121
122 DataType InfoMeshObjectPlugin::supportedDataTypes() {
123 return DataType(DATA_POLY_MESH | DATA_TRIANGLE_MESH);
124 }
125
126 //-----------------------------------------------------------------------------
127
128 template< class MeshT >
129 void InfoMeshObjectPlugin::printMeshInfo( MeshT* _mesh , int _id, unsigned int _index, ACG::Vec3d& _hitPoint ) {
130
131 bool face = false;
132 bool edge = false;
133 bool vertex = false;
134
135 int closestVertexIndex = -1;
136 int closestEdgeIndex = -1;
137
138 switch (info_->pickMode->currentIndex() ) {
139 case 0 : //Face
140 closestVertexIndex = getClosestVertexInFace(_mesh, _index, _hitPoint);
141 closestEdgeIndex = getClosestEdgeInFace (_mesh, _index, _hitPoint);
142 face = true;
143 break;
144 case 1 : //Edge
145 closestVertexIndex = getClosestVertexFromEdge(_mesh, _index, _hitPoint);
146 closestEdgeIndex = _index;
147 edge = true;
148 break;
149 case 2 : //Vertex
150 closestVertexIndex = _index;
151 vertex = true;
152 break;
153 default:
154 emit log(LOGERR,"Error: unknown picking mode in printMeshInfo");
155 return;
156 }
157
158 QLocale locale;
159
160 QString name;
161
162 // name
163 BaseObject* obj = 0;
164 if ( PluginFunctions::getObject(_id, obj) )
165 info_->generalBox->setTitle( tr("General object information for %1").arg( obj->name() ) );
166
167 // ID
168 info_->id->setText( locale.toString(_id) );
169 // Vertices
170 info_->vertices->setText( locale.toString( qulonglong(_mesh->n_vertices() ) ) );
171 // Faces
172 info_->faces->setText( locale.toString( qulonglong( _mesh->n_faces() ) ) );
173 // Edges
174 info_->edges->setText( locale.toString( qulonglong( _mesh->n_edges() ) ) );
175
176 if ( face ) {
177
178 // Picked Face
179 info_->closestFaceLabel->setText( tr("Picked Face:") );
180 info_->closestFaceLabel->show();
181 info_->faceHandle->setText( locale.toString( _index ) );
182 info_->faceHandle->show();
183
184 // Closest Vertex
185 info_->closestVertexLabel->setText( tr("Closest Vertex:") );
186 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
187
188 // Closest Edge
189 info_->closestEdgeLabel->setText( tr("Closest Edge:") );
190 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
191 info_->closestEdgeLabel->show();
192 info_->edgeHandle->show();
193
194 // Closest Edge Length
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();
201
202 //adjacent vertex handles
203 typename MeshT::FaceHandle fh = _mesh->face_handle(_index);
204
205 typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(fh);
206 QString adjacentVertices;
207
208 if ( fv_it.is_valid() ){
209 adjacentVertices = QString::number( fv_it->idx() );
210 ++fv_it;
211 }
212
213 while( fv_it.is_valid() ){
214 adjacentVertices += "; " + QString::number( fv_it->idx() );
215 ++fv_it;
216 }
217
218 info_->adjVertexHandles->setText( adjacentVertices );
219 info_->adjVertexHandles->show();
220 info_->adjacentVertexLabel->show();
221
222 //normal
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();
233
234 // closest vertex coordinates
235 info_->closestVertexPosLabel->setText(tr("Closest Vertex on the mesh:"));
236
237 } else if (edge) {
238
239 // Adjacent Faces
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);
244
245 int fh1 = _mesh->face_handle(he1).idx();
246 int fh2 = _mesh->face_handle(he2).idx();
247
248 info_->faceHandle->setText( locale.toString( fh1 ) + ";" + locale.toString( fh2 ) );
249 info_->faceHandle->show();
250
251 // Adjacent vertices
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();
255
256 // Closest Vertex
257 info_->closestVertexLabel->setText( tr("Closest Vertex:") );
258 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
259
260 // Picked Edge
261 info_->closestEdgeLabel->setText( tr("Picked Edge:") );
262 info_->edgeHandle->setText( locale.toString( closestEdgeIndex ) );
263 info_->closestEdgeLabel->show();
264 info_->edgeHandle->show();
265
266 // Edge Length
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();
273
274 // Normal
275 info_->normalLabel->hide();
276 info_->normalLeft->hide();
277 info_->normalX->hide();
278 info_->normalY->hide();
279 info_->normalZ->hide();
280 info_->normalRight->hide();
281
282 // closest vertex coordinates
283 info_->closestVertexPosLabel->setText(tr("Closest Vertex on the mesh:"));
284
285 } else if (vertex) {
286
287 // Faces
288 info_->closestFaceLabel->hide();
289 info_->faceHandle->hide();
290
291 // Adjacent vertices
292 info_->adjVertexHandles->hide();
293 info_->adjacentVertexLabel->hide();
294
295 // Closest Vertex
296 info_->closestVertexLabel->setText( tr("Picked Vertex:") );
297 info_->vertexHandle->setText( locale.toString( closestVertexIndex ) );
298
299 // Closest Edge
300 info_->closestEdgeLabel->hide();
301 info_->edgeHandle->hide();
302
303 // Edge Length
304 info_->edgeLengthLabel->hide();
305 info_->edgeLength->hide();
306
307 // Normal
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();
319
320 // closest vertex coordinates
321 info_->closestVertexPosLabel->setText(tr("Picked Vertex on the mesh:"));
322
323 // Adjacent Edges
324 info_->closestFaceLabel->setText( tr("Adjacent Edges:") );
325 info_->closestFaceLabel->show();
326
327 //adjacent vertex handles
328
329 typename MeshT::VertexEdgeIter ve_it = _mesh->ve_iter(vh);
330 QString adjacentEdges;
331
332 if ( ve_it.is_valid() ){
333 adjacentEdges = QString::number( ve_it->idx() );
334 ++ve_it;
335 }
336
337 while( ve_it.is_valid() ){
338 adjacentEdges += "; " + QString::number( ve_it->idx() );
339 ++ve_it;
340 }
341
342 info_->faceHandle->setText( adjacentEdges );
343 info_->faceHandle->show();
344 }
345
346 // closest vertex coordinates
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' ) );
350
351
352 // Components
353 int compo_count = MeshInfo::componentCount(_mesh);
354 info_->components->setText( locale.toString(compo_count));
355 // Boundaries
356 int boundary_count = MeshInfo::boundaryCount(_mesh);
357 info_->boundaries->setText( locale.toString(boundary_count) );
358 // Genus
359 int chi = _mesh->n_vertices();
360 chi -= _mesh->n_edges();
361 chi += _mesh->n_faces(); // chi = Euler characteristic
362 // chi + n_holes = 2(n_components - genus) => genus = n_components - (chi + n_holes)/2;
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)" );
368 else
369 info_->genus->setText( "(not manifold)" );
370
371 // Coordinates
372 typename MeshT::VertexIter v_it;
373 typename MeshT::VertexIter v_end = _mesh->vertices_end();
374
375 float maxX = FLT_MIN;
376 float minX = FLT_MAX;
377 //float sumX = 0.0;
378 float maxY = FLT_MIN;
379 float minY = FLT_MAX;
380 //float sumY = 0.0;
381 float maxZ = FLT_MIN;
382 float minZ = FLT_MAX;
383 //float sumZ = 0.0;
384 int minV = 999;
385 int maxV = 0;
386 int sumV = 0;
387 float maxE = FLT_MIN;
388 float minE = FLT_MAX;
389 float sumE = 0.0;
390
391 //iterate over all vertices
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];
396 //sumX += p[0];
397 if (p[1] < minY) minY = p[1];
398 if (p[1] > maxY) maxY = p[1];
399 //sumY += p[1];
400 if (p[2] < minZ) minZ = p[2];
401 if (p[2] > maxZ) maxZ = p[2];
402 //sumZ += p[2];
403
404
405
406 //check valence + edge length
407 int valence = 0;
408 typename MeshT::VertexVertexIter vv_it;
409
410 for (vv_it=_mesh->vv_iter( *v_it ); vv_it.is_valid(); ++vv_it){
411 valence++;
412
413 typename MeshT::Point p2 = _mesh->point( *vv_it );
414 typename MeshT::Scalar len = (p2 - p).norm();
415
416 if (len < minE) minE = len;
417 if (len > maxE) maxE = len;
418 sumE += len;
419 }
420
421 if (valence < minV) minV = valence;
422 if (valence > maxV) maxV = valence;
423 sumV += valence;
424 }
425
426
427 //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) );
431
432 //edge length
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') );
436
437 //get aspect ratio
438
439 typename MeshT::FaceIter f_it;
440 typename MeshT::FaceIter f_end = _mesh->faces_end();
441
442 float maxA = FLT_MIN;
443 float minA = FLT_MAX;
444 float sumA = 0.0;
445 float maxI = FLT_MIN;
446 float minI = FLT_MAX;
447 //float sumI = 0.0;
448 float maxD = FLT_MIN;
449 float minD = FLT_MAX;
450 float sumD = 0.0;
451 int numD = 0;
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;
455
456 //iterate over all faces
457 for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it){
458 typename MeshT::ConstFaceVertexIter cfv_it = _mesh->cfv_iter(*f_it);
459
460 const typename MeshT::Point v0 = _mesh->point( *cfv_it );
461 ++cfv_it;
462 const typename MeshT::Point v1 = _mesh->point( *cfv_it );
463 ++cfv_it;
464 const typename MeshT::Point v2 = _mesh->point( *cfv_it );
465
466 const float aspect = ACG::Geometry::aspectRatio(v0, v1, v2);
467
468 if (aspect < minA) minA = aspect;
469 if (aspect > maxA) maxA = aspect;
470 sumA += aspect;
471
472 //inner triangle angles
473
474 double angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v0) | MathTools::sane_normalized(v1 - v0) )));
475
476 if (angle < minI) minI = angle;
477 if (angle > maxI) maxI = angle;
478 //sumI += angle;
479
480 angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v1) | MathTools::sane_normalized(v0 - v1) )));
481
482 if (angle < minI) minI = angle;
483 if (angle > maxI) maxI = angle;
484 //sumI += angle;
485
486 angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v1 - v2) | MathTools::sane_normalized(v0 - v2) )));
487
488 if (angle < minI) minI = angle;
489 if (angle > maxI) maxI = angle;
490 //sumI += angle;
491
492 //compute dihedral angles
493 typename MeshT::FaceFaceIter ff_it;
494 const typename MeshT::Normal n1 = _mesh->normal(*f_it);
495
496 for (ff_it = _mesh->ff_iter(*f_it); ff_it.is_valid(); ++ff_it){
497
498 const typename MeshT::Normal n2 = _mesh->normal(*ff_it);
499
500 angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(n1) | MathTools::sane_normalized(n2) )));
501
502 if (angle < minD) minD = angle;
503 if (angle > maxD) maxD = angle;
504 sumD += angle;
505 numD ++;
506 }
507
508 const unsigned int valence = _mesh->valence(*f_it);
509 minFValence = std::min(minFValence, valence);
510 maxFValence = std::max(maxFValence, valence);
511 sumFValence += valence;
512 }
513
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') );
517
518 info_->angleMin->setText( QString::number(minI,'f') );
519 info_->angleMean->setText( "-" );
520 info_->angleMax->setText( QString::number(maxI,'f') );
521
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()));
526
527 // Only one face or no face -> don't output angles
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') );
532 } else {
533 info_->dihedralMin->setText( "-" );
534 info_->dihedralMean->setText( "-" );
535 info_->dihedralMax->setText( "-" );
536 }
537
538 //Calculate Bounding Box(min,max,cog)
539 ACG::Vec3d min;
540 ACG::Vec3d max;
541 MeshInfo::getBoundingBox(_mesh, min, max);
542
543 //Bounding Box Size
544 ACG::Vec3d diff = max-min;
545
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') );
549
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') );
553
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') );
557
558 //COG
559 ACG::Vec3d cog = MeshInfo::cog(_mesh);
560
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') );
564
565 //hitpoint
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' ) );
569
570 info_->setWindowFlags(info_->windowFlags() | Qt::WindowStaysOnTopHint);
571
572
573 info_->show();
574 }
575
576 //----------------------------------------------------------------------------------------------
577
587 template <class MeshT>
588 int InfoMeshObjectPlugin::getClosestVertexInFace(MeshT* _mesh, int _face_idx, ACG::Vec3d& _hitPoint) {
589
590 typename MeshT::FaceVertexIter fv_it;
591
592 int closest_v_idx = 0;
593 double dist = DBL_MAX;
594
595 ACG::Vec3d vTemp = ACG::Vec3d(0.0, 0.0, 0.0);
596 typename MeshT::Point p;
597
598 for (fv_it = _mesh->fv_iter(_mesh->face_handle(_face_idx)); fv_it.is_valid(); ++fv_it){
599
600 p = _mesh->point( *fv_it );
601
602 // Find closest vertex to selection
603 vTemp = ACG::Vec3d(p[0], p[1], p[2]);
604 const double temp_dist = (vTemp - _hitPoint).length();
605
606 if (temp_dist < dist) {
607 dist = temp_dist;
608 closest_v_idx = fv_it->idx();
609 }
610
611 }
612 return closest_v_idx;
613 }
614
615 //-------------------------------------------------------------------------------------------
616
626 template <class MeshT>
627 int InfoMeshObjectPlugin::getClosestEdgeInFace(MeshT* _mesh, int _face_idx, const ACG::Vec3d& _hitPoint) {
628
629 typename MeshT::ConstFaceHalfedgeIter fh_it;
630 typename MeshT::VertexHandle v1, v2;
631 typename MeshT::Point p1, p2;
632
633 ACG::Vec3d vp1, vp2, h;
634 double dist = DBL_MAX;
635 int closest_e_handle = 0;
636
637 for (fh_it = _mesh->fh_iter(_mesh->face_handle(_face_idx)); fh_it.is_valid(); ++fh_it){
638
639 v1 = _mesh->from_vertex_handle(*fh_it);
640 v2 = _mesh->to_vertex_handle(*fh_it);
641
642 p1 = _mesh->point(v1);
643 p2 = _mesh->point(v2);
644
645 vp1 = ACG::Vec3d(p1[0], p1[1], p1[2]);
646 vp2 = ACG::Vec3d(p2[0], p2[1], p2[2]);
647
648 const ACG::Vec3d e = (vp2 - vp1).normalized();
649 const ACG::Vec3d g = _hitPoint - vp1;
650 const double x = g | e;
651
652 const double temp_dist = (_hitPoint - (vp1 + x * e)).length();
653
654 if (temp_dist < dist) {
655 dist = temp_dist;
656 }
657 }
658
659 return closest_e_handle;
660 }
661
662 //----------------------------------------------------------------------------------------------
663
673 template <class MeshT>
674 int InfoMeshObjectPlugin::getClosestVertexFromEdge(MeshT* _mesh, int _edge_idx, ACG::Vec3d& _hitPoint) {
675
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 )) );
678
679 double distTo = (_hitPoint - toVertex ).norm();
680 double distFrom = (_hitPoint - fromVertex).norm();
681
682 if ( distTo > distFrom )
683 return _mesh->from_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 ) ).idx();
684 else
685 return _mesh->to_vertex_handle( _mesh->halfedge_handle(_mesh->edge_handle(_edge_idx),0 ) ).idx();
686
687 }
688
689 //----------------------------------------------------------------------------------------------
690
691 void
692 InfoMeshObjectPlugin::
693 slotInformationRequested(const QPoint _clickedPoint, DataType _type) {
694
695 // Only respond on mesh objects
696 if((_type != DATA_TRIANGLE_MESH) && (_type != DATA_POLY_MESH)) return;
697
698 ACG::SceneGraph::PickTarget target = ACG::SceneGraph::PICK_FACE;
699
700 unsigned int node_idx, target_idx;
701 ACG::Vec3d hit_point;
702
703 if (info_->isHidden())
704 {
705 //user couldn't select the pick mode,
706 //so we have to do this
707 target = ACG::SceneGraph::PICK_ANYTHING;
708 if (!PluginFunctions::scenegraphPick(target, _clickedPoint, node_idx, target_idx, &hit_point))
709 return;
710
711 BaseObjectData* object;
712 if (!PluginFunctions::getPickedObject(node_idx, object) )
713 return;
714
715 //object is picked, now we can decide, what the user wants to pick
716 //priority: face > edge > vertex
717 if ( object->dataType(DATA_TRIANGLE_MESH) )
718 {
719 TriMesh* mesh = PluginFunctions::triMesh(object);
720 if (mesh->n_faces() != 0)
721 info_->pickMode->setCurrentIndex(0);
722 else if (mesh->n_edges() != 0)
723 info_->pickMode->setCurrentIndex(1);
724 else
725 info_->pickMode->setCurrentIndex(2);
726 }
727 else if ( object->dataType(DATA_POLY_MESH) )
728 {
729 PolyMesh* mesh = PluginFunctions::polyMesh(object);
730 if (mesh->n_faces() != 0)
731 info_->pickMode->setCurrentIndex(0);
732 else if (mesh->n_edges() != 0)
733 info_->pickMode->setCurrentIndex(1);
734 else
735 info_->pickMode->setCurrentIndex(2);
736 }
737 }
738
739 target = ACG::SceneGraph::PICK_FACE;
740 if (info_->pickMode->currentIndex() == 1 )
741 target = ACG::SceneGraph::PICK_EDGE;
742 else if (info_->pickMode->currentIndex() == 2 )
743 target = ACG::SceneGraph::PICK_VERTEX;
744
745 if (PluginFunctions::scenegraphPick(target, _clickedPoint, node_idx, target_idx, &hit_point)) {
746 BaseObjectData* object;
747
748 if ( PluginFunctions::getPickedObject(node_idx, object) ) {
749
750 emit log( LOGINFO , object->getObjectinfo() );
751
752 lastPickedObject_ = object;
753 lastPickedObjectId_ = object->id();
754
755 if ( object->dataType(DATA_TRIANGLE_MESH) )
756 printMeshInfo( PluginFunctions::triMesh(object) , object->id(), target_idx, hit_point );
757
758 if ( object->dataType(DATA_POLY_MESH) )
759 printMeshInfo( PluginFunctions::polyMesh(object) , object->id(), target_idx, hit_point );
760 } else {
761 lastPickedObject_ = 0;
762 return;
763 }
764 }
765 else
766 {
767 emit log( LOGERR , tr("Unable to pick object.") );
768 }
769 }
770
771 //------------------------------------------------------------------------------
772
773 template< class MeshT >
774 void InfoMeshObjectPlugin::getEdgeLengths(MeshT* _mesh, double &min, double &max, double &mean)
775 {
776 typename MeshT::ConstEdgeIter e_it(_mesh->edges_sbegin()),
777 e_end(_mesh->edges_end());
778
779 min = FLT_MAX;
780 max = FLT_MIN;
781 mean = 0.0;
782 for (; e_it!=e_end; ++e_it)
783 {
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;
788 mean += len;
789 }
790
791 mean /= _mesh->n_edges();
792 }
793
794 //------------------------------------------------------------------------------
795
796 bool InfoMeshObjectPlugin::getEdgeLengths(int _id, double &min, double &max, double &mean)
797 {
798 BaseObjectData* object;
799 if ( ! PluginFunctions::getObject(_id,object) )
800 return false;
801
802 if ( object == 0){
803 emit log(LOGERR, tr("Unable to get object"));
804 return false;
805 }
806
807 if ( object->dataType(DATA_TRIANGLE_MESH) ) {
808 TriMesh* mesh = PluginFunctions::triMesh(object);
809
810 if ( mesh == 0 ) {
811 emit log(LOGERR,tr("Unable to get mesh"));
812 return false;
813 }
814
815 getEdgeLengths (mesh, min, max, mean);
816 return true;
817
818 } else {
819 PolyMesh* mesh = PluginFunctions::polyMesh(object);
820
821 if ( mesh == 0 ) {
822 emit log(LOGERR,tr("Unable to get mesh"));
823 return false;
824 }
825
826 getEdgeLengths (mesh, min, max, mean);
827 return true;
828 }
829
830 return false;
831 }
832
833 //------------------------------------------------------------------------------
834
835 void InfoMeshObjectPlugin::updateData( int _identifier , const UpdateType& _type, const bool _deleted){
836
837 if ( !infoBar_ ) {
838 return;
839 }
840
841 BaseObjectData* object;
842 PluginFunctions::getObject(_identifier,object);
843
844 if (_identifier == lastPickedObjectId_ && _deleted) {
845 lastPickedObject_ = 0;
846 lastPickedObjectId_ = -1;
847 }
848
849 // Last object that is target has been removed.
850 if ( _deleted && object && object->target() && (PluginFunctions::targetCount() == 1) ) {
851 infoBar_->hideCounts();
852 return;
853 }
854
855 // We only show the information in the status bar if one target mesh is selected or
856 // If 2 targets where selected, where one is deleted which was target
857 if ( PluginFunctions::targetCount() == 1 || ( _deleted && (PluginFunctions::targetCount() == 2) && object && object->target() ) ) {
858
859
860
861 // The object that caused the update is not a target anymore.
862 // Therefore we need to get the remaining target by iteration.
863 // If something was deleted, we might see this object here, so make sure, to not take the one with the same id as the deleted one
864 if ( object && !object->target() ) {
865 for ( PluginFunctions::ObjectIterator o_it = PluginFunctions::ObjectIterator(PluginFunctions::TARGET_OBJECTS); o_it != PluginFunctions::objectsEnd(); ++o_it ) {
866 if ( !_deleted || ( o_it->id() != _identifier ) ) {
867 object = *o_it;
868 break;
869 }
870 }
871 }
872
873 // We only need to update something, if the updated object is the target object
874 if (object && object->target() ) {
875
876 if (object->dataType(DATA_TRIANGLE_MESH)){
877
878 TriMesh* mesh = PluginFunctions::triMesh(object);
879
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()) ) );
883
884 infoBar_->showCounts();
885
886 return;
887 }
888
889 if (object->dataType(DATA_POLY_MESH)){
890
891 PolyMesh* mesh = PluginFunctions::polyMesh(object);
892
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()) ) );
896
897 infoBar_->showCounts();
898 return;
899 }
900
901 }
902
903 infoBar_->hideCounts();
904
905 } else {
906 // Display only count information
907 if ( (PluginFunctions::targetCount() > 1) && object ) {
908 if ( _deleted && object->target() ) {
909 infoBar_->showTargetCount( PluginFunctions::targetCount() - 1);
910 } else {
911 infoBar_->showTargetCount( PluginFunctions::targetCount() );
912 }
913 } else
914 infoBar_->hideCounts();
915 }
916
917 }
918
919 //------------------------------------------------------------------------------
920
921 void InfoMeshObjectPlugin::slotObjectUpdated( int _identifier , const UpdateType& _type){
922
923 updateData(_identifier,_type,false);
924
925 }
926
927 //------------------------------------------------------------------------------
928
929 void InfoMeshObjectPlugin::slotObjectSelectionChanged( int _identifier ){
930 updateData(_identifier,UPDATE_ALL,false);
931 }
932
933 //------------------------------------------------------------------------------
934
935 void InfoMeshObjectPlugin::objectDeleted( int _identifier ){
936 updateData(_identifier,UPDATE_ALL,true);
937 }
938
939
940 //------------------------------------------------------------------------------
941
942 void InfoMeshObjectPlugin::slotAllCleared(){
943 if ( infoBar_ )
944 infoBar_->hideCounts();
945
946 }
947
948 void InfoMeshObjectPlugin::slotShowHistogram() {
949 if (!lastPickedObject_) return;
950
951 ValenceHistogramDialog *dialog = 0;
952 {
953 TriMeshObject *tmo = dynamic_cast<TriMeshObject*>(lastPickedObject_);
954 if (tmo) {
955 dialog = new ValenceHistogramDialog(*tmo->mesh(), info_);
956 }
957 }
958
959 if (!dialog) {
960 PolyMeshObject *pmo = dynamic_cast<PolyMeshObject*>(lastPickedObject_);
961 if (pmo) {
962 dialog = new ValenceHistogramDialog(*pmo->mesh(), info_);
963 }
964 }
965
966 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
967 dialog->show();
968 dialog->raise();
969 }
970
971 #if QT_VERSION < 0x050000
972 Q_EXPORT_PLUGIN2( InfoMeshObjectPlugin , InfoMeshObjectPlugin );
973 #endif
974
975
InfoMeshObjectPlugin::pluginsInitialized
void pluginsInitialized()
initialize the plugin
Definition: MeshObjectInfoPlugin.cc:95
InfoMeshObjectPlugin
Plugin to visualize information about objects in the scene.
Definition: MeshObjectInfoPlugin.hh:83
InfoMeshObjectPlugin::name
QString name()
Name of the Plugin.
Definition: MeshObjectInfoPlugin.hh:137
MeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
PolyMeshObject
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:70
InfoMeshObjectPlugin::setDescriptions
void setDescriptions()
set scripting slot descriptions
Definition: MeshObjectInfoScripting.cc:60
OpenMesh::PolyMesh_ArrayKernelT
Definition: PolyMesh_ArrayKernelT.hh:98
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
BaseObject::getObjectinfo
virtual QString getObjectinfo()
Get all Info for the Object as a string.
Definition: BaseObject.cc:255
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
BaseObject::name
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
PluginFunctions::targetCount
int targetCount()
Get the number of target objects.
Definition: PluginFunctions.cc:1010
ACG::SceneGraph::PICK_FACE
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
InfoMeshObjectPlugin::genus
int genus(int _id)
get the genus of the given object
Definition: MeshObjectInfoScripting.cc:338
UpdateType
Update type class.
Definition: UpdateType.hh:70
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:73
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:134
InfoMeshObjectPlugin::supportedDataTypes
DataType supportedDataTypes()
Get data type for information requests.
Definition: MeshObjectInfoPlugin.cc:122
InfoDialog
Definition: infoDialog.hh:59
InfoMeshObjectPlugin::getClosestVertexInFace
int getClosestVertexInFace(MeshT *_mesh, int _face_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from a face.
Definition: MeshObjectInfoPlugin.cc:588
InfoMeshObjectPlugin::getClosestVertexFromEdge
int getClosestVertexFromEdge(MeshT *_mesh, int _edge_idx, ACG::Vec3d &_hitPoint)
Get closest vertex index from an edge.
Definition: MeshObjectInfoPlugin.cc:674
ACG::Vec3d
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
ACG::SceneGraph::PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
ACG::Geometry::aspectRatio
Scalar aspectRatio(const VectorT< Scalar, N > &_v0, const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
return aspect ratio (length/height) of triangle
Definition: Algorithms.cc:1266
ACG::SceneGraph::PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition: BaseNode.hh:106
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:140
InfoMeshObjectPlugin::getEdgeLengths
void getEdgeLengths(MeshT *_mesh, double &min, double &max, double &mean)
Get edge lengths.
Definition: MeshObjectInfoPlugin.cc:774
InfoMeshObjectPlugin::getClosestEdgeInFace
int getClosestEdgeInFace(MeshT *_mesh, int _face_idx, const ACG::Vec3d &_hitPoint)
Get closest edge index from a face.
Definition: MeshObjectInfoPlugin.cc:627
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:452
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:187
BaseObject
Definition: BaseObject.hh:94
OpenMesh::VectorT
Definition: Vector11T.hh:83
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
InfoBar
Definition: infoBar.hh:59
ValenceHistogramDialog
Definition: ValenceHistogramDialog.hh:64
InfoMeshObjectPlugin::cog
Vector cog(int _id)
get the center of gravity
Definition: MeshObjectInfoScripting.cc:380
LOGINFO
Definition: LoggingInterface.hh:105
InfoMeshObjectPlugin::updateData
void updateData(int _identifier, const UpdateType &_type, const bool deleted)
Slot that updates the visualization.
Definition: MeshObjectInfoPlugin.cc:835
OpenMesh::Attributes::Normal
Add normals to mesh item (vertices/faces)
Definition: Attributes.hh:87
InfoMeshObjectPlugin::slotInformationRequested
void slotInformationRequested(const QPoint _clickedPoint, DataType _type)
Show information dialog on clicked object.
Definition: MeshObjectInfoPlugin.cc:693
PluginFunctions::scenegraphPick
bool scenegraphPick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
Execute picking operation on scenegraph.
Definition: PluginFunctions.cc:482
DataType
Predefined datatypes.
Definition: DataTypes.hh:96
PluginFunctions::getPickedObject
bool getPickedObject(const unsigned int _node_idx, BaseObjectData *&_object)
Get the picked mesh.
Definition: PluginFunctions.cc:263
BaseObject::target
bool target()
Definition: BaseObject.cc:284
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
OpenMesh::angle
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:145
OpenMesh::sane_aarg
T sane_aarg(T _aarg)
Trigonometry/angles - related.
Definition: MathDefs.hh:127