diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp index 91abe79a3d9..9eada718ae9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp @@ -11,11 +11,17 @@ #include #include +#include #include #include +#include +#include #include +#include +#include + using namespace CGAL::Three; class Polyhedron_demo_stl_plugin : public QObject, @@ -116,13 +122,51 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) { return item; } -bool Polyhedron_demo_stl_plugin::canSave(const CGAL::Three::Scene_item*) +bool Polyhedron_demo_stl_plugin::canSave(const CGAL::Three::Scene_item* item) { - return false; + return qobject_cast(item) || + qobject_cast(item); } -bool Polyhedron_demo_stl_plugin::save(const CGAL::Three::Scene_item*, QFileInfo) +bool Polyhedron_demo_stl_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo) { + const Scene_polyhedron_item* poly_item = + qobject_cast(item); + const Scene_surface_mesh_item* sm_item = + qobject_cast(item); + + if(!poly_item && !sm_item) + return false; + + QStringList list; + list << tr("Binary"); + list << tr("Ascii"); + bool ok = false; + QString choice + = QInputDialog::getItem(NULL, tr("Save STL file"), tr("Format"), list, 0, false, &ok); + + if (!ok) + return false; + + std::ofstream out(fileinfo.filePath().toUtf8(), std::ios::out | std::ios::binary); + if ( choice == tr("Binary") ) + CGAL::set_mode(out, CGAL::IO::BINARY); + else + { + CGAL::set_mode(out, CGAL::IO::ASCII); + out.precision (std::numeric_limits::digits10 + 2); + } + + if (sm_item) + { + CGAL::write_STL(*sm_item->face_graph(), out); + return true; + } + if (poly_item) + { + CGAL::write_STL(*poly_item->polyhedron(), out); + return true; + } return false; } diff --git a/Polyhedron_IO/include/CGAL/IO/STL_writer.h b/Polyhedron_IO/include/CGAL/IO/STL_writer.h new file mode 100644 index 00000000000..527ac3beb1f --- /dev/null +++ b/Polyhedron_IO/include/CGAL/IO/STL_writer.h @@ -0,0 +1,100 @@ +// Copyright (c) 2017 GeometryFactory +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// Author(s) : Sebastien Loriot + +#ifndef CGAL_IO_STL_WRITER_H +#define CGAL_IO_STL_WRITER_H + +#include + +#include +#include + +#include +#include +#include + + + +namespace CGAL{ + +template +std::ostream& +write_STL(const TriangleMesh& tm, std::ostream& out) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::reference Point_3_ref; + typedef typename boost::property_traits::value_type Point_3; + typedef typename Kernel_traits::Kernel::Vector_3 Vector_3; + + Vpm vpm = get(boost::vertex_point, tm); + + if (get_mode(out) == IO::BINARY) + { + out << "FileType: Binary "; + const boost::uint32_t N32 = static_cast(faces(tm).size()); + out.write(reinterpret_cast(&N32), sizeof(N32)); + + BOOST_FOREACH(face_descriptor f, faces(tm)) + { + halfedge_descriptor h = halfedge(f, tm); + Point_3_ref p = get(vpm, target(h, tm)); + Point_3_ref q = get(vpm, target(next(h, tm), tm)); + Point_3_ref r = get(vpm, source(h, tm)); + + Vector_3 n = collinear(p,q,r) ? Vector_3(1,0,0): + unit_normal(p,q,r); + + const float coords[12]={ + static_cast(n.x()), static_cast(n.y()), static_cast(n.z()), + static_cast(p.x()), static_cast(p.y()), static_cast(p.z()), + static_cast(q.x()), static_cast(q.y()), static_cast(q.z()), + static_cast(r.x()), static_cast(r.y()), static_cast(r.z()) }; + + for (int i=0; i<12; ++i) + out.write(reinterpret_cast(&coords[i]), sizeof(coords[i])); + out << " "; + } + } + else + { + out << "solid\n"; + BOOST_FOREACH(face_descriptor f, faces(tm)) + { + halfedge_descriptor h = halfedge(f, tm); + Point_3_ref p = get(vpm, target(h, tm)); + Point_3_ref q = get(vpm, target(next(h, tm), tm)); + Point_3_ref r = get(vpm, source(h, tm)); + + Vector_3 n = collinear(p,q,r) ? Vector_3(1,0,0): + unit_normal(p,q,r); + out << "facet normal " << n << "\nouter loop\n"; + out << "vertex " << p << "\n"; + out << "vertex " << q << "\n"; + out << "vertex " << r << "\n"; + out << "endloop\nendfacet\n"; + } + out << "endsolid\n"; + } + return out; +} + +} // end of namespace CGAL + +#endif // CGAL_IO_STL_WRITER_H