Remove QtViewer remnants
Per aothms's request on #8605: QtViewer is being superseded by the new Bonsai Viewer, so its remains are deleted here (src/qtviewer, its BUILD_QTVIEWER cmake option and add_subdirectory, and its references in ci.yml's path filter, .gitignore, the conda recipe's license table, and README's library table). src/ifcopenshell-python/ifcopenshell/geom/app.py's qtViewer3d is unrelated (pythonocc-core's own OCC.Display widget class, a name coincidence) and is untouched. Generated with the assistance of an AI coding tool.
@@ -18,7 +18,6 @@ on:
|
||||
- 'src/ifcparse/**'
|
||||
- 'src/ifcquery/**'
|
||||
- 'src/ifcwrap/**'
|
||||
- 'src/qtviewer/**'
|
||||
- 'src/svgfill/**'
|
||||
- 'src/serializers/**'
|
||||
- 'conda/**'
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
/src/examples/out/
|
||||
/src/ifcmax/out/
|
||||
/src/ifcwrap/out/
|
||||
/src/qtviewer/out/
|
||||
/src/ifctester/webapp/public/pyodide/
|
||||
|
||||
/win/BuildDepsCache*.txt
|
||||
|
||||
@@ -70,7 +70,6 @@ The IfcOpenShell C++ codebase is split into multiple interal libraries:
|
||||
| ifcjni | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcparse | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| ifcwrap | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| qtviewer | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
| serializers | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
|
||||
|
||||
[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING.LESSER "LGPL-3.0-or-later"
|
||||
|
||||
@@ -79,7 +79,6 @@ option(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF)
|
||||
option(BUILD_EXAMPLES "Build example applications." ON)
|
||||
option(BUILD_GEOMSERVER "Build IfcGeomServer executable (Open CASCADE is required)." ON)
|
||||
option(BUILD_IFCMAX "Build IfcMax, a 3ds Max plug-in, Windows-only." OFF)
|
||||
option(BUILD_QTVIEWER "Build IfcOpenShell Qt GUI Viewer" OFF) # QtViewer requires Qt6
|
||||
option(BUILD_IFCMODEL_UI "Build minimal Qt IFC model UI prototype" OFF)
|
||||
option(BUILD_BONSAIVIEWER "Build Bonsai Viewer" OFF) # Requires Qt6 + OpenGL 4.5
|
||||
option(BUILD_IFCOPENSHELL_PARSE_TESTS "Build C++ unit tests for IfcParse (fetches Catch2 v3)" OFF)
|
||||
@@ -708,10 +707,6 @@ if(BUILD_IFCPYTHON)
|
||||
add_subdirectory(../src/ifcwrap ifcwrap)
|
||||
endif()
|
||||
|
||||
if(BUILD_QTVIEWER)
|
||||
add_subdirectory(../src/qtviewer qtviewer)
|
||||
endif()
|
||||
|
||||
if(BUILD_IFCMODEL_UI)
|
||||
add_subdirectory(../src/ifcmodel-ui ifcmodel-ui)
|
||||
endif()
|
||||
|
||||
@@ -284,11 +284,6 @@ about:
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>qtviewer</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
<td>LGPL-3.0-or-later*</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>serializers</td>
|
||||
<td>Internal library for IfcOpenShell</td>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# This CITATION.cff file was generated with cffinit.
|
||||
# Visit https://bit.ly/cffinit to generate yours today!
|
||||
|
||||
cff-version: 1.2.0
|
||||
title: qtviewer
|
||||
message: >-
|
||||
If you use this software, please cite it using the
|
||||
metadata from this file.
|
||||
type: software
|
||||
authors:
|
||||
- name: IfcOpenShell contributors
|
||||
repository-code: >-
|
||||
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/qtviewer
|
||||
abstract: Internal library for IfcOpenShell
|
||||
keywords:
|
||||
- IfcOpenShell
|
||||
- IFC
|
||||
license: LGPL-3.0-or-later
|
||||
@@ -1,104 +0,0 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of IfcOpenShell. #
|
||||
# #
|
||||
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the Lesser GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3.0 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IfcOpenShell is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# Lesser GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the Lesser GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
message("Running CMakeLists.txt in /src/qtviewer")
|
||||
|
||||
# Specify the Qt version and components to use
|
||||
set(QT_VERSION 6 CACHE STRING "Qt version")
|
||||
set(QT_COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
OpenGL
|
||||
OpenGLWidgets
|
||||
Widgets
|
||||
CACHE STRING
|
||||
"Qt components"
|
||||
)
|
||||
|
||||
find_package(Qt${QT_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED PATHS ${QT_DIR})
|
||||
|
||||
if(Qt${QT_VERSION}_FOUND)
|
||||
message(STATUS "Found Qt Version: ${Qt${QT_VERSION}_VERSION}")
|
||||
endif()
|
||||
|
||||
message(STATUS "OSG_DIR: ${OSG_DIR}")
|
||||
set(OSG_COMPONENTS osgDB osgGA osgUtil osgViewer CACHE STRING "OSG components")
|
||||
|
||||
# Do not add "PATHS <path>" in find_package for OpenSceneGraph CMake config to work
|
||||
# on appleSiliconMacOS + Homebrew
|
||||
find_package(OpenSceneGraph COMPONENTS ${OSG_COMPONENTS} REQUIRED)
|
||||
|
||||
if(OPENSCENEGRAPH_FOUND)
|
||||
message(STATUS "Found OpenSceneGraph Version: ${OPENSCENEGRAPH_VERSION}")
|
||||
endif()
|
||||
|
||||
set(targetName "QtViewer")
|
||||
|
||||
# Scan for .qrc files and add to build process
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(RESOURCE_FILES resources/qt_resources.qrc resources/qt_res.rc)
|
||||
|
||||
# The MACOSX_BUNDLE_ICON_FILE variable is added to the Info.plist
|
||||
# generated by CMake. This variable contains the .icns file name,
|
||||
# without the path.
|
||||
set(MACOSX_BUNDLE_ICON_FILE ifcosLogo.icns)
|
||||
|
||||
# The following tells CMake where to find and install the file itself.
|
||||
set(app_icon_macos "resources/ifcosLogo.icns")
|
||||
set_source_files_properties(${app_icon_macos} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
|
||||
add_executable(
|
||||
${targetName}
|
||||
MessageLogger.h
|
||||
IfcViewerWidget.h
|
||||
IfcViewerWidget.cpp
|
||||
ParseIfcFile.h
|
||||
ParseIfcFile.cpp
|
||||
MainWindow.h
|
||||
MainWindow.cpp
|
||||
main.cpp
|
||||
${RESOURCE_FILES}
|
||||
${app_icon_macos}
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
${targetName}
|
||||
PROPERTIES AUTOMOC On WIN32_EXECUTABLE ON MACOSX_BUNDLE ON RESOURCE "${RESOURCE_FILES}"
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
${targetName}
|
||||
${IFCOPENSHELL_LIBRARIES}
|
||||
${OpenCASCADE_LIBRARIES}
|
||||
${OPENSCENEGRAPH_LIBRARIES}
|
||||
Qt${QT_VERSION}::Core
|
||||
Qt${QT_VERSION}::Gui
|
||||
Qt${QT_VERSION}::OpenGL
|
||||
Qt${QT_VERSION}::OpenGLWidgets
|
||||
Qt${QT_VERSION}::Widgets
|
||||
)
|
||||
|
||||
target_include_directories(${targetName} PUBLIC ${QT_DIR}/include ${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||
|
||||
get_target_property(targetIncludeDirs ${targetName} INCLUDE_DIRECTORIES)
|
||||
message(STATUS "target_include_directories: ${targetIncludeDirs}")
|
||||
|
||||
install(TARGETS ${targetName})
|
||||
ifcopenshell_deploy_qt_runtime(${targetName})
|
||||
@@ -1,202 +0,0 @@
|
||||
#include "IfcViewerWidget.h"
|
||||
#include <osg/ShapeDrawable>
|
||||
#include <osg/Material>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "MainWindow.h"
|
||||
#include "MessageLogger.h"
|
||||
#include "osg/Geode"
|
||||
#include "osg/Geometry"
|
||||
#include "osg/Group"
|
||||
#include "osg/StateSet"
|
||||
#include "osg/Vec3"
|
||||
#include "osg/ref_ptr"
|
||||
#include "osgGA/TrackballManipulator"
|
||||
|
||||
IfcViewerWidget::IfcViewerWidget(qreal dpiScale, QWidget *parent) :
|
||||
QOpenGLWidget(parent),
|
||||
m_dpiScale(dpiScale),
|
||||
m_graphicsWindow(new osgViewer::GraphicsWindowEmbedded(
|
||||
this->x(), this->y(),
|
||||
this->width(), this->height()
|
||||
)),
|
||||
m_viewer(new osgViewer::Viewer),
|
||||
root(new osg::Group)
|
||||
{
|
||||
m_clearColor = osg::Vec4(0.8, 0.8, 0.8, 1.0);
|
||||
|
||||
//debug - override
|
||||
//std::string filePath = "/Users/onizudb/Downloads/IFC/wallAtOrigin.ifc";
|
||||
//std::string filePath = "/Users/onizudb/Downloads/IFC/FromAC_IFC4ref.ifc";
|
||||
//this->loadFile(filePath);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::initializeGL()
|
||||
{
|
||||
MessageLogger::log("Press `Cmd/Ctrl + o` or use the File menu to open an IFC file");
|
||||
|
||||
// Set up the rendering context, load shaders and other resources, etc.:
|
||||
|
||||
// Set the root node as the scene data for the viewer
|
||||
m_viewer->setSceneData(root);
|
||||
|
||||
osg::StateSet* state = root->getOrCreateStateSet();
|
||||
state->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
||||
|
||||
m_viewer->getCamera()->setViewport(0, 0, this->width(), this->height());
|
||||
m_viewer->getCamera()->setClearColor(m_clearColor);
|
||||
m_viewer->getCamera()->setGraphicsContext(m_graphicsWindow);
|
||||
|
||||
// set camera manipulator, etc.
|
||||
setupViewController();
|
||||
|
||||
m_viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||
m_viewer->realize();
|
||||
}
|
||||
|
||||
void IfcViewerWidget::resizeGL(int w, int h)
|
||||
{
|
||||
this->getEventQueue()->windowResize(this->x() * m_dpiScale, this->y() * m_dpiScale, w * m_dpiScale, h * m_dpiScale);
|
||||
m_graphicsWindow->resized(this->x() * m_dpiScale, this->y() * m_dpiScale, w * m_dpiScale, h * m_dpiScale);
|
||||
|
||||
m_viewer->getCamera()->setViewport(0, 0, this->width() * m_dpiScale, this->height() * m_dpiScale);
|
||||
|
||||
const float aspectRatio = static_cast<float>(w) / static_cast<float>(h);
|
||||
m_viewer->getCamera()->setProjectionMatrixAsPerspective(30.0f, aspectRatio, 1.0f, 1000.0f);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::paintGL()
|
||||
{
|
||||
// Render OSG scene
|
||||
m_viewer->frame();
|
||||
}
|
||||
|
||||
void IfcViewerWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
this->getEventQueue()->mouseMotion(event->position().x() * m_dpiScale, event->position().y() * m_dpiScale);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
unsigned int button = this->getMouseButtonNum(event);
|
||||
this->getEventQueue()->mouseButtonPress(event->position().x() * m_dpiScale, event->position().y() * m_dpiScale, button);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
unsigned int button = this->getMouseButtonNum(event);
|
||||
this->getEventQueue()->mouseButtonRelease(event->position().x() * m_dpiScale, event->position().y() * m_dpiScale, button);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
int delta = event->angleDelta().y();
|
||||
osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ?
|
||||
osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
|
||||
this->getEventQueue()->mouseScroll(motion);
|
||||
}
|
||||
|
||||
bool IfcViewerWidget::event(QEvent* event)
|
||||
{
|
||||
bool handled = QOpenGLWidget::event(event);
|
||||
this->update();
|
||||
return handled;
|
||||
}
|
||||
|
||||
osgGA::EventQueue* IfcViewerWidget::getEventQueue() const
|
||||
{
|
||||
osgGA::EventQueue* eventQueue = m_graphicsWindow->getEventQueue();
|
||||
return eventQueue;
|
||||
}
|
||||
|
||||
unsigned int IfcViewerWidget::getMouseButtonNum(QMouseEvent* event)
|
||||
{
|
||||
unsigned int button = 0;
|
||||
switch (event->button()){
|
||||
case Qt::LeftButton:
|
||||
button = 1;
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
button = 2;
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
button = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
void IfcViewerWidget::setupViewController()
|
||||
{
|
||||
setMouseTracking(false);
|
||||
m_mouseHandler = new osgGA::TrackballManipulator;
|
||||
m_mouseHandler->setAllowThrow(false);
|
||||
m_viewer->setCameraManipulator(m_mouseHandler);
|
||||
}
|
||||
|
||||
void IfcViewerWidget::loadFile(const std::string& filePath)
|
||||
{
|
||||
std::vector<osg::ref_ptr<osg::MatrixTransform>> matrixTransforms;
|
||||
|
||||
if(!m_parser.Parse(filePath, matrixTransforms)) {
|
||||
MessageLogger::log("Failed to prepare IFC geometry");
|
||||
return;
|
||||
}
|
||||
|
||||
MessageLogger::log("\nIFC geometry prepared");
|
||||
|
||||
for (auto matrixTransform : matrixTransforms) {
|
||||
root->addChild(matrixTransform);
|
||||
}
|
||||
|
||||
// set initial camera position
|
||||
orientScene(root);
|
||||
|
||||
// request redraw
|
||||
update();
|
||||
}
|
||||
|
||||
void IfcViewerWidget::orientScene(osg::ref_ptr<osg::Group> rootGroup)
|
||||
{
|
||||
// Get the bounding-box
|
||||
osg::ComputeBoundsVisitor cbv;
|
||||
rootGroup->accept(cbv);
|
||||
const osg::BoundingBox& bb = cbv.getBoundingBox();
|
||||
|
||||
// Center (average of opposite corners of bb)
|
||||
osg::Vec3d center = (bb.corner(0) + bb.corner(7)) * 0.5;
|
||||
|
||||
// Radius (distance between the center and the corner)
|
||||
// assuming corner(7) has maximum x,y,z coords
|
||||
float radius = (bb.corner(7) - center).length();
|
||||
|
||||
// Calc. eye position
|
||||
osg::Vec3d eye = center + osg::Vec3d(radius * 3, -radius * 3, 0.0);
|
||||
|
||||
osg::Vec3d up = osg::Vec3d(0.0, 0.0, 1.0);
|
||||
|
||||
// Set the camera's view matrix
|
||||
// In case a cameraManipulator is set, lookAt position setting does not work on the camera
|
||||
// as it is overridden.
|
||||
// So set it on the manipulator and reapply it to the viewer
|
||||
if (m_mouseHandler.valid())
|
||||
{
|
||||
m_mouseHandler->setHomePosition(eye, center, up);
|
||||
}
|
||||
|
||||
m_viewer->setCameraManipulator(m_mouseHandler);
|
||||
|
||||
auto log = [center, radius, eye]() {
|
||||
MessageLogger::log("center: " + std::to_string(center.length()));
|
||||
MessageLogger::log("radius: " + std::to_string(radius));
|
||||
MessageLogger::log("center: " + std::to_string(center.x()) + ", " + std::to_string(center.y()) + ", " + std::to_string(center.z()));
|
||||
MessageLogger::log("eye: " + std::to_string(eye.x()) + ", " + std::to_string(eye.y()) + ", " + std::to_string(eye.z()));
|
||||
};
|
||||
//log();
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#ifndef IFCVIEWERWIDGET_H
|
||||
#define IFCVIEWERWIDGET_H
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLContext>
|
||||
#include <QMatrix4x4>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osgViewer/GraphicsWindow>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgGA/TrackballManipulator>
|
||||
#include <osg/Group>
|
||||
#include <string>
|
||||
|
||||
#include "ParseIfcFile.h"
|
||||
#include "osg/Vec4"
|
||||
|
||||
class IfcViewerWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IfcViewerWidget(
|
||||
qreal dpiScale,
|
||||
QWidget *parent = nullptr
|
||||
);
|
||||
|
||||
public slots:
|
||||
void loadFile(const std::string& filePath);
|
||||
|
||||
protected:
|
||||
virtual void initializeGL() override; // to set up resources, state
|
||||
virtual void resizeGL(int w, int h) override; // to set up viewport, projection, etc.
|
||||
virtual void paintGL() override; // to render OpenGL scene
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void wheelEvent(QWheelEvent *event) override;
|
||||
virtual bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
qreal m_dpiScale;
|
||||
QMatrix4x4 m_projection;
|
||||
osg::Vec4 m_clearColor;
|
||||
osg::ref_ptr<osgGA::TrackballManipulator> m_mouseHandler;
|
||||
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> m_graphicsWindow;
|
||||
osg::ref_ptr<osgViewer::Viewer> m_viewer;
|
||||
osg::ref_ptr<osg::Group> root; // OSG root node
|
||||
|
||||
ParseIfcFile m_parser;
|
||||
|
||||
osgGA::EventQueue* getEventQueue() const;
|
||||
unsigned int getMouseButtonNum(QMouseEvent* event);
|
||||
|
||||
void setupViewController();
|
||||
|
||||
void orientScene(osg::ref_ptr<osg::Group> rootGroup);
|
||||
};
|
||||
|
||||
#endif // IFCVIEWERWIDGET_H
|
||||
@@ -1,130 +0,0 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QSplitter>
|
||||
#include <sstream>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "MessageLogger.h"
|
||||
#include "IfcViewerWidget.h"
|
||||
|
||||
MainWindow::MainWindow(qreal dpiScale, QWidget *parent)
|
||||
: QMainWindow(parent), m_dpiScale(dpiScale)
|
||||
{
|
||||
this->setWindowTitle("IfcOpenShell Viewer");
|
||||
this->resize(800, 600); //temporary reasonable initial size
|
||||
|
||||
m_glWidget = new IfcViewerWidget(m_dpiScale, this);
|
||||
QSizePolicy glSizePolicy = m_glWidget->sizePolicy();
|
||||
glSizePolicy.setVerticalStretch(3);
|
||||
m_glWidget->setSizePolicy(glSizePolicy);
|
||||
|
||||
m_outputText = new QPlainTextEdit(this);
|
||||
m_outputText->setReadOnly(true);
|
||||
|
||||
QSplitter* splitter = new QSplitter(Qt::Vertical, this);
|
||||
splitter->addWidget(m_glWidget);
|
||||
splitter->addWidget(m_outputText);
|
||||
|
||||
setCentralWidget(splitter);
|
||||
|
||||
createActions();
|
||||
createMenus();
|
||||
createConnections();
|
||||
}
|
||||
|
||||
void MainWindow::createActions()
|
||||
{
|
||||
openAction = new QAction(tr("&Open"), this);
|
||||
openAction->setShortcut(QKeySequence(tr("Ctrl+O")));
|
||||
|
||||
quitAction = new QAction(tr("E&xit"), this);
|
||||
quitAction->setShortcut(QKeySequence::Quit);
|
||||
|
||||
m_backgroundAction = new QAction(tr("&Background"));
|
||||
m_backgroundAction->setEnabled(false);
|
||||
m_backgroundAction->setCheckable(true);
|
||||
m_backgroundAction->setChecked(false);
|
||||
|
||||
m_outlineAction = new QAction(tr("&Outline"));
|
||||
m_outlineAction->setEnabled(false);
|
||||
m_outlineAction->setCheckable(true);
|
||||
m_outlineAction->setChecked(false);
|
||||
}
|
||||
|
||||
void MainWindow::createMenus()
|
||||
{
|
||||
QMenuBar *menuBar = new QMenuBar();
|
||||
setMenuBar(menuBar);
|
||||
|
||||
fileMenu = new QMenu(tr("&File"), menuBar);
|
||||
menuBar->addMenu(fileMenu);
|
||||
|
||||
fileMenu->addAction(openAction);
|
||||
fileMenu->addAction(quitAction);
|
||||
|
||||
viewMenu = new QMenu(tr("&View"), menuBar);
|
||||
menuBar->addMenu(viewMenu);
|
||||
|
||||
viewMenu->addAction(m_backgroundAction);
|
||||
viewMenu->addAction(m_outlineAction);
|
||||
}
|
||||
|
||||
void MainWindow::createConnections()
|
||||
{
|
||||
connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));
|
||||
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||
//connect(m_backgroundAction, SIGNAL(toggled(bool)), (QWidget*)m_v, SLOT(setViewBackground(bool)));
|
||||
//connect(m_outlineAction, SIGNAL(toggled(bool)), (QWidget*)m_v, SLOT(setViewOutline(bool)));
|
||||
|
||||
//connect(&m_parser, &ParseIfcFile::parsingInfo, this, &MainWindow::appendToOutputText);
|
||||
connect(&MessageLogger::getInstance(), SIGNAL(logMessage(QString)), this, SLOT(appendToOutputText(QString)));
|
||||
|
||||
connect(this, SIGNAL(loadFileInViewerWidget(const std::string&)), m_glWidget, SLOT(loadFile(const std::string&)));
|
||||
}
|
||||
|
||||
void MainWindow::appendToOutputText(const QString& message)
|
||||
{
|
||||
m_outputText->appendPlainText(message);
|
||||
}
|
||||
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
QString filePath = QFileDialog::getOpenFileName(this, tr("Open IFC File"),
|
||||
".", tr("IFC Files (*.ifc)"));
|
||||
|
||||
QFileInfo fileInfo(filePath);
|
||||
QString fileName = fileInfo.fileName();
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
// Check if the file is a Qt resource file
|
||||
if (fileName.startsWith(":/"))
|
||||
return;
|
||||
|
||||
QFile file(filePath);
|
||||
if (!file.exists()) {
|
||||
QMessageBox::critical(this, tr("Open IFC"),
|
||||
QString("Could not open '%1'.").arg(filePath));
|
||||
|
||||
m_outlineAction->setEnabled(false);
|
||||
m_backgroundAction->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
QString message = tr("Opening file: %1\n").arg(filePath);
|
||||
appendToOutputText(message);
|
||||
|
||||
setWindowTitle(tr("%1 - IFCViewer").arg(fileName));
|
||||
|
||||
m_outlineAction->setEnabled(true);
|
||||
m_backgroundAction->setEnabled(true);
|
||||
|
||||
emit loadFileInViewerWidget(filePath.toStdString());
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMainWindow>
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QPlainTextEdit>
|
||||
#include <string>
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(qreal dpiScale, QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void loadFileInViewerWidget(const std::string& filePath);
|
||||
|
||||
public slots:
|
||||
void openFile();
|
||||
void appendToOutputText(const QString& message);
|
||||
|
||||
private:
|
||||
void createActions();
|
||||
void createMenus();
|
||||
void createConnections();
|
||||
private:
|
||||
qreal m_dpiScale;
|
||||
|
||||
QMenu *fileMenu;
|
||||
QAction *openAction;
|
||||
QAction *quitAction;
|
||||
|
||||
QMenu *viewMenu;
|
||||
QAction *m_nativeAction;
|
||||
QAction *m_glAction;
|
||||
QAction *m_imageAction;
|
||||
QAction *m_highQualityAntialiasingAction;
|
||||
QAction *m_backgroundAction;
|
||||
QAction *m_outlineAction;
|
||||
|
||||
QOpenGLWidget *m_glWidget;
|
||||
QPlainTextEdit *m_outputText;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef MESSAGELOGGER_H
|
||||
#define MESSAGELOGGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <string>
|
||||
|
||||
// SINGLETON
|
||||
class MessageLogger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
signals:
|
||||
void logMessage(const QString& message);
|
||||
|
||||
public:
|
||||
static MessageLogger& getInstance()
|
||||
{
|
||||
static MessageLogger instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Convenience function to log a message
|
||||
static void log(const std::string& message)
|
||||
{
|
||||
getInstance().emitMessage(message);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void emitMessage(const std::string& message)
|
||||
{
|
||||
emit logMessage(QString::fromStdString(message));
|
||||
}
|
||||
|
||||
private:
|
||||
MessageLogger() {}
|
||||
~MessageLogger() {}
|
||||
|
||||
// Disable copy constructor for MessageLogger
|
||||
MessageLogger(const MessageLogger&) = delete;
|
||||
|
||||
// Disable copy assignment operator for MessageLogger
|
||||
MessageLogger& operator=(const MessageLogger&) = delete;
|
||||
};
|
||||
|
||||
#endif // MESSAGELOGGER_H
|
||||
@@ -1,214 +0,0 @@
|
||||
#include "ParseIfcFile.h"
|
||||
#include "../ifcgeom/hybrid_kernel.h"
|
||||
|
||||
#include "MessageLogger.h"
|
||||
#include "osg/Array"
|
||||
#include "osg/Geometry"
|
||||
#include "osg/Material"
|
||||
#include "osg/Matrixd"
|
||||
#include "osg/MatrixTransform"
|
||||
#include "osg/PrimitiveSet"
|
||||
#include "osg/ref_ptr"
|
||||
#include "osg/StateAttribute"
|
||||
#include "osg/StateSet"
|
||||
#include "osg/Vec4"
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <osg/Vec3>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
ParseIfcFile::ParseIfcFile() {}
|
||||
|
||||
ParseIfcFile::~ParseIfcFile() {}
|
||||
|
||||
bool ParseIfcFile::Parse(
|
||||
const std::string& filePath,
|
||||
std::vector<osg::ref_ptr<osg::MatrixTransform>>& matrixTransforms
|
||||
) {
|
||||
ifcopenshell::file file(filePath);
|
||||
ifcopenshell::geometry::Settings settings;
|
||||
settings.set("use-world-coords", false);
|
||||
settings.set("weld-vertices", false);
|
||||
settings.set("apply-default-materials", true);
|
||||
|
||||
IfcGeom::Iterator* it = new IfcGeom::Iterator(ifcopenshell::geometry::kernels::construct(&file, "opencascade", settings), settings, &file);
|
||||
if (!it->initialize()) {
|
||||
MessageLogger::log("Error: Iterator failed to initialize! Aborting.");
|
||||
delete it;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string lastId;
|
||||
std::vector<osg::ref_ptr<osg::Geometry>> lastGeometrySet;
|
||||
|
||||
do {
|
||||
//const IfcGeom::BRepElement* bRepElem = it->get_native();
|
||||
const IfcGeom::TriangulationElement* triElem = static_cast<const IfcGeom::TriangulationElement*>(it->get());
|
||||
|
||||
// Print element info
|
||||
std::string elemInfo = triElem->type();
|
||||
elemInfo += triElem->name() == "" ? "" : ": " + triElem->name();
|
||||
MessageLogger::log(elemInfo);
|
||||
|
||||
const std::string id = triElem->geometry().id();
|
||||
|
||||
//MessageLogger::log("id: " + id);
|
||||
|
||||
// Transformation Matrix
|
||||
std::vector<double> matrixData;
|
||||
auto transform4x4 = triElem->transformation().data()->components();
|
||||
for (int col = 0; col<4; col++)
|
||||
{
|
||||
for (int row =0; row<3; row++)
|
||||
{
|
||||
matrixData.push_back(transform4x4(row,col));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Debugging:
|
||||
std::string matrixStr = "";
|
||||
int col = 0;
|
||||
int row = 0;
|
||||
for (auto d : matrixData) {
|
||||
matrixStr += std::to_string(d) + " ";
|
||||
if (++col == 3) {
|
||||
std::string lastCol = (row == 3) ? "1" : "0";
|
||||
matrixStr += lastCol + "\n";
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
//MessageLogger::log(matrixStr); // Print matrix data
|
||||
|
||||
const osg::Matrixd matrixd (
|
||||
matrixData[0], matrixData[1], matrixData[2], 0,
|
||||
matrixData[3], matrixData[4], matrixData[5], 0,
|
||||
matrixData[6], matrixData[7], matrixData[8], 0,
|
||||
matrixData[9], matrixData[10], matrixData[11], 1
|
||||
);
|
||||
|
||||
const osg::ref_ptr<osg::MatrixTransform> matrixTransform = new osg::MatrixTransform;
|
||||
matrixTransform->setMatrix(matrixd);
|
||||
|
||||
if (id == lastId) {
|
||||
for (auto geometry : lastGeometrySet) {
|
||||
matrixTransform->addChild(geometry);
|
||||
}
|
||||
matrixTransforms.push_back(matrixTransform);
|
||||
continue;
|
||||
}
|
||||
|
||||
const boost::shared_ptr<IfcGeom::Representation::Triangulation>& triElemGeom = triElem->geometry_pointer();
|
||||
|
||||
const std::vector<int>& elemFaces = triElemGeom->faces();
|
||||
const std::vector<double>& elemVertices = triElemGeom->verts();
|
||||
const std::vector<double>& elemNormals = triElemGeom->normals();
|
||||
const std::vector<ifcopenshell::geometry::taxonomy::style::ptr>& elemMats = triElemGeom->materials();
|
||||
const std::vector<int>& elemMatIds = triElemGeom->material_ids();
|
||||
|
||||
std::map<int, osg::ref_ptr<osg::Material>> uniqueMaterials;
|
||||
|
||||
std::map<int, std::vector<int>> elemFaces_grouped;
|
||||
auto fit = elemFaces.begin();
|
||||
for (const int& matId : elemMatIds) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
elemFaces_grouped[matId].push_back(*fit++);
|
||||
}
|
||||
}
|
||||
|
||||
if (fit != elemFaces.end())
|
||||
MessageLogger::log("** Failed to map the faces to material IDs!");
|
||||
|
||||
std::vector<osg::ref_ptr<osg::Geometry>> geometrySet;
|
||||
|
||||
for (const auto& group : elemFaces_grouped) {
|
||||
int matId = group.first;
|
||||
const std::vector<int>& fVertIds = group.second;
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> osgVertices = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec3Array> osgNormals = new osg::Vec3Array;
|
||||
|
||||
for (size_t i = 0; i < fVertIds.size(); i += 3) {
|
||||
buildTriangleNodes(
|
||||
fVertIds, elemVertices, elemNormals, i,
|
||||
osgVertices, osgNormals
|
||||
);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
|
||||
|
||||
geometry->setVertexArray(osgVertices);
|
||||
geometry->setNormalArray(osgNormals);
|
||||
geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
|
||||
osg::ref_ptr<osg::DrawArrays> drawArrays = new osg::DrawArrays(
|
||||
osg::PrimitiveSet::TRIANGLES, 0, osgVertices->size());
|
||||
geometry->addPrimitiveSet(drawArrays);
|
||||
|
||||
osg::ref_ptr<osg::Material> osgMaterial = getOsgMaterial(elemMats[matId]);
|
||||
geometry->getOrCreateStateSet()->setAttributeAndModes(osgMaterial.get());
|
||||
|
||||
matrixTransform->addChild(geometry);
|
||||
|
||||
geometrySet.push_back(geometry);
|
||||
}
|
||||
|
||||
matrixTransforms.push_back(matrixTransform);
|
||||
|
||||
lastId = id;
|
||||
lastGeometrySet = geometrySet;
|
||||
|
||||
} while (it->next());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParseIfcFile::buildTriangleNodes(
|
||||
const std::vector<int>& fVertIds,
|
||||
const std::vector<double>& elemVertices,
|
||||
const std::vector<double>& elemNormals,
|
||||
size_t index,
|
||||
osg::ref_ptr<osg::Vec3Array> osgVertices,
|
||||
osg::ref_ptr<osg::Vec3Array> osgNormals)
|
||||
{
|
||||
auto addVertexAndNormal = [fVertIds, elemVertices, elemNormals, osgVertices, osgNormals](size_t i) {
|
||||
|
||||
size_t initVertIndex = 3 * fVertIds[i];
|
||||
size_t x_vertIndex = initVertIndex;
|
||||
size_t y_vertIndex = initVertIndex + 1;
|
||||
size_t z_vertIndex = initVertIndex + 2;
|
||||
|
||||
osgVertices->push_back(osg::Vec3 (
|
||||
elemVertices[x_vertIndex],
|
||||
elemVertices[y_vertIndex],
|
||||
elemVertices[z_vertIndex]
|
||||
));
|
||||
|
||||
osgNormals->push_back(osg::Vec3 (
|
||||
elemNormals[x_vertIndex],
|
||||
elemNormals[y_vertIndex],
|
||||
elemNormals[z_vertIndex]
|
||||
));
|
||||
};
|
||||
|
||||
addVertexAndNormal(index);
|
||||
addVertexAndNormal(index + 1);
|
||||
addVertexAndNormal(index + 2);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Material> ParseIfcFile::getOsgMaterial(const ifcopenshell::geometry::taxonomy::style::ptr& material)
|
||||
{
|
||||
ifcopenshell::geometry::taxonomy::colour diffuseColor = material->diffuse;
|
||||
osg::Vec4 matOsgDiffuseColor(
|
||||
diffuseColor.r(),
|
||||
diffuseColor.g(),
|
||||
diffuseColor.b(),
|
||||
material->transparency);
|
||||
|
||||
osg::ref_ptr<osg::Material> osgMaterial = new osg::Material;
|
||||
osgMaterial->setDiffuse(osg::Material::FRONT_AND_BACK, matOsgDiffuseColor);
|
||||
|
||||
return osgMaterial;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef PARSEIFCFILE_H
|
||||
#define PARSEIFCFILE_H
|
||||
|
||||
#include "../ifcgeom/Iterator.h"
|
||||
#include "osg/Geometry"
|
||||
#include "osg/Material"
|
||||
#include "osg/MatrixTransform"
|
||||
#include "osg/ref_ptr"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ParseIfcFile : public QObject {
|
||||
|
||||
public:
|
||||
ParseIfcFile();
|
||||
~ParseIfcFile();
|
||||
|
||||
bool Parse(
|
||||
const std::string& filePath,
|
||||
std::vector<osg::ref_ptr<osg::MatrixTransform>>& matrixTransforms);
|
||||
|
||||
private:
|
||||
void buildTriangleNodes(
|
||||
const std::vector<int>& fVertIds,
|
||||
const std::vector<double>& elemVertices,
|
||||
const std::vector<double>& elemNormals,
|
||||
size_t index,
|
||||
osg::ref_ptr<osg::Vec3Array> osgVertices,
|
||||
osg::ref_ptr<osg::Vec3Array> osgNormals);
|
||||
|
||||
osg::ref_ptr<osg::Material> getOsgMaterial(const ifcopenshell::geometry::taxonomy::style::ptr& material);
|
||||
};
|
||||
|
||||
#endif // PARSEIFCFILE_H
|
||||
@@ -1,25 +0,0 @@
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Set the icon in the window title-bar on mswindows
|
||||
// and dock icon on macos.
|
||||
// "icon" alias defined in .qrc file
|
||||
QIcon appIcon(":/icon");
|
||||
app.setWindowIcon(appIcon);
|
||||
// File icon set with:
|
||||
// mswindows - .rc file
|
||||
// macos - .icns file (using CMake)
|
||||
|
||||
qreal dpiScale = app.devicePixelRatio();
|
||||
|
||||
MainWindow window(dpiScale);
|
||||
|
||||
window.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 377 B |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 439 B |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 710 B |
|
Before Width: | Height: | Size: 740 B |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,37 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "ifcopenshell_logo.ico"
|
||||
@@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file alias="icon">ifcopenshell_logo.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,16 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by qt_res.rc
|
||||
//
|
||||
#define IDI_ICON1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||