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
|
||||
Exec=openscad %f
|
||||
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/GeometryCache.cc \
|
||||
src/Tree.cc \
|
||||
src/DrawingCallback.cc \
|
||||
src/FreetypeRenderer.cc \
|
||||
src/FontCache.cc \
|
||||
src/DrawingCallback.cc \
|
||||
src/FreetypeRenderer.cc \
|
||||
src/FontCache.cc \
|
||||
\
|
||||
src/rendersettings.cc \
|
||||
src/highlighter.cc \
|
||||
|
@ -397,7 +397,7 @@ src/FontCache.cc \
|
|||
src/openscad.cc \
|
||||
src/mainwin.cc \
|
||||
src/UIUtils.cc \
|
||||
src/FontListDialog.cc \
|
||||
src/FontListDialog.cc \
|
||||
src/launchingscreen.cpp \
|
||||
src/legacyeditor.cc \
|
||||
src/LibraryInfoDialog.cc
|
||||
|
@ -474,6 +474,10 @@ libraries.path = $$PREFIX/share/openscad/libraries/
|
|||
libraries.files = libraries/*
|
||||
INSTALLS += libraries
|
||||
|
||||
fonts.path = $$PREFIX/share/openscad/fonts/
|
||||
fonts.files = fonts/*
|
||||
INSTALLS += fonts
|
||||
|
||||
applications.path = $$PREFIX/share/applications
|
||||
applications.files = icons/openscad.desktop
|
||||
INSTALLS += applications
|
||||
|
|
|
@ -170,7 +170,7 @@
|
|||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">openscad</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.ProFile">openscad.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
|
|
47
openscad.qrc
|
@ -11,6 +11,53 @@
|
|||
<file>icons/prefsUpdate.png</file>
|
||||
<file>icons/flattr.png</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>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
diff --git a/opencsg.pro b/opencsg.pro
|
||||
index b56e622..5cf2d6d 100644
|
||||
--- a/opencsg.pro
|
||||
+++ b/opencsg.pro
|
||||
@@ -1,2 +1,2 @@
|
||||
|
@ -6,17 +7,25 @@ diff --git a/opencsg.pro b/opencsg.pro
|
|||
-SUBDIRS = src example
|
||||
+SUBDIRS = src
|
||||
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
|
||||
+++ OpenCSG-1.4.0-mac/src/src.pro 2014-09-15 18:17:09.000000000 -0400
|
||||
@@ -8,10 +8,9 @@
|
||||
index 9091251..598112a 100644
|
||||
--- a/src/src.pro
|
||||
+++ 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
|
||||
|
||||
DESTDIR = ../lib
|
||||
-DESTDIR = ../lib
|
||||
-INSTALLDIR = /usr/local
|
||||
headers.files = ../include/opencsg.h
|
||||
headers.path = $$INSTALLDIR/include
|
||||
-headers.path = $$INSTALLDIR/include
|
||||
-target.path = /usr/local/lib
|
||||
+target.path = $$INSTALLDIR/lib
|
||||
+headers.path = $$DESTDIR/include
|
||||
+target.path = $$DESTDIR/lib
|
||||
INSTALLS += target headers
|
||||
|
||||
HEADERS = ../include/opencsg.h \
|
||||
|
|
|
@ -427,7 +427,7 @@ build_opencsg()
|
|||
OPENCSG_EXTRA_FLAGS="x86"
|
||||
fi
|
||||
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()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QIcon>
|
||||
#include "ui_MainWindow.h"
|
||||
#include "UIUtils.h"
|
||||
#include "openscad.h"
|
||||
|
@ -106,6 +107,7 @@ private:
|
|||
QString get2dExportFilename(QString format, QString extension);
|
||||
void show_examples();
|
||||
void setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, bool topLevel);
|
||||
void addKeyboardShortCut(const QList<QAction *> &actions);
|
||||
|
||||
EditorInterface *editor;
|
||||
|
||||
|
@ -134,8 +136,10 @@ private slots:
|
|||
private slots:
|
||||
void pasteViewportTranslation();
|
||||
void pasteViewportRotation();
|
||||
void hideEditor();
|
||||
void preferences();
|
||||
void hideToolbars();
|
||||
void hideEditor();
|
||||
void hideConsole();
|
||||
|
||||
private slots:
|
||||
void selectFindType(int);
|
||||
|
@ -208,7 +212,6 @@ public slots:
|
|||
void viewOrthogonal();
|
||||
void viewResetView();
|
||||
void viewAll();
|
||||
void hideConsole();
|
||||
void animateUpdateDocChanged();
|
||||
void animateUpdate();
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>936</width>
|
||||
<width>1397</width>
|
||||
<height>586</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
@ -26,10 +26,10 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
@ -49,7 +49,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignBottom">
|
||||
<item>
|
||||
<widget class="QFrame" name="animate_panel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
@ -107,9 +107,32 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</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>
|
||||
<zorder>animate_panel</zorder>
|
||||
<zorder>qglview</zorder>
|
||||
<zorder>viewerToolBar</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -119,8 +142,6 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>936</width>
|
||||
<height>34</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
|
@ -244,8 +265,9 @@
|
|||
<addaction name="viewActionPerspective"/>
|
||||
<addaction name="viewActionOrthogonal"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="editActionHide"/>
|
||||
<addaction name="viewActionHide"/>
|
||||
<addaction name="viewActionHideToolBars"/>
|
||||
<addaction name="viewActionHideEditor"/>
|
||||
<addaction name="viewActionHideConsole"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
|
@ -270,11 +292,26 @@
|
|||
<number>1</number>
|
||||
</attribute>
|
||||
<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">
|
||||
<number>0</number>
|
||||
</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">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
@ -396,6 +433,10 @@
|
|||
</widget>
|
||||
</widget>
|
||||
<action name="fileActionNew">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackNew.png</normaloff>:/images/blackNew.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New</string>
|
||||
</property>
|
||||
|
@ -404,6 +445,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<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">
|
||||
<string>&Open...</string>
|
||||
</property>
|
||||
|
@ -412,6 +457,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<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">
|
||||
<string>&Save</string>
|
||||
</property>
|
||||
|
@ -559,7 +608,7 @@
|
|||
<string>Ctrl+-</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="editActionHide">
|
||||
<action name="viewActionHideEditor">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -576,6 +625,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<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">
|
||||
<string>&Preview</string>
|
||||
</property>
|
||||
|
@ -584,6 +637,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="designActionRender">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackRender.png</normaloff>:/images/blackRender.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Render</string>
|
||||
</property>
|
||||
|
@ -612,6 +669,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="designActionExportSTL">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/export.png</normaloff>:/images/export.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export as &STL...</string>
|
||||
</property>
|
||||
|
@ -669,6 +730,10 @@
|
|||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/Rotation-32.png</normaloff>:/images/Rotation-32.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Edges</string>
|
||||
</property>
|
||||
|
@ -680,6 +745,10 @@
|
|||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackaxes.png</normaloff>:/images/blackaxes.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Axes</string>
|
||||
</property>
|
||||
|
@ -691,6 +760,10 @@
|
|||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/cross.png</normaloff>:/images/cross.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Crosshairs</string>
|
||||
</property>
|
||||
|
@ -707,6 +780,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionTop">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackUp.png</normaloff>:/images/blackUp.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Top</string>
|
||||
</property>
|
||||
|
@ -715,6 +792,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionBottom">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackbottom.png</normaloff>:/images/blackbottom.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bottom</string>
|
||||
</property>
|
||||
|
@ -723,6 +804,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<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">
|
||||
<string>Left</string>
|
||||
</property>
|
||||
|
@ -731,6 +816,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionRight">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/rightright.png</normaloff>:/images/rightright.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right</string>
|
||||
</property>
|
||||
|
@ -739,6 +828,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionFront">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackfront.png</normaloff>:/images/blackfront.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Front</string>
|
||||
</property>
|
||||
|
@ -747,6 +840,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionBack">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/blackback.png</normaloff>:/images/blackback.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
|
@ -771,6 +868,10 @@
|
|||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/perspective1.png</normaloff>:/images/perspective1.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Perspective</string>
|
||||
</property>
|
||||
|
@ -779,11 +880,15 @@
|
|||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/orthogonal.png</normaloff>:/images/orthogonal.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Orthogonal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="viewActionHide">
|
||||
<action name="viewActionHideConsole">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
@ -934,6 +1039,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionZoomIn">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/zoomin.png</normaloff>:/images/zoomin.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom In</string>
|
||||
</property>
|
||||
|
@ -942,6 +1051,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<action name="viewActionZoomOut">
|
||||
<property name="icon">
|
||||
<iconset resource="../openscad.qrc">
|
||||
<normaloff>:/images/zoomout.png</normaloff>:/images/zoomout.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom Out</string>
|
||||
</property>
|
||||
|
@ -950,6 +1063,10 @@
|
|||
</property>
|
||||
</action>
|
||||
<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">
|
||||
<string>View All</string>
|
||||
</property>
|
||||
|
@ -959,6 +1076,14 @@
|
|||
<string>Convert Tabs to Spaces</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="viewActionHideToolBars">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hide toolbars</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -968,7 +1093,9 @@
|
|||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../openscad.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>fileActionClose</sender>
|
||||
|
|
117
src/mainwin.cc
|
@ -23,6 +23,7 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <iostream>
|
||||
#include "GeometryCache.h"
|
||||
#include "ModuleCache.h"
|
||||
#include "MainWindow.h"
|
||||
|
@ -169,9 +170,9 @@ MainWindow::MainWindow(const QString &filename)
|
|||
{
|
||||
setupUi(this);
|
||||
|
||||
editortype = Preferences::inst()->getValue("editor/editortype").toString();
|
||||
|
||||
editortype = Preferences::inst()->getValue("editor/editortype").toString();
|
||||
useScintilla = (editortype == "QScintilla Editor");
|
||||
|
||||
#ifdef USE_SCINTILLA_EDITOR
|
||||
if (useScintilla) {
|
||||
editor = new ScintillaEditor(editorDockContents);
|
||||
|
@ -267,8 +268,9 @@ MainWindow::MainWindow(const QString &filename)
|
|||
connect(this->appActionUpdateCheck, SIGNAL(triggered()), this, SLOT(actionUpdateCheck()));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 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->fileActionSave, SIGNAL(triggered()), this, SLOT(actionSave()));
|
||||
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->editActionZoomIn, SIGNAL(triggered()), editor, SLOT(zoomIn()));
|
||||
connect(this->editActionZoomOut, SIGNAL(triggered()), editor, SLOT(zoomOut()));
|
||||
connect(this->editActionHide, SIGNAL(triggered()), this, SLOT(hideEditor()));
|
||||
connect(this->editActionPreferences, SIGNAL(triggered()), this, SLOT(preferences()));
|
||||
// Edit->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->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective()));
|
||||
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->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
|
||||
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->replaceAllButton, SIGNAL(clicked()), this, SLOT(replaceAll()));
|
||||
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..
|
||||
QSettings settings;
|
||||
QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray();
|
||||
|
@ -476,6 +537,24 @@ MainWindow::MainWindow(const QString &filename)
|
|||
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(){
|
||||
QSettings settings;
|
||||
if (settings.value("view/showEdges").toBool()) {
|
||||
|
@ -495,10 +574,12 @@ void MainWindow::loadViewSettings(){
|
|||
} else {
|
||||
viewPerspective();
|
||||
}
|
||||
viewActionHide->setChecked(settings.value("view/hideConsole").toBool());
|
||||
viewActionHideConsole->setChecked(settings.value("view/hideConsole").toBool());
|
||||
hideConsole();
|
||||
editActionHide->setChecked(settings.value("view/hideEditor").toBool());
|
||||
viewActionHideEditor->setChecked(settings.value("view/hideEditor").toBool());
|
||||
hideEditor();
|
||||
viewActionHideToolBars->setChecked(settings.value("view/hideToolbar").toBool());
|
||||
hideToolbars();
|
||||
updateMdiMode(settings.value("advanced/mdi").toBool());
|
||||
updateUndockMode(settings.value("advanced/undockableWindows").toBool());
|
||||
}
|
||||
|
@ -2151,7 +2232,7 @@ void MainWindow::on_editorDock_visibilityChanged(bool visible)
|
|||
}
|
||||
QSettings settings;
|
||||
settings.setValue("view/hideEditor", !visible);
|
||||
editActionHide->setChecked(!visible);
|
||||
viewActionHideEditor->setChecked(!visible);
|
||||
editorTopLevelChanged(editorDock->isFloating());
|
||||
}
|
||||
|
||||
|
@ -2162,7 +2243,7 @@ void MainWindow::on_consoleDock_visibilityChanged(bool visible)
|
|||
}
|
||||
QSettings settings;
|
||||
settings.setValue("view/hideConsole", !visible);
|
||||
viewActionHide->setChecked(!visible);
|
||||
viewActionHideConsole->setChecked(!visible);
|
||||
consoleTopLevelChanged(consoleDock->isFloating());
|
||||
}
|
||||
|
||||
|
@ -2186,9 +2267,20 @@ void MainWindow::setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, boo
|
|||
dockWidget->setWindowTitle(title);
|
||||
}
|
||||
|
||||
void MainWindow::hideToolbars()
|
||||
{
|
||||
if (viewActionHideToolBars->isChecked()) {
|
||||
viewerToolBar->hide();
|
||||
editortoolbar->hide();
|
||||
} else {
|
||||
viewerToolBar->show();
|
||||
editortoolbar->show();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::hideEditor()
|
||||
{
|
||||
if (editActionHide->isChecked()) {
|
||||
if (viewActionHideEditor->isChecked()) {
|
||||
editorDock->close();
|
||||
} else {
|
||||
editorDock->show();
|
||||
|
@ -2196,8 +2288,9 @@ void MainWindow::hideEditor()
|
|||
}
|
||||
|
||||
void MainWindow::hideConsole()
|
||||
|
||||
{
|
||||
if (viewActionHide->isChecked()) {
|
||||
if (viewActionHideConsole->isChecked()) {
|
||||
consoleDock->hide();
|
||||
} else {
|
||||
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
|
||||
#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>
|
||||
#include <CGAL/Triangulation_2_filtered_projection_traits_3.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(); }
|
||||
};
|
||||
typedef CGAL::Triangulation_2_filtered_projection_traits_3<K> Projection;
|
||||
typedef CGAL::Triangulation_data_structure_2 <
|
||||
CGAL::Triangulation_vertex_base_2<Projection>,
|
||||
CGAL::Constrained_triangulation_face_base_2<Projection> > Tds;
|
||||
typedef CGAL::Constrained_Delaunay_triangulation_2<Projection, Tds, CGAL::Exact_predicates_tag> CDT;
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
@ -70,19 +47,6 @@ namespace PolysetUtils {
|
|||
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
|
||||
|
@ -92,126 +56,12 @@ namespace PolysetUtils {
|
|||
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::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
|
||||
/* 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. */
|
||||
polyset has simple polygon faces with no holes.
|
||||
The tessellation will be robust wrt. degenerate and self-intersecting
|
||||
*/
|
||||
void tessellate_faces(const PolySet &inps, PolySet &outps) {
|
||||
int degeneratePolygons = 0;
|
||||
for (size_t i = 0; i < inps.polygons.size(); i++) {
|
||||
|
@ -225,23 +75,47 @@ namespace PolysetUtils {
|
|||
triangles.push_back(pgon);
|
||||
}
|
||||
else {
|
||||
projection_t goodproj = find_good_projection( pgon );
|
||||
if (goodproj==NONE) {
|
||||
degeneratePolygons++;
|
||||
continue;
|
||||
// Build a data structure that CGAL accepts
|
||||
std::vector<K::Point_3> cgalpoints;
|
||||
BOOST_FOREACH(const Vector3d &v, pgon) {
|
||||
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++) {
|
||||
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());
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 platform
|
||||
import string
|
||||
import difflib
|
||||
|
||||
#_debug_tcct = True
|
||||
_debug_tcct = False
|
||||
|
@ -99,12 +100,15 @@ def compare_text(expected, actual):
|
|||
return get_normalized_text(expected) == get_normalized_text(actual)
|
||||
|
||||
def compare_default(resultfilename):
|
||||
print >> sys.stderr, 'diff text compare: '
|
||||
print >> sys.stderr, 'text comparison: '
|
||||
print >> sys.stderr, ' expected textfile: ', expectedfilename
|
||||
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:
|
||||
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 True
|
||||
|
||||
|
|