filter_qhull contains preliminary version of convex hull filter and Delaunay triangulation filter.

This commit is contained in:
Michele Sottile sottile 2009-03-06 00:09:52 +00:00
parent c29b4959e8
commit 6f67bb0351
5 changed files with 690 additions and 1 deletions

View File

@ -0,0 +1,293 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
****************************************************************************/
#include <Qt>
#include <QtGui>
#include "filter_qhull.h"
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <meshlab/meshmodel.h>
#include <meshlab/interfaces.h>
#include <vcg/complex/trimesh/allocate.h>
#include <vcg/complex/trimesh/update/normal.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include "qhull_tools.h"
using namespace std;
using namespace vcg;
// Constructor usually performs only two simple tasks of filling the two lists
// - typeList: with all the possible id of the filtering actions
// - actionList with the corresponding actions. If you want to add icons to your filtering actions you can do here by construction the QActions accordingly
QhullPlugin::QhullPlugin()
{
typeList << FP_QHULL_CONVEX_HULL
<< FP_QHULL_DELAUNAY_TRIANGULATIONS
<< FP_QHULL_VORONOI_DIAGRAMS;
foreach(FilterIDType tt , types())
actionList << new QAction(filterName(tt), this);
}
QhullPlugin::~QhullPlugin()
{
for (int i = 0; i < actionList.count() ; i++ )
delete actionList.at(i);
}
// ST() must return the very short string describing each filtering action
// (this string is used also to define the menu entry)
const QString QhullPlugin::filterName(FilterIDType filterId)
{
switch(filterId) {
case FP_QHULL_CONVEX_HULL : return QString("Convex Hull");
case FP_QHULL_DELAUNAY_TRIANGULATIONS : return QString("Delaunay Triangulation");
case FP_QHULL_VORONOI_DIAGRAMS : return QString("Voronoi Diagrams");
default : assert(0);
}
return QString("Error: Unknown Filter");
}
// Info() must return the longer string describing each filtering action
// (this string is used in the About plugin dialog)
const QString QhullPlugin::filterInfo(FilterIDType filterId)
{
switch(filterId) {
case FP_QHULL_CONVEX_HULL : return QString("Calculate mesh Convex Hull with Qhull library. The convex hull of a set of points is the smallest convex set containing the points.");
case FP_QHULL_DELAUNAY_TRIANGULATIONS : return QString("Calculate mesh Delaunay triangulations with Qhull library");
case FP_QHULL_VORONOI_DIAGRAMS : return QString("Calculate mesh Voronoi diagrams with Qhull library");
default : assert(0);
}
return QString("Error: Unknown Filter");
}
// The FilterClass describes in which generic class of filters it fits.
// This choice affect the submenu in which each filter will be placed
// More than a single class can be choosen.
const QhullPlugin::FilterClass QhullPlugin::getClass(QAction *a)
{
switch(ID(a))
{
case FP_QHULL_CONVEX_HULL :
case FP_QHULL_DELAUNAY_TRIANGULATIONS :
case FP_QHULL_VORONOI_DIAGRAMS :
return FilterClass (MeshFilterInterface::Remeshing) ;
default : assert(0);
}
}
// This function define the needed parameters for each filter. Return true if the filter has some parameters
// it is called every time, so you can set the default value of parameters according to the mesh
// For each parmeter you need to define,
// - the name of the parameter,
// - the string shown in the dialog
// - the default value
// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
void QhullPlugin::initParameterSet(QAction *action,MeshModel &m, FilterParameterSet & parlst)
{
switch(ID(action)) {
case FP_QHULL_CONVEX_HULL :
{
break;
}
case FP_QHULL_DELAUNAY_TRIANGULATIONS :
{
break;
}
case FP_QHULL_VORONOI_DIAGRAMS :
{
break;
}
default : assert(0);
}
}
// The Real Core Function doing the actual mesh processing.
bool QhullPlugin::applyFilter(QAction *filter, MeshDocument &md, FilterParameterSet & par, vcg::CallBackPos *cb)
{
switch(ID(filter))
{
case FP_QHULL_CONVEX_HULL :
{
MeshModel &m=*md.mm();
MeshModel &pm =*md.addNewMesh("Qhull mesh");
if (m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)){
m.clearDataMask(MeshModel::MM_WEDGTEXCOORD);
}
if (m.hasDataMask(MeshModel::MM_VERTTEXCOORD)){
m.clearDataMask(MeshModel::MM_VERTTEXCOORD);
}
int dim= 3; /* dimension of points */
int numpoints= m.cm.vn; /* number of mesh vertices */
//facet_list contains the convex hull
//facet_list contains simplicial (triangulated) facets.
//The convex hull of a set of points is the smallest convex set containing the points.
facetT *facet_list = compute_convex_hull(dim,numpoints,m);
int convexNumFaces = qh num_facets;
int convexNumVert = qh_setsize(qh_facetvertices (facet_list, NULL, false));
assert( qh num_vertices == convexNumVert);
tri::Allocator<CMeshO>::AddVertices(pm.cm,convexNumVert);
tri::Allocator<CMeshO>::AddFaces(pm.cm,convexNumFaces);
/*ivp length is 'numpoints' because each vertex is accessed through its ID whose range is
0<=qh_pointid(vertex->point)<numpoints*/
vector<tri::Allocator<CMeshO>::VertexPointer> ivp(numpoints);
vertexT *vertex;
int vertex_n, vertex_i;
FOREACHvertex_i_(qh_facetvertices (facet_list, NULL, false)){
if ((*vertex).point){
pm.cm.vert[vertex_i].P()[0] = (*vertex).point[0];
pm.cm.vert[vertex_i].P()[1] = (*vertex).point[1];
pm.cm.vert[vertex_i].P()[2] = (*vertex).point[2];
ivp[qh_pointid(vertex->point)] = &pm.cm.vert[vertex_i];
}
}
facetT *facet;
int i=0;
FORALLfacet_(facet_list){
vertexT *vertex;
int vertex_n, vertex_i;
FOREACHvertex_i_((*facet).vertices){
pm.cm.face[i].V(vertex_i)= ivp[qh_pointid(vertex->point)];
}
i++;
}
assert( pm.cm.fn == convexNumFaces);
Log(GLLogStream::FILTER,"Successfully created a mesh of %i vert and %i faces",convexNumVert,convexNumFaces);
//m.cm.Clear();
vcg::tri::UpdateBounding<CMeshO>::Box(pm.cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(pm.cm);
int curlong, totlong; /* memory remaining after qh_memfreeshort */
qh_freeqhull(!qh_ALL);
qh_memfreeshort (&curlong, &totlong);
if (curlong || totlong)
fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
totlong, curlong);
break;
}
case FP_QHULL_DELAUNAY_TRIANGULATIONS:
{
MeshModel &m=*md.mm();
MeshModel &pm =*md.addNewMesh("Qhull mesh");
if (m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)){
m.clearDataMask(MeshModel::MM_WEDGTEXCOORD);
}
if (m.hasDataMask(MeshModel::MM_VERTTEXCOORD)){
m.clearDataMask(MeshModel::MM_VERTTEXCOORD);
}
int dim= 3; /* dimension of points */
int numpoints= m.cm.vn; /* number of mesh vertices */
//facet_list contains the delaunauy triangulation as a list of tetrahedral facets */
facetT *facet_list = compute_delaunay(dim,numpoints,m);
int convexNumFaces = qh num_facets;
int convexNumVert = qh_setsize(qh_facetvertices (facet_list, NULL, false));
assert( qh num_vertices == convexNumVert);
tri::Allocator<CMeshO>::AddVertices(pm.cm,convexNumVert);
//convexNumVert is always >= numpoints
vector<tri::Allocator<CMeshO>::VertexPointer> ivp(convexNumVert);
vertexT *vertex;
int vertex_n, vertex_i;
FOREACHvertex_i_(qh_facetvertices (facet_list, NULL, false)){
if ((*vertex).point){
pm.cm.vert[vertex_i].P()[0] = (*vertex).point[0];
pm.cm.vert[vertex_i].P()[1] = (*vertex).point[1];
pm.cm.vert[vertex_i].P()[2] = (*vertex).point[2];
ivp[qh_pointid(vertex->point)] = &pm.cm.vert[vertex_i];
}
}
// In 3-d Delaunay triangulation each facet is a tetrahedron. If triangulated,
//each ridge (d-1 vertices between two neighboring facets) is a triangle
facetT *facet, **facetp, *neighbor;
qh visit_id++;
int ridgeCount=0;
//Compute each ridge (trinagle) once
FORALLfacet_(facet_list)
if (!facet->upperdelaunay) {
facet->visitid= qh visit_id;
qh_makeridges(facet);
ridgeT *ridge, **ridgep;
FOREACHridge_(facet->ridges) {
neighbor= otherfacet_(ridge, facet);
if (neighbor->visitid != qh visit_id) {
tri::Allocator<CMeshO>::FaceIterator fi=tri::Allocator<CMeshO>::AddFaces(pm.cm,1);
ridgeCount++;
FOREACHvertex_i_(ridge->vertices)
(*fi).V(vertex_i)= ivp[qh_pointid(vertex->point)];
}
}
}
assert(pm.cm.fn == ridgeCount);
Log(GLLogStream::FILTER,"Successfully created a mesh of %i vert and %i faces",pm.cm.vn,pm.cm.fn);
//m.cm.Clear();
vcg::tri::UpdateBounding<CMeshO>::Box(pm.cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(pm.cm);
int curlong, totlong; /* memory remaining after qh_memfreeshort */
qh_freeqhull(!qh_ALL);
qh_memfreeshort (&curlong, &totlong);
if (curlong || totlong)
fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n",
totlong, curlong);
break;
}
}
return true;
}
Q_EXPORT_PLUGIN(QhullPlugin)

View File

@ -0,0 +1,69 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
****************************************************************************/
#ifndef QHULLFILTERSPLUGIN_H
#define QHULLFILTERSPLUGIN_H
#include <QObject>
#include <QStringList>
#include <QString>
#include <meshlab/meshmodel.h>
#include <meshlab/interfaces.h>
class QhullPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
Q_INTERFACES(MeshFilterInterface)
public:
/* naming convention :
- FP -> Filter Plugin
- name of the plugin separated by _
*/
enum {
FP_QHULL_CONVEX_HULL,
FP_QHULL_DELAUNAY_TRIANGULATIONS,
FP_QHULL_VORONOI_DIAGRAMS
} ;
QhullPlugin();
~QhullPlugin();
virtual const QString filterName(FilterIDType filter);
virtual const QString filterInfo(FilterIDType filter);
virtual bool autoDialog(QAction *) {return true;}
virtual void initParameterSet(QAction *,MeshModel &/*m*/, FilterParameterSet & /*parent*/);
virtual bool applyFilter(QAction * /* filter */, MeshModel &, FilterParameterSet & /*parent*/, vcg::CallBackPos *) { assert(0); return false;} ;
virtual bool applyFilter(QAction *filter, MeshDocument &m, FilterParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
virtual const FilterClass getClass(QAction *);
};
#endif

View File

@ -1 +1,40 @@
MeshLab
include (../../shared.pri)
QT += opengl
HEADERS = ../../meshlab/meshmodel.h \
filter_qhull.h \
qhull_tools.h
SOURCES = filter_qhull.cpp \
qhull_tools.cpp \
../../meshlab/meshmodel.cpp \
../../meshlab/filterparameter.cpp
HEADERS += ../../external/qhull-2003.1/src/geom.h \
../../external/qhull-2003.1/src/io.h \
../../external/qhull-2003.1/src/mem.h \
../../external/qhull-2003.1/src/merge.h \
../../external/qhull-2003.1/src/poly.h \
../../external/qhull-2003.1/src/qhull.h \
../../external/qhull-2003.1/src/qset.h \
../../external/qhull-2003.1/src/stat.h \
../../external/qhull-2003.1/src/user.h
SOURCES += ../../external/qhull-2003.1/src/geom.c \
../../external/qhull-2003.1/src/geom2.c \
$$GLEWCODE \
../../external/qhull-2003.1/src/global.c \
../../external/qhull-2003.1/src/io.c \
../../external/qhull-2003.1/src/mem.c \
../../external/qhull-2003.1/src/merge.c \
../../external/qhull-2003.1/src/poly.c \
../../external/qhull-2003.1/src/poly2.c \
../../external/qhull-2003.1/src/qconvex.c \
../../external/qhull-2003.1/src/qhull.c \
../../external/qhull-2003.1/src/qset.c \
../../external/qhull-2003.1/src/stat.c \
../../external/qhull-2003.1/src/user.c
TARGET = filter_qhull

View File

@ -0,0 +1,217 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
****************************************************************************/
#include "qhull_tools.h"
/***************************************************************************/
/* */
/* qhull conventions: */
/* coplanar point - a nearly incident point to a hyperplane */
/* point - d coordinates */
/* vertex - extreme point of the input set */
/* ridge - d-1 vertices between two neighboring facets */
/* facet - a facet with vertices, ridges, coplanar points, neighboring */
/* facets, and hyperplane */
/* simplicial facet - a facet with d vertices, d ridges, and d neighbors */
/* non-simplicial facet - a facet with more than d vertices */
/* */
/* */
/***************************************************************************/
/* dim --> dimension of points
numpoints --> number of points
m --> original mesh
compute_convex_hull(int dim, int numpoints, MeshModel &m)
build convex hull from a set of vertices of a mesh
returns
the convex hull as a list of simplicial (triangulated) facets
*/
facetT *compute_convex_hull(int dim, int numpoints, MeshModel &m)
{
coordT *points; /* array of coordinates for each point*/
boolT ismalloc= True; /* True if qhull should free points in qh_freeqhull() or reallocation */
char flags[]= "qhull Tcv"; /* option flags for qhull, see qh_opt.htm */
FILE *outfile= NULL; /* output from qh_produce_output()
use NULL to skip qh_produce_output() */
FILE *errfile= stderr; /* error messages from qhull code */
int exitcode; /* 0 if no error from qhull */
facetT *facet; /* set by FORALLfacets */
/* initialize points[] here.
points is an array of coordinates. Each triplet of coordinates rapresents a 3d vertex */
points= qh_readpointsFromMesh(&numpoints, &dim, m);
exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
flags, outfile, errfile);
//By default, Qhull merges coplanar facets. So, it's necessary to triangulate the convex hull.
//If you call qh_triangulate() method , all facets will be simplicial (e.g., triangles in 2-d)
//In theory calling qh_triangulate() or using option 'Qt' should give the same result, but,
//in this case, option Qt does not triangulate the output because coplanar faces are still merged.
qh_triangulate();
if (!exitcode) { /* if no error */
/* 'qh facet_list' contains the convex hull */
}
return qh facet_list;
};
/* dim --> dimension of points
numpoints --> number of points
m --> original mesh
compute_delaunay(int dim, int numpoints, MeshModel &m)
build Delauanay triangulation from a set of vertices of a mesh.
By default, qdelaunay merges regions with cocircular or cospherical input sites.
If you want a simplicial triangulation use triangulated output ('Qt') or joggled input ('QJ').
Option 'QJ' joggle the input to avoid cospherical and coincident sites. The result is triangulated.
Same result could be achieved with options Qz Qt.
Option 'Qz' adds a point above the paraboloid of lifted sites for a Delaunay triangulation.
It allows the Delaunay triangulation of cospherical sites.
Option 'Qt' triangulates all non-simplicial facets before generating results
returns
the Delauanay triangulation as a list of tetrahedral facets. Each face of the tetrahedron is a triangle.
*/
facetT *compute_delaunay(int dim, int numpoints, MeshModel &m)
{
coordT *points; /* array of coordinates for each point*/
boolT ismalloc= True; /* True if qhull should free points in qh_freeqhull() or reallocation */
char flags[]= "qhull d QJ Tcv"; /* option flags for qhull, see qh_opt.htm */
FILE *outfile= NULL; /* output from qh_produce_output()
use NULL to skip qh_produce_output() */
FILE *errfile= stderr; /* error messages from qhull code */
int exitcode; /* 0 if no error from qhull */
facetT *facet; /* set by FORALLfacets */
/* initialize points[] here.
points is an array of coordinates. Each triplet of coordinates rapresents a 3d vertex */
points= qh_readpointsFromMesh(&numpoints, &dim, m);
exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
flags, outfile, errfile);
//II Metodo POI CANCELLALO
//char hidden_options[]=" d v H Qbb Qf Qg Qm Qr Qu Qv Qx Qz TR E V Fp Gt Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 ";
//
//boolT new_ismalloc;
//static boolT firstcall = True;
//coordT *new_points;
//if (firstcall) {
// qh_meminit (errfile);
// firstcall= False;
//}
//if (strncmp (flags,"qhull ", 6)) {
// fprintf (errfile, "qh_new_qhull: start qhull_cmd argument with \"qhull \"\n");
// exit(1);
//}
//qh_initqhull_start (NULL, outfile, errfile);
//exitcode= setjmp (qh errexit); /* simple statement for CRAY J916 */
//if (!exitcode) {
// qh_option ("delaunay Qbbound-last", NULL, NULL);
// qh DELAUNAY= True; /* 'd' */
// qh SCALElast= True; /* 'Qbb' */
// qh KEEPcoplanar= True; /* 'Qc', to keep coplanars in 'p' */
// qh_checkflags (qh qhull_command, hidden_options);
// qh PROJECTdelaunay= True;
// qh_initflags (qh qhull_command);
// points= qh_readpointsFromMesh(&numpoints, &dim, &ismalloc, m);
// if (dim >= 5) {
// qh_option ("Qxact_merge", NULL, NULL);
// qh MERGEexact= True; /* 'Qx' always */
// }
// qh_init_B (points, numpoints, dim, ismalloc);
// qh_qhull();
// qh_check_output();
// if (outfile)
// qh_produce_output();
// if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone)
// qh_check_points();
// exitcode= qh_ERRnone;
//}
//qh_triangulate();
if (!exitcode) { /* if no error */
/* 'qh facet_list' contains the convex hull */
}
return qh facet_list;
};
/* dim --> dimension of points
numpoints --> number of points
m --> original mesh
coordT *qh_readpointsFromMesh(int *numpoints, int *dimension, MeshModel &m)
build an array of coordinates from the vertices of the mesh m.
Each triplet of coordinates rapresents a 3d vertex.
returns
the array of coordinates.
*/
coordT *qh_readpointsFromMesh(int *numpoints, int *dimension, MeshModel &m) {
coordT *points, *coords;
coords= points=
(coordT*)malloc((*numpoints)*(*dimension)*sizeof(coordT));
int cnt=0;
CMeshO::VertexIterator vi;
for(vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); ++vi)
if(!(*vi).IsD()){
for(int ii=0;ii<*dimension;++ii)
*(coords++)=(*vi).P()[ii];
++cnt;
}
assert(cnt==m.cm.vn);
return(points);
}

View File

@ -0,0 +1,71 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
//--- Include qhull, so it works from with in a C++ source file
//---
//--- In MVC one cannot just do:
//---
//--- extern "C"
//--- {
//--- #include "qhull_a.h"
//--- }
//---
//--- Because qhull_a.h includes math.h, which can not appear
//--- inside a extern "C" declaration.
//---
//--- Maybe that why Numerical recipes in C avoid this problem, by removing
//--- standard include headers from its header files and add them in the
//--- respective source files instead.
//---
//--- [K. Erleben]
/****************************************************************************
History
****************************************************************************/
#include <meshlab/meshmodel.h>
#if defined(__cplusplus)
extern "C"
{
#endif
#include <stdio.h>
#include <stdlib.h>
#include "../../external/qhull-2003.1/src/qhull.h"
#include "../../external/qhull-2003.1/src/mem.h"
#include "../../external/qhull-2003.1/src/qset.h"
#include "../../external/qhull-2003.1/src/geom.h"
#include "../../external/qhull-2003.1/src/merge.h"
#include "../../external/qhull-2003.1/src/poly.h"
#include "../../external/qhull-2003.1/src/io.h"
#include "../../external/qhull-2003.1/src/stat.h"
#if defined(__cplusplus)
}
#endif
facetT *compute_convex_hull(int dim, int numpoints, MeshModel &m);
facetT *compute_delaunay(int dim, int numpoints, MeshModel &m);
coordT *qh_readpointsFromMesh(int *numpoints, int *dimension, MeshModel &m);