1 /****************************************************************************
2 * MeshLab o o *
3 * A versatile mesh processing toolbox o o *
4 * _ O _ *
5 * Copyright(C) 2005 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23
24 #include <QtGui>
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include <time.h>
29
30 #include <meshlab/meshmodel.h>
31 #include <meshlab/interfaces.h>
32
33 #include <vcg/complex/algorithms/clean.h>
34 #include <vcg/complex/algorithms/update/position.h>
35 #include <vcg/complex/algorithms/update/normal.h>
36 #include <vcg/complex/algorithms/update/bounding.h>
37 #include <vcg/complex/allocate.h>
38
39 #include <vcg/complex/algorithms/update/selection.h>
40 #include <vcg/complex/append.h>
41
42 #include "filter_rangemap.h"
43
44 using namespace std;
45 using namespace vcg;
46
47 // Constructor
RangeMapPlugin()48 RangeMapPlugin::RangeMapPlugin()
49 {
50 typeList <<
51 FP_SELECTBYANGLE;
52
53 foreach(FilterIDType tt , types())
54 actionList << new QAction(filterName(tt), this);
55 }
56
57 // ST() return the very short string describing each filtering action
filterName(FilterIDType filterId)58 const QString RangeMapPlugin::filterName(FilterIDType filterId)
59 {
60 switch(filterId) {
61 case FP_SELECTBYANGLE : return QString("Select Faces by view angle");
62 default : assert(0);
63 }
64 }
65
66 // Info() return the longer string describing each filtering action
filterInfo(FilterIDType filterId)67 const QString RangeMapPlugin::filterInfo(FilterIDType filterId)
68 {
69 switch(filterId) {
70 case FP_SELECTBYANGLE : return QString("Select faces according to the angle between their normal and the view direction. It is used in range map processing to select and delete steep faces parallel to viewdirection");
71 default : assert(0);
72 }
73 }
74
75 // Return true if the specified action has an automatic dialog.
76 // return false if the action has no parameters or has an self generated dialog.
autoDialog(QAction * action)77 bool RangeMapPlugin::autoDialog(QAction *action)
78 {
79 switch(ID(action))
80 {
81 case FP_SELECTBYANGLE :
82 return true;
83 }
84 return false;
85 }
86
87 // This function define the needed parameters for each filter.
initParameterSet(QAction * action,MeshDocument & m,FilterParameterSet & parlst)88 void RangeMapPlugin::initParameterSet(QAction *action, MeshDocument &m, FilterParameterSet & parlst)
89 {
90 switch(ID(action))
91 {
92 case FP_SELECTBYANGLE :
93 {
94 parlst.addDynamicFloat("anglelimit",
95 75.0f, 0.0f, 180.0f, MeshModel::MM_FACEFLAGSELECT,
96 "angle threshold (deg)",
97 "faces with normal at higher angle w.r.t. the view direction are selected");
98 parlst.addBool ("usecamera",
99 false,
100 "Use ViewPoint from Mesh Camera",
101 "Uses the ViewPoint from the camera associated to the current mesh\n if there is no camera, an error occurs");
102 parlst.addPoint3f("viewpoint",
103 Point3f(0.0f, 0.0f, 0.0f),
104 "ViewPoint",
105 "if UseCamera is true, this value is ignored");
106 }
107 break;
108
109 default : assert(0);
110 }
111 }
112
113 // Core Function doing the actual mesh processing.
applyFilter(QAction * filter,MeshDocument & m,FilterParameterSet & par,vcg::CallBackPos * cb)114 bool RangeMapPlugin::applyFilter(QAction *filter, MeshDocument &m, FilterParameterSet & par, vcg::CallBackPos *cb)
115 {
116 CMeshO::FaceIterator fi;
117
118 switch(ID(filter))
119 {
120 case FP_SELECTBYANGLE :
121 {
122 bool usecam = par.getBool("usecamera");
123 Point3f viewpoint = par.getPoint3f("viewpoint");
124
125 // if usecamera but mesh does not have one
126 if( usecam && !m.mm()->hasDataMask(MeshModel::MM_CAMERA) )
127 {
128 errorMessage = "Mesh has not a camera that can be used to compute view direction. Please set a view direction."; // text
129 return false;
130 }
131 if(usecam)
132 {
133 viewpoint = m.mm()->cm.shot.GetViewPoint();
134 }
135
136 // angle threshold in radians
137 float limit = cos( math::ToRad(par.getDynamicFloat("anglelimit")) );
138 Point3f viewray;
139
140 for(fi=m.mm()->cm.face.begin();fi!=m.mm()->cm.face.end();++fi)
141 if(!(*fi).IsD())
142 {
143 viewray = viewpoint - Barycenter(*fi);
144 viewray.Normalize();
145
146 if((viewray.dot((*fi).N().Normalize())) < limit)
147 fi->SetS();
148 }
149
150 }
151 break;
152
153 }
154
155 return true;
156 }
157
getClass(QAction * a)158 const RangeMapPlugin::FilterClass RangeMapPlugin::getClass(QAction *a)
159 {
160 switch(ID(a))
161 {
162 case FP_SELECTBYANGLE :
163 return MeshFilterInterface::FilterClass(MeshFilterInterface::RangeMap + MeshFilterInterface::Selection);
164 default :
165 return MeshFilterInterface::Generic;
166 }
167 }
168
169 Q_EXPORT_PLUGIN(RangeMapPlugin)
170