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
SubdividerPlugin.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 #include "SubdividerPlugin.hh"
52
53 #include <OpenMesh/Tools/Subdivider/Uniform/LoopT.hh>
54 #include <OpenMesh/Tools/Subdivider/Uniform/Sqrt3T.hh>
55 #include <OpenMesh/Tools/Subdivider/Uniform/Sqrt3InterpolatingSubdividerLabsikGreinerT.hh>
56 #include <OpenMesh/Tools/Subdivider/Uniform/ModifiedButterFlyT.hh>
57 #include <OpenMesh/Tools/Subdivider/Uniform/LongestEdgeT.hh>
58
59 #include <OpenMesh/Tools/Subdivider/Uniform/CatmullClarkT.hh>
60
61 #if QT_VERSION >= 0x050000
62 #else
63 #include <QtGui>
64 #endif
65
66
67 SubdividerPlugin::SubdividerPlugin() :
68 tool_(0),
69 toolIcon_(0)
70 {
71
72 }
73
74
75 void SubdividerPlugin::initializePlugin()
76 {
77 if ( OpenFlipper::Options::gui() ) {
78 tool_ = new subdividerToolbarWidget();
79 QSize size(300, 300);
80 tool_->resize(size);
81
82 connect(tool_->subdivide_uniform_toolButton, SIGNAL( clicked() ), this, SLOT( slotSubdivideUniformButton() ) );
83 connect(tool_->simpleButton, SIGNAL( clicked() ), this, SLOT( slotSimpleSubdivideButton() ) );
84
85
86
87 toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"subdivider.png");
88 emit addToolbox( tr("Subdivider") , tool_, toolIcon_ );
89 }
90 }
91
92 void SubdividerPlugin::pluginsInitialized()
93 {
94 emit setSlotDescription("subdivide(int,QString,int,bool)", "Subdivide a triangular or polygonal mesh. For polygonal meshes use catmullClark, the other algorithms are for triangular meshes.",
95 QString("object_id,algorithm,iterations,update_points").split(","),
96 QString(" id of an object, algorithm to use ( loop | sqrt3 | interpolating_sqrt3 | modifiedButterfly | catmullClark ), number of iterations, update original points").split(","));
97
98 emit setSlotDescription("subdivide(int,QString,int)", "Subdivide a triangular or polygonal mesh. For polygonal meshes use catmullClark, the other algorithms are for triangular meshes. This function will modify the original point locations.",
99 QString("object_id,algorithm,iterations").split(","),
100 QString(" id of an object, algorithm to use ( loop | sqrt3 | interpolating_sqrt3 | modifiedButterfly | catmullClark ), number of iterations").split(","));
101
102 emit setSlotDescription("simpleSubdivide(int,QString,int,double,bool)", "Subdivide a triangular mesh.",
103 QString("object_id,algorithm,iterations,parameter,update_points").split(","),
104 QString(" id of an object, algorithm to use ( longest ), number of iterations, additional parameter(e.g. maximal edge length for longest), update original points").split(","));
105
106 emit setSlotDescription("simpleSubdivide(int,QString,int,double)", "Subdivide a triangular mesh. This function will modify the original point locations.",
107 QString("object_id,algorithm,iterations,parameter").split(","),
108 QString(" id of an object, algorithm to use ( longest ), number of iterations, additional parameter(e.g. maximal edge length for longest)").split(","));
109 }
110
111 //-----------------------------------------------------------------------------
112
113 void SubdividerPlugin::slotSubdivideUniformButton()
114 {
115 std::vector< int > ids;
116 if ( PluginFunctions::getTargetIdentifiers( ids ) )
117 {
118
119 for (unsigned int i = 0; i < ids.size(); ++i)
120 {
121 if(tool_->loop_radioButton->isChecked())
122 {
123 subdivide(ids[i],"loop",tool_->subdivision_steps_spinBox->value(), tool_->updatePoints->isChecked());
124 }
125 else if ( tool_->sqrt3_radioButton->isChecked() )
126 {
127 subdivide(ids[i],"sqrt3",tool_->subdivision_steps_spinBox->value(), tool_->updatePoints->isChecked());
128 }
129 else if ( tool_->LabsikGreiner_radioButton->isChecked() )
130 {
131 subdivide(ids[i],"interpolating_sqrt3",tool_->subdivision_steps_spinBox->value(), tool_->updatePoints->isChecked());
132 }
133 else if ( tool_->modifiedButterfly_radioButton->isChecked() )
134 {
135 subdivide(ids[i],"modifiedButterfly",tool_->subdivision_steps_spinBox->value(), tool_->updatePoints->isChecked());
136 }
137 else if ( tool_->catmullClark_radioButton->isChecked() )
138 {
139 subdivide(ids[i],"catmullClark",tool_->subdivision_steps_spinBox->value(), tool_->updatePoints->isChecked());
140 }
141
142 // Create backup
143 emit createBackup(ids[i], "Subdivider", UPDATE_TOPOLOGY);
144 }
145
146 }
147 emit updateView();
148 }
149
150 //-----------------------------------------------------------------------------
151
152 void SubdividerPlugin::slotSimpleSubdivideButton()
153 {
154 std::vector< int > ids;
155 if ( PluginFunctions::getTargetIdentifiers( ids ) )
156 {
157 for (unsigned int i = 0; i < ids.size(); ++i)
158 {
159 if(tool_->longestEdgeSplit->isChecked())
160 {
161 simpleSubdivide(ids[i],"longest",tool_->subdivision_steps_spinBox->value(),
162 tool_->maximalEdgeLength->value(), tool_->updatePoints->isChecked());
163
164 // Create backup
165 emit createBackup(ids[i], "Subdivider", UPDATE_TOPOLOGY);
166 }
167 }
168 }
169 emit updateView();
170 }
171
172 //-----------------------------------------------------------------------------
173
174 void SubdividerPlugin::simpleSubdivide(int _objectId, QString _algorithm , int _steps, double _parameter, bool _update_points) {
175
176 BaseObjectData* object;
177 if (!test_trimesh_object(_objectId, object)) {
178 emit log(LOGERR,"The simple subdivision algorithms only work on triangular meshes.");
179 return;
180 }
181
182 TriMesh* mesh = PluginFunctions::triMesh(object);
183
184 if (_algorithm.contains("longest", Qt::CaseInsensitive)) {
185 OpenMesh::Subdivider::Uniform::LongestEdgeT<TriMesh, double> subdivider;
186
187 subdivider.attach(*mesh);
188 subdivider.set_max_edge_length(_parameter);
189 subdivider(*mesh, _steps, _update_points);
190 subdivider.detach();
191 } else {
192 emit log(LOGERR,"Unsupported algorithm in simpleSubdivide: " + _algorithm);
193 return;
194 }
195
196 mesh->garbage_collection();
197
198 mesh->update_face_normals();
199 mesh->update_vertex_normals();
200
201 // Geometry and topology changed!
202 emit updatedObject(object->id(), UPDATE_TOPOLOGY);
203 }
204
205 //-----------------------------------------------------------------------------
206
207 void SubdividerPlugin::subdivide(int _objectId, QString _algorithm , int _steps, bool _update_points) {
208
209 BaseObjectData* object;
210 PluginFunctions::getObject(_objectId,object);
211
212 if(!object) {
213 emit log(LOGERR,"Unable to get Object in SubdividerPlugin::subdivide");
214 return;
215 }
216
217
218 // Catmull clark:
219 if ( _algorithm.contains("catmullClark",Qt::CaseInsensitive) ) {
220
221 PolyMesh* polyMesh = PluginFunctions::polyMesh(object);
222 if ( ! polyMesh ) {
223 emit log(LOGERR,"Error: Catmull Clark only works on Poly Meshes!");
224 return;
225 }
226
227 OpenMesh::Subdivider::Uniform::CatmullClarkT<PolyMesh> subdivider;
228
229 subdivider.attach(*polyMesh);
230 subdivider(_steps,_update_points);
231 subdivider.detach();
232
233 polyMesh->garbage_collection();
234
235 polyMesh->update_face_normals();
236 polyMesh->update_vertex_normals();
237
238 // Geometry and topology changed!
239 emit updatedObject(object->id(), UPDATE_TOPOLOGY);
240
241 } else {
242
243 //=======================================================
244 // All other algorithms work on triangular meshes here
245 //=======================================================
246
247 TriMesh* mesh = PluginFunctions::triMesh(object);
248
249 if ( ! mesh ) {
250 emit log(LOGERR,"Error: Unable to get trisngular mesh in subdivider!");
251 return;
252 }
253
254 if(_algorithm.contains("loop",Qt::CaseInsensitive))
255 {
256 OpenMesh::Subdivider::Uniform::LoopT<TriMesh,double> subdivider;
257
258 subdivider.attach(*mesh);
259 subdivider(*mesh,_steps,_update_points);
260 subdivider.detach();
261 }
262 else if ( _algorithm.contains("sqrt3",Qt::CaseInsensitive) )
263 {
264 OpenMesh::Subdivider::Uniform::Sqrt3T<TriMesh,double> subdivider;
265
266 subdivider.attach(*mesh);
267 subdivider(_steps,_update_points);
268 subdivider.detach();
269 }
270 else if ( _algorithm.contains("interpolating_sqrt(3)",Qt::CaseInsensitive) )
271 {
272 OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT<TriMesh,double> subdivider;
273
274 subdivider.attach(*mesh);
275 subdivider(_steps,_update_points);
276 subdivider.detach();
277 }
278 else if ( _algorithm.contains("modifiedButterfly",Qt::CaseInsensitive) )
279 {
280 OpenMesh::Subdivider::Uniform::ModifiedButterflyT<TriMesh,double> subdivider;
281
282 subdivider.attach(*mesh);
283 subdivider(_steps,_update_points);
284 subdivider.detach();
285 } else {
286 emit log(LOGERR,"Unsupported or unknown subdivider for triangular meshes: " + _algorithm);
287 }
288
289 mesh->garbage_collection();
290
291 mesh->update_face_normals();
292 mesh->update_vertex_normals();
293
294 // Geometry and topology changed!
295 emit updatedObject(object->id(), UPDATE_TOPOLOGY);
296
297 }
298
299
300 }
301
302
303 //-----------------------------------------------------------------------------
304
305
306 bool SubdividerPlugin::test_trimesh_object(int _identifier, BaseObjectData*& _object)
307 {
308 if ( _identifier == -1)
309 return false;
310
311 if (! PluginFunctions::getObject(_identifier,_object) )
312 return false;
313
314 if (!_object->dataType(DATA_TRIANGLE_MESH) )
315 return false;
316 return true;
317 }
318
319 #if QT_VERSION < 0x050000
320 Q_EXPORT_PLUGIN2( subdividerplugin , SubdividerPlugin );
321 #endif
322
323
OpenMesh::Subdivider::Uniform::Sqrt3T
Definition: Sqrt3T.hh:103
SubdividerPlugin::tool_
subdividerToolbarWidget * tool_
Widget for Toolbox.
Definition: SubdividerPlugin.hh:163
OpenMesh::PolyMesh_ArrayKernelT
Definition: PolyMesh_ArrayKernelT.hh:98
Sqrt3InterpolatingSubdividerLabsikGreinerT.hh
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
LongestEdgeT.hh
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
SubdividerPlugin
Definition: SubdividerPlugin.hh:70
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:134
OpenMesh::Subdivider::Uniform::ModifiedButterflyT
Definition: ModifiedButterFlyT.hh:99
OpenMesh::Subdivider::Uniform::SubdividerT::attach
bool attach(MeshType &_m)
Definition: SubdividerT.hh:138
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
OpenMesh::Subdivider::Uniform::LoopT
Definition: LoopT.hh:96
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:140
OpenMesh::Subdivider::Uniform::CatmullClarkT
Definition: CatmullClarkT.hh:92
ModifiedButterFlyT.hh
SubdividerPlugin::simpleSubdivide
void simpleSubdivide(int _objectId, QString _algorithm, int _steps, double _parameter, bool _update_points=true)
Scripting slot for the simple subdivision algorithms.
Definition: SubdividerPlugin.cc:174
OpenMesh::PolyMeshT::update_vertex_normals
void update_vertex_normals()
Update normal vectors for all vertices.
Definition: PolyMeshT.cc:448
OpenMesh::PolyMeshT::update_face_normals
void update_face_normals()
Update normal vectors for all faces.
Definition: PolyMeshT.cc:259
UPDATE_TOPOLOGY
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
subdividerToolbarWidget
Definition: subdividerToolbar.hh:59
PluginFunctions::getTargetIdentifiers
bool getTargetIdentifiers(std::vector< int > &_identifiers)
Get the identifiers of all objects marked as a target object.
Definition: PluginFunctions.cc:284
OpenMesh::Subdivider::Uniform::InterpolatingSqrt3LGT
Definition: Sqrt3InterpolatingSubdividerLabsikGreinerT.hh:113
OpenMesh::Subdivider::Uniform::SubdividerT::detach
void detach(void)
Definition: SubdividerT.hh:161
LoopT.hh
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
Sqrt3T.hh
OpenMesh::Subdivider::Uniform::LongestEdgeT
Definition: LongestEdgeT.hh:105
SubdividerPlugin::subdivide
void subdivide(int _objectId, QString _algorithm, int _steps, bool _update_points=true)
Scripting slot for subdivision.
Definition: SubdividerPlugin.cc:207
BaseObject::id
int id() const
Definition: BaseObject.cc:201
CatmullClarkT.hh