Developer Documentation
FileSTL.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 "FileSTL.hh"
45 
46 
47  #include <QtWidgets>
48 
51  saveOptions_(0),
52  loadOptions_(0),
53  saveBinary_(0),
54  savePrecisionLabel_(0),
55  savePrecision_(0),
56  loadFaceNormal_(0),
57  saveDefaultButton_(0),
58  loadDefaultButton_(0)
59 
60 {
61 
62 }
63 
64 //-----------------------------------------------------------------------------------------------------
65 
67  emit setSlotDescription("loadObject(QString)",tr("Load Object from stl file."),
68  QString(tr("Filename")).split(","), QString(tr("Filename to load")).split(","));
69  emit setSlotDescription("saveObject(int,QString)",tr("Save Object to an stl file."),
70  QString(tr("objectId,Filename")).split(","), QString(tr("ID of an object to save, Filename")).split(","));
71  emit setSlotDescription("saveObject(int,QString,bool)",tr("Save Object to an stl file with parameters."),
72  QString(tr("objectId,Filename,Binary")).split(","), QString(tr("ID of an object to save, Filename,Save as binary?")).split(","));
73  emit setSlotDescription("saveObject(int,QString,bool,std::streamsize)",tr("Save Object to an stl file with parameters."),
74  QString(tr("objectId,Filename,Binary,Precision")).split(","), QString(tr("ID of an object to save, Filename,Save as binary?, Number of digits (6 is usually the default)")).split(","));
75 }
76 
77 //-----------------------------------------------------------------------------------------------------
78 
80  return QString( tr("Stereolithography files ( *.stl *.stla *.stlb )") );
81 };
82 
83 //-----------------------------------------------------------------------------------------------------
84 
86  return QString( tr("Stereolithography files ( *.stl *.stla *.stlb )") );
87 };
88 
89 //-----------------------------------------------------------------------------------------------------
90 
93  return type;
94 }
95 
96 //-----------------------------------------------------------------------------------------------------
97 
98 int FileSTLPlugin::loadObject(QString _filename) {
99 
100  int id = -1;
101  emit addEmptyObject(DATA_TRIANGLE_MESH, id);
102 
103  TriMeshObject* object(0);
104  if(PluginFunctions::getObject( id, object)) {
105 
106  if (PluginFunctions::objectCount() == 1 )
107  object->target(true);
108 
109  object->setFromFileName(_filename);
110  object->setName(object->filename());
111 
112  std::string filename = std::string( _filename.toUtf8() );
113 
114  object->mesh()->request_face_normals();
115 
116  bool loadNormals( (loadFaceNormal_ && loadFaceNormal_->isChecked()) ||
117  (!loadFaceNormal_ && OpenFlipperSettings().value("FileSTL/Load/FaceNormal", true).toBool())
118  );
119 
120  // load file
122  // load face normals from the stl file if requested
123  if (loadNormals) {
125  }
126 
127  bool ok = OpenMesh::IO::read_mesh( (*object->mesh()) , filename, opt );
128  if (!ok)
129  {
130  std::cerr << "Plugin FileSTL : Read error for stl mesh.\n";
131  emit deleteObject( object->id() );
132  return -1;
133 
134  }
135 
136  // only calculate the face normals if they are not read from the file
137  if (!loadNormals || !opt.face_has_normal())
138  object->mesh()->update_normals();
139  else {
140  if (object->mesh()->has_vertex_normals())
141  object->mesh()->update_vertex_normals();
142  if (object->mesh()->has_halfedge_normals())
143  object->mesh()->update_halfedge_normals();
144  }
145 
146  emit updatedObject(object->id(), UPDATE_ALL);
147 
148  emit openedFile( object->id() );
149 
150  return object->id();
151 
152  } else {
153  emit log(LOGERR,"Error : Could not create new triangle mesh object.");
154  return -1;
155  }
156 };
157 
158 //-----------------------------------------------------------------------------------------------------
159 
160 bool FileSTLPlugin::saveObject(int _id, QString _filename)
161 {
162  BaseObjectData* object;
163  if ( !PluginFunctions::getObject(_id,object) ) {
164  emit log(LOGERR, tr("saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
165  return false;
166  }
167 
168  std::string filename = std::string( _filename.toUtf8() );
169 
170  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
171 
172  object->setFromFileName(_filename);
173  object->setName(object->filename());
174 
175  TriMeshObject* triObj = dynamic_cast<TriMeshObject* >( object );
176 
178 
179  std::streamsize precision = 6;
180  if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0){
181 
182  if (!OpenFlipper::Options::nogui() && saveBinary_->isChecked())
184 
185  if (!saveBinary_->isChecked())
186  precision = savePrecision_->value();
187 
188  }
189 
190  if (OpenMesh::IO::write_mesh(*triObj->mesh(), filename.c_str(), opt, precision) ) {
191  emit log(LOGINFO, tr("Saved object to ") + _filename );
192  return true;
193  } else {
194  emit log(LOGERR, tr("Unable to save ") + _filename );
195  return false;
196  }
197 
198  } else {
199  emit log(LOGERR, tr("Unable to save (object is not a triangle mesh type)"));
200  return false;
201  }
202 }
203 
204 //-----------------------------------------------------------------------------------------------------
205 
206 bool FileSTLPlugin::saveObject(int _id, QString _filename, const bool _binary, const std::streamsize _precision ){
207  BaseObjectData* object;
208  if ( !PluginFunctions::getObject(_id,object) ) {
209  emit log(LOGERR, tr("saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
210  return false;
211  }
212 
213  std::string filename = std::string( _filename.toUtf8() );
214 
215  if ( object->dataType( DATA_TRIANGLE_MESH ) ) {
216 
217  object->setFromFileName(_filename);
218  object->setName(object->filename());
219 
220  TriMeshObject* triObj = dynamic_cast<TriMeshObject* >( object );
221 
223 
224  if (_binary)
226 
227  if (OpenMesh::IO::write_mesh(*triObj->mesh(), filename.c_str(), opt, _precision) ) {
228  emit log(LOGINFO, tr("Saved object to ") + _filename );
229  return true;
230  } else {
231  emit log(LOGERR, tr("Unable to save ") + _filename );
232  return false;
233  }
234 
235  } else {
236  emit log(LOGERR, tr("Unable to save (object is not a triangle mesh type)"));
237  return false;
238  }
239 
240 }
241 
242 //-----------------------------------------------------------------------------------------------------
243 
244 QWidget* FileSTLPlugin::saveOptionsWidget(QString /*_currentFilter*/) {
245 
246  if (saveOptions_ == 0){
247  //generate widget
248  saveOptions_ = new QWidget();
249  QVBoxLayout* layout = new QVBoxLayout();
250  layout->setAlignment(Qt::AlignTop);
251 
252  saveBinary_ = new QCheckBox("Save Binary");
253  layout->addWidget(saveBinary_);
254 
255  savePrecisionLabel_ = new QLabel("Writer Precision");
256  layout->addWidget(savePrecisionLabel_);
257 
258  savePrecision_ = new QSpinBox();
259  savePrecision_->setMinimum(1);
260  savePrecision_->setMaximum(12);
261  savePrecision_->setValue(6);
262  layout->addWidget(savePrecision_);
263 
264  saveDefaultButton_ = new QPushButton("Make Default");
265  layout->addWidget(saveDefaultButton_);
266 
267  saveOptions_->setLayout(layout);
268 
269  saveBinary_->setChecked( OpenFlipperSettings().value( "FileSTL/Save/Binary", false ).toBool() );
270 
271  connect(saveBinary_, SIGNAL(clicked(bool)), savePrecision_, SLOT(setDisabled(bool)));
272  connect(saveDefaultButton_, SIGNAL(clicked()), this, SLOT(slotSaveDefault()));
273 
274  }
275 
276  return saveOptions_;
277 }
278 
279 //-----------------------------------------------------------------------------------------------------
280 
281 QWidget* FileSTLPlugin::loadOptionsWidget(QString /*_currentFilter*/) {
282 
283  if (loadOptions_ == 0){
284  //generate widget
285  loadOptions_ = new QWidget();
286  QVBoxLayout* layout = new QVBoxLayout();
287  layout->setAlignment(Qt::AlignTop);
288 
289  loadFaceNormal_ = new QCheckBox("Load Face Normals");
290  layout->addWidget(loadFaceNormal_);
291 
292  loadFaceNormal_->setChecked( OpenFlipperSettings().value("FileSTL/Load/FaceNormal",true).toBool() );
293 
294  loadDefaultButton_ = new QPushButton("Make Default");
295  layout->addWidget(loadDefaultButton_);
296 
297  loadOptions_->setLayout(layout);
298 
299  connect(loadDefaultButton_, SIGNAL(clicked()), this, SLOT(slotLoadDefault()));
300  }
301 
302  return loadOptions_;
303 }
304 
305 //-----------------------------------------------------------------------------------------------------
306 
308  OpenFlipperSettings().setValue( "FileSTL/Load/FaceNormal", loadFaceNormal_->isChecked() );
309  OpenFlipperSettings().setValue( "Core/File/UseLoadDefaults", true );
310 }
311 
312 //-----------------------------------------------------------------------------------------------------
313 
315  OpenFlipperSettings().setValue( "FileSTL/Save/Binary", saveBinary_->isChecked() );
316 }
317 
318 
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
int id() const
Definition: BaseObject.cc:190
void initializePlugin()
Initialize Plugin.
Definition: FileSTL.cc:66
bool write_mesh(const Mesh &_mesh, const std::string &_filename, Options _opt=Options::Default, std::streamsize _precision=6)
Write a mesh to the file _filename.
Definition: MeshIO.hh:207
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Has (r) / store (w) face normals.
Definition: Options.hh:108
void slotSaveDefault()
Slot called when user wants to save the given Save options as default.
Definition: FileSTL.cc:314
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
int loadObject(QString _filename)
Loads Object as triangle mesh.
Definition: FileSTL.cc:98
MeshT * mesh()
return a pointer to the mesh
QWidget * loadOptionsWidget(QString)
Definition: FileSTL.cc:281
QWidget * saveOptionsWidget(QString)
Definition: FileSTL.cc:244
QString getSaveFilters()
Definition: FileSTL.cc:85
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
void slotLoadDefault()
Slot called when user wants to save the given Load options as default.
Definition: FileSTL.cc:307
QString filename() const
return the filename of the object
Definition: BaseObject.cc:706
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileSTL.cc:91
Set options for reader/writer modules.
Definition: Options.hh:90
Predefined datatypes.
Definition: DataTypes.hh:83
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Set binary mode for r/w.
Definition: Options.hh:100
QString getLoadFilters()
Definition: FileSTL.cc:79
int objectCount()
Get the number of available objects.
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition: MeshIO.hh:112
FileSTLPlugin()
Constructor.
Definition: FileSTL.cc:50