branch updated

This commit is contained in:
amarjeetkapoor1 2016-05-21 09:27:24 +05:30
commit 21d12601c5
479 changed files with 18923 additions and 14226 deletions

7
.gitignore vendored
View file

@ -1,3 +1,5 @@
/*.scad
**/out*.*
*.dmg
*~
*.tar*
@ -9,13 +11,12 @@ objects
.qmake.stash
parser_yacc.h
**/#*#
testdata/scad/features/import_dxf-tests.scad
testdata/scad/features/import_stl-tests.scad
testdata/scad/2D/features/import_dxf-tests.scad
testdata/scad/3D/features/import_stl-tests.scad
testdata/scad/misc/include-tests.scad
testdata/scad/misc/use-tests.scad
**/project.xcworkspace
**/xcuserdata
/*.scad
/*.stl
/*.dxf
/*.off

View file

@ -2,6 +2,8 @@
[![Coverity Status](https://scan.coverity.com/projects/2510/badge.svg)](https://scan.coverity.com/projects/2510)
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/openscad/openscad/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
[![Visit our IRC channel](https://kiwiirc.com/buttons/irc.freenode.net/openscad.png)](https://kiwiirc.com/client/irc.freenode.net/#openscad)
# What is OpenSCAD?
[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=openscad&url=http://openscad.org&title=OpenSCAD&language=&tags=github&category=software)
@ -88,13 +90,14 @@ libraries from aptitude. If you're using Mac, or an older Linux/BSD, there
are build scripts that download and compile the libraries from source.
Follow the instructions for the platform you're compiling on below.
* [Qt4 (4.4 - 5.4)](http://www.qt.nokia.com/)
* [QScintilla2 (2.7 - 2.8)](http://www.riverbankcomputing.co.uk/software/qscintilla/)
* [CGAL (3.6 - 4.5)](http://www.cgal.org/)
* A C++ compiler supporting C++11
* [Qt4 (4.4 ->)](http://www.qt.nokia.com/)
* [QScintilla2 (2.7 ->)](http://www.riverbankcomputing.co.uk/software/qscintilla/)
* [CGAL (3.6 ->)](http://www.cgal.org/)
* [GMP (5.x)](http://www.gmplib.org/)
* [MPFR (3.x)](http://www.mpfr.org/)
* [cmake (2.8 - 3.0, required by CGAL and the test framework)](http://www.cmake.org/)
* [boost (1.35 - 1.57)](http://www.boost.org/)
* [cmake (2.8 ->, required by CGAL and the test framework)](http://www.cmake.org/)
* [boost (1.35 ->)](http://www.boost.org/)
* [OpenCSG (1.3.2 ->)](http://www.opencsg.org/)
* [GLEW (1.5.4 ->)](http://glew.sourceforge.net/)
* [Eigen (3.x)](http://eigen.tuxfamily.org/)
@ -123,12 +126,14 @@ To pull the MCAD library (http://reprap.org/wiki/MCAD), do the following:
Prerequisites:
* XCode, including XCode command-line tools.
* Xcode
* cmake
* pkg-config
Install Dependencies:
Run the script that sets up the environment variables:
```source setenv_mac-qt5.sh```
```source setenv_mac.sh```
Then run the script to compile all the dependencies:
```./scripts/macosx-build-dependencies.sh```
@ -147,7 +152,7 @@ For the adventurous, it might be possible to build OpenSCAD using _MacPorts_ or
```sudo port install opencsg qscintilla boost cgal pkgconfig eigen3 harfbuzz fontconfig```
1. **Homebrew** (assumes [Homebrew](http://brew.sh)) is already installed)
1. **Homebrew** (assumes [Homebrew](http://brew.sh) is already installed)
NB! Homebrew's ```qscintilla2``` component doesn't support Qt5, so using Qt4 is currently necessary.
However, Homebrew's Qt4 has a broken ```moc``` command, causing OpenSCAD compilation to

View file

@ -1,6 +1,42 @@
# OpenSCAD 2015.03
## 2015.03-2
**Bugfixes**
* \#1483 - Fix Z-fighting in Ortho view
* \#1479 - No check for infinite $fn
* \#1472 - "nan" in list comprehension causes crash
* \#452 - rands() fails when the seed is a floating point number
* \#1407 - Recursive module crash
* \#1425 - Animate Filename Generation - Duplicate/Missing Filenames
* \#1420 - expression-evaluation-tests fails on arm64
* \#1410 - Crash when a polygon contains NaN
* \#1378 - Linear extrude plus infinite twist causes crash instead of just an error
* \#1358 - Add more detailed installer information including version number
* \#1356 - Crash when multiplying matrices with undefined elements
* \#1350 - Saving file when HD is full ends up in data loss
* \#1342 - Syntax Highlighting Does Not Work on Linux Mint 17.1
* \#1337 - Simple detection of script and direction based on given text
* \#1325 - Crash when polygons with > 3 indices turn out to be degenerate
* \#1329 - version() returned ```[0,0,0]```
## 2015.03-1
**Bugfixes**
* \#1203 - Linux: Missing icons on Xfce
* \#1258 - Occasional crash when exporting STL
* \#1260 - Minimal window width too large
* \#1264 - Replace All sometimes caused a hang
* \#1274 - Fixed some preview bugs on Intel GPUs (OpenCSG 1.4.0)
* \#1276 - Module recursion sometimes caused a crash
* \#1277 - Automatic reload sometimes messed up camera position
* \#1284 - Animation flicker eliminated
* \#1294 - Support reproducible builds
* \#1317 - Normals vectors in STL were sometimes 0 0 0
## 2015.03
**Language Features:**
* Added text() module for 2D text
* Added offset() module for 2D offsets

View file

@ -13,10 +13,12 @@ boost {
macx: DEFINES += __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0
# MXE cross build
CONFIG(mingw-cross-env) {
DEFINES += BOOST_STATIC
CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
DEFINES += BOOST_THREAD_USE_LIB
DEFINES += Boost_USE_STATIC_LIBS
!CONFIG(mingw-cross-env-shared) {
DEFINES += BOOST_STATIC
DEFINES += Boost_USE_STATIC_LIBS
}
BOOST_LINK_FLAGS = -lboost_thread_win32-mt -lboost_program_options-mt -lboost_filesystem-mt -lboost_system-mt -lboost_regex-mt -lboost_chrono-mt
}

View file

@ -28,8 +28,22 @@ macx {
}
c++11 {
QMAKE_CXXFLAGS += -std=c++11
# -std=c++11 is only available in gcc>=4.7
*g++*: QMAKE_CXXFLAGS += -std=c++0x
else: QMAKE_CXXFLAGS += -std=c++11
message("Using C++11")
*clang*: {
# 3rd party libraries will probably violate this for a long time
CXX11_SUPPRESS_WARNINGS += -Wno-inconsistent-missing-override
# boost/algorithm/string.hpp does this
CXX11_SUPPRESS_WARNINGS += -Wno-unused-local-typedef
# CGAL
CXX11_SUPPRESS_WARNINGS += -Wno-deprecated-register
QMAKE_CXXFLAGS_WARN_ON += $$CXX11_SUPPRESS_WARNINGS
QMAKE_OBJECTIVE_CFLAGS_WARN_ON += $$CXX11_SUPPRESS_WARNINGS
}
}
else {
*clang* {

View file

@ -10,7 +10,7 @@ cgal {
message("CGAL location: $$CGAL_DIR")
}
CONFIG(mingw-cross-env) {
CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
LIBS += -lgmp -lmpfr -lCGAL
QMAKE_CXXFLAGS += -frounding-math
} else {

203
cgal/data/issue1455.nef3 Normal file
View file

@ -0,0 +1,203 @@
Selective Nef Complex
standard
vertices 15
halfedges 42
facets 18
volumes 2
shalfedges 84
shalfloops 2
sfaces 30
0 { 0 2, 0 5, 0 1, -2 | 0 0 5 1 } 1
1 { 3 5, 6 11, 2 3, -2 | 5 0 5 1 } 1
2 { 6 8, 12 17, 4 5, -2 | 5 5 5 1 } 1
3 { 9 11, 18 23, 6 7, -2 | 0 5 0 1 } 1
4 { 12 14, 24 29, 8 9, -2 | 5 0 0 1 } 1
5 { 15 17, 30 35, 10 11, -2 | 5 5 0 1 } 1
6 { 18 20, 36 41, 12 13, -2 | 0 5 5 1 } 1
7 { 21 23, 42 47, 14 15, -2 | 0 0 3 1 } 0
8 { 24 26, 48 53, 16 17, -2 | 3 0 3 1 } 0
9 { 27 29, 54 59, 18 19, -2 | 3 3 3 1 } 0
10 { 30 32, 60 65, 20 21, -2 | 0 3 0 1 } 0
11 { 33 35, 66 71, 22 23, -2 | 3 0 0 1 } 0
12 { 36 38, 72 77, 24 25, -2 | 3 3 0 1 } 0
13 { 39 41, 78 83, 26 27, -2 | 0 3 3 1 } 0
14 { -2 -2, -2 -2, 28 29, 0 | 2 2 3 1 } 1
0 { 3, 0, 0 0 | 1 0 0 1 } 1
1 { 18, 0, 0 5 | 0 1 0 1 } 1
2 { 21, 0, 0 4 | 0 0 -1 1 } 1
3 { 0, 1, 0 6 | -1 0 0 1 } 1
4 { 6, 1, 0 7 | 0 1 0 1 } 1
5 { 13, 1, 0 10 | 0 0 -1 1 } 1
6 { 4, 2, 0 14 | 0 -1 0 1 } 1
7 { 19, 2, 0 13 | -1 0 0 1 } 1
8 { 17, 2, 0 16 | 0 0 -1 1 } 1
9 { 32, 3, 0 20 | 0 -1 0 1 } 1
10 { 20, 3, 0 22 | 0 0 1 1 } 1
11 { 16, 3, 0 21 | 1 0 0 1 } 1
12 { 34, 4, 0 26 | -1 0 0 1 } 1
13 { 5, 4, 0 28 | 0 0 1 1 } 1
14 { 15, 4, 0 25 | 0 1 0 1 } 1
15 { 14, 5, 0 30 | 0 -1 0 1 } 1
16 { 11, 5, 0 34 | -1 0 0 1 } 1
17 { 8, 5, 0 35 | 0 0 1 1 } 1
18 { 1, 6, 0 36 | 0 -1 0 1 } 1
19 { 7, 6, 0 40 | 1 0 0 1 } 1
20 { 10, 6, 0 41 | 0 0 -1 1 } 1
21 { 2, 7, 0 44 | 0 0 1 1 } 1
22 { 24, 7, 0 46 | 1 0 0 1 } 0
23 { 39, 7, 0 47 | 0 1 0 1 } 0
24 { 22, 8, 0 50 | -1 0 0 1 } 0
25 { 27, 8, 0 49 | 0 1 0 1 } 0
26 { 33, 8, 0 52 | 0 0 -1 1 } 0
27 { 25, 9, 0 56 | 0 -1 0 1 } 0
28 { 40, 9, 0 55 | -1 0 0 1 } 0
29 { 38, 9, 0 58 | 0 0 -1 1 } 0
30 { 41, 10, 0 62 | 0 0 1 1 } 0
31 { 37, 10, 0 64 | 1 0 0 1 } 0
32 { 9, 10, 0 65 | 0 1 0 1 } 1
33 { 26, 11, 0 68 | 0 0 1 1 } 0
34 { 12, 11, 0 70 | 1 0 0 1 } 1
35 { 36, 11, 0 71 | 0 1 0 1 } 0
36 { 35, 12, 0 74 | 0 -1 0 1 } 0
37 { 31, 12, 0 76 | -1 0 0 1 } 0
38 { 29, 12, 0 77 | 0 0 1 1 } 0
39 { 23, 13, 0 80 | 0 -1 0 1 } 0
40 { 28, 13, 0 82 | 1 0 0 1 } 0
41 { 30, 13, 0 79 | 0 0 -1 1 } 0
0 { 1, 79 , , 0 | -1 0 0 0 } 1
1 { 0, 78 , , 1 | 1 0 0 0 } 1
2 { 3, 37 , , 0 | 0 0 1 -5 } 1
3 { 2, 36 , , 1 | 0 0 -1 5 } 1
4 { 5, 9 , , 0 | 1 0 0 -5 } 1
5 { 4, 8 , , 1 | -1 0 0 5 } 1
6 { 7, 35 , , 0 | 0 1 0 -5 } 1
7 { 6, 34 , , 1 | 0 -1 0 5 } 1
8 { 9, 74 , , 0 | 0 0 -1 0 } 1
9 { 8, 75 , , 1 | 0 0 1 0 } 1
10 { 11, 2 , , 0 | 0 -1 0 0 } 1
11 { 10, 3 , , 1 | 0 1 0 0 } 1
12 { 13, 81 , 1 , 1 | 0 0 1 -3 } 0
13 { 12, 80 , 0 , 0 | 0 0 -1 3 } 0
14 { 15, 53 , , 1 | 1 0 0 -3 } 0
15 { 14, 52 , , 0 | -1 0 0 3 } 0
16 { 17, 77 , , 1 | 0 1 0 -3 } 0
17 { 16, 76 , , 0 | 0 -1 0 3 } 0
0 { 0 } 0
1 { 15 } 1
0 { 1, 3, 5, 0, 0, 7, 36, 3 | 0 0 1 0 } 1
1 { 0, 4, 2, 1, 1, 37, 6, 2 | 0 0 -1 0 } 1
2 { 3, 1, 4, 0, 1, 10, 44, 10 | 0 1 0 0 } 1
3 { 2, 5, 0, 2, 0, 45, 11, 11 | 0 -1 0 0 } 1
4 { 5, 2, 1, 2, 1, 43, 38, 0 | 1 0 0 0 } 1
5 { 4, 0, 3, 1, 0, 39, 42, 1 | -1 0 0 0 } 1
6 { 7, 10, 9, 3, 3, 1, 12, 2 | 0 0 -1 0 } 1
7 { 6, 8, 11, 4, 2, 13, 0, 3 | 0 0 1 0 } 1
8 { 9, 11, 7, 5, 2, 29, 14, 5 | 1 0 0 0 } 1
9 { 8, 6, 10, 4, 3, 15, 28, 4 | -1 0 0 0 } 1
10 { 11, 9, 6, 5, 3, 26, 2, 10 | 0 1 0 0 } 1
11 { 10, 7, 8, 3, 2, 3, 27, 11 | 0 -1 0 0 } 1
12 { 13, 15, 17, 6, 5, 6, 37, 2 | 0 0 -1 0 } 1
13 { 12, 16, 14, 7, 4, 36, 7, 3 | 0 0 1 0 } 1
14 { 15, 13, 16, 6, 4, 8, 33, 5 | 1 0 0 0 } 1
15 { 14, 17, 12, 8, 5, 32, 9, 4 | -1 0 0 0 } 1
16 { 17, 14, 13, 8, 4, 34, 40, 7 | 0 1 0 0 } 1
17 { 16, 12, 15, 7, 5, 41, 35, 6 | 0 -1 0 0 } 1
18 { 19, 21, 22, 9, 6, 60, 39, 1 | -1 0 0 0 } 1
19 { 18, 23, 20, 10, 7, 38, 61, 0 | 1 0 0 0 } 1
20 { 21, 19, 23, 9, 7, 64, 31, 8 | 0 0 1 0 } 1
21 { 20, 22, 18, 11, 6, 30, 65, 9 | 0 0 -1 0 } 1
22 { 23, 18, 21, 10, 6, 40, 34, 7 | 0 1 0 0 } 1
23 { 22, 20, 19, 11, 7, 35, 41, 6 | 0 -1 0 0 } 1
24 { 25, 27, 29, 12, 8, 71, 30, 9 | 0 0 -1 0 } 1
25 { 24, 28, 26, 14, 9, 31, 70, 8 | 0 0 1 0 } 1
26 { 27, 25, 28, 12, 9, 68, 10, 10 | 0 1 0 0 } 1
27 { 26, 29, 24, 13, 8, 11, 69, 11 | 0 -1 0 0 } 1
28 { 29, 26, 25, 13, 9, 9, 32, 4 | -1 0 0 0 } 1
29 { 28, 24, 27, 14, 8, 33, 8, 5 | 1 0 0 0 } 1
30 { 31, 33, 34, 15, 11, 24, 21, 9 | 0 0 -1 0 } 1
31 { 30, 35, 32, 16, 10, 20, 25, 8 | 0 0 1 0 } 1
32 { 33, 31, 35, 15, 10, 28, 15, 4 | -1 0 0 0 } 1
33 { 32, 34, 30, 17, 11, 14, 29, 5 | 1 0 0 0 } 1
34 { 35, 30, 33, 16, 11, 22, 16, 7 | 0 1 0 0 } 1
35 { 34, 32, 31, 17, 10, 17, 23, 6 | 0 -1 0 0 } 1
36 { 37, 39, 40, 18, 12, 0, 13, 3 | 0 0 1 0 } 1
37 { 36, 41, 38, 19, 13, 12, 1, 2 | 0 0 -1 0 } 1
38 { 39, 37, 41, 18, 13, 4, 19, 0 | 1 0 0 0 } 1
39 { 38, 40, 36, 20, 12, 18, 5, 1 | -1 0 0 0 } 1
40 { 41, 36, 39, 19, 12, 16, 22, 7 | 0 1 0 0 } 1
41 { 40, 38, 37, 20, 13, 23, 17, 6 | 0 -1 0 0 } 1
42 { 43, 45, 47, 21, 14, 5, 78, 1 | -1 0 0 0 } 1
43 { 42, 46, 44, 23, 15, 79, 4, 0 | 1 0 0 0 } 1
44 { 45, 43, 46, 21, 15, 2, 50, 10 | 0 1 0 0 } 1
45 { 44, 47, 42, 22, 14, 51, 3, 11 | 0 -1 0 0 } 1
46 { 47, 44, 43, 22, 15, 49, 80, 13 | 0 0 1 0 } 0
47 { 46, 42, 45, 23, 14, 81, 48, 12 | 0 0 -1 0 } 0
48 { 49, 51, 53, 24, 16, 47, 54, 12 | 0 0 -1 0 } 0
49 { 48, 52, 50, 25, 17, 55, 46, 13 | 0 0 1 0 } 0
50 { 51, 49, 52, 24, 17, 44, 68, 10 | 0 1 0 0 } 1
51 { 50, 53, 48, 26, 16, 69, 45, 11 | 0 -1 0 0 } 1
52 { 53, 50, 49, 26, 17, 67, 56, 15 | 1 0 0 0 } 0
53 { 52, 48, 51, 25, 16, 57, 66, 14 | -1 0 0 0 } 0
54 { 55, 57, 59, 27, 19, 48, 81, 12 | 0 0 -1 0 } 0
55 { 54, 58, 56, 28, 18, 80, 49, 13 | 0 0 1 0 } 0
56 { 57, 55, 58, 27, 18, 52, 73, 15 | 1 0 0 0 } 0
57 { 56, 59, 54, 29, 19, 72, 53, 14 | -1 0 0 0 } 0
58 { 59, 56, 55, 29, 18, 76, 82, 17 | 0 1 0 0 } 0
59 { 58, 54, 57, 28, 19, 83, 77, 16 | 0 -1 0 0 } 0
60 { 61, 63, 65, 30, 20, 78, 18, 1 | -1 0 0 0 } 1
61 { 60, 64, 62, 32, 21, 19, 79, 0 | 1 0 0 0 } 1
62 { 63, 61, 64, 30, 21, 82, 76, 17 | 0 1 0 0 } 0
63 { 62, 65, 60, 31, 20, 77, 83, 16 | 0 -1 0 0 } 0
64 { 65, 62, 61, 31, 21, 74, 20, 8 | 0 0 1 0 } 1
65 { 64, 60, 63, 32, 20, 21, 75, 9 | 0 0 -1 0 } 1
66 { 67, 69, 71, 33, 22, 53, 72, 14 | -1 0 0 0 } 0
67 { 66, 70, 68, 35, 23, 73, 52, 15 | 1 0 0 0 } 0
68 { 69, 67, 70, 33, 23, 50, 26, 10 | 0 1 0 0 } 1
69 { 68, 71, 66, 34, 22, 27, 51, 11 | 0 -1 0 0 } 1
70 { 71, 68, 67, 34, 23, 25, 74, 8 | 0 0 1 0 } 1
71 { 70, 66, 69, 35, 22, 75, 24, 9 | 0 0 -1 0 } 1
72 { 73, 75, 77, 36, 24, 66, 57, 14 | -1 0 0 0 } 0
73 { 72, 76, 74, 38, 25, 56, 67, 15 | 1 0 0 0 } 0
74 { 75, 73, 76, 36, 25, 70, 64, 8 | 0 0 1 0 } 1
75 { 74, 77, 72, 37, 24, 65, 71, 9 | 0 0 -1 0 } 1
76 { 77, 74, 73, 37, 25, 62, 58, 17 | 0 1 0 0 } 0
77 { 76, 72, 75, 38, 24, 59, 63, 16 | 0 -1 0 0 } 0
78 { 79, 81, 83, 39, 26, 42, 60, 1 | -1 0 0 0 } 1
79 { 78, 82, 80, 41, 27, 61, 43, 0 | 1 0 0 0 } 1
80 { 81, 79, 82, 39, 27, 46, 55, 13 | 0 0 1 0 } 0
81 { 80, 83, 78, 40, 26, 54, 47, 12 | 0 0 -1 0 } 0
82 { 83, 80, 79, 40, 27, 58, 62, 17 | 0 1 0 0 } 0
83 { 82, 78, 81, 41, 26, 63, 59, 16 | 0 -1 0 0 } 0
0 { 1, 28, 13 | 0 0 1 0 } 0
1 { 0, 29, 12 | 0 0 -1 0 } 0
0 { 0, 0 , , , 0 } 0
1 { 0, 1 , , , 1 } 1
2 { 1, 7 , , , 0 } 0
3 { 1, 6 , , , 1 } 1
4 { 2, 13 , , , 0 } 0
5 { 2, 12 , , , 1 } 1
6 { 3, 18 , , , 0 } 0
7 { 3, 19 , , , 1 } 1
8 { 4, 24 , , , 0 } 0
9 { 4, 25 , , , 1 } 1
10 { 5, 31 , , , 1 } 1
11 { 5, 30 , , , 0 } 0
12 { 6, 36 , , , 0 } 0
13 { 6, 37 , , , 1 } 1
14 { 7, 42 , , , 0 } 0
15 { 7, 43 , , , 1 } 1
16 { 8, 48 , , , 0 } 0
17 { 8, 49 , , , 1 } 1
18 { 9, 55 , , , 1 } 1
19 { 9, 54 , , , 0 } 0
20 { 10, 60 , , , 0 } 0
21 { 10, 61 , , , 1 } 1
22 { 11, 66 , , , 0 } 0
23 { 11, 67 , , , 1 } 1
24 { 12, 72 , , , 0 } 0
25 { 12, 73 , , , 1 } 1
26 { 13, 78 , , , 0 } 0
27 { 13, 79 , , , 1 } 1
28 { 14, , , 0, 1 } 1
29 { 14, , , 1, 0 } 0
/* end Selective Nef complex */

View file

@ -8,6 +8,9 @@
#include "export.h"
#include "polyset.h"
#include "CGAL_Nef_polyhedron.h"
#include "boosty.h"
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
using namespace CGALUtils;
@ -16,6 +19,7 @@ using namespace CGALUtils;
typedef CGAL::Epick K;
typedef CGAL::Polyhedron_3<K> PolyhedronK;
#include <boost/algorithm/string.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope
@ -629,21 +633,30 @@ int main(int argc, char *argv[])
OpenSCAD::debug = "decompose";
PolySet *ps = NULL;
CGAL_Nef_polyhedron *N = NULL;
if (argc == 2) {
if (!(ps = import_stl(argv[1]))) {
std::cerr << "Error importing STL " << argv[1] << std::endl;
exit(1);
std::string filename(argv[1]);
std::string suffix = boosty::extension_str(filename);
if (suffix == ".stl") {
if (!(ps = import_stl(filename))) {
std::cerr << "Error importing STL " << filename << std::endl;
exit(1);
}
std::cerr << "Imported " << ps->numPolygons() << " polygons" << std::endl;
}
else if (suffix == ".nef3") {
N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3);
std::ifstream stream(filename.c_str());
stream >> *N->p3;
std::cerr << "Imported Nef polyhedron" << std::endl;
}
std::cerr << "Imported " << ps->numPolygons() << " polygons" << std::endl;
}
else {
std::cerr << "Usage: " << argv[0] << " <file.stl> <file.stl>" << std::endl;
exit(1);
}
Geometry::ChildList children;
CGAL_Nef_polyhedron *N = createNefPolyhedronFromGeometry(*ps);
if (ps && !N) N = createNefPolyhedronFromGeometry(*ps);
std::vector<PolyhedronK> result;
decompose(N->p3.get(), std::back_inserter(result));

View file

@ -4,7 +4,7 @@ debug: DEFINES += DEBUG
TEMPLATE = app
INCLUDEPATH += ../src
INCLUDEPATH += ../src ../src/libtess2/Include
DEPENDPATH += ../src
# Handle custom library location.
@ -54,10 +54,12 @@ macx {
}
}
# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs.
*g++* {
# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs.
QMAKE_CXXFLAGS *= -fno-strict-aliasing
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs # ignored before 4.8
# use of 'auto'
QMAKE_CXXFLAGS += -std=c++11
}
*clang* {
@ -80,29 +82,52 @@ CONFIG += gettext
mac: {
LIBS += -framework OpenGL
} else {
LIBS += -lGL
}
include(../common.pri)
HEADERS += ../src/cgal.h \
../src/cgalutils.h \
../src/linalg.h \
../src/grid.h \
../src/polyset.h \
../src/polyset-utils.h \
../src/printutils.h
../src/printutils.h \
../src/GeometryUtils.h \
../src/libtess2/Include/tesselator.h \
../src/libtess2/Source/bucketalloc.h \
../src/libtess2/Source/dict.h \
../src/libtess2/Source/geom.h \
../src/libtess2/Source/mesh.h \
../src/libtess2/Source/priorityq.h \
../src/libtess2/Source/sweep.h \
../src/libtess2/Source/tess.h
SOURCES += decompose.cpp \
../src/polygon2d.cc \
../src/polygon2d-CGAL.cc \
../src/CGAL_Nef_polyhedron.cc \
../src/CGAL_Nef_polyhedron_DxfData.cc \
../src/cgalutils.cc \
../src/cgalutils-applyops.cc \
../src/cgalutils-tess.cc \
../src/cgalutils-polyhedron.cc \
../src/polyset.cc \
../src/polyset-gl.cc \
../src/GeometryUtils.cc \
../src/svg.cc \
../src/grid.cc \
../src/node.cc \
../src/export.cc \
../src/polyset-utils.cc \
../src/progress.cc \
../src/printutils.cc
../src/printutils.cc \
../src/libtess2/Source/bucketalloc.c \
../src/libtess2/Source/dict.c \
../src/libtess2/Source/geom.c \
../src/libtess2/Source/mesh.c \
../src/libtess2/Source/priorityq.c \
../src/libtess2/Source/sweep.c \
../src/libtess2/Source/tess.c

View file

@ -4,7 +4,7 @@ debug: DEFINES += DEBUG
TEMPLATE = app
INCLUDEPATH += ../src
INCLUDEPATH += ../src ../src/libtess2/Include
DEPENDPATH += ../src
# Handle custom library location.
@ -87,23 +87,42 @@ include(../common.pri)
HEADERS += ../src/cgal.h \
../src/cgalutils.h \
../src/linalg.h \
../src/grid.h \
../src/polyset.h \
../src/polyset-utils.h \
../src/printutils.h
../src/printutils.h \
../src/GeometryUtils.h \
../src/libtess2/Include/tesselator.h \
../src/libtess2/Source/bucketalloc.h \
../src/libtess2/Source/dict.h \
../src/libtess2/Source/geom.h \
../src/libtess2/Source/mesh.h \
../src/libtess2/Source/priorityq.h \
../src/libtess2/Source/sweep.h \
../src/libtess2/Source/tess.h
SOURCES += export_nef.cpp \
../src/polygon2d.cc \
../src/polygon2d-CGAL.cc \
../src/CGAL_Nef_polyhedron.cc \
../src/CGAL_Nef_polyhedron_DxfData.cc \
../src/cgalutils.cc \
../src/cgalutils-applyops.cc \
../src/cgalutils-tess.cc \
../src/cgalutils-polyhedron.cc \
../src/polyset.cc \
../src/polyset-gl.cc \
../src/GeometryUtils.cc \
../src/svg.cc \
../src/grid.cc \
../src/node.cc \
../src/export.cc \
../src/polyset-utils.cc \
../src/progress.cc \
../src/printutils.cc \
../src/grid.cc
../src/libtess2/Source/bucketalloc.c \
../src/libtess2/Source/dict.c \
../src/libtess2/Source/geom.c \
../src/libtess2/Source/mesh.c \
../src/libtess2/Source/priorityq.c \
../src/libtess2/Source/sweep.c \
../src/libtess2/Source/tess.c

View file

@ -8,6 +8,7 @@ include(flex.pri)
include(bison.pri)
include(cgal.pri)
include(opencsg.pri)
include(opengl.pri)
include(glew.pri)
include(eigen.pri)
include(boost.pri)

View file

@ -213,5 +213,5 @@ Key bindings:
(interactive)
(call-process scad-command nil 0 nil (buffer-file-name)))
(provide 'scad)
(provide 'scad-mode)
;;; scad-mode.el ends here

17
csgopnode.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "node.h"
#include "visitor.h"
#include "enums.h"
class CsgNode : public AbstractNode
{
public:
OpenSCADOperator type;
CsgNode(const ModuleInstantiation *mi, OpenSCADOperator type) : AbstractNode(mi), type(type) { }
virtual Response accept(class State &state, Visitor &visitor) const {
return visitor.visit(state, *this);
}
virtual std::string toString() const;
virtual std::string name() const;
};

259
doc/Python-LICENSE.txt Normal file
View file

@ -0,0 +1,259 @@
Part of OpenSCAD is copied from Python (linalg.cc/hash_floating_point()),
so the python license is included below.
----
A. HISTORY OF THE SOFTWARE
==========================
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations (now Zope
Corporation, see http://www.zope.com). In 2001, the Python Software
Foundation (PSF, see http://www.python.org/psf/) was formed, a
non-profit organization created specifically to own Python-related
Intellectual Property. Zope Corporation is a sponsoring member of
the PSF.
All Python releases are Open Source (see http://www.opensource.org for
the Open Source Definition). Historically, most, but not all, Python
releases have also been GPL-compatible; the table below summarizes
the various releases.
Release Derived Year Owner GPL-
from compatible? (1)
0.9.0 thru 1.2 1991-1995 CWI yes
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
1.6 1.5.2 2000 CNRI no
2.0 1.6 2000 BeOpen.com no
1.6.1 1.6 2001 CNRI yes (2)
2.1 2.0+1.6.1 2001 PSF no
2.0.1 2.0+1.6.1 2001 PSF yes
2.1.1 2.1+2.0.1 2001 PSF yes
2.1.2 2.1.1 2002 PSF yes
2.1.3 2.1.2 2002 PSF yes
2.2 and above 2.1.1 2001-now PSF yes
Footnotes:
(1) GPL-compatible doesn't mean that we're distributing Python under
the GPL. All Python licenses, unlike the GPL, let you distribute
a modified version without making your changes open source. The
GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
because its license has a choice of law clause. According to
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
is "not incompatible" with the GPL.
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
===============================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved"
are retained in Python alone or in any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-------------------------------------------
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization ("Licensee") accessing and otherwise using
this software in source or binary form and its associated
documentation ("the Software").
2. Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
3. BeOpen is making the Software available to Licensee on an "AS IS"
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
5. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
6. This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the "BeOpen Python" logos available at
http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
7. By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
---------------------------------------
1. This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 ("CNRI"), and the Individual or Organization
("Licensee") accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
2. Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
1995-2001 Corporation for National Research Initiatives; All Rights
Reserved" are retained in Python 1.6.1 alone or in any derivative
version prepared by Licensee. Alternately, in lieu of CNRI's License
Agreement, Licensee may substitute the following text (omitting the
quotes): "Python 1.6.1 is made available subject to the terms and
conditions in CNRI's License Agreement. This Agreement together with
Python 1.6.1 may be located on the Internet using the following
unique, persistent identifier (known as a handle): 1895.22/1013. This
Agreement may also be obtained from a proxy server on the Internet
using the following URL: http://hdl.handle.net/1895.22/1013".
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
8. By clicking on the "ACCEPT" button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
ACCEPT
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
--------------------------------------------------
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -82,8 +82,10 @@ If exporting an image, specify the pixel width and height
If exporting an image, specify whether to use orthographic or perspective
projection
.TP
.B \-\-colorscheme=[Cornfield|Sunset|Metallic|Starnight|BeforeDawn|Nature|DeepOcean]
.B \-\-colorscheme=\fIscheme
If exporting an image, use the specified color scheme for the rendering.
\fIscheme\fP can be any of \fBCornfield\fP, \fBSunset\fP, \fBMetallic\fP,
\fBStarnight\fP, \fBBeforeDawn\fP, \fBNature\fP or \fBDeepOcean\fP.
.TP
.B \-v, \-\-version
Show version of program.
@ -106,7 +108,7 @@ distance 500, with orthographic projection:
Set the 'mode' variable in example017 so that it will render only the
parts of the shape. Export to a .dxf file.
.PP
.B openscad -x example017.dxf -D'mode="parts"' examples/example017.scad
.B openscad -o example017.dxf -D'mode="parts"' examples/example017.scad
.SH AUTHOR
OpenSCAD was written by Clifford Wolf, Marius Kintel, and others.

View file

@ -3,6 +3,9 @@ Given:
o Make sure we have a $VERSION branch. If not, create one
o Update releases/$VERSION.md
o scripts/makereleasenotes.sh
o Update VERSION and VERSIONDATE in
openscad.pro
scripts/publish-macosx.sh
@ -12,16 +15,20 @@ o Update VERSION and VERSIONDATE in
o git tag "openscad-$VERSION"
o ./scripts/git-archive-all.py --prefix=openscad-$VERSION/ openscad-$VERSION.src.tar.gz
o git push --tags $VERSION
o git push --tags
o Upload Source package
$ scp openscad-$VERSION.src.tar.gz openscad@files.openscad.org:www
o Write short release email to mailing list
o Tweet as OpenSCAD
o Notify package managers
- Debian/Ubuntu: https://launchpad.net/~chrysn
- Ubuntu PPA: https://github.com/hyperair
- Fedora: Miro Hrončok <miro@hroncok.cz> or <mhroncok@redhat.com>
- OpenSUSE: Pavol Rusnak <prusnak@opensuse.org>
- Arch Linux: Kyle Keen <keenerd@gmail.com>
- MacPorts: https://svn.macports.org/repository/macports/trunk/dports/science/openscad/Portfile
- Homebrew: https://github.com/caskroom/homebrew-cask/blob/master/Casks/openscad.rb
o Revert VERSION and VERSIONDATE in openscad.pro scripts/publish-macosx.sh scripts/release-common.sh scripts/publish-mingw-x.sh tests/CMakeLists.txt
o Announce:
- Write short release email to mailing list
- Tweet as OpenSCAD
- Notify package managers
- Debian/Ubuntu: https://launchpad.net/~chrysn
- Ubuntu PPA: https://github.com/hyperair
- Fedora: Miro Hrončok <miro@hroncok.cz> or <mhroncok@redhat.com>
- OpenSUSE: Pavol Rusnak <prusnak@opensuse.org>
- Arch Linux: Kyle Keen <keenerd@gmail.com>
- MacPorts: https://svn.macports.org/repository/macports/trunk/dports/science/openscad/Portfile
- Homebrew: https://github.com/caskroom/homebrew-cask/blob/master/Casks/openscad.rb

View file

@ -26,14 +26,13 @@ o scripts/makereleasenotes.sh
o Update version number in doc/openscad.1
o Update copyright year in AboutDialog.html and mainwin.cc
o Add VERSION and VERSIONDATE in openscad.pro, scripts/publish-macosx.sh, scripts/release-common.sh
o Add VERSION and VERSIONDATE in openscad.pro, scripts/publish-macosx.sh, scripts/release-common.sh tests/CMakeLists.txt
o Add VERSION in tests/CMakeLists.txt, scripts/publish-mingw-x.sh
o Tag release
git tag "openscad-$VERSION"
o Revert VERSION and VERSIONDATE in
openscad.pro, scripts/publish-macosx.sh, scripts/release-common.sh, scripts/publish-mingw-x.sh
o Revert VERSION and VERSIONDATE in openscad.pro scripts/publish-macosx.sh scripts/release-common.sh scripts/publish-mingw-x.sh tests/CMakeLists.txt
o build source package
scripts/git-archive-all.py --prefix=openscad-$VERSION/ openscad-$VERSION.src.tar.gz

View file

@ -1,8 +1,8 @@
echo(version=version());
// rotate_extrude() always rotates the 2D shape 360 degrees
// around the Z axis. Note that the 2D shape must be either
// completely on the positive or negative side of the X axis.
// rotate_extrude() rotates a 2D shape around the Z axis.
// Note that the 2D shape must be either completely on the
// positive or negative side of the X axis.
color("red")
rotate_extrude()
translate([10, 0])
@ -23,6 +23,26 @@ color("green")
polygon( points=[[0,0],[8,4],[4,8],[4,12],[12,16],[0,20]] );
// By default rotate_extrude forms a full 360 degree circle,
// but a partial rotation can be performed by using the angle parameter.
// Positive angles create an arc starting from the X axis, going counter-clockwise.
// Negative angles generate an arc in the clockwise direction.
color("magenta")
translate([40,40]){
rotate_extrude(angle=180)
translate([12.5,0])
square(5);
translate([7.5,0])
rotate_extrude(angle=180)
translate([5,0])
square(5);
translate([-7.5,0])
rotate_extrude(angle=-180)
translate([5,0])
square(5);
}
// Written in 2015 by Torsten Paul <Torsten.Paul@gmx.de>
//
// To the extent possible under law, the author(s) have dedicated all

View file

@ -10,7 +10,9 @@ glew {
unix:LIBS += -lGLEW
CONFIG(mingw-cross-env): {
DEFINES += GLEW_STATIC
!CONFIG(mingw-cross-env-shared) {
DEFINES += GLEW_STATIC
}
} else {
win32:LIBS += -lglew32
}

View file

@ -40,7 +40,7 @@ isEmpty(GLIB2_LIBPATH) {
GLIB2_LIBS = -L$$GLIB2_LIBPATH -lglib-2.0
}
CONFIG(mingw-cross-env) {
CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
#message("mingw")
isEmpty(GLIB2_INCLUDEPATH) {
MXE_TARGET_DIR=$$(MXETARGETDIR)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -6,3 +6,4 @@ Icon=openscad
Exec=openscad %f
MimeType=application/x-openscad;
Categories=Graphics;3DGraphics;Engineering;
Keywords=3d;solid;geometry;csg;model;stl;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 570 B

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

After

Width:  |  Height:  |  Size: 991 B

View file

@ -936,7 +936,7 @@ msgid "PolySet Cache size"
msgstr "Velikost PolySet cache"
#: objects/ui_Preferences.h:1158
msgid "Allow to open multiple documents"
msgid "Allow opening multiple documents"
msgstr "Povolit současné otevření více dokumentů"
#: objects/ui_Preferences.h:1159

View file

@ -956,7 +956,7 @@ msgid "PolySet Cache size"
msgstr "PolySet Cache Größe"
#: objects/ui_Preferences.h:1158
msgid "Allow to open multiple documents"
msgid "Allow opening multiple documents"
msgstr "Öffnen von mehreren Dokumenten erlauben"
#: objects/ui_Preferences.h:1159

View file

@ -1,20 +1,20 @@
# Spanish translations for OpenSCAD package.
# This file is distributed under the same license as the OpenSCAD package.
# bazza <bazza@riseup.net>, 2015.
# <javialamo+github@gmail.com>, 2016.
#
msgid ""
msgstr ""
"Project-Id-Version: OpenSCAD 2015.03\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-03-10 10:38-0400\n"
"PO-Revision-Date: 2015-03-10 05:21-0300\n"
"Last-Translator: Ernesto Bazzano <bazza@riseup.net>\n"
"PO-Revision-Date: 2016-04-13 01:56-0300\n"
"Last-Translator: Javier del Álamo <javialamo+github@gmail.com>\n"
"Language-Team: Español\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.4\n"
#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13
msgid "About OpenSCAD"
@ -39,7 +39,7 @@ msgstr ""
"style=\"color: green;\">Open</span>SCAD</p>\n"
"<p style=\"font-family: 'Open Sans', 'Droid Sans', 'sans-serif'; font-"
"weight: normal; font-size: 14pt; padding-top: 0; margin-top: 0; margin-left: "
"2em;\">Los programadores de modelado 3D CAD</p>\n"
"2em;\">El programa de modelado 3D CAD de los programadores</p>\n"
"</body></html>\n"
"\n"
"\n"
@ -88,11 +88,11 @@ msgstr ""
#: objects/ui_LibraryInfoDialog.h:75
msgid "Lib & Build Info"
msgstr "Informacion de las librerias y compilación"
msgstr "Información de las librerias y compilación"
#: objects/ui_LibraryInfoDialog.h:76
msgid "OpenSCAD Detailed Library and Build Information"
msgstr "Informations detalles de las librerias y compilación"
msgstr "Información detallada de las librerias y compilación"
#: objects/ui_MainWindow.h:837
msgid "&New"
@ -112,7 +112,7 @@ msgstr "Ctrl+O"
#: objects/ui_MainWindow.h:841
msgid "&Save"
msgstr "&Salvar"
msgstr "&Guardar"
#: objects/ui_MainWindow.h:842
msgid "Ctrl+S"
@ -120,7 +120,7 @@ msgstr "Ctrl+S"
#: objects/ui_MainWindow.h:843
msgid "Save &As..."
msgstr "S&alvar como..."
msgstr "Guardar &como..."
#: objects/ui_MainWindow.h:844
msgid "Ctrl+Shift+S"
@ -136,7 +136,7 @@ msgstr "Ctrl+R"
#: objects/ui_MainWindow.h:847
msgid "&Quit"
msgstr "Salir"
msgstr "&Salir"
#: objects/ui_MainWindow.h:848
msgid "Ctrl+Q"
@ -144,7 +144,7 @@ msgstr "Ctrl+Q"
#: objects/ui_MainWindow.h:849
msgid "&Undo"
msgstr "An&ular"
msgstr "&Deshacer"
#: objects/ui_MainWindow.h:850
msgid "Ctrl+Z"
@ -184,7 +184,7 @@ msgstr "Ctrl+V"
#: objects/ui_MainWindow.h:859
msgid "&Indent"
msgstr "&Indenter"
msgstr "&Indentar"
#: objects/ui_MainWindow.h:860
msgid "Ctrl+I"
@ -209,7 +209,7 @@ msgstr "Ctrl+Shift+D"
#: objects/ui_MainWindow.h:865
#, fuzzy
msgid "P&aste viewport translation"
msgstr "Pegar posición de la marco"
msgstr "Pegar traslación de la ventana"
#: objects/ui_MainWindow.h:866
msgid "Ctrl+T"
@ -222,7 +222,7 @@ msgstr "Pegar rotación de la ventana"
#: objects/ui_MainWindow.h:868
msgid "Increase Font &Size"
msgstr ""
msgstr "Aumentar el tamaño de la &fuente"
#: objects/ui_MainWindow.h:869
msgid "Ctrl++"
@ -230,7 +230,7 @@ msgstr "Ctrl++"
#: objects/ui_MainWindow.h:870
msgid "Decrease Font Si&ze"
msgstr ""
msgstr "Disminuir el tamaño de la &fuente"
#: objects/ui_MainWindow.h:871
msgid "Ctrl+-"
@ -269,7 +269,7 @@ msgstr "F6"
#: objects/ui_MainWindow.h:879
#, fuzzy
msgid "&Check Validity"
msgstr "Chequear validez"
msgstr "&Comprobar validez"
#: objects/ui_MainWindow.h:880
#, fuzzy
@ -278,12 +278,12 @@ msgstr "Mostrar &AST..."
#: objects/ui_MainWindow.h:881
msgid "Display CSG &Tree..."
msgstr "Mostrar CSG &Arbre"
msgstr "Mostrar &Arbol CSG"
#: objects/ui_MainWindow.h:882
#, fuzzy
msgid "Display CSG Pr&oducts..."
msgstr "Mostar CSG &Produits"
msgstr "Mostar Pr&oductos CSG"
#: objects/ui_MainWindow.h:883
msgid "Export as &STL..."
@ -303,7 +303,7 @@ msgstr "F9"
#: objects/ui_MainWindow.h:887
msgid "Surfaces"
msgstr "Superficie"
msgstr "Superficies"
#: objects/ui_MainWindow.h:888
msgid "F10"
@ -327,7 +327,7 @@ msgstr "F12"
#: objects/ui_MainWindow.h:893
msgid "Show Edges"
msgstr "Mostrar puntos"
msgstr "Mostrar bordes"
#: objects/ui_MainWindow.h:894
msgid "Ctrl+1"
@ -351,7 +351,7 @@ msgstr "Ctrl+3"
#: objects/ui_MainWindow.h:899
msgid "Show Scale Markers"
msgstr "Mostar escala"
msgstr "Mostar indicadores de escala"
#: objects/ui_MainWindow.h:900
msgid "Animate"
@ -359,7 +359,7 @@ msgstr "Animar"
#: objects/ui_MainWindow.h:901
msgid "&Top"
msgstr ""
msgstr "&Arriba"
#: objects/ui_MainWindow.h:902
msgid "Ctrl+4"
@ -368,7 +368,7 @@ msgstr "Ctrl+4"
#: objects/ui_MainWindow.h:903
#, fuzzy
msgid "&Bottom"
msgstr "Abajo"
msgstr "&Abajo"
#: objects/ui_MainWindow.h:904
msgid "Ctrl+5"
@ -377,7 +377,7 @@ msgstr "Ctrl+5"
#: objects/ui_MainWindow.h:905
#, fuzzy
msgid "&Left"
msgstr "Izquierda"
msgstr "&Izquierda"
#: objects/ui_MainWindow.h:906
msgid "Ctrl+6"
@ -386,7 +386,7 @@ msgstr "Ctrl+6"
#: objects/ui_MainWindow.h:907
#, fuzzy
msgid "&Right"
msgstr "Derecha"
msgstr "&Derecha"
#: objects/ui_MainWindow.h:908
msgid "Ctrl+7"
@ -395,7 +395,7 @@ msgstr "Ctrl+7"
#: objects/ui_MainWindow.h:909
#, fuzzy
msgid "&Front"
msgstr "Frente"
msgstr "&Delante"
#: objects/ui_MainWindow.h:910
msgid "Ctrl+8"
@ -403,7 +403,7 @@ msgstr "Ctrl+8"
#: objects/ui_MainWindow.h:911
msgid "Bac&k"
msgstr ""
msgstr "&Detrás"
#: objects/ui_MainWindow.h:912
msgid "Ctrl+9"
@ -412,7 +412,7 @@ msgstr "Ctrl+9"
#: objects/ui_MainWindow.h:913
#, fuzzy
msgid "&Diagonal"
msgstr "Diagonal"
msgstr "&Diagonal"
#: objects/ui_MainWindow.h:914
msgid "Ctrl+0"
@ -426,12 +426,12 @@ msgstr "Centro"
#: objects/ui_MainWindow.h:916
#, fuzzy
msgid "&Perspective"
msgstr "Perspectiva"
msgstr "&Perspectiva"
#: objects/ui_MainWindow.h:917
#, fuzzy
msgid "&Orthogonal"
msgstr "Orthogonal"
msgstr "Ortogonal"
#: objects/ui_MainWindow.h:918
#, fuzzy
@ -492,7 +492,7 @@ msgstr "Ctrl+Alt+F"
#: objects/ui_MainWindow.h:930
#, fuzzy
msgid "Find Ne&xt"
msgstr "Buscar próximo"
msgstr "Buscar siguiente"
#: objects/ui_MainWindow.h:931
msgid "Ctrl+G"
@ -501,7 +501,7 @@ msgstr "Ctrl+G"
#: objects/ui_MainWindow.h:932
#, fuzzy
msgid "Find Pre&vious"
msgstr "Buscar previo"
msgstr "Buscar anterior"
#: objects/ui_MainWindow.h:933
msgid "Ctrl+Shift+G"
@ -534,7 +534,7 @@ msgstr "Recargar y previsualizar automáticamente"
#: objects/ui_MainWindow.h:939
#, fuzzy
msgid "Export as &Image..."
msgstr "Exportar imagen..."
msgstr "Exportar como imagen..."
#: objects/ui_MainWindow.h:940
#, fuzzy
@ -601,7 +601,7 @@ msgstr "Ocultar barra de herramientas"
#: objects/ui_MainWindow.h:954
msgid "U&nindent"
msgstr "Dési&ndenter"
msgstr "Desindentar"
#: objects/ui_MainWindow.h:955
msgid "Ctrl+Shift+I"
@ -609,7 +609,7 @@ msgstr "Ctrl+Shift+I"
#: objects/ui_MainWindow.h:956
msgid "&Cheat Sheet"
msgstr ""
msgstr "Hoja de referencia"
#: objects/ui_MainWindow.h:957
msgid "Message"
@ -748,7 +748,7 @@ msgstr "Vista 3D"
#: objects/ui_Preferences.h:1064 examples/examples.json:19
msgid "Advanced"
msgstr "Advertencia"
msgstr "Avanzado"
#: objects/ui_Preferences.h:1065 src/mainwin.cc:2422
msgid "Editor"
@ -760,11 +760,11 @@ msgstr "Actualizar"
#: objects/ui_Preferences.h:1067 objects/ui_Preferences.h:1148
msgid "Features"
msgstr "Mejoras"
msgstr "Características"
#: objects/ui_Preferences.h:1069
msgid "Enable/Disable experimental features"
msgstr "Activar/Desactivar mejoras experimentales"
msgstr "Activar/Desactivar características experimentales"
#: objects/ui_Preferences.h:1071
msgid "Color scheme:"
@ -772,7 +772,7 @@ msgstr "Paleta de colores:"
#: objects/ui_Preferences.h:1072
msgid "Show Warnings and Errors in 3D View"
msgstr ""
msgstr "Mostrar errores y advertencias en la vista 3D"
#: objects/ui_Preferences.h:1073
msgid "Editor Type"
@ -800,19 +800,19 @@ msgstr "Colorear sintaxis"
#: objects/ui_Preferences.h:1082
msgid "Ctrl/Cmd-Mouse-wheel zooms text"
msgstr "ctrl/cmd + la rueda del mouse para hacer zoom al texto"
msgstr "Ctrl/Cmd + la rueda del mouse para hacer zoom al texto"
#: objects/ui_Preferences.h:1083
msgid "Indentation"
msgstr "Identificación"
msgstr "Indentación"
#: objects/ui_Preferences.h:1084
msgid "Auto Indent"
msgstr "sangría automática"
msgstr "Sangría automática"
#: objects/ui_Preferences.h:1085
msgid "Indent using"
msgstr "usar sangría"
msgstr "Indentar usando"
#: objects/ui_Preferences.h:1088 src/settings.cc:135
msgid "Spaces"
@ -824,7 +824,7 @@ msgstr "Pestañas"
#: objects/ui_Preferences.h:1091
msgid "Indentation width"
msgstr "Ancho de sangría"
msgstr "Ancho de indentado"
#: objects/ui_Preferences.h:1092
msgid "Tab width"
@ -837,7 +837,7 @@ msgstr "Atajo de pestaña"
#: objects/ui_Preferences.h:1096 objects/ui_Preferences.h:1126
#: src/settings.cc:136
msgid "Indent"
msgstr "Sangría"
msgstr "Indentar"
#: objects/ui_Preferences.h:1097 src/settings.cc:136
msgid "Insert Tab"
@ -857,7 +857,7 @@ msgstr "Siempre"
#: objects/ui_Preferences.h:1104
msgid "Only after indentation"
msgstr "Sólo después de la sandría"
msgstr "Sólo después de la indentación"
#: objects/ui_Preferences.h:1106
msgid "Size"
@ -877,7 +877,7 @@ msgstr "Marcar linea actual"
#: objects/ui_Preferences.h:1110 objects/ui_Preferences.h:1143
msgid "Line wrap"
msgstr "Quiebre de linea"
msgstr "Ajuste de linea"
#: objects/ui_Preferences.h:1113 objects/ui_Preferences.h:1130
#: objects/ui_Preferences.h:1138 src/settings.cc:127 src/settings.cc:130
@ -895,11 +895,11 @@ msgstr "Salta en límites de las palabras"
#: objects/ui_Preferences.h:1117
msgid "Line wrap indentation"
msgstr "Salto de línea en el sangrado"
msgstr "Ajuste de línea en el sangrado"
#: objects/ui_Preferences.h:1118
msgid "Line wrap visualization"
msgstr "Salto de línea visible"
msgstr "Visualización del ajuste de línea"
#: objects/ui_Preferences.h:1119
msgid "Style"
@ -942,7 +942,7 @@ msgstr "Final"
#: objects/ui_Preferences.h:1144
msgid "Automatically check for updates"
msgstr "Comprobar actualización automáticamente"
msgstr "Comprobar actualizaciones automáticamente"
#: objects/ui_Preferences.h:1145
msgid "Include development snapshots"
@ -950,11 +950,11 @@ msgstr "Incluir las versiones en desarrollo"
#: objects/ui_Preferences.h:1146
msgid "Check Now"
msgstr "Chequear ahora"
msgstr "Comprobar ahora"
#: objects/ui_Preferences.h:1147
msgid "Last checked: "
msgstr "Último chequeo:"
msgstr "Último Comprobado:"
#: objects/ui_Preferences.h:1149
msgid "OpenCSG"
@ -962,7 +962,7 @@ msgstr "OpenCSG"
#: objects/ui_Preferences.h:1150
msgid "Show capability warning"
msgstr "Advertir incapacidad"
msgstr "Mostrar advertencias de capacidad"
#: objects/ui_Preferences.h:1151
msgid "Enable for OpenGL 1.x"
@ -993,8 +993,8 @@ msgid "PolySet Cache size"
msgstr "Tamaño de cache de PolySet"
#: objects/ui_Preferences.h:1159
msgid "Allow to open multiple documents"
msgstr "Permitir a abrir varios documentos"
msgid "Allow opening multiple documents"
msgstr "Permitir abrir varios documentos"
#: objects/ui_Preferences.h:1160
msgid "Enable docking of Editor and Console in different places"
@ -1002,17 +1002,15 @@ msgstr "Habilitar soporte de editor y consola en diferentes lugares"
#: objects/ui_Preferences.h:1161
msgid "Enable undocking of Editor and Console to separate windows"
msgstr ""
"Habilitar el desacoplamiento de editor y consola para separar las ventanas"
msgstr "Habilitar el desacoplamiento de editor y consola para separar las ventanas"
#: objects/ui_Preferences.h:1162
msgid "Show Welcome Screen"
msgstr "Pantalla de bienvenida"
msgstr "Mostrar pantalla de bienvenida"
#: objects/ui_Preferences.h:1163
msgid "Enable user interface localization (requires restart of OpenSCAD)"
msgstr ""
"Habilitar interfaz de usuario localización (requiere reiniciar OpenSCAD)"
msgstr "Habilitar localización de la interfaz de usuario (requiere reiniciar OpenSCAD)"
#: objects/ui_ProgressWidget.h:72
msgid "%v / %m"
@ -1064,7 +1062,7 @@ msgid ""
"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], "
"distance = %.2f"
msgstr ""
"Marco: translado = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], "
"Ventana: traslación = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], "
"distancia = %.2f"
#: src/QGLView.cc:129
@ -1072,7 +1070,7 @@ msgid ""
"Warning: You may experience OpenCSG rendering errors.\n"
"\n"
msgstr ""
"Advertencia: Usted puede experimentar OpenCSG errores de renderizado.\n"
"Advertencia: Usted puede experimentar errores de renderizado de OpenCSG.\n"
"\n"
#: src/QGLView.cc:132
@ -1081,8 +1079,8 @@ msgid ""
"disabled.\n"
"\n"
msgstr ""
"Advertencia: Manquantes capacités OpenGL vierten OpenCSG - OpenCSG ha sido "
"desactivada. .\n"
"Advertencia:Perdidas las capacidades OpenGL para OpenCSG - OpenCSG ha sido "
"desactivado. .\n"
"\n"
#: src/QGLView.cc:135
@ -1093,7 +1091,7 @@ msgid ""
msgstr ""
"Es muy recomendable utilizar OpenSCAD en un sistema con OpenGL 2.0 o "
"posterior.\n"
"Su información renderer es como sigue:\n"
"La información de su renderizador es la siguiente:\n"
#: src/QGLView.cc:139
#, c-format
@ -1116,14 +1114,14 @@ msgstr "Error de compilación"
#: src/mainwin.cc:976
msgid "Error while compiling '%1'."
msgstr "Error de compilación '%1'."
msgstr "Error durante la compilación '%1'."
#: src/mainwin.cc:980
#, fuzzy
msgid "Compilation generated %1 warning."
msgid_plural "Compilation generated %1 warnings."
msgstr[0] "Advertencias %1"
msgstr[1] "Advertencias %1"
msgstr[0] "La compilación generó %1 advertencia"
msgstr[1] "La compilación generó %1 advertencias"
#: src/mainwin.cc:990
msgid " For details see <a href=\"#console\">console window</a>."
@ -1131,18 +1129,18 @@ msgstr " Para más detalles <a href=\"#console\">ventana de consola</a>."
#: src/mainwin.cc:1355
msgid "Save File"
msgstr "Salvar archivo"
msgstr "Guardar archivo"
#: src/mainwin.cc:1357
msgid "OpenSCAD Designs (*.scad)"
msgstr "Diseño OpenSCAD (*.scad)"
msgstr "Diseños OpenSCAD (*.scad)"
#: src/mainwin.cc:1367
msgid ""
"%1 already exists.\n"
"Do you want to replace it?"
msgstr ""
"%1 existe.\n"
"%1 ya existe.\n"
"Deseas reemplazarlo?"
#: src/mainwin.cc:1686
@ -1163,7 +1161,7 @@ msgstr "Exportar %1 Archivo"
#: src/mainwin.cc:2041 src/mainwin.cc:2100
msgid "%1 Files (*%2)"
msgstr "%1 Archivo (*%2)"
msgstr "%1 Archivos (*%2)"
#: src/mainwin.cc:2042
msgid "Untitled"
@ -1183,7 +1181,7 @@ msgstr "Sintitulo.csg"
#: src/mainwin.cc:2151
msgid "CSG Files (*.csg)"
msgstr "Archivo CSG (*.csg)"
msgstr "Archivos CSG (*.csg)"
#: src/mainwin.cc:2177
msgid "Export Image"
@ -1191,7 +1189,7 @@ msgstr "Exportar una imagen"
#: src/mainwin.cc:2177
msgid "PNG Files (*.png)"
msgstr "Archivo PNG (*.png)"
msgstr "Archivos PNG (*.png)"
#: src/mainwin.cc:2427
msgid "Console"
@ -1210,26 +1208,24 @@ msgid ""
"Fontconfig needs to update its font cache.\n"
"This can take up to a couple of minutes."
msgstr ""
"Fontconfig necesita actualizar su caché de la fuente.\n"
"Fontconfig necesita actualizar su caché de fuentes.\n"
"Esto puede tardar hasta un par de minutos."
#: src/settings.cc:132
msgid "After indentation"
msgstr ""
"Marco: posición = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], "
"distancia = %.2f"
msgstr "Antes del indentado"
#: examples/examples.json:2
msgid "Basics"
msgstr "Básico"
msgstr "Básicos"
#: examples/examples.json:13
msgid "Functions"
msgstr ""
msgstr "Funciones"
#: examples/examples.json:28
msgid "Old"
msgstr ""
msgstr "Viejo"
#~ msgid "Top"
#~ msgstr "Arriba"
@ -1258,7 +1254,7 @@ msgstr ""
#~ "\n"
#~ msgstr ""
#~ "\n"
#~ "Utilizar QGLWidget\n"
#~ "Usando QGLWidget\n"
#~ "\n"
#~ msgid "Shapes"

View file

@ -956,7 +956,7 @@ msgid "PolySet Cache size"
msgstr "Taille du Cache PolySet"
#: objects/ui_Preferences.h:1158
msgid "Allow to open multiple documents"
msgid "Allow opening multiple documents"
msgstr "Autoriser l'ouverture de plusieurs documents"
#: objects/ui_Preferences.h:1159

View file

@ -926,7 +926,7 @@ msgid "PolySet Cache size"
msgstr ""
#: objects/ui_Preferences.h:1158
msgid "Allow to open multiple documents"
msgid "Allow opening multiple documents"
msgstr ""
#: objects/ui_Preferences.h:1159

View file

@ -954,7 +954,7 @@ msgid "PolySet Cache size"
msgstr "Размер кэша PolySet"
#: objects/ui_Preferences.h:1158
msgid "Allow to open multiple documents"
msgid "Allow opening multiple documents"
msgstr "Разрешить открытие нескольких документов"
#: objects/ui_Preferences.h:1159

View file

@ -1,4 +1,6 @@
# cross compilation unix->win32
# To use static linking, pass CONFIG+=mingw-cross-env to qmake
# To use shared linking, pass CONFIG+=mingw-cross-env-shared to qmake
CONFIG(mingw-cross-env) {
LIBS += mingw-cross-env/lib/libglew32s.a
LIBS += mingw-cross-env/lib/libglut.a
@ -19,6 +21,17 @@ CONFIG(mingw-cross-env) {
LIBS += mingw-cross-env/lib/libexpat.a
LIBS += mingw-cross-env/lib/libintl.a
LIBS += mingw-cross-env/lib/libiconv.a
}
CONFIG(mingw-cross-env-shared) {
# on MXE, the shared library .dll files are under 'bin' not 'lib'.
QMAKE_LFLAGS += -L./mingw-cross-env/bin
LIBS += -lglew32 -lglut -lopengl32 -lGLEW -lglu32
LIBS += -lopencsg -lmpfr -lgmp -lCGAL
LIBS += -lfontconfig -lfreetype -lharfbuzz -lbz2 -lexpat -lintl -liconv
}
CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
QMAKE_CXXFLAGS += -fpermissive
WINSTACKSIZE = 8388608 # 8MB # github issue 116
QMAKE_CXXFLAGS += -Wl,--stack,$$WINSTACKSIZE

View file

@ -1,6 +1,5 @@
opencsg {
DEFINES += ENABLE_OPENCSG
CONFIG += glew
# Optionally specify location of OpenCSG using the
# OPENCSGDIR env. variable

22
opengl.pri Normal file
View file

@ -0,0 +1,22 @@
# Prefer QOpenGLWidget for non-Windows platforms
# To explicitly enable QOpenGLWidget: qmake CONFIG += qopenglwidget
# To explicitly enable QGLWidget: qmake CONFIG += qglwidget
!win*: CONFIG += qopenglwidget
qopenglwidget:!qglwidget:!lessThan(QT_VERSION, 5.4): CONFIG += using_qopenglwidget
using_qopenglwidget {
message("Using QOpenGLWidget")
DEFINES += USE_QOPENGLWIDGET
}
else {
message("Using QGLWidget")
QT += opengl
}
# see http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
# and https://github.com/openscad/openscad/pull/119
# ( QT += opengl does not automatically link glu on some DSO systems. )
unix:!macx {
QMAKE_LIBS_OPENGL *= -lGLU
QMAKE_LIBS_OPENGL *= -lX11
}

View file

@ -116,15 +116,7 @@ mingw* {
}
CONFIG += qt
QT += opengl concurrent
# see http://fedoraproject.org/wiki/UnderstandingDSOLinkChange
# and https://github.com/openscad/openscad/pull/119
# ( QT += opengl does not automatically link glu on some DSO systems. )
unix:!macx {
QMAKE_LIBS_OPENGL *= -lGLU
QMAKE_LIBS_OPENGL *= -lX11
}
QT += widgets concurrent
netbsd* {
QMAKE_LFLAGS += -L/usr/X11R7/lib
@ -176,9 +168,10 @@ CONFIG(skip-version-check) {
# Application configuration
macx:CONFIG += mdi
#CONFIG += c++11
CONFIG += c++11
CONFIG += cgal
CONFIG += opencsg
CONFIG += glew
CONFIG += boost
CONFIG += eigen
CONFIG += glib-2.0
@ -208,7 +201,7 @@ mdi {
include(common.pri)
# mingw has to come after other items so OBJECT_DIRS will work properly
CONFIG(mingw-cross-env) {
CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
include(mingw-cross-env.pri)
}
@ -257,6 +250,8 @@ HEADERS += src/typedefs.h \
src/LibraryListWidget.h \
src/ParameterWidget.h \
src/ParameterEntryWidget.h \
src/OpenSCADApp.h \
src/WindowManager.h \
src/Preferences.h \
src/OpenCSGWarningDialog.h \
src/AboutDialog.h \
@ -267,8 +262,9 @@ HEADERS += src/typedefs.h \
src/context.h \
src/modcontext.h \
src/evalcontext.h \
src/csgterm.h \
src/csgtermnormalizer.h \
src/csgops.h \
src/CSGTreeNormalizer.h \
src/CSGTreeEvaluator.h \
src/dxfdata.h \
src/dxfdim.h \
src/export.h \
@ -277,6 +273,7 @@ HEADERS += src/typedefs.h \
src/function.h \
src/exceptions.h \
src/grid.h \
src/hash.h \
src/highlighter.h \
src/localscope.h \
src/module.h \
@ -314,12 +311,10 @@ HEADERS += src/typedefs.h \
src/ModuleCache.h \
src/GeometryCache.h \
src/GeometryEvaluator.h \
src/CSGTermEvaluator.h \
src/Tree.h \
src/DrawingCallback.h \
src/FreetypeRenderer.h \
src/FontCache.h \
src/mathc99.h \
src/DrawingCallback.h \
src/FreetypeRenderer.h \
src/FontCache.h \
src/memory.h \
src/linalg.h \
src/Camera.h \
@ -346,7 +341,6 @@ src/FontCache.h \
SOURCES += src/version_check.cc \
src/ProgressWidget.cc \
src/mathc99.cc \
src/linalg.cc \
src/Camera.cc \
src/handle_dep.cc \
@ -363,8 +357,9 @@ SOURCES += src/version_check.cc \
src/context.cc \
src/modcontext.cc \
src/evalcontext.cc \
src/csgterm.cc \
src/csgtermnormalizer.cc \
src/csgnode.cc \
src/CSGTreeNormalizer.cc \
src/CSGTreeEvaluator.cc \
src/Geometry.cc \
src/Polygon2d.cc \
src/clipper-utils.cc \
@ -417,16 +412,22 @@ SOURCES += src/version_check.cc \
src/AutoUpdater.cc \
\
src/grid.cc \
src/hash.cc \
src/builtin.cc \
src/calc.cc \
src/export.cc \
src/export_stl.cc \
src/export_amf.cc \
src/export_off.cc \
src/export_dxf.cc \
src/export_svg.cc \
src/export_nef.cc \
src/export_png.cc \
src/export_params.cc \
src/import.cc \
src/renderer.cc \
src/colormap.cc \
src/ThrownTogetherRenderer.cc \
src/CSGTermEvaluator.cc \
src/svg.cc \
src/OffscreenView.cc \
src/fbo.cc \
@ -440,6 +441,8 @@ SOURCES += src/version_check.cc \
src/LibraryListWidget.cc \
src/ParameterWidget.cc \
src/ParameterEntryWidget.cc \
src/OpenSCADApp.cc \
src/WindowManager.cc \
src/UIUtils.cc \
src/Dock.cc \
src/FontListDialog.cc \

View file

@ -29,7 +29,6 @@
<file>icons/prefs3DView.png</file>
<file>icons/prefsEditor.png</file>
<file>icons/prefsUpdate.png</file>
<file>icons/flattr.png</file>
<file>src/AboutDialog.html</file>
<file>images/export.png</file>
<file>images/axes.png</file>

View file

@ -32,3 +32,11 @@
gluTessCallback(tess_, GLenum(GLU_TESS_BEGIN),
(GLvoid (CGAL_GLU_TESS_CALLBACK *)(CGAL_GLU_TESS_DOTS)) &beginCallback);
gluTessCallback(tess_, GLenum(GLU_TESS_END),
@@ -410,6 +429,7 @@
gluTessEndPolygon(tess_);
// CGAL_NEF_TRACEN("End Polygon");
gluDeleteTess(tess_);
+ combineCallback(NULL, NULL, NULL, NULL);
}
void construct_axes() const

View file

@ -0,0 +1,23 @@
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index 83e94c4..80957e6 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -1076,14 +1076,16 @@ void QLabel::paintEvent(QPaintEvent *)
if (d->pixmap && !d->pixmap->isNull()) {
QPixmap pix;
if (d->scaledcontents) {
- if (!d->scaledpixmap || d->scaledpixmap->size() != cr.size()) {
+ QSize scaledSize = cr.size() * devicePixelRatio();
+ if (!d->scaledpixmap || d->scaledpixmap->size() != scaledSize) {
if (!d->cachedimage)
d->cachedimage = new QImage(d->pixmap->toImage());
delete d->scaledpixmap;
QImage scaledImage =
- d->cachedimage->scaled(cr.size() * devicePixelRatio(),
+ d->cachedimage->scaled(scaledSize,
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
d->scaledpixmap = new QPixmap(QPixmap::fromImage(scaledImage));
+ d->scaledpixmap->setDevicePixelRatio(devicePixelRatio());
}
pix = *d->scaledpixmap;
} else

View file

@ -1,3 +1,43 @@
## 2015.03-3
**OS X only: Auto-update vulnerability fix**
## 2015.03-2
**Bugfixes**
* \#1483 - Fix Z-fighting in Ortho view
* \#1479 - No check for infinite $fn
* \#1472 - "nan" in list comprehension causes crash
* \#452 - rands() fails when the seed is a floating point number
* \#1407 - Recursive module crash
* \#1425 - Animate Filename Generation - Duplicate/Missing Filenames
* \#1420 - expression-evaluation-tests fails on arm64
* \#1410 - Crash when a polygon contains NaN
* \#1378 - Linear extrude plus infinite twist causes crash instead of just an error
* \#1358 - Add more detailed installer information including version number
* \#1356 - Crash when multiplying matrices with undefined elements
* \#1350 - Saving file when HD is full ends up in data loss
* \#1342 - Syntax Highlighting Does Not Work on Linux Mint 17.1
* \#1337 - Simple detection of script and direction based on given text
* \#1325 - Crash when polygons with > 3 indices turn out to be degenerate
* \#1329 - version() returned ```[0,0,0]```
## 2015.03-1
**Bugfixes**
* \#1203 - Linux: Missing icons on Xfce
* \#1258 - Occasional crash when exporting STL
* \#1260 - Minimal window width too large
* \#1264 - Replace All sometimes caused a hang
* \#1274 - Fixed some preview bugs on Intel GPUs (OpenCSG 1.4.0)
* \#1276 - Module recursion sometimes caused a crash
* \#1277 - Automatic reload sometimes messed up camera position
* \#1284 - Animation flicker eliminated
* \#1294 - Support reproducible builds
* \#1317 - Normals vectors in STL were sometimes 0 0 0
## 2015.03
**Language Features:**
* Added text() module for 2D text
* Added offset() module for 2D offsets

8
releases/2016.XX.md Normal file
View file

@ -0,0 +1,8 @@
**Language Features:**
* Added angle parameter to rotate_extrude()
**Program Features:**
**Bugfixes/improvements:**
**Deprecations:**

View file

@ -4,23 +4,46 @@ scintilla {
DEFINES += USE_SCINTILLA_EDITOR
# The qscintilla2.prf which ships with QScintilla is broken for Mac/Windows
# debug builds, so we supply our own
win32|macx: {
include(qscintilla2.prf)
}
else: {
load(qscintilla2) {
# All good, found installed *.prf file.
} else {
# Older scintilla libs (e.g. 2.7.2 on fedora20) do not provide the
# prf file.
#
# In addition Ubuntu (and maybe other distributions) have the Qt5
# prf file in the wrong location so it's not picked up by qmake
#
message("Using local copy of qscintilla2.prf instead.")
include(qscintilla2.prf)
QSCILOADED =
OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES)
!isEmpty(OPENSCAD_LIBDIR) {
exists($$OPENSCAD_LIBDIR) {
exists($$OPENSCAD_LIBDIR/lib/x86_64-linux-gnu/qt5/mkspecs/features/qscintilla2.prf) {
include($$OPENSCAD_LIBDIR/lib/x86_64-linux-gnu/qt5/mkspecs/features/qscintilla2.prf)
INCLUDEPATH = $$OPENSCAD_LIBDIR/include/qt5 $$INCLUDEPATH
LIBS = -L$$OPENSCAD_LIBDIR/lib/x86_64-linux-gnu $$LIBS
QSCILOADED=yes
}
}
}
# The qscintilla2.prf which ships with QScintilla is broken for Mac/Windows
# debug builds, so we supply our own
isEmpty(QSCILOADED) {
win32|macx: {
include(qscintilla2.prf)
QSCILOADED=yes
}
}
isEmpty(QSCILOADED) {
load(qscintilla2) {
QSCILOADED=yes
# All good, found installed *.prf file.
}
}
isEmpty(QSCILOADED) {
# Older scintilla libs (e.g. 2.7.2 on fedora20) do not provide the
# prf file.
#
# In addition Ubuntu (and maybe other distributions) have the Qt5
# prf file in the wrong location so it's not picked up by qmake
#
message("Using local copy of qscintilla2.prf instead.")
include(qscintilla2.prf)
QSCILOADED=yes
}
}

View file

@ -120,6 +120,17 @@ check_nsis()
fi
}
check_zip()
if [ ! "`command -v zip`" ]; then
echo the zip command was not found. please install zip
echo on debian, sudo apt-get install zip
exit 1
else
echo zip found.
fi
}
get_openscad_source_code()
{
if [ -d openscad ]; then
@ -251,7 +262,7 @@ upload_win32()
SUMMARY1="Windows x86-32 Snapshot Installer"
SUMMARY2="Windows x86-32 Snapshot Zipfile"
SUMMARY3="Windows x86-32 Snapshot Tests"
BASEDIR=./mingw32/
BASEDIR=./mingw32.static/
WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.exe
WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.zip
WIN32_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-32.zip
@ -277,7 +288,7 @@ upload_win64()
SUMMARY1="Windows x86-64 Snapshot Zipfile"
SUMMARY2="Windows x86-64 Snapshot Installer"
SUMMARY3="Windows x86-64 Snapshot Tests"
BASEDIR=./mingw64/
BASEDIR=./mingw64.static/
WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64-Installer.exe
WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64.zip
WIN64_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-64.zip
@ -409,6 +420,7 @@ main()
fi
check_starting_path
check_nsis
check_zip
read_username_from_user
read_password_from_user
get_openscad_source_code

View file

@ -1,17 +1,21 @@
EXAMPLES := ../../examples
LOG := out.log
SRC=$(wildcard $(EXAMPLES)/*/*.scad)
PNG=$(patsubst $(EXAMPLES)/%.scad,html/%.png,$(SRC))
HTML=$(patsubst $(EXAMPLES)/%.scad,html/%.html,$(SRC))
OPENSCAD := ../../OpenSCAD.app/Contents/MacOS/OpenSCAD
#OPENSCAD := openscad
OPENSCAD := $(shell ls ../../openscad ../../OpenSCAD.app/Contents/MacOS/OpenSCAD 2>/dev/null | head -n 1)
ARGS := --imgsize=1200,900 --camera=0,0,0,55,0,25,180 --viewall --autocenter
all : $(PNG) $(HTML) example-data.js assets
all : info $(PNG) $(HTML) example-data.js assets
.PHONY: info
info:
@echo Using $(OPENSCAD)
.PHONY: clean
clean :
rm -rf html
rm -rf html $(LOG)
.PHONY: assets
assets :
@ -21,7 +25,7 @@ assets :
example-data.js :
( \
echo "openscad_examples = ["; \
for a in Basics Functions Shapes Extrusion Advanced; \
for a in `grep '\[' ../../examples/examples.json | tr -d ' \t":[]'`; \
do \
echo " {"; \
echo " name : \"$$a\","; \
@ -38,7 +42,7 @@ example-data.js :
html/%.png : $(EXAMPLES)/%.scad
mkdir -p `dirname $@`
$(OPENSCAD) $(ARGS) -o $@ $< > out.log 2>&1
$(OPENSCAD) $(ARGS) -o $@ $< > $(LOG) 2>&1
html/%.html : $(EXAMPLES)/%.scad template-pre.html template-post.html
#echo $(notdir $(patsubst %.scad,%.png,$<))

View file

@ -0,0 +1,20 @@
.rainbow {
border-spacing: 0;
border-collapse: collapse;
}
.rainbow .line:hover {
background-color: #eee8d5;
}
.rainbow .line .line-number {
text-align: right;
background-color: #eee8d5;
padding-left: 0.8em;
padding-right: 0.8em;
}
.rainbow .line .line-number:before {
content: attr(data-line-number);
}
.rainbow .line .line-code {
padding-left: 1em;
width: 100%;
}

View file

@ -0,0 +1,14 @@
JavaScript Libraries:
Rainbow by Craig Campbell
* https://github.com/ccampbell/rainbow
* Apache License, Version 2.0
Rainbow.linenumbers.js by Blender3D
* https://github.com/Blender3D/rainbow.linenumbers.js
* Apache License, Version 2.0
Dropdown Menu by Oliver Gast
* http://www.olivergast.de/blog/2012/04/18/css3-dropdown-menu/
* (update in http://www.olivergast.de/blog/2015/05/12/css-ein-horizontales-dropdown-menue-reloaded/)
* No specific license, download states "download for free usage"

View file

@ -2,7 +2,7 @@
* Generic language patterns
*
* @author Craig Campbell
* @version 1.0.11
* @version 1.0.13
*/
Rainbow.extend([
{
@ -25,7 +25,7 @@ Rainbow.extend([
}
}
},
'pattern': /(\(|\s|\[|\=|:|\+|\.)(('|")([^\\\1]|\\.)*?(\3))/gm
'pattern': /(\(|\s|\[|\=|:|\+|\.|\{)(('|")([^\\\1]|\\.)*?(\3))/gm
},
{
'name': 'comment',

View file

@ -0,0 +1,798 @@
/**
* Copyright 2013 Craig Campbell
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Rainbow is a simple code syntax highlighter
*
* @preserve @version 1.2
* @url rainbowco.de
*/
window['Rainbow'] = (function() {
/**
* array of replacements to process at the end
*
* @type {Object}
*/
var replacements = {},
/**
* an array of start and end positions of blocks to be replaced
*
* @type {Object}
*/
replacement_positions = {},
/**
* an array of the language patterns specified for each language
*
* @type {Object}
*/
language_patterns = {},
/**
* an array of languages and whether they should bypass the default patterns
*
* @type {Object}
*/
bypass_defaults = {},
/**
* processing level
*
* replacements are stored at this level so if there is a sub block of code
* (for example php inside of html) it runs at a different level
*
* @type {number}
*/
CURRENT_LEVEL = 0,
/**
* constant used to refer to the default language
*
* @type {number}
*/
DEFAULT_LANGUAGE = 0,
/**
* used as counters so we can selectively call setTimeout
* after processing a certain number of matches/replacements
*
* @type {number}
*/
match_counter = 0,
/**
* @type {number}
*/
replacement_counter = 0,
/**
* @type {null|string}
*/
global_class,
/**
* @type {null|Function}
*/
onHighlight;
/**
* cross browser get attribute for an element
*
* @see http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method
*
* @param {Node} el
* @param {string} attr attribute you are trying to get
* @returns {string|number}
*/
function _attr(el, attr, attrs, i) {
var result = (el.getAttribute && el.getAttribute(attr)) || 0;
if (!result) {
attrs = el.attributes;
for (i = 0; i < attrs.length; ++i) {
if (attrs[i].nodeName === attr) {
return attrs[i].nodeValue;
}
}
}
return result;
}
/**
* adds a class to a given code block
*
* @param {Element} el
* @param {string} class_name class name to add
* @returns void
*/
function _addClass(el, class_name) {
el.className += el.className ? ' ' + class_name : class_name;
}
/**
* checks if a block has a given class
*
* @param {Element} el
* @param {string} class_name class name to check for
* @returns {boolean}
*/
function _hasClass(el, class_name) {
return (' ' + el.className + ' ').indexOf(' ' + class_name + ' ') > -1;
}
/**
* gets the language for this block of code
*
* @param {Element} block
* @returns {string|null}
*/
function _getLanguageForBlock(block) {
// if this doesn't have a language but the parent does then use that
// this means if for example you have: <pre data-language="php">
// with a bunch of <code> blocks inside then you do not have
// to specify the language for each block
var language = _attr(block, 'data-language') || _attr(block.parentNode, 'data-language');
// this adds support for specifying language via a css class
// you can use the Google Code Prettify style: <pre class="lang-php">
// or the HTML5 style: <pre><code class="language-php">
if (!language) {
var pattern = /\blang(?:uage)?-(\w+)/,
match = block.className.match(pattern) || block.parentNode.className.match(pattern);
if (match) {
language = match[1];
}
}
return language;
}
/**
* makes sure html entities are always used for tags
*
* @param {string} code
* @returns {string}
*/
function _htmlEntities(code) {
return code.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/&(?![\w\#]+;)/g, '&amp;');
}
/**
* determines if a new match intersects with an existing one
*
* @param {number} start1 start position of existing match
* @param {number} end1 end position of existing match
* @param {number} start2 start position of new match
* @param {number} end2 end position of new match
* @returns {boolean}
*/
function _intersects(start1, end1, start2, end2) {
if (start2 >= start1 && start2 < end1) {
return true;
}
return end2 > start1 && end2 < end1;
}
/**
* determines if two different matches have complete overlap with each other
*
* @param {number} start1 start position of existing match
* @param {number} end1 end position of existing match
* @param {number} start2 start position of new match
* @param {number} end2 end position of new match
* @returns {boolean}
*/
function _hasCompleteOverlap(start1, end1, start2, end2) {
// if the starting and end positions are exactly the same
// then the first one should stay and this one should be ignored
if (start2 == start1 && end2 == end1) {
return false;
}
return start2 <= start1 && end2 >= end1;
}
/**
* determines if the match passed in falls inside of an existing match
* this prevents a regex pattern from matching inside of a bigger pattern
*
* @param {number} start - start position of new match
* @param {number} end - end position of new match
* @returns {boolean}
*/
function _matchIsInsideOtherMatch(start, end) {
for (var key in replacement_positions[CURRENT_LEVEL]) {
key = parseInt(key, 10);
// if this block completely overlaps with another block
// then we should remove the other block and return false
if (_hasCompleteOverlap(key, replacement_positions[CURRENT_LEVEL][key], start, end)) {
delete replacement_positions[CURRENT_LEVEL][key];
delete replacements[CURRENT_LEVEL][key];
}
if (_intersects(key, replacement_positions[CURRENT_LEVEL][key], start, end)) {
return true;
}
}
return false;
}
/**
* takes a string of code and wraps it in a span tag based on the name
*
* @param {string} name name of the pattern (ie keyword.regex)
* @param {string} code block of code to wrap
* @returns {string}
*/
function _wrapCodeInSpan(name, code) {
return '<span class="' + name.replace(/\./g, ' ') + (global_class ? ' ' + global_class : '') + '">' + code + '</span>';
}
/**
* finds out the position of group match for a regular expression
*
* @see http://stackoverflow.com/questions/1985594/how-to-find-index-of-groups-in-match
*
* @param {Object} match
* @param {number} group_number
* @returns {number}
*/
function _indexOfGroup(match, group_number) {
var index = 0,
i;
for (i = 1; i < group_number; ++i) {
if (match[i]) {
index += match[i].length;
}
}
return index;
}
/**
* matches a regex pattern against a block of code
* finds all matches that should be processed and stores the positions
* of where they should be replaced within the string
*
* this is where pretty much all the work is done but it should not
* be called directly
*
* @param {RegExp} pattern
* @param {string} code
* @returns void
*/
function _processPattern(regex, pattern, code, callback)
{
if (typeof regex === "undefined" || regex === null) {
//console.warn("undefined regular expression")
return callback();
}
var match = regex.exec(code);
if (!match) {
return callback();
}
++match_counter;
// treat match 0 the same way as name
if (!pattern['name'] && typeof pattern['matches'][0] == 'string') {
pattern['name'] = pattern['matches'][0];
delete pattern['matches'][0];
}
var replacement = match[0],
start_pos = match.index,
end_pos = match[0].length + start_pos,
/**
* callback to process the next match of this pattern
*/
processNext = function() {
var nextCall = function() {
_processPattern(regex, pattern, code, callback);
};
// every 100 items we process let's call set timeout
// to let the ui breathe a little
return match_counter % 100 > 0 ? nextCall() : setTimeout(nextCall, 0);
};
// if this is not a child match and it falls inside of another
// match that already happened we should skip it and continue processing
if (_matchIsInsideOtherMatch(start_pos, end_pos)) {
return processNext();
}
/**
* callback for when a match was successfully processed
*
* @param {string} replacement
* @returns void
*/
var onMatchSuccess = function(replacement) {
// if this match has a name then wrap it in a span tag
if (pattern['name']) {
replacement = _wrapCodeInSpan(pattern['name'], replacement);
}
// console.log('LEVEL', CURRENT_LEVEL, 'replace', match[0], 'with', replacement, 'at position', start_pos, 'to', end_pos);
// store what needs to be replaced with what at this position
if (!replacements[CURRENT_LEVEL]) {
replacements[CURRENT_LEVEL] = {};
replacement_positions[CURRENT_LEVEL] = {};
}
replacements[CURRENT_LEVEL][start_pos] = {
'replace': match[0],
'with': replacement
};
// store the range of this match so we can use it for comparisons
// with other matches later
replacement_positions[CURRENT_LEVEL][start_pos] = end_pos;
// process the next match
processNext();
},
// if this pattern has sub matches for different groups in the regex
// then we should process them one at a time by rerunning them through
// this function to generate the new replacement
//
// we run through them backwards because the match position of earlier
// matches will not change depending on what gets replaced in later
// matches
group_keys = keys(pattern['matches']),
/**
* callback for processing a sub group
*
* @param {number} i
* @param {Array} group_keys
* @param {Function} callback
*/
processGroup = function(i, group_keys, callback) {
if (i >= group_keys.length) {
return callback(replacement);
}
var processNextGroup = function() {
processGroup(++i, group_keys, callback);
},
block = match[group_keys[i]];
// if there is no match here then move on
if (!block) {
return processNextGroup();
}
var group = pattern['matches'][group_keys[i]],
language = group['language'],
/**
* process group is what group we should use to actually process
* this match group
*
* for example if the subgroup pattern looks like this
* 2: {
* 'name': 'keyword',
* 'pattern': /true/g
* }
*
* then we use that as is, but if it looks like this
*
* 2: {
* 'name': 'keyword',
* 'matches': {
* 'name': 'special',
* 'pattern': /whatever/g
* }
* }
*
* we treat the 'matches' part as the pattern and keep
* the name around to wrap it with later
*/
process_group = group['name'] && group['matches'] ? group['matches'] : group,
/**
* takes the code block matched at this group, replaces it
* with the highlighted block, and optionally wraps it with
* a span with a name
*
* @param {string} block
* @param {string} replace_block
* @param {string|null} match_name
*/
_replaceAndContinue = function(block, replace_block, match_name) {
replacement = _replaceAtPosition(_indexOfGroup(match, group_keys[i]), block, match_name ? _wrapCodeInSpan(match_name, replace_block) : replace_block, replacement);
processNextGroup();
};
// if this is a sublanguage go and process the block using that language
if (language) {
return _highlightBlockForLanguage(block, language, function(code) {
_replaceAndContinue(block, code);
});
}
// if this is a string then this match is directly mapped to selector
// so all we have to do is wrap it in a span and continue
if (typeof group === 'string') {
return _replaceAndContinue(block, block, group);
}
// the process group can be a single pattern or an array of patterns
// _processCodeWithPatterns always expects an array so we convert it here
_processCodeWithPatterns(block, process_group.length ? process_group : [process_group], function(code) {
_replaceAndContinue(block, code, group['matches'] ? group['name'] : 0);
});
};
processGroup(0, group_keys, onMatchSuccess);
}
/**
* should a language bypass the default patterns?
*
* if you call Rainbow.extend() and pass true as the third argument
* it will bypass the defaults
*/
function _bypassDefaultPatterns(language)
{
return bypass_defaults[language];
}
/**
* returns a list of regex patterns for this language
*
* @param {string} language
* @returns {Array}
*/
function _getPatternsForLanguage(language) {
var patterns = language_patterns[language] || [],
default_patterns = language_patterns[DEFAULT_LANGUAGE] || [];
return _bypassDefaultPatterns(language) ? patterns : patterns.concat(default_patterns);
}
/**
* substring replace call to replace part of a string at a certain position
*
* @param {number} position the position where the replacement should happen
* @param {string} replace the text we want to replace
* @param {string} replace_with the text we want to replace it with
* @param {string} code the code we are doing the replacing in
* @returns {string}
*/
function _replaceAtPosition(position, replace, replace_with, code) {
var sub_string = code.substr(position);
return code.substr(0, position) + sub_string.replace(replace, replace_with);
}
/**
* sorts an object by index descending
*
* @param {Object} object
* @return {Array}
*/
function keys(object) {
var locations = [],
replacement,
pos;
for(var location in object) {
if (object.hasOwnProperty(location)) {
locations.push(location);
}
}
// numeric descending
return locations.sort(function(a, b) {
return b - a;
});
}
/**
* processes a block of code using specified patterns
*
* @param {string} code
* @param {Array} patterns
* @returns void
*/
function _processCodeWithPatterns(code, patterns, callback)
{
// we have to increase the level here so that the
// replacements will not conflict with each other when
// processing sub blocks of code
++CURRENT_LEVEL;
// patterns are processed one at a time through this function
function _workOnPatterns(patterns, i)
{
// still have patterns to process, keep going
if (i < patterns.length) {
return _processPattern(patterns[i]['pattern'], patterns[i], code, function() {
_workOnPatterns(patterns, ++i);
});
}
// we are done processing the patterns
// process the replacements and update the DOM
_processReplacements(code, function(code) {
// when we are done processing replacements
// we are done at this level so we can go back down
delete replacements[CURRENT_LEVEL];
delete replacement_positions[CURRENT_LEVEL];
--CURRENT_LEVEL;
callback(code);
});
}
_workOnPatterns(patterns, 0);
}
/**
* process replacements in the string of code to actually update the markup
*
* @param {string} code the code to process replacements in
* @param {Function} onComplete what to do when we are done processing
* @returns void
*/
function _processReplacements(code, onComplete) {
/**
* processes a single replacement
*
* @param {string} code
* @param {Array} positions
* @param {number} i
* @param {Function} onComplete
* @returns void
*/
function _processReplacement(code, positions, i, onComplete) {
if (i < positions.length) {
++replacement_counter;
var pos = positions[i],
replacement = replacements[CURRENT_LEVEL][pos];
code = _replaceAtPosition(pos, replacement['replace'], replacement['with'], code);
// process next function
var next = function() {
_processReplacement(code, positions, ++i, onComplete);
};
// use a timeout every 250 to not freeze up the UI
return replacement_counter % 250 > 0 ? next() : setTimeout(next, 0);
}
onComplete(code);
}
var string_positions = keys(replacements[CURRENT_LEVEL]);
_processReplacement(code, string_positions, 0, onComplete);
}
/**
* takes a string of code and highlights it according to the language specified
*
* @param {string} code
* @param {string} language
* @param {Function} onComplete
* @returns void
*/
function _highlightBlockForLanguage(code, language, onComplete) {
var patterns = _getPatternsForLanguage(language);
_processCodeWithPatterns(_htmlEntities(code), patterns, onComplete);
}
/**
* highlight an individual code block
*
* @param {Array} code_blocks
* @param {number} i
* @returns void
*/
function _highlightCodeBlock(code_blocks, i, onComplete) {
if (i < code_blocks.length) {
var block = code_blocks[i],
language = _getLanguageForBlock(block);
if (!_hasClass(block, 'rainbow') && language) {
language = language.toLowerCase();
_addClass(block, 'rainbow');
return _highlightBlockForLanguage(block.innerHTML, language, function(code) {
block.innerHTML = code;
// reset the replacement arrays
replacements = {};
replacement_positions = {};
// if you have a listener attached tell it that this block is now highlighted
if (onHighlight) {
onHighlight(block, language);
}
// process the next block
setTimeout(function() {
_highlightCodeBlock(code_blocks, ++i, onComplete);
}, 0);
});
}
return _highlightCodeBlock(code_blocks, ++i, onComplete);
}
if (onComplete) {
onComplete();
}
}
/**
* start highlighting all the code blocks
*
* @returns void
*/
function _highlight(node, onComplete) {
// the first argument can be an Event or a DOM Element
// I was originally checking instanceof Event but that makes it break
// when using mootools
//
// @see https://github.com/ccampbell/rainbow/issues/32
//
node = node && typeof node.getElementsByTagName == 'function' ? node : document;
var pre_blocks = node.getElementsByTagName('pre'),
code_blocks = node.getElementsByTagName('code'),
i,
final_pre_blocks = [],
final_code_blocks = [];
// first loop through all pre blocks to find which ones to highlight
// also strip whitespace
for (i = 0; i < pre_blocks.length; ++i) {
// strip whitespace around code tags when they are inside of a pre tag
// this makes the themes look better because you can't accidentally
// add extra linebreaks at the start and end
//
// when the pre tag contains a code tag then strip any extra whitespace
// for example
// <pre>
// <code>var foo = true;</code>
// </pre>
//
// will become
// <pre><code>var foo = true;</code></pre>
//
// if you want to preserve whitespace you can use a pre tag on its own
// without a code tag inside of it
if (pre_blocks[i].getElementsByTagName('code').length) {
pre_blocks[i].innerHTML = pre_blocks[i].innerHTML.replace(/^\s+/, '').replace(/\s+$/, '');
continue;
}
// if the pre block has no code blocks then we are going to want to
// process it directly
final_pre_blocks.push(pre_blocks[i]);
}
// @see http://stackoverflow.com/questions/2735067/how-to-convert-a-dom-node-list-to-an-array-in-javascript
// we are going to process all <code> blocks
for (i = 0; i < code_blocks.length; ++i) {
final_code_blocks.push(code_blocks[i]);
}
_highlightCodeBlock(final_code_blocks.concat(final_pre_blocks), 0, onComplete);
}
/**
* public methods
*/
return {
/**
* extends the language pattern matches
*
* @param {*} language name of language
* @param {*} patterns array of patterns to add on
* @param {boolean|null} bypass if true this will bypass the default language patterns
*/
extend: function(language, patterns, bypass) {
// if there is only one argument then we assume that we want to
// extend the default language rules
if (arguments.length == 1) {
patterns = language;
language = DEFAULT_LANGUAGE;
}
bypass_defaults[language] = bypass;
language_patterns[language] = patterns.concat(language_patterns[language] || []);
},
/**
* call back to let you do stuff in your app after a piece of code has been highlighted
*
* @param {Function} callback
*/
onHighlight: function(callback) {
onHighlight = callback;
},
/**
* method to set a global class that will be applied to all spans
*
* @param {string} class_name
*/
addClass: function(class_name) {
global_class = class_name;
},
/**
* starts the magic rainbow
*
* @returns void
*/
color: function() {
// if you want to straight up highlight a string you can pass the string of code,
// the language, and a callback function
if (typeof arguments[0] == 'string') {
return _highlightBlockForLanguage(arguments[0], arguments[1], arguments[2]);
}
// if you pass a callback function then we rerun the color function
// on all the code and call the callback function on complete
if (typeof arguments[0] == 'function') {
return _highlight(0, arguments[0]);
}
// otherwise we use whatever node you passed in with an optional
// callback function as the second parameter
_highlight(arguments[0], arguments[1]);
}
};
}) ();
/**
* adds event listener to start highlighting
*/
(function() {
if (document.addEventListener) {
return document.addEventListener('DOMContentLoaded', Rainbow.color, false);
}
window.attachEvent('onload', Rainbow.color);
}) ();
// When using Google closure compiler in advanced mode some methods
// get renamed. This keeps a public reference to these methods so they can
// still be referenced from outside this library.
Rainbow["onHighlight"] = Rainbow.onHighlight;
Rainbow["addClass"] = Rainbow.addClass;

View file

@ -0,0 +1,118 @@
// Only install the plugin if Rainbow is present and has been loaded
if (window.Rainbow) window.Rainbow.linenumbers = (function(Rainbow) {
/**
* Splits up a single element into individual lines
*
* @param {HTMLElement} elem
* @returns {Array}
*/
function splitElement(elem) {
if (elem.nodeType === 3) {
// Just split up the text node
return elem.nodeValue.split('\n');
}
// Otherwise, we need to split up the HTML
var sourceLines = elem.innerHTML.split('\n');
var lines = [];
// Wraps each chunk in the parent element. For example:
// <b>foo\nbar</b> -> [<b>foo</b>, <b>bar</b>]
for (var i = 0; i < sourceLines.length; i++) {
// Handles <b>\nbar</b> -> [, <b>bar</b>]
if (sourceLines[i] === '') {
lines.push('');
} else {
var wrapper = elem.cloneNode(true);
wrapper.innerHTML = sourceLines[i];
var div = document.createElement('div');
div.appendChild(wrapper.cloneNode(true));
lines.push(div.innerHTML);
}
}
return lines;
};
/**
* Splits up the element containing highlighted source code
* into an array of lines
*
* @param {HTMLElement} block
* @returns {Array}
*/
function splitLines(block) {
var lines = [''];
for (var i = 0; i < block.childNodes.length; i++) {
var elemLines = splitElement(block.childNodes[i]);
// The first element in elemLines is
// a continuation of the previous line
lines[lines.length - 1] += elemLines[0];
// The remaining elements get their own lines
for (var j = 1; j < elemLines.length; j++) {
lines.push(elemLines[j]);
}
}
// Returns the array of lines
return lines;
};
// Callback is called when Rainbow has highlighted a block
Rainbow.onHighlight(function(block) {
// This addresses an issue when Rainbow.color() is called multiple times.
// Since code element is replaced with table element below,
// second pass of Rainbow.color() will result in block.parentNode being null.
if (!block || !block.parentNode) {
return;
}
// Create a table wrapper
var table = document.createElement('table');
table.className = 'rainbow';
table.setAttribute('data-language', block.getAttribute('data-language'));
// Split up the lines of the block
var lines = splitLines(block);
// For each line
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var index = i + 1;
// Create a row
var row = table.insertRow(-1);
row.className = 'line line-' + index;
// Create a cell which displays the line number with CSS
var lineNumber = row.insertCell(-1);
lineNumber.className = 'line-number';
lineNumber.setAttribute('data-line-number', index);
// Add in the actual line of source code
var code = row.insertCell(-1);
code.className = 'line-code';
// If the line is blank, add a newline to make it copyable.
if (line === '') {
line = '\n';
}
code.innerHTML = line;
}
// If the block is a <pre> element, its parent is not an element
// generated by Rainbow (i.e. it could be <body>). We don't want
// to clear this.
var parent = (block.nodeName.toLowerCase() === 'pre') ? block : block.parentNode;
// Clear the parent element and use the table in place of the <code> block
parent.innerHTML = '';
parent.appendChild(table);
});
})(window.Rainbow);

View file

@ -0,0 +1,2 @@
window.Rainbow&&(window.Rainbow.linenumbers=function(m){m.onHighlight(function(c){if(c&&c.parentNode){var h=document.createElement("table");h.className="rainbow";h.setAttribute("data-language",c.getAttribute("data-language"));for(var e=[""],d=0;d<c.childNodes.length;d++){var a;a=c.childNodes[d];if(3===a.nodeType)a=a.nodeValue.split("\n");else{for(var b=a.innerHTML.split("\n"),f=[],g=0;g<b.length;g++)if(""===b[g])f.push("");else{var k=a.cloneNode(!0);k.innerHTML=b[g];var l=document.createElement("div");
l.appendChild(k.cloneNode(!0));f.push(l.innerHTML)}a=f}e[e.length-1]+=a[0];for(b=1;b<a.length;b++)e.push(a[b])}for(d=0;d<e.length;d++)a=e[d],b=d+1,f=h.insertRow(-1),f.className="line line-"+b,g=f.insertCell(-1),g.className="line-number",g.setAttribute("data-line-number",b),b=f.insertCell(-1),b.className="line-code",""===a&&(a="\n"),b.innerHTML=a;c="pre"===c.nodeName.toLowerCase()?c:c.parentNode;c.innerHTML="";c.appendChild(h)}})}(window.Rainbow));

View file

@ -6,10 +6,12 @@
<link rel="stylesheet" href="../assets/css/main.css" type="text/css"/>
<link rel="stylesheet" href="../assets/css/menu.css" type="text/css" media="screen" />
<link rel="stylesheet" href="../assets/css/solarized-light.css" type="text/css"/>
<link rel="stylesheet" href="../assets/css/solarized-light-linenumbers.css" type="text/css" />
<script src="../example-data.js" type="text/javascript"></script>
<script src="../assets/js/menu.js" type="text/javascript"></script>
<script src="../assets/js/rainbow.min.js" type="text/javascript"></script>
<script src="../assets/js/rainbow.linenumbers.min.js" type="text/javascript"></script>
<script src="../assets/js/language/generic.js" type="text/javascript"></script>
<script src="../assets/js/language/javascript.js" type="text/javascript"></script>
</head>

View file

@ -4,4 +4,4 @@
#
# Requires release.token and releases/<version>.md
curl https://api.github.com/repos/openscad/openscad/releases -H "Authorization: token $(<release.token)" -d "$(./scripts/makereleasejson.py $1)"
curl https://api.github.com/repos/openscad/openscad/releases -H "Authorization: token $(<release.token>)" -d "$(./scripts/makereleasejson.py $1)"

View file

@ -1,14 +1,12 @@
#!/bin/bash
#
# This script builds all library dependencies of OpenSCAD for Mac OS X.
# The libraries will be build in 64-bit (and optionally 32-bit mode) mode
# and backwards compatible with 10.5 "Leopard".
# The libraries will be build in 64-bit mode and backwards compatible with 10.7 "Lion".
#
# This script must be run from the OpenSCAD source root directory
#
# Usage: macosx-build-dependencies.sh [-16lcdf] [<package>]
# -3 Build using C++03 and libstdc++
# -6 Build only 64-bit binaries
# -3 Build using C++03 and libstdc++ (default is C++11 and libc++)
# -l Force use of LLVM compiler
# -c Force use of clang compiler
# -d Build for deployment (if not specified, e.g. Sparkle won't be built)
@ -26,7 +24,6 @@ OPENSCADDIR=$PWD
SRCDIR=$BASEDIR/src
DEPLOYDIR=$BASEDIR/install
MAC_OSX_VERSION_MIN=10.7
OPTION_32BIT=false
OPTION_LLVM=false
OPTION_CLANG=false
OPTION_GCC=false
@ -35,36 +32,35 @@ OPTION_FORCE=0
OPTION_CXX11=true
PACKAGES=(
"eigen 3.2.4"
"gmp 5.1.3"
"mpfr 3.1.2"
"boost 1.58.0"
"qt5 5.4.1"
"qscintilla 2.8.4"
# NB! For eigen, also update the path in the function
"eigen 3.2.6"
"gmp 5.1.3"
"mpfr 3.1.3"
"boost 1.59.0"
"qt5 5.5.1"
"qscintilla 2.8.4"
# NB! For CGAL, also update the actual download URL in the function
"cgal 4.5.2"
"glew 1.12.0"
"gettext 0.19.4"
"cgal 4.6.3"
"glew 1.13.0"
"gettext 0.19.6"
"libffi 3.2.1"
"glib2 2.42.1"
"glib2 2.46.1"
"opencsg 1.4.0"
"freetype 2.5.5"
"freetype 2.6.1"
"ragel 6.9"
"harfbuzz 0.9.40"
"harfbuzz 1.0.6"
"libxml2 2.9.2"
"fontconfig 2.11.1"
)
DEPLOY_PACKAGES=(
"sparkle Cocoanetics:1e7dcb1a48b96d1a8c62100b5864bd50211cbae1"
"sparkle 1.13.1"
)
printUsage()
{
echo "Usage: $0 [-36lcdf] [<package>]"
echo "Usage: $0 [-3lcdf] [<package>]"
echo
echo " -3 Build using C++03 and libstdc++"
echo " -6 Build only 64-bit binaries"
echo " -l Force use of LLVM compiler"
echo " -c Force use of clang compiler"
echo " -d Build for deployment"
@ -112,7 +108,6 @@ build()
build_$package $version
set +e
fi
}
# Usage: is_installed <package> [<version>]
@ -188,9 +183,6 @@ build_qt()
sed -i "" -e "s/::TabletProximityRec/TabletProximityRec/g" src/gui/kernel/qt_cocoa_helpers_mac_p.h
PLATFORM="-platform unsupported/macx-clang"
fi
if $OPTION_32BIT; then
QT_32BIT="-arch x86"
fi
case "$OSX_VERSION" in
9)
# libtiff fails in the linker step with Mavericks / XCode 5.0.1
@ -202,7 +194,7 @@ build_qt()
MACOSX_RELEASE_OPTIONS=
;;
esac
./configure -prefix $DEPLOYDIR -release $QT_32BIT -arch x86_64 -opensource -confirm-license $PLATFORM -fast -no-qt3support -no-svg -no-phonon -no-audio-backend -no-multimedia -no-javascript-jit -no-script -no-scripttools -no-declarative -no-xmlpatterns -nomake demos -nomake examples -nomake docs -nomake translations -no-webkit $MACOSX_RELEASE_OPTIONS
./configure -prefix $DEPLOYDIR -release -arch x86_64 -opensource -confirm-license $PLATFORM -fast -no-qt3support -no-svg -no-phonon -no-audio-backend -no-multimedia -no-javascript-jit -no-script -no-scripttools -no-declarative -no-xmlpatterns -nomake demos -nomake examples -nomake docs -nomake translations -no-webkit $MACOSX_RELEASE_OPTIONS
make -j"$NUMCPU" install
}
@ -224,15 +216,20 @@ build_qt5()
fi
tar xzf qt-everywhere-opensource-src-$version.tar.gz
cd qt-everywhere-opensource-src-$version
CXXFLAGS="$CXXSTDFLAGS" ./configure -prefix $DEPLOYDIR -release -opensource -confirm-license \
patch -d qtbase -p1 < $OPENSCADDIR/patches/qt5/QTBUG-46846.patch
if ! $USING_CXX11; then
QT_EXTRA_FLAGS="-no-c++11"
fi
CXXFLAGS="$CXXSTDFLAGS" ./configure -prefix $DEPLOYDIR $QT_EXTRA_FLAGS -release -opensource -confirm-license \
-nomake examples -nomake tests \
-no-xcb -no-glib -no-harfbuzz -no-sql-db2 -no-sql-ibase -no-sql-mysql -no-sql-oci -no-sql-odbc \
-no-sql-psql -no-sql-sqlite2 -no-sql-tds -no-cups -no-qml-debug \
-skip activeqt -skip connectivity -skip declarative -skip doc \
-skip enginio -skip graphicaleffects -skip location -skip multimedia \
-skip quick1 -skip quickcontrols -skip script -skip sensors -skip serialport \
-skip svg -skip webkit -skip webkit-examples -skip websockets -skip xmlpatterns
make -j"$NUMCPU" install
-skip svg -skip webkit -skip webkit-examples -skip websockets -skip xmlpatterns -skip qtwebchannel
make -j"$NUMCPU"
make install
}
check_qscintilla()
@ -252,7 +249,7 @@ build_qscintilla()
tar xzf QScintilla-gpl-$version.tar.gz
cd QScintilla-gpl-$version/Qt4Qt5
qmake QMAKE_CXXFLAGS+="$CXXSTDFLAGS" QMAKE_LFLAGS+="$CXXSTDFLAGS" qscintilla.pro
make -j6 install
make -j"$NUMCPU" install
install_name_tool -id $DEPLOYDIR/lib/libqscintilla2.dylib $DEPLOYDIR/lib/libqscintilla2.dylib
}
@ -261,9 +258,6 @@ check_gmp()
check_file lib/libgmp.dylib
}
# Hack warning: gmplib is built separately in 32-bit and 64-bit mode
# and then merged afterwards. gmplib's header files are dependent on
# the CPU architecture on which configure was run and will be patched accordingly.
build_gmp()
{
version=$1
@ -276,87 +270,11 @@ build_gmp()
fi
tar xjf gmp-$version.tar.bz2
cd gmp-$version
patch -p0 gmp-h.in << EOF
--- gmp-5.1.3/gmp-h.in.old 2013-12-02 20:16:26.000000000 -0800
+++ gmp-5.1.3/gmp-h.in 2013-12-02 20:21:22.000000000 -0800
@@ -27,13 +27,38 @@
#endif
-/* Instantiated by configure. */
#if ! defined (__GMP_WITHIN_CONFIGURE)
+/* For benefit of fat builds on MacOSX, generate a .h file that can
+ * be used with a universal fat library
+ */
+#if defined(__x86_64__)
+#define __GMP_HAVE_HOST_CPU_FAMILY_power 0
+#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0
+#define GMP_LIMB_BITS 64
+#define GMP_NAIL_BITS 0
+#elif defined(__i386__)
+#define __GMP_HAVE_HOST_CPU_FAMILY_power 0
+#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 0
+#define GMP_LIMB_BITS 32
+#define GMP_NAIL_BITS 0
+#elif defined(__powerpc64__)
+#define __GMP_HAVE_HOST_CPU_FAMILY_power 0
+#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 1
+#define GMP_LIMB_BITS 64
+#define GMP_NAIL_BITS 0
+#elif defined(__ppc__)
+#define __GMP_HAVE_HOST_CPU_FAMILY_power 0
+#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc 1
+#define GMP_LIMB_BITS 32
+#define GMP_NAIL_BITS 0
+#else
+/* For other architectures, fall back on values computed by configure */
#define __GMP_HAVE_HOST_CPU_FAMILY_power @HAVE_HOST_CPU_FAMILY_power@
#define __GMP_HAVE_HOST_CPU_FAMILY_powerpc @HAVE_HOST_CPU_FAMILY_powerpc@
#define GMP_LIMB_BITS @GMP_LIMB_BITS@
#define GMP_NAIL_BITS @GMP_NAIL_BITS@
#endif
+#endif
#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS)
#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS)
#define GMP_NUMB_MAX GMP_NUMB_MASK
EOF
./configure --prefix=$DEPLOYDIR CXXFLAGS="$CXXSTDFLAGS" CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS="$LDSTDFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" ABI=64 --enable-cxx
make -j"$NUMCPU" install
if $OPTION_32BIT; then
mkdir build-i386
cd build-i386
../configure --prefix=$DEPLOYDIR/i386 CXXFLAGS="$CXXSTDFLAGS" CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386" LDFLAGS="$LDSTDFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386" ABI=32 --enable-cxx
make install
cd ..
fi
# 64-bit version
mkdir build-x86_64
cd build-x86_64
../configure --prefix=$DEPLOYDIR/x86_64 CXXFLAGS="$CXXSTDFLAGS" CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS="$LDSTDFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" ABI=64 --enable-cxx
make install
# merge
cd $DEPLOYDIR
mkdir -p lib
if $OPTION_32BIT; then
lipo -create i386/lib/libgmp.dylib x86_64/lib/libgmp.dylib -output lib/libgmp.dylib
lipo -create i386/lib/libgmpxx.dylib x86_64/lib/libgmpxx.dylib -output lib/libgmpxx.dylib
else
cp x86_64/lib/libgmp.dylib lib/libgmp.dylib
cp x86_64/lib/libgmpxx.dylib lib/libgmpxx.dylib
fi
install_name_tool -id $DEPLOYDIR/lib/libgmp.dylib lib/libgmp.dylib
install_name_tool -id $DEPLOYDIR/lib/libgmpxx.dylib lib/libgmpxx.dylib
install_name_tool -change $DEPLOYDIR/x86_64/lib/libgmp.10.dylib $DEPLOYDIR/lib/libgmp.dylib lib/libgmpxx.dylib
if $OPTION_32BIT; then
cp lib/libgmp.dylib i386/lib/
cp lib/libgmp.dylib x86_64/lib/
cp lib/libgmpxx.dylib i386/lib/
cp lib/libgmpxx.dylib x86_64/lib/
fi
mkdir -p include
cp x86_64/include/gmp.h include/
cp x86_64/include/gmpxx.h include/
install_name_tool -id $DEPLOYDIR/lib/libgmp.dylib $DEPLOYDIR/lib/libgmp.dylib
install_name_tool -id $DEPLOYDIR/lib/libgmpxx.dylib $DEPLOYDIR/lib/libgmpxx.dylib
}
check_mpfr()
@ -366,6 +284,11 @@ check_mpfr()
# As with gmplib, mpfr is built separately in 32-bit and 64-bit mode and then merged
# afterwards.
check_mpfr()
{
check_file include/mpfr.h
}
build_mpfr()
{
version=$1
@ -378,33 +301,11 @@ build_mpfr()
fi
tar xjf mpfr-$version.tar.bz2
cd mpfr-$version
# curl -O http://www.mpfr.org/mpfr-$version/allpatches
# patch -N -Z -p1 < allpatches
if $OPTION_32BIT; then
mkdir build-i386
cd build-i386
../configure --prefix=$DEPLOYDIR/i386 --with-gmp=$DEPLOYDIR/i386 CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386" LDFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386"
make install
cd ..
fi
# 64-bit version
mkdir build-x86_64
cd build-x86_64
../configure --prefix=$DEPLOYDIR/x86_64 --with-gmp=$DEPLOYDIR/x86_64 CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64"
make install
./configure --prefix=$DEPLOYDIR --with-gmp=$DEPLOYDIR CFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64"
make -j"$NUMCPU" install
# merge
cd $DEPLOYDIR
if $OPTION_32BIT; then
lipo -create i386/lib/libmpfr.dylib x86_64/lib/libmpfr.dylib -output lib/libmpfr.dylib
else
cp x86_64/lib/libmpfr.dylib lib/libmpfr.dylib
fi
install_name_tool -id $DEPLOYDIR/lib/libmpfr.dylib lib/libmpfr.dylib
mkdir -p include
cp x86_64/include/mpfr.h include/
cp x86_64/include/mpf2mpfr.h include/
install_name_tool -id $DEPLOYDIR/lib/libmpfr.dylib $DEPLOYDIR/lib/libmpfr.dylib
}
check_boost()
@ -427,9 +328,6 @@ build_boost()
cd boost_$bversion
# We only need the thread and program_options libraries
./bootstrap.sh --prefix=$DEPLOYDIR --with-libraries=thread,program_options,filesystem,chrono,system,regex
if $OPTION_32BIT; then
BOOST_EXTRA_FLAGS="-arch i386"
fi
if $USING_LLVM; then
BOOST_TOOLSET="toolset=darwin-llvm"
echo "using darwin : llvm : llvm-g++ ;" >> tools/build/user-config.jam
@ -437,7 +335,7 @@ build_boost()
BOOST_TOOLSET="toolset=clang"
echo "using clang ;" >> tools/build/user-config.jam
fi
./b2 -j"$NUMCPU" -d+2 $BOOST_TOOLSET cflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $BOOST_EXTRA_FLAGS $CXXSTDFLAGS" linkflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $BOOST_EXTRA_FLAGS $LDSTDFLAGS -headerpad_max_install_names" install
./b2 -j"$NUMCPU" -d+2 $BOOST_TOOLSET cflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $CXXSTDFLAGS" linkflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $LDSTDFLAGS -headerpad_max_install_names" install
install_name_tool -id $DEPLOYDIR/lib/libboost_thread.dylib $DEPLOYDIR/lib/libboost_thread.dylib
install_name_tool -change libboost_system.dylib $DEPLOYDIR/lib/libboost_system.dylib $DEPLOYDIR/lib/libboost_thread.dylib
install_name_tool -change libboost_chrono.dylib $DEPLOYDIR/lib/libboost_chrono.dylib $DEPLOYDIR/lib/libboost_thread.dylib
@ -463,8 +361,9 @@ build_cgal()
cd $BASEDIR/src
rm -rf CGAL-$version
if [ ! -f CGAL-$version.tar.gz ]; then
# 4.5.2
curl -O https://gforge.inria.fr/frs/download.php/file/34512/CGAL-$version.tar.gz
# 4.6.3
curl -O https://gforge.inria.fr/frs/download.php/file/35138/CGAL-$version.tar.gz
# 4.5.2 curl -O https://gforge.inria.fr/frs/download.php/file/34512/CGAL-$version.tar.gz
# 4.5.1 curl -O https://gforge.inria.fr/frs/download.php/file/34400/CGAL-$version.tar.gz
# 4.5 curl -O https://gforge.inria.fr/frs/download.php/file/34149/CGAL-$version.tar.gz
# 4.4 curl -O https://gforge.inria.fr/frs/download.php/file/33525/CGAL-$version.tar.gz
@ -480,10 +379,7 @@ build_cgal()
fi
tar xzf CGAL-$version.tar.gz
cd CGAL-$version
if $OPTION_32BIT; then
CGAL_EXTRA_FLAGS=";i386"
fi
CXXFLAGS="$CXXSTDFLAGS" cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DGMP_INCLUDE_DIR=$DEPLOYDIR/include -DGMP_LIBRARIES=$DEPLOYDIR/lib/libgmp.dylib -DGMPXX_LIBRARIES=$DEPLOYDIR/lib/libgmpxx.dylib -DGMPXX_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_LIBRARIES=$DEPLOYDIR/lib/libmpfr.dylib -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DBUILD_SHARED_LIBS=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$CGAL_EXTRA_FLAGS" -DBOOST_ROOT=$DEPLOYDIR -DBoost_USE_MULTITHREADED=false
CXXFLAGS="$CXXSTDFLAGS" cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DGMP_INCLUDE_DIR=$DEPLOYDIR/include -DGMP_LIBRARIES=$DEPLOYDIR/lib/libgmp.dylib -DGMPXX_LIBRARIES=$DEPLOYDIR/lib/libgmpxx.dylib -DGMPXX_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_INCLUDE_DIR=$DEPLOYDIR/include -DMPFR_LIBRARIES=$DEPLOYDIR/lib/libmpfr.dylib -DWITH_CGAL_Qt3=OFF -DWITH_CGAL_Qt4=OFF -DWITH_CGAL_ImageIO=OFF -DBUILD_SHARED_LIBS=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64" -DBOOST_ROOT=$DEPLOYDIR -DBoost_USE_MULTITHREADED=false
make -j"$NUMCPU" install
make install
install_name_tool -id $DEPLOYDIR/lib/libCGAL.dylib $DEPLOYDIR/lib/libCGAL.dylib
@ -509,10 +405,7 @@ build_glew()
tar xzf glew-$version.tgz
cd glew-$version
mkdir -p $DEPLOYDIR/lib/pkgconfig
if $OPTION_32BIT; then
GLEW_EXTRA_FLAGS="-arch i386"
fi
make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install
make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64" STRIP= install
}
check_opencsg()
@ -533,10 +426,7 @@ build_opencsg()
tar xzf OpenCSG-$version.tar.gz
cd OpenCSG-$version
patch -p1 < $OPENSCADDIR/patches/OpenCSG-$version-MacOSX-port.patch
if $OPTION_32BIT; then
OPENCSG_EXTRA_FLAGS="x86"
fi
qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include $CXXSTDFLAGS" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib $LDSTDFLAGS" CONFIG+="x86_64 $OPENCSG_EXTRA_FLAGS" DESTDIR=$DEPLOYDIR
qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include $CXXSTDFLAGS" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib $LDSTDFLAGS" CONFIG+="x86_64" DESTDIR=$DEPLOYDIR
make install
}
@ -570,6 +460,7 @@ build_eigen()
elif [ $version = "3.2.2" ]; then EIGENDIR=eigen-eigen-1306d75b4a21;
elif [ $version = "3.2.3" ]; then EIGENDIR=eigen-eigen-36fd1ba04c12;
elif [ $version = "3.2.4" ]; then EIGENDIR=eigen-eigen-10219c95fe65;
elif [ $version = "3.2.6" ]; then EIGENDIR=eigen-eigen-c58038c56923;
fi
if [ $EIGENDIR = "none" ]; then
@ -587,10 +478,7 @@ build_eigen()
cd eigen-$version
mkdir build
cd build
if $OPTION_32BIT; then
EIGEN_EXTRA_FLAGS=";i386"
fi
CXXFLAGS="$CXXSTDFLAGS" cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_TEST_NOQT=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$EIGEN_EXTRA_FLAGS" ..
CXXFLAGS="$CXXSTDFLAGS" cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_TEST_NOQT=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64" ..
make -j"$NUMCPU" install
}
@ -599,35 +487,48 @@ check_sparkle()
check_file lib/Sparkle.framework/Sparkle
}
# Usage: build_sparkle <githubuser>:<commitID>
# Usage:
# build_sparkle <githubuser>:<commitID>
# build_sparkle <version>
build_sparkle()
{
v=$1
github=${1%%:*} # Cut at first colon
version=${1#*:} # cut until first colon
echo "Building Sparkle" $version "..."
# Let Sparkle use the default compiler
unset CC
unset CXX
# Binary install:
version=$1
cd $BASEDIR/src
rm -rf Sparkle-$version
if [ ! -f Sparkle-$version.zip ]; then
curl -o Sparkle-$version.zip https://nodeload.github.com/$github/Sparkle/zip/$version
if [ ! -f Sparkle-$version.tar.bz2 ]; then
curl -LO https://github.com/sparkle-project/Sparkle/releases/download/$version/Sparkle-$version.tar.bz2
fi
unzip -q Sparkle-$version.zip
mkdir Sparkle-$version
cd Sparkle-$version
patch -p1 < $OPENSCADDIR/patches/sparkle.patch
if $OPTION_32BIT; then
SPARKLE_EXTRA_FLAGS="-arch i386"
fi
xcodebuild clean
xcodebuild -arch x86_64 $SPARKLE_EXTRA_FLAGS
rm -rf $DEPLOYDIR/lib/Sparkle.framework
cp -Rf build/Release/Sparkle.framework $DEPLOYDIR/lib/
install_name_tool -id $DEPLOYDIR/lib/Sparkle.framework/Versions/A/Sparkle $DEPLOYDIR/lib/Sparkle.framework/Sparkle
tar xjf ../Sparkle-$version.tar.bz2
cp -Rf Sparkle.framework $DEPLOYDIR/lib/
# Build from source:
# v=$1
# github=${1%%:*} # Cut at first colon
# version=${1#*:} # cut until first colon
#
# echo "Building Sparkle" $version "..."
#
# # Let Sparkle use the default compiler
# unset CC
# unset CXX
#
# cd $BASEDIR/src
# rm -rf Sparkle-$version
# if [ ! -f Sparkle-$version.zip ]; then
# curl -o Sparkle-$version.zip https://nodeload.github.com/$github/Sparkle/zip/$version
# fi
# unzip -q Sparkle-$version.zip
# cd Sparkle-$version
# patch -p1 < $OPENSCADDIR/patches/sparkle.patch
# xcodebuild clean
# xcodebuild -arch x86_64
# rm -rf $DEPLOYDIR/lib/Sparkle.framework
# cp -Rf build/Release/Sparkle.framework $DEPLOYDIR/lib/
# Install_name_tool -id $DEPLOYDIR/lib/Sparkle.framework/Versions/A/Sparkle $DEPLOYDIR/lib/Sparkle.framework/Sparkle
}
check_freetype()
@ -779,7 +680,6 @@ check_ragel()
check_file bin/ragel
}
set -x
build_ragel()
{
version=$1
@ -830,11 +730,10 @@ if [ ! -f $OPENSCADDIR/openscad.pro ]; then
fi
OPENSCAD_SCRIPTDIR=$PWD/scripts
while getopts '36lcdf' c
while getopts '3lcdf' c
do
case $c in
3) USING_CXX11=false;;
6) OPTION_32BIT=false;;
l) OPTION_LLVM=true;;
c) OPTION_CLANG=true;;
d) OPTION_DEPLOY=true;;
@ -846,7 +745,9 @@ done
OPTION_PACKAGES="${@:$OPTIND}"
OSX_VERSION=`sw_vers -productVersion | cut -d. -f2`
if (( $OSX_VERSION >= 10 )); then
if (( $OSX_VERSION >= 11 )); then
echo "Detected El Capitan (10.11) or later"
elif (( $OSX_VERSION >= 10 )); then
echo "Detected Yosemite (10.10) or later"
elif (( $OSX_VERSION >= 9 )); then
echo "Detected Mavericks (10.9)"
@ -893,6 +794,9 @@ fi
if $USING_CXX11; then
export CXXSTDFLAGS="-std=c++11 -stdlib=libc++"
export LDSTDFLAGS="-stdlib=libc++"
else
export CXXSTDFLAGS="-std=c++03 -stdlib=libstdc++"
export LDSTDFLAGS="-stdlib=libstdc++"
fi
echo "Building for $MAC_OSX_VERSION_MIN or later"
@ -906,12 +810,6 @@ if $OPTION_DEPLOY; then
echo "Building deployment version of libraries"
fi
if $OPTION_32BIT; then
echo "Building combined 32/64-bit binaries"
else
echo "Building 64-bit binaries"
fi
if (( $OPTION_FORCE )); then
echo "Forcing rebuild"
fi

View file

@ -31,21 +31,26 @@ def usage():
def lookup_library(file):
found = None
if not re.match("/", file):
if re.search("@executable_path", file):
abs = re.sub("^@executable_path", executable_path, file)
if os.path.exists(abs): found = abs
if DEBUG: print "Lib in @executable_path found: " + str(found)
elif re.search("\.app/", file):
found = file
if DEBUG: print "App found: " + str(found)
elif re.search("\.framework/", file):
found = os.path.join("/Library/Frameworks", file)
if DEBUG: print "Framework found: " + str(found)
else:
for path in os.getenv("DYLD_LIBRARY_PATH").split(':'):
abs = os.path.join(path, file)
if re.search("@rpath", file):
file = re.sub("^@rpath", lc_rpath, file)
if os.path.exists(file): found = file
if DEBUG: print "Lib in @rpath found: " + str(file)
if (not found):
if re.search("@executable_path", file):
abs = re.sub("^@executable_path", executable_path, file)
if os.path.exists(abs): found = abs
if DEBUG: print "Library found: " + str(found)
if DEBUG: print "Lib in @executable_path found: " + str(found)
elif re.search("\.app/", file):
found = file
if DEBUG: print "App found: " + str(found)
elif re.search("\.framework/", file):
found = os.path.join("/Library/Frameworks", file)
if DEBUG: print "Framework found: " + str(found)
else:
for path in os.getenv("DYLD_LIBRARY_PATH").split(':'):
abs = os.path.join(path, file)
if os.path.exists(abs): found = abs
if DEBUG: print "Library found: " + str(found)
else:
found = file
return found
@ -117,6 +122,18 @@ if __name__ == '__main__':
executable = sys.argv[1]
if DEBUG: print "Processing " + executable
executable_path = os.path.dirname(executable)
# Find the Runpath search path (LC_RPATH)
p = subprocess.Popen(["otool", "-l", executable], stdout=subprocess.PIPE)
output = p.communicate()[0]
if p.returncode != 0:
print 'Error otool -l failed on main executable'
sys.exit(1)
# Check deployment target
m = re.search("LC_RPATH\n(.*)\n\s+path ([^ ]+)", output, re.MULTILINE)
lc_rpath = m.group(2)
if DEBUG: print 'Runpath search path: ' + lc_rpath
# processed is a dict {libname : [parents]} - each parent is dependant on libname
processed = {}
pending = [executable]
@ -125,17 +142,18 @@ if __name__ == '__main__':
dep = pending.pop()
if DEBUG: print "Evaluating " + dep
deps = find_dependencies(dep)
# if DEBUG: print "Deps: " + ' '.join(deps)
assert(deps)
for d in deps:
absfile = lookup_library(d)
if not re.match(executable_path, absfile):
print "Error: External dependency " + d
sys.exit(1)
if absfile == None:
print "Not found: " + d
print " ..required by " + str(processed[dep])
error = True
continue
if not re.match(executable_path, absfile):
print "Error: External dependency " + d
sys.exit(1)
if absfile in processed:
processed[absfile].append(dep)
else:

View file

@ -20,8 +20,21 @@
#
# Also see http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Cross-compiling_for_Windows_on_Linux_or_Mac_OS_X
#
# Also note the 64 bit is built on the branch of mxe by Tony Theodore
# which hasnt been merged to official mxe as of writing
# Notes:
#
# Originally this was based on Tony Theodore's branch of MXE, which is now
# integrated into official MXE.
#
# Targets:
#
# MXE allows 4 separate targets with the MXE_TARGETS environment variable.
# As of 2015 shared are not guaranteed to work.
#
# 64 bit static linked libraries MXE_TARGETS=x86_64-w64-mingw32.static
# 32 bit static linked libraries MXE_TARGETS=i686-w64-mingw32.static
# 64 bit shared libraries MXE_TARGETS=x86_64-w64-mingw32.shared
# 32 bit shared libraries MXE_TARGETS=i686-w64-mingw32.shared
#
OPENSCADDIR=$PWD
if [ ! -f $OPENSCADDIR/openscad.pro ]; then

View file

@ -72,16 +72,17 @@ elif [[ $OSTYPE == "linux-gnu" ]]; then
echo "Detected build-machine ARCH: $ARCH"
fi
if [ "`echo $* | grep mingw32`" ]; then
if [ "`echo $* | grep mingw`" ]; then
OS=UNIX_CROSS_WIN
ARCH=32
echo Mingw-cross build using ARCH=32
fi
if [ "`echo $* | grep mingw64`" ]; then
OS=UNIX_CROSS_WIN
ARCH=64
echo Mingw-cross build using ARCH=64
MXELIBTYPE=static
if [ "`echo $* | grep mingw64`" ]; then
ARCH=64
fi
if [ "`echo $* | grep shared`" ]; then
MXELIBTYPE=shared
fi
echo Mingw-cross build using ARCH=$ARCH MXELIBTYPE=$MXELIBTYPE
fi
if [ "`echo $* | grep snapshot`" ]; then
@ -179,7 +180,7 @@ case $OS in
QT_SELECT=5
export QT_SELECT
;;
WIN)
WIN)
export QTDIR=/c/devmingw/qt2009.03
export QTMAKESPEC=win32-g++
export PATH=$PATH:/c/devmingw/qt2009.03/bin:/c/devmingw/qt2009.03/qt/bin
@ -187,8 +188,8 @@ case $OS in
ZIPARGS="a -tzip"
TARGET=release
;;
UNIX_CROSS_WIN)
. ./scripts/setenv-mingw-xbuild.sh $ARCH
UNIX_CROSS_WIN)
. ./scripts/setenv-mingw-xbuild.sh $ARCH $MXELIBTYPE
TARGET=release
ZIP="zip"
ZIPARGS="-r -q"
@ -198,7 +199,12 @@ esac
case $OS in
UNIX_CROSS_WIN)
cd $DEPLOYDIR && qmake VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+="$CONFIG" CONFIG+=mingw-cross-env CONFIG-=debug ../openscad.pro
cd $DEPLOYDIR
MINGWCONFIG=mingw-cross-env
if [ $MXELIBTYPE = "shared" ]; then
MINGWCONFIG=mingw-cross-env-shared
fi
qmake VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+="$CONFIG" CONFIG+=$MINGWCONFIG CONFIG-=debug ../openscad.pro
cd $OPENSCADDIR
;;
*)
@ -425,9 +431,78 @@ case $OS in
INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH-Installer.exe
#package
if [ $MXELIBTYPE = "shared" ]; then
flprefix=$DEPLOYDIR/mingw-cross-env/bin
echo Copying dlls for shared library build
echo from $flprefix
echo to $DEPLOYDIR/$TARGET
flist=
# fl="$fl opengl.dll" # use Windows version?
# fl="$fl libmpfr.dll" # does not exist
fl="$fl libgmp-10.dll"
fl="$fl libgmpxx-4.dll"
fl="$fl libboost_filesystem-mt.dll"
fl="$fl libboost_program_options-mt.dll"
fl="$fl libboost_regex-mt.dll"
fl="$fl libboost_chrono-mt.dll"
fl="$fl libboost_system-mt.dll"
fl="$fl libboost_thread_win32-mt.dll"
fl="$fl libCGAL.dll"
fl="$fl libCGAL_Core.dll"
fl="$fl GLEW.dll"
fl="$fl libglib-2.0-0.dll"
fl="$fl libopencsg-1.dll"
fl="$fl libharfbuzz-0.dll"
# fl="$fl libharfbuzz-gobject-0.dll" # ????
fl="$fl libfontconfig-1.dll"
fl="$fl libexpat-1.dll"
fl="$fl libbz2.dll"
fl="$fl libintl-8.dll"
fl="$fl libiconv-2.dll"
fl="$fl libfreetype-6.dll"
fl="$fl libpcre16-0.dll"
fl="$fl zlib1.dll"
fl="$fl libpng16-16.dll"
fl="$fl icudt54.dll"
fl="$fl icudt.dll"
fl="$fl icuin.dll"
fl="$fl libstdc++-6.dll"
fl="$fl ../qt5/lib/qscintilla2.dll"
fl="$fl ../qt5/bin/Qt5PrintSupport.dll"
fl="$fl ../qt5/bin/Qt5Core.dll"
fl="$fl ../qt5/bin/Qt5Gui.dll"
fl="$fl ../qt5/bin/Qt5OpenGL.dll"
# fl="$fl ../qt5/bin/QtSvg4.dll" # why is this here?
fl="$fl ../qt5/bin/Qt5Widgets.dll"
fl="$fl ../qt5/bin/Qt5PrintSupport.dll"
fl="$fl ../qt5/bin/Qt5PrintSupport.dll"
for dllfile in $fl; do
if [ -e $flprefix/$dllfile ]; then
echo $flprefix/$dllfile
cp $flprefix/$dllfile $DEPLOYDIR/$TARGET/
else
echo cannot find $flprefix/$dllfile
echo stopping build.
exit 1
fi
done
fi
echo "Copying main binary .exe, .com, and dlls"
echo "from $DEPLOYDIR/$TARGET"
echo "to $DEPLOYDIR/openscad-$VERSION"
TMPTAR=$DEPLOYDIR/tmpmingw.$ARCH.$MXELIBTYPE.tar
cd $DEPLOYDIR
cd $TARGET
tar cvf $TMPTAR --exclude=winconsole.o .
cd $DEPLOYDIR
cd ./openscad-$VERSION
tar xvf $TMPTAR
cd $DEPLOYDIR
rm -f $TMPTAR
echo "Creating binary zip package"
cp $TARGET/openscad.exe openscad-$VERSION
cp $TARGET/openscad.com openscad-$VERSION
rm -f OpenSCAD-$VERSION.x86-$ARCH.zip
"$ZIP" $ZIPARGS $BINFILE openscad-$VERSION
cd $OPENSCADDIR
@ -528,7 +603,7 @@ if [ $BUILD_TESTS ]; then
# while copying.
rm -f ./ostests.tar
for subdir in tests testdata libraries examples doc; do
tar prvf ./ostests.tar --exclude=.git* --exclude=*/mingw64/* --exclude=*/mingw32/* --exclude=*.cc.obj --exclude=*.a $subdir
tar prvf ./ostests.tar --exclude=.git* --exclude=*/mingw* --exclude=*.cc.obj --exclude=*.a $subdir
done
cd $DEPLOYDIR
tar prvf $OPENSCADDIR/ostests.tar --exclude=.git* --exclude=*/mingw* --exclude=*.cc.obj --exclude=*.a $TESTBINDIR

View file

@ -4,10 +4,12 @@
#
# Usage:
#
# source ./scripts/setenv-mingw-xbuild.sh # 32 bit build
# source ./scripts/setenv-mingw-xbuild.sh 64 # 64 bit build
# source ./scripts/setenv-mingw-xbuild.sh clean # Clean up exported variables
# source ./scripts/setenv-mingw-xbuild.sh qt5 # use qt5 (experimental)
# source ./scripts/setenv-mingw-xbuild.sh # 32 bit build
# source ./scripts/setenv-mingw-xbuild.sh shared # 32 bit build, shared libs
# source ./scripts/setenv-mingw-xbuild.sh 64 # 64 bit build
# source ./scripts/setenv-mingw-xbuild.sh 64 shared # 64 bit build, shared libs
# source ./scripts/setenv-mingw-xbuild.sh clean # Clean up exported variables
# source ./scripts/setenv-mingw-xbuild.sh qt5 # use qt5 (experimental)
#
# Prerequisites:
#
@ -22,8 +24,14 @@ if [ ! $BASEDIR ]; then
BASEDIR=$HOME/openscad_deps
fi
DEPLOYDIR64=$OPENSCADDIR/mingw64
DEPLOYDIR32=$OPENSCADDIR/mingw32
MXELIBTYPE=static
if [ "`echo $* | grep shared `" ]; then
MXELIBTYPE=shared
fi
DEPLOYDIR64=$OPENSCADDIR/mingw64.$MXELIBTYPE
DEPLOYDIR32=$OPENSCADDIR/mingw32.$MXELIBTYPE
if [ ! $DEPLOYDIR ]; then
if [ "`echo $* | grep 64 `" ]; then
@ -39,6 +47,11 @@ if [ ! $MXEDIR ]; then
else
MXEDIR=$BASEDIR/mxe
fi
if [ ! -e $MXEDIR ]; then
if [ -e /opt/mxe ]; then
MXEDIR=/opt/mxe
fi
fi
fi
if [ ! $MXEQTSUBDIR ]; then
@ -56,9 +69,9 @@ if [ ! -e $DEPLOYDIR ]; then
fi
if [ "`echo $* | grep 64 `" ]; then
MXETARGETDIR=$MXEDIR/usr/x86_64-w64-mingw32.static
MXETARGETDIR=$MXEDIR/usr/x86_64-w64-mingw32.$MXELIBTYPE
else
MXETARGETDIR=$MXEDIR/usr/i686-w64-mingw32.static
MXETARGETDIR=$MXEDIR/usr/i686-w64-mingw32.$MXELIBTYPE
fi
if [ ! $MINGWX_SAVED_ORIGINAL_PATH ]; then
@ -91,6 +104,7 @@ export OPENSCAD_LIBRARIES
export BASEDIR
export MXEDIR
export MXETARGETDIR
export MXELIBTYPE
export DEPLOYDIR
export PATH
export MINGWX_SAVED_ORIGINAL_PATH
@ -100,6 +114,7 @@ echo OPENSCAD_LIBRARIES: $OPENSCAD_LIBRARIES
echo BASEDIR: $BASEDIR
echo MXEDIR: $MXEDIR
echo MXETARGETDIR: $MXETARGETDIR
echo MXELIBTYPE: $MXELIBTYPE
echo DEPLOYDIR: $DEPLOYDIR
echo MXEQTSUBDIR: $MXEQTSUBDIR
if [ "`echo $* | grep clean`" ]; then

View file

@ -190,7 +190,11 @@ build_qt5scintilla2()
tar xzf QScintilla-gpl-$version.tar.gz
cd QScintilla-gpl-$version/Qt4Qt5/
qmake CONFIG+=staticlib
make -j"$NUMCPU" install
tmpinstalldir=$DEPLOYDIR/tmp/qsci$version
INSTALL_ROOT=$tmpinstalldir make -j"$NUMCPU" install
cp -av $tmpinstalldir/usr/share $DEPLOYDIR/
cp -av $tmpinstalldir/usr/include $DEPLOYDIR/
cp -av $tmpinstalldir/usr/lib $DEPLOYDIR/
}
build_bison()
@ -412,8 +416,10 @@ build_cgal()
# older cmakes have buggy FindBoost that can result in
# finding the system libraries but OPENSCAD_LIBRARIES include paths
FINDBOOST_CMAKE=$OPENSCAD_SCRIPTDIR/../tests/FindBoost.cmake
cp $FINDBOOST_CMAKE ./cmake/modules/
# NB! This was removed 2015-12-02 - if this problem resurfaces, fix it only for the relevant platforms as this
# messes up more recent installations of cmake and CGAL.
# FINDBOOST_CMAKE=$OPENSCAD_SCRIPTDIR/../tests/FindBoost.cmake
# cp $FINDBOOST_CMAKE ./cmake/modules/
mkdir bin
cd bin

View file

@ -82,22 +82,70 @@ get_debian_deps()
gtk-doc-tools libglib2.0-dev gettext xvfb pkg-config ragel
}
get_debian_8_deps()
{
get_debian_deps
apt-get -y install libharfbuzz-dev qtbase5-dev libqt5scintilla2-dev
}
get_debian_7_deps()
{
get_debian_deps
apt-get -y install libqt4-dev libqscintilla2-dev
echo "debian 7 detected"
echo "please build harfbuzz & see the README on building dependencies"
echo ". ./scripts/setenv-unibuild.sh"
echo "./scripts/uni-build-dependencies.sh harfbuzz"
}
get_qt4or5_deps_debian()
{
# debian 8 can have both qt4 and qt5 installed... or neither. figure out which
# and cater to it.
useqt=5
if [ "`dpkg --list | grep qt5-default`" ]; then
useqt=5
elif [ "`dpkg --list | grep qt4-default`" ]; then
useqt=4
elif [ "`echo QT_SELECT | grep ^4`" ]; then
useqt=4
elif [ "`echo QT_SELECT | grep qt4`" ]; then
useqt=4
elif [ "`echo QT_SELECT | grep ^5`" ]; then
useqt=5
elif [ "`echo QT_SELECT | grep qt5`" ]; then
useqt=5
elif [ ! "`command -v qtchooser`" ]; then
useqt=5
elif [ "`qtchooser -l | grep qt5`" ]; then
useqt=5
elif [ ! "`qtchooser -l | grep qt4`" ]; then
useqt=5
elif [ ! "`command -v qmake`" ]; then
useqt=5
elif [ "`qmake --version | grep -i qt.version.4`" ]; then
useqt=4
fi
if [ $useqt = 5 ]; then
apt-get -y install qtbase5-dev libqt5scintilla2-dev libqt5opengl5-dev qt5-qmake
else
apt-get -y install libqt4-dev libqscintilla2-dev libqt4-opengl-dev
fi
if [ ! "`command -v qmake`" ]; then
apt-get -y install qt$useqt-default
echo "installed qt$useqt-default to enable qmake"
elif [ ! "`qmake --version | grep qmake.version`" ]; then
apt-get -y install qt$useqt-default
echo "installed qt$useqt-default to enable qmake"
fi
}
get_debian_8_deps()
{
apt-get -y install libharfbuzz-dev
get_debian_deps
get_qt4or5_deps_debian
}
get_ubuntu_14_deps()
{
get_debian_8_deps
apt-get -y install qt5-qmake
}
unknown()
@ -117,8 +165,12 @@ if [ -e /etc/issue ]; then
get_debian_8_deps
elif [ "`grep -i raspbian /etc/issue`" ]; then
get_debian_deps
elif [ "`grep -i linux.mint.2 /etc/issue`" ]; then
get_ubuntu_14_deps
elif [ "`grep -i linux.mint.1[789] /etc/issue`" ]; then
get_ubuntu_14_deps
elif [ "`grep -i mint /etc/issue`" ]; then
get_debian_deps
get_debian_7_deps
elif [ "`grep -i suse /etc/issue`" ]; then
get_opensuse_deps
elif [ "`grep -i fedora.release.2[2-9] /etc/issue`" ]; then

11
setenv_mac-c++11.sh Normal file
View file

@ -0,0 +1,11 @@
export OPENSCAD_LIBRARIES=$PWD/../libraries/install-c++11
export DYLD_LIBRARY_PATH=$OPENSCAD_LIBRARIES/lib
export DYLD_FRAMEWORK_PATH=$OPENSCAD_LIBRARIES/lib
# Our own Qt
export PATH=$OPENSCAD_LIBRARIES/bin:$PATH
unset QMAKESPEC
# ccache:
export PATH=/opt/local/libexec/ccache:$PATH
export CCACHE_BASEDIR=$PWD/..

View file

@ -11,8 +11,6 @@ public:
AboutDialog(QWidget *) {
setupUi(this);
this->setWindowTitle( QString(_("About OpenSCAD")) + " " + openscad_shortversionnumber.c_str());
QUrl flattr_qurl(":icons/flattr.png" );
this->aboutText->loadResource( QTextDocument::ImageResource, flattr_qurl );
QString tmp = this->aboutText->toHtml();
tmp.replace("__VERSION__", openscad_detailedversionnumber.c_str());
this->aboutText->setHtml(tmp);

View file

@ -9,13 +9,29 @@
<head>
<meta charset="UTF-8"/>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<style type=text/css>
body {
font: 13pt Arial,sans-serif;
}
.flattr-link {
color: white;
background: #88B058;
font: bold 14px Helvetica,sans-serif;
}
.donate-link {
color: white;
background: dodgerblue;
font: bold 14px Helvetica,sans-serif;
}
</style>
</head>
<body>
<body style="font-family:'Arial'; font-size:13pt;">
<p>
<a align=right href="https://flattr.com/submit/auto?user_id=openscad&amp;url=http://openscad.org&amp;title=OpenSCAD&amp;language=&amp;tags=github&amp;category=software"><img align=right src=":icons/flattr.png" /></a>
<p align="right">
<a class="flattr-link" href="https://flattr.com/submit/auto?user_id=openscad&amp;url=http://openscad.org&amp;title=OpenSCAD&amp;language=&amp;tags=github&amp;category=software">&nbsp;Flattr&nbsp;this!&nbsp;</a>
<a class="donate-link" href="http://www.openscad.org/community.html">&nbsp;Donate&nbsp;</a>
</p>
<p>

View file

@ -1,4 +1,4 @@
#include <AppleEvents.h>
#include "AppleEvents.h"
#include <MacTypes.h>
#include <CoreServices/CoreServices.h>
#include <QApplication>
@ -12,7 +12,7 @@ OSErr eventHandler(const AppleEvent *, AppleEvent *, SRefCon )
{
// FIXME: Ugly hack; just using the first MainWindow we can find
MainWindow *mainwin = NULL;
foreach (QWidget *w, QApplication::topLevelWidgets()) {
for (auto &w : QApplication::topLevelWidgets()) {
mainwin = qobject_cast<MainWindow*>(w);
if (mainwin) break;
}

View file

@ -109,7 +109,7 @@ void CGALRenderer::draw(bool showfaces, bool showedges) const
glBegin(GL_POLYGON);
for (size_t j=0; j < this->polyset->polygons[i].size(); j++) {
const Vector3d &p = this->polyset->polygons[i][j];
glVertex3d(p[0], p[1], -0.1);
glVertex3d(p[0], p[1], 0);
}
glEnd();
}

View file

@ -93,7 +93,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
}
#endif
void CGAL_Nef_polyhedron::resize(Vector3d newsize,
void CGAL_Nef_polyhedron::resize(const Vector3d &newsize,
const Eigen::Matrix<bool,3,1> &autosize)
{
// Based on resize() in Giles Bathgate's RapCAD (but not exactly)

View file

@ -30,7 +30,7 @@ public:
// FIXME: Deprecated by CGALUtils::createPolySetFromNefPolyhedron3
// class PolySet *convertToPolyset() const;
void transform( const Transform3d &matrix );
void resize(Vector3d newsize, const Eigen::Matrix<bool,3,1> &autosize);
void resize(const Vector3d &newsize, const Eigen::Matrix<bool,3,1> &autosize);
shared_ptr<CGAL_Nef_polyhedron3> p3;
};

View file

@ -1,251 +0,0 @@
#include "CSGTermEvaluator.h"
#include "visitor.h"
#include "state.h"
#include "csgterm.h"
#include "module.h"
#include "csgnode.h"
#include "transformnode.h"
#include "colornode.h"
#include "rendernode.h"
#include "cgaladvnode.h"
#include "printutils.h"
#include "GeometryEvaluator.h"
#include "polyset.h"
#include "polyset-utils.h"
#include <string>
#include <map>
#include <list>
#include <sstream>
#include <iostream>
#include <assert.h>
#include <cstddef>
#include <boost/foreach.hpp>
/*!
\class CSGTermEvaluator
A visitor responsible for creating a tree of CSGTerm nodes used for rendering
with OpenCSG.
*/
shared_ptr<CSGTerm> CSGTermEvaluator::evaluateCSGTerm(const AbstractNode &node,
std::vector<shared_ptr<CSGTerm> > &highlights,
std::vector<shared_ptr<CSGTerm> > &background)
{
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
evaluate.execute();
highlights = this->highlights;
background = this->background;
return this->stored_term[node.index()];
}
void CSGTermEvaluator::applyToChildren(const AbstractNode &node, CSGTermEvaluator::CsgOp op)
{
shared_ptr<CSGTerm> t1;
BOOST_FOREACH(const AbstractNode *chnode, this->visitedchildren[node.index()]) {
shared_ptr<CSGTerm> t2(this->stored_term[chnode->index()]);
this->stored_term.erase(chnode->index());
if (t2 && !t1) {
t1 = t2;
} else if (t2 && t1) {
if (op == CSGT_UNION) {
t1 = CSGTerm::createCSGTerm(CSGTerm::TYPE_UNION, t1, t2);
} else if (op == CSGT_DIFFERENCE) {
t1 = CSGTerm::createCSGTerm(CSGTerm::TYPE_DIFFERENCE, t1, t2);
} else if (op == CSGT_INTERSECTION) {
t1 = CSGTerm::createCSGTerm(CSGTerm::TYPE_INTERSECTION, t1, t2);
}
}
}
if (t1 && node.modinst->isHighlight()) {
t1->flag = CSGTerm::FLAG_HIGHLIGHT;
this->highlights.push_back(t1);
}
if (t1 && node.modinst->isBackground()) {
this->background.push_back(t1);
t1.reset(); // don't propagate background tagged nodes
}
this->stored_term[node.index()] = t1;
}
Response CSGTermEvaluator::visit(State &state, const AbstractNode &node)
{
if (state.isPostfix()) {
applyToChildren(node, CSGT_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermEvaluator::visit(State &state, const AbstractIntersectionNode &node)
{
if (state.isPostfix()) {
applyToChildren(node, CSGT_INTERSECTION);
addToParent(state, node);
}
return ContinueTraversal;
}
static shared_ptr<CSGTerm> evaluate_csg_term_from_geometry(const State &state,
std::vector<shared_ptr<CSGTerm> > &highlights,
std::vector<shared_ptr<CSGTerm> > &background,
const shared_ptr<const Geometry> &geom,
const ModuleInstantiation *modinst,
const AbstractNode &node)
{
std::stringstream stream;
stream << node.name() << node.index();
// We cannot render Polygon2d directly, so we preprocess (tessellate) it here
shared_ptr<const Geometry> g = geom;
if (!g->isEmpty()) {
shared_ptr<const Polygon2d> p2d = dynamic_pointer_cast<const Polygon2d>(geom);
if (p2d) {
g.reset(p2d->tessellate());
}
else {
// We cannot render concave polygons, so tessellate any 3D PolySets
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(geom);
// Since is_convex() doesn't handle non-planar faces, we need to tessellate
// also in the indeterminate state so we cannot just use a boolean comparison. See #1061
bool convex = ps->convexValue();
if (ps && !convex) {
assert(ps->getDimension() == 3);
PolySet *ps_tri = new PolySet(3, ps->convexValue());
ps_tri->setConvexity(ps->getConvexity());
PolysetUtils::tessellate_faces(*ps, *ps_tri);
g.reset(ps_tri);
}
}
}
shared_ptr<CSGTerm> t(new CSGTerm(g, state.matrix(), state.color(), stream.str()));
if (modinst->isHighlight()) {
t->flag = CSGTerm::FLAG_HIGHLIGHT;
highlights.push_back(t);
}
if (modinst->isBackground()) {
background.push_back(t);
t.reset();
}
return t;
}
Response CSGTermEvaluator::visit(State &state, const AbstractPolyNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGTerm> t1;
if (this->geomevaluator) {
shared_ptr<const Geometry> geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermEvaluator::visit(State &state, const CsgNode &node)
{
if (state.isPostfix()) {
CsgOp op = CSGT_UNION;
switch (node.type) {
case OPENSCAD_UNION:
op = CSGT_UNION;
break;
case OPENSCAD_DIFFERENCE:
op = CSGT_DIFFERENCE;
break;
case OPENSCAD_INTERSECTION:
op = CSGT_INTERSECTION;
break;
default:
assert(false);
}
applyToChildren(node, op);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermEvaluator::visit(State &state, const TransformNode &node)
{
if (state.isPrefix()) {
state.setMatrix(state.matrix() * node.matrix);
}
if (state.isPostfix()) {
applyToChildren(node, CSGT_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermEvaluator::visit(State &state, const ColorNode &node)
{
if (state.isPrefix()) {
if (!state.color().isValid()) state.setColor(node.color);
}
if (state.isPostfix()) {
applyToChildren(node, CSGT_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
// FIXME: If we've got CGAL support, render this node as a CGAL union into a PolySet
Response CSGTermEvaluator::visit(State &state, const RenderNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGTerm> t1;
shared_ptr<const Geometry> geom;
if (this->geomevaluator) {
geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTermEvaluator::visit(State &state, const CgaladvNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGTerm> t1;
// FIXME: Calling evaluator directly since we're not a PolyNode. Generalize this.
shared_ptr<const Geometry> geom;
if (this->geomevaluator) {
geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluate_csg_term_from_geometry(state, this->highlights, this->background,
geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
/*!
Adds ourself to out parent's list of traversed children.
Call this for _every_ node which affects output during traversal.
Usually, this should be called from the postfix stage, but for some nodes, we defer traversal letting other components (e.g. CGAL) render the subgraph, and we'll then call this from prefix and prune further traversal.
*/
void CSGTermEvaluator::addToParent(const State &state, const AbstractNode &node)
{
this->visitedchildren.erase(node.index());
if (state.parent()) {
this->visitedchildren[state.parent()->index()].push_back(&node);
}
}

View file

@ -1,47 +0,0 @@
#pragma once
#include <map>
#include <list>
#include <vector>
#include <cstddef>
#include "visitor.h"
#include "memory.h"
class CSGTermEvaluator : public Visitor
{
public:
CSGTermEvaluator(const class Tree &tree, class GeometryEvaluator *geomevaluator = NULL)
: tree(tree), geomevaluator(geomevaluator) {
}
virtual ~CSGTermEvaluator() {}
virtual Response visit(State &state, const class AbstractNode &node);
virtual Response visit(State &state, const class AbstractIntersectionNode &node);
virtual Response visit(State &state, const class AbstractPolyNode &node);
virtual Response visit(State &state, const class CsgNode &node);
virtual Response visit(State &state, const class TransformNode &node);
virtual Response visit(State &state, const class ColorNode &node);
virtual Response visit(State &state, const class RenderNode &node);
virtual Response visit(State &state, const class CgaladvNode &node);
shared_ptr<class CSGTerm> evaluateCSGTerm(const AbstractNode &node,
std::vector<shared_ptr<CSGTerm> > &highlights,
std::vector<shared_ptr<CSGTerm> > &background);
private:
enum CsgOp {CSGT_UNION, CSGT_INTERSECTION, CSGT_DIFFERENCE, CSGT_MINKOWSKI};
void addToParent(const State &state, const AbstractNode &node);
void applyToChildren(const AbstractNode &node, CSGTermEvaluator::CsgOp op);
const AbstractNode *root;
typedef std::list<const AbstractNode *> ChildList;
std::map<int, ChildList> visitedchildren;
public:
std::map<int, shared_ptr<CSGTerm> > stored_term; // The term evaluated from each node index
std::vector<shared_ptr<CSGTerm> > highlights;
std::vector<shared_ptr<CSGTerm> > background;
const Tree &tree;
class GeometryEvaluator *geomevaluator;
};

294
src/CSGTreeEvaluator.cc Normal file
View file

@ -0,0 +1,294 @@
#include "CSGTreeEvaluator.h"
#include "visitor.h"
#include "state.h"
#include "csgops.h"
#include "module.h"
#include "csgnode.h"
#include "transformnode.h"
#include "colornode.h"
#include "rendernode.h"
#include "cgaladvnode.h"
#include "printutils.h"
#include "GeometryEvaluator.h"
#include "polyset.h"
#include "polyset-utils.h"
#include <string>
#include <map>
#include <list>
#include <sstream>
#include <iostream>
#include <assert.h>
#include <cstddef>
/*!
\class CSGTreeEvaluator
A visitor responsible for creating a binary tree of CSGNode nodes used for rendering
with OpenCSG.
*/
shared_ptr<CSGNode> CSGTreeEvaluator::buildCSGTree(const AbstractNode &node)
{
Traverser evaluate(*this, node, Traverser::PRE_AND_POSTFIX);
evaluate.execute();
shared_ptr<CSGNode> t(this->stored_term[node.index()]);
if (t) {
if (t->isHighlight()) this->highlightNodes.push_back(t);
if (t->isBackground()) {
this->backgroundNodes.push_back(t);
t.reset();
}
}
return this->rootNode = t;
}
void CSGTreeEvaluator::applyBackgroundAndHighlight(State &state, const AbstractNode &node)
{
for(const auto &chnode : this->visitedchildren[node.index()]) {
shared_ptr<CSGNode> t(this->stored_term[chnode->index()]);
this->stored_term.erase(chnode->index());
if (t) {
if (t->isBackground()) this->backgroundNodes.push_back(t);
if (t->isHighlight()) this->highlightNodes.push_back(t);
}
}
}
void CSGTreeEvaluator::applyToChildren(State &state, const AbstractNode &node, OpenSCADOperator op)
{
shared_ptr<CSGNode> t1;
const ModuleInstantiation *t1_modinst;
for(const auto &chnode : this->visitedchildren[node.index()]) {
shared_ptr<CSGNode> t2(this->stored_term[chnode->index()]);
const ModuleInstantiation *t2_modinst = chnode->modinst;
this->stored_term.erase(chnode->index());
if (t2 && !t1) {
t1 = t2;
t1_modinst = t2_modinst;
} else if (t2 && t1) {
shared_ptr<CSGNode> t;
// Handle background
if (t1->isBackground() &&
// For difference, we inherit the flag from the positive object
(t2->isBackground() || op == OPENSCAD_DIFFERENCE)) {
t = CSGOperation::createCSGNode(op, t1, t2);
t->setBackground(true);
}
// Background objects are simply moved to backgroundNodes
else if (t2->isBackground()) {
t = t1;
this->backgroundNodes.push_back(t2);
}
else if (t1->isBackground()) {
t = t2;
this->backgroundNodes.push_back(t1);
}
else {
t = CSGOperation::createCSGNode(op, t1, t2);
}
// Handle highlight
switch (op) {
case OPENSCAD_DIFFERENCE:
if (t != t1 && t1->isHighlight()) {
t->setHighlight(true);
}
else if (t != t2 && t2->isHighlight()) {
this->highlightNodes.push_back(t2);
}
break;
case OPENSCAD_INTERSECTION:
if (t != t1 && t != t2 &&
t1->isHighlight() && t2->isHighlight()) {
t->setHighlight(true);
}
else if (t != t1 && t1->isHighlight()) {
this->highlightNodes.push_back(t1);
}
else if (t != t2 && t2->isHighlight()) {
this->highlightNodes.push_back(t2);
}
break;
case OPENSCAD_UNION:
if (t != t1 && t != t2 &&
t1->isHighlight() && t2->isHighlight()) {
t->setHighlight(true);
}
else if (t != t1 && t1->isHighlight()) {
this->highlightNodes.push_back(t1);
t = t2;
}
else if (t != t2 && t2->isHighlight()) {
this->highlightNodes.push_back(t2);
t = t1;
}
break;
}
t1 = t;
}
}
if (t1) {
if (node.modinst->isBackground()) t1->setBackground(true);
if (node.modinst->isHighlight()) t1->setHighlight(true);
}
this->stored_term[node.index()] = t1;
}
Response CSGTreeEvaluator::visit(State &state, const AbstractNode &node)
{
if (state.isPostfix()) {
applyToChildren(state, node, OPENSCAD_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTreeEvaluator::visit(State &state, const AbstractIntersectionNode &node)
{
if (state.isPostfix()) {
applyToChildren(state, node, OPENSCAD_INTERSECTION);
addToParent(state, node);
}
return ContinueTraversal;
}
shared_ptr<CSGNode> CSGTreeEvaluator::evaluateCSGNodeFromGeometry(
State &state, const shared_ptr<const Geometry> &geom,
const ModuleInstantiation *modinst, const AbstractNode &node)
{
std::stringstream stream;
stream << node.name() << node.index();
// We cannot render Polygon2d directly, so we preprocess (tessellate) it here
shared_ptr<const Geometry> g = geom;
if (!g->isEmpty()) {
shared_ptr<const Polygon2d> p2d = dynamic_pointer_cast<const Polygon2d>(geom);
if (p2d) {
g.reset(p2d->tessellate());
}
else {
// We cannot render concave polygons, so tessellate any 3D PolySets
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(geom);
// Since is_convex() doesn't handle non-planar faces, we need to tessellate
// also in the indeterminate state so we cannot just use a boolean comparison. See #1061
bool convex = ps->convexValue();
if (ps && !convex) {
assert(ps->getDimension() == 3);
PolySet *ps_tri = new PolySet(3, ps->convexValue());
ps_tri->setConvexity(ps->getConvexity());
PolysetUtils::tessellate_faces(*ps, *ps_tri);
g.reset(ps_tri);
}
}
}
shared_ptr<CSGNode> t(new CSGLeaf(g, state.matrix(), state.color(), stream.str()));
if (modinst->isHighlight()) t->setHighlight(true);
else if (modinst->isBackground()) t->setBackground(true);
return t;
}
Response CSGTreeEvaluator::visit(State &state, const AbstractPolyNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGNode> t1;
if (this->geomevaluator) {
shared_ptr<const Geometry> geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluateCSGNodeFromGeometry(state, geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTreeEvaluator::visit(State &state, const CsgOpNode &node)
{
if (state.isPostfix()) {
applyToChildren(state, node, node.type);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTreeEvaluator::visit(State &state, const TransformNode &node)
{
if (state.isPrefix()) {
state.setMatrix(state.matrix() * node.matrix);
}
if (state.isPostfix()) {
applyToChildren(state, node, OPENSCAD_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTreeEvaluator::visit(State &state, const ColorNode &node)
{
if (state.isPrefix()) {
if (!state.color().isValid()) state.setColor(node.color);
}
if (state.isPostfix()) {
applyToChildren(state, node, OPENSCAD_UNION);
addToParent(state, node);
}
return ContinueTraversal;
}
// FIXME: If we've got CGAL support, render this node as a CGAL union into a PolySet
Response CSGTreeEvaluator::visit(State &state, const RenderNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGNode> t1;
shared_ptr<const Geometry> geom;
if (this->geomevaluator) {
geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluateCSGNodeFromGeometry(state, geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
addToParent(state, node);
}
return ContinueTraversal;
}
Response CSGTreeEvaluator::visit(State &state, const CgaladvNode &node)
{
if (state.isPostfix()) {
shared_ptr<CSGNode> t1;
// FIXME: Calling evaluator directly since we're not a PolyNode. Generalize this.
shared_ptr<const Geometry> geom;
if (this->geomevaluator) {
geom = this->geomevaluator->evaluateGeometry(node, false);
if (geom) {
t1 = evaluateCSGNodeFromGeometry(state, geom, node.modinst, node);
}
node.progress_report();
}
this->stored_term[node.index()] = t1;
applyBackgroundAndHighlight(state, node);
addToParent(state, node);
}
return ContinueTraversal;
}
/*!
Adds ourself to out parent's list of traversed children.
Call this for _every_ node which affects output during traversal.
Usually, this should be called from the postfix stage, but for some nodes, we defer traversal letting other components (e.g. CGAL) render the subgraph, and we'll then call this from prefix and prune further traversal.
*/
void CSGTreeEvaluator::addToParent(const State &state, const AbstractNode &node)
{
this->visitedchildren.erase(node.index());
if (state.parent()) {
this->visitedchildren[state.parent()->index()].push_back(&node);
}
}

60
src/CSGTreeEvaluator.h Normal file
View file

@ -0,0 +1,60 @@
#pragma once
#include <map>
#include <list>
#include <vector>
#include <cstddef>
#include "visitor.h"
#include "memory.h"
#include "csgnode.h"
class CSGTreeEvaluator : public Visitor
{
public:
CSGTreeEvaluator(const class Tree &tree, class GeometryEvaluator *geomevaluator = NULL)
: tree(tree), geomevaluator(geomevaluator) {
}
virtual ~CSGTreeEvaluator() {}
virtual Response visit(State &state, const class AbstractNode &node);
virtual Response visit(State &state, const class AbstractIntersectionNode &node);
virtual Response visit(State &state, const class AbstractPolyNode &node);
virtual Response visit(State &state, const class CsgOpNode &node);
virtual Response visit(State &state, const class TransformNode &node);
virtual Response visit(State &state, const class ColorNode &node);
virtual Response visit(State &state, const class RenderNode &node);
virtual Response visit(State &state, const class CgaladvNode &node);
shared_ptr<class CSGNode> buildCSGTree(const AbstractNode &node);
const shared_ptr<CSGNode> &getRootNode() const {
return this->rootNode;
}
const std::vector<shared_ptr<CSGNode>> &getHighlightNodes() const {
return this->highlightNodes;
}
const std::vector<shared_ptr<CSGNode>> &getBackgroundNodes() const {
return this->backgroundNodes;
}
private:
void addToParent(const State &state, const AbstractNode &node);
void applyToChildren(State &state, const AbstractNode &node, OpenSCADOperator op);
shared_ptr<CSGNode> evaluateCSGNodeFromGeometry(State &state,
const shared_ptr<const class Geometry> &geom,
const class ModuleInstantiation *modinst,
const AbstractNode &node);
void applyBackgroundAndHighlight(State &state, const AbstractNode &node);
const AbstractNode *root;
typedef std::list<const AbstractNode *> ChildList;
std::map<int, ChildList> visitedchildren;
protected:
const Tree &tree;
class GeometryEvaluator *geomevaluator;
shared_ptr<CSGNode> rootNode;
std::vector<shared_ptr<CSGNode>> highlightNodes;
std::vector<shared_ptr<CSGNode>> backgroundNodes;
std::map<int, shared_ptr<CSGNode>> stored_term; // The term evaluated from each node index
};

235
src/CSGTreeNormalizer.cc Normal file
View file

@ -0,0 +1,235 @@
#include "CSGTreeNormalizer.h"
#include "csgnode.h"
#include "printutils.h"
// Helper function to debug normalization bugs
#if 0
static bool validate_tree(const shared_ptr<CSGNode> &node)
{
if (node->getType() == OPENSCAD_PRIMITIVE) return true;
if (!node->left() || !node->right()) return false;
if (!validate_tree(node->left())) return false;
if (!validate_tree(node->right())) return false;
return true;
}
#endif
/*!
NB! for e.g. empty intersections, this can normalize a tree to nothing and return NULL.
*/
shared_ptr<CSGNode> CSGTreeNormalizer::normalize(const shared_ptr<CSGNode> &root)
{
this->aborted = false;
shared_ptr<CSGNode> temp = root;
while (1) {
this->rootnode = temp;
this->nodecount = 0;
shared_ptr<CSGNode> n = normalizePass(temp);
if (!n) return n; // If normalized to nothing
if (temp == n) break;
temp = n;
if (this->nodecount > this->limit) {
PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit);
// Clean up any partially evaluated nodes
shared_ptr<CSGNode> newroot = root, tmproot;
while (newroot && newroot != tmproot) {
tmproot = newroot;
newroot = collapse_null_terms(tmproot);
}
newroot = cleanup_term(newroot);
return newroot;
}
}
this->rootnode.reset();
return temp;
}
/*!
After aborting, a subtree might have become invalidated (NULL child node)
since terms can be instantiated multiple times.
This will search for NULL children an recursively repair the corresponding
subtree.
*/
shared_ptr<CSGNode> CSGTreeNormalizer::cleanup_term(shared_ptr<CSGNode> &t)
{
if (shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(t)) {
if (op->left()) op->left() = cleanup_term(op->left());
if (op->right()) op->right() = cleanup_term(op->right());
return collapse_null_terms(op);
}
return t;
}
static bool isUnion(shared_ptr<CSGNode> node) {
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
return op && op->getType() == OPENSCAD_UNION;
}
static bool hasRightLeaf(shared_ptr<CSGNode> node) {
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
return op && dynamic_pointer_cast<CSGLeaf>(op->right());
}
static bool hasLeftUnion(shared_ptr<CSGNode> node) {
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
return op && isUnion(op->left());
}
shared_ptr<CSGNode> CSGTreeNormalizer::normalizePass(shared_ptr<CSGNode> node)
{
// This function implements the CSG normalization
// Reference:
// Goldfeather, J., Molnar, S., Turk, G., and Fuchs, H. Near
// Realtime CSG Rendering Using Tree Normalization and Geometric
// Pruning. IEEE Computer Graphics and Applications, 9(3):20-28,
// 1989.
// http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
if (dynamic_pointer_cast<CSGLeaf>(node)) return node;
do {
while (node && match_and_replace(node)) { }
this->nodecount++;
if (nodecount > this->limit) {
PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit);
this->aborted = true;
return shared_ptr<CSGNode>();
}
if (!node) return node;
if (shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node)) {
op->left() = normalizePass(op->left());
}
} while (!this->aborted && !isUnion(node) &&
(!hasRightLeaf(node) ||
hasLeftUnion(node)));
if (!this->aborted) {
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
assert(op);
op->right() = normalizePass(op->right());
}
// FIXME: Do we need to take into account any transformation of item here?
shared_ptr<CSGNode> t = collapse_null_terms(node);
if (this->aborted) {
if (t) t = cleanup_term(t);
}
return t;
}
shared_ptr<CSGNode> CSGTreeNormalizer::collapse_null_terms(const shared_ptr<CSGNode> &node)
{
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
if (op) {
if (!op->right()) {
if (op->getType() == OPENSCAD_UNION || op->getType() == OPENSCAD_DIFFERENCE) return op->left();
else return op->right();
}
if (!op->left()) {
if (op->getType() == OPENSCAD_UNION) return op->right();
else return op->left();
}
}
return node;
}
bool CSGTreeNormalizer::match_and_replace(shared_ptr<CSGNode> &node)
{
shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node);
if (!op) return false;
if (op->getType() == OPENSCAD_UNION) return false;
// Part A: The 'x . (y . z)' expressions
shared_ptr<CSGOperation> rightop = dynamic_pointer_cast<CSGOperation>(op->right());
if (rightop) {
shared_ptr<CSGNode> x = op->left();
shared_ptr<CSGNode> y = rightop->left();
shared_ptr<CSGNode> z = rightop->right();
// 1. x - (y + z) -> (x - y) - z
if (op->getType() == OPENSCAD_DIFFERENCE && rightop->getType() == OPENSCAD_UNION) {
node = CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE,
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, x, y),
z);
return true;
}
// 2. x * (y + z) -> (x * y) + (x * z)
else if (op->getType() == OPENSCAD_INTERSECTION && rightop->getType() == OPENSCAD_UNION) {
node = CSGOperation::createCSGNode(OPENSCAD_UNION,
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, y),
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, z));
return true;
}
// 3. x - (y * z) -> (x - y) + (x - z)
else if (op->getType() == OPENSCAD_DIFFERENCE && rightop->getType() == OPENSCAD_INTERSECTION) {
node = CSGOperation::createCSGNode(OPENSCAD_UNION,
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, x, y),
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, x, z));
return true;
}
// 4. x * (y * z) -> (x * y) * z
else if (op->getType() == OPENSCAD_INTERSECTION && rightop->getType() == OPENSCAD_INTERSECTION) {
node = CSGOperation::createCSGNode(OPENSCAD_INTERSECTION,
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, y),
z);
return true;
}
// 5. x - (y - z) -> (x - y) + (x * z)
else if (op->getType() == OPENSCAD_DIFFERENCE && rightop->getType() == OPENSCAD_DIFFERENCE) {
node = CSGOperation::createCSGNode(OPENSCAD_UNION,
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, x, y),
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, z));
return true;
}
// 6. x * (y - z) -> (x * y) - z
else if (op->getType() == OPENSCAD_INTERSECTION && rightop->getType() == OPENSCAD_DIFFERENCE) {
node = CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE,
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, y),
z);
return true;
}
}
shared_ptr<CSGOperation> leftop = dynamic_pointer_cast<CSGOperation>(op->left());
if (leftop) {
// Part B: The '(x . y) . z' expressions
shared_ptr<CSGNode> x = leftop->left();
shared_ptr<CSGNode> y = leftop->right();
shared_ptr<CSGNode> z = op->right();
// 7. (x - y) * z -> (x * z) - y
if (leftop->getType() == OPENSCAD_DIFFERENCE && op->getType() == OPENSCAD_INTERSECTION) {
node = CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE,
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, z),
y);
return true;
}
// 8. (x + y) - z -> (x - z) + (y - z)
else if (leftop->getType() == OPENSCAD_UNION && op->getType() == OPENSCAD_DIFFERENCE) {
node = CSGOperation::createCSGNode(OPENSCAD_UNION,
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, x, z),
CSGOperation::createCSGNode(OPENSCAD_DIFFERENCE, y, z));
return true;
}
// 9. (x + y) * z -> (x * z) + (y * z)
else if (leftop->getType() == OPENSCAD_UNION && op->getType() == OPENSCAD_INTERSECTION) {
node = CSGOperation::createCSGNode(OPENSCAD_UNION,
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, x, z),
CSGOperation::createCSGNode(OPENSCAD_INTERSECTION, y, z));
return true;
}
}
return false;
}
// Counts all non-leaf nodes
unsigned int CSGTreeNormalizer::count(const shared_ptr<CSGNode> &node) const
{
if (shared_ptr<CSGOperation> op = dynamic_pointer_cast<CSGOperation>(node)) {
return 1 + count(op->left()) + count(op->right());
}
return 0;
}

24
src/CSGTreeNormalizer.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include "memory.h"
class CSGTreeNormalizer
{
public:
CSGTreeNormalizer(size_t limit) : limit(limit) {}
~CSGTreeNormalizer() {}
shared_ptr<class CSGNode> normalize(const shared_ptr<CSGNode> &term);
private:
shared_ptr<CSGNode> normalizePass(shared_ptr<CSGNode> term) ;
bool match_and_replace(shared_ptr<class CSGNode> &term);
shared_ptr<CSGNode> collapse_null_terms(const shared_ptr<CSGNode> &term);
shared_ptr<CSGNode> cleanup_term(shared_ptr<CSGNode> &t);
unsigned int count(const shared_ptr<CSGNode> &term) const;
bool aborted;
size_t limit;
size_t nodecount;
shared_ptr<class CSGNode> rootnode;
};

View file

@ -6,15 +6,17 @@ Camera::Camera(enum CameraType camtype) :
type(camtype), projection(Camera::PERSPECTIVE), fov(22.5), viewall(false)
{
PRINTD("Camera()");
if (this->type == Camera::GIMBAL) {
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
} else if (this->type == Camera::VECTOR) {
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
}
// gimbal cam values
object_trans << 0,0,0;
object_rot << 35,0,25;
viewer_distance = 500;
// vector cam values
center << 0,0,0;
Eigen::Vector3d cameradir(1, 1, -0.5);
eye = center - 500 * cameradir;
pixel_width = RenderSettings::inst()->img_width;
pixel_height = RenderSettings::inst()->img_height;
autocenter = false;

View file

@ -1,77 +1,62 @@
#pragma once
#include "OffscreenView.h"
#include "csgterm.h"
#include "csgnode.h"
#include "Tree.h"
#include "GeometryEvaluator.h"
#include "CSGTermEvaluator.h"
#include "csgtermnormalizer.h"
#include "CSGTreeEvaluator.h"
#include "CSGTreeNormalizer.h"
#include "rendersettings.h"
#include "printutils.h"
/*
Small helper class for compiling and normalizing node trees into CSG products
*/
class CsgInfo
{
public:
CsgInfo() : glview(NULL), root_chain(NULL), highlights_chain(NULL), background_chain(NULL), progress_function(NULL)
{
normalizelimit = RenderSettings::inst()->openCSGTermLimit;
}
OffscreenView *glview;
shared_ptr<CSGTerm> root_norm_term; // Normalized CSG products
class CSGChain *root_chain;
std::vector<shared_ptr<CSGTerm> > highlight_terms;
CSGChain *highlights_chain;
std::vector<shared_ptr<CSGTerm> > background_terms;
CSGChain *background_chain;
int normalizelimit;
CsgInfo() {}
shared_ptr<class CSGProducts> root_products;
shared_ptr<CSGProducts> highlights_products;
shared_ptr<CSGProducts> background_products;
void (*progress_function)();
void call_progress_function()
{
if (progress_function) progress_function();
}
bool compile_chains( const Tree &tree )
{
bool compile_products(const Tree &tree) {
const AbstractNode *root_node = tree.root();
GeometryEvaluator geomevaluator(tree);
CSGTermEvaluator evaluator(tree, &geomevaluator);
boost::shared_ptr<CSGTerm> root_raw_term = evaluator.evaluateCSGTerm( *root_node, this->highlight_terms, this->background_terms );
CSGTreeEvaluator evaluator(tree, &geomevaluator);
shared_ptr<CSGNode> csgRoot = evaluator.buildCSGTree(*root_node);
std::vector<shared_ptr<CSGNode> > highlightNodes = evaluator.getHighlightNodes();
std::vector<shared_ptr<CSGNode> > backgroundNodes = evaluator.getBackgroundNodes();
PRINT("Compiling design (CSG Products normalization)...");
call_progress_function();
CSGTermNormalizer normalizer( normalizelimit );
if (root_raw_term) {
this->root_norm_term = normalizer.normalize(root_raw_term);
if (this->root_norm_term) {
this->root_chain = new CSGChain();
this->root_chain->import(this->root_norm_term);
PRINTB("Normalized CSG tree has %d elements", int(this->root_chain->objects.size()));
CSGTreeNormalizer normalizer(RenderSettings::inst()->openCSGTermLimit);
if (csgRoot) {
shared_ptr<CSGNode> normalizedRoot = normalizer.normalize(csgRoot);
if (normalizedRoot) {
this->root_products.reset(new CSGProducts());
this->root_products->import(normalizedRoot);
PRINTB("Normalized CSG tree has %d elements", int(this->root_products->size()));
}
else {
this->root_chain = NULL;
this->root_products.reset();
PRINT("WARNING: CSG normalization resulted in an empty tree");
call_progress_function();
}
}
if (this->highlight_terms.size() > 0) {
PRINTB("Compiling highlights (%i CSG Trees)...", this->highlight_terms.size() );
call_progress_function();
this->highlights_chain = new CSGChain();
for (unsigned int i = 0; i < this->highlight_terms.size(); i++) {
this->highlight_terms[i] = normalizer.normalize(this->highlight_terms[i]);
this->highlights_chain->import(this->highlight_terms[i]);
if (highlightNodes.size() > 0) {
PRINTB("Compiling highlights (%i CSG Trees)...", highlightNodes.size() );
this->highlights_products.reset(new CSGProducts());
for (unsigned int i = 0; i < highlightNodes.size(); i++) {
highlightNodes[i] = normalizer.normalize(highlightNodes[i]);
this->highlights_products->import(highlightNodes[i]);
}
}
if (this->background_terms.size() > 0) {
PRINTB("Compiling background (%i CSG Trees)...", this->background_terms.size());
call_progress_function();
this->background_chain = new CSGChain();
for (unsigned int i = 0; i < this->background_terms.size(); i++) {
this->background_terms[i] = normalizer.normalize(this->background_terms[i]);
this->background_chain->import(this->background_terms[i]);
if (backgroundNodes.size() > 0) {
PRINTB("Compiling background (%i CSG Trees)...", backgroundNodes.size());
this->background_products.reset(new CSGProducts());
for (unsigned int i = 0; i < backgroundNodes.size(); i++) {
backgroundNodes[i] = normalizer.normalize(backgroundNodes[i]);
this->background_products->import(backgroundNodes[i]);
}
}
return true;

View file

@ -31,8 +31,8 @@
#include "Polygon2d.h"
#include "DrawingCallback.h"
DrawingCallback::DrawingCallback(unsigned long fn) : fn(fn),
pen(Vector2d(0, 0)), offset(Vector2d(0, 0)), advance(Vector2d(0, 0))
DrawingCallback::DrawingCallback(unsigned long fn) :
pen(Vector2d(0, 0)), offset(Vector2d(0, 0)), advance(Vector2d(0, 0)), fn(fn)
{
}
@ -74,12 +74,12 @@ void DrawingCallback::add_glyph_advance(double advance_x, double advance_y)
advance += Vector2d(advance_x, advance_y);
}
void DrawingCallback::add_vertex(Vector2d v)
void DrawingCallback::add_vertex(const Vector2d &v)
{
this->outline.vertices.push_back(v + offset + advance);
}
void DrawingCallback::move_to(Vector2d to)
void DrawingCallback::move_to(const Vector2d &to)
{
if (this->outline.vertices.size() > 0) {
this->polygon->addOutline(this->outline);
@ -89,14 +89,14 @@ void DrawingCallback::move_to(Vector2d to)
pen = to;
}
void DrawingCallback::line_to(Vector2d to)
void DrawingCallback::line_to(const Vector2d &to)
{
add_vertex(to);
pen = to;
}
// Quadric Bezier curve
void DrawingCallback::curve_to(Vector2d c1, Vector2d to)
void DrawingCallback::curve_to(const Vector2d &c1, const Vector2d &to)
{
for (unsigned long idx = 1;idx <= fn;idx++) {
const double a = idx * (1.0 / (double)fn);
@ -108,7 +108,7 @@ void DrawingCallback::curve_to(Vector2d c1, Vector2d to)
}
// Cubic Bezier curve
void DrawingCallback::curve_to(Vector2d c1, Vector2d c2, Vector2d to)
void DrawingCallback::curve_to(const Vector2d &c1, const Vector2d &c2, const Vector2d &to)
{
for (unsigned long idx = 1;idx <= fn;idx++) {
const double a = idx * (1.0 / (double)fn);

View file

@ -41,19 +41,19 @@ public:
void add_glyph_advance(double advance_x, double advance_y);
std::vector<const Geometry *> get_result();
void move_to(Vector2d to);
void line_to(Vector2d to);
void curve_to(Vector2d c1, Vector2d to);
void curve_to(Vector2d c1, Vector2d c2, Vector2d to);
void move_to(const Vector2d &to);
void line_to(const Vector2d &to);
void curve_to(const Vector2d &c1, const Vector2d &to);
void curve_to(const Vector2d &c1, const Vector2d &c2, const Vector2d &to);
private:
unsigned long fn;
Vector2d pen;
Vector2d offset;
Vector2d advance;
unsigned long fn;
Outline2d outline;
class Polygon2d *polygon;
std::vector<const class Geometry *> polygons;
void add_vertex(Vector2d v);
void add_vertex(const Vector2d &v);
};

View file

@ -2,7 +2,7 @@
#include <QObject>
#include <QFileOpenEvent>
#include "MainWindow.h"
#include "OpenSCADApp.h"
#include "launchingscreen.h"
class EventFilter : public QObject
@ -24,7 +24,7 @@ protected:
Q_ARG(QString, filename));
}
else {
MainWindow::requestOpenFile(filename);
scadApp->requestOpenFile(filename);
}
return true;
} else {

View file

@ -26,7 +26,6 @@
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

View file

@ -3,9 +3,9 @@
#include "stdio.h"
#include "colormap.h"
#include "rendersettings.h"
#include "mathc99.h"
#include "printutils.h"
#include "renderer.h"
#include <cmath>
#ifdef _WIN32
#include <GL/wglew.h>
@ -105,7 +105,7 @@ void GLView::setupCamera()
double height = dist * tan(cam.fov/2*M_PI/180);
glOrtho(-height*aspectratio, height*aspectratio,
-height, height,
-far_far_away, +far_far_away);
-100*dist, +100*dist);
break;
}
}
@ -130,7 +130,7 @@ void GLView::setupCamera()
double height = dist * tan(cam.fov/2*M_PI/180);
glOrtho(-height*aspectratio, height*aspectratio,
-height, height,
-far_far_away, +far_far_away);
-100*dist, +100*dist);
break;
}
}
@ -163,7 +163,7 @@ void GLView::paintGL()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
setupCamera();
if (this->cam.type) {
if (this->cam.type == Camera::GIMBAL) {
// Only for GIMBAL cam
// The crosshair should be fixed at the center of the viewport...
if (showcrosshairs) GLView::showCrosshairs();
@ -272,7 +272,7 @@ void GLView::enable_opencsg_shaders()
" vec3 normal, lightDir;\n"
" normal = normalize(gl_NormalMatrix * gl_Normal);\n"
" lightDir = normalize(vec3(gl_LightSource[0].position));\n"
" shading = abs(dot(normal, lightDir));\n"
" shading = 0.2 + abs(dot(normal, lightDir));\n"
"}\n";
/*
@ -419,15 +419,15 @@ void GLView::showSmallaxes(const Color4f &col)
GLdouble xlabel_x, xlabel_y, xlabel_z;
gluProject(12*dpi, 0, 0, mat_model, mat_proj, viewport, &xlabel_x, &xlabel_y, &xlabel_z);
xlabel_x = round(xlabel_x); xlabel_y = round(xlabel_y);
xlabel_x = std::round(xlabel_x); xlabel_y = std::round(xlabel_y);
GLdouble ylabel_x, ylabel_y, ylabel_z;
gluProject(0, 12*dpi, 0, mat_model, mat_proj, viewport, &ylabel_x, &ylabel_y, &ylabel_z);
ylabel_x = round(ylabel_x); ylabel_y = round(ylabel_y);
ylabel_x = std::round(ylabel_x); ylabel_y = std::round(ylabel_y);
GLdouble zlabel_x, zlabel_y, zlabel_z;
gluProject(0, 0, 12*dpi, mat_model, mat_proj, viewport, &zlabel_x, &zlabel_y, &zlabel_z);
zlabel_x = round(zlabel_x); zlabel_y = round(zlabel_y);
zlabel_x = std::round(zlabel_x); zlabel_y = std::round(zlabel_y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

View file

@ -20,9 +20,6 @@ Some actions (showCrossHairs) only work properly on Gimbal Camera.
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <string>
#ifndef _MSC_VER
#include <stdint.h>
#endif
#include "system-gl.h"
#include <iostream>
#include "Camera.h"

View file

@ -10,8 +10,8 @@
class Geometry
{
public:
typedef std::pair<const class AbstractNode *, shared_ptr<const Geometry> > ChildItem;
typedef std::list<ChildItem> ChildList;
typedef std::pair<const class AbstractNode *, shared_ptr<const Geometry>> GeometryItem;
typedef std::list<GeometryItem> Geometries;
Geometry() : convexity(1) {}
virtual ~Geometry() {}

View file

@ -13,6 +13,7 @@
#include "csgnode.h"
#include "cgaladvnode.h"
#include "projectionnode.h"
#include "csgops.h"
#include "textnode.h"
#include "CGAL_Nef_polyhedron.h"
#include "cgalutils.h"
@ -27,7 +28,6 @@
#include "dxfdata.h"
#include <algorithm>
#include <boost/foreach.hpp>
#include <CGAL/convex_hull_2.h>
#include <CGAL/Point_2.h>
@ -63,16 +63,15 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
PolySet *ps = new PolySet(3);
ps->setConvexity(N->getConvexity());
this->root.reset(ps);
if (!N->isEmpty()) {
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *ps);
if (err) {
PRINT("ERROR: Nef->PolySet failed");
}
}
smartCacheInsert(node, this->root);
if (!N->isEmpty()) {
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *ps);
if (err) {
PRINT("ERROR: Nef->PolySet failed");
}
}
}
}
smartCacheInsert(node, this->root);
return this->root;
}
return GeometryCache::instance()->get(this->tree.getIdString(node));
@ -81,7 +80,7 @@ shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNod
GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren(const AbstractNode &node, OpenSCADOperator op)
{
unsigned int dim = 0;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
for(const auto &item : this->visitedchildren[node.index()]) {
if (!item.first->modinst->isBackground() && item.second) {
if (!dim) dim = item.second->getDimension();
else if (dim != item.second->getDimension()) {
@ -106,7 +105,7 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren(const Abstrac
*/
GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const AbstractNode &node, OpenSCADOperator op)
{
Geometry::ChildList children = collectChildren3D(node);
Geometry::Geometries children = collectChildren3D(node);
if (children.size() == 0) return ResultObject();
if (op == OPENSCAD_HULL) {
@ -124,8 +123,8 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr
if (children.size() == 1) return ResultObject(children.front().second);
if (op == OPENSCAD_MINKOWSKI) {
Geometry::ChildList actualchildren;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
Geometry::Geometries actualchildren;
for(const auto &item : children) {
if (!item.second->isEmpty()) actualchildren.push_back(item);
}
if (actualchildren.empty()) return ResultObject();
@ -151,12 +150,12 @@ Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
std::vector<const Polygon2d *> children = collectChildren2D(node);
Polygon2d *geometry = new Polygon2d();
typedef CGAL::Point_2<CGAL::Cartesian<double> > CGALPoint2;
typedef CGAL::Point_2<CGAL::Cartesian<double>> CGALPoint2;
// Collect point cloud
std::list<CGALPoint2> points;
BOOST_FOREACH(const Polygon2d *p, children) {
BOOST_FOREACH(const Outline2d &o, p->outlines()) {
BOOST_FOREACH(const Vector2d &v, o.vertices) {
for(const auto &p : children) {
for(const auto &o : p->outlines()) {
for(const auto &v : o.vertices) {
points.push_back(CGALPoint2(v[0], v[1]));
}
}
@ -168,7 +167,7 @@ Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
// Construct Polygon2d
Outline2d outline;
BOOST_FOREACH(const CGALPoint2 &p, result) {
for(const auto &p : result) {
outline.vertices.push_back(Vector2d(p[0], p[1]));
}
geometry->addOutline(outline);
@ -178,7 +177,7 @@ Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
Geometry *GeometryEvaluator::applyHull3D(const AbstractNode &node)
{
Geometry::ChildList children = collectChildren3D(node);
Geometry::Geometries children = collectChildren3D(node);
PolySet *P = new PolySet(3);
if (CGALUtils::applyHull(children, *P)) {
@ -204,10 +203,9 @@ Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
std::vector<const class Polygon2d *> GeometryEvaluator::collectChildren2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
for(const auto &item : this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
// NB! We insert into the cache here to ensure that all children of
@ -275,13 +273,12 @@ shared_ptr<const Geometry> GeometryEvaluator::smartCacheGet(const AbstractNode &
Returns a list of 3D Geometry children of the given node.
May return empty geometries, but not NULL objects
*/
Geometry::ChildList GeometryEvaluator::collectChildren3D(const AbstractNode &node)
Geometry::Geometries GeometryEvaluator::collectChildren3D(const AbstractNode &node)
{
Geometry::ChildList children;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
Geometry::Geometries children;
for(const auto &item : this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members
if (chnode->modinst->isBackground()) continue;
// NB! We insert into the cache here to ensure that all children of
@ -345,7 +342,7 @@ Polygon2d *GeometryEvaluator::applyToChildren2D(const AbstractNode &node, OpenSC
}
/*!
Adds ourself to out parent's list of traversed children.
Adds ourself to our parent's list of traversed children.
Call this for _every_ node which affects output during traversal.
Usually, this should be called from the postfix stage, but for some nodes,
we defer traversal letting other components (e.g. CGAL) render the subgraph,
@ -362,10 +359,9 @@ void GeometryEvaluator::addToParent(const State &state,
this->visitedchildren[state.parent()->index()].push_back(std::make_pair(&node, geom));
}
else {
// Root node, insert into cache
smartCacheInsert(node, geom);
// Root node
this->root = geom;
assert(this->visitedchildren.empty());
assert(this->visitedchildren.empty());
}
}
@ -391,6 +387,19 @@ Response GeometryEvaluator::visit(State &state, const AbstractNode &node)
return ContinueTraversal;
}
/*!
*/
Response GeometryEvaluator::visit(State &state, const GroupNode &node)
{
return visit(state, (const AbstractNode &)node);
}
Response GeometryEvaluator::visit(State &state, const RootNode &node)
{
// Just union the top-level objects
return visit(state, (const GroupNode &)node);
}
Response GeometryEvaluator::visit(State &state, const OffsetNode &node)
{
if (state.isPrefix() && isSmartCached(node)) return PruneTraversal;
@ -493,7 +502,7 @@ Response GeometryEvaluator::visit(State &state, const TextNode &node)
if (!isSmartCached(node)) {
std::vector<const Geometry *> geometrylist = node.createGeometryList();
std::vector<const Polygon2d *> polygonlist;
BOOST_FOREACH(const Geometry *geometry, geometrylist) {
for(const auto &geometry : geometrylist) {
const Polygon2d *polygon = dynamic_cast<const Polygon2d*>(geometry);
assert(polygon);
polygonlist.push_back(polygon);
@ -513,7 +522,7 @@ Response GeometryEvaluator::visit(State &state, const TextNode &node)
operation:
o Perform csg op on children
*/
Response GeometryEvaluator::visit(State &state, const CsgNode &node)
Response GeometryEvaluator::visit(State &state, const CsgOpNode &node)
{
if (state.isPrefix()) {
if (isSmartCached(node)) return PruneTraversal;
@ -609,8 +618,8 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node)
static void translate_PolySet(PolySet &ps, const Vector3d &translation)
{
BOOST_FOREACH(Polygon &p, ps.polygons) {
BOOST_FOREACH(Vector3d &v, p) {
for(auto &p : ps.polygons) {
for(auto &v : p) {
v += translation;
}
}
@ -626,7 +635,7 @@ static void add_slice(PolySet *ps, const Polygon2d &poly,
Eigen::Affine2d trans2(Eigen::Scaling(scale2) * Eigen::Rotation2D<double>(-rot2*M_PI/180));
bool splitfirst = sin((rot1 - rot2)*M_PI/180) > 0.0;
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
for(const auto &o : poly.outlines()) {
Vector2d prev1 = trans1 * o.vertices[0];
Vector2d prev2 = trans2 * o.vertices[0];
for (size_t i=1;i<=o.vertices.size();i++) {
@ -687,7 +696,7 @@ static Geometry *extrudePolygon(const LinearExtrudeNode &node, const Polygon2d &
PolySet *ps_bottom = poly.tessellate(); // bottom
// Flip vertex ordering for bottom polygon
BOOST_FOREACH(Polygon &p, ps_bottom->polygons) {
for(auto &p : ps_bottom->polygons) {
std::reverse(p.begin(), p.end());
}
translate_PolySet(*ps_bottom, Vector3d(0,0,h1));
@ -761,12 +770,21 @@ Response GeometryEvaluator::visit(State &state, const LinearExtrudeNode &node)
return ContinueTraversal;
}
static void fill_ring(std::vector<Vector3d> &ring, const Outline2d &o, double a)
static void fill_ring(std::vector<Vector3d> &ring, const Outline2d &o, double a, bool flip)
{
for (unsigned int i=0;i<o.vertices.size();i++) {
ring[i][0] = o.vertices[i][0] * sin(a);
ring[i][1] = o.vertices[i][0] * cos(a);
ring[i][2] = o.vertices[i][1];
if (flip) {
unsigned int l = o.vertices.size()-1;
for (unsigned int i=0 ;i<o.vertices.size();i++) {
ring[i][0] = o.vertices[l-i][0] * sin(a);
ring[i][1] = o.vertices[l-i][0] * cos(a);
ring[i][2] = o.vertices[l-i][1];
}
} else {
for (unsigned int i=0 ;i<o.vertices.size();i++) {
ring[i][0] = o.vertices[i][0] * sin(a);
ring[i][1] = o.vertices[i][0] * cos(a);
ring[i][2] = o.vertices[i][1];
}
}
}
@ -790,13 +808,16 @@ static void fill_ring(std::vector<Vector3d> &ring, const Outline2d &o, double a)
*/
static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &poly)
{
if (node.angle == 0) return NULL;
PolySet *ps = new PolySet(3);
ps->setConvexity(node.convexity);
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
double min_x = 0;
double max_x = 0;
BOOST_FOREACH(const Vector2d &v, o.vertices) {
double min_x = 0;
double max_x = 0;
int fragments = 0;
for(const auto &o : poly.outlines()) {
for(const auto &v : o.vertices) {
min_x = fmin(min_x, v[0]);
max_x = fmax(max_x, v[0]);
@ -806,16 +827,49 @@ static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &p
return NULL;
}
}
int fragments = Calc::get_fragments_from_r(max_x - min_x, node.fn, node.fs, node.fa);
fragments = fmax(Calc::get_fragments_from_r(max_x - min_x, node.fn, node.fs, node.fa) * std::abs(node.angle) / 360, 1);
}
bool flip_faces = (min_x >= 0 && node.angle > 0 && node.angle != 360) || (min_x < 0 && (node.angle < 0 || node.angle == 360));
if (node.angle != 360) {
PolySet *ps_start = poly.tessellate(); // starting face
Transform3d rot(Eigen::AngleAxisd(M_PI/2, Vector3d::UnitX()));
ps_start->transform(rot);
// Flip vertex ordering
if (!flip_faces) {
for(auto &p : ps_start->polygons) {
std::reverse(p.begin(), p.end());
}
}
ps->append(*ps_start);
delete ps_start;
PolySet *ps_end = poly.tessellate();
Transform3d rot2(Eigen::AngleAxisd(node.angle*M_PI/180, Vector3d::UnitZ()) * Eigen::AngleAxisd(M_PI/2, Vector3d::UnitX()));
ps_end->transform(rot2);
if (flip_faces) {
for(auto &p : ps_end->polygons) {
std::reverse(p.begin(), p.end());
}
}
ps->append(*ps_end);
delete ps_end;
}
for(const auto &o : poly.outlines()) {
std::vector<Vector3d> rings[2];
rings[0].resize(o.vertices.size());
rings[1].resize(o.vertices.size());
fill_ring(rings[0], o, -M_PI/2); // first ring
fill_ring(rings[0], o, (node.angle == 360) ? -M_PI/2 : M_PI/2, flip_faces); // first ring
for (int j = 0; j < fragments; j++) {
double a = ((j+1)%fragments*2*M_PI) / fragments - M_PI/2; // start on the X axis
fill_ring(rings[(j+1)%2], o, a);
double a;
if (node.angle == 360)
a = -M_PI/2 + ((j+1)%fragments*2*M_PI) / fragments; // start on the -X axis, for legacy support
else
a = M_PI/2 - (j+1)*(node.angle*M_PI/180) / fragments; // start on the X axis
fill_ring(rings[(j+1)%2], o, a, flip_faces);
for (size_t i=0;i<o.vertices.size();i++) {
ps->append_poly();
@ -829,6 +883,7 @@ static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &p
}
}
}
return ps;
}
@ -871,7 +926,7 @@ Response GeometryEvaluator::visit(State &state, const RotateExtrudeNode &node)
}
/*!
Handles non-leaf PolyNodes; projection
FIXME: Not in use
*/
Response GeometryEvaluator::visit(State &state, const AbstractPolyNode &node)
{
@ -895,7 +950,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (!node.cut_mode) {
ClipperLib::Clipper sumclipper;
BOOST_FOREACH(const Geometry::ChildItem &item, this->visitedchildren[node.index()]) {
for(const auto &item : this->visitedchildren[node.index()]) {
const AbstractNode *chnode = item.first;
const shared_ptr<const Geometry> &chgeom = item.second;
// FIXME: Don't use deep access to modinst members

View file

@ -23,9 +23,11 @@ public:
virtual Response visit(State &state, const AbstractPolyNode &node);
virtual Response visit(State &state, const LinearExtrudeNode &node);
virtual Response visit(State &state, const RotateExtrudeNode &node);
virtual Response visit(State &state, const GroupNode &node);
virtual Response visit(State &state, const RootNode &node);
virtual Response visit(State &state, const LeafNode &node);
virtual Response visit(State &state, const TransformNode &node);
virtual Response visit(State &state, const CsgNode &node);
virtual Response visit(State &state, const CsgOpNode &node);
virtual Response visit(State &state, const CgaladvNode &node);
virtual Response visit(State &state, const ProjectionNode &node);
virtual Response visit(State &state, const RenderNode &node);
@ -57,7 +59,7 @@ private:
shared_ptr<const Geometry> smartCacheGet(const AbstractNode &node, bool preferNef);
bool isSmartCached(const AbstractNode &node);
std::vector<const class Polygon2d *> collectChildren2D(const AbstractNode &node);
Geometry::ChildList collectChildren3D(const AbstractNode &node);
Geometry::Geometries collectChildren3D(const AbstractNode &node);
Polygon2d *applyMinkowski2D(const AbstractNode &node);
Polygon2d *applyHull2D(const AbstractNode &node);
Geometry *applyHull3D(const AbstractNode &node);
@ -67,7 +69,7 @@ private:
ResultObject applyToChildren(const AbstractNode &node, OpenSCADOperator op);
void addToParent(const State &state, const AbstractNode &node, const shared_ptr<const Geometry> &geom);
std::map<int, Geometry::ChildList> visitedchildren;
std::map<int, Geometry::Geometries> visitedchildren;
const Tree &tree;
shared_ptr<const Geometry> root;

View file

@ -2,11 +2,11 @@
#include "tesselator.h"
#include "printutils.h"
#include "Reindexer.h"
#include "grid.h"
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/unordered_map.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <unordered_map>
#include <cmath>
#include <boost/functional/hash.hpp>
static void *stdAlloc(void* userData, unsigned int size) {
TESS_NOTUSED(userData);
@ -27,7 +27,7 @@ typedef std::pair<int,int> IndexedEdge;
class EdgeDict {
public:
// Counts occurrences of edges
typedef boost::unordered_map<IndexedEdge, int> IndexedEdgeDict;
typedef std::unordered_map<IndexedEdge, int, boost::hash<IndexedEdge>> IndexedEdgeDict;
EdgeDict() { }
@ -91,7 +91,7 @@ public:
size_t size() const { return this->edges.size(); }
void print() const {
BOOST_FOREACH(const IndexedEdgeDict::value_type &v, this->edges) {
for(const auto &v : this->edges) {
const IndexedEdge &e = v.first;
PRINTDB(" (%d,%d)%s", e.first % e.second % ((v.second > 1) ? boost::lexical_cast<std::string>(v.second).c_str() : ""));
}
@ -139,7 +139,7 @@ public:
// First, look for self-intersections in edges
v2e.clear();
v2e_reverse.clear();
BOOST_FOREACH(const IndexedEdgeDict::value_type &v, this->edges) {
for(const auto &v : this->edges) {
const IndexedEdge &e = v.first;
for (int i=0;i<v.second;i++) {
v2e[e.first].push_back(e.second);
@ -148,7 +148,7 @@ public:
}
while (!v2e.empty()) {
boost::unordered_map<int, std::list<int> >::iterator it;
std::unordered_map<int, std::list<int>>::iterator it;
for (it = v2e.begin();it != v2e.end();it++) {
if (it->second.size() == 1) { // First single vertex
int vidx = it->first;
@ -167,8 +167,8 @@ public:
}
IndexedEdgeDict edges;
boost::unordered_map<int, std::list<int> > v2e;
boost::unordered_map<int, std::list<int> > v2e_reverse;
std::unordered_map<int, std::list<int>> v2e;
std::unordered_map<int, std::list<int>> v2e_reverse;
};
@ -207,7 +207,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const Vector3f *vertices,
// Remove consecutive equal vertices, as well as null ears
std::vector<IndexedFace> cleanfaces = faces;
BOOST_FOREACH(IndexedFace &face, cleanfaces) {
for(auto &face : cleanfaces) {
size_t i=0;
while (face.size() >= 3 && i < face.size()) {
if (face[i] == face[(i+1)%face.size()]) { // Two consecutively equal indices
@ -223,7 +223,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const Vector3f *vertices,
const Vector3f &v = vertices[face[i]];
int k;
for (k=0;k<3;k++) {
if (boost::math::isnan(v[k]) || boost::math::isinf(v[k])) {
if (std::isnan(v[k]) || std::isinf(v[k])) {
face.erase(face.begin()+i);
break;
}
@ -253,7 +253,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const Vector3f *vertices,
// This contains all edges in the original polygon.
// To maintain connectivity, all these edges must exist in the output.
EdgeDict edges;
BOOST_FOREACH(IndexedFace &face, cleanfaces) {
for(const auto &face : cleanfaces) {
edges.add(face);
}
@ -281,9 +281,9 @@ bool GeometryUtils::tessellatePolygonWithHoles(const Vector3f *vertices,
// Since libtess2's indices is based on the running number of points added, we need to map back
// to our indices. allindices does the mapping.
std::vector<int> allindices;
BOOST_FOREACH(const IndexedFace &face, cleanfaces) {
for(const auto &face : cleanfaces) {
contour.clear();
BOOST_FOREACH(int idx, face) {
for(auto idx : face) {
const Vector3f &v = vertices[idx];
contour.push_back(v[0]);
contour.push_back(v[1]);
@ -428,7 +428,7 @@ bool GeometryUtils::tessellatePolygon(const Polygon &polygon, Polygons &triangle
std::vector<IndexedFace> indexedfaces;
indexedfaces.push_back(IndexedFace());
IndexedFace &currface = indexedfaces.back();
BOOST_FOREACH (const Vector3d &v, polygon) {
for(const auto &v : polygon) {
int idx = uniqueVertices.lookup(v.cast<float>());
if (currface.empty() || idx != currface.back()) currface.push_back(idx);
}
@ -437,7 +437,7 @@ bool GeometryUtils::tessellatePolygon(const Polygon &polygon, Polygons &triangle
const Vector3f *verts = uniqueVertices.getArray();
std::vector<IndexedTriangle> indexedtriangles;
err = tessellatePolygonWithHoles(verts, indexedfaces, indexedtriangles, normal);
BOOST_FOREACH(const IndexedTriangle &t, indexedtriangles) {
for(const auto &t : indexedtriangles) {
triangles.push_back(Polygon());
Polygon &p = triangles.back();
p.push_back(verts[t[0]].cast<double>());
@ -448,11 +448,11 @@ bool GeometryUtils::tessellatePolygon(const Polygon &polygon, Polygons &triangle
return err;
}
int GeometryUtils::findUnconnectedEdges(const std::vector<std::vector<IndexedFace> > &polygons)
int GeometryUtils::findUnconnectedEdges(const std::vector<std::vector<IndexedFace>> &polygons)
{
EdgeDict edges;
BOOST_FOREACH(const std::vector<IndexedFace> &faces, polygons) {
BOOST_FOREACH(const IndexedFace &face, faces) {
for(const auto &faces : polygons) {
for(const auto &face : faces) {
edges.add(face);
}
}
@ -468,7 +468,7 @@ int GeometryUtils::findUnconnectedEdges(const std::vector<std::vector<IndexedFac
int GeometryUtils::findUnconnectedEdges(const std::vector<IndexedTriangle> &triangles)
{
EdgeDict edges;
BOOST_FOREACH(const IndexedTriangle &t, triangles) {
for(const auto &t : triangles) {
edges.add(t);
}
#if 1 // for debugging

View file

@ -22,7 +22,7 @@ struct IndexedTriangleMesh {
// Indexed polygon mesh, where each polygon can have holes
struct IndexedPolyMesh {
std::vector<Vector3f> vertices;
std::vector<std::vector<IndexedFace> > polygons;
std::vector<std::vector<IndexedFace>> polygons;
};
namespace GeometryUtils {
@ -34,6 +34,6 @@ namespace GeometryUtils {
std::vector<IndexedTriangle> &triangles,
const Vector3f *normal = NULL);
int findUnconnectedEdges(const std::vector<std::vector<IndexedFace> > &polygons);
int findUnconnectedEdges(const std::vector<std::vector<IndexedFace>> &polygons);
int findUnconnectedEdges(const std::vector<IndexedTriangle> &triangles);
}

View file

@ -11,32 +11,27 @@
#include "Tree.h"
#include "memory.h"
#include "editor.h"
#include "export.h"
#include <vector>
#include <QMutex>
#include <QSet>
#include <QTime>
#include <QIODevice>
enum export_type_e {
EXPORT_TYPE_UNKNOWN,
EXPORT_TYPE_STL,
EXPORT_TYPE_AMF,
EXPORT_TYPE_OFF
};
class MainWindow : public QMainWindow, public Ui::MainWindow
{
Q_OBJECT
public:
static void requestOpenFile(const QString &filename);
QString fileName;
class Preferences *prefs;
QTimer *animate_timer;
double tval, fps, fsteps;
int anim_step;
int anim_numsteps;
double anim_tval;
bool anim_dumping;
int anim_dump_start_step;
QTimer *autoReloadTimer;
std::string autoReloadId;
@ -51,9 +46,6 @@ public:
AbstractNode *root_node; // Root if the root modifier (!) is used
Tree tree;
shared_ptr<class CSGTerm> root_raw_term; // Result of CSG term rendering
shared_ptr<CSGTerm> root_norm_term; // Normalized CSG products
class CSGChain *root_chain;
#ifdef ENABLE_CGAL
shared_ptr<const class Geometry> root_geom;
class CGALRenderer *cgalRenderer;
@ -63,10 +55,6 @@ public:
#endif
class ThrownTogetherRenderer *thrownTogetherRenderer;
std::vector<shared_ptr<CSGTerm> > highlight_terms;
CSGChain *highlights_chain;
std::vector<shared_ptr<CSGTerm> > background_terms;
CSGChain *background_chain;
QString last_compiled_doc;
QAction *actionRecentFile[UIUtils::maxRecentFiles];
@ -91,7 +79,10 @@ protected:
void closeEvent(QCloseEvent *event);
private slots:
void updatedFps();
void updatedAnimTval();
void updatedAnimFps();
void updatedAnimSteps();
void updatedAnimDump(bool checked);
void updateTVal();
void updateMdiMode(bool mdi);
void updateUndockMode(bool undockMode);
@ -105,7 +96,6 @@ private slots:
private:
void initActionIcon(QAction *action, const char *darkResource, const char *lightResource);
void openFile(const QString &filename);
void handleFileDrop(const QString &filename);
void refreshDocument();
void updateCamera();
@ -194,7 +184,7 @@ private slots:
void actionDisplayAST();
void actionDisplayCSGTree();
void actionDisplayCSGProducts();
void actionExport(export_type_e, const char *, const char *);
void actionExport(FileFormat format, const char *type_name, const char *suffix, unsigned int dim);
void actionExportSTL();
void actionExportOFF();
void actionExportAMF();
@ -206,12 +196,13 @@ private slots:
void actionFlushCaches();
public:
static QSet<MainWindow*> *getWindows();
void viewModeActionsUncheck();
void setCurrentOutput();
void clearCurrentOutput();
bool isEmpty();
public slots:
void openFile(const QString &filename);
void actionReloadRenderPreview();
void on_editorDock_visibilityChanged(bool);
void on_consoleDock_visibilityChanged(bool);
@ -262,16 +253,18 @@ public slots:
void waitAfterReload();
void autoReloadSet(bool);
void setContentsChanged();
void showFontCacheDialog();
void hideFontCacheDialog();
private:
static void report_func(const class AbstractNode*, void *vp, int mark);
static bool mdiMode;
static bool undockMode;
static bool reorderMode;
static QSet<MainWindow*> *windows;
static class QProgressDialog *fontCacheDialog;
shared_ptr<class CSGNode> csgRoot; // Result of the CSGTreeEvaluator
shared_ptr<CSGNode> normalizedRoot; // Normalized CSG tree
shared_ptr<class CSGProducts> root_products;
shared_ptr<CSGProducts> highlights_products;
shared_ptr<CSGProducts> background_products;
char const * afterCompileSlot;
bool procevents;

View file

@ -522,6 +522,7 @@
</item>
</layout>
</widget>
<addaction name="editActionRedo_2"/>
</widget>
<widget class="Dock" name="consoleDock">
<attribute name="dockWidgetArea">
@ -680,6 +681,14 @@
<enum>Qt::WidgetWithChildrenShortcut</enum>
</property>
</action>
<action name="editActionRedo_2">
<property name="shortcut">
<string>Ctrl+Y</string>
</property>
<property name="shortcutContext">
<enum>Qt::WidgetWithChildrenShortcut</enum>
</property>
</action>
<action name="editActionCut">
<property name="text">
<string>Cu&amp;t</string>
@ -1270,6 +1279,9 @@
<property name="text">
<string>View All</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+V</string>
</property>
</action>
<action name="editActionConvertTabsToSpaces">
<property name="text">

View file

@ -6,7 +6,6 @@
#include "boosty.h"
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <stdio.h>
#include <fstream>

View file

@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <boost/unordered_map.hpp>
#include <unordered_map>
/*!
Caches FileModules based on their filenames
@ -26,5 +26,5 @@ private:
class FileModule *module;
std::string cache_id;
};
boost::unordered_map<std::string, cache_entry> entries;
std::unordered_map<std::string, cache_entry> entries;
};

View file

@ -486,6 +486,7 @@ namespace OGL {
gluTessEndPolygon(tess_);
// CGAL_NEF_TRACEN("End Polygon");
gluDeleteTess(tess_);
combineCallback(NULL, NULL, NULL, NULL);
}
void construct_axes() const

View file

@ -7,7 +7,7 @@
#include <sstream>
#include "printutils.h"
OffscreenView::OffscreenView(size_t width, size_t height)
OffscreenView::OffscreenView(int width, int height)
{
this->ctx = create_offscreen_context(width, height);
if ( this->ctx == NULL ) throw -1;

View file

@ -4,9 +4,6 @@
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <string>
#ifndef _MSC_VER
#include <stdint.h>
#endif
#include "system-gl.h"
#include <iostream>
#include "GLView.h"
@ -14,7 +11,7 @@
class OffscreenView : public GLView
{
public:
OffscreenView(size_t width, size_t height);
OffscreenView(int width, int height);
~OffscreenView();
bool save(std::ostream &output);
OffscreenContext *ctx;

View file

@ -27,11 +27,11 @@
#include "system-gl.h"
#include "OpenCSGRenderer.h"
#include "polyset.h"
#include "csgterm.h"
#include "csgnode.h"
#include "stl-utils.h"
#ifdef ENABLE_OPENCSG
# include <opencsg.h>
#endif
class OpenCSGPrim : public OpenCSG::Primitive
{
@ -49,10 +49,15 @@ public:
}
};
OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain,
CSGChain *background_chain, GLint *shaderinfo)
: root_chain(root_chain), highlights_chain(highlights_chain),
background_chain(background_chain), shaderinfo(shaderinfo)
#endif
OpenCSGRenderer::OpenCSGRenderer(shared_ptr<CSGProducts> root_products,
shared_ptr<CSGProducts> highlights_products,
shared_ptr<CSGProducts> background_products,
GLint *shaderinfo)
: root_products(root_products),
highlights_products(highlights_products),
background_products(background_products), shaderinfo(shaderinfo)
{
}
@ -60,104 +65,109 @@ void OpenCSGRenderer::draw(bool /*showfaces*/, bool showedges) const
{
GLint *shaderinfo = this->shaderinfo;
if (!shaderinfo[0]) shaderinfo = NULL;
if (this->root_chain) {
renderCSGChain(this->root_chain, showedges ? shaderinfo : NULL, false, false);
if (this->root_products) {
renderCSGProducts(*this->root_products, showedges ? shaderinfo : NULL, false, false);
}
if (this->background_chain) {
renderCSGChain(this->background_chain, showedges ? shaderinfo : NULL, false, true);
if (this->background_products) {
renderCSGProducts(*this->background_products, showedges ? shaderinfo : NULL, false, true);
}
if (this->highlights_chain) {
renderCSGChain(this->highlights_chain, showedges ? shaderinfo : NULL, true, false);
if (this->highlights_products) {
renderCSGProducts(*this->highlights_products, showedges ? shaderinfo : NULL, true, false);
}
}
void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
bool highlight, bool background) const
// Primitive for rendering using OpenCSG
OpenCSGPrim *OpenCSGRenderer::createCSGPrimitive(const CSGChainObject &csgobj, OpenCSG::Operation operation, bool highlight_mode, bool background_mode, OpenSCADOperator type) const
{
std::vector<OpenCSG::Primitive*> primitives;
size_t j = 0;
for (size_t i = 0;; i++) {
bool last = i == chain->objects.size();
const CSGChainObject &i_obj = last ? chain->objects[i-1] : chain->objects[i];
if (last || i_obj.type == CSGTerm::TYPE_UNION) {
if (j+1 != i) {
OpenCSG::render(primitives);
glDepthFunc(GL_EQUAL);
}
if (shaderinfo) glUseProgram(shaderinfo[0]);
for (; j < i; j++) {
const CSGChainObject &j_obj = chain->objects[j];
const Color4f &c = j_obj.color;
glPushMatrix();
glMultMatrixd(j_obj.matrix.data());
OpenCSGPrim *prim = new OpenCSGPrim(operation, csgobj.leaf->geom->getConvexity());
prim->geom = csgobj.leaf->geom;
prim->m = csgobj.leaf->matrix;
prim->csgmode = csgmode_e(
(highlight_mode ?
CSGMODE_HIGHLIGHT :
(background_mode ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
(type == OPENSCAD_DIFFERENCE ? CSGMODE_DIFFERENCE : CSGMODE_NONE));
return prim;
}
void OpenCSGRenderer::renderCSGProducts(const CSGProducts &products, GLint *shaderinfo,
bool highlight_mode, bool background_mode) const
{
#ifdef ENABLE_OPENCSG
for(const auto &product : products.products) {
std::vector<OpenCSG::Primitive*> primitives;
for(const auto &csgobj : product.intersections) {
if (csgobj.leaf->geom) primitives.push_back(createCSGPrimitive(csgobj, OpenCSG::Intersection, highlight_mode, background_mode, OPENSCAD_INTERSECTION));
}
for(const auto &csgobj : product.subtractions) {
if (csgobj.leaf->geom) primitives.push_back(createCSGPrimitive(csgobj, OpenCSG::Subtraction, highlight_mode, background_mode, OPENSCAD_DIFFERENCE));
}
if (primitives.size() > 1) {
OpenCSG::render(primitives);
glDepthFunc(GL_EQUAL);
}
if (shaderinfo) glUseProgram(shaderinfo[0]);
const CSGChainObject &parent_obj = product.intersections[0];
for(const auto &csgobj : product.intersections) {
const Color4f &c = csgobj.leaf->color;
csgmode_e csgmode = csgmode_e(
(highlight ?
CSGMODE_HIGHLIGHT :
(background ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
(j_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : 0));
ColorMode colormode = COLORMODE_NONE;
if (background) {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
}
else {
colormode = COLORMODE_BACKGROUND;
}
} else if (j_obj.type == CSGTerm::TYPE_DIFFERENCE) {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
}
else {
colormode = COLORMODE_CUTOUT;
}
} else {
if (j_obj.flag & CSGTerm::FLAG_HIGHLIGHT) {
colormode = COLORMODE_HIGHLIGHT;
}
else {
colormode = COLORMODE_MATERIAL;
}
}
setColor(colormode, c.data(), shaderinfo);
render_surface(j_obj.geom, csgmode, j_obj.matrix, shaderinfo);
glPopMatrix();
}
if (shaderinfo) glUseProgram(0);
for (unsigned int k = 0; k < primitives.size(); k++) {
delete primitives[k];
}
glDepthFunc(GL_LEQUAL);
primitives.clear();
}
if (last) break;
if (i_obj.geom) {
OpenCSGPrim *prim = new OpenCSGPrim(i_obj.type == CSGTerm::TYPE_DIFFERENCE ?
OpenCSG::Subtraction : OpenCSG::Intersection, i_obj.geom->getConvexity());
highlight_mode ?
CSGMODE_HIGHLIGHT :
(background_mode ? CSGMODE_BACKGROUND : CSGMODE_NORMAL));
prim->geom = i_obj.geom;
prim->m = i_obj.matrix;
prim->csgmode = csgmode_e(
(highlight ?
CSGMODE_HIGHLIGHT :
(background ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) |
(i_obj.type == CSGTerm::TYPE_DIFFERENCE ? CSGMODE_DIFFERENCE : 0));
primitives.push_back(prim);
ColorMode colormode = COLORMODE_NONE;
if (highlight_mode) {
colormode = COLORMODE_HIGHLIGHT;
} else if (background_mode) {
colormode = COLORMODE_BACKGROUND;
} else {
colormode = COLORMODE_MATERIAL;
}
setColor(colormode, c.data(), shaderinfo);
glPushMatrix();
glMultMatrixd(csgobj.leaf->matrix.data());
render_surface(csgobj.leaf->geom, csgmode, csgobj.leaf->matrix, shaderinfo);
glPopMatrix();
}
for(const auto &csgobj : product.subtractions) {
const Color4f &c = csgobj.leaf->color;
csgmode_e csgmode = csgmode_e(
(highlight_mode ?
CSGMODE_HIGHLIGHT :
(background_mode ? CSGMODE_BACKGROUND : CSGMODE_NORMAL)) | CSGMODE_DIFFERENCE);
ColorMode colormode = COLORMODE_NONE;
if (highlight_mode) {
colormode = COLORMODE_HIGHLIGHT;
} else if (background_mode) {
colormode = COLORMODE_BACKGROUND;
} else {
colormode = COLORMODE_CUTOUT;
}
setColor(colormode, c.data(), shaderinfo);
glPushMatrix();
glMultMatrixd(csgobj.leaf->matrix.data());
render_surface(csgobj.leaf->geom, csgmode, csgobj.leaf->matrix, shaderinfo);
glPopMatrix();
}
if (shaderinfo) glUseProgram(0);
for(auto &p : primitives) delete p;
glDepthFunc(GL_LEQUAL);
}
std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>());
#endif
}
BoundingBox OpenCSGRenderer::getBoundingBox() const
{
BoundingBox bbox;
if (this->root_chain) bbox = this->root_chain->getBoundingBox();
if (this->background_chain) bbox.extend(this->background_chain->getBoundingBox());
if (this->root_products) bbox = this->root_products->getBoundingBox();
if (this->highlights_products) bbox.extend(this->highlights_products->getBoundingBox());
if (this->background_products) bbox.extend(this->background_products->getBoundingBox());
return bbox;
}

View file

@ -2,20 +2,29 @@
#include "renderer.h"
#include "system-gl.h"
#ifdef ENABLE_OPENCSG
#include <opencsg.h>
#endif
#include "csgnode.h"
class OpenCSGRenderer : public Renderer
{
public:
OpenCSGRenderer(class CSGChain *root_chain, CSGChain *highlights_chain,
CSGChain *background_chain, GLint *shaderinfo);
OpenCSGRenderer(shared_ptr<class CSGProducts> root_products,
shared_ptr<CSGProducts> highlights_products,
shared_ptr<CSGProducts> background_products,
GLint *shaderinfo);
virtual void draw(bool showfaces, bool showedges) const;
virtual BoundingBox getBoundingBox() const;
private:
void renderCSGChain(class CSGChain *chain, GLint *shaderinfo,
bool highlight, bool background) const;
#ifdef ENABLE_OPENCSG
class OpenCSGPrim *createCSGPrimitive(const class CSGChainObject &csgobj, OpenCSG::Operation operation, bool highlight_mode, bool background_mode, OpenSCADOperator type) const;
#endif
void renderCSGProducts(const class CSGProducts &products, GLint *shaderinfo,
bool highlight_mode, bool background_mode) const;
CSGChain *root_chain;
CSGChain *highlights_chain;
CSGChain *background_chain;
shared_ptr<CSGProducts> root_products;
shared_ptr<CSGProducts> highlights_products;
shared_ptr<CSGProducts> background_products;
GLint *shaderinfo;
};

74
src/OpenSCADApp.cc Normal file
View file

@ -0,0 +1,74 @@
#include "OpenSCADApp.h"
#include "MainWindow.h"
#ifdef Q_OS_MAC
#include "EventFilter.h"
#endif
#include <QProgressDialog>
#include <iostream>
#include <boost/foreach.hpp>
OpenSCADApp::OpenSCADApp(int &argc ,char **argv)
: QApplication(argc, argv), fontCacheDialog(NULL)
{
#ifdef Q_OS_MAC
this->installEventFilter(new EventFilter(this));
#endif
}
OpenSCADApp::~OpenSCADApp()
{
delete this->fontCacheDialog;
}
#include <QMessageBox>
bool OpenSCADApp::notify(QObject *object, QEvent *event)
{
QString msg;
try {
return QApplication::notify(object, event);
}
catch (const std::exception &e) {
msg = e.what();
}
catch (...) {
msg = _("Unknown error");
}
// This happens when an uncaught exception is thrown in a Qt event handler
QMessageBox::critical(NULL, QString(_("Critical Error")), QString(_("A critical error was caught. The application may have become unstable:\n%1")).arg(QString(msg)));
return false;
}
/*!
Requests to open a file from an external event, e.g. by double-clicking a filename.
*/
void OpenSCADApp::requestOpenFile(const QString &filename)
{
BOOST_FOREACH(MainWindow *win, this->windowManager.getWindows()) {
// if we have an empty open window, use that one
if (win->isEmpty()) {
win->openFile(filename);
return;
}
}
// ..otherwise, create a new one
new MainWindow(filename);
}
void OpenSCADApp::showFontCacheDialog()
{
if (!this->fontCacheDialog) this->fontCacheDialog = new QProgressDialog();
this->fontCacheDialog->setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes."));
this->fontCacheDialog->setMinimum(0);
this->fontCacheDialog->setMaximum(0);
this->fontCacheDialog->setCancelButton(0);
this->fontCacheDialog->exec();
}
void OpenSCADApp::hideFontCacheDialog()
{
assert(this->fontCacheDialog);
this->fontCacheDialog->reset();
}

28
src/OpenSCADApp.h Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include <QApplication>
#include "WindowManager.h"
class OpenSCADApp : public QApplication
{
Q_OBJECT
public:
OpenSCADApp(int &argc ,char **argv);
~OpenSCADApp();
bool notify(QObject *object, QEvent *event);
void requestOpenFile(const QString &filename);
public slots:
void showFontCacheDialog();
void hideFontCacheDialog();
public:
WindowManager windowManager;
private:
class QProgressDialog *fontCacheDialog;
};
#define scadApp (static_cast<OpenSCADApp *>(QCoreApplication::instance()))

View file

@ -123,7 +123,7 @@ bool ParameterEntryWidget::isDefaultValue()
void ParameterEntryWidget::applyParameter(Assignment *assignment)
{
assignment->second = boost::shared_ptr<Expression>(new ExpressionConst(value));
assignment->second = shared_ptr<Expression>(new ExpressionConst(value));
}
void ParameterEntryWidget::setAssignment(Context *ctx, const Assignment *assignment, const ValuePtr defaultValue)
@ -185,8 +185,8 @@ void ParameterEntryWidget::setValue(const ValuePtr defaultValue, const ValuePtr
comboBox->clear();
const Value::VectorType& vec = values->toVector();
for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) {
const Value *v = &(*it);
comboBox->addItem(QString::fromStdString((*it).toString()), qVariantFromValue((void *)v));
const ValuePtr *v = &(*it);
comboBox->addItem(QString::fromStdString((*it)->toString()), qVariantFromValue((void *)v));
}
QString defaultText = QString::fromStdString(value->toString());
int idx = comboBox->findText(defaultText);
@ -234,17 +234,17 @@ void ParameterEntryWidget::setValue(const ValuePtr defaultValue, const ValuePtr
this->doubleSpinBox2->hide();
this->doubleSpinBox2->setReadOnly(true);
}
this->doubleSpinBox1->setValue(vec.at(0).toDouble());
this->doubleSpinBox1->setValue(vec.at(0)->toDouble());
if (vec.size() > 1) {
this->doubleSpinBox2->setValue(vec.at(1).toDouble());
this->doubleSpinBox2->setValue(vec.at(1)->toDouble());
this->doubleSpinBox2->setReadOnly(false);
}
if (vec.size() > 2) {
this->doubleSpinBox3->setValue(vec.at(2).toDouble());
this->doubleSpinBox3->setValue(vec.at(2)->toDouble());
this->doubleSpinBox3->setReadOnly(false);
}
if (vec.size() > 3) {
this->doubleSpinBox4->setValue(vec.at(3).toDouble());
this->doubleSpinBox4->setValue(vec.at(3)->toDouble());
this->doubleSpinBox4->setReadOnly(false);
}
}

View file

@ -8,8 +8,6 @@
#include <CGAL/Polygon_2.h>
#include <iostream>
#include <boost/foreach.hpp>
namespace Polygon2DCGAL {
struct FaceInfo
@ -111,10 +109,10 @@ PolySet *Polygon2d::tessellate() const
Polygon2DCGAL::CDT cdt; // Uses a constrained Delaunay triangulator.
OPENSCAD_CGAL_ERROR_BEGIN;
// Adds all vertices, and add all contours as constraints.
BOOST_FOREACH(const Outline2d &outline, this->outlines()) {
for(const auto &outline : this->outlines()) {
// Start with last point
Polygon2DCGAL::CDT::Vertex_handle prev = cdt.insert(Polygon2DCGAL::Point(outline.vertices[outline.vertices.size()-1][0], outline.vertices[outline.vertices.size()-1][1]));
BOOST_FOREACH(const Vector2d &v, outline.vertices) {
for(const auto &v : outline.vertices) {
Polygon2DCGAL::CDT::Vertex_handle curr = cdt.insert(Polygon2DCGAL::Point(v[0], v[1]));
if (prev != curr) { // Ignore duplicate vertices
cdt.insert_constraint(prev, curr);

View file

@ -1,14 +1,13 @@
#include "Polygon2d.h"
#include "printutils.h"
#include <boost/foreach.hpp>
/*!
Class for holding 2D geometry.
This class will hold 2D geometry consisting of a number of closed
contours. A polygon can contain holes and islands, as well as
intersecting contours.
polygons. Each polygon can contain holes and islands. Both polygons,
holes and island contours may intersect each other.
We can store sanitized vs. unsanitized polygons. Sanitized polygons
will have opposite winding order for holes and is guaranteed to not
have intersecting geometry. The winding order will be counter-clockwise
@ -20,7 +19,7 @@
size_t Polygon2d::memsize() const
{
size_t mem = 0;
BOOST_FOREACH(const Outline2d &o, this->outlines()) {
for(const auto &o : this->outlines()) {
mem += o.vertices.size() * sizeof(Vector2d) + sizeof(Outline2d);
}
mem += sizeof(Polygon2d);
@ -30,8 +29,8 @@ size_t Polygon2d::memsize() const
BoundingBox Polygon2d::getBoundingBox() const
{
BoundingBox bbox;
BOOST_FOREACH(const Outline2d &o, this->outlines()) {
BOOST_FOREACH(const Vector2d &v, o.vertices) {
for(const auto &o : this->outlines()) {
for(const auto &v : o.vertices) {
bbox.extend(Vector3d(v[0], v[1], 0));
}
}
@ -41,9 +40,9 @@ BoundingBox Polygon2d::getBoundingBox() const
std::string Polygon2d::dump() const
{
std::stringstream out;
BOOST_FOREACH(const Outline2d &o, this->theoutlines) {
for(const auto &o : this->theoutlines) {
out << "contour:\n";
BOOST_FOREACH(const Vector2d &v, o.vertices) {
for(const auto &v : o.vertices) {
out << " " << v.transpose();
}
out << "\n";
@ -63,14 +62,14 @@ void Polygon2d::transform(const Transform2d &mat)
this->theoutlines.clear();
return;
}
BOOST_FOREACH(Outline2d &o, this->theoutlines) {
BOOST_FOREACH(Vector2d &v, o.vertices) {
for(auto &o : this->theoutlines) {
for(auto &v : o.vertices) {
v = mat * v;
}
}
}
void Polygon2d::resize(Vector2d newsize, const Eigen::Matrix<bool,2,1> &autosize)
void Polygon2d::resize(const Vector2d &newsize, const Eigen::Matrix<bool,2,1> &autosize)
{
BoundingBox bbox = this->getBoundingBox();

View file

@ -32,7 +32,7 @@ public:
const Outlines2d &outlines() const { return theoutlines; }
void transform(const Transform2d &mat);
void resize(Vector2d newsize, const Eigen::Matrix<bool,2,1> &autosize);
void resize(const Vector2d &newsize, const Eigen::Matrix<bool,2,1> &autosize);
bool isSanitized() const { return this->sanitized; }
void setSanitized(bool s) { this->sanitized = s; }

View file

@ -49,7 +49,7 @@ Q_DECLARE_METATYPE(Feature *);
class SettingsReader : public Settings::Visitor
{
QSettings settings;
const Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const {
Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const {
std::string trimmed_value(value);
boost::trim(trimmed_value);
@ -101,7 +101,7 @@ class SettingsWriter : public Settings::Visitor
settings.remove(key);
PRINTDB("SettingsWriter D: %s", key.toStdString().c_str());
} else {
Value value = s->get(entry);
const Value &value = s->get(entry);
settings.setValue(key, QString::fromStdString(value.toString()));
PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str());
}
@ -142,7 +142,7 @@ void Preferences::init() {
uint savedsize = getValue("editor/fontsize").toUInt();
QFontDatabase db;
foreach(uint size, db.standardSizes()) {
for(auto size : db.standardSizes()) {
this->fontSize->addItem(QString::number(size));
if (size == savedsize) {
this->fontSize->setCurrentIndex(this->fontSize->count()-1);
@ -504,6 +504,7 @@ void Preferences::on_comboBoxLineWrap_activated(int val)
void Preferences::on_comboBoxLineWrapIndentationStyle_activated(int val)
{
spinBoxLineWrapIndentationIndent->setDisabled(comboBoxLineWrapIndentationStyle->currentText() == "Same");
applyComboBox(comboBoxLineWrapIndentationStyle, val, Settings::Settings::lineWrapIndentationStyle);
}
@ -540,6 +541,12 @@ void Preferences::on_checkBoxAutoIndent_toggled(bool val)
writeSettings();
}
void Preferences::on_checkBoxBackspaceUnindents_toggled(bool val)
{
Settings::Settings::inst()->set(Settings::Settings::backspaceUnindents, Value(val));
writeSettings();
}
void Preferences::on_comboBoxIndentUsing_activated(int val)
{
applyComboBox(comboBoxIndentUsing, val, Settings::Settings::indentStyle);
@ -561,6 +568,11 @@ void Preferences::on_checkBoxEnableBraceMatching_toggled(bool val)
Settings::Settings::inst()->set(Settings::Settings::enableBraceMatching, Value(val));
writeSettings();
}
void Preferences::on_checkBoxEnableLineNumbers_toggled(bool checked)
{
Settings::Settings::inst()->set(Settings::Settings::enableLineNumbers, Value(checked));
writeSettings();
}
void Preferences::writeSettings()
{
@ -681,26 +693,28 @@ void Preferences::updateGUI()
this->spinBoxLineWrapIndentationIndent->setValue(s->get(Settings::Settings::lineWrapIndentation).toDouble());
this->spinBoxShowWhitespaceSize->setValue(s->get(Settings::Settings::showWhitespaceSize).toDouble());
this->checkBoxAutoIndent->setChecked(s->get(Settings::Settings::autoIndent).toBool());
this->checkBoxBackspaceUnindents->setChecked(s->get(Settings::Settings::backspaceUnindents).toBool());
this->checkBoxHighlightCurrentLine->setChecked(s->get(Settings::Settings::highlightCurrentLine).toBool());
this->checkBoxEnableBraceMatching->setChecked(s->get(Settings::Settings::enableBraceMatching).toBool());
this->checkBoxShowWarningsIn3dView->setChecked(s->get(Settings::Settings::showWarningsIn3dView).toBool());
this->checkBoxEnableLineNumbers->setChecked(s->get(Settings::Settings::enableLineNumbers).toBool());
this->spinBoxLineWrapIndentationIndent->setDisabled(this->comboBoxLineWrapIndentationStyle->currentText() == "Same");
}
void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry)
{
comboBox->clear();
Value::VectorType vector = entry.range().toVector();
for (Value::VectorType::iterator it = vector.begin();it != vector.end();it++) {
QString val = QString::fromStdString((*it)[0].toString());
std::string text((*it)[1].toString());
QString qtext = QString::fromStdString(gettext(text.c_str()));
// Range is a vector of 2D vectors: [[name, value], ...]
for(const auto &v : entry.range().toVector()) {
QString val = QString::fromStdString(v[0]->toString());
QString qtext = QString::fromStdString(gettext(v[1]->toString().c_str()));
comboBox->addItem(qtext, val);
}
}
void Preferences::initSpinBox(QSpinBox *spinBox, const Settings::SettingsEntry& entry)
{
Value::RangeType range = entry.range().toRange();
RangeType range = entry.range().toRange();
spinBox->setMinimum(range.begin_value());
spinBox->setMaximum(range.end_value());
}
@ -709,13 +723,13 @@ void Preferences::updateComboBox(QComboBox *comboBox, const Settings::SettingsEn
{
Settings::Settings *s = Settings::Settings::inst();
Value value = s->get(entry);
const Value &value = s->get(entry);
QString text = QString::fromStdString(value.toString());
int idx = comboBox->findData(text);
if (idx >= 0) {
comboBox->setCurrentIndex(idx);
} else {
Value defaultValue = entry.defaultValue();
const Value &defaultValue = entry.defaultValue();
QString defaultText = QString::fromStdString(defaultValue.toString());
int defIdx = comboBox->findData(defaultText);
if (defIdx >= 0) {
@ -749,9 +763,7 @@ void Preferences::create(QStringList colorSchemes)
std::list<std::string> names = ColorMap::inst()->colorSchemeNames(true);
QStringList renderColorSchemes;
foreach (std::string name, names) {
renderColorSchemes << name.c_str();
}
for(const auto &name : names) renderColorSchemes << name.c_str();
instance = new Preferences();
instance->syntaxHighlight->clear();

Some files were not shown because too many files have changed in this diff Show more