Merge pull request #3919 from maxGimeno/Add_3mf_wrapper-GF

Stream_support: Add a 3mf wrapper
This commit is contained in:
Laurent Rineau 2019-06-20 14:21:11 +02:00
commit 33e7de45e9
39 changed files with 2612 additions and 470 deletions

View File

@ -299,6 +299,16 @@ public Q_SLOTS:
zClippingCoef_ = coef;
projectionMatrixIsUpToDate_ = false;
}
/*! Sets the zNear value in orthographic mode. */
void setOrthoZNear(qreal z)
{
m_zMin = z;
}
/*! Returns the zNear value in orthographic mode*/
qreal orthoZNear()
{
return m_zMin;
}
//@}
/*! @name Scene radius and center */
@ -463,6 +473,7 @@ private:
mutable bool modelViewMatrixIsUpToDate_;
mutable GLdouble projectionMatrix_[16]; // Buffered projection matrix.
mutable bool projectionMatrixIsUpToDate_;
qreal m_zMin; //USed for near plane in orthographic projection.
// S t e r e o p a r a m e t e r s
qreal IODistance_; // inter-ocular distance, in meters

View File

@ -46,6 +46,7 @@ CGAL_INLINE_FUNCTION
Camera::Camera(QObject *parent)
: frame_(nullptr), fieldOfView_(CGAL_PI / 4.0), modelViewMatrixIsUpToDate_(false),
projectionMatrixIsUpToDate_(false) {
m_zMin = 0;
setParent(parent);
// #CONNECTION# Camera copy constructor
interpolationKfi_ = new KeyFrameInterpolator;
@ -228,7 +229,7 @@ qreal Camera::zNear() const {
z = zMin;
break;
case Camera::ORTHOGRAPHIC:
z = 0.0;
z = m_zMin;
break;
}
return z;

View File

@ -41,7 +41,7 @@
#include <QTime>
#include <QWidgetAction>
#include <QJsonArray>
#include <QSequentialIterable>
#ifdef QT_SCRIPT_LIB
# include <QScriptValue>
# ifdef QT_SCRIPTTOOLS_LIB
@ -790,6 +790,7 @@ bool MainWindow::initIOPlugin(QObject* obj)
CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin =
qobject_cast<CGAL::Three::Polyhedron_demo_io_plugin_interface*>(obj);
if(plugin) {
plugin->init();
io_plugins << plugin;
return true;
}
@ -999,20 +1000,29 @@ void MainWindow::reloadItem() {
CGAL::Three::Polyhedron_demo_io_plugin_interface* fileloader = findLoader(loader_name);
QFileInfo fileinfo(filename);
CGAL::Three::Scene_item* new_item = loadItem(fileinfo, fileloader);
if(!new_item)
bool ok;
QList<Scene_item*> new_items = loadItem(fileinfo, fileloader, ok, false);
if(!ok)
return;
new_item->setName(item->name());
new_item->setColor(item->color());
new_item->setRenderingMode(item->renderingMode());
new_item->setVisible(item->visible());
QVariant varian = item->property("load_mates");
QSequentialIterable iterable = varian.value<QSequentialIterable>();
// Can use foreach:
int mate_id = 0;
Q_FOREACH(const QVariant &v, iterable)
{
Scene_item* mate = v.value<Scene_item*>();
Scene_item* new_item = new_items[mate_id];
new_item->setName(mate->name());
new_item->setColor(mate->color());
new_item->setRenderingMode(mate->renderingMode());
new_item->setVisible(mate->visible());
Scene_item_with_properties *property_item = dynamic_cast<Scene_item_with_properties*>(new_item);
scene->replaceItem(scene->item_id(item), new_item, true);
scene->replaceItem(scene->item_id(mate), new_item, true);
if(property_item)
property_item->copyProperties(item);
property_item->copyProperties(mate);
new_item->invalidateOpenGLBuffers();
item->deleteLater();
mate->deleteLater();
}
}
}
@ -1105,11 +1115,11 @@ void MainWindow::open(QString filename)
{
// collect all io_plugins and offer them to load if the file extension match one name filter
// also collect all available plugin in case of a no extension match
Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* io_plugin, io_plugins) {
if ( !io_plugin->canLoad() ) continue;
all_items << io_plugin->name();
for(CGAL::Three::Polyhedron_demo_io_plugin_interface* io_plugin : io_plugins) {
if ( file_matches_filter(io_plugin->loadNameFilters(), filename.toLower()) )
{
if ( !io_plugin->canLoad(fileinfo) ) continue;
all_items << io_plugin->name();
if(io_plugin->isDefaultLoader(fileinfo.completeSuffix()))
selected_items.prepend(io_plugin->name());
else
@ -1149,71 +1159,69 @@ void MainWindow::open(QString filename)
settings.setValue("OFF open directory",
fileinfo.absoluteDir().absolutePath());
CGAL::Three::Scene_item* scene_item = loadItem(fileinfo, findLoader(load_pair.first));
loadItem(fileinfo, findLoader(load_pair.first), ok);
if(!scene_item)
if(!ok)
return;
this->addToRecentFiles(fileinfo.absoluteFilePath());
selectSceneItem(scene->addItem(scene_item));
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(scene_item);
if(group)
scene->redraw_model();
updateViewersBboxes(true);
}
bool MainWindow::open(QString filename, QString loader_name) {
QFileInfo fileinfo(filename);
boost::optional<CGAL::Three::Scene_item*> item_opt;
CGAL::Three::Scene_item* item = 0;
boost::optional<bool> item_opt;
try {
item_opt = wrap_a_call_to_cpp
([this, fileinfo, loader_name]()
{
return loadItem(fileinfo, findLoader(loader_name));
bool ok;
loadItem(fileinfo, findLoader(loader_name), ok);
return ok;
},
this, __FILE__, __LINE__
);
if(!item_opt) return false;
else item = *item_opt;
}
catch(std::logic_error& e) {
std::cerr << e.what() << std::endl;
return false;
}
selectSceneItem(scene->addItem(item));
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item);
if(group)
scene->redraw_model();
return true;
}
CGAL::Three::Scene_item* MainWindow::loadItem(QFileInfo fileinfo, CGAL::Three::Polyhedron_demo_io_plugin_interface* loader) {
CGAL::Three::Scene_item* item = NULL;
QList<Scene_item*> MainWindow::loadItem(QFileInfo fileinfo,
CGAL::Three::Polyhedron_demo_io_plugin_interface* loader,
bool &ok,
bool add_to_scene) {
if(!fileinfo.isFile() || !fileinfo.isReadable()) {
QMessageBox::warning(this, tr("Error"),
QString("File %1 is not a readable file.")
.arg(fileinfo.absoluteFilePath()));
}
QApplication::setOverrideCursor(Qt::WaitCursor);
item = loader->load(fileinfo);
QCursor tmp_cursor(Qt::WaitCursor);
CGAL::Three::Three::CursorScopeGuard guard(tmp_cursor);
QList<Scene_item*> result = loader->load(fileinfo, ok, add_to_scene);
if(result.empty() || !ok)
{
QApplication::restoreOverrideCursor();
if(!item) {
QMessageBox::warning(this, tr("Error"),
QString("Could not load item from file %1 using plugin %2")
.arg(fileinfo.absoluteFilePath()).arg(loader->name()));
return 0;
return QList<Scene_item*>();
}
selectSceneItem(scene->item_id(result.back()));
for(Scene_item* item : result)
{
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item);
if(group)
scene->redraw_model();
item->setProperty("source filename", fileinfo.absoluteFilePath());
item->setProperty("loader_name", loader->name());
return item;
item->setProperty("load_mates",QVariant::fromValue(result));
}
return result;
}
@ -1832,7 +1840,7 @@ void MainWindow::on_actionLoad_triggered()
typedef QMap<QString, CGAL::Three::Polyhedron_demo_io_plugin_interface*> FilterPluginMap;
FilterPluginMap filterPluginMap;
Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin, io_plugins) {
for(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin : io_plugins) {
QStringList split_filters = plugin->loadNameFilters().split(";;");
Q_FOREACH(const QString& filter, split_filters) {
FilterPluginMap::iterator it = filterPluginMap.find(filter);
@ -1882,35 +1890,50 @@ void MainWindow::on_actionLoad_triggered()
CGAL::Three::Scene_item* item = NULL;
if(selectedPlugin) {
QFileInfo info(filename);
item = loadItem(info, selectedPlugin);
item->setColor(colors_[++nb_item]);
Scene::Item_id index = scene->addItem(item);
selectSceneItem(index);
bool ok;
QList<Scene_item*> result = loadItem(info, selectedPlugin, ok);
if(!ok)
continue;
for(Scene_item* item : result)
{
if(!item->property("already_colored").toBool())
{
++nb_item;
item->setColor(colors_[nb_item]);
}
selectSceneItem(scene->item_id(item));
CGAL::Three::Scene_group_item* group =
qobject_cast<CGAL::Three::Scene_group_item*>(item);
if(group)
scene->redraw_model();
}
this->addToRecentFiles(filename);
} else {
int scene_size = scene->numberOfEntries();
open(filename);
if(scene->numberOfEntries() != scene_size)
scene->item(scene->numberOfEntries()-1)->setColor(colors_[++nb_item]);
item = scene->item(scene->numberOfEntries()-1);
if(scene->numberOfEntries() != scene_size
&& !item->property("already_colored").toBool())
item->setColor(colors_[++nb_item]);
}
}
}
void MainWindow::on_actionSaveAs_triggered()
{
Scene_item* item = NULL;
Q_FOREACH(Scene::Item_id id, scene->selectionIndices())
QList<Scene_item*> to_save;
for(Scene::Item_id id : scene->selectionIndices())
{
item = scene->item(id);
Scene_item* item = scene->item(id);
to_save.append(item);
}
while(!to_save.empty())
{
Scene_item* item = to_save.front();
QVector<CGAL::Three::Polyhedron_demo_io_plugin_interface*> canSavePlugins;
QStringList filters;
QString sf;
Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin, io_plugins) {
for(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin : io_plugins) {
if(plugin->canSave(item)) {
canSavePlugins << plugin;
filters += plugin->saveNameFilters();
@ -2017,18 +2040,18 @@ void MainWindow::on_actionSaveAs_triggered()
}
for(auto v : CGAL::QGLViewer::QGLViewerPool())
v->update();
save(filename, item);
save(filename, to_save);
}
}
void MainWindow::save(QString filename, CGAL::Three::Scene_item* item) {
void MainWindow::save(QString filename, QList<CGAL::Three::Scene_item*>& to_save) {
QFileInfo fileinfo(filename);
bool saved = false;
Q_FOREACH(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin, io_plugins) {
if( plugin->canSave(item) &&
for(CGAL::Three::Polyhedron_demo_io_plugin_interface* plugin : io_plugins) {
if( plugin->canSave(to_save.front()) &&
file_matches_filter(plugin->saveNameFilters(),filename.toLower()) )
{
if(plugin->save(item, fileinfo))
if(plugin->save(fileinfo, to_save))
{
saved = true;
break;
@ -2039,7 +2062,7 @@ void MainWindow::save(QString filename, CGAL::Three::Scene_item* item) {
QMessageBox::warning(this,
tr("Cannot save"),
tr("The selected object %1 was not saved. (Maybe a wrong extension ?)")
.arg(item->name()));
.arg(to_save.front()->name()));
}
void MainWindow::on_actionSaveSnapshot_triggered()
@ -3132,14 +3155,16 @@ void MainWindow::on_action_Save_triggered()
if(QMessageBox::question(this, "Save", "Are you sure you want to override these files ?")
== QMessageBox::No)
return;
Scene_item* item = nullptr;
Q_FOREACH(Scene::Item_id id, scene->selectionIndices())
QList<Scene_item*> to_save;
for(Scene::Item_id id : scene->selectionIndices())
{
item = scene->item(id);
Scene_item* item = scene->item(id);
if(!item->property("source filename").toString().isEmpty())
{
QString filename = item->property("source filename").toString();
save(filename, item);
to_save.append(item);
save(filename, to_save);
}
}
}

View File

@ -87,11 +87,14 @@ public:
@returns the IO plugin associated with `loader_name`*/
CGAL::Three::Polyhedron_demo_io_plugin_interface* findLoader(const QString& loader_name) const;
/*! \brief Loads an item with a given loader.
/*! \brief Loads on or more item with a given loader.
*
* throws `std::logic_error` if loading does not succeed or
* `std::invalid_argument` if `fileinfo` specifies an invalid file*/
CGAL::Three::Scene_item* loadItem(QFileInfo fileinfo, CGAL::Three::Polyhedron_demo_io_plugin_interface*);
QList<CGAL::Three::Scene_item *> loadItem(QFileInfo fileinfo,
CGAL::Three::Polyhedron_demo_io_plugin_interface*,
bool& ok,
bool add_to_scene=true);
void computeViewerBBox(CGAL::qglviewer::Vec &min, CGAL::qglviewer::Vec &max);
void updateViewerBbox(Viewer* vi, bool recenter, CGAL::qglviewer::Vec min,
CGAL::qglviewer::Vec max);
@ -346,7 +349,7 @@ protected Q_SLOTS:
//!Opens a dialog to save selected item if able.
void on_actionSaveAs_triggered();
//!Calls the function save of the current plugin if able.
void save(QString filename, CGAL::Three::Scene_item* item);
void save(QString filename, QList<CGAL::Three::Scene_item*>& to_save);
//!Calls the function saveSnapShot of the viewer.
void on_actionSaveSnapshot_triggered();
//!Opens a Dialog to choose a color and make it the background color.

View File

@ -791,14 +791,15 @@ class Polyhedron_demo_cut_plugin :
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90")
public:
Polyhedron_demo_cut_plugin() : QObject(), edges_item(0) {
}
virtual ~Polyhedron_demo_cut_plugin();
~Polyhedron_demo_cut_plugin();
bool applicable(QAction*) const {
bool applicable(QAction*) const Q_DECL_OVERRIDE{
// returns true if one surface_mesh is in the entries
for (int i=0; i< scene->numberOfEntries(); ++i)
{
@ -808,29 +809,32 @@ public:
return false;
}
virtual QString name() const
QString name() const Q_DECL_OVERRIDE
{
return "cut-plugin";
}
virtual QString nameFilters() const
QString nameFilters() const Q_DECL_OVERRIDE
{
return "Segment soup file (*.polylines.txt *.cgal)";
}
bool canLoad() const
bool canLoad(QFileInfo) const Q_DECL_OVERRIDE
{
return false;
}
virtual CGAL::Three::Scene_item* load(QFileInfo /* fileinfo */)
QList<Scene_item*> load(QFileInfo , bool& ok, bool add_to_scene=true) Q_DECL_OVERRIDE
{
return 0;
Q_UNUSED(add_to_scene);
ok = false;
return QList<Scene_item*>();
}
virtual bool canSave(const CGAL::Three::Scene_item* item)
bool canSave(const CGAL::Three::Scene_item* item) Q_DECL_OVERRIDE
{
// This plugin supports edges items
bool b = qobject_cast<const Scene_edges_item*>(item) != 0;
@ -838,8 +842,10 @@ public:
}
virtual bool save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
{ // This plugin supports edges items
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items) Q_DECL_OVERRIDE
{
Scene_item* item = items.front();
// This plugin supports edges items
const Scene_edges_item* edges_item =
qobject_cast<const Scene_edges_item*>(item);
@ -848,15 +854,18 @@ public:
}
std::ofstream out(fileinfo.filePath().toUtf8());
return (out && edges_item->save(out));
bool ok = (out && edges_item->save(out));
if(ok)
items.pop_front();
return ok;
}
using Polyhedron_demo_io_plugin_interface::init;
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface,
Messages_interface* m);
QList<QAction*> actions() const;
Messages_interface* m) override;
QList<QAction*> actions() const Q_DECL_OVERRIDE;
bool eventFilter(QObject *, QEvent *event)
bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE
{
if(!plane_item)
return false;

View File

@ -1,50 +1,47 @@
#include <QtCore/qglobal.h>
#include "Messages_interface.h"
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include "Camera_positions_list.h"
#include <CGAL/Three/Three.h>
#include <CGAL/Three/Viewer_interface.h>
#include <QMainWindow>
using namespace CGAL::Three;
class Polyhedron_demo_camera_positions_plugin :
public QObject,
public Polyhedron_demo_plugin_interface,
public CGAL::Three::Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90")
public:
void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface* );
QList<QAction*> actions() const;
void init() override;
QString name() const { return "camera_positions_plugin"; }
QString nameFilters() const { return "Camera positions (*.camera.txt)"; }
bool canLoad() const { return true; }
Scene_item* load(QFileInfo fileinfo) { cpl->load(fileinfo.filePath()); return 0; }
QString name() const override { return "camera_positions_plugin"; }
QString nameFilters() const override { return "Camera positions (*.camera.txt)"; }
bool canLoad(QFileInfo) const override { return true; }
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) override
{
Q_UNUSED(add_to_scene);
ok = true;
cpl->load(fileinfo.filePath());
return QList<Scene_item*>();
}
bool canSave(const Scene_item*) { return false; }
bool save(const Scene_item*, QFileInfo ) {return false; }
bool applicable(QAction*) const {return false;}
bool canSave(const Scene_item*) override { return false; }
bool save(QFileInfo,QList<CGAL::Three::Scene_item*>& ) override {return false; }
private:
Camera_positions_list* cpl;
};
void Polyhedron_demo_camera_positions_plugin::init(QMainWindow* mainWindow, Scene_interface*, Messages_interface *)
void Polyhedron_demo_camera_positions_plugin::init()
{
cpl = new Camera_positions_list(mainWindow);
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, cpl);
}
QList<QAction*>
Polyhedron_demo_camera_positions_plugin::actions() const
{
return QList<QAction*>();
cpl = new Camera_positions_list(CGAL::Three::Three::mainWindow());
CGAL::Three::Three::mainWindow()->addDockWidget(Qt::LeftDockWidgetArea, cpl);
}
#include "Camera_positions_plugin.moc"

View File

@ -0,0 +1,327 @@
#include <CGAL/Three/Three.h>
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/IO/read_3mf.h>
#include <CGAL/IO/write_3mf.h>
#include "Scene_surface_mesh_item.h"
#include "Scene_points_with_normal_item.h"
#include "Scene_polylines_item.h"
#include <iostream>
#include <fstream>
#include <unordered_map>
using namespace NMR;
class Io_3mf_plugin:
public QObject,
public CGAL::Three::Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "3mf_io_plugin.json")
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef std::vector<Kernel::Point_3> PointRange;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef std::list<PointRange> PolylineRange;
typedef std::vector<CGAL::Color> ColorRange;
void init() Q_DECL_OVERRIDE
{
QMenu* menuFile = CGAL::Three::Three::mainWindow()->findChild<QMenu*>("menuFile");
QAction* actionSaveSceneTo3mf = new QAction("Save the Scene as a 3mf File...");
connect(actionSaveSceneTo3mf, &QAction::triggered, this,
[this](){
QString filename =
QFileDialog::getSaveFileName(CGAL::Three::Three::mainWindow(),
tr("Save Scene to File..."),
QString(),
"*.3mf");
if(filename.isEmpty())
return;
if(!filename.endsWith(".3mf"))
filename.append(".3mf");
QList<Scene_item*> all_items;
for(int i = 0; i< CGAL::Three::Three::scene()->numberOfEntries(); ++i)
all_items.push_back(CGAL::Three::Three::scene()->item(i));
save(filename, all_items);
});
menuFile->insertAction(CGAL::Three::Three::mainWindow()->findChild<QAction*>("actionSa_ve_Scene_as_Script"), actionSaveSceneTo3mf);
}
QString name() const { return "3mf_io_plugin"; }
QString nameFilters() const { return
"3mf files (*.3mf)"; }
bool canLoad(QFileInfo) const Q_DECL_OVERRIDE { return true; }
QList<CGAL::Three::Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) Q_DECL_OVERRIDE {
namespace PMP = CGAL::Polygon_mesh_processing;
// Open file
ok = true;
std::vector<PointRange> all_points;
std::vector<PolygonRange> all_polygons;
std::vector<std::string> names;
QList<Scene_item*> result;
std::vector<std::vector<CGAL::Color> > all_colors;
int nb_polylines =
CGAL::read_polylines_from_3mf(fileinfo.filePath().toUtf8().toStdString(),
all_points, all_colors, names);
if(nb_polylines < 0 )
{
ok = false;
std::cerr << "Error in reading of meshes."<<std::endl;
return result;
}
for(int i=0; i< nb_polylines; ++i)
{
Scene_polylines_item* pol_item = new Scene_polylines_item();
PolylineRange& polylines = pol_item->polylines;
polylines.push_back(all_points[i]);
pol_item->setName(names[i].data());
pol_item->invalidateOpenGLBuffers();
CGAL::Color c = all_colors[i].front();
pol_item->setColor(QColor(c.red(), c.green(), c.blue()));
pol_item->setProperty("already_colord", true);
result << pol_item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(pol_item);
}
all_points.clear();
all_colors.clear();
names.clear();
int nb_point_sets =
CGAL::read_point_clouds_from_3mf(fileinfo.filePath().toUtf8().toStdString(),
all_points, all_colors, names);
if(nb_point_sets < 0 )
{
ok = false;
std::cerr << "Error in reading of meshes."<<std::endl;
return result;
}
for(int i=0; i< nb_point_sets; ++i)
{
Scene_points_with_normal_item* pts_item = new Scene_points_with_normal_item();
for(std::size_t j = 0; j < all_points[i].size(); ++j)
{
pts_item->point_set()->insert(all_points[i][j]);
}
pts_item->setName(names[i].data());
pts_item->invalidateOpenGLBuffers();
CGAL::Color c = all_colors[i].front();
pts_item->setColor(QColor(c.red(), c.green(), c.blue()));
pts_item->setProperty("already_colord", true);
result << pts_item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(pts_item);
}
all_points.clear();
names.clear();
all_colors.clear();
int nb_meshes =
CGAL::read_triangle_soups_from_3mf(fileinfo.filePath().toUtf8().toStdString(),
all_points, all_polygons, all_colors, names);
if(nb_meshes <0 )
{
ok = false;
std::cerr << "Error in reading of meshes."<<std::endl;
return result;
}
for(int i = 0; i< nb_meshes; ++i)
{
PolygonRange triangles = all_polygons[i];
PointRange points = all_points[i];
ColorRange colors = all_colors[i];
bool ok = true;
if(!PMP::is_polygon_soup_a_polygon_mesh(triangles))
ok = PMP::orient_polygon_soup(points, triangles);
if(!ok)
{
std::cerr<<"Object was not directly orientable, some vertices have been duplicated."<<std::endl;
}
SMesh mesh;
PMP::polygon_soup_to_polygon_mesh(points, triangles, mesh);
CGAL::Color first = colors.front();
bool need_pmap = false;
for(auto color : colors)
{
if (color != first)
{
need_pmap = true;
break;
}
}
if(need_pmap)
{
SMesh::Property_map<face_descriptor,CGAL::Color> fcolor =
mesh.add_property_map<face_descriptor,CGAL::Color>("f:color",first).first;
for(std::size_t pid = 0; pid < colors.size(); ++pid)
{
put(fcolor, face_descriptor(pid), colors[pid]);//should work bc mesh is just created and shouldn't have any destroyed face. Not so sure bc of orientation though.
}
}
Scene_surface_mesh_item* sm_item = new Scene_surface_mesh_item(mesh);
if(first == CGAL::Color(0,0,0,0))
first = CGAL::Color(50,80,120,255);
sm_item->setColor(QColor(first.red(), first.green(), first.blue()));
sm_item->setProperty("already_colored", true);
sm_item->setName(names[i].data());
sm_item->invalidateOpenGLBuffers();
result << sm_item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(sm_item);
}
ok = true;
return result;
}
bool canSave(const CGAL::Three::Scene_item*) Q_DECL_OVERRIDE {return false;}
bool save(QFileInfo fi, QList<CGAL::Three::Scene_item*>& items) Q_DECL_OVERRIDE {
QList<CGAL::Three::Scene_item*> to_return;
std::vector<Scene_surface_mesh_item*> sm_items;
std::vector<Scene_points_with_normal_item*> pts_items;
std::vector<Scene_polylines_item*> pol_items;
for(Scene_item* item : items)
{
Scene_surface_mesh_item* sm_item =
qobject_cast<Scene_surface_mesh_item*>(item);
if(sm_item)
{
sm_items.push_back(sm_item);
continue;
}
Scene_points_with_normal_item* pts_item =
qobject_cast<Scene_points_with_normal_item*>(item);
if(pts_item)
{
pts_items.push_back(pts_item);
continue;
}
Scene_polylines_item* pol_item =
qobject_cast<Scene_polylines_item*>(item);
if(pol_item)
{
pol_items.push_back(pol_item);
continue;
}
qDebug()<<item->name()<<" will not be saved.";
to_return.push_back(item);
}
HRESULT hResult;
NMR::PLib3MFModel * pModel;
hResult = NMR::lib3mf_createmodel(&pModel);
NMR::PLib3MFModelMeshObject* pMeshObject;
if (hResult != LIB3MF_OK) {
std::cerr << "could not create model: " << std::hex << hResult << std::endl;
return false;
}
for(Scene_surface_mesh_item* sm_item : sm_items)
{
SMesh &mesh = *sm_item->polyhedron();
PointRange points;
PolygonRange triangles;
typedef boost::property_map<SMesh, boost::vertex_point_t>::type VPMap;
VPMap vpm = get(boost::vertex_point, mesh);
std::unordered_map<boost::graph_traits<SMesh>::vertex_descriptor,
std::size_t> vertex_id_map;
std::size_t i = 0;
for(auto v : mesh.vertices())
{
points.push_back(get(vpm, v));
vertex_id_map[v] = i++;
}
for(auto f : mesh.faces())
{
Polygon triangle;
for(auto vert : CGAL::vertices_around_face(halfedge(f, mesh), mesh))
{
triangle.push_back(vertex_id_map[vert]);
}
triangles.push_back(triangle);
}
std::vector<CGAL::Color> colors;
//if item is multicolor, fill colors with f:color
if(sm_item->isItemMulticolor())
{
colors.reserve(triangles.size());
SMesh::Property_map<face_descriptor, CGAL::Color> fcolors =
mesh.property_map<face_descriptor, CGAL::Color >("f:color").first;
for(auto fd : mesh.faces())
{
colors.push_back(get(fcolors, fd));
}
}
else if(sm_item->hasPatchIds())
{
colors.reserve(triangles.size());
SMesh::Property_map<face_descriptor, int> fpid =
mesh.property_map<face_descriptor, int >("f:patch_id").first;
for(auto fd : mesh.faces())
{
int pid = get(fpid, fd);
QColor q_color = sm_item->color_vector()[pid];
colors.push_back(CGAL::Color(q_color.red(), q_color.green(),
q_color.blue(), q_color.alpha()));
}
}
//else fill it with item->color()
else
{
colors.resize(triangles.size());
const QColor& c = sm_item->color();
for(auto& color : colors)
color.set_rgb(c.red(), c.green(), c.blue());
}
CGAL::write_mesh_to_model(points, triangles, colors,
sm_item->name().toStdString(), &pMeshObject, pModel);
}
for(Scene_points_with_normal_item* pts_item : pts_items)
{
QColor qc = pts_item->color();
CGAL::Color color(qc.red(), qc.green(), qc.blue());
CGAL::write_point_cloud_to_model(pts_item->point_set()->points(), color,
pts_item->name().toStdString(),
&pMeshObject, pModel);
}
for(Scene_polylines_item* pol_item : pol_items)
{
for(auto pol_it = pol_item->polylines.begin();
pol_it != pol_item->polylines.end(); ++pol_it)
{
QColor qc = pol_item->color();
CGAL::Color color(qc.red(), qc.green(), qc.blue());
CGAL::write_polyline_to_model(*pol_it,color,
pol_item->name().toStdString(),
&pMeshObject, pModel);
}
}
CGAL::export_model_to_file(fi.filePath().toUtf8().toStdString(), pModel);
items = to_return;
return true;
}
};
#include "3mf_io_plugin.moc"

View File

@ -73,3 +73,17 @@ else()
message(STATUS "NOTICE : the LAS IO plugin needs LAS libraries and will not be compiled.")
endif()
endif()
find_path(3MF_INCLUDE_DIR
NAMES Model/COM/NMR_DLLInterfaces.h
DOC "Path to lib3MF headers"
)
find_library(3MF_LIBRARIES NAMES 3MF DOC "Path to the lib3MF library")
if(3MF_LIBRARIES AND 3MF_INCLUDE_DIR)
include_directories(${3MF_INCLUDE_DIR})
polyhedron_demo_plugin(3mf_io_plugin 3mf_io_plugin KEYWORDS IO)
target_link_libraries(3mf_io_plugin PRIVATE scene_surface_mesh_item scene_points_with_normal_item scene_polylines_item ${3MF_LIBRARIES})
else()
message(STATUS "NOTICE : The 3mf_io_plugin requires the lib3MF library, and will not be compiled.")
endif()

View File

@ -17,53 +17,42 @@ using namespace CGAL::Three;
class Polyhedron_demo_gocad_plugin :
public QObject,
public Polyhedron_demo_io_plugin_interface,
public Polyhedron_demo_plugin_helper
public Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "gocad_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" )
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "gocad_io_plugin.json")
public:
void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*) {
//get the references
this->scene = scene_interface;
this->mw = mainWindow;
}
QList<QAction*> actions() const {
return QList<QAction*>();
}
bool applicable(QAction*) const { return false;}
QString nameFilters() const;
QString name() const { return "gocad_plugin"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo, QList<CGAL::Three::Scene_item*>& );
};
QString Polyhedron_demo_gocad_plugin::nameFilters() const {
return "GOCAD files (*.ts)";
}
bool Polyhedron_demo_gocad_plugin::canLoad() const {
bool Polyhedron_demo_gocad_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
// Open file
std::ifstream in(fileinfo.filePath().toUtf8());
if(!in) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
@ -74,7 +63,10 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) {
if(fileinfo.size() == 0)
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
SMesh& P = * const_cast<SMesh*>(item->polyhedron());
@ -82,7 +74,8 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) {
if(! read_gocad(P, in, name, color)){
std::cerr << "Error: Invalid polyhedron" << std::endl;
delete item;
return 0;
ok = false;
return QList<Scene_item*>();
}
t.stop();
@ -98,7 +91,10 @@ Polyhedron_demo_gocad_plugin::load(QFileInfo fileinfo) {
item->setColor(qcolor);
}
item->invalidateOpenGLBuffers();
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_gocad_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -107,8 +103,10 @@ bool Polyhedron_demo_gocad_plugin::canSave(const CGAL::Three::Scene_item* item)
return qobject_cast<const Scene_surface_mesh_item*>(item);
}
bool Polyhedron_demo_gocad_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_gocad_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// This plugin supports polyhedrons
const Scene_surface_mesh_item* sm_item =
qobject_cast<const Scene_surface_mesh_item*>(item);
@ -120,6 +118,7 @@ bool Polyhedron_demo_gocad_plugin::save(const CGAL::Three::Scene_item* item, QFi
out.precision (std::numeric_limits<double>::digits10 + 2);
SMesh* poly = const_cast<SMesh*>(sm_item->polyhedron());
write_gocad(*poly, out, qPrintable(fileinfo.baseName()));
items.pop_front();
return true;
}

View File

@ -42,7 +42,6 @@
using namespace CGAL::Three;
class Io_implicit_function_plugin :
public QObject,
// public Polyhedron_demo_plugin_interface,
protected Polyhedron_demo_plugin_helper
{
Q_OBJECT

View File

@ -1,32 +1,33 @@
#include "Scene_points_with_normal_item.h"
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include <CGAL/Three/Three.h>
#include <CGAL/Three/Scene_item.h>
#include <fstream>
using namespace CGAL::Three;
class Polyhedron_demo_las_plugin :
public QObject,
public CGAL::Three::Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "las_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "las_io_plugin.json")
public:
QString name() const { return "las_plugin"; }
QString nameFilters() const { return "LAS files (*.las);;Compressed LAS files (*.laz)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo fileinfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& );
};
bool Polyhedron_demo_las_plugin::canLoad() const {
bool Polyhedron_demo_las_plugin::canLoad(QFileInfo ) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_las_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*> Polyhedron_demo_las_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
std::ifstream in(fileinfo.filePath().toUtf8(), std::ios_base::binary);
if(!in)
@ -37,11 +38,15 @@ Polyhedron_demo_las_plugin::load(QFileInfo fileinfo) {
if(!item->read_las_point_set(in))
{
delete item;
return 0;
ok = false;
return QList<Scene_item*>();
}
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_las_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -49,8 +54,9 @@ bool Polyhedron_demo_las_plugin::canSave(const CGAL::Three::Scene_item* item)
return qobject_cast<const Scene_points_with_normal_item*>(item);
}
bool Polyhedron_demo_las_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_las_plugin::save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// Check extension (quietly)
std::string extension = fileinfo.suffix().toUtf8().data();
if (extension != "las" && extension != "LAS")
@ -63,6 +69,7 @@ bool Polyhedron_demo_las_plugin::save(const CGAL::Three::Scene_item* item, QFile
return false;
std::ofstream out(fileinfo.filePath().toUtf8().data());
items.pop_front();
return point_set_item->write_las_point_set(out);
}

View File

@ -17,32 +17,37 @@ class Polyhedron_demo_io_nef_plugin :
public:
QString nameFilters() const;
QString name() const { return "io_nef_plugin"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items);
};
QString Polyhedron_demo_io_nef_plugin::nameFilters() const {
return "nef files (*.nef3)";
}
bool Polyhedron_demo_io_nef_plugin::canLoad() const {
bool Polyhedron_demo_io_nef_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_io_nef_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*> Polyhedron_demo_io_nef_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
//do not try file with extension different from nef3
if (fileinfo.suffix() != "nef3") return 0;
if (fileinfo.suffix() != "nef3")
{
ok = false;
return QList<Scene_item*>();
}
// Open file
std::ifstream in(fileinfo.filePath().toUtf8());
if(!in) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
// Try to read .nef3 in a polyhedron
@ -51,15 +56,22 @@ Polyhedron_demo_io_nef_plugin::load(QFileInfo fileinfo) {
if(fileinfo.size() == 0)
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
if(!item->load(in))
{
delete item;
return 0;
ok = false;
return QList<Scene_item*>();
}
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_io_nef_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -68,8 +80,9 @@ bool Polyhedron_demo_io_nef_plugin::canSave(const CGAL::Three::Scene_item* item)
return qobject_cast<const Scene_nef_polyhedron_item*>(item);
}
bool Polyhedron_demo_io_nef_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_io_nef_plugin::save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// This plugin supports polyhedrons and polygon soups
const Scene_nef_polyhedron_item* nef_item =
qobject_cast<const Scene_nef_polyhedron_item*>(item);
@ -79,6 +92,7 @@ bool Polyhedron_demo_io_nef_plugin::save(const CGAL::Three::Scene_item* item, QF
std::ofstream out(fileinfo.filePath().toUtf8());
out.precision (std::numeric_limits<double>::digits10 + 2);
items.pop_front();
return (nef_item && nef_item->save(out));
}

View File

@ -22,7 +22,7 @@ class Polyhedron_demo_off_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "off_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "off_io_plugin.json")
public:
bool isDefaultLoader(const Scene_item *item) const
@ -40,22 +40,21 @@ public:
}
QString name() const { return "off_plugin"; }
QString nameFilters() const { return "OFF files (*.off);;Wavefront OBJ (*.obj)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo fileinfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
CGAL::Three::Scene_item* load_off(QFileInfo fileinfo);
CGAL::Three::Scene_item* load_obj(QFileInfo fileinfo);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& );
};
bool Polyhedron_demo_off_plugin::canLoad() const {
bool Polyhedron_demo_off_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*> Polyhedron_demo_off_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
if(fileinfo.size() == 0)
{
@ -63,14 +62,41 @@ Polyhedron_demo_off_plugin::load(QFileInfo fileinfo) {
Scene_surface_mesh_item* item =
new Scene_surface_mesh_item(SMesh());
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
if(fileinfo.suffix().toLower() == "off"){
return load_off(fileinfo);
} else if(fileinfo.suffix().toLower() == "obj"){
return load_obj(fileinfo);
Scene_item* item = load_off(fileinfo);
if(item){
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
return 0;
else
{
ok = false;
return QList<Scene_item*>();
}
} else if(fileinfo.suffix().toLower() == "obj"){
Scene_item* item = load_obj(fileinfo);
if(item)
{
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
else
{
ok = true;
return QList<Scene_item*>();
}
}
return QList<Scene_item*>();
}
@ -183,8 +209,12 @@ bool Polyhedron_demo_off_plugin::canSave(const CGAL::Three::Scene_item* item)
qobject_cast<const Scene_points_with_normal_item*>(item);
}
bool Polyhedron_demo_off_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool
Polyhedron_demo_off_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// This plugin supports point sets, surface_meshes and polygon soups
const Scene_points_with_normal_item* points_item =
qobject_cast<const Scene_points_with_normal_item*>(item);
@ -200,12 +230,26 @@ bool Polyhedron_demo_off_plugin::save(const CGAL::Three::Scene_item* item, QFile
out.precision (std::numeric_limits<double>::digits10 + 2);
if(fileinfo.suffix().toLower() == "off"){
return (sm_item && sm_item->save(out)) ||
bool res = (sm_item && sm_item->save(out)) ||
(soup_item && soup_item->save(out)) ||
(points_item && points_item->write_off_point_set(out));
if(res){
items.pop_front();
return true;
}
else{
return false;
}
}
if(fileinfo.suffix().toLower() == "obj"){
return (sm_item && sm_item->save_obj(out));
bool res = (sm_item && sm_item->save_obj(out));
if(res)
{
items.pop_front();
return true;
}
else
return false;
}
return false;
}

View File

@ -11,24 +11,24 @@ class Polyhedron_demo_off_to_nef_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "off_to_nef_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "off_to_nef_io_plugin.json")
public:
QString name() const { return "off_to_nef_plugin"; }
QString nameFilters() const { return "OFF files, into nef (*.off)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& );
};
bool Polyhedron_demo_off_to_nef_plugin::canLoad() const {
bool Polyhedron_demo_off_to_nef_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*> Polyhedron_demo_off_to_nef_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene){
std::ifstream in(fileinfo.filePath().toUtf8());
if(!in)
@ -38,16 +38,23 @@ Polyhedron_demo_off_to_nef_plugin::load(QFileInfo fileinfo) {
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
if(!item->load_from_off(in))
{
delete item;
return 0;
ok = false;
return QList<Scene_item*>()<<item;
}
item->setName(fileinfo.baseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_off_to_nef_plugin::canSave(const CGAL::Three::Scene_item*)
@ -55,7 +62,8 @@ bool Polyhedron_demo_off_to_nef_plugin::canSave(const CGAL::Three::Scene_item*)
return false;
}
bool Polyhedron_demo_off_to_nef_plugin::save(const CGAL::Three::Scene_item*, QFileInfo)
bool Polyhedron_demo_off_to_nef_plugin::
save(QFileInfo ,QList<CGAL::Three::Scene_item*>&)
{
return false;
}

View File

@ -13,14 +13,14 @@
#include <CGAL/IO/PLY_writer.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <QMessageBox>
using namespace CGAL::Three;
class Polyhedron_demo_ply_plugin :
public QObject,
public CGAL::Three::Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "ply_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "ply_io_plugin.json")
public:
bool isDefaultLoader(const CGAL::Three::Scene_item *item) const
@ -31,20 +31,22 @@ public:
}
QString name() const { return "ply_plugin"; }
QString nameFilters() const { return "PLY files (*.ply)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo fileinfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&);
};
bool Polyhedron_demo_ply_plugin::canLoad() const {
bool Polyhedron_demo_ply_plugin::
canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Polyhedron_demo_ply_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene) {
std::ifstream in(fileinfo.filePath().toUtf8(), std::ios_base::binary);
if(!in)
@ -55,7 +57,8 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
if(fileinfo.size() == 0)
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
return 0;
ok = false;
return QList<Scene_item*>();
}
// Test if input is mesh or point set
@ -99,7 +102,10 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
sm_item->setName(fileinfo.completeBaseName());
sm_item->comments() = comments;
QApplication::restoreOverrideCursor();
return sm_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(sm_item);
return QList<Scene_item*>()<<sm_item;
}
in.clear();
@ -114,14 +120,18 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
if (!(CGAL::read_PLY (in, points, polygons, fcolors, vcolors)))
{
QApplication::restoreOverrideCursor();
return NULL;
ok = false;
return QList<Scene_item*>();
}
Scene_polygon_soup_item* soup_item = new Scene_polygon_soup_item;
soup_item->setName(fileinfo.completeBaseName());
soup_item->load (points, polygons, fcolors, vcolors);
QApplication::restoreOverrideCursor();
return soup_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(soup_item);
return QList<Scene_item*>()<<soup_item;
}
else // Open point set
{
@ -131,16 +141,21 @@ Polyhedron_demo_ply_plugin::load(QFileInfo fileinfo) {
{
delete item;
QApplication::restoreOverrideCursor();
return NULL;
ok = false;
return QList<Scene_item*>();
}
if(item->has_normals())
item->setRenderingMode(CGAL::Three::Three::defaultPointSetRenderingMode());
item->setName(fileinfo.completeBaseName());
QApplication::restoreOverrideCursor();
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
QApplication::restoreOverrideCursor();
return NULL;
ok = true;
return QList<Scene_item*>();
}
bool Polyhedron_demo_ply_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -152,8 +167,10 @@ bool Polyhedron_demo_ply_plugin::canSave(const CGAL::Three::Scene_item* item)
|| qobject_cast<const Scene_textured_surface_mesh_item*>(item));
}
bool Polyhedron_demo_ply_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_ply_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// Check extension (quietly)
std::string extension = fileinfo.suffix().toUtf8().data();
if (extension != "ply" && extension != "PLY")
@ -179,25 +196,49 @@ bool Polyhedron_demo_ply_plugin::save(const CGAL::Three::Scene_item* item, QFile
const Scene_points_with_normal_item* point_set_item =
qobject_cast<const Scene_points_with_normal_item*>(item);
if (point_set_item)
return point_set_item->write_ply_point_set(out, (choice == tr("Binary")));
{
bool res =
point_set_item->write_ply_point_set(out, (choice == tr("Binary")));
if(res)
items.pop_front();
return res;
}
// This plugin supports polygon soups
const Scene_polygon_soup_item* soup_item =
qobject_cast<const Scene_polygon_soup_item*>(item);
if (soup_item)
return CGAL::write_PLY (out, soup_item->points(), soup_item->polygons());
{
bool res =
CGAL::write_PLY (out, soup_item->points(), soup_item->polygons());
if(res)
items.pop_front();
return res;
}
// This plugin supports surface meshes
const Scene_surface_mesh_item* sm_item =
qobject_cast<const Scene_surface_mesh_item*>(item);
if (sm_item)
return CGAL::write_ply (out, *(sm_item->polyhedron()), sm_item->comments());
{
bool res =
CGAL::write_ply (out, *(sm_item->polyhedron()), sm_item->comments());
if(res)
items.pop_front();
return res;
}
// This plugin supports textured surface meshes
const Scene_textured_surface_mesh_item* stm_item =
qobject_cast<const Scene_textured_surface_mesh_item*>(item);
if (stm_item)
return CGAL::write_ply (out, *(stm_item->textured_face_graph()));
{
bool res =
CGAL::write_ply (out, *(stm_item->textured_face_graph()));
if(res)
items.pop_front();
return res;
}
return false;
}

View File

@ -17,17 +17,18 @@ class Polyhedron_demo_polylines_io_plugin :
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "polylines_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90")
public:
// To silent a warning -Woverloaded-virtual
// See http://stackoverflow.com/questions/9995421/gcc-woverloaded-virtual-warnings
using Polyhedron_demo_io_plugin_interface::init;
//! Configures the widget
void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*) {
Messages_interface*) override{
//get the references
this->scene = scene_interface;
this->mw = mainWindow;
@ -43,14 +44,14 @@ public:
connect(actionJoin_polylines, &QAction::triggered, this, &Polyhedron_demo_polylines_io_plugin::join);
}
QString name() const { return "polylines_io_plugin"; }
QString nameFilters() const { return "Polylines files (*.polylines.txt *.cgal)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
QString name() const override{ return "polylines_io_plugin"; }
QString nameFilters() const override{ return "Polylines files (*.polylines.txt *.cgal)"; }
bool canLoad(QFileInfo fileinfo) const override;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) override;
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool applicable(QAction* a) const {
bool canSave(const CGAL::Three::Scene_item*) override;
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&) override;
bool applicable(QAction* a) const override{
bool all_polylines_selected = true;
Q_FOREACH(int index, scene->selectionIndices())
{
@ -69,7 +70,7 @@ public:
else
return false;
}
QList<QAction*> actions() const {
QList<QAction*> actions() const override{
return QList<QAction*>()<<actionSplit_polylines
<<actionJoin_polylines;
@ -85,19 +86,31 @@ private:
QAction* actionJoin_polylines;
};
bool Polyhedron_demo_polylines_io_plugin::canLoad() const {
bool Polyhedron_demo_polylines_io_plugin::canLoad(QFileInfo fileinfo) const{
if(!fileinfo.suffix().contains("cgal"))
return true;
std::ifstream in(fileinfo.filePath().toUtf8());
if(!in) {
return false;
}
int first;
if(!(in >> first)
|| first <= 0)
return false;
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Polyhedron_demo_polylines_io_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene){
// Open file
std::ifstream ifs(fileinfo.filePath().toUtf8());
if(!ifs) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
if(fileinfo.size() == 0)
@ -105,7 +118,10 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) {
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
Scene_polylines_item* item = new Scene_polylines_item;
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
std::list<std::vector<Scene_polylines_item::Point_3> > polylines;
@ -123,7 +139,11 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) {
Scene_polylines_item::Point_3 p;
ifs >> p;
polyline.push_back(p);
if(!ifs.good()) return 0;
if(!ifs.good())
{
ok = false;
return QList<Scene_item*>();
}
}
std::string line_remainder;
std::getline(ifs, line_remainder);
@ -136,9 +156,17 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) {
std::cerr << " (metadata: \"" << qPrintable(metadata) << "\")\n";
} else {
}
if(ifs.bad() || ifs.fail()) return 0;
if(ifs.bad() || ifs.fail())
{
ok = false;
return QList<Scene_item*>();
}
}
if(counter == 0)
{
ok = false;
return QList<Scene_item*>();
}
if(counter == 0) return 0;
Scene_polylines_item* item = new Scene_polylines_item;
item->polylines = polylines;
item->setName(fileinfo.baseName());
@ -146,7 +174,10 @@ Polyhedron_demo_polylines_io_plugin::load(QFileInfo fileinfo) {
item->setProperty("polylines metadata", polylines_metadata);
std::cerr << "Number of polylines in item: " << item->polylines.size() << std::endl;
item->invalidateOpenGLBuffers();
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_polylines_io_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -154,8 +185,10 @@ bool Polyhedron_demo_polylines_io_plugin::canSave(const CGAL::Three::Scene_item*
return qobject_cast<const Scene_polylines_item*>(item) != 0;
}
bool Polyhedron_demo_polylines_io_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_polylines_io_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
const Scene_polylines_item* poly_item =
qobject_cast<const Scene_polylines_item*>(item);
@ -188,7 +221,10 @@ bool Polyhedron_demo_polylines_io_plugin::save(const CGAL::Three::Scene_item* it
}
out << std::endl;
}
return (bool) out;
bool res = (bool) out;
if(res)
items.pop_front();
return res;
}
void Polyhedron_demo_polylines_io_plugin::split()

View File

@ -5,8 +5,6 @@
#include "SMesh_type.h"
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
#include <CGAL/Three/Three.h>
#include <fstream>
@ -25,66 +23,60 @@
using namespace CGAL::Three;
class Polyhedron_demo_stl_plugin :
public QObject,
public Polyhedron_demo_io_plugin_interface,
public Polyhedron_demo_plugin_helper
public Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "stl_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "stl_io_plugin.json")
public:
void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*) {
//get the references
this->scene = scene_interface;
this->mw = mainWindow;
}
QList<QAction*> actions() const {
return QList<QAction*>();
}
bool applicable(QAction*) const { return false;}
QString nameFilters() const;
QString name() const { return "stl_plugin"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo fileinfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&);
};
QString Polyhedron_demo_stl_plugin::nameFilters() const {
return "STL files (*.stl)";
}
bool Polyhedron_demo_stl_plugin::canLoad() const {
bool Polyhedron_demo_stl_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Polyhedron_demo_stl_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene){
// Open file
std::ifstream in(fileinfo.filePath().toUtf8(), std::ios::in | std::ios::binary);
if(!in) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
if(fileinfo.size() == 0)
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
Scene_surface_mesh_item* item = new Scene_surface_mesh_item();
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
std::vector<std::array<double, 3> > points;
std::vector<std::array<int, 3> > triangles;
if (!CGAL::read_STL(in, points, triangles))
{
std::cerr << "Error: invalid STL file" << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
try{
@ -98,7 +90,10 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) {
else{
Scene_surface_mesh_item* item = new Scene_surface_mesh_item(SM);
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
}
catch(...){}
@ -106,7 +101,10 @@ Polyhedron_demo_stl_plugin::load(QFileInfo fileinfo) {
Scene_polygon_soup_item* item = new Scene_polygon_soup_item();
item->setName(fileinfo.completeBaseName());
item->load(points, triangles);
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool Polyhedron_demo_stl_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -114,8 +112,10 @@ bool Polyhedron_demo_stl_plugin::canSave(const CGAL::Three::Scene_item* item)
return qobject_cast<const Scene_surface_mesh_item*>(item);
}
bool Polyhedron_demo_stl_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_stl_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
const Scene_surface_mesh_item* sm_item =
qobject_cast<const Scene_surface_mesh_item*>(item);
@ -144,6 +144,7 @@ bool Polyhedron_demo_stl_plugin::save(const CGAL::Three::Scene_item* item, QFile
if (sm_item)
{
CGAL::write_STL(*sm_item->face_graph(), out);
items.pop_front();
return true;
}
return false;

View File

@ -3,8 +3,6 @@
#include <QMainWindow>
#include <QObject>
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
#include <CGAL/Three/Scene_group_item.h>
#include <CGAL/Three/Three.h>
@ -20,41 +18,44 @@
using namespace CGAL::Three;
class Surf_io_plugin:
public QObject,
public Polyhedron_demo_io_plugin_interface,
public Polyhedron_demo_plugin_helper
public Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "surf_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "surf_io_plugin.json")
public:
void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*) {
//get the references
this->scene = scene_interface;
this->mw = mainWindow;
}
QList<QAction*> actions() const {
return QList<QAction*>();
}
bool applicable(QAction*) const { return false;}
QString name() const { return "surf_io_plugin"; }
QString nameFilters() const { return "Amira files (*.surf)"; }
bool canLoad() const{ return true; }
bool canLoad(QFileInfo) const{ return true; }
template<class FaceGraphItem>
CGAL::Three::Scene_item* actual_load(QFileInfo fileinfo);
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*) { return false; }
bool save(const CGAL::Three::Scene_item*, QFileInfo) { return false; }
bool save(QFileInfo ,QList<CGAL::Three::Scene_item*>& ) { return false; }
};
CGAL::Three::Scene_item* Surf_io_plugin::load(QFileInfo fileinfo)
QList<Scene_item*>
Surf_io_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
{
return actual_load<Scene_surface_mesh_item>(fileinfo);
Scene_item* item =
actual_load<Scene_surface_mesh_item>(fileinfo);
if(item)
{
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
else
{
ok = false;
return QList<Scene_item*>();
}
}
template< class FaceGraphItem>
CGAL::Three::Scene_item* Surf_io_plugin::actual_load(QFileInfo fileinfo)
@ -103,8 +104,8 @@ CGAL::Three::Scene_item* Surf_io_plugin::actual_load(QFileInfo fileinfo)
FaceGraphItem *patch = new FaceGraphItem(patches[i]);
patch->setName(QString("Patch #%1").arg(i));
patch->setColor(colors_[i]);
scene->addItem(patch);
scene->changeGroup(patch, group);
CGAL::Three::Three::scene()->addItem(patch);
CGAL::Three::Three::scene()->changeGroup(patch, group);
}
return group;
}

View File

@ -291,7 +291,7 @@ class Polyhedron_demo_vtk_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "vtk_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "vtk_io_plugin.json")
public:
typedef boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
@ -308,8 +308,9 @@ public:
}
bool save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
std::string extension = fileinfo.suffix().toLower().toStdString();
if ( extension != "vtk" && extension != "vtp" && extension != "vtu")
return false;
@ -356,10 +357,11 @@ public:
CGAL::output_to_vtu(os, c3t3);
}
items.pop_front();
return true;
}
bool canLoad() const { return true; }
bool canLoad(QFileInfo) const { return true; }
template <class vtkReader>
vtkSmartPointer<vtkReader>
@ -374,11 +376,14 @@ public:
return reader;
}
CGAL::Three::Scene_item* load(QFileInfo fileinfo)
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
{
std::string extension=fileinfo.suffix().toLower().toStdString();
if (extension != "vtk" && extension != "vtp" && extension != "vtu")
return 0;
{
ok = false;
return QList<Scene_item*>();
}
std::string fname = fileinfo.absoluteFilePath().toStdString();
@ -389,7 +394,10 @@ public:
Scene_facegraph_item* item =
new Scene_facegraph_item();
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
vtkSmartPointer<vtkPointSet> data;
@ -421,7 +429,8 @@ public:
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
return NULL;
ok = false;
return QList<Scene_item*>();
}
if (obs->GetWarning())
{
@ -442,7 +451,8 @@ public:
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Critical);
msgBox.exec();
return NULL;
ok = false;
return QList<Scene_item*>();
}
if (obs->GetWarning())
{
@ -491,7 +501,10 @@ public:
}
else{
poly_item->setName(fileinfo.baseName());
return poly_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(poly_item);
return QList<Scene_item*>()<<poly_item;
}
}
}
@ -592,7 +605,10 @@ public:
}
else{
c3t3_item->setName(fileinfo.baseName());
return c3t3_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(c3t3_item);
return QList<Scene_item*>()<<c3t3_item;
}
}
@ -611,12 +627,19 @@ public:
}
else{
polyline_item->setName(fileinfo.baseName());
return polyline_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(polyline_item);
return QList<Scene_item*>()<<polyline_item;
}
}
if(group)
return group;
if(group){
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(group);
return QList<Scene_item*>()<<group;
}
QApplication::restoreOverrideCursor();
QMessageBox::warning(CGAL::Three::Three::mainWindow(),
@ -630,7 +653,10 @@ public:
point_item->point_set()->insert(Point_3(p[0], p[1], p[2]));
}
point_item->setName(fileinfo.baseName());
return point_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(point_item);
return QList<Scene_item*>()<<point_item;
}
}; // end Polyhedron_demo_vtk_plugin

View File

@ -15,32 +15,34 @@ class Polyhedron_demo_xyz_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "xyz_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "xyz_io_plugin.json")
public:
QString name() const { return "xyz_plugin"; }
QString nameFilters() const { return "XYZ as Point Set (*.xyz);;Point Set with Normal (*.pwn)"; }
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&);
};
bool Polyhedron_demo_xyz_plugin::canLoad() const {
bool Polyhedron_demo_xyz_plugin::canLoad(QFileInfo) const {
return true;
}
CGAL::Three::Scene_item*
Polyhedron_demo_xyz_plugin::load(QFileInfo fileinfo)
QList<Scene_item*>
Polyhedron_demo_xyz_plugin::
load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
{
// Open file
std::ifstream in(fileinfo.filePath().toUtf8().data());
if(!in) {
std::cerr << "Error! Cannot open file " << fileinfo.filePath().toStdString() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
@ -50,19 +52,26 @@ Polyhedron_demo_xyz_plugin::load(QFileInfo fileinfo)
Scene_points_with_normal_item* item =
new Scene_points_with_normal_item();
item->setName(fileinfo.completeBaseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
// Read .xyz in a point set
Scene_points_with_normal_item* point_set_item = new Scene_points_with_normal_item;
point_set_item->setName(fileinfo.completeBaseName());
if(!point_set_item->read_xyz_point_set(in)) {
delete point_set_item;
return NULL;
ok = false;
return QList<Scene_item*>();
}
if(point_set_item->has_normals())
point_set_item->setRenderingMode(CGAL::Three::Three::defaultPointSetRenderingMode());
return point_set_item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(point_set_item);
return QList<Scene_item*>()<<point_set_item;
}
bool Polyhedron_demo_xyz_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -71,8 +80,10 @@ bool Polyhedron_demo_xyz_plugin::canSave(const CGAL::Three::Scene_item* item)
return qobject_cast<const Scene_points_with_normal_item*>(item);
}
bool Polyhedron_demo_xyz_plugin::save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
bool Polyhedron_demo_xyz_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
// Check extension (quietly)
std::string extension = fileinfo.suffix().toUtf8().data();
if (extension != "xyz" && extension != "XYZ" &&
@ -88,7 +99,10 @@ bool Polyhedron_demo_xyz_plugin::save(const CGAL::Three::Scene_item* item, QFile
// Save point set as .xyz
std::ofstream out(fileinfo.filePath().toUtf8().data());
out.precision (std::numeric_limits<double>::digits10 + 2);
return point_set_item->write_xyz_point_set(out);
bool res = point_set_item->write_xyz_point_set(out);
if(res)
items.pop_front();
return res;
}
#include "XYZ_io_plugin.moc"

View File

@ -14,7 +14,7 @@ class LCC_io_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "lcc_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "lcc_io_plugin.json")
public:
bool isDefaultLoader(const CGAL::Three::Scene_item *item) const
@ -33,13 +33,14 @@ public:
"3-map files (*.3map)";
}
bool canLoad() const { return true; }
CGAL::Three::Scene_item* load(QFileInfo fileinfo){
bool canLoad(QFileInfo) const { return true; }
QList<CGAL::Three::Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true){
// Open file
std::ifstream ifs(fileinfo.filePath().toUtf8());
if(!ifs) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return nullptr;
ok = false;
return QList<CGAL::Three::Scene_item*>();
}
Scene_lcc_item::LCC lcc;
@ -53,17 +54,21 @@ public:
}
if(!res)
{
return nullptr;
ok = false;
return QList<CGAL::Three::Scene_item*>();
}
Scene_lcc_item* new_item = new Scene_lcc_item(lcc);
new_item->setName(fileinfo.fileName());
new_item->invalidateOpenGLBuffers();
return new_item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(new_item);
ok = true;
return QList<CGAL::Three::Scene_item*>()<<new_item;
}
bool canSave(const CGAL::Three::Scene_item*){return false;}
bool save(const CGAL::Three::Scene_item*, QFileInfo){
bool save(QFileInfo, QList<CGAL::Three::Scene_item*>& ){
return false;
}

View File

@ -2,7 +2,6 @@
#include "Scene_c3t3_item.h"
#include <CGAL/Mesh_3/tet_soup_to_c3t3.h>
#include <CGAL/Three/Polyhedron_demo_io_plugin_interface.h>
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Three/Three.h>
#include <CGAL/IO/File_avizo.h>
#include <iostream>
@ -12,59 +11,63 @@
class Polyhedron_demo_c3t3_binary_io_plugin :
public QObject,
public CGAL::Three::Polyhedron_demo_io_plugin_interface,
public CGAL::Three::Polyhedron_demo_plugin_interface
public CGAL::Three::Polyhedron_demo_io_plugin_interface
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "c3t3_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "c3t3_io_plugin.json")
public:
void init(QMainWindow*, CGAL::Three::Scene_interface* sc, Messages_interface*)
{
this->scene = sc;
}
QString name() const { return "C3t3_io_plugin"; }
QString nameFilters() const { return "binary files (*.cgal);;ascii (*.mesh);;maya (*.ma)"; }
QString saveNameFilters() const { return "binary files (*.cgal);;ascii (*.mesh);;maya (*.ma);;avizo (*.am);;OFF files (*.off)"; }
QString loadNameFilters() const { return "binary files (*.cgal);;ascii (*.mesh)"; }
QList<QAction*> actions() const
{
return QList<QAction*>();
}
bool applicable(QAction*) const
{
return false;
}
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
bool canLoad(QFileInfo) const;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true);
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo);
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& );
private:
bool try_load_other_binary_format(std::istream& in, C3t3& c3t3);
bool try_load_a_cdt_3(std::istream& in, C3t3& c3t3);
CGAL::Three::Scene_interface* scene;
};
bool Polyhedron_demo_c3t3_binary_io_plugin::canLoad() const {
bool Polyhedron_demo_c3t3_binary_io_plugin::canLoad(QFileInfo fi) const {
if(!fi.suffix().contains("cgal"))
return true;
std::ifstream in(fi.filePath().toUtf8(),
std::ios_base::in|std::ios_base::binary);
if(!in) {
std::cerr << "Error! Cannot open file "
<< (const char*)fi.filePath().toUtf8() << std::endl;
return false;
}
std::string line;
std::istringstream iss;
std::getline (in,line);
iss.str(line);
std::string keyword;
if (iss >> keyword)
if (keyword == "binary")
return true;
return false;
}
CGAL::Three::Scene_item*
Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Polyhedron_demo_c3t3_binary_io_plugin::load(
QFileInfo fileinfo, bool& ok, bool add_to_scene) {
// Open file
ok = true;
std::ifstream in(fileinfo.filePath().toUtf8(),
std::ios_base::in|std::ios_base::binary);
if(!in) {
std::cerr << "Error! Cannot open file "
<< (const char*)fileinfo.filePath().toUtf8() << std::endl;
return NULL;
ok = false;
return QList<Scene_item*>();
}
Scene_c3t3_item* item = new Scene_c3t3_item();
@ -72,7 +75,9 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
{
CGAL::Three::Three::warning( tr("The file you are trying to load is empty."));
item->setName(fileinfo.completeBaseName());
return item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<< item;
}
if(fileinfo.suffix().toLower() == "cgal")
{
@ -80,7 +85,9 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
if(item->load_binary(in)) {
return item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>() << item;
}
item->c3t3().clear();
@ -89,7 +96,9 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
item->c3t3_changed();
item->changed();
item->resetCutPlane();
return item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<< item;
}
item->c3t3().clear();
@ -98,7 +107,9 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
item->c3t3_changed();
item->changed();
item->resetCutPlane();
return item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
}
else if (fileinfo.suffix().toLower() == "mesh")
@ -154,7 +165,9 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
item->c3t3_changed();
item->resetCutPlane();
return item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
else if(item->c3t3().triangulation().number_of_finite_cells() == 0)
{
@ -168,7 +181,8 @@ Polyhedron_demo_c3t3_binary_io_plugin::load(QFileInfo fileinfo) {
// if all loading failed...
delete item;
return NULL;
ok = false;
return QList<Scene_item*>();
}
bool Polyhedron_demo_c3t3_binary_io_plugin::canSave(const CGAL::Three::Scene_item* item)
@ -179,8 +193,9 @@ bool Polyhedron_demo_c3t3_binary_io_plugin::canSave(const CGAL::Three::Scene_ite
bool
Polyhedron_demo_c3t3_binary_io_plugin::
save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
save(QFileInfo fileinfo, QList<Scene_item *> &items)
{
Scene_item* item = items.front();
const Scene_c3t3_item* c3t3_item = qobject_cast<const Scene_c3t3_item*>(item);
if ( NULL == c3t3_item )
{
@ -194,13 +209,21 @@ save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
std::ofstream out(fileinfo.filePath().toUtf8(),
std::ios_base::out|std::ios_base::binary);
return out && c3t3_item->save_binary(out);
bool ok = out && c3t3_item->save_binary(out);
if(!ok)
return false;
else
{
items.pop_front();
return true;
}
}
else if (fileinfo.suffix() == "mesh")
{
std::ofstream medit_file (qPrintable(path));
c3t3_item->c3t3().output_to_medit(medit_file,true,true);
items.pop_front();
return true;
}
else if (fileinfo.suffix() == "ma")
@ -208,18 +231,21 @@ save(const CGAL::Three::Scene_item* item, QFileInfo fileinfo)
std::ofstream maya_file (qPrintable(path));
c3t3_item->c3t3().output_to_maya(
maya_file,true);
items.pop_front();
return true;
}
else if (fileinfo.suffix() == "am")
{
std::ofstream avizo_file (qPrintable(path));
CGAL::output_to_avizo(avizo_file, c3t3_item->c3t3());
items.pop_front();
return true;
}
else if (fileinfo.suffix() == "off")
{
std::ofstream off_file(qPrintable(path));
c3t3_item->c3t3().output_facets_in_complex_to_off(off_file);
items.pop_front();
return true;
}
else

View File

@ -207,16 +207,16 @@ class Io_image_plugin :
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "io_image_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90" FILE "io_image_plugin.json")
public:
bool applicable(QAction*) const {
bool applicable(QAction*) const override{
return qobject_cast<Scene_image_item*>(scene->item(scene->mainSelectionIndex()));
}
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface *mi) {
using Polyhedron_demo_io_plugin_interface::init;
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface *mi) override {
this->message_interface = mi;
this->scene = scene_interface;
this->mw = mainWindow;
@ -270,10 +270,10 @@ public:
}
}
}
QList<QAction*> actions() const {
QList<QAction*> actions() const override{
return QList<QAction*>() << planeSwitch;
}
virtual void closure()
virtual void closure() override
{
QDockWidget* controlDockWidget = mw->findChild<QDockWidget*>("volumePlanesControl");
if(controlDockWidget)
@ -281,18 +281,21 @@ public:
}
Io_image_plugin() : planeSwitch(NULL) {}
QString nameFilters() const;
bool canLoad() const;
CGAL::Three::Scene_item* load(QFileInfo fileinfo);
QString nameFilters() const override;
bool canLoad(QFileInfo) const override;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) override;
bool canSave(const CGAL::Three::Scene_item*);
bool save(const CGAL::Three::Scene_item* item, QFileInfo fi) {
bool canSave(const CGAL::Three::Scene_item*) override;
bool save(QFileInfo fileinfo, QList<CGAL::Three::Scene_item*>& items ) override{
Scene_item* item = items.front();
const Scene_image_item* im_item = qobject_cast<const Scene_image_item*>(item);
point_image p_im = *im_item->image()->image();
return _writeImage(&p_im, fi.filePath().toUtf8()) == 0;
bool ok = _writeImage(&p_im, fileinfo.filePath().toUtf8()) == 0;
items.pop_front();
return ok;
}
QString name() const { return "segmented images"; }
QString name() const override{ return "segmented images"; }
public Q_SLOTS:
@ -965,7 +968,7 @@ QString Io_image_plugin::nameFilters() const {
}
bool Io_image_plugin::canLoad() const {
bool Io_image_plugin::canLoad(QFileInfo) const {
return true;
}
@ -987,8 +990,11 @@ void convert(Image* image)
image->image()->wdim = 4;
image->image()->wordKind = WK_FLOAT;
}
CGAL::Three::Scene_item*
Io_image_plugin::load(QFileInfo fileinfo) {
QList<Scene_item*>
Io_image_plugin::load(QFileInfo fileinfo, bool& ok, bool add_to_scene)
{
ok = true;
QApplication::restoreOverrideCursor();
Image* image = new Image;
if(fileinfo.suffix() != "H" && fileinfo.suffix() != "HH" &&
@ -1075,8 +1081,9 @@ Io_image_plugin::load(QFileInfo fileinfo) {
success = false;
}
if(!success){
ok = false;
delete image;
return NULL;
return QList<Scene_item*>();
}
}
//read a sep file
@ -1117,7 +1124,8 @@ Io_image_plugin::load(QFileInfo fileinfo) {
if(return_code != QDialog::Accepted)
{
delete image;
return NULL;
ok = false;
return QList<Scene_item*>();
}
// Get selected precision
@ -1145,7 +1153,9 @@ Io_image_plugin::load(QFileInfo fileinfo) {
else
image_item = new Scene_image_item(image,voxel_scale, false);
image_item->setName(fileinfo.baseName());
return image_item;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(image_item);
return QList<Scene_item*>() << image_item;
}
bool Io_image_plugin::canSave(const CGAL::Three::Scene_item* item)

View File

@ -560,7 +560,7 @@ void Volume_plane<T>::draw(Viewer_interface *viewer) const {
template<typename T>
bool Volume_plane<T>::eventFilter(QObject *sender, QEvent *event)
{
CGAL::QGLViewer* viewer = qobject_cast<CGAL::QGLViewer*>(sender);
CGAL::Three::Viewer_interface* viewer = qobject_cast<CGAL::Three::Viewer_interface*>(sender);
if(!viewer)
return false;
if(event->type() == QEvent::MouseButtonPress)

View File

@ -73,12 +73,12 @@ class Polyhedron_demo_selection_plugin :
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface CGAL::Three::Polyhedron_demo_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "selection_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90")
public:
QString nameFilters() const { return "Selection files(*.selection.txt)"; }
QString name() const { return "selection_sm_plugin"; }
QString nameFilters() const override { return "Selection files(*.selection.txt)"; }
QString name() const override { return "selection_sm_plugin"; }
bool canLoad() const {
bool canLoad(QFileInfo) const override {
Scene_item * item = CGAL::Three::Three::scene()->item(
CGAL::Three::Three::scene()->mainSelectionIndex());
Scene_facegraph_item* fg_item = qobject_cast<Scene_facegraph_item*>(item);
@ -91,36 +91,48 @@ public:
return false;
}
CGAL::Three::Scene_item* load(QFileInfo fileinfo) {
if(fileinfo.suffix().toLower() != "txt") return 0;
QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) override {
if(fileinfo.suffix().toLower() != "txt")
{
ok = false;
return QList<Scene_item*>();
}
// There will be no actual loading at this step.
Scene_polyhedron_selection_item* item = new Scene_polyhedron_selection_item();
if(!item->load(fileinfo.filePath().toStdString())) {
delete item;
return NULL;
ok = false;
return QList<Scene_item*>();
}
item->setName(fileinfo.baseName());
return item;
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
bool canSave(const CGAL::Three::Scene_item* scene_item) {
bool canSave(const CGAL::Three::Scene_item* scene_item) override {
return qobject_cast<const Scene_polyhedron_selection_item*>(scene_item);
}
bool save(const CGAL::Three::Scene_item* scene_item, QFileInfo fileinfo) {
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items) override {
Scene_item* scene_item = items.front();
const Scene_polyhedron_selection_item* item = qobject_cast<const Scene_polyhedron_selection_item*>(scene_item);
if(item == NULL) { return false; }
return item->save(fileinfo.filePath().toStdString());
bool res = item->save(fileinfo.filePath().toStdString());
if(res)
items.pop_front();
return res;
}
bool applicable(QAction*) const {
bool applicable(QAction*) const override {
return qobject_cast<Scene_face_graph_item*>(scene->item(scene->mainSelectionIndex()))
|| qobject_cast<Scene_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex()));
}
void print_message(QString message) { CGAL::Three::Three::information(message); }
QList<QAction*> actions() const { return QList<QAction*>() << actionSelection; }
void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m) {
QList<QAction*> actions() const override { return QList<QAction*>() << actionSelection; }
using Polyhedron_demo_io_plugin_interface::init;
virtual void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface* m) override{
mw = mainWindow;
scene = scene_interface;
messages = m;
@ -204,7 +216,7 @@ public:
operations_map[operations_strings[8]] = 8;
operations_map[operations_strings[9]] = 9;
}
virtual void closure()
virtual void closure() override
{
dock_widget->hide();
}

View File

@ -19,7 +19,7 @@ class Polyhedron_demo_features_detection_plugin :
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
QAction* actionDetectFeatures;
public:
QList<QAction*> actions() const { return QList<QAction*>() << actionDetectFeatures; }

View File

@ -1633,15 +1633,24 @@ void Scene_c3t3_item::show_intersection(bool b)
d->intersection->setName("Intersection tetrahedra");
d->intersection->setRenderingMode(renderingMode());
connect(d->intersection, SIGNAL(destroyed()), this, SLOT(reset_intersection_item()));
scene->addItem(d->intersection);
scene->changeGroup(d->intersection, this);
lockChild(d->intersection);
BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool())
{
CGAL::Three::Viewer_interface* viewer = static_cast<CGAL::Three::Viewer_interface*>(v);
d->are_intersection_buffers_filled[viewer] = false;
if(!d->areInterBufFilled(viewer))
{
//initGL
Scene_c3t3_item* ncthis = const_cast<Scene_c3t3_item*>(this);
ncthis->d->computeIntersections(viewer);
d->are_intersection_buffers_filled[viewer] = true;
ncthis->show_intersection(true);
}
}
scene->addItem(d->intersection);
scene->changeGroup(d->intersection, this);
lockChild(d->intersection);
}
else if (!b && d->intersection!=NULL)
{
unlockChild(d->intersection);

View File

@ -286,6 +286,14 @@ void Scene_nef_polyhedron_item_priv::compute_normals_and_vertices(void) const
Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector();
if(f->plane().a() != 0)
v /= f->plane().a();
else if(f->plane().b() != 0)
v /= f->plane().b();
else if(f->plane().c() != 0)
v /= f->plane().c();
else if(f->plane().d() != 0)
v /= f->plane().d();
GLfloat normal[3];
normal[0] = CGAL::to_double(v.x());
normal[1] = CGAL::to_double(v.y());

View File

@ -1779,6 +1779,7 @@ void Scene_polyhedron_selection_item::common_constructor()
d->are_temp_buffers_filled = false;
d->poly = NULL;
d->ready_to_move = false;
do_process = true;
setProperty("no_picking", true);
setPointContainer(3,

View File

@ -879,8 +879,13 @@ protected:
if(gen_event->type() == QEvent::Wheel)
{
QWheelEvent *event = static_cast<QWheelEvent*>(gen_event);
int steps = event->delta() / 120;
int steps = event->angleDelta().y()/120;
if(do_process)
{
expand_or_reduce(steps);
do_process = false;
QTimer::singleShot(0,this, [this](){do_process = true;});
}
return true;
}
return false;
@ -997,6 +1002,7 @@ protected:
Scene_facegraph_item_k_ring_selection k_ring_selector;
// action state
bool is_insert;
bool do_process;
public:
// selection

View File

@ -621,12 +621,24 @@ void Viewer::keyPressEvent(QKeyEvent* e)
}
else if(e->key() == Qt::Key_M) {
d->macro_mode = ! d->macro_mode;
switch(camera()->type()){
case CGAL::qglviewer::Camera::PERSPECTIVE:
if(d->macro_mode) {
camera()->setZNearCoefficient(0.0005f);
} else {
camera()->setZNearCoefficient(0.005f);
}
break;
case CGAL::qglviewer::Camera::ORTHOGRAPHIC:
if(d->macro_mode) {
camera()->setOrthoZNear(-0.5f);
} else {
camera()->setOrthoZNear(0.0f);
}
break;
default:
break;
}
this->displayMessage(tr("Macro mode: %1").
arg(d->macro_mode ? tr("on") : tr("off")));
@ -1356,10 +1368,30 @@ void Viewer::wheelEvent(QWheelEvent* e)
double delta = e->delta();
if(delta>0)
{
switch(camera()->type())
{
case CGAL::qglviewer::Camera::ORTHOGRAPHIC:
camera()->setOrthoZNear(camera()->orthoZNear() + 0.01);
break;
case CGAL::qglviewer::Camera::PERSPECTIVE:
camera()->setZNearCoefficient(camera()->zNearCoefficient() * 1.01);
break;
default:
break;
}
}
else
switch(camera()->type())
{
case CGAL::qglviewer::Camera::ORTHOGRAPHIC:
camera()->setOrthoZNear(camera()->orthoZNear() - 0.01);
break;
case CGAL::qglviewer::Camera::PERSPECTIVE:
camera()->setZNearCoefficient(camera()->zNearCoefficient() / 1.01);
break;
default:
break;
}
update();
}
else

View File

@ -0,0 +1,657 @@
// Copyright (c) 2019 Geometry Factory
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser 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$
// SPDX-License-Identifier: LGPL-3.0+
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_IO_READ_3MF_H
#define CGAL_IO_READ_3MF_H
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include <CGAL/IO/Color.h>
#include <CGAL/Kernel_traits.h>
#include <Model/COM/NMR_DLLInterfaces.h>
namespace CGAL{
namespace transform_nmr_internal{
NMR::MODELTRANSFORM initMatrix()
{
NMR::MODELTRANSFORM mMatrix;
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
mMatrix.m_fFields[j][i] = (i == j) ? 1.0f : 0.0f;
}
}
return mMatrix;
}
}//end transform_nmr_internal
template<typename PointRange,
typename PolygonRange,
typename ColorRange>
bool extract_soups (NMR::PLib3MFModelMeshObject *pMeshObject,
const NMR::MODELTRANSFORM& transform,
PointRange& points,
PolygonRange& triangles,
ColorRange& colors,
std::string& name) {
typedef typename PointRange::value_type Point_3;
typedef typename PolygonRange::value_type Polygon;
typedef typename Kernel_traits<Point_3>::Kernel Kernel;
HRESULT hResult;
DWORD nNeededChars;
std::vector<char> pBuffer;
// Retrieve Mesh Name Length
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, NULL, 0, &nNeededChars);
if (hResult != LIB3MF_OK)
{
std::cerr<<"Error during name extraction.";
return false;
}
// Retrieve Mesh Name
if (nNeededChars > 0) {
pBuffer.resize(nNeededChars + 1);
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, &pBuffer[0], nNeededChars + 1, NULL);
pBuffer[nNeededChars] = 0;
std::string temp(&pBuffer[0]);
if(temp.find("_cgal_pc") != std::string::npos
|| temp.find("_cgal_pl")!= std::string::npos) //ignore point clouds and polylines
{
return false;
}
name = std::string(&pBuffer[0]);
}
else
name = std::string("Unknown Mesh");
typename Kernel::Aff_transformation_3 t(
transform.m_fFields[0][0], transform.m_fFields[0][1], transform.m_fFields[0][2], transform.m_fFields[0][3],
transform.m_fFields[1][0], transform.m_fFields[1][1], transform.m_fFields[1][2], transform.m_fFields[1][3],
transform.m_fFields[2][0], transform.m_fFields[2][1], transform.m_fFields[2][2], transform.m_fFields[2][3]
);
NMR::PLib3MFPropertyHandler * pPropertyHandler;
hResult = NMR::lib3mf_meshobject_createpropertyhandler(pMeshObject, &pPropertyHandler);
if (hResult != LIB3MF_OK) {
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
std::cerr << "could not create property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(pMeshObject);
return false;
}
for(DWORD vid = 0; vid < points.size(); ++vid)
{
NMR::MODELMESHVERTEX pVertex;
NMR::lib3mf_meshobject_getvertex(pMeshObject, vid, &pVertex);
Point_3 p(pVertex.m_fPosition[0],
pVertex.m_fPosition[1],
pVertex.m_fPosition[2]);
points[vid] = t.transform(p);
}
for(DWORD pid = 0; pid < triangles.size(); ++pid)
{
NMR::MODELMESHTRIANGLE pTriangle;
NMR::lib3mf_meshobject_gettriangle(pMeshObject, pid, &pTriangle);
Polygon triangle(3);
for(DWORD i = 0; i< 3; ++i)
triangle[i] = pTriangle.m_nIndices[i];
triangles[pid] = triangle;
NMR::MODELMESH_TRIANGLECOLOR_SRGB pColor;
NMR::lib3mf_propertyhandler_getcolor(pPropertyHandler, pid, &pColor);
NMR::MODELMESHCOLOR_SRGB mColor = pColor.m_Colors[0];
colors[pid]=CGAL::Color(mColor.m_Red, mColor.m_Green,
mColor.m_Blue, mColor.m_Alpha);
}
return true;
}
template<typename PointRange,
typename PolygonRange,
typename ColorRange>
bool extract_polylines (NMR::PLib3MFModelMeshObject *pMeshObject,
const NMR::MODELTRANSFORM& ,
PointRange& points,
PolygonRange&,
ColorRange& colors,
std::string& name) {
typedef typename PointRange::value_type Point_3;
HRESULT hResult;
DWORD nNeededChars;
std::vector<char> pBuffer;
// Retrieve Mesh Name Length
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, NULL, 0, &nNeededChars);
if (hResult != LIB3MF_OK)
{
points.resize(0);
std::cerr<<"Error during name extraction.";
return false;
}
// Retrieve Mesh Name
if (nNeededChars > 0) {
pBuffer.resize(nNeededChars + 1);
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, &pBuffer[0], nNeededChars + 1, NULL);
pBuffer[nNeededChars] = 0;
std::string temp(&pBuffer[0]);
if(temp.find("_cgal_pl")== std::string::npos) //ignore not polylines
{
points.resize(0);
return false;
}
name = std::string(&pBuffer[0]);
}
else
{
points.resize(0);
return false;
}
NMR::PLib3MFPropertyHandler * pPropertyHandler;
hResult = NMR::lib3mf_meshobject_createpropertyhandler(pMeshObject, &pPropertyHandler);
if (hResult != LIB3MF_OK) {
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
std::cerr << "could not create property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(pMeshObject);
return false;
}
points.resize(points.size()-3);//ignore dummy_vertices
for(DWORD vid = 0; vid < points.size(); ++vid)
{
NMR::MODELMESHVERTEX pVertex;
NMR::lib3mf_meshobject_getvertex(pMeshObject, vid+3, &pVertex);
points[vid] =
Point_3(pVertex.m_fPosition[0],
pVertex.m_fPosition[1],
pVertex.m_fPosition[2]);
}
NMR::MODELMESH_TRIANGLECOLOR_SRGB pColor;
NMR::lib3mf_propertyhandler_getcolor(pPropertyHandler, 0, &pColor);//get color of the dummy triangle
NMR::MODELMESHCOLOR_SRGB mColor = pColor.m_Colors[0];
colors[0]=CGAL::Color(mColor.m_Red, mColor.m_Green,
mColor.m_Blue, mColor.m_Alpha);
return true;
}
template<typename PointRange,
typename PolygonRange,
typename ColorRange>
bool extract_point_clouds (NMR::PLib3MFModelMeshObject *pMeshObject,
const NMR::MODELTRANSFORM&,
PointRange& points,
PolygonRange&,
ColorRange& colors,
std::string& name) {
typedef typename PointRange::value_type Point_3;
HRESULT hResult;
DWORD nNeededChars;
std::vector<char> pBuffer;
// Retrieve Mesh Name Length
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, NULL, 0, &nNeededChars);
if (hResult != LIB3MF_OK)
{
std::cerr<<"Error during name extraction.";
points.resize(0);
return false;
}
// Retrieve Mesh Name
if (nNeededChars > 0) {
pBuffer.resize(nNeededChars + 1);
hResult = NMR::lib3mf_object_getnameutf8(pMeshObject, &pBuffer[0], nNeededChars + 1, NULL);
pBuffer[nNeededChars] = 0;
std::string temp(&pBuffer[0]);
if(temp.find("_cgal_pc")== std::string::npos) //ignore not point_cloud
{
points.resize(0);
return false;
}
name = std::string(&pBuffer[0]);
}
else{
points.resize(0);
return false;
}
NMR::PLib3MFPropertyHandler * pPropertyHandler;
hResult = NMR::lib3mf_meshobject_createpropertyhandler(pMeshObject, &pPropertyHandler);
if (hResult != LIB3MF_OK) {
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
std::cerr << "could not create property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(pMeshObject);
return -1;
}
points.resize(points.size()-3);//ignore dummy_vertices
for(DWORD vid = 0; vid < points.size(); ++vid)
{
NMR::MODELMESHVERTEX pVertex;
NMR::lib3mf_meshobject_getvertex(pMeshObject, vid+3, &pVertex);
points[vid] =
Point_3(pVertex.m_fPosition[0],
pVertex.m_fPosition[1],
pVertex.m_fPosition[2]);
}
NMR::MODELMESH_TRIANGLECOLOR_SRGB pColor;
NMR::lib3mf_propertyhandler_getcolor(pPropertyHandler, 0, &pColor);//get color of the dummy triangle
NMR::MODELMESHCOLOR_SRGB mColor = pColor.m_Colors[0];
colors[0]=CGAL::Color(mColor.m_Red, mColor.m_Green,
mColor.m_Blue, mColor.m_Alpha);
return true;
}
template<typename PointRanges, typename PolygonRanges, typename ColorRanges,
typename PointRange, typename PolygonRange, typename ColorRange>
int read_from_3mf(const std::string& file_name, PointRanges& all_points,
PolygonRanges& all_polygons, ColorRanges& all_colors,
std::vector<std::string>& names,
std::function<bool(NMR::PLib3MFModelMeshObject*,
const NMR::MODELTRANSFORM&,
PointRange&,
PolygonRange&,
ColorRange&,
std::string&)> func
)
{
DWORD nInterfaceVersionMajor, nInterfaceVersionMinor, nInterfaceVersionMicro, nbVertices, nbPolygons;
HRESULT hResult;
NMR::PLib3MFModel * pModel;
NMR::PLib3MFModelReader * pReader;
// Extract Extension of filename
std::string sReaderName("3mf");
hResult = NMR::lib3mf_getinterfaceversion(&nInterfaceVersionMajor, &nInterfaceVersionMinor, &nInterfaceVersionMicro);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get 3MF Library version: " << std::hex << hResult << std::endl;
return -1;
}
// Create Model Instance
hResult = NMR::lib3mf_createmodel(&pModel);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create model: " << std::hex << hResult << std::endl;
return -1;
}
// Create Model Reader
hResult = NMR::lib3mf_model_queryreader(pModel, sReaderName.c_str(), &pReader);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create model reader: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pModel);
return -1;
}
// Import Model from File
hResult = NMR::lib3mf_reader_readfromfileutf8(pReader, file_name.c_str());
if (hResult != LIB3MF_OK) {
std::cerr << "could not parse file: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pReader);
NMR::lib3mf_release(pModel);
return -1;
}
// Release Model Reader
NMR::lib3mf_release(pReader);
//Iterate Model
BOOL pbHasNext;
NMR::PLib3MFModelResourceIterator * pResourceIterator;
hResult = NMR::lib3mf_model_getobjects(pModel, &pResourceIterator);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get object: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pModel);
return -1;
}
hResult = NMR::lib3mf_resourceiterator_movenext(pResourceIterator, &pbHasNext);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get next object: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pResourceIterator);
NMR::lib3mf_release(pModel);
return -1;
}
/**************************************************
**** Iterate Resources To Find Meshes ************
**************************************************/
while (pbHasNext) {
NMR::PLib3MFModelResource * pResource;
NMR::PLib3MFModelMeshObject * pMeshObject;
NMR::PLib3MFModelComponentsObject * pComponentsObject;
NMR::ModelResourceID ResourceID;
// get current resource
hResult = NMR::lib3mf_resourceiterator_getcurrent(pResourceIterator, &pResource);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get resource: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pResourceIterator);
NMR::lib3mf_release(pModel);
return -1;
}
// get resource ID
hResult = NMR::lib3mf_resource_getresourceid(pResource, &ResourceID);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get resource id: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pResource);
NMR::lib3mf_release(pResourceIterator);
NMR::lib3mf_release(pModel);
return -1;
}
// Query mesh interface
BOOL bIsMeshObject;
hResult = NMR::lib3mf_object_ismeshobject(pResource, &bIsMeshObject);
if (hResult == LIB3MF_OK)
{
if(bIsMeshObject) {
//skip it. Only get it through the components and buildItems.
}
else {
BOOL bIsComponentsObject;
hResult = NMR::lib3mf_object_iscomponentsobject(pResource, &bIsComponentsObject);
if ((hResult == LIB3MF_OK) && (bIsComponentsObject)) {
pComponentsObject = (NMR::PLib3MFModelComponentsObject*)pResource;
DWORD nComponentCount;
hResult = NMR::lib3mf_componentsobject_getcomponentcount(pComponentsObject, &nComponentCount);
if (hResult != LIB3MF_OK)
return -1;
//for each component
DWORD nIndex;
for (nIndex = 0; nIndex < nComponentCount; ++nIndex) {
NMR::PLib3MFModelResource * compResource;
NMR::PLib3MFModelComponent * pComponent;
hResult = NMR::lib3mf_componentsobject_getcomponent(pComponentsObject, nIndex, &pComponent);
if (hResult != LIB3MF_OK) {
return -1;
}
hResult = NMR::lib3mf_component_getobjectresource(pComponent, &compResource);
if (hResult != LIB3MF_OK) {
NMR::lib3mf_release(pComponent);
return -1;
}
hResult = NMR::lib3mf_object_ismeshobject(compResource, &bIsMeshObject);
if (hResult == LIB3MF_OK)
{
if(bIsMeshObject) {
BOOL bHasTransform;
NMR::MODELTRANSFORM Transform;
hResult = NMR::lib3mf_component_hastransform(pComponent, &bHasTransform);
if (hResult != LIB3MF_OK) {
NMR::lib3mf_release(pComponent);
return -1;
}
if (bHasTransform) {
// Retrieve Transform
hResult = NMR::lib3mf_component_gettransform(pComponent, &Transform);
if (hResult != LIB3MF_OK) {
NMR::lib3mf_release(pComponent);
return -1;
}
}
else {
Transform = transform_nmr_internal::initMatrix();
}
pMeshObject = compResource;
NMR::lib3mf_meshobject_getvertexcount(pMeshObject, &nbVertices);
NMR::lib3mf_meshobject_gettrianglecount(pMeshObject, &nbPolygons);
PointRange points (nbVertices);
PolygonRange triangles(nbPolygons);
ColorRange colors(nbPolygons);
std::string name;
if(func(pMeshObject, Transform, points, triangles, colors, name)){
all_points.push_back(points);
all_polygons.push_back(triangles);
all_colors.push_back(colors);
names.push_back(name);
}
}
}
}
//end component
}
}
}
// free instances
NMR::lib3mf_release(pResource);
hResult = NMR::lib3mf_resourceiterator_movenext(pResourceIterator, &pbHasNext);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get next object: " << std::hex << hResult << std::endl;
return -1;
}
}
/********************************************************
**** Iterate Build items To Find Transformed Meshes ****
********************************************************/
// Iterate through all the Build items
NMR::PLib3MFModelBuildItemIterator * pBuildItemIterator;
hResult = NMR::lib3mf_model_getbuilditems(pModel, &pBuildItemIterator);
if (hResult != LIB3MF_OK) {
std::cout << "could not get build items: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
return -1;
}
hResult = NMR::lib3mf_builditemiterator_movenext(pBuildItemIterator, &pbHasNext);
if (hResult != LIB3MF_OK) {
std::cout << "could not get next build item: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
return -1;
}
while (pbHasNext) {
NMR::PLib3MFModelMeshObject * pMeshObject;
NMR::MODELTRANSFORM Transform;
NMR::PLib3MFModelBuildItem * pBuildItem;
// Retrieve Build Item
hResult = NMR::lib3mf_builditemiterator_getcurrent(pBuildItemIterator, &pBuildItem);
if (hResult != LIB3MF_OK) {
std::cout << "could not get build item: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
return -1;
}
// Retrieve Resource
NMR::PLib3MFModelObjectResource * pObjectResource;
hResult = NMR::lib3mf_builditem_getobjectresource(pBuildItem, &pObjectResource);
if (hResult != LIB3MF_OK) {
std::cout << "could not get build item resource: " << std::hex << hResult << std::endl;
NMR::lib3mf_release(pBuildItem);
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
return -1;
}
BOOL bIsMeshObject;
hResult = NMR::lib3mf_object_ismeshobject(pObjectResource, &bIsMeshObject);
if (hResult == LIB3MF_OK)
{
if(bIsMeshObject) {
pMeshObject = pObjectResource;
NMR::lib3mf_meshobject_getvertexcount(pMeshObject, &nbVertices);
NMR::lib3mf_meshobject_gettrianglecount(pMeshObject, &nbPolygons);
PointRange points (nbVertices);
PolygonRange triangles(nbPolygons);
ColorRange colors(nbPolygons);
std::string name;
// Check Object Transform
BOOL bHasTransform;
hResult = NMR::lib3mf_builditem_hasobjecttransform(pBuildItem, &bHasTransform);
if (hResult != LIB3MF_OK) {
NMR::lib3mf_release(pBuildItem);
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
std::cerr << "could not check object transform: " << std::hex << hResult << std::endl;
return -1;
}
if (bHasTransform) {
// Retrieve Transform
hResult = NMR::lib3mf_builditem_getobjecttransform(pBuildItem, &Transform);
if (hResult != LIB3MF_OK) {
NMR::lib3mf_release(pBuildItem);
NMR::lib3mf_release(pBuildItemIterator);
NMR::lib3mf_release(pModel);
std::cerr << "could not get object transform: " << std::hex << hResult << std::endl;
return -1;
}
}
else {
Transform = transform_nmr_internal::initMatrix();
}
if(func(pMeshObject, Transform, points, triangles, colors, name)){
all_points.push_back(points);
all_polygons.push_back(triangles);
all_colors.push_back(colors);
names.push_back(name);
}
}
}
// Release Object Resource ID
NMR::lib3mf_release(pObjectResource);
// Release Build Item
NMR::lib3mf_release(pBuildItem);
// Move to next Item
hResult = NMR::lib3mf_builditemiterator_movenext(pBuildItemIterator, &pbHasNext);
if (hResult != LIB3MF_OK) {
std::cerr << "could not get next build item: " << std::hex << hResult << std::endl;
return -1;
}
}
// Release Build Item Iterator
NMR::lib3mf_release(pBuildItemIterator);
return all_points.size();
}
/*!
* \brief extracts ranges of points and triangles from a 3mf file.
* \tparam PointRanges a model of the concepts `RandomAccessContainer` and
* `BackInsertionSequence` whose `value type` is
* a model of the concepts `RandomAccessContainer` and `BackInsertionSequence`
* whose `value type` is the point type.
* \tparam PolygonRanges a model of the concept `RandomAccessContainer` whose
* `value_type` is a model of the concept `RandomAccessContainer`
* whose `value_type` is a model of the concept `RandomAccessContainer` whose
* `value_type` is std::size_t.
* \tparam ColorRanges a model of the concepts `RandomAccessContainer` and
* `BackInsertionSequence` whose `value type` is
* a model of the concepts `RandomAccessContainer` and `BackInsertionSequence`
* whose `value type` is `CGAL::Color`.
* \param file_name the name of the 3mf file to read.
* \param all_points a `PointRanges` that will contain the points of the meshes
* in `file_name`.
* Each of these meshes will add a range of its points.
* \param all_polygons a `PolygonRanges` that will contain the triangles of the
* meshes in `file_name`.
* Each of these meshes will add a range of its triangles. A `triangle` of
* `all_polygons[i]` contains the indices of its points in `all_points[i]`.
* \param all_colors will contain the color of each triangle for each soup.
* \param names will contain the name of each mesh in `file_name` if any.
* If the i'th mesh has no name, it will be called "Unknown Mesh" in names.
* \return the number of soups read.
*/
template<typename PointRanges, typename PolygonRanges, typename ColorRanges>
int read_triangle_soups_from_3mf(const std::string& file_name, PointRanges& all_points,
PolygonRanges& all_polygons, ColorRanges& all_colors,
std::vector<std::string>& names
)
{
typedef typename PointRanges::value_type PointRange;
typedef typename PolygonRanges::value_type PolygonRange;
typedef typename ColorRanges::value_type ColorRange;
return read_from_3mf<PointRanges,PolygonRanges,ColorRanges,
PointRange, PolygonRange, ColorRange>
(file_name, all_points, all_polygons,
all_colors, names, extract_soups<PointRange, PolygonRange, ColorRange>);
}
template<typename PointRanges, typename ColorRanges>
int read_polylines_from_3mf(const std::string& file_name,
PointRanges& all_points,
ColorRanges& all_colors,
std::vector<std::string>& names
)
{
typedef typename PointRanges::value_type PointRange;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef std::vector<CGAL::Color> ColorRange;
std::vector<PolygonRange> all_polygons;
return read_from_3mf<PointRanges,std::vector<PolygonRange>,
std::vector<ColorRange>, PointRange, PolygonRange, ColorRange>
(file_name, all_points, all_polygons, all_colors, names,
extract_polylines<PointRange, PolygonRange, ColorRange>);
}
template<typename PointRanges, typename ColorRanges>
int read_point_clouds_from_3mf(const std::string& file_name,
PointRanges& all_points,
ColorRanges& all_colors,
std::vector<std::string>& names
)
{
typedef typename PointRanges::value_type PointRange;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef std::vector<CGAL::Color> ColorRange;
std::vector<PolygonRange> all_polygons;
return read_from_3mf<PointRanges,std::vector<PolygonRange>,
std::vector<ColorRange>, PointRange, PolygonRange, ColorRange>
(file_name, all_points, all_polygons, all_colors, names,
extract_point_clouds<PointRange, PolygonRange, ColorRange>);
}
}//end CGAL
#endif // CGAL_IO_READ_3MF_H

View File

@ -0,0 +1,468 @@
// Copyright (c) 2019 Geometry Factory
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser 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$
// SPDX-License-Identifier: LGPL-3.0+
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_IO_WRITE_3MF_H
#define CGAL_IO_WRITE_3MF_H
#include <iostream>
#include <vector>
#include <string>
#include <CGAL/IO/Color.h>
#include <Model/COM/NMR_DLLInterfaces.h>
namespace CGAL{
namespace tmf_internal{
// Utility functions to create vertices and triangles
NMR::MODELMESHVERTEX fnCreateVertex(float x, float y, float z)
{
NMR::MODELMESHVERTEX result;
result.m_fPosition[0] = x;
result.m_fPosition[1] = y;
result.m_fPosition[2] = z;
return result;
}
NMR::MODELMESHTRIANGLE fnCreateTriangle(int v0, int v1, int v2)
{
NMR::MODELMESHTRIANGLE result;
result.m_nIndices[0] = v0;
result.m_nIndices[1] = v1;
result.m_nIndices[2] = v2;
return result;
}
NMR::MODELMESHCOLOR_SRGB fnCreateColor(unsigned char red, unsigned char green,
unsigned char blue, unsigned char alpha=255)
{
NMR::MODELMESHCOLOR_SRGB result;
result.m_Red = red;
result.m_Green = green;
result.m_Blue = blue;
result.m_Alpha = alpha;
return result;
}
} //end internal
bool add_build_item(NMR::PLib3MFModel * pModel,
NMR::PLib3MFModelMeshObject* pMeshObject)
{
HRESULT hResult;
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
// Add Build Item for Mesh
NMR::PLib3MFModelBuildItem * pBuildItem;
hResult = NMR::lib3mf_model_addbuilditem(pModel, pMeshObject, NULL, &pBuildItem);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create build item: "
<< std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage
<< ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
// Release BuildItem and Mesh
NMR::lib3mf_release(pMeshObject);
NMR::lib3mf_release(pBuildItem);
return true;
}
bool export_model_to_file(const std::string& file_name,
NMR::PLib3MFModel * pModel)
{
HRESULT hResult;
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
// Output mesh as 3MF
// Create Model Writer for 3MF
NMR::PLib3MFModelWriter * p3MFWriter;
hResult = NMR::lib3mf_model_querywriter(pModel, "3mf", &p3MFWriter);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create model reader: "
<< std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage
<< ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(pModel);
return false;
}
// Export Model into File
hResult = NMR::lib3mf_writer_writetofileutf8(p3MFWriter, file_name.c_str());
if (hResult != LIB3MF_OK) {
std::cerr << "could not write file: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(p3MFWriter, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": "
<< pszErrorMessage << std::endl;
NMR::lib3mf_release(pModel);
NMR::lib3mf_release(p3MFWriter);
return false;
}
// Release Model Writer
NMR::lib3mf_release(p3MFWriter);
return true;
}
template<typename PointRange, typename PolygonRange, typename ColorRange>
bool write_mesh_to_model( const PointRange& points,
const PolygonRange& polygons,
const ColorRange& colors,
const std::string& name,
NMR::PLib3MFModelMeshObject** pMeshObject,
NMR::PLib3MFModel * pModel
)
{
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
HRESULT hResult;
// Create mesh structure
std::vector<NMR::MODELMESHVERTEX> pVertices;
std::vector<NMR::MODELMESHTRIANGLE> pTriangles;
// Create Mesh Object
hResult = NMR::lib3mf_model_addmeshobject(pModel, pMeshObject);
if (hResult != LIB3MF_OK) {
std::cerr << "could not add mesh object: " << std::hex
<< hResult << std::endl;
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": "
<< pszErrorMessage << std::endl;
NMR::lib3mf_release(pModel);
return false;
}
for( auto point : points)
{
pVertices.push_back(tmf_internal::fnCreateVertex(point.x(), point.y(), point.z()));
}
for( auto triangle : polygons)
{
pTriangles.push_back(tmf_internal::fnCreateTriangle(triangle[0], triangle[1], triangle[2]));
}
hResult = NMR::lib3mf_meshobject_setgeometry(*pMeshObject, pVertices.data(),
pVertices.size(), pTriangles.data(),
pTriangles.size());
if (hResult != LIB3MF_OK) {
std::cerr << "could not set mesh geometry: "
<< std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage
<< ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
// Create color entries
NMR::PLib3MFPropertyHandler * pPropertyHandler;
hResult = NMR::lib3mf_meshobject_createpropertyhandler(*pMeshObject, &pPropertyHandler);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
// define colors
for(std::size_t pid = 0; pid<colors.size(); ++pid)
{
NMR::MODELMESHCOLOR_SRGB sColor = tmf_internal::fnCreateColor (colors[pid].red(),
colors[pid].green(),
colors[pid].blue(),
colors[pid].alpha());
// One-colored Triangles
NMR::lib3mf_propertyhandler_setsinglecolor(pPropertyHandler, pid, &sColor);
}
// make sure to define a default property
NMR::PLib3MFDefaultPropertyHandler * pDefaultPropertyHandler;
hResult = NMR::lib3mf_object_createdefaultpropertyhandler(*pMeshObject, &pDefaultPropertyHandler);
if (hResult != LIB3MF_OK) {
std::cerr<< "could not create default property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr<< "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
NMR::MODELMESHCOLOR_SRGB default_color = tmf_internal::fnCreateColor(0,0,0,0);
NMR::lib3mf_defaultpropertyhandler_setcolor(pDefaultPropertyHandler,
&default_color);
// release default property handler
NMR::lib3mf_release(pDefaultPropertyHandler);
// Set name
hResult = NMR::lib3mf_object_setnameutf8(*pMeshObject, name.c_str());
if (hResult != LIB3MF_OK) {
std::cerr << "could not set object name: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
//add a builditem to finish
return add_build_item(pModel, *pMeshObject);
}
//remember that it adds 3 demmy vertices in the beginning, and a dummy triangle to be ignored.
template<typename PointRange, typename Color>
bool write_points(const PointRange& points,
const Color& color,
const std::string& name,
NMR::PLib3MFModelMeshObject** pMeshObject,
NMR::PLib3MFModel * pModel
)
{
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
HRESULT hResult;
// Create mesh structure
std::vector<NMR::MODELMESHVERTEX> pVertices;
// Create Mesh Object
hResult = NMR::lib3mf_model_addmeshobject(pModel, pMeshObject);
if (hResult != LIB3MF_OK) {
std::cerr << "could not add mesh object: " << std::hex
<< hResult << std::endl;
NMR::lib3mf_getlasterror(pModel, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": "
<< pszErrorMessage << std::endl;
NMR::lib3mf_release(pModel);
return false;
}
//add 3 demmy vertices to be sure to have a valid triangle and accept point sets with less than 3 vertices.
for(int i = 0; i< 3; ++i)
pVertices.push_back(tmf_internal::fnCreateVertex(0,0,0));
for( auto point : points)
{
pVertices.push_back(tmf_internal::fnCreateVertex(point.x(), point.y(), point.z()));
}
NMR::MODELMESHTRIANGLE dummy_triangle = tmf_internal::fnCreateTriangle(0,1,2); //add a triangle to avoid lib error.
hResult = NMR::lib3mf_meshobject_setgeometry(*pMeshObject, pVertices.data(),
pVertices.size(), &dummy_triangle, 1);
if (hResult != LIB3MF_OK) {
std::cerr << "could not set mesh geometry: "
<< std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage
<< ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
// Create color entries
NMR::PLib3MFPropertyHandler * pPropertyHandler;
hResult = NMR::lib3mf_meshobject_createpropertyhandler(*pMeshObject, &pPropertyHandler);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
// define colors
NMR::MODELMESHCOLOR_SRGB sColor = tmf_internal::fnCreateColor (color.red(),
color.green(),
color.blue(),
color.alpha());
// One-colored Triangles
NMR::lib3mf_propertyhandler_setsinglecolor(pPropertyHandler, 0, &sColor);
// make sure to define a default property
NMR::PLib3MFDefaultPropertyHandler * pDefaultPropertyHandler;
hResult = NMR::lib3mf_object_createdefaultpropertyhandler(*pMeshObject, &pDefaultPropertyHandler);
if (hResult != LIB3MF_OK) {
std::cerr<< "could not create default property handler: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr<< "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
NMR::MODELMESHCOLOR_SRGB default_color = tmf_internal::fnCreateColor(0,0,0,0);
NMR::lib3mf_defaultpropertyhandler_setcolor(pDefaultPropertyHandler,
&default_color);
// release default property handler
NMR::lib3mf_release(pDefaultPropertyHandler);
// Set name
hResult = NMR::lib3mf_object_setnameutf8(*pMeshObject, name.c_str());
if (hResult != LIB3MF_OK) {
std::cerr << "could not set object name: " << std::hex << hResult << std::endl;
NMR::lib3mf_getlasterror(*pMeshObject, &nErrorMessage, &pszErrorMessage);
std::cerr << "error #" << std::hex << nErrorMessage << ": " << pszErrorMessage << std::endl;
NMR::lib3mf_release(*pMeshObject);
NMR::lib3mf_release(pModel);
return false;
}
return add_build_item(pModel, *pMeshObject);
}
template<typename PointRange, typename Color>
bool write_point_cloud_to_model(const PointRange& points,
const Color& color,
const std::string& name,
NMR::PLib3MFModelMeshObject** pMeshObject,
NMR::PLib3MFModel * pModel
)
{
std::string pc_name = name;
pc_name.append("_cgal_pc");
return write_points(points, color, pc_name, pMeshObject, pModel);
}
template<typename PointRange, typename Color>
bool write_polyline_to_model(const PointRange& points,
const Color& color,
const std::string& name,
NMR::PLib3MFModelMeshObject** pMeshObject,
NMR::PLib3MFModel * pModel
)
{
std::string pc_name = name;
pc_name.append("_cgal_pl");
return write_points(points, color, pc_name, pMeshObject, pModel);
}
/*!
* \brief writes the triangle soups contained in `all_points` and
* `all_polygons` into the 3mf file `file_name`.
* \tparam PointRanges a model of the concepts `RandomAccessContainer` and
* `BackInsertionSequence` whose `value type` is
* a model of the concepts `RandomAccessContainer` and `BackInsertionSequence`
* whose `value type` is the point type.
* \tparam PolygonRanges a model of the concept `RandomAccessContainer` whose
* `value_type` is a model of the concept `RandomAccessContainer`
* whose `value_type` is a model of the concept `RandomAccessContainer` whose
* `value_type` is std::size_t.
* \param file_name the name of the 3mf file to write.
* \param all_points a `PointRanges` that contains the points of the soups
* to write.
* \param all_polygons a `PolygonRanges` that contains the triangles of the
* soups in `file_name`.
* \param names will contains the name of each mesh in `file_name`.
* \return `true` if the writing is successful, `false` otherwise.
*/
template<typename PointRanges, typename PolygonRanges>
bool write_triangle_soups_to_3mf(const std::string& file_name,
const PointRanges& all_points,
const PolygonRanges& all_polygons,
const std::vector<std::string>& names)
{
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
HRESULT hResult;
// Create Model Instance
NMR::PLib3MFModel * pModel;
hResult = NMR::lib3mf_createmodel(&pModel);
if (hResult != LIB3MF_OK) {
std::cerr << "could not create model: " << std::hex << hResult << std::endl;
return false;
}
for(std::size_t id = 0; id < all_points.size(); ++id)
{
NMR::PLib3MFModelMeshObject* pMeshObject;
std::string name;
if(names.size() > id
&& ! names[id].empty())
{
name=names[id];
}
else
name = std::string("");
std::vector<CGAL::Color> colors(all_polygons[id].size());
write_mesh_to_model(all_points[id], all_polygons[id], colors, name, &pMeshObject, pModel);
}
return export_model_to_file(file_name, pModel);
}
/*!
* \brief writes the triangle meshes contained in `tms`
* into the 3mf file `file_name`.
* \tparam TriangleMeshRange a model of the concepts `RandomAccessContainer`
* and `BackInsertionSequence` whose `value type` is
* a model of the concepts `FaceListGraph` and `HalfedgeListGraph`
* that has only triangle faces.
* \param file_name the name of the 3mf file to write.
* \param tms a `TriangleMeshRange` that contains the meshes
* to write. An internal property map for `CGAL::vertex_point_t`
* must be available for each mesh.
* \param names will contains the name of each mesh in `file_name`.
* \return `true` if the writing is successful, `false` otherwise.
*/
template<typename TriangleMeshRange>
bool write_triangle_meshes_to_3mf(const std::string& file_name,
const TriangleMeshRange& tms,
const std::vector<std::string>& names)
{
typedef typename TriangleMeshRange::value_type Mesh;
typedef typename boost::property_map<Mesh, boost::vertex_point_t>::type VPMap;
typedef typename boost::property_traits<VPMap>::value_type Point_3;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef std::vector<Point_3> PointRange;
std::vector<PointRange> all_points;
std::vector<PolygonRange> all_polygons;
for(auto tm : tms)
{
PointRange points;
PolygonRange triangles;
VPMap vpm = get(boost::vertex_point, tm);
std::unordered_map<typename boost::graph_traits<Mesh>::vertex_descriptor,
std::size_t> vertex_id_map;
std::size_t i = 0;
for(auto v : vertices(tm))
{
points.push_back(get(vpm, v));
vertex_id_map[v] = i++;
}
all_points.push_back(points);
for(auto f : faces(tm))
{
Polygon triangle;
for(auto vert : CGAL::vertices_around_face(halfedge(f, tm), tm))
{
triangle.push_back(vertex_id_map[vert]);
}
triangles.push_back(triangle);
}
all_polygons.push_back(triangles);
}
return write_triangle_soups_to_3mf(file_name, all_points, all_polygons, names);
}
}//end CGAL
#endif // CGAL_IO_WRITE_3MF_H

View File

@ -7,13 +7,27 @@ project( Stream_support_Tests )
cmake_minimum_required(VERSION 3.1)
find_package(CGAL QUIET)
if ( CGAL_FOUND )
find_path(3MF_INCLUDE_DIR
NAMES Model/COM/NMR_DLLInterfaces.h
DOC "Path to lib3MF headers"
)
find_library(3MF_LIBRARIES NAMES 3MF DOC "Path to the lib3MF library")
# create a target per cppfile
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
if ( "${cppfile}" STREQUAL "test_3mf_to_sm.cpp" )
if(3MF_LIBRARIES AND 3MF_INCLUDE_DIR)
include_directories(${3MF_INCLUDE_DIR})
create_single_source_cgal_program( "${cppfile}" )
target_link_libraries(test_3mf_to_sm PRIVATE ${3MF_LIBRARIES})
else()
message(STATUS "NOTICE : This program requires the lib3MF library, and will not be compiled.")
endif()
else()
create_single_source_cgal_program( "${cppfile}" )
endif()
endforeach()
else()
@ -22,3 +36,4 @@ else()
endif()

Binary file not shown.

View File

@ -0,0 +1,179 @@
//needed by functions
#include <iostream>
#include <vector>
#include <string>
#include "Model/COM/NMR_DLLInterfaces.h"
//needed by example
#include <CGAL/boost/graph/helpers.h>
#include <fstream>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Surface_mesh/IO/3mf.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <unordered_map>
#include <CGAL/IO/read_3mf.h>
#include <CGAL/IO/write_3mf.h>
// Use NMR namespace for the interfaces
using namespace NMR;
namespace PMP = CGAL::Polygon_mesh_processing;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Mesh;
typedef std::vector<Point_3> PointRange;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef std::vector<CGAL::Color> ColorRange;
int main(int argc, char** argv)
{
const char* file_name=(argc == 2) ? argv[1] : "data/test.3mf";
std::vector<PointRange> all_points;
std::vector<PolygonRange> all_polygons;
std::vector<ColorRange> all_colors;
std::vector<std::string> names;
std::vector<Mesh> meshes;
//testing reading functions.
int nb_meshes =
CGAL::read_3mf(file_name, meshes);
if(nb_meshes <0)
return 1;
for(std::size_t i = 0; i< nb_meshes; ++i)
{
Mesh mesh = meshes[i];
std::cout<<names[i]<<" is valid: "<<mesh.is_valid()<<std::endl;
std::string outputName("output");
outputName.append(std::to_string(i));
outputName.append(".off");
std::ofstream ofs(outputName);
ofs << mesh;
ofs.close();
}
int nb_polylines =
CGAL::read_polylines_from_3mf(file_name, all_points, all_colors, names);
if(nb_polylines == 0)
std::cout<<"No polyline found."<<std::endl;
else
{
std::cout<<nb_polylines<<" polylines found, of ";
for(std::size_t i = 0; i< nb_polylines-1; ++i){
std::cout<<all_points[i].size()<<", ";
}
std::cout<<all_points.back().size()<<" points."<<std::endl;
}
all_points.clear();
all_colors.clear();
int nb_point_sets =
CGAL::read_point_clouds_from_3mf(file_name, all_points, all_colors, names);
if(nb_point_sets == 0)
std::cout<<"No point cloud found."<<std::endl;
else
{
std::cout<<nb_point_sets<<" point clouds found, of ";
for(std::size_t i = 0; i< nb_point_sets-1; ++i){
std::cout<<all_points[i].size()<<", ";
}
std::cout<<all_points.back().size()<<" points."<<std::endl;
}
// testing writing functions
Mesh sphere, tube;
CGAL::make_icosahedron<Mesh, Point_3>(sphere);
CGAL::make_regular_prism(10, tube, Point_3(0,-10,0), 10);
all_points.clear();
all_polygons.clear();
all_colors.clear();
names.clear();
PointRange points;
PolygonRange triangles;
ColorRange colors;
typedef boost::property_map<Mesh, boost::vertex_point_t>::type VPMap;
VPMap vpm = get(boost::vertex_point, sphere);
std::unordered_map<boost::graph_traits<Mesh>::vertex_descriptor,
std::size_t> vertex_id_map;
std::size_t i = 0;
for(auto v : sphere.vertices())
{
points.push_back(get(vpm, v));
vertex_id_map[v] = i++;
}
all_points.push_back(points);
for(auto f : sphere.faces())
{
Polygon triangle;
for(auto vert : CGAL::vertices_around_face(halfedge(f, sphere), sphere))
{
triangle.push_back(vertex_id_map[vert]);
}
triangles.push_back(triangle);
colors.push_back(CGAL::Color(255,0,0,255));
}
all_polygons.push_back(triangles);
all_colors.push_back(colors);
points.clear();
triangles.clear();
colors.clear();
vertex_id_map.clear();
i = 0;
vpm = get(boost::vertex_point, tube);
for(auto v : tube.vertices())
{
points.push_back(get(vpm, v));
vertex_id_map[v] = i++;
}
all_points.push_back(points);
for(auto f : tube.faces())
{
Polygon triangle;
for(auto vert : CGAL::vertices_around_face(halfedge(f, tube), tube))
{
triangle.push_back(vertex_id_map[vert]);
}
triangles.push_back(triangle);
colors.push_back(CGAL::Color(0,0,255,255));
}
all_polygons.push_back(triangles);
all_colors.push_back(colors);
names.push_back(std::string("sphere"));
names.push_back(std::string("tube"));
meshes.resize(2);
meshes[0] = sphere;
meshes[1] = tube;
CGAL::write_triangle_meshes_to_3mf("meshes.3mf", meshes, names);
//testing of point clouds
DWORD nErrorMessage;
LPCSTR pszErrorMessage;
HRESULT hResult;
NMR::PLib3MFModel * pModel;
hResult = NMR::lib3mf_createmodel(&pModel);
NMR::PLib3MFModelMeshObject* pMeshObject;
if (hResult != LIB3MF_OK) {
std::cout << "could not create model: " << std::hex << hResult << std::endl;
return false;
}
for(int i=0; i< names.size(); ++i)
{
CGAL::write_mesh_to_model(all_points[i], all_polygons[i],
all_colors[i], names[i], &pMeshObject, pModel);
}
CGAL::Color color(255,0,0);
CGAL::write_point_cloud_to_model(all_points.front(),
color, names.front(), &pMeshObject, pModel);
CGAL::export_model_to_file("micro.3mf", pModel);
//testing of polylines
CGAL::write_polyline_to_model(all_points.back(),
color, names.back(), &pMeshObject, pModel);
CGAL::export_model_to_file("micro.3mf", pModel);
std::cout<<"OK."<<std::endl;
return 0;
}

View File

@ -0,0 +1,124 @@
// Copyright (c) 2019 Geometry Factory
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser 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$
// SPDX-License-Identifier: LGPL-3.0+
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_SURFACE_MESH_IO_3MF_H
#define CGAL_SURFACE_MESH_IO_3MF_H
#include <iostream>
#include <CGAL/IO/read_3mf.h>
#include <CGAL/Surface_mesh.h>
namespace CGAL{
/*!
* Extracts the surface meshes from an input 3mf file and appends it to `output`.
*\tparam Point the Point type of the output meshes.
* \param file_name the path to the 3mf file.
* \param output a `std::vector` containing the `CGAL::Surface_mesh`s that will be filled by this function.
* \return the number of extracted meshes.
*/
template<typename Point>
int read_3mf(const std::string& file_name,
std::vector<CGAL::Surface_mesh<Point> >& output)
{
typedef std::vector<Point> PointRange;
typedef std::vector<std::size_t> Polygon;
typedef std::vector<Polygon> PolygonRange;
typedef CGAL::Surface_mesh<Point> SMesh;
typedef typename SMesh::Vertex_index Vertex_index;
typedef typename SMesh::Face_index Face_index;
std::vector<PointRange> all_points;
std::vector<PolygonRange> all_polygons;
std::vector<std::string> names;
std::vector<std::vector<CGAL::Color> > all_colors;
int result = 0;
int nb_meshes =
CGAL::read_triangle_soups_from_3mf(file_name,
all_points, all_polygons, all_colors, names);
if(nb_meshes < 0 )
{
std::cerr << "Error in reading meshes."<<std::endl;
return -1;
}
output.reserve(nb_meshes);
for(int i = 0; i< nb_meshes; ++i)
{
bool skip = false;
SMesh sm;
PolygonRange triangles = all_polygons[i];
PointRange points = all_points[i];
std::vector<CGAL::Color> colors = all_colors[i];
//Create the surface mesh from scratch
std::size_t n(points.size());
sm.reserve(n,0, triangles.size());
for(const Point& p : points)
{
sm.add_vertex(p);
}
for(Polygon& triangle : triangles)
{
std::vector<Vertex_index> face;
face.reserve(triangle.size());
for(auto index : triangle)
{
face.push_back(Vertex_index(index));
}
Face_index fi = sm.add_face(face);
if(fi == sm.null_face())
{
skip = true;
sm.clear();
break;
}
}
if(skip)
continue;
//end constructin the surface mesh from scratch
CGAL::Color first = colors.front();
bool need_pmap = false;
for(auto color : colors)
{
if (color != first)
{
need_pmap = true;
break;
}
}
if(need_pmap)
{
typename SMesh::template Property_map<Face_index, CGAL::Color> fcolor =
sm.template add_property_map<Face_index,CGAL::Color>("f:color",first).first;
for(std::size_t pid = 0; pid < colors.size(); ++pid)
{
put(fcolor, Face_index(pid), colors[pid]);//should work bc mesh is just created and shouldn't have any destroyed face.
}
}
output.push_back(sm);
++result;
}
return result;
}
}//end CGAL
#endif // CGAL_SURFACE_MESH_3MF_H

View File

@ -28,16 +28,23 @@
#include <QFileInfo>
#include <QStringList>
#include <QtPlugin>
class QMainWindow;
class Messages_interface;
namespace CGAL{
namespace Three {
class Scene_item;
class Scene_interface;
/*!
* This class provides a base for creating a new IO plugin.
*/
class Polyhedron_demo_io_plugin_interface
{
public:
//! \brief Initializes the plugin
//! This function is called in the constructor of the MainWindow.
//! Whatever initialization the plugin needs can be done here. Default
//! behavior is to do nothing.
virtual void init(){}
//!Returns the name of the plugin
//!It is used by the loading system.
virtual QString name() const = 0;
@ -58,17 +65,23 @@ public:
//! Specifies if the io_plugin is able to load an item or not.
//! This must be overriden.
virtual bool canLoad() const = 0;
//! Loads an item from a file.
virtual bool canLoad(QFileInfo fileinfo) const = 0;
//! Loads one or more item(s) from a file. `ok` is `true` if the loading
//! was successful, `false` otherwise.
//! New items will be added to the scene if `add_to_scene` is `true`.
//! You don't want that when you reload an item, for example,
//! as it will be added at some other point of the process.
//! This must be overriden.
virtual Scene_item* load(QFileInfo fileinfo) = 0;
virtual QList<Scene_item*> load(QFileInfo fileinfo, bool& ok, bool add_to_scene=true) = 0;
//!Specifies if the io_plugin can save the item or not.
//!This must be overriden.
virtual bool canSave(const Scene_item*) = 0;
//!Saves the item in the file corresponding to the path
//!Saves one or more items in the file corresponding to the path
//!contained in fileinfo. Returns false if error.
//! This must be overriden.
virtual bool save(const Scene_item*, QFileInfo fileinfo) = 0;
//! @attention When a file is successfully saved, it must be removed from the
//! list.
virtual bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& ) = 0;
//! If this returns `true`, then the loader will be chosen as default in the
//! list of available loaders when saving a file, which means it will be the
@ -83,6 +96,6 @@ public:
}
}
Q_DECLARE_INTERFACE(CGAL::Three::Polyhedron_demo_io_plugin_interface,
"com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0")
"com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.90")
#endif // POLYHEDRON_DEMO_IO_PLUGIN_INTERFACE_H

View File

@ -60,7 +60,7 @@ public :
:x(p_x), y(p_y), z(p_z),_3D(p_3D), _is_always_visible(always_visible), m_text(p_text), m_font(font), m_color(p_color)
{
QFontMetrics fm(m_font);
_width = float(fm.width(m_text));
_width = float(fm.width(m_text)+2);
_height = float(fm.height());
}
//!\brief Accessor for the string