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
50 FileSTLPlugin::FileSTLPlugin() :
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
66 void FileSTLPlugin::initializePlugin() {
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
79 QString FileSTLPlugin::getLoadFilters() {
80 return QString( tr("Stereolithography files ( *.stl *.stla *.stlb )") );
81 };
82
83 //-----------------------------------------------------------------------------------------------------
84
85 QString FileSTLPlugin::getSaveFilters() {
86 return QString( tr("Stereolithography files ( *.stl *.stla *.stlb )") );
87 };
88
89 //-----------------------------------------------------------------------------------------------------
90
91 DataType FileSTLPlugin::supportedType() {
92 DataType type = DATA_TRIANGLE_MESH;
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
121 OpenMesh::IO::Options opt;
122 // load face normals from the stl file if requested
123 if (loadNormals) {
124 opt += OpenMesh::IO::Options::FaceNormal;
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
177 OpenMesh::IO::Options opt = OpenMesh::IO::Options::Default;
178
179 std::streamsize precision = 6;
180 if ( !OpenFlipper::Options::savingSettings() && saveOptions_ != 0){
181
182 if (!OpenFlipper::Options::nogui() && saveBinary_->isChecked())
183 opt += OpenMesh::IO::Options::Binary;
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
222 OpenMesh::IO::Options opt = OpenMesh::IO::Options::Default;
223
224 if (_binary)
225 opt += OpenMesh::IO::Options::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
307 void FileSTLPlugin::slotLoadDefault() {
308 OpenFlipperSettings().setValue( "FileSTL/Load/FaceNormal", loadFaceNormal_->isChecked() );
309 OpenFlipperSettings().setValue( "Core/File/UseLoadDefaults", true );
310 }
311
312 //-----------------------------------------------------------------------------------------------------
313
314 void FileSTLPlugin::slotSaveDefault() {
315 OpenFlipperSettings().setValue( "FileSTL/Save/Binary", saveBinary_->isChecked() );
316 }
317
318
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:1038
LOGINFO
Definition: LoggingInterface.hh:94
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
BaseObject::id
int id() const
Definition: BaseObject.cc:190
FileSTLPlugin::initializePlugin
void initializePlugin()
Initialize Plugin.
Definition: FileSTL.cc:66
OpenMesh::IO::write_mesh
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
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:61
OpenMesh::IO::Options::FaceNormal
Has (r) / store (w) face normals.
Definition: Options.hh:108
FileSTLPlugin::slotSaveDefault
void slotSaveDefault()
Slot called when user wants to save the given Save options as default.
Definition: FileSTL.cc:314
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
FileSTLPlugin::loadObject
int loadObject(QString _filename)
Loads Object as triangle mesh.
Definition: FileSTL.cc:98
MeshObject::mesh
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT_impl.hh:350
LOGERR
Definition: LoggingInterface.hh:96
OpenMesh::IO::Options::Default
No options.
Definition: Options.hh:99
FileSTLPlugin::loadOptionsWidget
QWidget * loadOptionsWidget(QString)
Definition: FileSTL.cc:281
FileSTLPlugin::saveOptionsWidget
QWidget * saveOptionsWidget(QString)
Definition: FileSTL.cc:244
FileSTLPlugin::getSaveFilters
QString getSaveFilters()
Definition: FileSTL.cc:85
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:294
TriMeshObject
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
FileSTLPlugin::slotLoadDefault
void slotLoadDefault()
Slot called when user wants to save the given Load options as default.
Definition: FileSTL.cc:307
BaseObject::filename
QString filename() const
return the filename of the object
Definition: BaseObject.cc:706
FileSTLPlugin::supportedType
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileSTL.cc:91
OpenMesh::IO::Options
Set options for reader/writer modules.
Definition: Options.hh:90
DataType
Predefined datatypes.
Definition: DataTypes.hh:83
OpenFlipperQSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: OpenFlipperQSettings.cc:46
OpenMesh::IO::Options::Binary
Set binary mode for r/w.
Definition: Options.hh:100
FileSTLPlugin::getLoadFilters
QString getLoadFilters()
Definition: FileSTL.cc:79
PluginFunctions::objectCount
int objectCount()
Get the number of available objects.
Definition: PluginFunctions.cc:1000
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
OpenMesh::IO::read_mesh
bool read_mesh(Mesh &_mesh, const std::string &_filename)
Read a mesh from file _filename.
Definition: MeshIO.hh:112
BaseObjectData
Definition: BaseObjectData.hh:102
FileSTLPlugin::FileSTLPlugin
FileSTLPlugin()
Constructor.
Definition: FileSTL.cc:50