Lab: Plugin to open .spheres.txt files (#9028)

## Summary of Changes

Added a Plugin to import .spheres.txt files with a list of spheres.

## Release Management

* Affected package(s): Lab
This commit is contained in:
Sebastien Loriot 2025-09-08 15:30:38 +02:00 committed by GitHub
commit 106f9659b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 205 additions and 5 deletions

View File

@ -35,6 +35,9 @@ target_link_libraries(off_to_nef_plugin PRIVATE scene_nef_polyhedron_item)
cgal_lab_plugin(polylines_io_plugin Polylines_io_plugin KEYWORDS Viewer Mesh_3)
target_link_libraries(polylines_io_plugin PRIVATE scene_polylines_item)
cgal_lab_plugin(spheres_io_plugin Spheres_io_plugin KEYWORDS Viewer Mesh_3)
target_link_libraries(spheres_io_plugin PRIVATE scene_basic_objects)
cgal_lab_plugin(wkt_plugin WKT_io_plugin KEYWORDS Viewer PointSetProcessing Mesh_3)
target_link_libraries(wkt_plugin PRIVATE scene_polylines_item)

View File

@ -0,0 +1,162 @@
#include "Scene_spheres_item.h"
#include <QMainWindow>
#include <CGAL/Three/CGAL_Lab_io_plugin_interface.h>
#include <CGAL/Three/CGAL_Lab_plugin_interface.h>
#include <CGAL/Three/CGAL_Lab_plugin_helper.h>
#include <CGAL/Three/Three.h>
#include <fstream>
#include <QVariant>
#include <QMessageBox>
#include <QInputDialog>
using namespace CGAL::Three;
class CGAL_Lab_spheres_io_plugin :
public QObject,
public CGAL_Lab_io_plugin_interface,
public CGAL_Lab_plugin_helper
{
Q_OBJECT
Q_INTERFACES(CGAL::Three::CGAL_Lab_plugin_interface CGAL::Three::CGAL_Lab_io_plugin_interface)
Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.PluginInterface/1.0" FILE "spheres_io_plugin.json")
Q_PLUGIN_METADATA(IID "com.geometryfactory.CGALLab.IOPluginInterface/1.90")
public:
// To silent a warning -Woverloaded-virtual
// See https://stackoverflow.com/questions/9995421/gcc-woverloaded-virtual-warnings
using CGAL_Lab_io_plugin_interface::init;
//! Configures the widget
void init(QMainWindow* mainWindow,
CGAL::Three::Scene_interface* scene_interface,
Messages_interface*) override{
//get the references
this->scene = scene_interface;
this->mw = mainWindow;
}
QString name() const override{ return "spheres_io_plugin"; }
QString nameFilters() const override{ return "Spheres files (*.spheres.txt)"; }
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*) override;
bool save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>&) override;
bool applicable(QAction* ) const override {
return false;
}
QList<QAction*> actions() const override{
return QList<QAction*>();
}
bool isDefaultLoader(const Scene_item* item) const override{
if(qobject_cast<const Scene_spheres_item*>(item))
return true;
return false;
}
};
bool CGAL_Lab_spheres_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;
}
QList<Scene_item*>
CGAL_Lab_spheres_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;
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_spheres_item* item = new Scene_spheres_item(nullptr, 0, false, false);
item->setName(fileinfo.completeBaseName());
ok = true;
if(add_to_scene)
CGAL::Three::Three::scene()->addItem(item);
return QList<Scene_item*>()<<item;
}
double x, y, z, r;
std::vector<std::array<double, 4> > spheres;
while (ifs >> x && ifs >> y && ifs >> z && ifs >> r)
spheres.push_back({x, y, z, r});
std::vector<QColor> colors;
if (true) {
colors.resize(spheres.size());
for (QColor &c : colors)
c = generate_random_color();
}
else {
colors.reserve(spheres.size());
compute_deterministic_color_map(QColor(180, 120, 130, 255), spheres.size(), std::back_inserter(colors));
}
Scene_spheres_item* item = new Scene_spheres_item(nullptr, spheres.size(), false, true);
item->setName(fileinfo.completeBaseName());
for (std::size_t i = 0;i<spheres.size();i++) {
const std::array<double, 4>& s = spheres[i];
item->add_sphere(CGAL::Epick::Sphere_3(CGAL::Epick::Point_3(s[0], s[1], s[2]), s[3] * s[3]), i, CGAL::IO::Color(colors[i].red(), colors[i].green(), colors[i].blue()));
}
std::cerr << "Number of spheres loaded: " << spheres.size() << std::endl;
item->invalidateOpenGLBuffers();
item->setRenderingMode(Gouraud);
CGAL::Three::Three::scene()->addItem(item);
item->computeElements();
return QList<Scene_item*>()<<item;
}
bool CGAL_Lab_spheres_io_plugin::canSave(const CGAL::Three::Scene_item* item)
{
return qobject_cast<const Scene_spheres_item*>(item) != 0;
}
bool CGAL_Lab_spheres_io_plugin::
save(QFileInfo fileinfo,QList<CGAL::Three::Scene_item*>& items)
{
Scene_item* item = items.front();
const Scene_spheres_item* sphere_item =
qobject_cast<const Scene_spheres_item*>(item);
if(!sphere_item)
return false;
std::ofstream out(fileinfo.filePath().toUtf8());
out.precision (std::numeric_limits<double>::digits10 + 2);
if(!out) {
std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl;
return false;
}
return false;
}
#include "Spheres_io_plugin.moc"

View File

@ -2,7 +2,9 @@
#include<fstream>
#include <CGAL/Three/Triangle_container.h>
#include <CGAL/Three/Edge_container.h>
#include <CGAL/Three/Three.h>
#include <QApplication>
#include <QMenu>
using namespace CGAL::Three;
@ -43,9 +45,7 @@ struct Scene_spheres_item_priv
model_sphere_is_up = false;
}
~Scene_spheres_item_priv()
{
}
~Scene_spheres_item_priv() {}
void pick(int &id)const;
@ -85,6 +85,15 @@ void Scene_spheres_item_priv::pick(int& id) const
id = -1;
}
if (id != -1 && spheres[id].size() == 1) {
const Sphere& sphere = spheres[id][0].first;
Three::information(QString("Selected sphere: center (%1, %2, %3) radius %4").
arg(sphere.center().x(), 0, 'g', 10).
arg(sphere.center().y(), 0, 'g', 10).
arg(sphere.center().z(), 0, 'g', 10).
arg(CGAL::approximate_sqrt(sphere.squared_radius()), 0, 'g', 10));
}
int offset = 0;
float color[4];
for(std::size_t i=0; i<spheres.size(); ++i)
@ -112,8 +121,10 @@ void Scene_spheres_item_priv::pick(int& id) const
}
}
Scene_spheres_item::Scene_spheres_item(Scene_group_item* parent, std::size_t max_index, bool planed, bool pickable)
Scene_spheres_item::Scene_spheres_item(Scene_group_item* parent, std::size_t max_index, bool planed, bool pickable) : Scene_group_item()
{
connected_alpha_slider = false;
rendering_mode = Gouraud;
setParent(parent);
d = new Scene_spheres_item_priv(planed, max_index, this, pickable);
if(pickable)
@ -173,6 +184,9 @@ void Scene_spheres_item_priv::initializeBuffers(CGAL::Three::Viewer_interface *v
void Scene_spheres_item::draw(Viewer_interface *viewer) const
{
if (renderingMode() != Gouraud || !visible())
return;
if(!isInit(viewer))
initGL(viewer);
if ( getBuffersFilled() &&
@ -201,6 +215,7 @@ void Scene_spheres_item::draw(Viewer_interface *viewer) const
}
else
{
getTriangleContainer(0)->setAlpha(alpha());
getTriangleContainer(0)->draw(viewer, false);
}
if(d->pickable && (d->spheres.size() > 1 && viewer->inDrawWithNames()))
@ -218,6 +233,9 @@ void Scene_spheres_item::draw(Viewer_interface *viewer) const
void Scene_spheres_item::drawEdges(Viewer_interface *viewer) const
{
if (renderingMode() != Wireframe || !visible())
return;
if(!isInit(viewer))
initGL(viewer);
if ( getBuffersFilled() &&
@ -295,6 +313,18 @@ void Scene_spheres_item::invalidateOpenGLBuffers()
getTriangleContainer(1)->reset_vbos(COLORS);
}
getEdgeContainer(0)->reset_vbos(NOT_INSTANCED);
compute_bbox();
}
QMenu* Scene_spheres_item::contextMenu() {
QMenu* menu = Scene_item_rendering_helper::contextMenu();
if (!connected_alpha_slider && alphaSlider() != nullptr) {
connect(alphaSlider(), &QSlider::valueChanged, [this]() {redraw(); });
connected_alpha_slider = true;
}
return menu;
}
QString

View File

@ -2,6 +2,7 @@
#define SCENE_SPHERES_ITEM_H
#include "Scene_basic_objects_config.h"
#include "create_sphere.h"
#include "Color_map.h"
#include <CGAL/Three/Scene_group_item.h>
#include <CGAL/Three/Scene_item_rendering_helper.h>
@ -24,7 +25,7 @@ struct Scene_spheres_item_priv;
* have a Scene_spheres_item child).
*/
class SCENE_BASIC_OBJECTS_EXPORT Scene_spheres_item
: public CGAL::Three::Scene_item_rendering_helper
: public CGAL::Three::Scene_group_item
{
Q_OBJECT
public:
@ -37,6 +38,7 @@ public:
~Scene_spheres_item();
Bbox bbox() const override { return _bbox; }
bool isFinite() const override{ return true; }
bool isEmpty() const override{ return false; }
Scene_item* clone() const override{return nullptr;}
@ -57,10 +59,12 @@ public:
void setColor(QColor c) override;
bool save(const std::string &file_name) const;
QMenu *contextMenu() override;
void initializeBuffers(Viewer_interface *) const override;
void computeElements() const override;
bool eventFilter(QObject *watched, QEvent *event)override;
Q_SIGNALS:
void on_color_changed();
void picked(std::size_t id) const;
@ -68,6 +72,7 @@ Q_SIGNALS:
protected:
friend struct Scene_spheres_item_priv;
Scene_spheres_item_priv* d;
bool connected_alpha_slider;
};
#endif // SCENE_SPHERES_ITEM_H