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