After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 64 KiB |
|
@ -5,4 +5,4 @@ Name=OpenSCAD
|
||||||
Icon=openscad
|
Icon=openscad
|
||||||
Exec=openscad %f
|
Exec=openscad %f
|
||||||
MimeType=application/x-openscad;
|
MimeType=application/x-openscad;
|
||||||
Categories=Graphics;3DGraphics;Engineering;Development;
|
Categories=Graphics;3DGraphics;Engineering;
|
||||||
|
|
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 773 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 463 B |
After Width: | Height: | Size: 955 B |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 942 B |
After Width: | Height: | Size: 939 B |
After Width: | Height: | Size: 920 B |
After Width: | Height: | Size: 909 B |
After Width: | Height: | Size: 942 B |
After Width: | Height: | Size: 200 B |
After Width: | Height: | Size: 889 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 864 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 885 B |
After Width: | Height: | Size: 317 B |
After Width: | Height: | Size: 325 B |
After Width: | Height: | Size: 425 B |
After Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 641 B |
After Width: | Height: | Size: 910 B |
After Width: | Height: | Size: 884 B |
After Width: | Height: | Size: 570 B |
After Width: | Height: | Size: 518 B |
After Width: | Height: | Size: 368 B |
After Width: | Height: | Size: 361 B |
After Width: | Height: | Size: 882 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 884 B |
After Width: | Height: | Size: 922 B |
After Width: | Height: | Size: 710 B |
After Width: | Height: | Size: 927 B |
After Width: | Height: | Size: 934 B |
After Width: | Height: | Size: 945 B |
After Width: | Height: | Size: 938 B |
After Width: | Height: | Size: 884 B |
12
openscad.pro
|
@ -365,9 +365,9 @@ SOURCES += src/version_check.cc \
|
||||||
src/ModuleCache.cc \
|
src/ModuleCache.cc \
|
||||||
src/GeometryCache.cc \
|
src/GeometryCache.cc \
|
||||||
src/Tree.cc \
|
src/Tree.cc \
|
||||||
src/DrawingCallback.cc \
|
src/DrawingCallback.cc \
|
||||||
src/FreetypeRenderer.cc \
|
src/FreetypeRenderer.cc \
|
||||||
src/FontCache.cc \
|
src/FontCache.cc \
|
||||||
\
|
\
|
||||||
src/rendersettings.cc \
|
src/rendersettings.cc \
|
||||||
src/highlighter.cc \
|
src/highlighter.cc \
|
||||||
|
@ -397,7 +397,7 @@ src/FontCache.cc \
|
||||||
src/openscad.cc \
|
src/openscad.cc \
|
||||||
src/mainwin.cc \
|
src/mainwin.cc \
|
||||||
src/UIUtils.cc \
|
src/UIUtils.cc \
|
||||||
src/FontListDialog.cc \
|
src/FontListDialog.cc \
|
||||||
src/launchingscreen.cpp \
|
src/launchingscreen.cpp \
|
||||||
src/legacyeditor.cc \
|
src/legacyeditor.cc \
|
||||||
src/LibraryInfoDialog.cc
|
src/LibraryInfoDialog.cc
|
||||||
|
@ -474,6 +474,10 @@ libraries.path = $$PREFIX/share/openscad/libraries/
|
||||||
libraries.files = libraries/*
|
libraries.files = libraries/*
|
||||||
INSTALLS += libraries
|
INSTALLS += libraries
|
||||||
|
|
||||||
|
fonts.path = $$PREFIX/share/openscad/fonts/
|
||||||
|
fonts.files = fonts/*
|
||||||
|
INSTALLS += fonts
|
||||||
|
|
||||||
applications.path = $$PREFIX/share/applications
|
applications.path = $$PREFIX/share/applications
|
||||||
applications.files = icons/openscad.desktop
|
applications.files = icons/openscad.desktop
|
||||||
INSTALLS += applications
|
INSTALLS += applications
|
||||||
|
|
|
@ -170,7 +170,7 @@
|
||||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">openscad</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">openscad</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/shaina/letsbegin/openscad/openscad.pro</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/shaina/openscad/openscad.pro</value>
|
||||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">openscad.pro</value>
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">openscad.pro</value>
|
||||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||||
|
|
47
openscad.qrc
|
@ -11,6 +11,53 @@
|
||||||
<file>icons/prefsUpdate.png</file>
|
<file>icons/prefsUpdate.png</file>
|
||||||
<file>icons/flattr.png</file>
|
<file>icons/flattr.png</file>
|
||||||
<file>src/AboutDialog.html</file>
|
<file>src/AboutDialog.html</file>
|
||||||
|
<file>images/Arrowhead-Right-32.png</file>
|
||||||
|
<file>images/export.png</file>
|
||||||
|
<file>images/axes.png</file>
|
||||||
|
<file>images/export-white.png</file>
|
||||||
|
<file>images/back.png</file>
|
||||||
|
<file>images/Document-New-128.png</file>
|
||||||
|
<file>images/front.png</file>
|
||||||
|
<file>images/grid.png</file>
|
||||||
|
<file>images/Open-128.png</file>
|
||||||
|
<file>images/openscad.png</file>
|
||||||
|
<file>images/right.png</file>
|
||||||
|
<file>images/Save-128.png</file>
|
||||||
|
<file>images/up.png</file>
|
||||||
|
<file>images/bottom.png</file>
|
||||||
|
<file>images/left.png</file>
|
||||||
|
<file>images/blackUp.png</file>
|
||||||
|
<file>images/blackNew.png</file>
|
||||||
|
<file>images/blackRender.png</file>
|
||||||
|
<file>images/Rotation-32.png</file>
|
||||||
|
<file>images/Shape-Cube-32.png</file>
|
||||||
|
<file>images/Open-32.png</file>
|
||||||
|
<file>images/Save-32.png</file>
|
||||||
|
<file>images/blackbottom.png</file>
|
||||||
|
<file>images/blackleft (copy).png</file>
|
||||||
|
<file>images/rightright.png</file>
|
||||||
|
<file>images/blackfront.png</file>
|
||||||
|
<file>images/blackback.png</file>
|
||||||
|
<file>images/blackaxes.png</file>
|
||||||
|
<file>images/zoomin.png</file>
|
||||||
|
<file>images/zoomout.png</file>
|
||||||
|
<file>images/wireframe1.png</file>
|
||||||
|
<file>images/surface.png</file>
|
||||||
|
<file>images/Zoom-In-32.png</file>
|
||||||
|
<file>images/Zoom-Out-32.png</file>
|
||||||
|
<file>images/zoom-all.png</file>
|
||||||
|
<file>images/zoom-all-white.png</file>
|
||||||
|
<file>images/surfaceWhite.png</file>
|
||||||
|
<file>images/wireframeWhite.png</file>
|
||||||
|
<file>images/orthogonal.png</file>
|
||||||
|
<file>images/cross.png</file>
|
||||||
|
<file>images/perspective1.png</file>
|
||||||
|
<file>images/Preview-32.png</file>
|
||||||
|
<file>images/animate.png</file>
|
||||||
|
<file>images/Preview-32 (1).png</file>
|
||||||
|
<file>images/orthogonalwhite.png</file>
|
||||||
|
<file>images/perspective1white.png</file>
|
||||||
|
<file>images/crosswhite.png</file>
|
||||||
<file>icons/background.png</file>
|
<file>icons/background.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
diff --git a/opencsg.pro b/opencsg.pro
|
diff --git a/opencsg.pro b/opencsg.pro
|
||||||
|
index b56e622..5cf2d6d 100644
|
||||||
--- a/opencsg.pro
|
--- a/opencsg.pro
|
||||||
+++ b/opencsg.pro
|
+++ b/opencsg.pro
|
||||||
@@ -1,2 +1,2 @@
|
@@ -1,2 +1,2 @@
|
||||||
|
@ -6,17 +7,25 @@ diff --git a/opencsg.pro b/opencsg.pro
|
||||||
-SUBDIRS = src example
|
-SUBDIRS = src example
|
||||||
+SUBDIRS = src
|
+SUBDIRS = src
|
||||||
diff --git a/src/src.pro b/src/src.pro
|
diff --git a/src/src.pro b/src/src.pro
|
||||||
--- OpenCSG-1.4.0/src/src.pro 2014-09-15 16:25:33.000000000 -0400
|
index 9091251..598112a 100644
|
||||||
+++ OpenCSG-1.4.0-mac/src/src.pro 2014-09-15 18:17:09.000000000 -0400
|
--- a/src/src.pro
|
||||||
@@ -8,10 +8,9 @@
|
+++ b/src/src.pro
|
||||||
|
@@ -3,15 +3,14 @@ TARGET = opencsg
|
||||||
|
VERSION = 1.4.0
|
||||||
|
|
||||||
|
CONFIG += opengl warn_on release
|
||||||
|
+CONFIG += absolute_library_soname
|
||||||
|
INCLUDEPATH += ../include ../
|
||||||
|
CONFIG -= qt
|
||||||
LIBS += -lGLEW
|
LIBS += -lGLEW
|
||||||
|
|
||||||
DESTDIR = ../lib
|
-DESTDIR = ../lib
|
||||||
-INSTALLDIR = /usr/local
|
-INSTALLDIR = /usr/local
|
||||||
headers.files = ../include/opencsg.h
|
headers.files = ../include/opencsg.h
|
||||||
headers.path = $$INSTALLDIR/include
|
-headers.path = $$INSTALLDIR/include
|
||||||
-target.path = /usr/local/lib
|
-target.path = /usr/local/lib
|
||||||
+target.path = $$INSTALLDIR/lib
|
+headers.path = $$DESTDIR/include
|
||||||
|
+target.path = $$DESTDIR/lib
|
||||||
INSTALLS += target headers
|
INSTALLS += target headers
|
||||||
|
|
||||||
HEADERS = ../include/opencsg.h \
|
HEADERS = ../include/opencsg.h \
|
||||||
|
|
|
@ -427,7 +427,7 @@ build_opencsg()
|
||||||
OPENCSG_EXTRA_FLAGS="x86"
|
OPENCSG_EXTRA_FLAGS="x86"
|
||||||
fi
|
fi
|
||||||
qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib" CONFIG+="x86_64 $OPENCSG_EXTRA_FLAGS"
|
qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib" CONFIG+="x86_64 $OPENCSG_EXTRA_FLAGS"
|
||||||
INSTALL_ROOT=$DEPLOYDIR make install
|
make install
|
||||||
}
|
}
|
||||||
|
|
||||||
build_eigen()
|
build_eigen()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QIcon>
|
||||||
#include "ui_MainWindow.h"
|
#include "ui_MainWindow.h"
|
||||||
#include "UIUtils.h"
|
#include "UIUtils.h"
|
||||||
#include "openscad.h"
|
#include "openscad.h"
|
||||||
|
@ -106,6 +107,7 @@ private:
|
||||||
QString get2dExportFilename(QString format, QString extension);
|
QString get2dExportFilename(QString format, QString extension);
|
||||||
void show_examples();
|
void show_examples();
|
||||||
void setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, bool topLevel);
|
void setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, bool topLevel);
|
||||||
|
void addKeyboardShortCut(const QList<QAction *> &actions);
|
||||||
|
|
||||||
EditorInterface *editor;
|
EditorInterface *editor;
|
||||||
|
|
||||||
|
@ -134,8 +136,10 @@ private slots:
|
||||||
private slots:
|
private slots:
|
||||||
void pasteViewportTranslation();
|
void pasteViewportTranslation();
|
||||||
void pasteViewportRotation();
|
void pasteViewportRotation();
|
||||||
void hideEditor();
|
|
||||||
void preferences();
|
void preferences();
|
||||||
|
void hideToolbars();
|
||||||
|
void hideEditor();
|
||||||
|
void hideConsole();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void selectFindType(int);
|
void selectFindType(int);
|
||||||
|
@ -208,7 +212,6 @@ public slots:
|
||||||
void viewOrthogonal();
|
void viewOrthogonal();
|
||||||
void viewResetView();
|
void viewResetView();
|
||||||
void viewAll();
|
void viewAll();
|
||||||
void hideConsole();
|
|
||||||
void animateUpdateDocChanged();
|
void animateUpdateDocChanged();
|
||||||
void animateUpdate();
|
void animateUpdate();
|
||||||
void dragEnterEvent(QDragEnterEvent *event);
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>936</width>
|
<width>1397</width>
|
||||||
<height>586</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -26,10 +26,10 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true"/>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="margin">
|
<property name="margin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignBottom">
|
<item>
|
||||||
<widget class="QFrame" name="animate_panel">
|
<widget class="QFrame" name="animate_panel">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -107,9 +107,32 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolBar" name="viewerToolBar">
|
||||||
|
<addaction name="designActionPreview"/>
|
||||||
|
<addaction name="designActionRender"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="viewActionViewAll"/>
|
||||||
|
<addaction name="viewActionZoomIn"/>
|
||||||
|
<addaction name="viewActionZoomOut"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="viewActionRight"/>
|
||||||
|
<addaction name="viewActionTop"/>
|
||||||
|
<addaction name="viewActionBottom"/>
|
||||||
|
<addaction name="viewActionLeft"/>
|
||||||
|
<addaction name="viewActionFront"/>
|
||||||
|
<addaction name="viewActionBack"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="viewActionPerspective"/>
|
||||||
|
<addaction name="viewActionOrthogonal"/>
|
||||||
|
<addaction name="viewActionShowAxes"/>
|
||||||
|
<addaction name="viewActionShowEdges"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
<zorder>animate_panel</zorder>
|
<zorder>animate_panel</zorder>
|
||||||
<zorder>qglview</zorder>
|
<zorder>qglview</zorder>
|
||||||
|
<zorder>viewerToolBar</zorder>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -119,8 +142,6 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>936</width>
|
|
||||||
<height>34</height>
|
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_File">
|
<widget class="QMenu" name="menu_File">
|
||||||
|
@ -244,8 +265,9 @@
|
||||||
<addaction name="viewActionPerspective"/>
|
<addaction name="viewActionPerspective"/>
|
||||||
<addaction name="viewActionOrthogonal"/>
|
<addaction name="viewActionOrthogonal"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="editActionHide"/>
|
<addaction name="viewActionHideToolBars"/>
|
||||||
<addaction name="viewActionHide"/>
|
<addaction name="viewActionHideEditor"/>
|
||||||
|
<addaction name="viewActionHideConsole"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -270,11 +292,26 @@
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</attribute>
|
</attribute>
|
||||||
<widget class="QWidget" name="editorDockContents">
|
<widget class="QWidget" name="editorDockContents">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="margin">
|
<property name="margin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item alignment="Qt::AlignTop">
|
<item>
|
||||||
|
<widget class="QToolBar" name="editortoolbar">
|
||||||
|
<addaction name="fileActionNew"/>
|
||||||
|
<addaction name="fileActionOpen"/>
|
||||||
|
<addaction name="fileActionSave"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="designActionPreview"/>
|
||||||
|
<addaction name="designActionRender"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="designActionExportSTL"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QFrame" name="find_panel">
|
<widget class="QFrame" name="find_panel">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -396,6 +433,10 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<action name="fileActionNew">
|
<action name="fileActionNew">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackNew.png</normaloff>:/images/blackNew.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&New</string>
|
<string>&New</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -404,6 +445,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="fileActionOpen">
|
<action name="fileActionOpen">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/Open-32.png</normaloff>:/images/Open-32.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Open...</string>
|
<string>&Open...</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -412,6 +457,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="fileActionSave">
|
<action name="fileActionSave">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/Save-32.png</normaloff>:/images/Save-32.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Save</string>
|
<string>&Save</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -559,7 +608,7 @@
|
||||||
<string>Ctrl+-</string>
|
<string>Ctrl+-</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="editActionHide">
|
<action name="viewActionHideEditor">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -576,6 +625,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="designActionPreview">
|
<action name="designActionPreview">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/Preview-32.png</normaloff>:/images/Preview-32.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Preview</string>
|
<string>&Preview</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -584,6 +637,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="designActionRender">
|
<action name="designActionRender">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackRender.png</normaloff>:/images/blackRender.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Render</string>
|
<string>&Render</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -612,6 +669,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="designActionExportSTL">
|
<action name="designActionExportSTL">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/export.png</normaloff>:/images/export.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Export as &STL...</string>
|
<string>Export as &STL...</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -669,6 +730,10 @@
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/Rotation-32.png</normaloff>:/images/Rotation-32.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Edges</string>
|
<string>Show Edges</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -680,6 +745,10 @@
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackaxes.png</normaloff>:/images/blackaxes.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Axes</string>
|
<string>Show Axes</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -691,6 +760,10 @@
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/cross.png</normaloff>:/images/cross.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Crosshairs</string>
|
<string>Show Crosshairs</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -707,6 +780,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionTop">
|
<action name="viewActionTop">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackUp.png</normaloff>:/images/blackUp.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Top</string>
|
<string>Top</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -715,6 +792,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionBottom">
|
<action name="viewActionBottom">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackbottom.png</normaloff>:/images/blackbottom.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bottom</string>
|
<string>Bottom</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -723,6 +804,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionLeft">
|
<action name="viewActionLeft">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackleft (copy).png</normaloff>:/images/blackleft (copy).png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Left</string>
|
<string>Left</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -731,6 +816,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionRight">
|
<action name="viewActionRight">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/rightright.png</normaloff>:/images/rightright.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Right</string>
|
<string>Right</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -739,6 +828,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionFront">
|
<action name="viewActionFront">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackfront.png</normaloff>:/images/blackfront.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Front</string>
|
<string>Front</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -747,6 +840,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionBack">
|
<action name="viewActionBack">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/blackback.png</normaloff>:/images/blackback.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Back</string>
|
<string>Back</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -771,6 +868,10 @@
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/perspective1.png</normaloff>:/images/perspective1.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Perspective</string>
|
<string>Perspective</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -779,11 +880,15 @@
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/orthogonal.png</normaloff>:/images/orthogonal.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Orthogonal</string>
|
<string>Orthogonal</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionHide">
|
<action name="viewActionHideConsole">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -934,6 +1039,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionZoomIn">
|
<action name="viewActionZoomIn">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/zoomin.png</normaloff>:/images/zoomin.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Zoom In</string>
|
<string>Zoom In</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -942,6 +1051,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionZoomOut">
|
<action name="viewActionZoomOut">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/zoomout.png</normaloff>:/images/zoomout.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Zoom Out</string>
|
<string>Zoom Out</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -950,6 +1063,10 @@
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="viewActionViewAll">
|
<action name="viewActionViewAll">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../openscad.qrc">
|
||||||
|
<normaloff>:/images/zoom-all.png</normaloff>:/images/zoom-all.png</iconset>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>View All</string>
|
<string>View All</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -959,6 +1076,14 @@
|
||||||
<string>Convert Tabs to Spaces</string>
|
<string>Convert Tabs to Spaces</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="viewActionHideToolBars">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide toolbars</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -968,7 +1093,9 @@
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="../openscad.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>fileActionClose</sender>
|
<sender>fileActionClose</sender>
|
||||||
|
|
117
src/mainwin.cc
|
@ -23,6 +23,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <iostream>
|
||||||
#include "GeometryCache.h"
|
#include "GeometryCache.h"
|
||||||
#include "ModuleCache.h"
|
#include "ModuleCache.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
@ -169,9 +170,9 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
editortype = Preferences::inst()->getValue("editor/editortype").toString();
|
editortype = Preferences::inst()->getValue("editor/editortype").toString();
|
||||||
|
|
||||||
useScintilla = (editortype == "QScintilla Editor");
|
useScintilla = (editortype == "QScintilla Editor");
|
||||||
|
|
||||||
#ifdef USE_SCINTILLA_EDITOR
|
#ifdef USE_SCINTILLA_EDITOR
|
||||||
if (useScintilla) {
|
if (useScintilla) {
|
||||||
editor = new ScintillaEditor(editorDockContents);
|
editor = new ScintillaEditor(editorDockContents);
|
||||||
|
@ -267,8 +268,9 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
connect(this->appActionUpdateCheck, SIGNAL(triggered()), this, SLOT(actionUpdateCheck()));
|
connect(this->appActionUpdateCheck, SIGNAL(triggered()), this, SLOT(actionUpdateCheck()));
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// File menu
|
// File menu
|
||||||
connect(this->fileActionNew, SIGNAL(triggered()), this, SLOT(actionNew()));
|
connect(this->fileActionNew, SIGNAL(triggered()), this, SLOT(actionNew()));
|
||||||
connect(this->fileActionOpen, SIGNAL(triggered()), this, SLOT(actionOpen()));
|
connect(this->fileActionOpen, SIGNAL(triggered()), this, SLOT(actionOpen()));
|
||||||
connect(this->fileActionSave, SIGNAL(triggered()), this, SLOT(actionSave()));
|
connect(this->fileActionSave, SIGNAL(triggered()), this, SLOT(actionSave()));
|
||||||
connect(this->fileActionSaveAs, SIGNAL(triggered()), this, SLOT(actionSaveAs()));
|
connect(this->fileActionSaveAs, SIGNAL(triggered()), this, SLOT(actionSaveAs()));
|
||||||
|
@ -313,7 +315,6 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
connect(this->editActionPasteVPR, SIGNAL(triggered()), this, SLOT(pasteViewportRotation()));
|
connect(this->editActionPasteVPR, SIGNAL(triggered()), this, SLOT(pasteViewportRotation()));
|
||||||
connect(this->editActionZoomIn, SIGNAL(triggered()), editor, SLOT(zoomIn()));
|
connect(this->editActionZoomIn, SIGNAL(triggered()), editor, SLOT(zoomIn()));
|
||||||
connect(this->editActionZoomOut, SIGNAL(triggered()), editor, SLOT(zoomOut()));
|
connect(this->editActionZoomOut, SIGNAL(triggered()), editor, SLOT(zoomOut()));
|
||||||
connect(this->editActionHide, SIGNAL(triggered()), this, SLOT(hideEditor()));
|
|
||||||
connect(this->editActionPreferences, SIGNAL(triggered()), this, SLOT(preferences()));
|
connect(this->editActionPreferences, SIGNAL(triggered()), this, SLOT(preferences()));
|
||||||
// Edit->Find
|
// Edit->Find
|
||||||
connect(this->editActionFind, SIGNAL(triggered()), this, SLOT(find()));
|
connect(this->editActionFind, SIGNAL(triggered()), this, SLOT(find()));
|
||||||
|
@ -377,9 +378,11 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
connect(this->viewActionViewAll, SIGNAL(triggered()), this, SLOT(viewAll()));
|
connect(this->viewActionViewAll, SIGNAL(triggered()), this, SLOT(viewAll()));
|
||||||
connect(this->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective()));
|
connect(this->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective()));
|
||||||
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
|
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
|
||||||
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole()));
|
|
||||||
connect(this->viewActionZoomIn, SIGNAL(triggered()), qglview, SLOT(ZoomIn()));
|
connect(this->viewActionZoomIn, SIGNAL(triggered()), qglview, SLOT(ZoomIn()));
|
||||||
connect(this->viewActionZoomOut, SIGNAL(triggered()), qglview, SLOT(ZoomOut()));
|
connect(this->viewActionZoomOut, SIGNAL(triggered()), qglview, SLOT(ZoomOut()));
|
||||||
|
connect(this->viewActionHideToolBars, SIGNAL(triggered()), this, SLOT(hideToolbars()));
|
||||||
|
connect(this->viewActionHideEditor, SIGNAL(triggered()), this, SLOT(hideEditor()));
|
||||||
|
connect(this->viewActionHideConsole, SIGNAL(triggered()), this, SLOT(hideConsole()));
|
||||||
|
|
||||||
// Help menu
|
// Help menu
|
||||||
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
|
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
|
||||||
|
@ -433,7 +436,65 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
connect(this->replaceButton, SIGNAL(clicked()), this, SLOT(replace()));
|
connect(this->replaceButton, SIGNAL(clicked()), this, SLOT(replace()));
|
||||||
connect(this->replaceAllButton, SIGNAL(clicked()), this, SLOT(replaceAll()));
|
connect(this->replaceAllButton, SIGNAL(clicked()), this, SLOT(replaceAll()));
|
||||||
connect(this->replaceInputField, SIGNAL(returnPressed()), this->replaceButton, SLOT(animateClick()));
|
connect(this->replaceInputField, SIGNAL(returnPressed()), this->replaceButton, SLOT(animateClick()));
|
||||||
|
|
||||||
|
addKeyboardShortCut(this->viewerToolBar->actions());
|
||||||
|
addKeyboardShortCut(this->editortoolbar->actions());
|
||||||
|
|
||||||
|
//Toolbar
|
||||||
|
int defaultcolor = viewerToolBar->palette().background().color().lightness();
|
||||||
|
|
||||||
|
if (defaultcolor > 165) {
|
||||||
|
fileActionNew->setIcon(QIcon("://images/blackNew.png"));
|
||||||
|
fileActionOpen->setIcon(QIcon("://images/Open-32.png"));
|
||||||
|
fileActionSave->setIcon(QIcon("://images/Save-32.png"));
|
||||||
|
editActionZoomIn->setIcon(QIcon("://images/zoomin.png"));
|
||||||
|
editActionZoomOut->setIcon(QIcon("://images/zoomout.png"));
|
||||||
|
designActionRender->setIcon(QIcon("://images/blackRender.png"));
|
||||||
|
viewActionShowAxes->setIcon(QIcon("://images/blackaxes.png"));
|
||||||
|
viewActionShowEdges->setIcon(QIcon("://images/Rotation-32.png"));
|
||||||
|
viewActionZoomIn->setIcon(QIcon("://images/zoomin.png"));
|
||||||
|
viewActionZoomOut->setIcon(QIcon("://images/zoomout.png"));
|
||||||
|
viewActionTop->setIcon(QIcon("://images/blackUp.png"));
|
||||||
|
viewActionBottom->setIcon(QIcon("://images/blackbottom.png"));
|
||||||
|
viewActionLeft->setIcon(QIcon("://images/blackleft (copy).png"));
|
||||||
|
viewActionRight->setIcon(QIcon("://images/rightright.png"));
|
||||||
|
viewActionFront->setIcon(QIcon("://images/blackfront.png"));
|
||||||
|
viewActionBack->setIcon(QIcon("://images/blackback.png"));
|
||||||
|
viewActionSurfaces->setIcon(QIcon("://images/surface.png"));
|
||||||
|
viewActionWireframe->setIcon(QIcon("://images/wireframe1.png"));
|
||||||
|
viewActionShowCrosshairs->setIcon(QIcon("://images/cross.png"));
|
||||||
|
viewActionPerspective->setIcon(QIcon("://images/perspective1.png"));
|
||||||
|
viewActionOrthogonal->setIcon(QIcon("://images/orthogonal.png"));
|
||||||
|
viewActionPreview->setIcon(QIcon("://images/Preview-32.png"));
|
||||||
|
viewActionAnimate->setIcon(QIcon("://images/animate.png"));
|
||||||
|
} else {
|
||||||
|
fileActionNew->setIcon(QIcon("://images/Document-New-128.png"));
|
||||||
|
fileActionOpen->setIcon(QIcon("://images/Open-128.png"));
|
||||||
|
fileActionSave->setIcon(QIcon("://images/Save-128.png"));
|
||||||
|
editActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png"));
|
||||||
|
editActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png"));
|
||||||
|
designActionRender->setIcon(QIcon("://images/Arrowhead-Right-32.png"));
|
||||||
|
viewActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png"));
|
||||||
|
viewActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png"));
|
||||||
|
viewActionShowAxes->setIcon(QIcon("://images/axes.png"));
|
||||||
|
viewActionShowEdges->setIcon(QIcon("://images/grid.png"));
|
||||||
|
viewActionTop->setIcon(QIcon("://images/up.png"));
|
||||||
|
viewActionBottom->setIcon(QIcon("://images/bottom.png"));
|
||||||
|
viewActionLeft->setIcon(QIcon("://images/left.png"));
|
||||||
|
viewActionRight->setIcon(QIcon("://images/right.png"));
|
||||||
|
viewActionFront->setIcon(QIcon("://images/front.png"));
|
||||||
|
viewActionBack->setIcon(QIcon("://images/back.png"));
|
||||||
|
viewActionSurfaces->setIcon(QIcon("://images/surfaceWhite.png"));
|
||||||
|
viewActionWireframe->setIcon(QIcon("://images/wireframeWhite.png"));
|
||||||
|
viewActionShowCrosshairs->setIcon(QIcon("://images/crosswhite.png"));
|
||||||
|
viewActionPreview->setIcon(QIcon("://images/Preview-32(1).png"));
|
||||||
|
viewActionPerspective->setIcon(QIcon("://images/perspective1white.png"));
|
||||||
|
viewActionOrthogonal->setIcon(QIcon("://images/orthogonalwhite.png"));
|
||||||
|
viewActionAnimate->setIcon(QIcon("://images/animate.png"));
|
||||||
|
designActionExportSTL->setIcon(QIcon(":/images/export-white.png"));
|
||||||
|
viewActionViewAll->setIcon(QIcon(":/images/zoom-all-white.png"));
|
||||||
|
}
|
||||||
|
|
||||||
// make sure it looks nice..
|
// make sure it looks nice..
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray();
|
QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray();
|
||||||
|
@ -476,6 +537,24 @@ MainWindow::MainWindow(const QString &filename)
|
||||||
clearCurrentOutput();
|
clearCurrentOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::addKeyboardShortCut(const QList<QAction *> &actions)
|
||||||
|
{
|
||||||
|
foreach (QAction *action, actions) {
|
||||||
|
// prevent adding shortcut twice if action is added to multiple toolbars
|
||||||
|
if (action->toolTip().contains(" ")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString shortCut(action->shortcut().toString(QKeySequence::NativeText));
|
||||||
|
if (shortCut.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString toolTip("%1 <span style=\"color: gray; font-size: small; font-style: italic\">%2</span>");
|
||||||
|
action->setToolTip(toolTip.arg(action->toolTip(), shortCut));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::loadViewSettings(){
|
void MainWindow::loadViewSettings(){
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
if (settings.value("view/showEdges").toBool()) {
|
if (settings.value("view/showEdges").toBool()) {
|
||||||
|
@ -495,10 +574,12 @@ void MainWindow::loadViewSettings(){
|
||||||
} else {
|
} else {
|
||||||
viewPerspective();
|
viewPerspective();
|
||||||
}
|
}
|
||||||
viewActionHide->setChecked(settings.value("view/hideConsole").toBool());
|
viewActionHideConsole->setChecked(settings.value("view/hideConsole").toBool());
|
||||||
hideConsole();
|
hideConsole();
|
||||||
editActionHide->setChecked(settings.value("view/hideEditor").toBool());
|
viewActionHideEditor->setChecked(settings.value("view/hideEditor").toBool());
|
||||||
hideEditor();
|
hideEditor();
|
||||||
|
viewActionHideToolBars->setChecked(settings.value("view/hideToolbar").toBool());
|
||||||
|
hideToolbars();
|
||||||
updateMdiMode(settings.value("advanced/mdi").toBool());
|
updateMdiMode(settings.value("advanced/mdi").toBool());
|
||||||
updateUndockMode(settings.value("advanced/undockableWindows").toBool());
|
updateUndockMode(settings.value("advanced/undockableWindows").toBool());
|
||||||
}
|
}
|
||||||
|
@ -2151,7 +2232,7 @@ void MainWindow::on_editorDock_visibilityChanged(bool visible)
|
||||||
}
|
}
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.setValue("view/hideEditor", !visible);
|
settings.setValue("view/hideEditor", !visible);
|
||||||
editActionHide->setChecked(!visible);
|
viewActionHideEditor->setChecked(!visible);
|
||||||
editorTopLevelChanged(editorDock->isFloating());
|
editorTopLevelChanged(editorDock->isFloating());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2162,7 +2243,7 @@ void MainWindow::on_consoleDock_visibilityChanged(bool visible)
|
||||||
}
|
}
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.setValue("view/hideConsole", !visible);
|
settings.setValue("view/hideConsole", !visible);
|
||||||
viewActionHide->setChecked(!visible);
|
viewActionHideConsole->setChecked(!visible);
|
||||||
consoleTopLevelChanged(consoleDock->isFloating());
|
consoleTopLevelChanged(consoleDock->isFloating());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2186,9 +2267,20 @@ void MainWindow::setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, boo
|
||||||
dockWidget->setWindowTitle(title);
|
dockWidget->setWindowTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::hideToolbars()
|
||||||
|
{
|
||||||
|
if (viewActionHideToolBars->isChecked()) {
|
||||||
|
viewerToolBar->hide();
|
||||||
|
editortoolbar->hide();
|
||||||
|
} else {
|
||||||
|
viewerToolBar->show();
|
||||||
|
editortoolbar->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::hideEditor()
|
void MainWindow::hideEditor()
|
||||||
{
|
{
|
||||||
if (editActionHide->isChecked()) {
|
if (viewActionHideEditor->isChecked()) {
|
||||||
editorDock->close();
|
editorDock->close();
|
||||||
} else {
|
} else {
|
||||||
editorDock->show();
|
editorDock->show();
|
||||||
|
@ -2196,8 +2288,9 @@ void MainWindow::hideEditor()
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::hideConsole()
|
void MainWindow::hideConsole()
|
||||||
|
|
||||||
{
|
{
|
||||||
if (viewActionHide->isChecked()) {
|
if (viewActionHideConsole->isChecked()) {
|
||||||
consoleDock->hide();
|
consoleDock->hide();
|
||||||
} else {
|
} else {
|
||||||
consoleDock->show();
|
consoleDock->show();
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
#include "polyset-utils.h"
|
||||||
|
#include "polyset.h"
|
||||||
|
#include "Polygon2d.h"
|
||||||
|
#include "printutils.h"
|
||||||
|
#include "cgal.h"
|
||||||
|
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define PREV_NDEBUG NDEBUG
|
||||||
|
#undef NDEBUG
|
||||||
|
#endif
|
||||||
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
|
#include <CGAL/Delaunay_mesher_2.h>
|
||||||
|
#include <CGAL/Delaunay_mesher_no_edge_refinement_2.h>
|
||||||
|
#include <CGAL/Delaunay_mesh_face_base_2.h>
|
||||||
|
#include <CGAL/Delaunay_mesh_criteria_2.h>
|
||||||
|
#include <CGAL/Mesh_2/Face_badness.h>
|
||||||
|
#ifdef PREV_NDEBUG
|
||||||
|
#define NDEBUG PREV_NDEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||||
|
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
||||||
|
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;
|
||||||
|
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
|
||||||
|
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag > CDT;
|
||||||
|
//typedef CGAL::Delaunay_mesh_criteria_2<CDT> Criteria;
|
||||||
|
|
||||||
|
typedef CDT::Vertex_handle Vertex_handle;
|
||||||
|
typedef CDT::Point CDTPoint;
|
||||||
|
|
||||||
|
template <class T> class DummyCriteria {
|
||||||
|
public:
|
||||||
|
typedef double Quality;
|
||||||
|
class Is_bad {
|
||||||
|
public:
|
||||||
|
CGAL::Mesh_2::Face_badness operator()(const Quality) const {
|
||||||
|
return CGAL::Mesh_2::NOT_BAD;
|
||||||
|
}
|
||||||
|
CGAL::Mesh_2::Face_badness operator()(const typename T::Face_handle&, Quality&q) const {
|
||||||
|
q = 1;
|
||||||
|
return CGAL::Mesh_2::NOT_BAD;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Is_bad is_bad_object() const { return Is_bad(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
namespace PolysetUtils {
|
||||||
|
|
||||||
|
// Project all polygons (also back-facing) into a Polygon2d instance.
|
||||||
|
// It's important to select all faces, since filtering by normal vector here
|
||||||
|
// will trigger floating point incertainties and cause problems later.
|
||||||
|
Polygon2d *project(const PolySet &ps) {
|
||||||
|
Polygon2d *poly = new Polygon2d;
|
||||||
|
|
||||||
|
BOOST_FOREACH(const PolySet::Polygon &p, ps.polygons) {
|
||||||
|
Outline2d outline;
|
||||||
|
BOOST_FOREACH(const Vector3d &v, p) {
|
||||||
|
outline.vertices.push_back(Vector2d(v[0], v[1]));
|
||||||
|
}
|
||||||
|
poly->addOutline(outline);
|
||||||
|
}
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tessellation of 3d PolySet faces
|
||||||
|
|
||||||
|
This code is for tessellating the faces of a 3d PolySet, assuming that
|
||||||
|
the faces are near-planar polygons.
|
||||||
|
|
||||||
|
We do the tessellation by projecting each polygon of the Polyset onto a
|
||||||
|
2-d plane, then running a 2d tessellation algorithm on the projected 2d
|
||||||
|
polygon. Then we project each of the newly generated 2d 'tiles' (the
|
||||||
|
polygons used for tessellation, typically triangles) back up into 3d
|
||||||
|
space.
|
||||||
|
|
||||||
|
(in reality as of writing, we dont need to do a back-projection from 2d->3d
|
||||||
|
because the algorithm we are using doesn't create any new points, and we can
|
||||||
|
just use a 'map' to associate 3d points with 2d points).
|
||||||
|
|
||||||
|
The code assumes the input polygons are simple, non-intersecting, without
|
||||||
|
holes, without duplicate input points, and with proper orientation.
|
||||||
|
|
||||||
|
The purpose of this code is originally to fix github issue 349. Our CGAL
|
||||||
|
kernel does not accept polygons for Nef_Polyhedron_3 if each of the
|
||||||
|
points is not exactly coplanar. "Near-planar" or "Almost planar" polygons
|
||||||
|
often occur due to rounding issues on, for example, polyhedron() input.
|
||||||
|
By tessellating the 3d polygon into individual smaller tiles that
|
||||||
|
are perfectly coplanar (triangles, for example), we can get CGAL to accept
|
||||||
|
the polyhedron() input.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum { XYPLANE, YZPLANE, XZPLANE, NONE } projection_t;
|
||||||
|
|
||||||
|
// this is how we make 3d points appear as though they were 2d points to
|
||||||
|
//the tessellation algorithm.
|
||||||
|
Vector2d get_projected_point( Vector3d v, projection_t projection ) {
|
||||||
|
Vector2d v2(0,0);
|
||||||
|
if (projection==XYPLANE) { v2.x() = v.x(); v2.y() = v.y(); }
|
||||||
|
else if (projection==XZPLANE) { v2.x() = v.x(); v2.y() = v.z(); }
|
||||||
|
else if (projection==YZPLANE) { v2.x() = v.y(); v2.y() = v.z(); }
|
||||||
|
return v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGAL_Point_3 cgp( Vector3d v ) { return CGAL_Point_3( v.x(), v.y(), v.z() ); }
|
||||||
|
|
||||||
|
/* Find a 'good' 2d projection for a given 3d polygon. the XY, YZ, or XZ
|
||||||
|
plane. This is needed because near-planar polygons in 3d can have 'bad'
|
||||||
|
projections into 2d. For example if the square 0,0,0 0,1,0 0,1,1 0,0,1
|
||||||
|
is projected onto the XY plane you will not get a polygon, you wil get
|
||||||
|
a skinny line thing. It's better to project that square onto the yz
|
||||||
|
plane.*/
|
||||||
|
projection_t find_good_projection( PolySet::Polygon pgon ) {
|
||||||
|
// step 1 - find 3 non-collinear points in the input
|
||||||
|
if (pgon.size()<3) return NONE;
|
||||||
|
Vector3d v1,v2,v3;
|
||||||
|
v1 = v2 = v3 = pgon[0];
|
||||||
|
for (size_t i=0;i<pgon.size();i++) {
|
||||||
|
if (pgon[i]!=v1) { v2=pgon[i]; break; }
|
||||||
|
}
|
||||||
|
if (v1==v2) return NONE;
|
||||||
|
for (size_t i=0;i<pgon.size();i++) {
|
||||||
|
if (!CGAL::collinear( cgp(v1), cgp(v2), cgp(pgon[i]) )) {
|
||||||
|
v3=pgon[i]; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CGAL::collinear( cgp(v1), cgp(v2), cgp(v3) ) ) return NONE;
|
||||||
|
// step 2 - find which direction is best for projection. planes use
|
||||||
|
// the equation ax+by+cz+d = 0. a,b, and c determine the direction the
|
||||||
|
// plane is in. we want to find which projection of the 'normal vector'
|
||||||
|
// would make the smallest shadow if projected onto the XY, YZ, or XZ
|
||||||
|
// plane. 'quadrance' (distance squared) can tell this w/o using sqrt.
|
||||||
|
CGAL::Plane_3<CGAL_Kernel3> pl( cgp(v1), cgp(v2), cgp(v3) );
|
||||||
|
NT3 qxy = pl.a()*pl.a()+pl.b()*pl.b();
|
||||||
|
NT3 qyz = pl.b()*pl.b()+pl.c()*pl.c();
|
||||||
|
NT3 qxz = pl.c()*pl.c()+pl.a()*pl.a();
|
||||||
|
NT3 min = std::min(qxy,std::min(qyz,qxz));
|
||||||
|
if (min==qxy) return XYPLANE;
|
||||||
|
else if (min==qyz) return YZPLANE;
|
||||||
|
return XZPLANE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* triangulate the given 3d polygon using CGAL's 2d Constrained Delaunay
|
||||||
|
algorithm. Project the polygon's points into 2d using the given projection
|
||||||
|
before performing the triangulation. This code assumes input polygon is
|
||||||
|
simple, no holes, no self-intersections, no duplicate points, and is
|
||||||
|
properly oriented. output is a sequence of 3d triangles. */
|
||||||
|
bool triangulate_polygon( const PolySet::Polygon &pgon, std::vector<PolySet::Polygon> &triangles, projection_t projection )
|
||||||
|
{
|
||||||
|
bool err = false;
|
||||||
|
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||||
|
try {
|
||||||
|
CDT cdt;
|
||||||
|
std::vector<Vertex_handle> vhandles;
|
||||||
|
std::map<CDTPoint,Vector3d> vertmap;
|
||||||
|
CGAL::Orientation original_orientation;
|
||||||
|
std::vector<CDTPoint> orienpgon;
|
||||||
|
for (size_t i = 0; i < pgon.size(); i++) {
|
||||||
|
Vector3d v3 = pgon.at(i);
|
||||||
|
Vector2d v2 = get_projected_point( v3, projection );
|
||||||
|
CDTPoint cdtpoint = CDTPoint(v2.x(),v2.y());
|
||||||
|
vertmap[ cdtpoint ] = v3;
|
||||||
|
Vertex_handle vh = cdt.insert( cdtpoint );
|
||||||
|
vhandles.push_back(vh);
|
||||||
|
orienpgon.push_back( cdtpoint );
|
||||||
|
}
|
||||||
|
original_orientation = CGAL::orientation_2( orienpgon.begin(),orienpgon.end() );
|
||||||
|
for (size_t i = 0; i < vhandles.size(); i++ ) {
|
||||||
|
int vindex1 = (i+0);
|
||||||
|
int vindex2 = (i+1)%vhandles.size();
|
||||||
|
cdt.insert_constraint( vhandles[vindex1], vhandles[vindex2] );
|
||||||
|
}
|
||||||
|
std::list<CDTPoint> list_of_seeds;
|
||||||
|
CGAL::refine_Delaunay_mesh_2_without_edge_refinement(cdt,
|
||||||
|
list_of_seeds.begin(), list_of_seeds.end(), DummyCriteria<CDT>());
|
||||||
|
|
||||||
|
CDT::Finite_faces_iterator fit;
|
||||||
|
for( fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++ )
|
||||||
|
{
|
||||||
|
if(fit->is_in_domain()) {
|
||||||
|
CDTPoint p1 = cdt.triangle( fit )[0];
|
||||||
|
CDTPoint p2 = cdt.triangle( fit )[1];
|
||||||
|
CDTPoint p3 = cdt.triangle( fit )[2];
|
||||||
|
Vector3d v1 = vertmap[p1];
|
||||||
|
Vector3d v2 = vertmap[p2];
|
||||||
|
Vector3d v3 = vertmap[p3];
|
||||||
|
PolySet::Polygon pgon;
|
||||||
|
if (CGAL::orientation(p1,p2,p3)==original_orientation) {
|
||||||
|
pgon.push_back(v1);
|
||||||
|
pgon.push_back(v2);
|
||||||
|
pgon.push_back(v3);
|
||||||
|
} else {
|
||||||
|
pgon.push_back(v3);
|
||||||
|
pgon.push_back(v2);
|
||||||
|
pgon.push_back(v1);
|
||||||
|
}
|
||||||
|
triangles.push_back( pgon );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const CGAL::Failure_exception &e) {
|
||||||
|
// Using failure exception to catch precondition errors for malformed polygons
|
||||||
|
// in e.g. CGAL::orientation_2().
|
||||||
|
PRINTB("CGAL error in triangulate_polygon(): %s", e.what());
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
CGAL::set_error_behaviour(old_behaviour);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a 3d PolySet with 'near planar' polygonal faces, Tessellate the
|
||||||
|
faces. As of writing, our only tessellation method is Triangulation
|
||||||
|
using CGAL's Constrained Delaunay algorithm. This code assumes the input
|
||||||
|
polyset has simple polygon faces with no holes, no self intersections, no
|
||||||
|
duplicate points, and proper orientation. */
|
||||||
|
void tessellate_faces(const PolySet &inps, PolySet &outps) {
|
||||||
|
int degeneratePolygons = 0;
|
||||||
|
for (size_t i = 0; i < inps.polygons.size(); i++) {
|
||||||
|
const PolySet::Polygon pgon = inps.polygons[i];
|
||||||
|
if (pgon.size() < 3) {
|
||||||
|
degeneratePolygons++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::vector<PolySet::Polygon> triangles;
|
||||||
|
if (pgon.size() == 3) {
|
||||||
|
triangles.push_back(pgon);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
projection_t goodproj = find_good_projection( pgon );
|
||||||
|
if (goodproj==NONE) {
|
||||||
|
degeneratePolygons++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool err = triangulate_polygon(pgon, triangles, goodproj);
|
||||||
|
if (err) continue;
|
||||||
|
}
|
||||||
|
for (size_t j=0;j<triangles.size();j++) {
|
||||||
|
PolySet::Polygon t = triangles[j];
|
||||||
|
outps.append_poly();
|
||||||
|
outps.append_vertex(t[0].x(),t[0].y(),t[0].z());
|
||||||
|
outps.append_vertex(t[1].x(),t[1].y(),t[1].z());
|
||||||
|
outps.append_vertex(t[2].x(),t[2].y(),t[2].z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (degeneratePolygons > 0) PRINT("WARNING: PolySet has degenerate polygons");
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,40 +10,17 @@
|
||||||
#endif
|
#endif
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
|
||||||
#include <CGAL/Delaunay_mesher_2.h>
|
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
|
||||||
#include <CGAL/Delaunay_mesher_no_edge_refinement_2.h>
|
|
||||||
#include <CGAL/Delaunay_mesh_face_base_2.h>
|
|
||||||
#include <CGAL/Delaunay_mesh_criteria_2.h>
|
|
||||||
#include <CGAL/Mesh_2/Face_badness.h>
|
|
||||||
#ifdef PREV_NDEBUG
|
#ifdef PREV_NDEBUG
|
||||||
#define NDEBUG PREV_NDEBUG
|
#define NDEBUG PREV_NDEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||||
typedef CGAL::Triangulation_vertex_base_2<K> Vb;
|
typedef CGAL::Triangulation_2_filtered_projection_traits_3<K> Projection;
|
||||||
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;
|
typedef CGAL::Triangulation_data_structure_2 <
|
||||||
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
|
CGAL::Triangulation_vertex_base_2<Projection>,
|
||||||
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag > CDT;
|
CGAL::Constrained_triangulation_face_base_2<Projection> > Tds;
|
||||||
//typedef CGAL::Delaunay_mesh_criteria_2<CDT> Criteria;
|
typedef CGAL::Constrained_Delaunay_triangulation_2<Projection, Tds, CGAL::Exact_predicates_tag> CDT;
|
||||||
|
|
||||||
typedef CDT::Vertex_handle Vertex_handle;
|
|
||||||
typedef CDT::Point CDTPoint;
|
|
||||||
|
|
||||||
template <class T> class DummyCriteria {
|
|
||||||
public:
|
|
||||||
typedef double Quality;
|
|
||||||
class Is_bad {
|
|
||||||
public:
|
|
||||||
CGAL::Mesh_2::Face_badness operator()(const Quality) const {
|
|
||||||
return CGAL::Mesh_2::NOT_BAD;
|
|
||||||
}
|
|
||||||
CGAL::Mesh_2::Face_badness operator()(const typename T::Face_handle&, Quality&q) const {
|
|
||||||
q = 1;
|
|
||||||
return CGAL::Mesh_2::NOT_BAD;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Is_bad is_bad_object() const { return Is_bad(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
@ -70,19 +47,6 @@ namespace PolysetUtils {
|
||||||
This code is for tessellating the faces of a 3d PolySet, assuming that
|
This code is for tessellating the faces of a 3d PolySet, assuming that
|
||||||
the faces are near-planar polygons.
|
the faces are near-planar polygons.
|
||||||
|
|
||||||
We do the tessellation by projecting each polygon of the Polyset onto a
|
|
||||||
2-d plane, then running a 2d tessellation algorithm on the projected 2d
|
|
||||||
polygon. Then we project each of the newly generated 2d 'tiles' (the
|
|
||||||
polygons used for tessellation, typically triangles) back up into 3d
|
|
||||||
space.
|
|
||||||
|
|
||||||
(in reality as of writing, we dont need to do a back-projection from 2d->3d
|
|
||||||
because the algorithm we are using doesn't create any new points, and we can
|
|
||||||
just use a 'map' to associate 3d points with 2d points).
|
|
||||||
|
|
||||||
The code assumes the input polygons are simple, non-intersecting, without
|
|
||||||
holes, without duplicate input points, and with proper orientation.
|
|
||||||
|
|
||||||
The purpose of this code is originally to fix github issue 349. Our CGAL
|
The purpose of this code is originally to fix github issue 349. Our CGAL
|
||||||
kernel does not accept polygons for Nef_Polyhedron_3 if each of the
|
kernel does not accept polygons for Nef_Polyhedron_3 if each of the
|
||||||
points is not exactly coplanar. "Near-planar" or "Almost planar" polygons
|
points is not exactly coplanar. "Near-planar" or "Almost planar" polygons
|
||||||
|
@ -92,126 +56,12 @@ namespace PolysetUtils {
|
||||||
the polyhedron() input.
|
the polyhedron() input.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum { XYPLANE, YZPLANE, XZPLANE, NONE } projection_t;
|
/* Given a 3D PolySet with near planar polygonal faces, tessellate the
|
||||||
|
faces. As of writing, our only tessellation method is triangulation
|
||||||
// this is how we make 3d points appear as though they were 2d points to
|
|
||||||
//the tessellation algorithm.
|
|
||||||
Vector2d get_projected_point( Vector3d v, projection_t projection ) {
|
|
||||||
Vector2d v2(0,0);
|
|
||||||
if (projection==XYPLANE) { v2.x() = v.x(); v2.y() = v.y(); }
|
|
||||||
else if (projection==XZPLANE) { v2.x() = v.x(); v2.y() = v.z(); }
|
|
||||||
else if (projection==YZPLANE) { v2.x() = v.y(); v2.y() = v.z(); }
|
|
||||||
return v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGAL_Point_3 cgp( Vector3d v ) { return CGAL_Point_3( v.x(), v.y(), v.z() ); }
|
|
||||||
|
|
||||||
/* Find a 'good' 2d projection for a given 3d polygon. the XY, YZ, or XZ
|
|
||||||
plane. This is needed because near-planar polygons in 3d can have 'bad'
|
|
||||||
projections into 2d. For example if the square 0,0,0 0,1,0 0,1,1 0,0,1
|
|
||||||
is projected onto the XY plane you will not get a polygon, you wil get
|
|
||||||
a skinny line thing. It's better to project that square onto the yz
|
|
||||||
plane.*/
|
|
||||||
projection_t find_good_projection( PolySet::Polygon pgon ) {
|
|
||||||
// step 1 - find 3 non-collinear points in the input
|
|
||||||
if (pgon.size()<3) return NONE;
|
|
||||||
Vector3d v1,v2,v3;
|
|
||||||
v1 = v2 = v3 = pgon[0];
|
|
||||||
for (size_t i=0;i<pgon.size();i++) {
|
|
||||||
if (pgon[i]!=v1) { v2=pgon[i]; break; }
|
|
||||||
}
|
|
||||||
if (v1==v2) return NONE;
|
|
||||||
for (size_t i=0;i<pgon.size();i++) {
|
|
||||||
if (!CGAL::collinear( cgp(v1), cgp(v2), cgp(pgon[i]) )) {
|
|
||||||
v3=pgon[i]; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CGAL::collinear( cgp(v1), cgp(v2), cgp(v3) ) ) return NONE;
|
|
||||||
// step 2 - find which direction is best for projection. planes use
|
|
||||||
// the equation ax+by+cz+d = 0. a,b, and c determine the direction the
|
|
||||||
// plane is in. we want to find which projection of the 'normal vector'
|
|
||||||
// would make the smallest shadow if projected onto the XY, YZ, or XZ
|
|
||||||
// plane. 'quadrance' (distance squared) can tell this w/o using sqrt.
|
|
||||||
CGAL::Plane_3<CGAL_Kernel3> pl( cgp(v1), cgp(v2), cgp(v3) );
|
|
||||||
NT3 qxy = pl.a()*pl.a()+pl.b()*pl.b();
|
|
||||||
NT3 qyz = pl.b()*pl.b()+pl.c()*pl.c();
|
|
||||||
NT3 qxz = pl.c()*pl.c()+pl.a()*pl.a();
|
|
||||||
NT3 min = std::min(qxy,std::min(qyz,qxz));
|
|
||||||
if (min==qxy) return XYPLANE;
|
|
||||||
else if (min==qyz) return YZPLANE;
|
|
||||||
return XZPLANE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* triangulate the given 3d polygon using CGAL's 2d Constrained Delaunay
|
|
||||||
algorithm. Project the polygon's points into 2d using the given projection
|
|
||||||
before performing the triangulation. This code assumes input polygon is
|
|
||||||
simple, no holes, no self-intersections, no duplicate points, and is
|
|
||||||
properly oriented. output is a sequence of 3d triangles. */
|
|
||||||
bool triangulate_polygon( const PolySet::Polygon &pgon, std::vector<PolySet::Polygon> &triangles, projection_t projection )
|
|
||||||
{
|
|
||||||
bool err = false;
|
|
||||||
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
|
||||||
try {
|
|
||||||
CDT cdt;
|
|
||||||
std::vector<Vertex_handle> vhandles;
|
|
||||||
std::map<CDTPoint,Vector3d> vertmap;
|
|
||||||
CGAL::Orientation original_orientation;
|
|
||||||
std::vector<CDTPoint> orienpgon;
|
|
||||||
for (size_t i = 0; i < pgon.size(); i++) {
|
|
||||||
Vector3d v3 = pgon.at(i);
|
|
||||||
Vector2d v2 = get_projected_point( v3, projection );
|
|
||||||
CDTPoint cdtpoint = CDTPoint(v2.x(),v2.y());
|
|
||||||
vertmap[ cdtpoint ] = v3;
|
|
||||||
Vertex_handle vh = cdt.insert( cdtpoint );
|
|
||||||
vhandles.push_back(vh);
|
|
||||||
orienpgon.push_back( cdtpoint );
|
|
||||||
}
|
|
||||||
original_orientation = CGAL::orientation_2( orienpgon.begin(),orienpgon.end() );
|
|
||||||
for (size_t i = 0; i < vhandles.size(); i++ ) {
|
|
||||||
int vindex1 = (i+0);
|
|
||||||
int vindex2 = (i+1)%vhandles.size();
|
|
||||||
cdt.insert_constraint( vhandles[vindex1], vhandles[vindex2] );
|
|
||||||
}
|
|
||||||
std::list<CDTPoint> list_of_seeds;
|
|
||||||
CGAL::refine_Delaunay_mesh_2_without_edge_refinement(cdt,
|
|
||||||
list_of_seeds.begin(), list_of_seeds.end(), DummyCriteria<CDT>());
|
|
||||||
|
|
||||||
CDT::Finite_faces_iterator fit;
|
|
||||||
for( fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++ )
|
|
||||||
{
|
|
||||||
if(fit->is_in_domain()) {
|
|
||||||
CDTPoint p1 = cdt.triangle( fit )[0];
|
|
||||||
CDTPoint p2 = cdt.triangle( fit )[1];
|
|
||||||
CDTPoint p3 = cdt.triangle( fit )[2];
|
|
||||||
Vector3d v1 = vertmap[p1];
|
|
||||||
Vector3d v2 = vertmap[p2];
|
|
||||||
Vector3d v3 = vertmap[p3];
|
|
||||||
PolySet::Polygon pgon;
|
|
||||||
if (CGAL::orientation(p1,p2,p3)==original_orientation) {
|
|
||||||
pgon.push_back(v1);
|
|
||||||
pgon.push_back(v2);
|
|
||||||
pgon.push_back(v3);
|
|
||||||
} else {
|
|
||||||
pgon.push_back(v3);
|
|
||||||
pgon.push_back(v2);
|
|
||||||
pgon.push_back(v1);
|
|
||||||
}
|
|
||||||
triangles.push_back( pgon );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (const CGAL::Assertion_exception &e) {
|
|
||||||
PRINTB("CGAL error in triangulate_polygon(): %s", e.what());
|
|
||||||
err = true;
|
|
||||||
}
|
|
||||||
CGAL::set_error_behaviour(old_behaviour);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Given a 3d PolySet with 'near planar' polygonal faces, Tessellate the
|
|
||||||
faces. As of writing, our only tessellation method is Triangulation
|
|
||||||
using CGAL's Constrained Delaunay algorithm. This code assumes the input
|
using CGAL's Constrained Delaunay algorithm. This code assumes the input
|
||||||
polyset has simple polygon faces with no holes, no self intersections, no
|
polyset has simple polygon faces with no holes.
|
||||||
duplicate points, and proper orientation. */
|
The tessellation will be robust wrt. degenerate and self-intersecting
|
||||||
|
*/
|
||||||
void tessellate_faces(const PolySet &inps, PolySet &outps) {
|
void tessellate_faces(const PolySet &inps, PolySet &outps) {
|
||||||
int degeneratePolygons = 0;
|
int degeneratePolygons = 0;
|
||||||
for (size_t i = 0; i < inps.polygons.size(); i++) {
|
for (size_t i = 0; i < inps.polygons.size(); i++) {
|
||||||
|
@ -225,23 +75,47 @@ namespace PolysetUtils {
|
||||||
triangles.push_back(pgon);
|
triangles.push_back(pgon);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
projection_t goodproj = find_good_projection( pgon );
|
// Build a data structure that CGAL accepts
|
||||||
if (goodproj==NONE) {
|
std::vector<K::Point_3> cgalpoints;
|
||||||
degeneratePolygons++;
|
BOOST_FOREACH(const Vector3d &v, pgon) {
|
||||||
continue;
|
cgalpoints.push_back(K::Point_3(v[0], v[1], v[2]));
|
||||||
|
}
|
||||||
|
// Calculate best guess at face normal using Newell's method
|
||||||
|
K::Vector_3 normal;
|
||||||
|
CGAL::normal_vector_newell_3(cgalpoints.begin(), cgalpoints.end(), normal);
|
||||||
|
|
||||||
|
// Pass the normal vector to the (undocumented)
|
||||||
|
// CGAL::Triangulation_2_filtered_projection_traits_3. This
|
||||||
|
// trait deals with projection from 3D to 2D using the normal
|
||||||
|
// vector as a hint, and allows for near-planar polygons to be passed to
|
||||||
|
// the Constrained Delaunay Triangulator.
|
||||||
|
Projection actualProjection(normal);
|
||||||
|
CDT cdt(actualProjection);
|
||||||
|
for (size_t i=0;i<cgalpoints.size(); i++) {
|
||||||
|
cdt.insert_constraint(cgalpoints[i], cgalpoints[(i+1)%cgalpoints.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the resulting faces
|
||||||
|
CDT::Finite_faces_iterator fit;
|
||||||
|
for (fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++) {
|
||||||
|
PolySet::Polygon pgon;
|
||||||
|
for (int i=0;i<3;i++) {
|
||||||
|
const K::Point_3 &v = cdt.triangle(fit)[i];
|
||||||
|
pgon.push_back(Vector3d(v.x(), v.y(), v.z()));
|
||||||
|
}
|
||||||
|
triangles.push_back(pgon);
|
||||||
}
|
}
|
||||||
bool err = triangulate_polygon(pgon, triangles, goodproj);
|
|
||||||
if (err) continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ..and pass to the output polyhedron
|
||||||
for (size_t j=0;j<triangles.size();j++) {
|
for (size_t j=0;j<triangles.size();j++) {
|
||||||
PolySet::Polygon t = triangles[j];
|
PolySet::Polygon t = triangles[j];
|
||||||
outps.append_poly();
|
outps.append_poly();
|
||||||
outps.append_vertex(t[0].x(),t[0].y(),t[0].z());
|
outps.append_vertex(t[0].x(),t[0].y(),t[0].z());
|
||||||
outps.append_vertex(t[1].x(),t[1].y(),t[1].z());
|
outps.append_vertex(t[1].x(),t[1].y(),t[1].z());
|
||||||
outps.append_vertex(t[2].x(),t[2].y(),t[2].z());
|
outps.append_vertex(t[2].x(),t[2].y(),t[2].z());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (degeneratePolygons > 0) PRINT("WARNING: PolySet has degenerate polygons");
|
if (degeneratePolygons > 0) PRINT("WARNING: PolySet has degenerate polygons");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
polyhedron(points=[
|
||||||
|
[0,0,0],
|
||||||
|
[10,0,0],
|
||||||
|
[10,10,0],
|
||||||
|
[0,10,0],
|
||||||
|
[0,-20,20],
|
||||||
|
[10,-20,20],
|
||||||
|
[10,-20,30],
|
||||||
|
[0,-20,30]
|
||||||
|
],
|
||||||
|
faces = [[0,1,2,3],[4,5,6,7],
|
||||||
|
[1,2,5,4],
|
||||||
|
[2,3,6,5],
|
||||||
|
[3,0,6,5],
|
||||||
|
[0,1,4,7]
|
||||||
|
]);
|
|
@ -0,0 +1 @@
|
||||||
|
polyhedron(points = [[8.4991, -4.98973, 62.7876], [-0.423767, 0.0568668, 64.4948], [-0.505246, -10.1774, 62.6914], [9.17023, -6.28686, 70.9731], [0.213931, -1.18909, 69.6324], [0.168244, -11.4782, 71.0926], [6.96718, -1.88303, 76.9407], [0.507199, -1.73168, 68.8016], [-2.19023, -6.7664, 77.4835], [3.05033, 5.76153, 77.3746], [-2.1412, 3.4281, 68.6796], [-6.17499, 1.01119, 77.9472]], faces = [[0, 3, 4, 1], [1, 4, 5, 2], [2, 5, 3, 0], [3, 6, 7, 4], [4, 7, 8, 5], [5, 8, 6, 3], [6, 9, 10, 7], [7, 10, 11, 8], [8, 11, 9, 6], [2, 1, 0], [9, 10, 11]]);
|
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 8.9 KiB |
|
@ -25,6 +25,7 @@ import getopt
|
||||||
import shutil
|
import shutil
|
||||||
import platform
|
import platform
|
||||||
import string
|
import string
|
||||||
|
import difflib
|
||||||
|
|
||||||
#_debug_tcct = True
|
#_debug_tcct = True
|
||||||
_debug_tcct = False
|
_debug_tcct = False
|
||||||
|
@ -99,12 +100,15 @@ def compare_text(expected, actual):
|
||||||
return get_normalized_text(expected) == get_normalized_text(actual)
|
return get_normalized_text(expected) == get_normalized_text(actual)
|
||||||
|
|
||||||
def compare_default(resultfilename):
|
def compare_default(resultfilename):
|
||||||
print >> sys.stderr, 'diff text compare: '
|
print >> sys.stderr, 'text comparison: '
|
||||||
print >> sys.stderr, ' expected textfile: ', expectedfilename
|
print >> sys.stderr, ' expected textfile: ', expectedfilename
|
||||||
print >> sys.stderr, ' actual textfile: ', resultfilename
|
print >> sys.stderr, ' actual textfile: ', resultfilename
|
||||||
if not compare_text(expectedfilename, resultfilename):
|
expected_text = get_normalized_text(expectedfilename)
|
||||||
|
actual_text = get_normalized_text(resultfilename)
|
||||||
|
if not expected_text == actual_text:
|
||||||
if resultfilename:
|
if resultfilename:
|
||||||
execute_and_redirect("diff", ["-u", expectedfilename, resultfilename], sys.stderr)
|
differences = difflib.unified_diff(expected_text.splitlines(1), actual_text.splitlines(1))
|
||||||
|
for line in differences: sys.stderr.write(line)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|