InfoPlugin.cc 21 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
 *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openflipper.org                             *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenFlipper.                                        *
 *                                                                           *
 *  OpenFlipper is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Lesser General Public License as           *
 *  published by the Free Software Foundation, either version 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenFlipper is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU Lesser General Public License for more details.                      *
 *                                                                           *
 *  You should have received a copy of the GNU LesserGeneral Public          *
 *  License along with OpenFlipper. If not,                                  *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
Jan Möbius's avatar
Jan Möbius committed
37
 *   $Revision$                                                       *
38 39 40 41 42
 *   $Author$                                                      *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/

Jan Möbius's avatar
 
Jan Möbius committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
//=============================================================================
//
//  CLASS InfoPlugin - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================

#include <QtGui>

#include "InfoPlugin.hh"

#include <iostream>
#include <ACG/GL/GLState.hh>
#include <QStringList>
Jan Möbius's avatar
Jan Möbius committed
59
#include <QLocale>
Jan Möbius's avatar
 
Jan Möbius committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <MeshTools/MeshInfoT.hh>
#include <OpenFlipper/common/BaseObject.hh>
#include <ACG/Geometry/Algorithms.hh>

#include <Math_Tools/Math_Tools.hh>

#include <float.h>

//== IMPLEMENTATION ==========================================================

/// initialize the plugin
void InfoPlugin::pluginsInitialized() {

  //set the slot descriptions
  setDescriptions();
Jan Möbius's avatar
Jan Möbius committed
77

Jan Möbius's avatar
 
Jan Möbius committed
78 79 80 81 82 83 84 85
  // Initialize hit point
  hit_point_ = ACG::Vec3d(0.0, 0.0, 0.0);
}

//-----------------------------------------------------------------------------

template< class MeshT >
void InfoPlugin::printMeshInfo( MeshT* _mesh , int _id, unsigned int _face ) {
Jan Möbius's avatar
Jan Möbius committed
86 87 88

  QLocale locale;

Jan Möbius's avatar
 
Jan Möbius committed
89 90 91
  if (info_ == 0){
    info_ = new InfoDialog();
  }
Jan Möbius's avatar
Jan Möbius committed
92

Jan Möbius's avatar
 
Jan Möbius committed
93 94
  int closest_v_idx = getClosestVertex(_mesh, _face);
  int closest_e_idx = getClosestEdge(_mesh, _face);
Jan Möbius's avatar
Jan Möbius committed
95

Jan Möbius's avatar
 
Jan Möbius committed
96
  // ID
Jan Möbius's avatar
Jan Möbius committed
97
  info_->id->setText( tr("<B>Object ID:</B> ") + locale.toString(_id) );
Jan Möbius's avatar
 
Jan Möbius committed
98
  // Vertices
Jan Möbius's avatar
Jan Möbius committed
99
  info_->vertices->setText( tr("<B>Vertices:</B> ") + locale.toString( _mesh->n_vertices() ) );
Jan Möbius's avatar
 
Jan Möbius committed
100
  // Faces
Jan Möbius's avatar
Jan Möbius committed
101
  info_->faces->setText( tr("<B>Faces:</B> ") + locale.toString( _mesh->n_faces() ) );
Jan Möbius's avatar
 
Jan Möbius committed
102
  // Edges
Jan Möbius's avatar
Jan Möbius committed
103
  info_->edges->setText( tr("<B>Edges:</B> ") + locale.toString( _mesh->n_edges() ) );
Jan Möbius's avatar
 
Jan Möbius committed
104
  // Closest Vertex
Jan Möbius's avatar
Jan Möbius committed
105
  info_->closestv->setText( tr("<B>Closest vertex:</B> ") + locale.toString( closest_v_idx ) );
Jan Möbius's avatar
 
Jan Möbius committed
106
  // Closest Edge
Jan Möbius's avatar
Jan Möbius committed
107
  info_->closeste->setText( tr("<B>Closest edge:</B> ") + locale.toString( closest_e_idx ) );
Jan Möbius's avatar
Jan Möbius committed
108
  // Picked Vertex
Jan Möbius's avatar
Jan Möbius committed
109
  info_->pickedFace->setText( tr("<B>Picked face:</B> ") + locale.toString( _face ) );
Jan Möbius's avatar
 
Jan Möbius committed
110
  // Components
Jan Möbius's avatar
Jan Möbius committed
111
  info_->components->setText( tr("<B>Components:</B> ") + locale.toString(MeshInfo::componentCount(_mesh)));
Jan Möbius's avatar
 
Jan Möbius committed
112
  // Boundaries
Jan Möbius's avatar
Jan Möbius committed
113
  info_->boundaries->setText( tr("<B>Boundaries:</B> ") + locale.toString(MeshInfo::boundaryCount(_mesh)) );
Jan Möbius's avatar
 
Jan Möbius committed
114 115
  // Genus
  int genus = 1 - (_mesh->n_vertices() - _mesh->n_edges() + _mesh->n_faces() ) / 2;
Jan Möbius's avatar
Jan Möbius committed
116
  info_->genus->setText( tr("<B>Genus:</B> ") + QString::number(genus) );
Jan Möbius's avatar
 
Jan Möbius committed
117 118 119 120 121 122 123 124

  info_->table->clear();

  info_->table->setColumnCount ( 3 );
  info_->table->setRowCount ( 8 );


  QStringList headerdata;
Jan Möbius's avatar
Jan Möbius committed
125
  headerdata << tr("Min") << tr("Mean") << tr("Max");
Jan Möbius's avatar
 
Jan Möbius committed
126 127 128 129

  info_->table->setHorizontalHeaderLabels(headerdata);

  headerdata.clear();
Jan Möbius's avatar
Jan Möbius committed
130 131
  headerdata << tr("X Coordinate") << tr("Y Coordinate") << tr("Z Coordinate") << tr("Vertex Valence") << tr("Edge Length") << tr("Aspect Ratio");
  headerdata << tr("Inner Face Angles") << tr("Dihedral Angles");
Jan Möbius's avatar
 
Jan Möbius committed
132 133 134 135

  info_->table->setVerticalHeaderLabels(headerdata);

  //set tooltips
Jan Möbius's avatar
Jan Möbius committed
136 137 138 139 140 141 142 143 144 145
  info_->table->verticalHeaderItem(0)->setToolTip(tr("minimum, maximum and arithmetic mean of the vertex x-coordinates"));
  info_->table->verticalHeaderItem(1)->setToolTip(tr("minimum, maximum and arithmetic mean of the vertex y-coordinates"));
  info_->table->verticalHeaderItem(2)->setToolTip(tr("minimum, maximum and arithmetic mean of the vertex z-coordinates"));
  info_->table->verticalHeaderItem(3)->setToolTip(tr("minimum, maximum and arithmetic mean of the vertex valences"));
  info_->table->verticalHeaderItem(4)->setToolTip(tr("minimum, maximum and arithmetic mean of the edge lengthes"));
  info_->table->verticalHeaderItem(5)->setToolTip(tr("minimum, maximum and arithmetic mean of the aspect ratio."
                                                     " i.e. the ratio between longest and shortest edge in a triangle."));
  info_->table->verticalHeaderItem(6)->setToolTip(tr("minimum, maximum and arithmetic mean of the inner angles in a face."));
  info_->table->verticalHeaderItem(7)->setToolTip(tr("minimum, maximum and arithmetic mean of the dihedral angles"
                                                     " i.e. the angles between neighboring faces."));
Jan Möbius's avatar
 
Jan Möbius committed
146 147 148 149

  // Coordinates
  typename MeshT::VertexIter v_it;
  typename MeshT::VertexIter v_end = _mesh->vertices_end();
Jan Möbius's avatar
Jan Möbius committed
150

Jan Möbius's avatar
 
Jan Möbius committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  float maxX = FLT_MIN;
  float minX = FLT_MAX;
  float sumX = 0.0;
  float maxY = FLT_MIN;
  float minY = FLT_MAX;
  float sumY = 0.0;
  float maxZ = FLT_MIN;
  float minZ = FLT_MAX;
  float sumZ = 0.0;
  int minV = 999;
  int maxV = 0;
  int sumV = 0;
  float maxE = FLT_MIN;
  float minE = FLT_MAX;
  float sumE = 0.0;
Jan Möbius's avatar
Jan Möbius committed
166

Jan Möbius's avatar
 
Jan Möbius committed
167 168 169 170 171 172 173 174 175 176 177 178 179
  //iterate over all vertices
  for (v_it = _mesh->vertices_begin(); v_it != v_end; ++v_it){
    typename MeshT::Point p = _mesh->point( v_it.handle() );
    if (p[0] < minX) minX = p[0];
    if (p[0] > maxX) maxX = p[0];
    sumX += p[0];
    if (p[1] < minY) minY = p[1];
    if (p[1] > maxY) maxY = p[1];
    sumY += p[1];
    if (p[2] < minZ) minZ = p[2];
    if (p[2] > maxZ) maxZ = p[2];
    sumZ += p[2];

Jan Möbius's avatar
Jan Möbius committed
180 181


Jan Möbius's avatar
 
Jan Möbius committed
182 183 184
    //check valence + edge length
    int valence = 0;
    typename MeshT::VertexVertexIter vv_it;
Jan Möbius's avatar
Jan Möbius committed
185

Jan Möbius's avatar
 
Jan Möbius committed
186 187
    for (vv_it=_mesh->vv_iter( v_it ); vv_it; ++vv_it){
      valence++;
Jan Möbius's avatar
Jan Möbius committed
188

Jan Möbius's avatar
 
Jan Möbius committed
189 190 191 192 193 194 195 196 197 198 199 200
      typename MeshT::Point p2 = _mesh->point( vv_it.handle() );
      typename MeshT::Scalar len = (p2 - p).norm();

      if (len < minE) minE = len;
      if (len > maxE) maxE = len;
      sumE += len;
    }

    if (valence < minV) minV = valence;
    if (valence > maxV) maxV = valence;
    sumV += valence;
  }
Jan Möbius's avatar
Jan Möbius committed
201

Jan Möbius's avatar
 
Jan Möbius committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
  int row=0;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minX,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumX / _mesh->n_vertices(),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxX,'f') ) );
  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minY,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumY / _mesh->n_vertices(),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxY,'f') ) );
  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minZ,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumZ / _mesh->n_vertices(),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxZ,'f') ) );
  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minV) ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumV / (float)_mesh->n_vertices(),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxV) ) );
  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minE,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumE / (_mesh->n_edges()*2),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxE,'f') ) );

  //get aspect ratio

  typename MeshT::FaceIter f_it;
  typename MeshT::FaceIter f_end = _mesh->faces_end();

  float maxA = FLT_MIN;
  float minA = FLT_MAX;
  float sumA = 0.0;
  float maxI = FLT_MIN;
  float minI = FLT_MAX;
  float sumI = 0.0;
  float maxD = FLT_MIN;
  float minD = FLT_MAX;
  float sumD = 0.0;

  //iterate over all faces
  for (f_it = _mesh->faces_begin(); f_it != f_end; ++f_it){
    typename MeshT::ConstFaceVertexIter cfv_it = _mesh->cfv_iter(f_it);

    typename MeshT::Point v0 = _mesh->point( cfv_it.handle() );
    ++cfv_it;
    typename MeshT::Point v1 = _mesh->point( cfv_it.handle() );
    ++cfv_it;
    typename MeshT::Point v2 = _mesh->point( cfv_it.handle() );

    float aspect = ACG::Geometry::aspectRatio(v0, v1, v2);

    if (aspect < minA) minA = aspect;
    if (aspect > maxA) maxA = aspect;
    sumA += aspect;

    //inner triangle angles

    double angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v0) | MathTools::sane_normalized(v1 - v0) )));

    if (angle < minI) minI = angle;
    if (angle > maxI) maxI = angle;
    sumI += angle;

    angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v2 - v1) | MathTools::sane_normalized(v0 - v1) )));

    if (angle < minI) minI = angle;
    if (angle > maxI) maxI = angle;
    sumI += angle;

    angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(v1 - v2) | MathTools::sane_normalized(v0 - v2) )));

    if (angle < minI) minI = angle;
    if (angle > maxI) maxI = angle;
    sumI += angle;

    //compute dihedral angles
    typename MeshT::FaceFaceIter ff_it;
    typename MeshT::Normal n1 = _mesh->normal(f_it);

    for (ff_it = _mesh->ff_iter(f_it); ff_it; ++ff_it){

Jan Möbius's avatar
Jan Möbius committed
280
      typename MeshT::Normal n2 = _mesh->normal(ff_it);
Jan Möbius's avatar
 
Jan Möbius committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

      angle = OpenMesh::rad_to_deg(acos(OpenMesh::sane_aarg( MathTools::sane_normalized(n1) | MathTools::sane_normalized(n2) )));

      if (angle < minD) minD = angle;
      if (angle > maxD) maxD = angle;
      sumD += angle;

    }
  }

  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minA,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumA / _mesh->n_faces(),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxA,'f') ) );
  row++;
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minI,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( "-" ) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxI,'f') ) );
  row++;
Jan Möbius's avatar
Jan Möbius committed
300

Jan Möbius's avatar
 
Jan Möbius committed
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  info_->table->setItem(row,0, new QTableWidgetItem( QString::number(minD,'f') ) );
  info_->table->setItem(row,1, new QTableWidgetItem( QString::number( sumD / (_mesh->n_faces()*3),'f' )) );
  info_->table->setItem(row,2, new QTableWidgetItem( QString::number(maxD,'f') ) );

  info_->table->resizeColumnsToContents();


  info_->table3->clear();

  info_->table3->setColumnCount ( 3 );


  headerdata.clear();
  headerdata << "X" << "Y" << "Z";

  info_->table3->setHorizontalHeaderLabels(headerdata);

  typename MeshT::FaceHandle fh = _mesh->face_handle(_face);

  headerdata.clear();
Jan Möbius's avatar
Jan Möbius committed
321 322
  headerdata << tr("Bounding Box (Minimum)") << tr("Bounding Box (Maximum)") << tr("BoundingBox (Size)") << tr("Center of Gravity");
  headerdata << tr("Picked Face Normal (Handle %1 )" ).arg(fh.idx());
Jan Möbius's avatar
 
Jan Möbius committed
323 324 325 326

  typename MeshT::FaceVertexIter fv_it = _mesh->fv_iter(fh);
  int vertexCount = 0;
  while( fv_it ){
Jan Möbius's avatar
Jan Möbius committed
327
    headerdata << tr("Adjacent Vertex (Handle %1 )").arg(fv_it.handle().idx());
Jan Möbius's avatar
 
Jan Möbius committed
328 329 330 331 332 333 334 335
    ++fv_it;
    vertexCount++;
  }

  info_->table3->setRowCount ( 5 + vertexCount );
  info_->table3->setVerticalHeaderLabels(headerdata);

  //set tooltips
Jan Möbius's avatar
Jan Möbius committed
336 337 338 339 340
  info_->table3->verticalHeaderItem(0)->setToolTip(tr("minimum corner coordinates of the bounding box"));
  info_->table3->verticalHeaderItem(1)->setToolTip(tr("maximum corner coordinates of the bounding box"));
  info_->table3->verticalHeaderItem(2)->setToolTip(tr("diagonal size of the bounding box"));
  info_->table3->verticalHeaderItem(3)->setToolTip(tr("coordinates of the center of gravity"));
  info_->table3->verticalHeaderItem(4)->setToolTip(tr("direction of the face normal that was picked"));
Jan Möbius's avatar
 
Jan Möbius committed
341
  for (int i=0; i < vertexCount; i++)
Jan Möbius's avatar
Jan Möbius committed
342
    info_->table3->verticalHeaderItem(5 + i)->setToolTip(tr("Coordinates of a vertex which is adjacent to the picked face"));
Jan Möbius's avatar
 
Jan Möbius committed
343 344 345 346 347

  //Calculate Bounding Box(min,max,cog)
  ACG::Vec3d min;
  ACG::Vec3d max;
  MeshInfo::getBoundingBox(*_mesh, min, max);
Jan Möbius's avatar
Jan Möbius committed
348

Jan Möbius's avatar
 
Jan Möbius committed
349 350
  //Bounding Box Size
  ACG::Vec3d diff = max-min;
Jan Möbius's avatar
Jan Möbius committed
351

Jan Möbius's avatar
 
Jan Möbius committed
352 353 354 355 356 357 358 359 360 361 362 363 364
  row=0;
  info_->table3->setItem(row,0, new QTableWidgetItem( QString::number(min[0],'f') ) );
  info_->table3->setItem(row,1, new QTableWidgetItem( QString::number(min[1],'f') ) );
  info_->table3->setItem(row,2, new QTableWidgetItem( QString::number(min[2],'f') ) );
  row++;
  info_->table3->setItem(row,0, new QTableWidgetItem( QString::number(max[0],'f') ) );
  info_->table3->setItem(row,1, new QTableWidgetItem( QString::number(max[1],'f') ) );
  info_->table3->setItem(row,2, new QTableWidgetItem( QString::number(max[2],'f') ) );
  row++;
  info_->table3->setItem(row,0, new QTableWidgetItem( QString::number(diff[0],'f') ) );
  info_->table3->setItem(row,1, new QTableWidgetItem( QString::number(diff[1],'f') ) );
  info_->table3->setItem(row,2, new QTableWidgetItem( QString::number(diff[2],'f') ) );

Jan Möbius's avatar
Jan Möbius committed
365
  //COG
Jan Möbius's avatar
 
Jan Möbius committed
366 367 368 369 370 371 372 373 374 375 376
  ACG::Vec3d cog = MeshInfo::cog(*_mesh);

  row++;
  info_->table3->setItem(row,0, new QTableWidgetItem( QString::number(cog[0],'f') ) );
  info_->table3->setItem(row,1, new QTableWidgetItem( QString::number(cog[1],'f') ) );
  info_->table3->setItem(row,2, new QTableWidgetItem( QString::number(cog[2],'f') ) );

  //face-normal
  row++;
  info_->table3->setItem(row,0, new QTableWidgetItem( QString::number( _mesh->normal(fh)[0],'f' ) ) );
  info_->table3->setItem(row,1, new QTableWidgetItem( QString::number( _mesh->normal(fh)[1],'f' ) ) );
Jan Möbius's avatar
Jan Möbius committed
377 378
  info_->table3->setItem(row,2, new QTableWidgetItem( QString::number( _mesh->normal(fh)[2],'f' ) ) );

Jan Möbius's avatar
 
Jan Möbius committed
379 380
  fv_it = _mesh->fv_iter(fh);
  while( fv_it )
Jan Möbius's avatar
Jan Möbius committed
381
  {
Jan Möbius's avatar
 
Jan Möbius committed
382 383 384
    row++;
    info_->table3->setItem(row,0, new QTableWidgetItem( QString::number( _mesh->point(fv_it)[0],'f' ) ) );
    info_->table3->setItem(row,1, new QTableWidgetItem( QString::number( _mesh->point(fv_it)[1],'f' ) ) );
Jan Möbius's avatar
Jan Möbius committed
385
    info_->table3->setItem(row,2, new QTableWidgetItem( QString::number( _mesh->point(fv_it)[2],'f' ) ) );
Jan Möbius's avatar
 
Jan Möbius committed
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406

    ++fv_it;
  }

  info_->table3->resizeColumnsToContents();

  info_->setWindowFlags(info_->windowFlags() | Qt::WindowStaysOnTopHint);

  info_->show();
}

//----------------------------------------------------------------------------------------------

/** \brief Find closest vertex to selection
 *
 * @param _mesh Refernce to the mesh
 * @param _face_idx Index of the face that has been clicked on
 */

template <class MeshT>
int InfoPlugin::getClosestVertex(MeshT* _mesh, int _face_idx) {
Jan Möbius's avatar
Jan Möbius committed
407

Jan Möbius's avatar
 
Jan Möbius committed
408
    typename MeshT::FaceVertexIter fv_it;
Jan Möbius's avatar
Jan Möbius committed
409

Jan Möbius's avatar
 
Jan Möbius committed
410 411 412
    int closest_v_idx = 0;
    double dist = DBL_MAX;
    double temp_dist = 0.0;
Jan Möbius's avatar
Jan Möbius committed
413

Jan Möbius's avatar
 
Jan Möbius committed
414 415
    ACG::Vec3d vTemp = ACG::Vec3d(0.0, 0.0, 0.0);
    typename MeshT::Point p;
Jan Möbius's avatar
Jan Möbius committed
416

Jan Möbius's avatar
 
Jan Möbius committed
417
    for (fv_it = _mesh->fv_iter(_mesh->face_handle(_face_idx)); fv_it; ++fv_it){
Jan Möbius's avatar
Jan Möbius committed
418

Jan Möbius's avatar
 
Jan Möbius committed
419
	p = _mesh->point( fv_it.handle() );
Jan Möbius's avatar
Jan Möbius committed
420

Jan Möbius's avatar
 
Jan Möbius committed
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
	// Find closest vertex to selection
	vTemp = ACG::Vec3d(p[0], p[1], p[2]);
	temp_dist = (vTemp - hit_point_).length();

	if (temp_dist < dist) {
	    dist = temp_dist;
	    closest_v_idx = fv_it.handle().idx();
	}

    }
    return closest_v_idx;
}

//-------------------------------------------------------------------------------------------

/** \brief Find closest edge to selection
 *
 * @param _mesh Reference to the mesh
 * @param _face_idx Index of the face that has been clicked on
 */

template <class MeshT>
int InfoPlugin::getClosestEdge(MeshT* _mesh, int _face_idx) {
Jan Möbius's avatar
Jan Möbius committed
444

Jan Möbius's avatar
 
Jan Möbius committed
445 446 447
    typename MeshT::ConstFaceHalfedgeIter fh_it;
    typename MeshT::VertexHandle v1, v2;
    typename MeshT::Point p1, p2;
Jan Möbius's avatar
Jan Möbius committed
448

Jan Möbius's avatar
 
Jan Möbius committed
449 450 451 452
    ACG::Vec3d vp1, vp2, click, e, g, h;
    double x, temp_dist, dist = DBL_MAX;
    int closest_e_handle = 0;
    click = ACG::Vec3d(hit_point_[0], hit_point_[1], hit_point_[2]);
Jan Möbius's avatar
Jan Möbius committed
453

Jan Möbius's avatar
 
Jan Möbius committed
454
    for (fh_it = _mesh->fh_iter(_mesh->face_handle(_face_idx)); fh_it; ++fh_it){
Jan Möbius's avatar
Jan Möbius committed
455

Jan Möbius's avatar
 
Jan Möbius committed
456 457
	v1 = _mesh->from_vertex_handle(fh_it);
	v2 = _mesh->to_vertex_handle(fh_it);
Jan Möbius's avatar
Jan Möbius committed
458

Jan Möbius's avatar
 
Jan Möbius committed
459 460
	p1 = _mesh->point(v1);
	p2 = _mesh->point(v2);
Jan Möbius's avatar
Jan Möbius committed
461

Jan Möbius's avatar
 
Jan Möbius committed
462 463
	vp1 = ACG::Vec3d(p1[0], p1[1], p1[2]);
	vp2 = ACG::Vec3d(p2[0], p2[1], p2[2]);
Jan Möbius's avatar
Jan Möbius committed
464

Jan Möbius's avatar
 
Jan Möbius committed
465 466 467 468
	e = vp2 - vp1;
	e.normalize();
	g = click - vp1;
	x = g | e;
Jan Möbius's avatar
Jan Möbius committed
469

Jan Möbius's avatar
 
Jan Möbius committed
470
	temp_dist = (click - (vp1 + x * e)).length();
Jan Möbius's avatar
Jan Möbius committed
471

Jan Möbius's avatar
 
Jan Möbius committed
472 473 474 475 476
	if (temp_dist < dist) {
	    dist = temp_dist;
	    closest_e_handle = _mesh->edge_handle(fh_it.handle()).idx();
	}
    }
Jan Möbius's avatar
Jan Möbius committed
477

Jan Möbius's avatar
 
Jan Möbius committed
478
    return closest_e_handle;
Jan Möbius's avatar
Jan Möbius committed
479 480
}

Jan Möbius's avatar
 
Jan Möbius committed
481 482
//----------------------------------------------------------------------------------------------

Jan Möbius's avatar
Jan Möbius committed
483
void
Jan Möbius's avatar
 
Jan Möbius committed
484
InfoPlugin::
Jan Möbius's avatar
Jan Möbius committed
485
  slotMouseEventIdentify( QMouseEvent* _event ) {
Jan Möbius's avatar
 
Jan Möbius committed
486 487 488 489
  if (_event->type() == QEvent::MouseButtonPress)
  {
    unsigned int   node_idx, target_idx;
    ACG::Vec3d     hit_point;
Jan Möbius's avatar
Jan Möbius committed
490

Jan Möbius's avatar
 
Jan Möbius committed
491 492 493 494
    if (PluginFunctions::scenegraphPick(ACG::SceneGraph::PICK_FACE, _event->pos(),node_idx, target_idx, &hit_point)) {
      BaseObjectData* object;

//     BaseObject* obj = dynamic_cast< BaseObject* > (object);
Jan Möbius's avatar
Jan Möbius committed
495

Jan Möbius's avatar
 
Jan Möbius committed
496
      if ( PluginFunctions::getPickedObject(node_idx, object) ) {
Jan Möbius's avatar
Jan Möbius committed
497

Jan Möbius's avatar
 
Jan Möbius committed
498
         emit log( LOGINFO , object->getObjectinfo() );
Jan Möbius's avatar
Jan Möbius committed
499

Jan Möbius's avatar
 
Jan Möbius committed
500 501
	 // Set hit point
	 hit_point_ = ACG::Vec3d(hit_point[0], hit_point[1], hit_point[2]);
Jan Möbius's avatar
Jan Möbius committed
502 503

         if ( object->picked(node_idx) && object->dataType(DATA_TRIANGLE_MESH) )
Jan Möbius's avatar
 
Jan Möbius committed
504
            printMeshInfo( PluginFunctions::triMesh(object) , object->id(), target_idx );
Jan Möbius's avatar
Jan Möbius committed
505 506

         if ( object->picked(node_idx) && object->dataType(DATA_POLY_MESH) )
Jan Möbius's avatar
 
Jan Möbius committed
507
            printMeshInfo( PluginFunctions::polyMesh(object) , object->id(), target_idx );
Jan Möbius's avatar
Jan Möbius committed
508

Jan Möbius's avatar
 
Jan Möbius committed
509 510 511 512 513 514 515
      } else return;
    }
  }
}

//------------------------------------------------------------------------------

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
template< class MeshT >
void InfoPlugin::getEdgeLengths(MeshT* _mesh, double &min, double &max, double &mean)
{
  typename MeshT::ConstEdgeIter e_it(_mesh->edges_sbegin()),
                                e_end(_mesh->edges_end());

  min = FLT_MIN;
  max = FLT_MAX;
  mean = 0.0;
  for (; e_it!=e_end; ++e_it)
  {
    typename MeshT::Scalar len = (_mesh->point(_mesh->to_vertex_handle(_mesh->halfedge_handle(e_it, 0))) -
                                  _mesh->point(_mesh->to_vertex_handle(_mesh->halfedge_handle(e_it, 1)))).norm ();
    if (len < min) min = len;
    if (len > max) max = len;
    mean += len;
  }

  mean /= _mesh->n_edges();
}

//------------------------------------------------------------------------------

bool InfoPlugin::getEdgeLengths(int _id, double &min, double &max, double &mean)
{
  BaseObjectData* object;
  if ( ! PluginFunctions::getObject(_id,object) )
    return false;

  if ( object == 0){
Jan Möbius's avatar
Jan Möbius committed
546
    emit log(LOGERR, tr("Unable to get object"));
547 548 549 550 551 552 553
    return false;
  }

  if ( object->dataType(DATA_TRIANGLE_MESH) ) {
    TriMesh* mesh = PluginFunctions::triMesh(object);

    if ( mesh == 0 ) {
Jan Möbius's avatar
Jan Möbius committed
554
      emit log(LOGERR,tr("Unable to get mesh"));
555 556 557 558 559 560 561 562 563 564
      return false;
    }

    getEdgeLengths (mesh, min, max, mean);
    return true;

  } else {
    PolyMesh* mesh = PluginFunctions::polyMesh(object);

    if ( mesh == 0 ) {
Jan Möbius's avatar
Jan Möbius committed
565
      emit log(LOGERR,tr("Unable to get mesh"));
566 567 568 569 570 571 572 573 574 575 576 577 578 579
      return false;
    }

    getEdgeLengths (mesh, min, max, mean);
    return true;
  }

  return false;
}

//------------------------------------------------------------------------------



Jan Möbius's avatar
 
Jan Möbius committed
580 581
Q_EXPORT_PLUGIN2( InfoPlugin , InfoPlugin );

Jan Möbius's avatar
Jan Möbius committed
582