Developer Documentation
Loading...
Searching...
No Matches
IsotropicRemesherPlugin.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#include "IsotropicRemesherPlugin.hh"
45#include "IsotropicRemesherT.hh"
46
47IsotropicRemesherPlugin::IsotropicRemesherPlugin() :
48tool_(nullptr),
49toolIcon_(nullptr),
50edgeLength_(0),
51thread_(nullptr)
52{
53}
54
55IsotropicRemesherPlugin::~IsotropicRemesherPlugin() {
56 delete toolIcon_;
57}
58
61 if ( OpenFlipper::Options::gui() ) {
62 tool_ = new IsotropicRemesherToolBox();
63
64 QSize size(300, 300);
65 tool_->resize(size);
66
67 connect(tool_->remeshButton, SIGNAL(clicked()), this, SLOT(slotRemeshButtonClicked()) );
68
69 connect(tool_->minEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMinLength()) );
70 connect(tool_->maxEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMaxLength()) );
71 connect(tool_->meanEdgeLength, SIGNAL(clicked()), this, SLOT(slotSetMeanLength()) );
72
73 toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"remesher.png");
74 emit addToolbox( tr("Isotropic Remesher") , tool_, toolIcon_ );
75 }
76}
77
78void IsotropicRemesherPlugin::slotRemeshButtonClicked() {
79 edgeLength_ = tool_->targetEdgeLength->value();
80
81 if ( thread_ == 0){
82 thread_ = new OpenFlipperThread(name() + "IsotropicRemesh"); // Create your thread containing a unique id \n
83 connect(thread_,SIGNAL( finished(QString)), this,SIGNAL(finishJob(QString))); // connect your threads finish info to the global one ( you can do the same for a local one ) \n
84 connect(thread_,SIGNAL( function() ), this,SLOT(slotRemesh()),Qt::DirectConnection); // You can directly give a slot of your app that gets called \n
85 connect(this,SIGNAL( finishJob(QString)), this, SLOT(threadFinished(QString)), Qt::QueuedConnection);
86 }
87
88 emit startJob( name() + "IsotropicRemesh", "Isotropic remeshing" , 0 , 100 , true); // As long as meshes cannot be locked, this thread has to be blocking. Otherwise, during operation the mesh could be deleted. We don't want that!
89
90 thread_->start(); // start thread
91 thread_->startProcessing(); // start processing
92}
93
94
95void IsotropicRemesherPlugin::slotRemesh(){
96
97 //read one target objects
99
100 //check dataType
101 if ( o_it->dataType(DATA_TRIANGLE_MESH) ) {
102 TriMesh* mesh = PluginFunctions::triMesh(o_it);
103
104 IsoRemesherProgressEmitter prgEmt(name() + "IsotropicRemesh");
105 connect (&prgEmt, SIGNAL(changeDescription(QString,QString)), this, SIGNAL(setJobDescription(QString,QString)) );
106 connect (&prgEmt, SIGNAL(signalJobState(QString,int)), this, SIGNAL(setJobState(QString,int)) );
107 IsotropicRemesher< TriMesh > remesher(&prgEmt);
108
109 remesher.remesh(*mesh, edgeLength_);
110
111 mesh->update_normals();
112
113 }else{
114 emit log("Remeshing currently only implemented for triangle Meshes");
115 }
116 }
117}
118
119void IsotropicRemesherPlugin::threadFinished(QString /*_jobId*/) {
120
121 std::cerr << "threadFinished() called" << std::endl;
122
124
125 emit updatedObject( o_it->id(), UPDATE_ALL );
126
127 emit createBackup(o_it->id(),"Isotropic Remeshing");
128
129 emit updateView();
130
131 }
132}
133
134void IsotropicRemesherPlugin::slotSetMinLength()
135{
136 double current = 0.0;
137 bool first = true;
138
139 bool ok;
140 emit functionExists( "infomeshobject" , "minEdgeLength(int)", ok ) ;
141 if (!ok)
142 return;
143
145
146 if (first)
147 {
148 current = RPC::callFunctionValue<double>("infomeshobject" , "minEdgeLength",o_it->id() );
149 first = false;
150 }
151 else
152 current = qMin (current, RPC::callFunctionValue<double>("infomeshobject" , "minEdgeLength",o_it->id() ));
153
154 }
155
156 if (!first)
157 tool_->targetEdgeLength->setValue (current);
158}
159
160void IsotropicRemesherPlugin::slotSetMaxLength()
161{
162 double current = 0.0;
163 bool first = true;
164
165 bool ok;
166 emit functionExists( "infomeshobject" , "maxEdgeLength(int)", ok ) ;
167 if (!ok)
168 return;
169
171
172 if (first)
173 {
174 current = RPC::callFunctionValue<double>("infomeshobject" , "maxEdgeLength",o_it->id() );
175 first = false;
176 }
177 else
178 current = qMax (current, RPC::callFunctionValue<double>("infomeshobject" , "maxEdgeLength",o_it->id() ));
179
180 }
181
182 if (!first)
183 tool_->targetEdgeLength->setValue (current);
184}
185
186void IsotropicRemesherPlugin::slotSetMeanLength()
187{
188 double current = 0.0;
189 int div = 0;
190
191 bool ok;
192 emit functionExists( "infomeshobject" , "edgeCount(int)", ok ) ;
193 if (!ok)
194 return;
195
197 current += RPC::callFunctionValue<int> ("infomeshobject" , "edgeCount",o_it->id()) *
198 RPC::callFunctionValue<double>("infomeshobject" , "meanEdgeLength",o_it->id() );
199 div += RPC::callFunctionValue<int> ("infomeshobject" , "edgeCount",o_it->id() );
200 }
201
202 if (div > 0)
203 tool_->targetEdgeLength->setValue (current / div);
204}
205
206
209
210 emit setSlotDescription("isotropicRemesh(int,double)", "Isotropic Remeshing",
211 QString("object_id,targetEdgeLength").split(","),
212 QString("id of an object, target edge length").split(","));
213}
214
215
216void IsotropicRemesherPlugin::isotropicRemesh(int _objectID, double _targetEdgeLength ){
217 BaseObjectData* object = 0;
218
219
220 if ( PluginFunctions::getObject(_objectID, object) ){
221
222 //check dataType
223 if ( object->dataType(DATA_TRIANGLE_MESH)) {
224
225 TriMesh* mesh = PluginFunctions::triMesh(object);
226
228
229 remesher.remesh(*mesh, _targetEdgeLength);
230
231 mesh->update_normals();
232
233 emit updatedObject( object->id(), UPDATE_ALL );
234
235 emit scriptInfo("isotropicRemesh(" + QString::number(_objectID) + ", " + QString::number(_targetEdgeLength) + ")");
236
237 emit updateView();
238
239 return;
240
241 }else{
242 emit log("Remeshing currently only implemented for triangle Meshes");
243 return;
244 }
245 }else{
246 emit log("Unable to get object");
247 }
248}
249
250
251
252
#define DATA_TRIANGLE_MESH
bool dataType(DataType _type) const
int id() const
Predefined datatypes.
Definition DataTypes.hh:83
QString name()
Return a name for the plugin.
void initializePlugin()
init the Toolbox
void pluginsInitialized()
Initialize the plugin.
void remesh(MeshT &_mesh, const double _targetEdgeLength)
do the remeshing
Thread handling class for OpenFlipper.
void startProcessing()
start processing
void update_normals()
Compute normals for all primitives.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
const QStringList TARGET_OBJECTS("target")
Iterable object range.
ObjectRange objects(IteratorRestriction _restriction, DataType _dataType)
Iterable object range.