Compare commits

...

248 commits

Author SHA1 Message Date
Marius Kintel
823a8d2600 Force travis error for testing 2015-11-10 16:25:04 -05:00
Marius Kintel
53cbfe1008 Force travis error for testing 2015-11-10 15:39:07 -05:00
Marius Kintel
8819d6bde6 #1472 Another attempt at fixing; fix the iterator 2015-11-09 21:12:36 -05:00
Marius Kintel
9e43ca1299 #1472: Fixed infinite loop when passing NaN to for loops 2015-11-09 19:52:47 -05:00
Marius Kintel
1b030d7b71 #1472: Fixed infinite loop when passing NaN to for loops 2015-11-09 18:12:55 -05:00
Marius Kintel
c12ab83d22 Added echo OK 2015-11-09 18:10:36 -05:00
Marius Kintel
46e79118b1 #1472 Added test case 2015-11-09 17:52:50 -05:00
Marius Kintel
16026cfed7 Merge branch 'master' of github.com:openscad/openscad 2015-11-03 02:21:45 -05:00
Marius Kintel
e15c36f53f Patch Qt scaling issue when using pixmaps in QLabels 2015-11-03 02:21:42 -05:00
Marius Kintel
fbb5e895ab Updated Qt to 5.5.1, Sparkle to 1.11.0, added tweaks to build using Xcode 7 2015-11-03 01:35:11 -05:00
Marius Kintel
5639962224 doc 2015-11-03 01:18:18 -05:00
Don
2794123deb improve shared library MXE cross build. set CONFIG proper and copy .dll libs 2015-11-03 00:15:33 -05:00
Don
b9ff5fc5a7 allow shared library cross-build under MXE 2015-11-01 21:26:48 -05:00
Don
ab73c8c8a2 updates to MXE/win cross-build. use mingw64.static build dir.
check for 'zip' command when building package. auto detect mxe in /opt/mxe
2015-11-01 17:41:09 -05:00
Don
a2814e11a7 add some updated notes on MXE cross build 2015-11-01 16:57:04 -05:00
Don Bright
f65cc7816c use boost cstdint.hpp, prevent "int32_t does not name a type" error on new gcc 2015-10-28 21:05:26 -05:00
Marius Kintel
53c255d4fd Merge branch 'master' of github.com:openscad/openscad 2015-10-26 15:45:28 -04:00
Marius Kintel
6736b1e3a3 Merge pull request #1464 from openscad/issue452part2
Issue452part2
2015-10-26 15:45:22 -04:00
Marius Kintel
e3c1a90a97 Detect El Capitan 2015-10-26 15:39:19 -04:00
Marius Kintel
5bdc9383f5 Merge pull request #1462 from GilesBathgate/Enable_OpenCSG
Enable compilation without OpenCSG.
2015-10-25 17:44:19 -04:00
Don Bright
24124f62bf improve infinity tests per discussion on email list 2015-10-24 21:57:19 -05:00
Don Bright
65cc670385 make Orthogonal View button show Orthogonal projected cube, not perspective. 2015-10-24 12:48:53 -05:00
don bright
da426df8c7 simplify documentation, for deeper knowledge people should follow urls 2015-10-23 22:16:45 -05:00
don bright
a667eba60c remove extraneous space 2015-10-23 22:12:56 -05:00
don bright
0dded01c37 improve documentation of number conversion function (again) 2015-10-23 22:11:03 -05:00
don bright
fa34694af4 better documentation of number conversion function 2015-10-23 22:09:12 -05:00
don bright
cb69ab404f Merge branch 'master' of github.com:openscad/openscad into issue452part2 2015-10-23 21:53:13 -05:00
Giles Bathgate
5a3d81d553 QGLView requires glew regardless of whether opencsg is used. 2015-10-23 23:02:02 +01:00
Giles Bathgate
280ae53f8e Enable compilation without OpenCSG. 2015-10-23 21:46:23 +01:00
Marius Kintel
9a83b0bacf Updated dependencies 2015-10-16 16:33:48 -04:00
Marius Kintel
7310cd7aab CGAL-4.6.3 2015-10-16 14:00:13 -04:00
Marius Kintel
5b92c90f9b Sync with recent changes to the codebase 2015-10-16 13:59:56 -04:00
Marius Kintel
24408ef220 minor wording fixes 2015-10-16 13:44:35 -04:00
Marius Kintel
6c8bff81d3 #1425 For backwards compatibility, revert calculation so that never reaches 1.0 2015-10-16 12:44:35 -04:00
Marius Kintel
2b5c3ef70d Simplified example 2015-10-15 21:28:12 -04:00
Marius Kintel
ab8278416a Test for #1455 2015-10-15 21:16:42 -04:00
Marius Kintel
2ff35fed0c Nef polyhedron for testing #1455 against a pure CGAL app 2015-10-15 21:14:14 -04:00
Marius Kintel
b40e492d87 Respect ENABLE_OPENCSG define 2015-10-15 21:03:40 -04:00
Marius Kintel
f1e8f2c1a5 Merge pull request #1447 from kant/patch-1
Minor fix
2015-10-03 23:37:57 -04:00
Darío Hereñú
e6e933d844 Minor fix 2015-10-03 09:47:37 -03:00
Marius Kintel
e225f2d341 #1425 Let the last animation frame correspond with =1.0, to allow people to design for a valid last frame. 2015-09-24 16:29:17 -04:00
Marius Kintel
29d472b691 #1425 Correctly reset picture dump if anim steps were changed 2015-09-24 16:09:47 -04:00
Don Bright
8baea085c6 friendly helping reminder for debian 7, which lacks harfbuzz 2015-09-24 01:44:46 +00:00
don bright
42dba75497 add convenience search for openscad binary under openscad/bin/openscad 2015-09-23 18:22:15 -07:00
don bright
c1e12e4782 Merge branch 'issue452part2' of github.com:openscad/openscad into issue452part2 2015-09-23 18:21:40 -07:00
Don Bright
3bab13d2ee update test results to match output verbiage 2015-09-23 20:20:52 -05:00
don bright
19b9f99ee8 convenience search of openscad gui binary, for test run 2015-09-23 18:09:07 -07:00
Don Bright
d2d273895e add a few more tests for floating point rands() seeds, and expected results. 2015-09-23 20:03:34 -05:00
Don Bright
3327231847 add test results for rands() dealing with floating point seeds & infinite inputs 2015-09-23 19:58:04 -05:00
Don Bright
b8ec2c2bc8 minor cleanup of unneeded code 2015-09-23 19:52:52 -05:00
Don Bright
ff4debec77 add new tests for infinite inputs to rands() 2015-09-23 19:40:46 -05:00
Don Bright
a675ef6e4e rm my old hash, use awesome floating point hash from Python, include license 2015-09-23 19:30:46 -05:00
Don Bright
600a96f3f4 create better hash function for 64 double->32 bit unsigned int 2015-09-20 22:46:16 -05:00
Don Bright
25c31d124e make rands() deal better with float input for seed, and inf input 2015-09-19 01:00:53 -05:00
Marius Kintel
6144d45457 Added IRC button 2015-09-17 22:29:54 -04:00
Marius Kintel
7f9e7f9c83 Merge pull request #1432 from openscad/issue1407
Fix #1407 by storing vector values as heap objects (ValuePtr) rather than stack objects(Value)
2015-09-14 00:53:16 -04:00
Marius Kintel
ed637eb6d5 Minor fix: No need to convert to char*. Fixes #1429 2015-09-06 11:17:52 -04:00
Don Bright
c8097fd604 add expected result of recursion-test-vector 2015-09-05 22:38:50 -05:00
Don Bright
5e1df90c55 add test for issue1407, recursion crash when vectors are parameters 2015-09-05 22:26:33 -05:00
Don Bright
3fa0046638 allow custom location of openscad GUI binary by setting OPENSCAD_BINARY
environment variable
2015-09-05 19:26:45 -05:00
Marius Kintel
78234a10ac #1407 Minor Value vs. ValuePtr value/reference cleanup 2015-09-05 15:32:58 -04:00
Marius Kintel
847cc76f20 Refactored to let VectorValues use ValuePtr instead of Value, to avoid having to copy large vectors. Attempt to fix #1407 2015-09-04 15:28:50 -04:00
Marius Kintel
e98a6de11f #1425 Implemented some improvements suggested by @DBramley 2015-09-04 12:40:13 -04:00
Marius Kintel
23b6faa17c Merge pull request #1431 from openscad/issue1425
Use integers for underlying frame counter. Fixes rounding issue #1425
2015-09-02 23:28:08 -04:00
Marius Kintel
32a2f3aeaf Use integers for underlying frame counter. Fixes rounding issue #1425 2015-09-01 17:23:00 -04:00
Marius Kintel
b6e55ad66c Merge pull request #1421 from openscad/issue1420-arm64-int-cast
Check for infinite double values when using values as index (fixes #1420).
2015-08-31 17:01:49 -04:00
Marius Kintel
b152acb9e4 Catch RangeTest exception from clipper. Fixes #1410 2015-08-31 16:56:00 -04:00
Marius Kintel
6441ac4da2 Merge pull request #1416 from chrysn-pull-requests/chrysn/issue1415
Fix path discovery for fonts
2015-08-18 23:11:16 +02:00
Marius Kintel
4cd1bf9541 Merge pull request #1406 from openscad/update-web-colors
Validate colors against CSS4 draft - add "RebeccaPurple".
2015-08-18 23:01:56 +02:00
Marius Kintel
a2a1f23d6d Merge pull request #1423 from openscad/mint-17-deps-fix
Use Debian7 dependencies for Linux Mint (fixes #1422).
2015-08-18 22:16:18 +02:00
Torsten Paul
dcbab229c6 Use Debian7 dependencies for Linux Mint (fixes #1422). 2015-08-18 22:13:05 +02:00
Torsten Paul
f7a5313917 Check for infinite double values when using values as index (fixes #1420).
On arm64 the integer constructor returns 0 for an input value of NaN. To
prevent this, index values are now checked against Inf/NaN and protected
against overflow using boost::numeric_cast.
2015-08-17 13:35:53 +02:00
Marius Kintel
2f4091b1b7 Merge pull request #1379 from openscad/issue1378-linear-extrude-crash
Ignore Inf/NaN parameters to linear_extrude() (fixes #1378).
2015-08-12 20:47:41 +02:00
chrysn
90a660d718 Fix path discovery for fonts
When the path to the openscad binary changed in [1], the relative path
was not changed and therefore led into the void, falling back to system
paths.

[1] https://github.com/openscad/openscad/issues/1362
2015-08-11 16:19:51 +02:00
Marius Kintel
d60691b995 Merge pull request #1411 from chrysn-pull-requests/chrysn/fixes-from-debian
Minor fixes from Debian's checks
2015-08-11 12:11:44 +02:00
chrysn
a17b894316 Change "Allow to open multiple documents" to "Allow opening"
This is for grammatical reasons. It is being discussed in
https://bugs.debian.org/795158, and "allowing" seems to be a correct
(not necessarily ideal, but not intrusive) solution.

Forwarded: no
2015-08-11 12:02:57 +02:00
chrysn
2aaafa44bc man page: Rephase colorscheme option to avoid problems with wrapping
The old version threw errors when formatted:

$ LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z ./doc/openscad.1 >/dev/null
<standard input>:85: warning [p 2, 4.7i, div `an-div', 0.0i]: cannot adjust line

This was discovered by lintian and reported as
'manpage-has-errors-from-man'.

Forwarded: no

Gbp-Pq: Name man-page-Rephase-colorscheme-option-to-avoid-problem.patch
2015-08-11 11:47:44 +02:00
chrysn
e4c25bc2f6 Add keywords to the desktop file
Forwarded: no

Gbp-Pq: Name Add-keywords-to-the-desktop-file.patch
2015-08-11 11:47:34 +02:00
Chow Loong Jin
211b795326 Add hashbang to test_cmdline_tool.py
Forwarded: no

Gbp-Pq: Name Add-hashbang-to-test_cmdline_tool.py.patch
2015-08-11 11:47:01 +02:00
Marius Kintel
1c5ac3b6fd Merge pull request #1377 from openscad/flattr-patch
Remove flattr icon and use styled link instead.
2015-08-10 19:40:35 +02:00
Torsten Paul
a06c44a333 Validate colors against CSS4 draft - add "RebeccaPurple". 2015-08-02 16:42:21 +02:00
Torsten Paul
1f5367bd46 Ignore Inf/NaN parameters to linear_extrude() (fixes #1378). 2015-07-04 16:50:59 +02:00
Torsten Paul
1ef90ace3d Remove flattr icon and use styled link instead.
This change is mainly driven by Debian declaring the button non-free so
it must be removed when distributing OpenSCAD in Debian.
2015-06-28 19:25:12 +02:00
Marius Kintel
68e41af144 Merge pull request #1372 from hroncok/patch-1
Add a line about itstool to translation doc
2015-06-21 14:42:14 -04:00
Miro Hrončok
68a296b408 Add a line about itstool to translation doc
After #1366 was merged, itstool is required to update the .po files.
2015-06-21 19:39:04 +02:00
Marius Kintel
1beeb4880e #1366 bugfix: use single = for string comparison for dash compatibility 2015-06-21 12:47:35 -04:00
Marius Kintel
012ef6624c Merge pull request #1366 from hroncok/itstool
Create multilingual appdata file using itstool
2015-06-21 12:40:18 -04:00
Miro Hrončok
1522dae4cf Create multilingual appdata file using itstool
- updated appdata file to a newer syntax
 - created an english appdata template
 - the strings are extracted during updatepot function in translation-update.sh
 - the multilingual file is created at the end of updatemo in the same script if possible
2015-06-21 15:59:56 +02:00
Marius Kintel
6bd23abdab Merge branch 'master' of github.com:openscad/openscad 2015-06-19 18:34:44 -04:00
Marius Kintel
f9e7c945ba Merge pull request #1367 from openscad/issue1350-save-file
Use QSaveFile (if available) to write designs to disk. (fixes #1350)
2015-06-19 18:31:46 -04:00
Marius Kintel
9a113b9407 Merge branch 'master' of github.com:openscad/openscad 2015-06-19 18:20:49 -04:00
Marius Kintel
310b8fa693 Reinstated openscad_nogui as an optional build target (cmake -DNOGUI=1). No need to run translation-make.sh as that's done by qmake 2015-06-19 18:20:26 -04:00
Marius Kintel
ae9ab8fd5e Merge pull request #1365 from openscad/issue1355
Issue1355
2015-06-19 18:06:52 -04:00
Marius Kintel
058330b0ad Merge branch 'chrysn/drop-openscadtesting' of https://github.com/chrysn-pull-requests/openscad 2015-06-19 16:52:55 -04:00
Marius Kintel
38dbd49613 Merge pull request #1369 from openscad/win-export-fix
Fix export call for non-ASCII file names.
2015-06-14 18:01:50 -04:00
Torsten Paul
02c1cf322f Fix export call for non-ASCII file names. 2015-06-14 15:33:21 +02:00
Torsten Paul
1514514a76 Use QSaveFile (if available) to write designs to disk.
Always check the status of the QTextStream to catch problems like disk
full.
In addition QSaveFile can ensure the old file is not destroyed as it's
using a temporary file which is committed at the end by just renaming it
to the output file name.
2015-06-14 01:23:54 +02:00
don bright
31de8e0f8e fix bug in fedora version detection 2015-06-09 18:25:44 -07:00
don bright
b1caaaa344 Merge branch 'master' of github.com:openscad/openscad into issue1355 2015-06-09 18:20:58 -07:00
don bright
3ca9b32849 Merge branch 'issue1355' of github.com:openscad/openscad into issue1355 2015-06-09 17:46:20 -07:00
don bright
d1d7bb21c4 improve OpenCSG build - qmake5 detection and GLU include finding 2015-06-09 17:45:39 -07:00
Don Bright
d2e05710e2 deal with qt4/qt5 situaton on ubuntu. see
http://perezmeyer.blogspot.com.ar/2013/08/qt-in-debian-using-qt4-andor-qt5-in.html
http://askubuntu.com/questions/508503/whats-the-development-package-for-qt5-in-14-04
2015-06-09 04:50:05 +00:00
Don Bright
3b9d1ca4d8 fixes for debian 7. add correct dependencies. add option to easily build harfbuzz 2015-06-09 04:08:38 +00:00
chrysn
f85ace9dd0 fix font directory discovery in export_import_pngtest
the old way of constructing the font path from the openscad binary
has failed since the binary built outside testing has been used.
building the path from the test script works with any openscad binary.
2015-06-08 11:05:52 +02:00
chrysn
1b30f641ad pack OPENSCAD_NOGUI in qmake nogui config
thus, scintilla can be kept from being built at all, slimming down the
build dependencies for the nogui build
2015-06-08 09:58:38 +02:00
chrysn
2227b5cbb8 use qmake in travis to build gui-free openscad binary
with OPENSCAD_TESTING gone, the openscad binary (even in a non-gui
version) is easiest made using qmake.
2015-06-08 08:34:36 +02:00
Marius Kintel
87e32efc18 Handle dimensional errors in matrix multiplication, including undef values. Fixes #1356 2015-06-07 13:11:27 -04:00
Marius Kintel
2745b8534c Updated harfbuzz to 0.9.40 2015-06-07 13:09:41 -04:00
Marius Kintel
662a57a7bd Merge pull request #1358 from openscad/installer-updates
Add more detailed installer information including version number.
2015-06-07 11:17:18 -04:00
chrysn
7b39f455b5 fix building of remaining binaries
the previous patch has removed the -DENABLE_EXPERIMENTAL flag, assuming
that it is not required any more without openscad_nogui being built.
while that is sufficient for the test suite, other binaries built in the
tests/ directory would still use those flags.

in order to make them buildable again, the -DOPENSCAD_NOGUI compile time
option is added (as the resulting binaries are command-line-only tools,
which was previously implicit by setting -DOPENSCAD_TESTING), and
-DENABLE_EXPERIMENTAL is restored.
2015-06-07 15:32:36 +02:00
Don
cbccc87677 update opensuse dependency fetcher 2015-06-07 13:12:00 +00:00
Don Bright
dad1566ffa add xvfb download for debian dependencies (for Tests) 2015-06-06 22:22:12 -04:00
Don Bright
db206e78de fix typo for previous commit 2015-06-06 14:51:56 -04:00
Don Bright
357e7db66b workaround FORTIFY_SOURCE bug where clang won't build under fedora 22 2015-06-06 14:50:44 -04:00
Don Bright
51c4622ca0 prevent err message when calling boost::canonical on a path that doesnt exist 2015-06-06 13:30:21 -04:00
Don Bright
1bf93e1c77 install mesa-dri-drivers on fedora/redhat to allow Xvfb to work with OpenGL 2015-06-06 13:07:26 -04:00
Don Bright
892510b47b move #ifdef-out code where it was. document #if 0 #endif. move func up in file 2015-06-06 12:32:30 -04:00
chrysn
47f93e3f44 don't build openscad_nogui any more 2015-06-04 21:28:17 +02:00
chrysn
574f6e7d33 drop OPENSCAD_TESTING definition
for cases when a binary without gui / qt should be built, OPENSCAD_NOGUI
can now be defined. all the other uses for OPENSCAD_TESTING are now
covered by the unit test framework.
2015-06-04 21:24:07 +02:00
chrysn
d3494d66b1 add float normalization to test_cmdline_tool
this helps removing the need for OPENSCAD_TESTING
2015-06-04 21:17:27 +02:00
Don Bright
f993361f8b get scintilla for qt5 for fedora 2015-06-02 00:28:06 -04:00
Don Bright
75f10648c9 fix missing namespace bracket i previously deleted 2015-06-02 00:03:39 -04:00
Don Bright
5b917adff9 remove redundant vector_convert (its in cgalutils.h now) 2015-06-01 23:20:06 -04:00
Don Bright
4db4aa5563 prevent gcc crash on systems w 2GB RAM, by splitting cgalutils 2015-06-01 23:18:22 -04:00
Don Bright
0a2556304f split cgalutils to reduce gcc RAM usage. fix fedora deps. fix warnings 2015-06-01 21:43:27 -04:00
Torsten Paul
e1e3dae220 Add more detailed installer information including version number. 2015-06-01 21:37:51 +02:00
Don Bright
515c77b949 update fedora 22+ to use 'dnf' instead of 'yum', fix ImageMagick pkgname 2015-06-01 00:07:58 -04:00
Don Bright
7279c1c019 issue 1355 on Un*X find X11 for Offscreen, due to cmake change in OpenGL finding 2015-05-31 23:13:58 -04:00
Marius Kintel
42d6629156 Merge pull request #1339 from openscad/export-to-clipboard
Add "Export to Clipboard" to copy the current 3d view to the system clipboard.
2015-05-18 22:20:28 -04:00
Torsten Paul
ff2427cc1e Move to Edit->Copy Viewport and add shortcut SHIFT-CTRL-C. 2015-05-16 17:41:52 +02:00
Marius Kintel
5451fabcc1 Merge pull request #1346 from ArchimedesPi/fixup-some-coverity-defects
Fix some defects from Coverity (WIP)
2015-05-15 15:45:11 -04:00
Liam Marshall
9641e9bd7f oops can't delete a pointer address 2015-05-15 14:25:08 -05:00
Liam Marshall
365c562a17 Fix #1 of 2 in 25081 (OffscreenContextGLX.cc) 2015-05-15 14:20:46 -05:00
Liam Marshall
a1a238a9cd Fix memory leak 25072 (ModuleCache::evaluate) 2015-05-15 14:07:42 -05:00
Liam Marshall
7223f2ac05 Preserve output state so that everything afterwards doesn't get turned into hex 2015-05-15 13:43:23 -05:00
Liam Marshall
1752fcee8c Easier fix for 93925 (control.cc) 2015-05-15 13:31:20 -05:00
Liam Marshall
4f1132e5a6 Fix memory leak 25008 2015-05-15 13:15:31 -05:00
Liam Marshall
306cece150 Fix memory leak 25035 2015-05-15 13:11:55 -05:00
Liam Marshall
289d84aac0 Fix memory leak 93925 2015-05-15 12:52:12 -05:00
Liam Marshall
38b93fe7a7 Fix memory leak 25100 2015-05-15 12:46:30 -05:00
Marius Kintel
031e016df7 Fix resource path search; the 'libraries' folder isn't always installed. Fixes #1342 2015-05-14 22:32:00 -04:00
Marius Kintel
52f5fe2e92 Merge pull request #1343 from ArchimedesPi/quiet-mode
Implement quiet mode
2015-05-14 22:14:21 -04:00
Marius Kintel
f71e0acbbb Merge pull request #1338 from ArchimedesPi/axes-colorscheme
Add a axes-color option for color schemes
2015-05-14 22:12:37 -04:00
Marius Kintel
59f63b5e17 Merge pull request #1337 from openscad/script-detect
Simple detection of script and direction based on given text.
2015-05-14 22:10:44 -04:00
Marius Kintel
cd4ced5456 Merge pull request #1327 from openscad/issue1254-qscintilla-fedora
Workaround for Fedora 21 builds (fixes #1254).
2015-05-14 22:08:47 -04:00
Liam Marshall
2c6d783eb7 Change bacl to black axes for Cornfield 2015-05-14 14:48:12 -05:00
Liam Marshall
1ab390d115 Don't suppress error messages 2015-05-13 17:38:47 -05:00
Liam Marshall
c31a96454c Need to add quiet to OpenSCAD namespace 2015-05-13 11:23:15 -05:00
Liam Marshall
5239121706 Make PRINT_NOCACHE respect OpenSCAD::quiet 2015-05-13 11:21:55 -05:00
Liam Marshall
061537e773 Add OpenSCAD::quiet definition 2015-05-13 11:21:36 -05:00
Liam Marshall
02db2e15a4 Make -q toggle a global variable for quiet mode 2015-05-13 11:18:32 -05:00
Liam Marshall
4f4ddb938a Add --quiet,-q option 2015-05-13 11:16:24 -05:00
Liam Marshall
17f9941a08 Make default blue color a bit darker 2015-05-12 17:37:00 -05:00
Torsten Paul
591c98e979 Add "Export to Clipboard" to copy the current 3d view to the system clipboard. 2015-05-12 23:48:17 +02:00
Liam Marshall
ca9f9d9d9c axes-color for Tomorrow Night 2015-05-12 15:53:26 -05:00
Liam Marshall
0c2af2defa axes-color for Tomorrow 2015-05-12 15:53:19 -05:00
Liam Marshall
8e53c29612 axes-color for Sunset 2015-05-12 15:53:11 -05:00
Liam Marshall
e6cd3fdda1 axes-color for StarNight 2015-05-12 15:50:22 -05:00
Liam Marshall
f9b074c473 axes-color for Nature 2015-05-12 15:50:14 -05:00
Liam Marshall
3511e7079f axes-color for Monotone 2015-05-12 15:47:49 -05:00
Liam Marshall
7fb626fb08 axes-color for Metallic 2015-05-12 15:45:53 -05:00
Liam Marshall
55affd0273 axes-color for DeepOcean 2015-05-12 15:44:56 -05:00
Liam Marshall
c2f2ba5293 axes-color for beforedawn 2015-05-12 15:43:31 -05:00
Liam Marshall
69e6707c62 axes-color for solarized 2015-05-12 15:41:54 -05:00
Liam Marshall
9fb5893540 Map axes-color in JSON files to AXES_COLOR 2015-05-12 15:26:08 -05:00
Liam Marshall
cdbd08a4d3 Default for axis color (for testing) 2015-05-12 15:25:53 -05:00
Liam Marshall
98b6cf3d19 Add AXES_COLOR to enum RenderColor 2015-05-12 15:22:26 -05:00
Liam Marshall
5e3cd59eeb Switch from getContrastColor to getColor in GLView
* Removed bgcontrast
* Added new `Color4f axescolor` obtained by `ColorMap::getColor(...,
AXES_COLOR)`
* Switched showAxes and showScalemarkers to `axescolor`
2015-05-12 15:09:20 -05:00
Torsten Paul
9f372cff41 Simple detection of script and direction based on given text.
This adds a simple detection logic based on the hb_unicode_script()
function provided by harfbuzz. Automatic script selection will only
happen if no valid parameter was given (basically only in case of
a missing script parameter in text()).
If different scripts are found in a single text, the resulting value
is HB_SCRIPT_UNKNOWN.
2015-05-09 18:05:07 +02:00
Marius Kintel
89371f60cf Merge pull request #1335 from hroncok/patch-1
Czech translation: Add missing space
2015-05-04 15:02:58 -04:00
Miro Hrončok
c94e62878a Czech translation: Add missing space 2015-05-04 20:12:53 +02:00
Marius Kintel
2dbf9755c3 Version splitting used wrong variable, causing version() to return [0,0,0]. Fixes #1329 2015-04-28 10:21:02 -04:00
Marius Kintel
0e1b0daf36 #1254 Backport some code to boost filesystem V2, for old RedHat version 2015-04-26 16:11:51 -04:00
Marius Kintel
e21b321323 Allow compiling against libstdc++ and c++03 2015-04-26 16:11:10 -04:00
Torsten Paul
cc4b633e43 Workaround for Fedora 21 builds (fixes #1254).
Fedora installs qscintilla2.prf in the wrong location and has a different
naming scheme than the one used in Ubuntu so the existing workaround fails.
This adds yet another workaround to detect the different naming for the
Qt5 version of the QScintilla2 library.
2015-04-26 16:45:04 +02:00
Marius Kintel
c45f2b5f36 Merge branch 'master' of github.com:openscad/openscad 2015-04-25 21:31:17 -04:00
Marius Kintel
2b3392266f Merge pull request #1326 from openscad/issue1325
Fixes Issue #1325
2015-04-25 16:57:05 -04:00
Marius Kintel
12a43fd942 bugfix: bash substitution of SHORTVERSION was wrong 2015-04-21 11:10:24 -04:00
Marius Kintel
b3ae7fa1ff Merge pull request #1319 from openscad/issue1317
Fixed bug reversing result of is_nan(), causing normals vectors to somet...
2015-04-21 01:56:00 -04:00
Marius Kintel
a1bece5c51 Merge pull request #1316 from openscad/issue1288
Grab framebuffer before opening file dialog. Should fix #1288
2015-04-17 10:14:02 -04:00
Marius Kintel
4d3800cc89 Merge pull request #1313 from clothbot/patch-3
Removed deprecated assign statement
2015-04-16 00:32:12 -04:00
Andrew Plumb
c32e271a0c Sync up output with example023 cleanup. 2015-04-15 23:58:06 -04:00
Marius Kintel
6e5315b430 Merge pull request #1312 from clothbot/patch-2
Comment out search term not found WARNING
2015-04-15 22:08:24 -04:00
Andrew Plumb
9897174a03 Found more search PRINTB warnings to remove 2015-04-15 18:29:05 -04:00
Marius Kintel
e87dab0bc6 Merge branch 'master' of https://github.com/openscad/openscad 2015-04-15 14:35:15 -07:00
Marius Kintel
e5e9f20f95 Prefer http over ftp 2015-04-15 14:35:12 -07:00
Marius Kintel
b9c8985377 Fix gmp issue; ptrdiff_t not found. Fixes #1314 2015-04-15 14:33:51 -07:00
Andrew Plumb
e8c8bda674 Manually removing WARNING echos. 2015-04-15 14:50:44 -04:00
Andrew Plumb
dee5885d9f Manually removing WARNING echos. 2015-04-15 14:49:02 -04:00
Andrew Plumb
bb183558ae Removing instead of just commenting out line. 2015-04-15 14:47:30 -04:00
Marius Kintel
ed2f4c2e22 Merge pull request #1315 from ankush1995/compile-gl
separate-compile
2015-04-15 13:22:38 -04:00
ankush1995
7e5394c6fa separate-compile 2015-04-15 14:56:19 +05:30
Andrew Plumb
330b41656b Removed deprecated assign statement 2015-04-13 19:24:51 -04:00
Andrew Plumb
3adfdad66d Comment out search term not found WARNING
Returning empty result should be sufficient for detecting a no-match condition.

See forum discussion http://forum.openscad.org/Suppressing-quot-search-term-not-found-quot-warning-in-search-td12359.html
2015-04-13 18:46:43 -04:00
Marius Kintel
82f85cd328 Merge pull request #1311 from openscad/issue1276
Issue1276
2015-04-13 13:21:09 -04:00
Marius Kintel
f53b3a3ac1 Merge pull request #1310 from openscad/issue1284
Issue1284
2015-04-13 13:10:00 -04:00
Marius Kintel
90094fff25 Merge pull request #1295 from openscad/issue1294
Don't include build date. Fixes #1294
2015-04-01 17:10:36 -04:00
Marius Kintel
38ef9fddde Don't include build date. Fixes #1294 2015-04-01 17:09:57 -04:00
Marius Kintel
6c3c2de264 Merge pull request #1283 from Lenbok/scad-mode-updates
Updates to Emacs scad-mode
2015-03-30 23:29:24 -04:00
Lenbok
7632b065c6 Fix incorrect indentation for lines affected by # modifier 2015-03-28 15:38:13 +13:00
Lenbok
b43734c3e5 * Convert to being derived from cc-mode, as per a 2013 post from Lukasz
Stelmach. This yields better indentation (particularly for
  continuations) as well as being simpler.

* Update keywords for the 2015.03 release (plus a couple missed from
  earlier)

* Use separate highlighting style for deprecated keywords.
2015-03-28 13:59:45 +13:00
Torsten Paul
a5ec4587b6 Switch to MXE hosted in openscad github / branch openscad-snapshot-build. 2015-03-24 01:29:33 +01:00
Marius Kintel
1b840be127 Merge pull request #1280 from openscad/issue1264b
#1264 Backported to QScintilla 2.7, left a small bug when using 2.7 but ...
2015-03-23 16:30:57 -04:00
Marius Kintel
85290e4d51 Merge pull request #1279 from openscad/issue1277
Update temporal variables for each evaluation, not for each compilation....
2015-03-23 15:28:54 -04:00
Marius Kintel
3ac213d649 Merge pull request #1278 from openscad/issue1264
Reimplemented Replace All to work properly. Fixes #1264
2015-03-23 14:26:11 -04:00
Marius Kintel
2001f1302e Merge pull request #1275 from openscad/mxe-c++11
Build fixes to compile on MXE with C++11 enabled.
2015-03-23 11:32:34 -04:00
Torsten Paul
c71e70c0f9 Build fixes to compile on MXE with C++11 enabled. 2015-03-22 14:17:36 +01:00
Marius Kintel
d37f4fbbab install in normal location, set c++11 as default for dependencies 2015-03-20 20:16:55 -04:00
Marius Kintel
c5e1e2b9af Merge remote-tracking branch 'origin/master' into c++11 2015-03-20 17:00:41 -04:00
Marius Kintel
c037625b65 Disable c++11 as default for now 2015-03-20 17:00:05 -04:00
Marius Kintel
9660ba84a0 Merge remote-tracking branch 'origin/master' into c++11 2015-03-14 15:46:49 -04:00
Marius Kintel
067eec8743 Merge remote-tracking branch 'origin/master' into c++11 2015-03-12 01:38:29 -04:00
Marius Kintel
e78206d2aa Separate out std/stdlib flags since ragel doesn't currently build with C++11 2015-03-12 01:38:12 -04:00
Marius Kintel
394cc15fba Merge remote-tracking branch 'origin/master' into c++11 2015-03-10 22:08:06 -04:00
Marius Kintel
54239a2534 Merge remote-tracking branch 'origin/master' into c++11 2015-02-17 15:28:58 -05:00
Marius Kintel
6ac8d017b7 #669 Added DXX11 and LIBCXX11 options 2015-02-10 19:10:08 -05:00
Marius Kintel
8216e98afd Merge remote-tracking branch 'origin/master' into c++11 2015-02-10 19:09:12 -05:00
Marius Kintel
b567f844ad #669 Support libc++ in macosx-sanity-check 2015-02-10 17:50:42 -05:00
Marius Kintel
137928fced #669 C++11 build fix 2015-02-10 17:46:55 -05:00
Marius Kintel
7c2db84fe6 #669 Added C++11 support 2015-02-10 17:32:24 -05:00
Marius Kintel
65935b4466 Merge remote-tracking branch 'origin/master' into c++11 2015-02-10 17:31:12 -05:00
Marius Kintel
6576ee7d05 Merge remote-tracking branch 'origin/master' into c++11 2015-02-10 16:42:48 -05:00
Marius Kintel
a41c8716ec Merge remote-tracking branch 'origin/master' into c++11
Conflicts:
	openscad.pro
2015-01-06 01:10:04 -05:00
Marius Kintel
e1da26bd8b Merge remote-tracking branch 'origin/master' into c++11 2014-11-25 17:42:59 -05:00
Marius Kintel
437aa69292 Merge remote-tracking branch 'origin/master' into c++11 2014-11-25 17:13:01 -05:00
Marius Kintel
2bdf02d352 Cleaned up c++11 config a bit 2014-11-06 12:53:53 +01:00
Marius Kintel
637244d59e Merge remote-tracking branch 'origin/master' into c++11 2014-11-06 12:41:54 +01:00
Marius Kintel
3a3ffc0118 Merge remote-tracking branch 'origin/master' into c++11 2014-09-02 00:16:38 -04:00
Marius Kintel
67c68634b6 Be more verbose when using c++11 2014-09-02 00:16:36 -04:00
Marius Kintel
b394da33c7 Mac: Disallow c++11 if dependencies are linked against libstdc++ 2014-06-21 16:52:35 -04:00
Marius Kintel
a0875c845c Merge remote-tracking branch 'origin/master' into c++11 2014-06-21 16:15:56 -04:00
Marius Kintel
c4f369fbf8 Merge branch 'master' into c++11
Conflicts:
	openscad.pro
2014-06-10 00:16:05 -04:00
Marius Kintel
da56dff89d minor c++11 config fixes 2014-06-10 00:15:14 -04:00
Marius Kintel
1d6b7923bd Merge branch 'master' into c++11 2014-06-09 23:38:32 -04:00
Marius Kintel
7b4411bbcc We're actually checking for libc++, not c++11 2014-06-09 23:35:33 -04:00
Marius Kintel
2de378bef5 Merge branch 'master' into c++11 2014-06-09 23:23:44 -04:00
Marius Kintel
35222064c1 Adapt to using CONFIG+=c++11 2014-06-08 00:03:06 -04:00
Marius Kintel
7f782832d7 Merge remote-tracking branch 'origin/mac_libc++_build' into c++11 2014-06-07 23:45:31 -04:00
Oskar Linde
c5bc92d97c Mac: Automate build with libc++ when not using OPENSCAD_LIBRARIES
Conflicts:
	openscad.pro
2014-06-08 01:27:44 +02:00
Marius Kintel
19cea6f3a8 Merge branch 'master' into c++11 2014-06-07 17:49:29 -04:00
Marius Kintel
2eb96a2a88 Build as c++11. On Mac, build as c++11 if as libc++-linked boost exists 2014-06-07 17:48:42 -04:00
Marius Kintel
2cf6dcacf2 Merge branch 'master' into c++11 2014-06-05 19:18:33 -04:00
Marius Kintel
b2b3306205 Merge branch 'master' into c++11 2014-04-25 02:29:40 -04:00
Marius Kintel
d6340b18db Merge branch 'master' into c++11 2014-03-03 21:04:27 -05:00
Marius Kintel
fd1ae57c16 Merge branch 'f_enable_cpp11' of git://github.com/8p0/openscad into 8p0-f_enable_cpp11 2014-02-22 11:30:02 -05:00
Jan Huwald
086f231d5a fix typo 2014-02-21 12:21:38 +01:00
Jan Huwald
c259e5275c compile with -std=c++0x to support older C++11 compilers 2014-02-21 09:22:39 +01:00
Jan Huwald
ec3743dc9a compile as C++11 2014-02-13 12:00:12 +01:00
160 changed files with 5495 additions and 2439 deletions

1
.gitignore vendored
View file

@ -37,6 +37,7 @@ testdata/scad/misc/use-tests.scad
/lexer_lex.cpp /lexer_lex.cpp
/parser_yacc.cpp /parser_yacc.cpp
/OpenSCAD.app /OpenSCAD.app
/openscad.appdata.xml
/openscad.pro.user /openscad.pro.user
/openscad /openscad
/locale/*/*/*.mo /locale/*/*/*.mo

View file

@ -2,6 +2,8 @@
[![Coverity Status](https://scan.coverity.com/projects/2510/badge.svg)](https://scan.coverity.com/projects/2510) [![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") [![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? # 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) [![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)
@ -147,7 +149,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``` ```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. 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 However, Homebrew's Qt4 has a broken ```moc``` command, causing OpenSCAD compilation to
@ -231,9 +233,9 @@ For a 64-bit Windows cross-build, replace 32 with 64 in the above instructions.
### Compilation ### Compilation
First, run 'qmake openscad.pro' from Qt4 to generate a Makefile. First, run 'qmake openscad.pro' from Qt to generate a Makefile.
On some systems, depending on which version(s) of Qt you have installed, you may need to specify which version you want to use, e.g. by running 'qmake4', 'qmake-qt4' or something alike. On some systems, depending on which version(s) of Qt you have installed, you may need to specify which version you want to use, e.g. by running 'qmake4', 'qmake-qt4', 'qmake -qt=qt5', or something alike.
Then run make. Finally you might run 'make install' as root or simply copy the Then run make. Finally you might run 'make install' as root or simply copy the
'openscad' binary (OpenSCAD.app on Mac OS X) to the bin directory of your choice. 'openscad' binary (OpenSCAD.app on Mac OS X) to the bin directory of your choice.

View file

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

38
c++11.pri Normal file
View file

@ -0,0 +1,38 @@
macx {
# Mac needs special care to link against the correct C++ library
# We attempt to auto-detect it by inspecting Boost
dirs = $${BOOSTDIR} $${QMAKE_LIBDIR}
for(dir, dirs) {
system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) {
message("Using libc++11")
CONFIG += libc++
}
else {
message("Using libstdc++")
CONFIG += libstdc++
c++11 {
# libc++ is a requirement for using C++11
warning("Disabling C++11 since libstdc++ dependencies were found")
CONFIG -= c++11
}
}
}
libc++ {
QMAKE_CXXFLAGS += -stdlib=libc++
QMAKE_LFLAGS += -stdlib=libc++
QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++
# libc++ on requires Mac OS X 10.7+
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
}
}
c++11 {
QMAKE_CXXFLAGS += -std=c++11
message("Using C++11")
}
else {
*clang* {
QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions
}
}

View file

@ -10,7 +10,7 @@ cgal {
message("CGAL location: $$CGAL_DIR") message("CGAL location: $$CGAL_DIR")
} }
CONFIG(mingw-cross-env) { CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
LIBS += -lgmp -lmpfr -lCGAL LIBS += -lgmp -lmpfr -lCGAL
QMAKE_CXXFLAGS += -frounding-math QMAKE_CXXFLAGS += -frounding-math
} else { } 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 "export.h"
#include "polyset.h" #include "polyset.h"
#include "CGAL_Nef_polyhedron.h" #include "CGAL_Nef_polyhedron.h"
#include "boosty.h"
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
using namespace CGALUtils; using namespace CGALUtils;
@ -16,6 +19,7 @@ using namespace CGALUtils;
typedef CGAL::Epick K; typedef CGAL::Epick K;
typedef CGAL::Polyhedron_3<K> PolyhedronK; typedef CGAL::Polyhedron_3<K> PolyhedronK;
#include <boost/algorithm/string.hpp>
#include <boost/assign/std/vector.hpp> #include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
using namespace boost::assign; // bring 'operator+=()' into scope using namespace boost::assign; // bring 'operator+=()' into scope
@ -629,21 +633,30 @@ int main(int argc, char *argv[])
OpenSCAD::debug = "decompose"; OpenSCAD::debug = "decompose";
PolySet *ps = NULL; PolySet *ps = NULL;
CGAL_Nef_polyhedron *N = NULL;
if (argc == 2) { if (argc == 2) {
if (!(ps = import_stl(argv[1]))) { std::string filename(argv[1]);
std::cerr << "Error importing STL " << argv[1] << std::endl; std::string suffix = boosty::extension_str(filename);
exit(1); 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 { else {
std::cerr << "Usage: " << argv[0] << " <file.stl> <file.stl>" << std::endl; std::cerr << "Usage: " << argv[0] << " <file.stl> <file.stl>" << std::endl;
exit(1); exit(1);
} }
Geometry::ChildList children; if (ps && !N) N = createNefPolyhedronFromGeometry(*ps);
CGAL_Nef_polyhedron *N = createNefPolyhedronFromGeometry(*ps);
std::vector<PolyhedronK> result; std::vector<PolyhedronK> result;
decompose(N->p3.get(), std::back_inserter(result)); decompose(N->p3.get(), std::back_inserter(result));

View file

@ -4,7 +4,7 @@ debug: DEFINES += DEBUG
TEMPLATE = app TEMPLATE = app
INCLUDEPATH += ../src INCLUDEPATH += ../src ../src/libtess2/Include
DEPENDPATH += ../src DEPENDPATH += ../src
# Handle custom library location. # Handle custom library location.
@ -87,22 +87,42 @@ include(../common.pri)
HEADERS += ../src/cgal.h \ HEADERS += ../src/cgal.h \
../src/cgalutils.h \ ../src/cgalutils.h \
../src/linalg.h \ ../src/linalg.h \
../src/grid.h \
../src/polyset.h \ ../src/polyset.h \
../src/polyset-utils.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 \ SOURCES += decompose.cpp \
../src/polygon2d.cc \ ../src/polygon2d.cc \
../src/polygon2d-CGAL.cc \ ../src/polygon2d-CGAL.cc \
../src/CGAL_Nef_polyhedron.cc \ ../src/CGAL_Nef_polyhedron.cc \
../src/CGAL_Nef_polyhedron_DxfData.cc \
../src/cgalutils.cc \ ../src/cgalutils.cc \
../src/cgalutils-applyops.cc \
../src/cgalutils-tess.cc \ ../src/cgalutils-tess.cc \
../src/cgalutils-polyhedron.cc \ ../src/cgalutils-polyhedron.cc \
../src/polyset.cc \ ../src/polyset.cc \
../src/polyset-gl.cc \
../src/GeometryUtils.cc \
../src/svg.cc \ ../src/svg.cc \
../src/grid.cc \
../src/node.cc \ ../src/node.cc \
../src/export.cc \ ../src/export.cc \
../src/polyset-utils.cc \ ../src/polyset-utils.cc \
../src/progress.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 TEMPLATE = app
INCLUDEPATH += ../src INCLUDEPATH += ../src ../src/libtess2/Include
DEPENDPATH += ../src DEPENDPATH += ../src
# Handle custom library location. # Handle custom library location.
@ -87,23 +87,42 @@ include(../common.pri)
HEADERS += ../src/cgal.h \ HEADERS += ../src/cgal.h \
../src/cgalutils.h \ ../src/cgalutils.h \
../src/linalg.h \ ../src/linalg.h \
../src/grid.h \
../src/polyset.h \ ../src/polyset.h \
../src/polyset-utils.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 \ SOURCES += export_nef.cpp \
../src/polygon2d.cc \ ../src/polygon2d.cc \
../src/polygon2d-CGAL.cc \ ../src/polygon2d-CGAL.cc \
../src/CGAL_Nef_polyhedron.cc \ ../src/CGAL_Nef_polyhedron.cc \
../src/CGAL_Nef_polyhedron_DxfData.cc \
../src/cgalutils.cc \ ../src/cgalutils.cc \
../src/cgalutils-applyops.cc \
../src/cgalutils-tess.cc \ ../src/cgalutils-tess.cc \
../src/cgalutils-polyhedron.cc \ ../src/cgalutils-polyhedron.cc \
../src/polyset.cc \ ../src/polyset.cc \
../src/polyset-gl.cc \
../src/GeometryUtils.cc \
../src/svg.cc \ ../src/svg.cc \
../src/grid.cc \
../src/node.cc \ ../src/node.cc \
../src/export.cc \ ../src/export.cc \
../src/polyset-utils.cc \ ../src/polyset-utils.cc \
../src/progress.cc \ ../src/progress.cc \
../src/printutils.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

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#333333", "background" : "#333333",
"axes-color" : "#c1c1c1",
"opencsg-face-front" : "#cccccc", "opencsg-face-front" : "#cccccc",
"opencsg-face-back" : "#5563dd", "opencsg-face-back" : "#5563dd",
"cgal-face-front" : "#cccccc", "cgal-face-front" : "#cccccc",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#333333", "background" : "#333333",
"axes-color" : "#c1c1c1",
"opencsg-face-front" : "#eeeeee", "opencsg-face-front" : "#eeeeee",
"opencsg-face-back" : "#0babc8", "opencsg-face-back" : "#0babc8",
"cgal-face-front" : "#eeeeee", "cgal-face-front" : "#eeeeee",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#aaaaff", "background" : "#aaaaff",
"axes-color" : "#222233",
"opencsg-face-front" : "#ddddff", "opencsg-face-front" : "#ddddff",
"opencsg-face-back" : "#dd22dd", "opencsg-face-back" : "#dd22dd",
"cgal-face-front" : "#ddddff", "cgal-face-front" : "#ddddff",

View file

@ -6,6 +6,7 @@
"colors" : { "colors" : {
"background" : "#ffffe5", "background" : "#ffffe5",
"axes-color" : "#191916",
"opencsg-face-front" : "#f9d72c", "opencsg-face-front" : "#f9d72c",
"opencsg-face-back" : "#f9d72c", "opencsg-face-back" : "#f9d72c",
"cgal-face-front" : "#f9d72c", "cgal-face-front" : "#f9d72c",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#fafafa", "background" : "#fafafa",
"axes-color" : "#323232",
"opencsg-face-front" : "#16a085", "opencsg-face-front" : "#16a085",
"opencsg-face-back" : "#dbf4da", "opencsg-face-back" : "#dbf4da",
"cgal-face-front" : "#16a085", "cgal-face-front" : "#16a085",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#fdf6e3", "background" : "#fdf6e3",
"axes-color" : "#191816",
"opencsg-face-front" : "#b58800", "opencsg-face-front" : "#b58800",
"opencsg-face-back" : "#882233", "opencsg-face-back" : "#882233",
"cgal-face-front" : "#b58800", "cgal-face-front" : "#b58800",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#000000", "background" : "#000000",
"axes-color" : "#e5e5e5",
"opencsg-face-front" : "#ffffe0", "opencsg-face-front" : "#ffffe0",
"opencsg-face-back" : "#00ffff", "opencsg-face-back" : "#00ffff",
"cgal-face-front" : "#ffffe0", "cgal-face-front" : "#ffffe0",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#aa4444", "background" : "#aa4444",
"axes-color" : "#220d0d",
"opencsg-face-front" : "#ffaaaa", "opencsg-face-front" : "#ffaaaa",
"opencsg-face-back" : "#882233", "opencsg-face-back" : "#882233",
"cgal-face-front" : "#ffaaaa", "cgal-face-front" : "#ffaaaa",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#1d1f21", "background" : "#1d1f21",
"axes-color" : "#e8e8e8",
"opencsg-face-front" : "#81a2be", "opencsg-face-front" : "#81a2be",
"opencsg-face-back" : "#de935f", "opencsg-face-back" : "#de935f",
"cgal-face-front" : "#8abeb7", "cgal-face-front" : "#8abeb7",

View file

@ -5,6 +5,7 @@
"colors" : { "colors" : {
"background" : "#f8f8f8", "background" : "#f8f8f8",
"axes-color" : "#181818",
"opencsg-face-front" : "#4271ae", "opencsg-face-front" : "#4271ae",
"opencsg-face-back" : "#f5871f", "opencsg-face-back" : "#f5871f",
"cgal-face-front" : "#3e999f", "cgal-face-front" : "#3e999f",

View file

@ -18,3 +18,4 @@ include(harfbuzz.pri)
include(freetype.pri) include(freetype.pri)
include(fontconfig.pri) include(fontconfig.pri)
include(scintilla.pri) include(scintilla.pri)
include(c++11.pri)

9
contrib/appdata.its Normal file
View file

@ -0,0 +1,9 @@
<!-- Copyright 2013 Richard Hughes <richard@hughsie.com> -->
<its:rules
xmlns:its="http://www.w3.org/2005/11/its"
version="1.0">
<its:translateRule translate="no" selector="/component"/>
<its:translateRule translate="yes"
selector="/component/summary |
/component/description"/>
</its:rules>

View file

@ -1,9 +1,9 @@
;;; scad-mode.el --- Major mode for editing SCAD files ;;; scad-mode.el --- A major mode for editing OpenSCAD code
;; Author: Len Trigg ;; Author: Len Trigg, Łukasz Stelmach
;; Maintainer: Len Trigg <lenbok@gmail.com> ;; Maintainer: Len Trigg <lenbok@gmail.com>
;; Created: March 2010 ;; Created: March 2010
;; Modified: 24 May 2014 ;; Modified: 28 Mar 2015
;; Keywords: languages ;; Keywords: languages
;; URL: https://raw.github.com/openscad/openscad/master/contrib/scad-mode.el ;; URL: https://raw.github.com/openscad/openscad/master/contrib/scad-mode.el
;; Version: 91.0 ;; Version: 91.0
@ -26,11 +26,11 @@
;;; Commentary: ;;; Commentary:
;; ;;
;; This is a major-mode to implement the SCAD constructs and ;; This is a major-mode to implement the SCAD constructs and
;; font-locking for openscad ;; font-locking for OpenSCAD
;; ;;
;; If installing manually, insert the following into your emacs startup: ;; If installing manually, insert the following into your emacs startup:
;; ;;
;; (autoload 'scad-mode "scad-mode" "Major mode for editing SCAD code." t) ;; (autoload 'scad-mode "scad-mode" "A major mode for editing OpenSCAD code." t)
;; (add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode)) ;; (add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode))
;; ;;
;; or ;; or
@ -48,6 +48,8 @@
;;;###autoload ;;;###autoload
(add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode)) (add-to-list 'auto-mode-alist '("\\.scad$" . scad-mode))
(require 'cc-mode)
(defcustom scad-command (defcustom scad-command
'"openscad" '"openscad"
"Path to openscad executable" "Path to openscad executable"
@ -68,30 +70,41 @@
"str" "str"
"lookup" "version" "version_num" "len" "search" "lookup" "version" "version_num" "len" "search"
"dxf_dim" "dxf_cross" ;;dxfdim.cc "dxf_dim" "dxf_cross" ;;dxfdim.cc
"norm" "cross" ;;2014.03
"concat" "chr" ;;2015.03
) )
"SCAD functions." "SCAD functions."
:type 'list :type 'list
:group 'scad-font-lock) :group 'scad-font-lock)
(defcustom scad-modules (defcustom scad-modules
'("child" "children" "echo" "assign" "for" "intersection_for" "if" "else" ;;control.cc '("children" "echo" "for" "intersection_for" "if" "else" ;;control.cc
"cube" "sphere" "cylinder" "polyhedron" "square" "circle" "polygon" ;;primitives.cc "cube" "sphere" "cylinder" "polyhedron" "square" "circle" "polygon" ;;primitives.cc
"scale" "rotate" "translate" "mirror" "multmatrix" ;;transform.cc "scale" "rotate" "translate" "mirror" "multmatrix" ;;transform.cc
"union" "difference" "intersection" ;;csgops.cc "union" "difference" "intersection" ;;csgops.cc
"render" ;;render.cc "render" ;;render.cc
"color" ;;color.cc "color" ;;color.cc
"surface" ;;surface.cc "surface" ;;surface.cc
"dxf_linear_extrude" "linear_extrude" ;;linearextrude.cc "linear_extrude" ;;linearextrude.cc
"dxf_rotate_extrude" "rotate_extrude" ;;rotateextrude.cc "rotate_extrude" ;;rotateextrude.cc
"import_stl" "import_off" "import_dxf" "import" ;;import.cc "import" ;;import.cc
"group" ;;builtin.cc "group" ;;builtin.cc
"projection" ;;projection.cc "projection" ;;projection.cc
"minkowski" "glide" "subdiv" "hull" "resize" ;;cgaladv.cc "minkowski" "glide" "subdiv" "hull" "resize" ;;cgaladv.cc
"parent_module" ;;2014.03
"let" "offset" "text" ;;2015.03
) )
"SCAD modules." "SCAD modules."
:type 'list :type 'list
:group 'scad-font-lock) :group 'scad-font-lock)
(defcustom scad-deprecated
'("child" "assign" "dxf_linear_extrude" "dxf_rotate_extrude"
"import_stl" "import_off" "import_dxf")
"SCAD deprecated modules and functions."
:type 'list
:group 'scad-font-lock)
(defcustom scad-operators (defcustom scad-operators
'("+" "-" "*" "/" "%" '("+" "-" "*" "/" "%"
"&&" "||" "!" "&&" "||" "!"
@ -103,9 +116,9 @@
(defvar scad-mode-map (defvar scad-mode-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map "\t" 'scad-indent-line)
(define-key map [(control c) (control o)] 'scad-open-current-buffer) (define-key map [(control c) (control o)] 'scad-open-current-buffer)
(define-key map [return] 'newline-and-indent) (define-key map [return] 'newline-and-indent)
;;(define-key map [(control c) (control s)] 'c-show-syntactic-information) ;; Debugging info
map) map)
"Keymap for `scad-mode'.") "Keymap for `scad-mode'.")
@ -138,6 +151,7 @@
(defvar scad-keywords-regexp (regexp-opt scad-keywords 'words)) (defvar scad-keywords-regexp (regexp-opt scad-keywords 'words))
(defvar scad-modules-regexp (regexp-opt scad-modules 'words)) (defvar scad-modules-regexp (regexp-opt scad-modules 'words))
(defvar scad-functions-regexp (regexp-opt scad-functions 'words)) (defvar scad-functions-regexp (regexp-opt scad-functions 'words))
(defvar scad-deprecated-regexp (regexp-opt scad-deprecated 'words))
(defvar scad-operators-regexp (regexp-opt scad-operators)) (defvar scad-operators-regexp (regexp-opt scad-operators))
(defvar scad-font-lock-keywords (defvar scad-font-lock-keywords
@ -149,30 +163,41 @@
(,scad-keywords-regexp . font-lock-keyword-face) (,scad-keywords-regexp . font-lock-keyword-face)
(,scad-modules-regexp . font-lock-builtin-face) (,scad-modules-regexp . font-lock-builtin-face)
(,scad-functions-regexp . font-lock-function-name-face) (,scad-functions-regexp . font-lock-function-name-face)
(,scad-deprecated-regexp . font-lock-warning-face)
;(,scad-operators-regexp . font-lock-operator-face) ;; This actually looks pretty ugly ;(,scad-operators-regexp . font-lock-operator-face) ;; This actually looks pretty ugly
;("\\(\\<\\S +\\>\\)\\s *(" 1 font-lock-function-name-face t) ;; Seems to override other stuff (e.g. in comments and builtins) ;("\\(\\<\\S +\\>\\)\\s *(" 1 font-lock-function-name-face t) ;; Seems to override other stuff (e.g. in comments and builtins)
) )
"Keyword highlighting specification for `scad-mode'.") "Keyword highlighting specification for `scad-mode'.")
(defconst scad-font-lock-keywords-1 scad-font-lock-keywords)
(defconst scad-font-lock-keywords-2 scad-font-lock-keywords)
(defconst scad-font-lock-keywords-3 scad-font-lock-keywords)
;(defvar scad-imenu-generic-expression ...) (defvar scad-indent-style nil
;(defvar scad-outline-regexp ...) "The style of indentation for scad-mode. Defaults to \"k&r\" if
nil. If you want to set the style with file local variables use
the `c-file-style' variable")
(put 'scad-mode 'c-mode-prefix "scad-")
;;;###autoload ;;;###autoload
(define-derived-mode scad-mode fundamental-mode "SCAD" (define-derived-mode scad-mode prog-mode "SCAD"
"A major mode for editing SCAD files." "Major mode for editing OpenSCAD code.
:syntax-table scad-mode-syntax-table
(set (make-local-variable 'font-lock-defaults) '(scad-font-lock-keywords))
(set (make-local-variable 'indent-line-function) 'scad-indent-line)
;(set (make-local-variable 'imenu-generic-expression) scad-imenu-generic-expression)
;(set (make-local-variable 'outline-regexp) scad-outline-regexp)
;; set comment styles for scad mode
(set (make-local-variable 'comment-start) "//")
(set (make-local-variable 'comment-end) "")
(set (make-local-variable 'block-comment-start) "/*")
(set (make-local-variable 'block-comment-end) "*/")
) To see what version of CC Mode you are running, enter `\\[c-version]'.
The hook `c-mode-common-hook' is run with no args at mode
initialization, then `scad-mode-hook'.
Key bindings:
\\{scad-mode-map}"
(c-initialize-cc-mode)
;; (setq local-abbrev-table scad-mode-abbrev-table
;; abbrev-mode t)
(use-local-map scad-mode-map)
(c-set-offset (quote cpp-macro) 0 nil)
(c-basic-common-init 'scad-mode (or scad-indent-style "k&r"))
(c-font-lock-init)
(c-run-mode-hooks 'c-mode-common-hook 'scad-mode-hook)
(c-update-modeline))
;; From: http://stackoverflow.com/questions/14520073/add-words-for-dynamic-expansion-to-emacs-mode ;; From: http://stackoverflow.com/questions/14520073/add-words-for-dynamic-expansion-to-emacs-mode
(defun scad-prime-dabbrev () (defun scad-prime-dabbrev ()
@ -181,66 +206,9 @@
(with-current-buffer (get-buffer-create " *scad words*") (with-current-buffer (get-buffer-create " *scad words*")
(scad-mode) (scad-mode)
(insert "module function use include") ; Explicitly add these -- they're not in the below vars (insert "module function use include") ; Explicitly add these -- they're not in the below vars
(insert (mapconcat 'identity (append scad-keywords scad-functions scad-modules) " "))))) (insert (mapconcat 'identity (append scad-keywords scad-functions scad-modules scad-deprecated) " ")))))
(add-hook 'scad-mode-hook 'scad-prime-dabbrev) (add-hook 'scad-mode-hook 'scad-prime-dabbrev)
;;; Indentation, based on http://www.emacswiki.org/emacs/download/actionscript-mode-haas-7.0.el
(defun scad-indent-line ()
"Indent current line of SCAD code."
(interactive)
(let ((savep (> (current-column) (current-indentation)))
(indent (max (scad-calculate-indentation) 0)))
(if savep
(save-excursion (indent-line-to indent))
(indent-line-to indent))))
(defun scad-calculate-indentation ()
"Return the column to which the current line should be indented."
(save-excursion
(scad-maybe-skip-leading-close-delim)
(let ((pos (point)))
(beginning-of-line)
(if (not (search-backward-regexp "[^\n\t\r ]" 1 0))
0
(progn
(scad-maybe-skip-leading-close-delim)
(+ (current-indentation) (* standard-indent (scad-count-scope-depth (point) pos))))))))
(defun scad-maybe-skip-leading-close-delim ()
(beginning-of-line)
(forward-to-indentation 0)
(if (looking-at "\\s)")
(forward-char)
(beginning-of-line)))
(defun scad-face-at-point (pos)
"Return face descriptor for char at point."
(plist-get (text-properties-at pos) 'face))
(defun scad-count-scope-depth (rstart rend)
"Return difference between open and close scope delimeters."
(save-excursion
(goto-char rstart)
(let ((open-count 0)
(close-count 0)
opoint)
(while (and (< (point) rend)
(progn (setq opoint (point))
(re-search-forward "\\s)\\|\\s(" rend t)))
(if (= opoint (point))
(forward-char 1)
(cond
;; Don't count if in string or comment.
((scad-face-at-point (- (point) 1)))
((looking-back "\\s)")
(setq close-count (+ close-count 1)))
((looking-back "\\s(")
(setq open-count (+ open-count 1)))
)))
(- open-count close-count))))
(defun scad-open-current-buffer () (defun scad-open-current-buffer ()
(interactive) (interactive)
(call-process scad-command nil 0 nil (buffer-file-name))) (call-process scad-command nil 0 nil (buffer-file-name)))

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 If exporting an image, specify whether to use orthographic or perspective
projection projection
.TP .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. 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 .TP
.B \-v, \-\-version .B \-v, \-\-version
Show version of program. Show version of program.

View file

@ -1,7 +1,6 @@
Given: Given a version, e.g. 2015.03, and a patchlevel release, e.g. 2015.03-1
VERSION (e.g. 2015.03-1)
o Make sure we have a $VERSION branch. If not, create one o Make sure we have an "openscad-$VERSION-branch" branch. If not, create one
o Update VERSION and VERSIONDATE in o Update VERSION and VERSIONDATE in
openscad.pro openscad.pro

View file

@ -50,6 +50,7 @@ files.
$ make clean && qmake && make $ make clean && qmake && make
Then run the script to scan the source files, and regenerate .pot & .po files. Then run the script to scan the source files, and regenerate .pot & .po files.
You'll need itstool (http://itstool.org/) installed.
$ ./scripts/translation-update.sh $ ./scripts/translation-update.sh

View file

@ -11,11 +11,13 @@ y_shift=thisFont[0][1];
hours=["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"]; hours=["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"];
module clock_hour_words(word_offset=20.0,word_height=2.0) { module clock_hour_words(word_offset=20.0,word_height=2.0) {
for(i=[0:(len(hours)-1)]) assign( hourHandAngle=(i+1)*360/len(hours), theseIndicies=search(hours[i],thisFont[2],1,1) ) { for(i=[0:(len(hours)-1)]) {
hourHandAngle=(i+1)*360/len(hours);
theseIndicies=search(hours[i],thisFont[2],1,1);
rotate(90-hourHandAngle) translate([word_offset,0]) rotate(90-hourHandAngle) translate([word_offset,0])
for( j=[0:(len(theseIndicies)-1)] ) translate([j*x_shift,-y_shift/2]) { for( j=[0:(len(theseIndicies)-1)] ) translate([j*x_shift,-y_shift/2]) {
linear_extrude(height=word_height) polygon(points=thisFont[2][theseIndicies[j]][6][0],paths=thisFont[2][theseIndicies[j]][6][1]); linear_extrude(height=word_height) polygon(points=thisFont[2][theseIndicies[j]][6][0],paths=thisFont[2][theseIndicies[j]][6][1]);
} }
} }
} }

View file

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

View file

@ -40,7 +40,7 @@ isEmpty(GLIB2_LIBPATH) {
GLIB2_LIBS = -L$$GLIB2_LIBPATH -lglib-2.0 GLIB2_LIBS = -L$$GLIB2_LIBPATH -lglib-2.0
} }
CONFIG(mingw-cross-env) { CONFIG(mingw-cross-env)|CONFIG(mingw-cross-env-shared) {
#message("mingw") #message("mingw")
isEmpty(GLIB2_INCLUDEPATH) { isEmpty(GLIB2_INCLUDEPATH) {
MXE_TARGET_DIR=$$(MXETARGETDIR) 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 Exec=openscad %f
MimeType=application/x-openscad; MimeType=application/x-openscad;
Categories=Graphics;3DGraphics;Engineering; 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" msgstr "Velikost PolySet cache"
#: objects/ui_Preferences.h:1158 #: 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ů" msgstr "Povolit současné otevření více dokumentů"
#: objects/ui_Preferences.h:1159 #: objects/ui_Preferences.h:1159
@ -1086,7 +1086,7 @@ msgstr[2] "Kompilace vyvolala %1 varování."
#: src/mainwin.cc:990 #: src/mainwin.cc:990
msgid " For details see <a href=\"#console\">console window</a>." msgid " For details see <a href=\"#console\">console window</a>."
msgstr "Pro podrobnosti nahlédněte do <a href=\"#console\">konzole</a>." msgstr " Pro podrobnosti nahlédněte do <a href=\"#console\">konzole</a>."
#: src/mainwin.cc:1355 #: src/mainwin.cc:1355
msgid "Save File" msgid "Save File"

View file

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

View file

@ -993,7 +993,7 @@ msgid "PolySet Cache size"
msgstr "Tamaño de cache de PolySet" msgstr "Tamaño de cache de PolySet"
#: objects/ui_Preferences.h:1159 #: objects/ui_Preferences.h:1159
msgid "Allow to open multiple documents" msgid "Allow opening multiple documents"
msgstr "Permitir a abrir varios documentos" msgstr "Permitir a abrir varios documentos"
#: objects/ui_Preferences.h:1160 #: objects/ui_Preferences.h:1160

View file

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

View file

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

View file

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

View file

@ -1,4 +1,6 @@
# cross compilation unix->win32 # 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) { CONFIG(mingw-cross-env) {
LIBS += mingw-cross-env/lib/libglew32s.a LIBS += mingw-cross-env/lib/libglew32s.a
LIBS += mingw-cross-env/lib/libglut.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/libexpat.a
LIBS += mingw-cross-env/lib/libintl.a LIBS += mingw-cross-env/lib/libintl.a
LIBS += mingw-cross-env/lib/libiconv.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 QMAKE_CXXFLAGS += -fpermissive
WINSTACKSIZE = 8388608 # 8MB # github issue 116 WINSTACKSIZE = 8388608 # 8MB # github issue 116
QMAKE_CXXFLAGS += -Wl,--stack,$$WINSTACKSIZE QMAKE_CXXFLAGS += -Wl,--stack,$$WINSTACKSIZE

View file

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

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<application> <component type="desktop">
<id type="desktop">openscad.desktop</id> <id>openscad.desktop</id>
<licence>CC0</licence> <metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+ and CC0-1.0</project_license>
<name>OpenSCAD</name>
<summary>The Programmers Solid 3D CAD Modeller</summary> <summary>The Programmers Solid 3D CAD Modeller</summary>
<description> <description>
<p>OpenSCAD is a software for creating solid 3D CAD models. Unlike most free software for creating 3D models (such as Blender) it does not focus on the artistic aspects of 3D modelling but instead on the CAD aspects. Thus it might be the application you are looking for when you are planning to create 3D models of machine parts but pretty sure is not what you are looking for when you are more interested in creating computer-animated movies.</p> <p>OpenSCAD is a software for creating solid 3D CAD models. Unlike most free software for creating 3D models (such as Blender) it does not focus on the artistic aspects of 3D modelling but instead on the CAD aspects. Thus it might be the application you are looking for when you are planning to create 3D models of machine parts but pretty sure is not what you are looking for when you are more interested in creating computer-animated movies.</p>
@ -9,8 +11,12 @@
<p>OpenSCAD provides two main modelling techniques: First there is constructive solid geometry (aka CSG) and second there is extrusion of 2D outlines. As data exchange format format for this 2D outlines Autocad DXF files are used. In addition to 2D paths for extrusion it is also possible to read design parameters from DXF files. Besides DXF files OpenSCAD can read and create 3D models in the STL and OFF file formats.</p> <p>OpenSCAD provides two main modelling techniques: First there is constructive solid geometry (aka CSG) and second there is extrusion of 2D outlines. As data exchange format format for this 2D outlines Autocad DXF files are used. In addition to 2D paths for extrusion it is also possible to read design parameters from DXF files. Besides DXF files OpenSCAD can read and create 3D models in the STL and OFF file formats.</p>
</description> </description>
<screenshots> <screenshots>
<screenshot type="default" width="800" height="437">http://www.openscad.org/images/appdata-screenshot-1.png</screenshot> <screenshot type="default">
<screenshot width="800" height="465">http://www.openscad.org/images/appdata-screenshot-2.png</screenshot> <image>http://www.openscad.org/images/appdata-screenshot-1.png</image>
</screenshot>
<screenshot>
<image>http://www.openscad.org/images/appdata-screenshot-2.png</image>
</screenshot>
</screenshots> </screenshots>
<url type="homepage">http://www.openscad.org/</url> <url type="homepage">http://www.openscad.org/</url>
</application> </component>

View file

@ -100,26 +100,9 @@ macx {
APP_RESOURCES.files = OpenSCAD.sdef dsa_pub.pem icons/SCAD.icns APP_RESOURCES.files = OpenSCAD.sdef dsa_pub.pem icons/SCAD.icns
QMAKE_BUNDLE_DATA += APP_RESOURCES QMAKE_BUNDLE_DATA += APP_RESOURCES
LIBS += -framework Cocoa -framework ApplicationServices LIBS += -framework Cocoa -framework ApplicationServices
# Mac needs special care to link against the correct C++ library
# We attempt to auto-detect it by inspecting Boost
dirs = $${BOOSTDIR} $${QMAKE_LIBDIR}
for(dir, dirs) {
system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) {
message("Detected libc++-linked boost in $${dir}")
CONFIG += libc++
}
}
libc++ {
QMAKE_CXXFLAGS += -stdlib=libc++
QMAKE_LFLAGS += -stdlib=libc++
QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++
# libc++ on requires Mac OS X 10.7+
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
}
} }
win* { win* {
RC_FILE = openscad_win32.rc RC_FILE = openscad_win32.rc
QMAKE_CXXFLAGS += -DNOGDI QMAKE_CXXFLAGS += -DNOGDI
@ -147,7 +130,6 @@ netbsd* {
QMAKE_LFLAGS += -L/usr/X11R7/lib QMAKE_LFLAGS += -L/usr/X11R7/lib
QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib
QMAKE_LFLAGS += -Wl,-R/usr/pkg/lib QMAKE_LFLAGS += -Wl,-R/usr/pkg/lib
!clang: { QMAKE_CXXFLAGS += -std=c++0x }
# FIXME: Can the lines below be removed in favour of the OPENSCAD_LIBDIR handling above? # FIXME: Can the lines below be removed in favour of the OPENSCAD_LIBDIR handling above?
!isEmpty(OPENSCAD_LIBDIR) { !isEmpty(OPENSCAD_LIBDIR) {
QMAKE_CFLAGS = -I$$OPENSCAD_LIBDIR/include $$QMAKE_CFLAGS QMAKE_CFLAGS = -I$$OPENSCAD_LIBDIR/include $$QMAKE_CFLAGS
@ -181,7 +163,6 @@ netbsd* {
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function
QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions
# gettext # gettext
QMAKE_CXXFLAGS_WARN_ON += -Wno-format-security QMAKE_CXXFLAGS_WARN_ON += -Wno-format-security
# might want to actually turn this on once in a while # might want to actually turn this on once in a while
@ -195,8 +176,10 @@ CONFIG(skip-version-check) {
# Application configuration # Application configuration
macx:CONFIG += mdi macx:CONFIG += mdi
#CONFIG += c++11
CONFIG += cgal CONFIG += cgal
CONFIG += opencsg CONFIG += opencsg
CONFIG += glew
CONFIG += boost CONFIG += boost
CONFIG += eigen CONFIG += eigen
CONFIG += glib-2.0 CONFIG += glib-2.0
@ -206,13 +189,19 @@ CONFIG += fontconfig
CONFIG += gettext CONFIG += gettext
#Uncomment the following line to enable the QScintilla editor #Uncomment the following line to enable the QScintilla editor
CONFIG += scintilla !nogui {
CONFIG += scintilla
}
# Make experimental features available # Make experimental features available
experimental { experimental {
DEFINES += ENABLE_EXPERIMENTAL DEFINES += ENABLE_EXPERIMENTAL
} }
nogui {
DEFINES += OPENSCAD_NOGUI
}
mdi { mdi {
DEFINES += ENABLE_MDI DEFINES += ENABLE_MDI
} }
@ -220,7 +209,7 @@ mdi {
include(common.pri) include(common.pri)
# mingw has to come after other items so OBJECT_DIRS will work properly # 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) include(mingw-cross-env.pri)
} }
@ -374,6 +363,7 @@ SOURCES += src/version_check.cc \
src/polyset-utils.cc \ src/polyset-utils.cc \
src/GeometryUtils.cc \ src/GeometryUtils.cc \
src/polyset.cc \ src/polyset.cc \
src/polyset-gl.cc \
src/csgops.cc \ src/csgops.cc \
src/transform.cc \ src/transform.cc \
src/color.cc \ src/color.cc \
@ -499,6 +489,8 @@ HEADERS += src/cgal.h \
src/Polygon2d-CGAL.h src/Polygon2d-CGAL.h
SOURCES += src/cgalutils.cc \ SOURCES += src/cgalutils.cc \
src/cgalutils-applyops.cc \
src/cgalutils-project.cc \
src/cgalutils-tess.cc \ src/cgalutils-tess.cc \
src/cgalutils-polyhedron.cc \ src/cgalutils-polyhedron.cc \
src/CGALCache.cc \ src/CGALCache.cc \

View file

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

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

@ -10,6 +10,16 @@ INCLUDEPATH += $$[QT_INSTALL_HEADERS]
LIBS += -L$$[QT_INSTALL_LIBS] LIBS += -L$$[QT_INSTALL_LIBS]
QT5LIB=qt5scintilla2
unix:linux* {
FEDORA32LIBS=/usr/lib/libqscintilla2-qt5.so
FEDORA64LIBS=/usr/lib64/libqscintilla2-qt5.so
exists($$FEDORA32LIBS) | exists($$FEDORA64LIBS) {
QT5LIB=qscintilla2-qt5
}
}
CONFIG(debug, debug|release) { CONFIG(debug, debug|release) {
mac: { mac: {
#LIBS += -lqscintilla2_debug #LIBS += -lqscintilla2_debug
@ -19,7 +29,8 @@ CONFIG(debug, debug|release) {
LIBS += -lqscintilla2d LIBS += -lqscintilla2d
} else { } else {
greaterThan(QT_MAJOR_VERSION, 4) { greaterThan(QT_MAJOR_VERSION, 4) {
LIBS += -lqt5scintilla2 message("Using $$QT5LIB as library name")
LIBS += -l$$QT5LIB
} else { } else {
LIBS += -lqscintilla2 LIBS += -lqscintilla2
} }
@ -33,7 +44,8 @@ CONFIG(debug, debug|release) {
LIBS += -lqscintilla2 LIBS += -lqscintilla2
} else { } else {
greaterThan(QT_MAJOR_VERSION, 4) { greaterThan(QT_MAJOR_VERSION, 4) {
LIBS += -lqt5scintilla2 message("Using $$QT5LIB as library name")
LIBS += -l$$QT5LIB
} else { } else {
LIBS += -lqscintilla2 LIBS += -lqscintilla2
} }

View file

@ -120,6 +120,17 @@ check_nsis()
fi 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() get_openscad_source_code()
{ {
if [ -d openscad ]; then if [ -d openscad ]; then
@ -251,7 +262,7 @@ upload_win32()
SUMMARY1="Windows x86-32 Snapshot Installer" SUMMARY1="Windows x86-32 Snapshot Installer"
SUMMARY2="Windows x86-32 Snapshot Zipfile" SUMMARY2="Windows x86-32 Snapshot Zipfile"
SUMMARY3="Windows x86-32 Snapshot Tests" SUMMARY3="Windows x86-32 Snapshot Tests"
BASEDIR=./mingw32/ BASEDIR=./mingw32.static/
WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.exe WIN32_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-32-Installer.exe
WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.zip WIN32_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-32.zip
WIN32_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-32.zip WIN32_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-32.zip
@ -277,7 +288,7 @@ upload_win64()
SUMMARY1="Windows x86-64 Snapshot Zipfile" SUMMARY1="Windows x86-64 Snapshot Zipfile"
SUMMARY2="Windows x86-64 Snapshot Installer" SUMMARY2="Windows x86-64 Snapshot Installer"
SUMMARY3="Windows x86-64 Snapshot Tests" SUMMARY3="Windows x86-64 Snapshot Tests"
BASEDIR=./mingw64/ BASEDIR=./mingw64.static/
WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64-Installer.exe WIN64_PACKAGEFILE1=OpenSCAD-$DATECODE-x86-64-Installer.exe
WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64.zip WIN64_PACKAGEFILE2=OpenSCAD-$DATECODE-x86-64.zip
WIN64_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-64.zip WIN64_PACKAGEFILE3=OpenSCAD-Tests-$DATECODE-x86-64.zip
@ -409,6 +420,7 @@ main()
fi fi
check_starting_path check_starting_path
check_nsis check_nsis
check_zip
read_username_from_user read_username_from_user
read_password_from_user read_password_from_user
get_openscad_source_code get_openscad_source_code

View file

@ -18,7 +18,13 @@ File /r /x mingw-cross-env color-schemes
${registerExtension} "$INSTDIR\openscad.exe" ".scad" "OpenSCAD_File" ${registerExtension} "$INSTDIR\openscad.exe" ".scad" "OpenSCAD_File"
CreateShortCut $SMPROGRAMS\OpenSCAD.lnk $INSTDIR\openscad.exe CreateShortCut $SMPROGRAMS\OpenSCAD.lnk $INSTDIR\openscad.exe
WriteUninstaller $INSTDIR\Uninstall.exe WriteUninstaller $INSTDIR\Uninstall.exe
# see https://msdn.microsoft.com/en-us/library/aa372105(v=vs.85).aspx
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "DisplayName" "OpenSCAD (remove only)" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "DisplayName" "OpenSCAD (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "DisplayVersion" "${VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "Publisher" "The OpenSCAD Developers"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "URLInfoAbout" "http://www.openscad.org/"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "URLUpdateInfo" "http://www.openscad.org/downloads.html"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "HelpLink" "http://forum.openscad.org/"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenSCAD" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegStr HKCR ".scad" "PerceivedType" "text" WriteRegStr HKCR ".scad" "PerceivedType" "text"
SectionEnd SectionEnd

View file

@ -6,7 +6,8 @@
# #
# This script must be run from the OpenSCAD source root directory # This script must be run from the OpenSCAD source root directory
# #
# Usage: macosx-build-dependencies.sh [-6lcd] [<package>] # Usage: macosx-build-dependencies.sh [-16lcdf] [<package>]
# -3 Build using C++03 and libstdc++
# -6 Build only 64-bit binaries # -6 Build only 64-bit binaries
# -l Force use of LLVM compiler # -l Force use of LLVM compiler
# -c Force use of clang compiler # -c Force use of clang compiler
@ -31,36 +32,38 @@ OPTION_CLANG=false
OPTION_GCC=false OPTION_GCC=false
OPTION_DEPLOY=false OPTION_DEPLOY=false
OPTION_FORCE=0 OPTION_FORCE=0
OPTION_CXX11=true
PACKAGES=( PACKAGES=(
"eigen 3.2.4"
"gmp 5.1.3"
"mpfr 3.1.2"
"boost 1.57.0"
"qt5 5.4.1"
"qscintilla 2.8.4"
# NB! For eigen, also update the path in the function # 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.9"
# NB! For CGAL, also update the actual download URL in the function # NB! For CGAL, also update the actual download URL in the function
"cgal 4.5.2" "cgal 4.6.3"
"glew 1.12.0" "glew 1.13.0"
"gettext 0.19.4" "gettext 0.19.6"
"libffi 3.2.1" "libffi 3.2.1"
"glib2 2.42.1" "glib2 2.46.1"
"opencsg 1.4.0" "opencsg 1.4.0"
"freetype 2.5.5" "freetype 2.6.1"
"ragel 6.9" "ragel 6.9"
"harfbuzz 0.9.37" "harfbuzz 1.0.6"
"libxml2 2.9.2" "libxml2 2.9.2"
"fontconfig 2.11.1" "fontconfig 2.11.1"
) )
DEPLOY_PACKAGES=( DEPLOY_PACKAGES=(
"sparkle Cocoanetics:1e7dcb1a48b96d1a8c62100b5864bd50211cbae1" "sparkle 1.11.0"
) )
printUsage() printUsage()
{ {
echo "Usage: $0 [-6lcd] [<package>]" echo "Usage: $0 [-36lcdf] [<package>]"
echo echo
echo " -3 Build using C++03 and libstdc++"
echo " -6 Build only 64-bit binaries" echo " -6 Build only 64-bit binaries"
echo " -l Force use of LLVM compiler" echo " -l Force use of LLVM compiler"
echo " -c Force use of clang compiler" echo " -c Force use of clang compiler"
@ -221,9 +224,13 @@ build_qt5()
fi fi
tar xzf qt-everywhere-opensource-src-$version.tar.gz tar xzf qt-everywhere-opensource-src-$version.tar.gz
cd qt-everywhere-opensource-src-$version cd qt-everywhere-opensource-src-$version
./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 \ -nomake examples -nomake tests \
-no-xcb -no-c++11 -no-glib -no-harfbuzz -no-sql-db2 -no-sql-ibase -no-sql-mysql -no-sql-oci -no-sql-odbc \ -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 \ -no-sql-psql -no-sql-sqlite2 -no-sql-tds -no-cups -no-qml-debug \
-skip activeqt -skip connectivity -skip declarative -skip doc \ -skip activeqt -skip connectivity -skip declarative -skip doc \
-skip enginio -skip graphicaleffects -skip location -skip multimedia \ -skip enginio -skip graphicaleffects -skip location -skip multimedia \
@ -248,7 +255,7 @@ build_qscintilla()
fi fi
tar xzf QScintilla-gpl-$version.tar.gz tar xzf QScintilla-gpl-$version.tar.gz
cd QScintilla-gpl-$version/Qt4Qt5 cd QScintilla-gpl-$version/Qt4Qt5
qmake qscintilla.pro qmake QMAKE_CXXFLAGS+="$CXXSTDFLAGS" QMAKE_LFLAGS+="$CXXSTDFLAGS" qscintilla.pro
make -j6 install make -j6 install
install_name_tool -id $DEPLOYDIR/lib/libqscintilla2.dylib $DEPLOYDIR/lib/libqscintilla2.dylib install_name_tool -id $DEPLOYDIR/lib/libqscintilla2.dylib $DEPLOYDIR/lib/libqscintilla2.dylib
} }
@ -321,7 +328,7 @@ EOF
if $OPTION_32BIT; then if $OPTION_32BIT; then
mkdir build-i386 mkdir build-i386
cd build-i386 cd build-i386
../configure --prefix=$DEPLOYDIR/i386 "CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386" LDFLAGS="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch i386" ABI=32 --enable-cxx ../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 make install
cd .. cd ..
fi fi
@ -329,7 +336,7 @@ EOF
# 64-bit version # 64-bit version
mkdir build-x86_64 mkdir build-x86_64
cd build-x86_64 cd build-x86_64
../configure --prefix=$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" ABI=64 --enable-cxx ../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 make install
# merge # merge
@ -434,7 +441,7 @@ build_boost()
BOOST_TOOLSET="toolset=clang" BOOST_TOOLSET="toolset=clang"
echo "using clang ;" >> tools/build/user-config.jam echo "using clang ;" >> tools/build/user-config.jam
fi fi
./b2 -j"$NUMCPU" -d+2 $BOOST_TOOLSET cflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $BOOST_EXTRA_FLAGS" linkflags="-mmacosx-version-min=$MAC_OSX_VERSION_MIN -arch x86_64 $BOOST_EXTRA_FLAGS -headerpad_max_install_names" install ./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
install_name_tool -id $DEPLOYDIR/lib/libboost_thread.dylib $DEPLOYDIR/lib/libboost_thread.dylib 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_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 install_name_tool -change libboost_chrono.dylib $DEPLOYDIR/lib/libboost_chrono.dylib $DEPLOYDIR/lib/libboost_thread.dylib
@ -460,8 +467,9 @@ build_cgal()
cd $BASEDIR/src cd $BASEDIR/src
rm -rf CGAL-$version rm -rf CGAL-$version
if [ ! -f CGAL-$version.tar.gz ]; then if [ ! -f CGAL-$version.tar.gz ]; then
# 4.5.2 # 4.6.3
curl -O https://gforge.inria.fr/frs/download.php/file/34512/CGAL-$version.tar.gz 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.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.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 # 4.4 curl -O https://gforge.inria.fr/frs/download.php/file/33525/CGAL-$version.tar.gz
@ -480,7 +488,7 @@ build_cgal()
if $OPTION_32BIT; then if $OPTION_32BIT; then
CGAL_EXTRA_FLAGS=";i386" CGAL_EXTRA_FLAGS=";i386"
fi fi
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$CGAL_EXTRA_FLAGS" -DBOOST_ROOT=$DEPLOYDIR -DBoost_USE_MULTITHREADED=false
make -j"$NUMCPU" install make -j"$NUMCPU" install
make install make install
install_name_tool -id $DEPLOYDIR/lib/libCGAL.dylib $DEPLOYDIR/lib/libCGAL.dylib install_name_tool -id $DEPLOYDIR/lib/libCGAL.dylib $DEPLOYDIR/lib/libCGAL.dylib
@ -533,7 +541,7 @@ build_opencsg()
if $OPTION_32BIT; then if $OPTION_32BIT; then
OPENCSG_EXTRA_FLAGS="x86" OPENCSG_EXTRA_FLAGS="x86"
fi fi
qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib" CONFIG+="x86_64 $OPENCSG_EXTRA_FLAGS" DESTDIR=$DEPLOYDIR qmake -r QMAKE_CXXFLAGS+="-I$DEPLOYDIR/include $CXXSTDFLAGS" QMAKE_LFLAGS+="-L$DEPLOYDIR/lib $LDSTDFLAGS" CONFIG+="x86_64 $OPENCSG_EXTRA_FLAGS" DESTDIR=$DEPLOYDIR
make install make install
} }
@ -567,6 +575,7 @@ build_eigen()
elif [ $version = "3.2.2" ]; then EIGENDIR=eigen-eigen-1306d75b4a21; elif [ $version = "3.2.2" ]; then EIGENDIR=eigen-eigen-1306d75b4a21;
elif [ $version = "3.2.3" ]; then EIGENDIR=eigen-eigen-36fd1ba04c12; elif [ $version = "3.2.3" ]; then EIGENDIR=eigen-eigen-36fd1ba04c12;
elif [ $version = "3.2.4" ]; then EIGENDIR=eigen-eigen-10219c95fe65; elif [ $version = "3.2.4" ]; then EIGENDIR=eigen-eigen-10219c95fe65;
elif [ $version = "3.2.6" ]; then EIGENDIR=eigen-eigen-c58038c56923;
fi fi
if [ $EIGENDIR = "none" ]; then if [ $EIGENDIR = "none" ]; then
@ -587,7 +596,7 @@ build_eigen()
if $OPTION_32BIT; then if $OPTION_32BIT; then
EIGEN_EXTRA_FLAGS=";i386" EIGEN_EXTRA_FLAGS=";i386"
fi fi
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$EIGEN_EXTRA_FLAGS" ..
make -j"$NUMCPU" install make -j"$NUMCPU" install
} }
@ -596,35 +605,51 @@ check_sparkle()
check_file lib/Sparkle.framework/Sparkle check_file lib/Sparkle.framework/Sparkle
} }
# Usage: build_sparkle <githubuser>:<commitID> # Usage:
# build_sparkle <githubuser>:<commitID>
# build_sparkle <version>
build_sparkle() build_sparkle()
{ {
v=$1 # Binary install:
github=${1%%:*} # Cut at first colon version=$1
version=${1#*:} # cut until first colon
echo "Building Sparkle" $version "..."
# Let Sparkle use the default compiler
unset CC
unset CXX
cd $BASEDIR/src cd $BASEDIR/src
rm -rf Sparkle-$version rm -rf Sparkle-$version
if [ ! -f Sparkle-$version.zip ]; then if [ ! -f Sparkle-$version.zip ]; then
curl -o Sparkle-$version.zip https://nodeload.github.com/$github/Sparkle/zip/$version curl -LO https://github.com/sparkle-project/Sparkle/releases/download/$version/Sparkle-$version.tar.bz2
fi fi
unzip -q Sparkle-$version.zip mkdir Sparkle-$version
cd Sparkle-$version cd Sparkle-$version
patch -p1 < $OPENSCADDIR/patches/sparkle.patch tar xjf ../Sparkle-$version.tar.bz2
if $OPTION_32BIT; then cp -Rf Sparkle.framework $DEPLOYDIR/lib/
SPARKLE_EXTRA_FLAGS="-arch i386"
fi # Build from source:
xcodebuild clean # v=$1
xcodebuild -arch x86_64 $SPARKLE_EXTRA_FLAGS # github=${1%%:*} # Cut at first colon
rm -rf $DEPLOYDIR/lib/Sparkle.framework # version=${1#*:} # cut until first colon
cp -Rf build/Release/Sparkle.framework $DEPLOYDIR/lib/ #
install_name_tool -id $DEPLOYDIR/lib/Sparkle.framework/Versions/A/Sparkle $DEPLOYDIR/lib/Sparkle.framework/Sparkle # 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
# 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
} }
check_freetype() check_freetype()
@ -815,7 +840,7 @@ build_harfbuzz()
# disable doc directories as they make problems on Mac OS Build # disable doc directories as they make problems on Mac OS Build
sed -e "s/SUBDIRS = src util test docs/SUBDIRS = src util test/g" Makefile.am > Makefile.am.bak && mv Makefile.am.bak Makefile.am sed -e "s/SUBDIRS = src util test docs/SUBDIRS = src util test/g" Makefile.am > Makefile.am.bak && mv Makefile.am.bak Makefile.am
sed -e "s/^docs.*$//" configure.ac > configure.ac.bak && mv configure.ac.bak configure.ac sed -e "s/^docs.*$//" configure.ac > configure.ac.bak && mv configure.ac.bak configure.ac
PKG_CONFIG_LIBDIR="$DEPLOYDIR/lib/pkgconfig" ./autogen.sh --prefix="$DEPLOYDIR" --with-freetype=yes --with-gobject=no --with-cairo=no --with-icu=no CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN CXXFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN $extra_config_flags PKG_CONFIG_LIBDIR="$DEPLOYDIR/lib/pkgconfig" ./autogen.sh --prefix="$DEPLOYDIR" --with-freetype=yes --with-gobject=no --with-cairo=no --with-icu=no CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN CXXFLAGS="$CXXFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN" LDFLAGS="$CXXFLAGS -mmacosx-version-min=$MAC_OSX_VERSION_MIN" $extra_config_flags
make -j$NUMCPU make -j$NUMCPU
make install make install
} }
@ -826,9 +851,10 @@ if [ ! -f $OPENSCADDIR/openscad.pro ]; then
fi fi
OPENSCAD_SCRIPTDIR=$PWD/scripts OPENSCAD_SCRIPTDIR=$PWD/scripts
while getopts '6lcdf' c while getopts '36lcdf' c
do do
case $c in case $c in
3) USING_CXX11=false;;
6) OPTION_32BIT=false;; 6) OPTION_32BIT=false;;
l) OPTION_LLVM=true;; l) OPTION_LLVM=true;;
c) OPTION_CLANG=true;; c) OPTION_CLANG=true;;
@ -841,7 +867,9 @@ done
OPTION_PACKAGES="${@:$OPTIND}" OPTION_PACKAGES="${@:$OPTIND}"
OSX_VERSION=`sw_vers -productVersion | cut -d. -f2` 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" echo "Detected Yosemite (10.10) or later"
elif (( $OSX_VERSION >= 9 )); then elif (( $OSX_VERSION >= 9 )); then
echo "Detected Mavericks (10.9)" echo "Detected Mavericks (10.9)"
@ -885,6 +913,14 @@ elif $USING_CLANG; then
export CXX=clang++ export CXX=clang++
fi 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" echo "Building for $MAC_OSX_VERSION_MIN or later"
if [ ! $NUMCPU ]; then if [ ! $NUMCPU ]; then
@ -917,6 +953,7 @@ fi
# Build specified (or all) packages # Build specified (or all) packages
ALL_PACKAGES=$(all_packages) ALL_PACKAGES=$(all_packages)
echo $ALL_PACKAGES
if [ -z "$OPTION_PACKAGES" ]; then if [ -z "$OPTION_PACKAGES" ]; then
OPTION_PACKAGES=$ALL_PACKAGES OPTION_PACKAGES=$ALL_PACKAGES
fi fi

View file

@ -20,6 +20,8 @@ import re
DEBUG = False DEBUG = False
cxxlib = None
def usage(): def usage():
print >> sys.stderr, "Usage: " + sys.argv[0] + " <executable>" print >> sys.stderr, "Usage: " + sys.argv[0] + " <executable>"
sys.exit(1) sys.exit(1)
@ -62,12 +64,17 @@ def find_dependencies(file):
return None return None
deps = output.split('\n') deps = output.split('\n')
for dep in deps: for dep in deps:
#print dep # print dep
# Fail if anything is linked with libc++, as that's not backwards compatible # Fail if libstc++ and libc++ was mixed
# with Mac OS X 10.6 global cxxlib
if re.search("libc\+\+", dep): match = re.search("lib(std)?c\+\+", dep)
print "Error: clang's libc++ is used by " + file if match:
return None if not cxxlib:
cxxlib = match.group(0)
else:
if cxxlib != match.group(0):
print "Error: Mixing libc++ and libstdc++"
return None
dep = re.sub(".*:$", "", dep) # Take away header line dep = re.sub(".*:$", "", dep) # Take away header line
dep = re.sub("^\t", "", dep) # Remove initial tabs dep = re.sub("^\t", "", dep) # Remove initial tabs
dep = re.sub(" \(.*\)$", "", dep) # Remove trailing parentheses dep = re.sub(" \(.*\)$", "", dep) # Remove trailing parentheses

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 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 # Notes:
# which hasnt been merged to official mxe as of writing #
# 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 OPENSCADDIR=$PWD
if [ ! -f $OPENSCADDIR/openscad.pro ]; then if [ ! -f $OPENSCADDIR/openscad.pro ]; then

View file

@ -72,16 +72,17 @@ elif [[ $OSTYPE == "linux-gnu" ]]; then
echo "Detected build-machine ARCH: $ARCH" echo "Detected build-machine ARCH: $ARCH"
fi fi
if [ "`echo $* | grep mingw32`" ]; then if [ "`echo $* | grep mingw`" ]; then
OS=UNIX_CROSS_WIN OS=UNIX_CROSS_WIN
ARCH=32 ARCH=32
echo Mingw-cross build using ARCH=32 MXELIBTYPE=static
fi if [ "`echo $* | grep mingw64`" ]; then
ARCH=64
if [ "`echo $* | grep mingw64`" ]; then fi
OS=UNIX_CROSS_WIN if [ "`echo $* | grep shared`" ]; then
ARCH=64 MXELIBTYPE=shared
echo Mingw-cross build using ARCH=64 fi
echo Mingw-cross build using ARCH=$ARCH MXELIBTYPE=$MXELIBTYPE
fi fi
if [ "`echo $* | grep snapshot`" ]; then if [ "`echo $* | grep snapshot`" ]; then
@ -188,7 +189,7 @@ case $OS in
TARGET=release TARGET=release
;; ;;
UNIX_CROSS_WIN) UNIX_CROSS_WIN)
. ./scripts/setenv-mingw-xbuild.sh $ARCH . ./scripts/setenv-mingw-xbuild.sh $ARCH $MXELIBTYPE
TARGET=release TARGET=release
ZIP="zip" ZIP="zip"
ZIPARGS="-r -q" ZIPARGS="-r -q"
@ -198,7 +199,12 @@ esac
case $OS in case $OS in
UNIX_CROSS_WIN) 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 cd $OPENSCADDIR
;; ;;
*) *)
@ -425,9 +431,78 @@ case $OS in
INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH-Installer.exe INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH-Installer.exe
#package #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" echo "Creating binary zip package"
cp $TARGET/openscad.exe openscad-$VERSION
cp $TARGET/openscad.com openscad-$VERSION
rm -f OpenSCAD-$VERSION.x86-$ARCH.zip rm -f OpenSCAD-$VERSION.x86-$ARCH.zip
"$ZIP" $ZIPARGS $BINFILE openscad-$VERSION "$ZIP" $ZIPARGS $BINFILE openscad-$VERSION
cd $OPENSCADDIR cd $OPENSCADDIR
@ -443,8 +518,8 @@ case $OS in
cd $DEPLOYDIR/openscad-$VERSION cd $DEPLOYDIR/openscad-$VERSION
NSISDEBUG=-V2 NSISDEBUG=-V2
# NSISDEBUG= # leave blank for full log # NSISDEBUG= # leave blank for full log
echo $MAKENSIS $NSISDEBUG installer.nsi echo $MAKENSIS $NSISDEBUG "-DVERSION=$VERSION" installer.nsi
$MAKENSIS $NSISDEBUG installer.nsi $MAKENSIS $NSISDEBUG "-DVERSION=$VERSION" installer.nsi
cp $DEPLOYDIR/openscad-$VERSION/openscad_setup.exe $INSTFILE cp $DEPLOYDIR/openscad-$VERSION/openscad_setup.exe $INSTFILE
cd $OPENSCADDIR cd $OPENSCADDIR
@ -528,7 +603,7 @@ if [ $BUILD_TESTS ]; then
# while copying. # while copying.
rm -f ./ostests.tar rm -f ./ostests.tar
for subdir in tests testdata libraries examples doc; do 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 done
cd $DEPLOYDIR cd $DEPLOYDIR
tar prvf $OPENSCADDIR/ostests.tar --exclude=.git* --exclude=*/mingw* --exclude=*.cc.obj --exclude=*.a $TESTBINDIR tar prvf $OPENSCADDIR/ostests.tar --exclude=.git* --exclude=*/mingw* --exclude=*.cc.obj --exclude=*.a $TESTBINDIR

View file

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

View file

@ -25,6 +25,9 @@ updatepot()
| awk '{ printf "#: examples/examples.json:%d\nmsgid %s\nmsgstr \"\"\n\n", $1, $2 }' \ | awk '{ printf "#: examples/examples.json:%d\nmsgid %s\nmsgstr \"\"\n\n", $1, $2 }' \
> ./locale/json-strings.pot > ./locale/json-strings.pot
# extract strings from appdata file
itstool -o ./locale/appdata-strings.pot ./openscad.appdata.xml.in --its=./contrib/appdata.its
VER=`date +"%Y.%m.%d"` VER=`date +"%Y.%m.%d"`
OPTS= OPTS=
OPTS=$OPTS' --package-name=OpenSCAD' OPTS=$OPTS' --package-name=OpenSCAD'
@ -41,7 +44,7 @@ updatepot()
exit 1 exit 1
fi fi
cmd="${GETTEXT_PATH}msgcat -o ./locale/openscad.pot ./locale/openscad-tmp.pot ./locale/json-strings.pot" cmd="${GETTEXT_PATH}msgcat -o ./locale/openscad.pot ./locale/openscad-tmp.pot ./locale/json-strings.pot ./locale/appdata-strings.pot"
echo $cmd echo $cmd
$cmd $cmd
if [ ! $? = 0 ]; then if [ ! $? = 0 ]; then
@ -50,7 +53,7 @@ updatepot()
fi fi
sed -e s/"CHARSET"/"UTF-8"/g ./locale/openscad.pot > ./locale/openscad.pot.new && mv ./locale/openscad.pot.new ./locale/openscad.pot sed -e s/"CHARSET"/"UTF-8"/g ./locale/openscad.pot > ./locale/openscad.pot.new && mv ./locale/openscad.pot.new ./locale/openscad.pot
rm -f ./locale/json-strings.pot ./locale/openscad-tmp.pot rm -f ./locale/json-strings.pot ./locale/openscad-tmp.pot ./locale/appdata-strings.pot
} }
updatepo() updatepo()
@ -80,6 +83,26 @@ updatemo()
exit 1 exit 1
fi fi
done done
if which itstool > /dev/null 2>&1; then
# ugly workaround for bug https://bugs.freedesktop.org/show_bug.cgi?id=90937
for LANGCODE in `cat locale/LINGUAS | grep -v "#"`; do
ln -s openscad.mo ./locale/$LANGCODE/LC_MESSAGES/$LANGCODE.mo
done
# generate translated appdata file
itstool -j ./openscad.appdata.xml.in -o ./openscad.appdata.xml ./locale/*/LC_MESSAGES/[a-z][a-z].mo
# clean the mess
for LANGCODE in `cat locale/LINGUAS | grep -v "#"`; do
unlink ./locale/$LANGCODE/LC_MESSAGES/$LANGCODE.mo
done
else
if [ x"$(uname -s)" = x"Linux" ]; then
echo "itstool missing, won't apply translations to openscad.appdata.xml"
fi
cp -f ./openscad.appdata.xml.in ./openscad.appdata.xml
fi
} }
GETTEXT_PATH="" GETTEXT_PATH=""

View file

@ -1,5 +1,8 @@
#!/bin/bash #!/bin/bash
qmake CONFIG+=experimental CONFIG+=nogui
make
cd tests cd tests
cmake . cmake .
if [[ $? != 0 ]]; then if [[ $? != 0 ]]; then

View file

@ -79,10 +79,22 @@ check_env()
detect_glu() detect_glu()
{ {
detect_glu_result= detect_glu_result=
if [ -e $DEPLOYDIR/include/GL/glu.h ]; then detect_glu_result=1; fi if [ -e $DEPLOYDIR/include/GL/glu.h ]; then
if [ -e /usr/include/GL/glu.h ]; then detect_glu_result=1; fi detect_glu_include=$DEPLOYDIR/include
if [ -e /usr/local/include/GL/glu.h ]; then detect_glu_result=1; fi detect_glu_result=1;
if [ -e /usr/pkg/X11R7/include/GL/glu.h ]; then detect_glu_result=1; fi fi
if [ -e /usr/include/GL/glu.h ]; then
detect_glu_include=/usr/include
detect_glu_result=1;
fi
if [ -e /usr/local/include/GL/glu.h ]; then
detect_glu_include=/usr/local/include
detect_glu_result=1;
fi
if [ -e /usr/pkg/X11R7/include/GL/glu.h ]; then
detect_glu_include=/usr/pkg/X11R7/include
detect_glu_result=1;
fi
return return
} }
@ -505,10 +517,20 @@ build_opencsg()
cp opencsg.pro opencsg.pro.bak cp opencsg.pro opencsg.pro.bak
cat opencsg.pro.bak | sed s/example// > opencsg.pro cat opencsg.pro.bak | sed s/example// > opencsg.pro
detect_glu
GLU_INCLUDE=$detect_glu_include
if [ ! $detect_glu_result ]; then
build_glu 9.0.0
fi
if [ "`command -v qmake-qt4`" ]; then if [ "`command -v qmake-qt4`" ]; then
OPENCSG_QMAKE=qmake-qt4 OPENCSG_QMAKE=qmake-qt4
elif [ "`command -v qmake4`" ]; then elif [ "`command -v qmake4`" ]; then
OPENCSG_QMAKE=qmake4 OPENCSG_QMAKE=qmake4
elif [ "`command -v qmake-qt5`" ]; then
OPENCSG_QMAKE=qmake-qt5
elif [ "`command -v qmake5`" ]; then
OPENCSG_QMAKE=qmake5
elif [ "`command -v qmake`" ]; then elif [ "`command -v qmake`" ]; then
OPENCSG_QMAKE=qmake OPENCSG_QMAKE=qmake
else else
@ -518,15 +540,18 @@ build_opencsg()
cp src/Makefile src/Makefile.bak cp src/Makefile src/Makefile.bak
cat Makefile.bak | sed s/example// |sed s/glew// > Makefile cat Makefile.bak | sed s/example// |sed s/glew// > Makefile
cat src/Makefile.bak | sed s@^INCPATH.*@INCPATH\ =\ -I$BASEDIR/include\ -I../include\ -I..\ -I.@ > src/Makefile cat src/Makefile.bak | sed s@^INCPATH.*@INCPATH\ =\ -I$BASEDIR/include\ -I../include\ -I..\ -I$GLU_INCLUDE -I.@ > src/Makefile
cp src/Makefile src/Makefile.bak2 cp src/Makefile src/Makefile.bak2
cat src/Makefile.bak2 | sed s@^LIBS.*@LIBS\ =\ -L$BASEDIR/lib\ -L/usr/X11R6/lib\ -lGLU\ -lGL@ > src/Makefile cat src/Makefile.bak2 | sed s@^LIBS.*@LIBS\ =\ -L$BASEDIR/lib\ -L/usr/X11R6/lib\ -lGLU\ -lGL@ > src/Makefile
tmp=$version tmp=$version
detect_glu
if [ ! $detect_glu_result ]; then build_glu 9.0.0 ; fi
version=$tmp version=$tmp
fi fi
if [ ! $OPENCSG_QMAKE = "make" ]; then
OPENCSG_QMAKE=$OPENCSG_QMAKE' "QMAKE_CXXFLAGS+=-I'$GLU_INCLUDE'"'
fi
echo OPENCSG_QMAKE: $OPENCSG_QMAKE
cd $BASEDIR/src/OpenCSG-$version/src cd $BASEDIR/src/OpenCSG-$version/src
$OPENCSG_QMAKE $OPENCSG_QMAKE
@ -776,6 +801,11 @@ if [ $1 ]; then
build_gettext 0.18.3.1 build_gettext 0.18.3.1
exit $? exit $?
fi fi
if [ $1 = "harfbuzz" ]; then
# debian 7 lacks only harfbuzz
build_harfbuzz 0.9.23 --with-glib=yes
exit $?
fi
if [ $1 = "glib2" ]; then if [ $1 = "glib2" ]; then
# such a huge build, put here by itself # such a huge build, put here by itself
build_pkgconfig 0.28 build_pkgconfig 0.28

View file

@ -4,13 +4,24 @@
# this assumes you have sudo installed and running, or are running as root. # this assumes you have sudo installed and running, or are running as root.
# #
get_fedora_deps() get_fedora_deps_yum()
{ {
yum -y install qt5-qtbase-devel bison flex eigen3-devel harfbuzz-devel \ yum -y install qt5-qtbase-devel bison flex eigen3-devel harfbuzz-devel \
fontconfig-devel freetype-devel \ fontconfig-devel freetype-devel \
boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc gcc-c++ pkgconfig \ boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc gcc-c++ pkgconfig \
opencsg-devel git libXmu-devel curl imagemagick ImageMagick glib2-devel make \ opencsg-devel git libXmu-devel curl imagemagick ImageMagick glib2-devel make \
xorg-x11-server-Xvfb gettext xorg-x11-server-Xvfb gettext qscintilla-devel qscintilla-qt5-devel \
mesa-dri-drivers
}
get_fedora_deps_dnf()
{
dnf -y install qt5-qtbase-devel bison flex eigen3-devel harfbuzz-devel \
fontconfig-devel freetype-devel \
boost-devel mpfr-devel gmp-devel glew-devel CGAL-devel gcc gcc-c++ pkgconfig \
opencsg-devel git libXmu-devel curl ImageMagick glib2-devel make \
xorg-x11-server-Xvfb gettext qscintilla-devel qscintilla-qt5-devel \
mesa-dri-drivers
} }
get_qomo_deps() get_qomo_deps()
@ -43,8 +54,13 @@ get_netbsd_deps()
get_opensuse_deps() get_opensuse_deps()
{ {
zypper install libeigen3-devel mpfr-devel gmp-devel boost-devel \ zypper install libeigen3-devel mpfr-devel gmp-devel boost-devel \
libqt4-devel glew-devel cmake git bison flex cgal-devel opencsg-devel curl \ libqt4-devel glew-devel cmake git bison flex cgal-devel curl \
glib2-devel gettext glib2-devel gettext freetype-devel harfbuzz-devel libqscintilla-devel \
xvfb-run imagemagick opencsg-devel
echo if you are missing opencsg, please add the -graphics- repository
echo find your version from cat /etc/issue, then replace it below, then run
echo " zypper ar -f http://download.opensuse.org/repositories/graphics/openSUSE_13.2 graphics"
echo " zypper install opencsg-devel"
} }
get_mageia_deps() get_mageia_deps()
@ -58,12 +74,34 @@ get_mageia_deps()
get_debian_deps() get_debian_deps()
{ {
apt-get -y install \ apt-get -y install \
build-essential curl libffi-dev qtbase5-dev libqt5scintilla2-dev \ build-essential curl libffi-dev \
libxmu-dev cmake bison flex git-core libboost-all-dev \ libxmu-dev cmake bison flex git-core libboost-all-dev \
libXi-dev libmpfr-dev libboost-dev libglew-dev \ libXi-dev libmpfr-dev libboost-dev libglew-dev \
libeigen3-dev libcgal-dev libopencsg-dev libgmp3-dev libgmp-dev \ libeigen3-dev libcgal-dev libopencsg-dev libgmp3-dev libgmp-dev \
imagemagick libfontconfig-dev libfreetype6-dev \ imagemagick libfontconfig-dev libfreetype6-dev \
libharfbuzz-dev gtk-doc-tools libglib2.0-dev gettext 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_ubuntu_14_deps()
{
get_debian_8_deps
apt-get -y install qt5-qmake
} }
unknown() unknown()
@ -73,18 +111,28 @@ unknown()
} }
if [ -e /etc/issue ]; then if [ -e /etc/issue ]; then
if [ "`grep -i ubuntu /etc/issue`" ]; then if [ "`grep -i ubuntu.1[4-9] /etc/issue`" ]; then
get_ubuntu_14_deps
elif [ "`grep -i ubuntu /etc/issue`" ]; then
get_debian_deps get_debian_deps
elif [ "`grep -i debian.GNU.Linux.7 /etc/issue`" ]; then
get_debian_7_deps
elif [ "`grep -i debian /etc/issue`" ]; then elif [ "`grep -i debian /etc/issue`" ]; then
get_debian_deps get_debian_8_deps
elif [ "`grep -i raspbian /etc/issue`" ]; then elif [ "`grep -i raspbian /etc/issue`" ]; then
get_debian_deps get_debian_deps
elif [ "`grep -i mint /etc/issue`" ]; then elif [ "`grep -i mint /etc/issue`" ]; then
get_debian_deps get_debian_7_deps
elif [ "`grep -i suse /etc/issue`" ]; then elif [ "`grep -i suse /etc/issue`" ]; then
get_opensuse_deps get_opensuse_deps
elif [ "`grep -i fedora.release.2[2-9] /etc/issue`" ]; then
get_fedora_deps_dnf
elif [ "`grep -i fedora.release.[3-9][0-9] /etc/issue`" ]; then
get_fedora_deps_dnf
elif [ "`grep -i fedora.release.2[0-1] /etc/issue`" ]; then
get_fedora_deps_yum
elif [ "`grep -i fedora /etc/issue`" ]; then elif [ "`grep -i fedora /etc/issue`" ]; then
get_fedora_deps get_fedora_deps_yum
elif [ "`grep -i red.hat /etc/issue`" ]; then elif [ "`grep -i red.hat /etc/issue`" ]; then
get_fedora_deps get_fedora_deps
elif [ "`grep -i mageia /etc/issue`" ]; then elif [ "`grep -i mageia /etc/issue`" ]; then

View file

@ -11,8 +11,6 @@ public:
AboutDialog(QWidget *) { AboutDialog(QWidget *) {
setupUi(this); setupUi(this);
this->setWindowTitle( QString(_("About OpenSCAD")) + " " + openscad_shortversionnumber.c_str()); 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(); QString tmp = this->aboutText->toHtml();
tmp.replace("__VERSION__", openscad_detailedversionnumber.c_str()); tmp.replace("__VERSION__", openscad_detailedversionnumber.c_str());
this->aboutText->setHtml(tmp); this->aboutText->setHtml(tmp);

View file

@ -9,13 +9,29 @@
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta http-equiv="Content-Type" content="text/html;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> </head>
<body>
<body style="font-family:'Arial'; font-size:13pt;"> <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>
<p> <a class="donate-link" href="http://www.openscad.org/community.html">&nbsp;Donate&nbsp;</a>
<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> </p>
<p> <p>

View file

@ -40,6 +40,8 @@
#include FT_OUTLINE_H #include FT_OUTLINE_H
#define SCRIPT_UNTAG(tag) ((uint8_t)((tag)>>24)) % ((uint8_t)((tag)>>16)) % ((uint8_t)((tag)>>8)) % ((uint8_t)(tag))
static inline Vector2d get_scaled_vector(const FT_Vector *ft_vector, double scale) { static inline Vector2d get_scaled_vector(const FT_Vector *ft_vector, double scale) {
return Vector2d(ft_vector->x / scale, ft_vector->y / scale); return Vector2d(ft_vector->x / scale, ft_vector->y / scale);
} }
@ -122,6 +124,75 @@ double FreetypeRenderer::calc_y_offset(std::string valign, double ascend, double
} }
} }
hb_direction_t FreetypeRenderer::get_direction(const FreetypeRenderer::Params &params, const hb_script_t script) const
{
hb_direction_t param_direction = hb_direction_from_string(params.direction.c_str(), -1);
if (param_direction != HB_DIRECTION_INVALID) {
return param_direction;
}
hb_direction_t direction = hb_script_get_horizontal_direction(script);
PRINTDB("Detected direction '%s' for %s", hb_direction_to_string(direction) % params.text.c_str());
return direction;
}
bool FreetypeRenderer::is_ignored_script(const hb_script_t script) const
{
switch (script) {
case HB_SCRIPT_COMMON:
case HB_SCRIPT_INHERITED:
case HB_SCRIPT_UNKNOWN:
case HB_SCRIPT_INVALID:
return true;
default:
return false;
}
}
hb_script_t FreetypeRenderer::get_script(const FreetypeRenderer::Params &params, hb_glyph_info_t *glyph_info, unsigned int glyph_count) const
{
hb_script_t param_script = hb_script_from_string(params.script.c_str(), -1);
if (param_script != HB_SCRIPT_INVALID) {
return param_script;
}
hb_script_t script = HB_SCRIPT_INVALID;
for (unsigned int idx = 0;idx < glyph_count;idx++) {
hb_codepoint_t cp = glyph_info[idx].codepoint;
hb_script_t s = hb_unicode_script(hb_unicode_funcs_get_default(), cp);
if (!is_ignored_script(s)) {
if (script == HB_SCRIPT_INVALID) {
script = s;
} else if ((script != s) && (script != HB_SCRIPT_UNKNOWN)) {
script = HB_SCRIPT_UNKNOWN;
}
}
}
PRINTDB("Detected script '%c%c%c%c' for %s", SCRIPT_UNTAG(script) % params.text.c_str());
return script;
}
void FreetypeRenderer::detect_properties(FreetypeRenderer::Params &params) const
{
hb_buffer_t *hb_buf = hb_buffer_create();
hb_buffer_add_utf8(hb_buf, params.text.c_str(), strlen(params.text.c_str()), 0, strlen(params.text.c_str()));
unsigned int glyph_count;
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(hb_buf, &glyph_count);
hb_script_t script = get_script(params, glyph_info, glyph_count);
hb_buffer_destroy(hb_buf);
if (!is_ignored_script(script)) {
char script_buf[5] = { 0, };
hb_tag_to_string(hb_script_to_iso15924_tag(script), script_buf);
params.set_script(script_buf);
}
hb_direction_t direction = get_direction(params, script);
params.set_direction(hb_direction_to_string(direction));
}
std::vector<const Geometry *> FreetypeRenderer::render(const FreetypeRenderer::Params &params) const std::vector<const Geometry *> FreetypeRenderer::render(const FreetypeRenderer::Params &params) const
{ {
FT_Face face; FT_Face face;

View file

@ -85,7 +85,7 @@ public:
<< ", font = \"" << params.font << ", font = \"" << params.font
<< "\", direction = \"" << params.direction << "\", direction = \"" << params.direction
<< "\", language = \"" << params.language << "\", language = \"" << params.language
<< "\", script = \"" << params.script << (params.script.empty() ? "" : "\", script = \"") << params.script
<< "\", halign = \"" << params.halign << "\", halign = \"" << params.halign
<< "\", valign = \"" << params.valign << "\", valign = \"" << params.valign
<< "\", $fn = " << params.fn << "\", $fn = " << params.fn
@ -102,6 +102,7 @@ public:
FreetypeRenderer(); FreetypeRenderer();
virtual ~FreetypeRenderer(); virtual ~FreetypeRenderer();
void detect_properties(FreetypeRenderer::Params &params) const;
std::vector<const class Geometry *> render(const FreetypeRenderer::Params &params) const; std::vector<const class Geometry *> render(const FreetypeRenderer::Params &params) const;
private: private:
const static double scale; const static double scale;
@ -136,6 +137,10 @@ private:
} }
}; };
bool is_ignored_script(const hb_script_t script) const;
hb_script_t get_script(const FreetypeRenderer::Params &params, hb_glyph_info_t *glyph_info, unsigned int glyph_count) const;
hb_direction_t get_direction(const FreetypeRenderer::Params &params, const hb_script_t script) const;
double calc_x_offset(std::string halign, double width) const; double calc_x_offset(std::string halign, double width) const;
double calc_y_offset(std::string valign, double ascend, double descend) const; double calc_y_offset(std::string valign, double ascend, double descend) const;

View file

@ -158,7 +158,7 @@ void GLView::paintGL()
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
Color4f bgcol = ColorMap::getColor(*this->colorscheme, BACKGROUND_COLOR); Color4f bgcol = ColorMap::getColor(*this->colorscheme, BACKGROUND_COLOR);
Color4f bgcontrast = ColorMap::getContrastColor(bgcol); Color4f axescolor = ColorMap::getColor(*this->colorscheme, AXES_COLOR);
glClearColor(bgcol[0], bgcol[1], bgcol[2], 1.0); glClearColor(bgcol[0], bgcol[1], bgcol[2], 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@ -169,9 +169,9 @@ void GLView::paintGL()
if (showcrosshairs) GLView::showCrosshairs(); if (showcrosshairs) GLView::showCrosshairs();
glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z()); glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z());
// ...the axis lines need to follow the object translation. // ...the axis lines need to follow the object translation.
if (showaxes) GLView::showAxes(bgcontrast); if (showaxes) GLView::showAxes(axescolor);
// mark the scale along the axis lines // mark the scale along the axis lines
if (showaxes && showscale) GLView::showScalemarkers(bgcontrast); if (showaxes && showscale) GLView::showScalemarkers(axescolor);
} }
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
@ -191,7 +191,7 @@ void GLView::paintGL()
// Only for GIMBAL // Only for GIMBAL
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
if (showaxes) GLView::showSmallaxes(bgcontrast); if (showaxes) GLView::showSmallaxes(axescolor);
} }
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
@ -216,7 +216,7 @@ void GLView::enable_opencsg_shaders()
else if (GLEW_EXT_framebuffer_object && GLEW_EXT_packed_depth_stencil) { else if (GLEW_EXT_framebuffer_object && GLEW_EXT_packed_depth_stencil) {
this->is_opencsg_capable = true; this->is_opencsg_capable = true;
} }
#ifdef WIN32 #ifdef _WIN32
else if (WGLEW_ARB_pbuffer && WGLEW_ARB_pixel_format) this->is_opencsg_capable = true; else if (WGLEW_ARB_pbuffer && WGLEW_ARB_pixel_format) this->is_opencsg_capable = true;
#elif !defined(__APPLE__) #elif !defined(__APPLE__)
else if (GLXEW_SGIX_pbuffer && GLXEW_SGIX_fbconfig) this->is_opencsg_capable = true; else if (GLXEW_SGIX_pbuffer && GLXEW_SGIX_fbconfig) this->is_opencsg_capable = true;

View file

@ -740,6 +740,7 @@ Response GeometryEvaluator::visit(State &state, const LinearExtrudeNode &node)
Polygon2d *p2d = dxf.toPolygon2d(); Polygon2d *p2d = dxf.toPolygon2d();
if (p2d) geometry = ClipperUtils::sanitize(*p2d); if (p2d) geometry = ClipperUtils::sanitize(*p2d);
delete p2d;
} }
else { else {
geometry = applyToChildren2D(node, OPENSCAD_UNION); geometry = applyToChildren2D(node, OPENSCAD_UNION);
@ -849,6 +850,7 @@ Response GeometryEvaluator::visit(State &state, const RotateExtrudeNode &node)
DxfData dxf(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); DxfData dxf(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale);
Polygon2d *p2d = dxf.toPolygon2d(); Polygon2d *p2d = dxf.toPolygon2d();
if (p2d) geometry = ClipperUtils::sanitize(*p2d); if (p2d) geometry = ClipperUtils::sanitize(*p2d);
delete p2d;
} }
else { else {
geometry = applyToChildren2D(node, OPENSCAD_UNION); geometry = applyToChildren2D(node, OPENSCAD_UNION);
@ -954,6 +956,8 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
// Add correctly winded polygons to the main clipper // Add correctly winded polygons to the main clipper
sumclipper.AddPaths(result, ClipperLib::ptSubject, true); sumclipper.AddPaths(result, ClipperLib::ptSubject, true);
} }
delete poly;
} }
ClipperLib::PolyTree sumresult; ClipperLib::PolyTree sumresult;
// This is key - without StrictlySimple, we tend to get self-intersecting results // This is key - without StrictlySimple, we tend to get self-intersecting results

View file

@ -15,6 +15,7 @@
#include <QMutex> #include <QMutex>
#include <QSet> #include <QSet>
#include <QTime> #include <QTime>
#include <QIODevice>
enum export_type_e { enum export_type_e {
EXPORT_TYPE_UNKNOWN, EXPORT_TYPE_UNKNOWN,
@ -35,7 +36,11 @@ public:
class Preferences *prefs; class Preferences *prefs;
QTimer *animate_timer; 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; QTimer *autoReloadTimer;
std::string autoReloadId; std::string autoReloadId;
@ -88,7 +93,10 @@ protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
private slots: private slots:
void updatedFps(); void updatedAnimTval();
void updatedAnimFps();
void updatedAnimSteps();
void updatedAnimDump(bool checked);
void updateTVal(); void updateTVal();
void updateMdiMode(bool mdi); void updateMdiMode(bool mdi);
void updateUndockMode(bool undockMode); void updateUndockMode(bool undockMode);
@ -113,6 +121,7 @@ private:
void compile(bool reload, bool forcedone = false); void compile(bool reload, bool forcedone = false);
void compileCSG(bool procevents); void compileCSG(bool procevents);
bool maybeSave(); bool maybeSave();
void saveError(const QIODevice &file, const std::string &msg);
bool checkEditorModified(); bool checkEditorModified();
QString dumpCSGTree(AbstractNode *root); QString dumpCSGTree(AbstractNode *root);
static void consoleOutput(const std::string &msg, void *userdata); static void consoleOutput(const std::string &msg, void *userdata);
@ -196,6 +205,7 @@ private slots:
void actionExportSVG(); void actionExportSVG();
void actionExportCSG(); void actionExportCSG();
void actionExportImage(); void actionExportImage();
void actionCopyViewport();
void actionFlushCaches(); void actionFlushCaches();
public: public:

View file

@ -302,6 +302,8 @@
<addaction name="editActionCopy"/> <addaction name="editActionCopy"/>
<addaction name="editActionPaste"/> <addaction name="editActionPaste"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="editActionCopyViewport"/>
<addaction name="separator"/>
<addaction name="editActionIndent"/> <addaction name="editActionIndent"/>
<addaction name="editActionUnindent"/> <addaction name="editActionUnindent"/>
<addaction name="editActionComment"/> <addaction name="editActionComment"/>
@ -1261,6 +1263,14 @@
<string>&amp;Cheat Sheet</string> <string>&amp;Cheat Sheet</string>
</property> </property>
</action> </action>
<action name="editActionCopyViewport">
<property name="text">
<string>Copy Viewport</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+C</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View file

@ -237,6 +237,7 @@ bool create_glx_dummy_window(OffscreenContext &ctx)
// this call alters ctx->xDisplay and ctx->openGLContext // this call alters ctx->xDisplay and ctx->openGLContext
// and ctx->xwindow if successfull // and ctx->xwindow if successfull
if (!create_glx_dummy_context( *ctx )) { if (!create_glx_dummy_context( *ctx )) {
delete ctx;
return NULL; return NULL;
} }

View file

@ -31,7 +31,6 @@
#include "stl-utils.h" #include "stl-utils.h"
#ifdef ENABLE_OPENCSG #ifdef ENABLE_OPENCSG
# include <opencsg.h> # include <opencsg.h>
#endif
class OpenCSGPrim : public OpenCSG::Primitive class OpenCSGPrim : public OpenCSG::Primitive
{ {
@ -49,6 +48,8 @@ public:
} }
}; };
#endif
OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain, OpenCSGRenderer::OpenCSGRenderer(CSGChain *root_chain, CSGChain *highlights_chain,
CSGChain *background_chain, GLint *shaderinfo) CSGChain *background_chain, GLint *shaderinfo)
: root_chain(root_chain), highlights_chain(highlights_chain), : root_chain(root_chain), highlights_chain(highlights_chain),
@ -74,6 +75,7 @@ void OpenCSGRenderer::draw(bool /*showfaces*/, bool showedges) const
void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo, void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
bool highlight, bool background) const bool highlight, bool background) const
{ {
#ifdef ENABLE_OPENCSG
std::vector<OpenCSG::Primitive*> primitives; std::vector<OpenCSG::Primitive*> primitives;
size_t j = 0; size_t j = 0;
for (size_t i = 0;; i++) { for (size_t i = 0;; i++) {
@ -151,6 +153,7 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo,
} }
} }
std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>()); std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>());
#endif
} }
BoundingBox OpenCSGRenderer::getBoundingBox() const BoundingBox OpenCSGRenderer::getBoundingBox() const

View file

@ -23,7 +23,7 @@ const char *PlatformUtils::OPENSCAD_FOLDER_NAME = "OpenSCAD";
static std::string lookupResourcesPath() static std::string lookupResourcesPath()
{ {
fs::path resourcedir(applicationpath); fs::path resourcedir(applicationpath);
PRINTDB("Looking up resource folder with application path '%s'", resourcedir.c_str()); PRINTDB("Looking up resource folder with application path '%s'", boosty::stringy(resourcedir).c_str());
#ifdef __APPLE__ #ifdef __APPLE__
const char *searchpath[] = { const char *searchpath[] = {
@ -33,7 +33,7 @@ static std::string lookupResourcesPath()
NULL NULL
}; };
#else #else
#ifdef WIN32 #ifdef _WIN32
const char *searchpath[] = { const char *searchpath[] = {
".", // Release location ".", // Release location
RESOURCE_FOLDER("../share/openscad"), // MSYS2 location RESOURCE_FOLDER("../share/openscad"), // MSYS2 location
@ -56,12 +56,14 @@ static std::string lookupResourcesPath()
for (int a = 0;searchpath[a] != NULL;a++) { for (int a = 0;searchpath[a] != NULL;a++) {
tmpdir = resourcedir / searchpath[a]; tmpdir = resourcedir / searchpath[a];
const fs::path checkdir = tmpdir / "libraries"; // The resource folder is the folder which contains "color-schemes" (as well as
PRINTDB("Checking '%s'", checkdir.c_str()); // "examples" and "locale", and optionally "libraries" and "fonts")
const fs::path checkdir = tmpdir / "color-schemes";
PRINTDB("Checking '%s'", boosty::stringy(checkdir).c_str());
if (is_directory(checkdir)) { if (is_directory(checkdir)) {
resourcedir = tmpdir; resourcedir = tmpdir;
PRINTDB("Found resource folder '%s'", tmpdir.c_str()); PRINTDB("Found resource folder '%s'", boosty::stringy(tmpdir).c_str());
break; break;
} }
} }
@ -111,7 +113,9 @@ std::string PlatformUtils::userLibraryPath()
try { try {
std::string pathstr = PlatformUtils::documentsPath(); std::string pathstr = PlatformUtils::documentsPath();
if (pathstr=="") return ""; if (pathstr=="") return "";
path = boosty::canonical(fs::path( pathstr )); path = fs::path( pathstr );
if (!fs::exists(path)) return "";
path = boosty::canonical( path );
//PRINTB("path size %i",boosty::stringy(path).size()); //PRINTB("path size %i",boosty::stringy(path).size());
//PRINTB("lib path found: [%s]", path ); //PRINTB("lib path found: [%s]", path );
if (path.empty()) return ""; if (path.empty()) return "";
@ -132,7 +136,9 @@ std::string PlatformUtils::backupPath()
try { try {
std::string pathstr = PlatformUtils::documentsPath(); std::string pathstr = PlatformUtils::documentsPath();
if (pathstr=="") return ""; if (pathstr=="") return "";
path = boosty::canonical(fs::path( pathstr )); path = fs::path( pathstr );
if (!fs::exists(path)) return "";
path = boosty::canonical( path );
if (path.empty()) return ""; if (path.empty()) return "";
path /= OPENSCAD_FOLDER_NAME; path /= OPENSCAD_FOLDER_NAME;
path /= "backups"; path /= "backups";
@ -185,7 +191,7 @@ fs::path PlatformUtils::resourcePath(const std::string &resource)
int PlatformUtils::setenv(const char *name, const char *value, int overwrite) int PlatformUtils::setenv(const char *name, const char *value, int overwrite)
{ {
#if defined(WIN32) #if defined(_WIN32)
const char *ptr = getenv(name); const char *ptr = getenv(name);
if ((overwrite == 0) && (ptr != NULL)) { if ((overwrite == 0) && (ptr != NULL)) {
return 0; return 0;

View file

@ -32,6 +32,7 @@
#include <QSettings> #include <QSettings>
#include <QStatusBar> #include <QStatusBar>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include "GeometryCache.h" #include "GeometryCache.h"
#include "AutoUpdater.h" #include "AutoUpdater.h"
#include "feature.h" #include "feature.h"
@ -49,7 +50,7 @@ Q_DECLARE_METATYPE(Feature *);
class SettingsReader : public Settings::Visitor class SettingsReader : public Settings::Visitor
{ {
QSettings settings; 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); std::string trimmed_value(value);
boost::trim(trimmed_value); boost::trim(trimmed_value);
@ -101,7 +102,7 @@ class SettingsWriter : public Settings::Visitor
settings.remove(key); settings.remove(key);
PRINTDB("SettingsWriter D: %s", key.toStdString().c_str()); PRINTDB("SettingsWriter D: %s", key.toStdString().c_str());
} else { } else {
Value value = s->get(entry); const Value &value = s->get(entry);
settings.setValue(key, QString::fromStdString(value.toString())); settings.setValue(key, QString::fromStdString(value.toString()));
PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str()); PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str());
} }
@ -689,18 +690,17 @@ void Preferences::updateGUI()
void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry) void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry)
{ {
comboBox->clear(); comboBox->clear();
Value::VectorType vector = entry.range().toVector(); // Range is a vector of 2D vectors: [[name, value], ...]
for (Value::VectorType::iterator it = vector.begin();it != vector.end();it++) { BOOST_FOREACH(const ValuePtr &v, entry.range().toVector()) {
QString val = QString::fromStdString((*it)[0].toString()); QString val = QString::fromStdString(v[0]->toString());
std::string text((*it)[1].toString()); QString qtext = QString::fromStdString(gettext(v[1]->toString().c_str()));
QString qtext = QString::fromStdString(gettext(text.c_str()));
comboBox->addItem(qtext, val); comboBox->addItem(qtext, val);
} }
} }
void Preferences::initSpinBox(QSpinBox *spinBox, const Settings::SettingsEntry& entry) 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->setMinimum(range.begin_value());
spinBox->setMaximum(range.end_value()); spinBox->setMaximum(range.end_value());
} }
@ -709,13 +709,13 @@ void Preferences::updateComboBox(QComboBox *comboBox, const Settings::SettingsEn
{ {
Settings::Settings *s = Settings::Settings::inst(); Settings::Settings *s = Settings::Settings::inst();
Value value = s->get(entry); const Value &value = s->get(entry);
QString text = QString::fromStdString(value.toString()); QString text = QString::fromStdString(value.toString());
int idx = comboBox->findData(text); int idx = comboBox->findData(text);
if (idx >= 0) { if (idx >= 0) {
comboBox->setCurrentIndex(idx); comboBox->setCurrentIndex(idx);
} else { } else {
Value defaultValue = entry.defaultValue(); const Value &defaultValue = entry.defaultValue();
QString defaultText = QString::fromStdString(defaultValue.toString()); QString defaultText = QString::fromStdString(defaultValue.toString());
int defIdx = comboBox->findData(defaultText); int defIdx = comboBox->findData(defaultText);
if (defIdx >= 0) { if (defIdx >= 0) {

View file

@ -1333,7 +1333,7 @@
<item> <item>
<widget class="QCheckBox" name="mdiCheckBox"> <widget class="QCheckBox" name="mdiCheckBox">
<property name="text"> <property name="text">
<string>Allow to open multiple documents</string> <string>Allow opening multiple documents</string>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -135,14 +135,11 @@ void QGLView::display_opencsg_warning_dialog()
message += _("It is highly recommended to use OpenSCAD on a system with " message += _("It is highly recommended to use OpenSCAD on a system with "
"OpenGL 2.0 or later.\n" "OpenGL 2.0 or later.\n"
"Your renderer information is as follows:\n"); "Your renderer information is as follows:\n");
QString rendererinfo; QString rendererinfo(_("GLEW version %1\n%2 (%3)\nOpenGL version %4\n"));
rendererinfo.sprintf(_("GLEW version %s\n" message += rendererinfo.arg((const char *)glewGetString(GLEW_VERSION),
"%s (%s)\n" (const char *)glGetString(GL_RENDERER),
"OpenGL version %s\n"), (const char *)glGetString(GL_VENDOR),
glewGetString(GLEW_VERSION), (const char *)glGetString(GL_VERSION));
glGetString(GL_RENDERER), glGetString(GL_VENDOR),
glGetString(GL_VERSION));
message += rendererinfo;
dialog->setText(message); dialog->setText(message);
dialog->enableOpenCSGBox->setChecked(Preferences::inst()->getValue("advanced/enable_opencsg_opengl1x").toBool()); dialog->enableOpenCSGBox->setChecked(Preferences::inst()->getValue("advanced/enable_opencsg_opengl1x").toBool());
@ -297,11 +294,12 @@ void QGLView::mouseReleaseEvent(QMouseEvent*)
releaseMouse(); releaseMouse();
} }
void QGLView::grabFrame() const QImage & QGLView::grabFrame()
{ {
// Force reading from front buffer. Some configurations will read from the back buffer here. // Force reading from front buffer. Some configurations will read from the back buffer here.
glReadBuffer(GL_FRONT); glReadBuffer(GL_FRONT);
this->frame = grabFrameBuffer(); this->frame = grabFrameBuffer();
return this->frame;
} }
bool QGLView::save(const char *filename) bool QGLView::save(const char *filename)

View file

@ -43,7 +43,7 @@ public:
float getDPI() { return this->devicePixelRatio(); } float getDPI() { return this->devicePixelRatio(); }
#endif #endif
void grabFrame(); const QImage & grabFrame();
bool save(const char *filename); bool save(const char *filename);
void resetView(); void resetView();
void viewAll(); void viewAll();

View file

@ -8,3 +8,42 @@ namespace fs = boost::filesystem;
fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to); fs::path boostfs_relative_path(const fs::path &path, const fs::path &relative_to);
fs::path boostfs_normalize(const fs::path &path); fs::path boostfs_normalize(const fs::path &path);
fs::path boostfs_uncomplete(fs::path const p, fs::path const base); fs::path boostfs_uncomplete(fs::path const p, fs::path const base);
#include <boost/cast.hpp>
#include <sstream>
/* Convert number types but print WARNING for failures during
conversion. This is useful for situations where it is important to not
fail silently during casting or conversion. (For example, accidentally
converting 64 bit types to 32 bit types, float to int, etc).
For positive overflow, return max of Tout template type
For negative overflow, return min of Tout template type
On other conversion failures, return 0. */
template <class Tout,class Tin> Tout boost_numeric_cast( Tin input )
{
Tout result = 0;
std::stringstream status;
status.str("ok");
try {
result = boost::numeric_cast<Tout>(input);
} catch (boost::numeric::negative_overflow& e) {
status << e.what();
result = std::numeric_limits<Tout>::min();
} catch (boost::numeric::positive_overflow& e) {
status << e.what();
result = std::numeric_limits<Tout>::max();
} catch (boost::numeric::bad_numeric_cast& e) {
status << e.what();
result = 0;
}
if (status.str()!="ok") {
std::stringstream tmp;
tmp << input;
PRINTB("WARNING: problem converting this number: %s",tmp.str());
PRINTB("WARNING: %s", status.str() );
PRINTB("WARNING: setting result to %u",result);
}
return result;
}

View file

@ -101,9 +101,9 @@ Builtins::Builtins()
this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0))))); this->globalscope.assignments.push_back(Assignment("$t", boost::shared_ptr<Expression>(new ExpressionConst(ValuePtr(0.0)))));
Value::VectorType zero3; Value::VectorType zero3;
zero3.push_back(Value(0.0)); zero3.push_back(ValuePtr(0.0));
zero3.push_back(Value(0.0)); zero3.push_back(ValuePtr(0.0));
zero3.push_back(Value(0.0)); zero3.push_back(ValuePtr(0.0));
ValuePtr zero3val(zero3); ValuePtr zero3val(zero3);
this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new ExpressionConst(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpt", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));
this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new ExpressionConst(zero3val)))); this->globalscope.assignments.push_back(Assignment("$vpr", boost::shared_ptr<Expression>(new ExpressionConst(zero3val))));

View file

@ -89,17 +89,17 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant
node->newsize << 0,0,0; node->newsize << 0,0,0;
if ( ns->type() == Value::VECTOR ) { if ( ns->type() == Value::VECTOR ) {
const Value::VectorType &vs = ns->toVector(); const Value::VectorType &vs = ns->toVector();
if ( vs.size() >= 1 ) node->newsize[0] = vs[0].toDouble(); if ( vs.size() >= 1 ) node->newsize[0] = vs[0]->toDouble();
if ( vs.size() >= 2 ) node->newsize[1] = vs[1].toDouble(); if ( vs.size() >= 2 ) node->newsize[1] = vs[1]->toDouble();
if ( vs.size() >= 3 ) node->newsize[2] = vs[2].toDouble(); if ( vs.size() >= 3 ) node->newsize[2] = vs[2]->toDouble();
} }
ValuePtr autosize = c.lookup_variable("auto"); ValuePtr autosize = c.lookup_variable("auto");
node->autosize << false, false, false; node->autosize << false, false, false;
if ( autosize->type() == Value::VECTOR ) { if ( autosize->type() == Value::VECTOR ) {
const Value::VectorType &va = autosize->toVector(); const Value::VectorType &va = autosize->toVector();
if ( va.size() >= 1 ) node->autosize[0] = va[0].toBool(); if ( va.size() >= 1 ) node->autosize[0] = va[0]->toBool();
if ( va.size() >= 2 ) node->autosize[1] = va[1].toBool(); if ( va.size() >= 2 ) node->autosize[1] = va[1]->toBool();
if ( va.size() >= 3 ) node->autosize[2] = va[2].toBool(); if ( va.size() >= 3 ) node->autosize[2] = va[2]->toBool();
} }
else if ( autosize->type() == Value::BOOL ) { else if ( autosize->type() == Value::BOOL ) {
node->autosize << autosize->toBool(),autosize->toBool(),autosize->toBool(); node->autosize << autosize->toBool(),autosize->toBool(),autosize->toBool();

422
src/cgalutils-applyops.cc Normal file
View file

@ -0,0 +1,422 @@
// this file is split into many separate cgalutils* files
// in order to workaround gcc 4.9.1 crashing on systems with only 2GB of RAM
#ifdef ENABLE_CGAL
#include "cgalutils.h"
#include "polyset.h"
#include "printutils.h"
#include "Polygon2d.h"
#include "polyset-utils.h"
#include "grid.h"
#include "node.h"
#include "cgal.h"
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/normal_vector_newell_3.h>
#include <CGAL/Handle_hash_function.h>
#include <CGAL/config.h>
#include <CGAL/version.h>
// Apply CGAL bugfix for CGAL-4.5.x
#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,5,0)
#include <CGAL/convex_hull_3.h>
#else
#include "convex_hull_3_bugfix.h"
#endif
#include "svg.h"
#include "Reindexer.h"
#include "GeometryUtils.h"
#include <map>
#include <queue>
#include <boost/foreach.hpp>
#include <boost/unordered_set.hpp>
namespace CGALUtils {
template<typename Polyhedron>
bool is_weakly_convex(Polyhedron const& p) {
for (typename Polyhedron::Edge_const_iterator i = p.edges_begin(); i != p.edges_end(); ++i) {
typename Polyhedron::Plane_3 p(i->opposite()->vertex()->point(), i->vertex()->point(), i->next()->vertex()->point());
if (p.has_on_positive_side(i->opposite()->next()->vertex()->point()) &&
CGAL::squared_distance(p, i->opposite()->next()->vertex()->point()) > 1e-8) {
return false;
}
}
// Also make sure that there is only one shell:
boost::unordered_set<typename Polyhedron::Facet_const_handle, typename CGAL::Handle_hash_function> visited;
// c++11
// visited.reserve(p.size_of_facets());
std::queue<typename Polyhedron::Facet_const_handle> to_explore;
to_explore.push(p.facets_begin()); // One arbitrary facet
visited.insert(to_explore.front());
while (!to_explore.empty()) {
typename Polyhedron::Facet_const_handle f = to_explore.front();
to_explore.pop();
typename Polyhedron::Facet::Halfedge_around_facet_const_circulator he, end;
end = he = f->facet_begin();
CGAL_For_all(he,end) {
typename Polyhedron::Facet_const_handle o = he->opposite()->facet();
if (!visited.count(o)) {
visited.insert(o);
to_explore.push(o);
}
}
}
return visited.size() == p.size_of_facets();
}
/*!
Applies op to all children and returns the result.
The child list should be guaranteed to contain non-NULL 3D or empty Geometry objects
*/
CGAL_Nef_polyhedron *applyOperator(const Geometry::ChildList &children, OpenSCADOperator op)
{
CGAL_Nef_polyhedron *N = NULL;
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
// Speeds up n-ary union operations significantly
CGAL::Nef_nary_union_3<CGAL_Nef_polyhedron3> nary_union;
int nary_union_num_inserted = 0;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
shared_ptr<const CGAL_Nef_polyhedron> chN =
dynamic_pointer_cast<const CGAL_Nef_polyhedron>(chgeom);
if (!chN) {
const PolySet *chps = dynamic_cast<const PolySet*>(chgeom.get());
if (chps) chN.reset(createNefPolyhedronFromGeometry(*chps));
}
if (op == OPENSCAD_UNION) {
if (!chN->isEmpty()) {
// nary_union.add_polyhedron() can issue assertion errors:
// https://github.com/openscad/openscad/issues/802
nary_union.add_polyhedron(*chN->p3);
nary_union_num_inserted++;
}
continue;
}
// Initialize N with first expected geometric object
if (!N) {
N = new CGAL_Nef_polyhedron(*chN);
continue;
}
// Intersecting something with nothing results in nothing
if (chN->isEmpty()) {
if (op == OPENSCAD_INTERSECTION) *N = *chN;
continue;
}
// empty op <something> => empty
if (N->isEmpty()) continue;
switch (op) {
case OPENSCAD_INTERSECTION:
*N *= *chN;
break;
case OPENSCAD_DIFFERENCE:
*N -= *chN;
break;
case OPENSCAD_MINKOWSKI:
N->minkowski(*chN);
break;
default:
PRINTB("ERROR: Unsupported CGAL operator: %d", op);
}
item.first->progress_report();
}
if (op == OPENSCAD_UNION && nary_union_num_inserted > 0) {
N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3(nary_union.get_union()));
}
}
// union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad and testdata/scad/bugs/issue204.scad
catch (const CGAL::Failure_exception &e) {
std::string opstr = op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_UNION ? "union" : "UNKNOWN";
PRINTB("ERROR: CGAL error in CGALUtils::applyBinaryOperator %s: %s", opstr % e.what());
}
CGAL::set_error_behaviour(old_behaviour);
return N;
}
bool applyHull(const Geometry::ChildList &children, PolySet &result)
{
typedef CGAL::Epick K;
// Collect point cloud
// NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list
// instead.
std::list<K::Point_3> points;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(chgeom.get());
if (N) {
if (!N->isEmpty()) {
for (CGAL_Nef_polyhedron3::Vertex_const_iterator i = N->p3->vertices_begin(); i != N->p3->vertices_end(); ++i) {
points.push_back(vector_convert<K::Point_3>(i->point()));
}
}
} else {
const PolySet *ps = dynamic_cast<const PolySet *>(chgeom.get());
if (ps) {
BOOST_FOREACH(const Polygon &p, ps->polygons) {
BOOST_FOREACH(const Vector3d &v, p) {
points.push_back(K::Point_3(v[0], v[1], v[2]));
}
}
}
}
}
if (points.size() <= 3) return false;
// Apply hull
bool success = false;
if (points.size() >= 4) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL::Polyhedron_3<K> r;
CGAL::convex_hull_3(points.begin(), points.end(), r);
PRINTDB("After hull vertices: %d", r.size_of_vertices());
PRINTDB("After hull facets: %d", r.size_of_facets());
PRINTDB("After hull closed: %d", r.is_closed());
PRINTDB("After hull valid: %d", r.is_valid());
success = !createPolySetFromPolyhedron(r, result);
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("ERROR: CGAL error in applyHull(): %s", e.what());
}
CGAL::set_error_behaviour(old_behaviour);
}
return success;
}
/*!
children cannot contain NULL objects
*/
Geometry const * applyMinkowski(const Geometry::ChildList &children)
{
CGAL::Timer t,t_tot;
assert(children.size() >= 2);
Geometry::ChildList::const_iterator it = children.begin();
t_tot.start();
Geometry const* operands[2] = {it->second.get(), NULL};
try {
while (++it != children.end()) {
operands[1] = it->second.get();
typedef CGAL::Epick Hull_kernel;
std::list<CGAL_Polyhedron> P[2];
std::list<CGAL::Polyhedron_3<Hull_kernel> > result_parts;
for (size_t i = 0; i < 2; i++) {
CGAL_Polyhedron poly;
const PolySet * ps = dynamic_cast<const PolySet *>(operands[i]);
const CGAL_Nef_polyhedron * nef = dynamic_cast<const CGAL_Nef_polyhedron *>(operands[i]);
if (ps) CGALUtils::createPolyhedronFromPolySet(*ps, poly);
else if (nef && nef->p3->is_simple()) nefworkaround::convert_to_Polyhedron<CGAL_Kernel3>(*nef->p3, poly);
else throw 0;
if ((ps && ps->is_convex()) ||
(!ps && is_weakly_convex(poly))) {
PRINTDB("Minkowski: child %d is convex and %s",i % (ps?"PolySet":"Nef"));
P[i].push_back(poly);
} else {
CGAL_Nef_polyhedron3 decomposed_nef;
if (ps) {
PRINTDB("Minkowski: child %d is nonconvex PolySet, transforming to Nef and decomposing...", i);
CGAL_Nef_polyhedron *p = createNefPolyhedronFromGeometry(*ps);
if (!p->isEmpty()) decomposed_nef = *p->p3;
delete p;
} else {
PRINTDB("Minkowski: child %d is nonconvex Nef, decomposing...",i);
decomposed_nef = *nef->p3;
}
t.start();
CGAL::convex_decomposition_3(decomposed_nef);
// the first volume is the outer volume, which ignored in the decomposition
CGAL_Nef_polyhedron3::Volume_const_iterator ci = ++decomposed_nef.volumes_begin();
for(; ci != decomposed_nef.volumes_end(); ++ci) {
if(ci->mark()) {
CGAL_Polyhedron poly;
decomposed_nef.convert_inner_shell_to_polyhedron(ci->shells_begin(), poly);
P[i].push_back(poly);
}
}
PRINTDB("Minkowski: decomposed into %d convex parts", P[i].size());
t.stop();
PRINTDB("Minkowski: decomposition took %f s", t.time());
}
}
std::vector<Hull_kernel::Point_3> points[2];
std::vector<Hull_kernel::Point_3> minkowski_points;
for (size_t i = 0; i < P[0].size(); i++) {
for (size_t j = 0; j < P[1].size(); j++) {
t.start();
points[0].clear();
points[1].clear();
for (int k = 0; k < 2; k++) {
std::list<CGAL_Polyhedron>::iterator it = P[k].begin();
std::advance(it, k==0?i:j);
CGAL_Polyhedron const& poly = *it;
points[k].reserve(poly.size_of_vertices());
for (CGAL_Polyhedron::Vertex_const_iterator pi = poly.vertices_begin(); pi != poly.vertices_end(); ++pi) {
CGAL_Polyhedron::Point_3 const& p = pi->point();
points[k].push_back(Hull_kernel::Point_3(to_double(p[0]),to_double(p[1]),to_double(p[2])));
}
}
minkowski_points.clear();
minkowski_points.reserve(points[0].size() * points[1].size());
for (size_t i = 0; i < points[0].size(); i++) {
for (size_t j = 0; j < points[1].size(); j++) {
minkowski_points.push_back(points[0][i]+(points[1][j]-CGAL::ORIGIN));
}
}
if (minkowski_points.size() <= 3) {
t.stop();
continue;
}
CGAL::Polyhedron_3<Hull_kernel> result;
t.stop();
PRINTDB("Minkowski: Point cloud creation (%d ⨉ %d -> %d) took %f ms", points[0].size() % points[1].size() % minkowski_points.size() % (t.time()*1000));
t.reset();
t.start();
CGAL::convex_hull_3(minkowski_points.begin(), minkowski_points.end(), result);
std::vector<Hull_kernel::Point_3> strict_points;
strict_points.reserve(minkowski_points.size());
for (CGAL::Polyhedron_3<Hull_kernel>::Vertex_iterator i = result.vertices_begin(); i != result.vertices_end(); ++i) {
Hull_kernel::Point_3 const& p = i->point();
CGAL::Polyhedron_3<Hull_kernel>::Vertex::Halfedge_handle h,e;
h = i->halfedge();
e = h;
bool collinear = false;
bool coplanar = true;
do {
Hull_kernel::Point_3 const& q = h->opposite()->vertex()->point();
if (coplanar && !CGAL::coplanar(p,q,
h->next_on_vertex()->opposite()->vertex()->point(),
h->next_on_vertex()->next_on_vertex()->opposite()->vertex()->point())) {
coplanar = false;
}
for (CGAL::Polyhedron_3<Hull_kernel>::Vertex::Halfedge_handle j = h->next_on_vertex();
j != h && !collinear && ! coplanar;
j = j->next_on_vertex()) {
Hull_kernel::Point_3 const& r = j->opposite()->vertex()->point();
if (CGAL::collinear(p,q,r)) {
collinear = true;
}
}
h = h->next_on_vertex();
} while (h != e && !collinear);
if (!collinear && !coplanar)
strict_points.push_back(p);
}
result.clear();
CGAL::convex_hull_3(strict_points.begin(), strict_points.end(), result);
t.stop();
PRINTDB("Minkowski: Computing convex hull took %f s", t.time());
t.reset();
result_parts.push_back(result);
}
}
if (it != boost::next(children.begin()))
delete operands[0];
if (result_parts.size() == 1) {
PolySet *ps = new PolySet(3,true);
createPolySetFromPolyhedron(*result_parts.begin(), *ps);
operands[0] = ps;
} else if (!result_parts.empty()) {
t.start();
PRINTDB("Minkowski: Computing union of %d parts",result_parts.size());
Geometry::ChildList fake_children;
for (std::list<CGAL::Polyhedron_3<Hull_kernel> >::iterator i = result_parts.begin(); i != result_parts.end(); ++i) {
PolySet ps(3,true);
createPolySetFromPolyhedron(*i, ps);
fake_children.push_back(std::make_pair((const AbstractNode*)NULL,
shared_ptr<const Geometry>(createNefPolyhedronFromGeometry(ps))));
}
CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(fake_children, OPENSCAD_UNION);
// FIXME: This hould really never throw.
// Assert once we figured out what went wrong with issue #1069?
if (!N) throw 0;
t.stop();
PRINTDB("Minkowski: Union done: %f s",t.time());
t.reset();
operands[0] = N;
} else {
operands[0] = new CGAL_Nef_polyhedron();
}
}
t_tot.stop();
PRINTDB("Minkowski: Total execution time %f s", t_tot.time());
t_tot.reset();
return operands[0];
}
catch (...) {
// If anything throws we simply fall back to Nef Minkowski
PRINTD("Minkowski: Falling back to Nef Minkowski");
CGAL_Nef_polyhedron *N = applyOperator(children, OPENSCAD_MINKOWSKI);
return N;
}
}
}; // namespace CGALUtils
#endif // ENABLE_CGAL

View file

@ -11,13 +11,8 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
namespace /* anonymous */ {
template<typename Result, typename V>
Result vector_convert(V const& v) {
return Result(CGAL::to_double(v[0]),CGAL::to_double(v[1]),CGAL::to_double(v[2]));
}
#undef GEN_SURFACE_DEBUG #undef GEN_SURFACE_DEBUG
namespace /* anonymous */ {
template <typename Polyhedron> template <typename Polyhedron>
class CGAL_Build_PolySet : public CGAL::Modifier_base<typename Polyhedron::HalfedgeDS> class CGAL_Build_PolySet : public CGAL::Modifier_base<typename Polyhedron::HalfedgeDS>

266
src/cgalutils-project.cc Normal file
View file

@ -0,0 +1,266 @@
// this file is split into many separate cgalutils* files
// in order to workaround gcc 4.9.1 crashing on systems with only 2GB of RAM
#ifdef ENABLE_CGAL
#include "cgalutils.h"
#include "polyset.h"
#include "printutils.h"
#include "Polygon2d.h"
#include "polyset-utils.h"
#include "grid.h"
#include "node.h"
#include "cgal.h"
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/normal_vector_newell_3.h>
#include <CGAL/Handle_hash_function.h>
#include <CGAL/config.h>
#include <CGAL/version.h>
// Apply CGAL bugfix for CGAL-4.5.x
#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,5,0)
#include <CGAL/convex_hull_3.h>
#else
#include "convex_hull_3_bugfix.h"
#endif
#include "svg.h"
#include "Reindexer.h"
#include "GeometryUtils.h"
#include <map>
#include <queue>
#include <boost/foreach.hpp>
#include <boost/unordered_set.hpp>
static void add_outline_to_poly(CGAL_Nef_polyhedron2::Explorer &explorer,
CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator circ,
CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator end,
bool positive,
Polygon2d *poly) {
Outline2d outline;
CGAL_For_all(circ, end) {
if (explorer.is_standard(explorer.target(circ))) {
CGAL_Nef_polyhedron2::Explorer::Point ep = explorer.point(explorer.target(circ));
outline.vertices.push_back(Vector2d(to_double(ep.x()),
to_double(ep.y())));
}
}
if (!outline.vertices.empty()) {
outline.positive = positive;
poly->addOutline(outline);
}
}
static Polygon2d *convertToPolygon2d(const CGAL_Nef_polyhedron2 &p2)
{
Polygon2d *poly = new Polygon2d;
typedef CGAL_Nef_polyhedron2::Explorer Explorer;
typedef Explorer::Face_const_iterator fci_t;
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
Explorer E = p2.explorer();
for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit) {
if (!fit->mark()) continue;
heafcc_t fcirc(E.face_cycle(fit)), fend(fcirc);
add_outline_to_poly(E, fcirc, fend, true, poly);
for (CGAL_Nef_polyhedron2::Explorer::Hole_const_iterator j = E.holes_begin(fit);j != E.holes_end(fit); ++j) {
CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator hcirc(j), hend(hcirc);
add_outline_to_poly(E, hcirc, hend, false, poly);
}
}
poly->setSanitized(true);
return poly;
}
/*
ZRemover
This class converts one or more Nef3 polyhedra into a Nef2 polyhedron by
stripping off the 'z' coordinates from the vertices. The resulting Nef2
poly is accumulated in the 'output_nefpoly2d' member variable.
The 'z' coordinates will either be all 0s, for an xy-plane intersected Nef3,
or, they will be a mixture of -eps and +eps, for a thin-box intersected Nef3.
Notes on CGAL's Nef Polyhedron2:
1. The 'mark' on a 2d Nef face is important when doing unions/intersections.
If the 'mark' of a face is wrong the resulting nef2 poly will be unexpected.
2. The 'mark' can be dependent on the points fed to the Nef2 constructor.
This is why we iterate through the 3d faces using the halfedge cycle
source()->target() instead of the ordinary source()->source(). The
the latter can generate sequences of points that will fail the
the CGAL::is_simple_2() test, resulting in improperly marked nef2 polys.
3. 3d facets have 'two sides'. we throw out the 'down' side to prevent dups.
The class uses the 'visitor' pattern from the CGAL manual. See also
http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3/Chapter_main.html
http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Nef_3_ref/Class_Nef_polyhedron3.html
OGL_helper.h
*/
class ZRemover {
public:
CGAL_Nef_polyhedron2::Boundary boundary;
boost::shared_ptr<CGAL_Nef_polyhedron2> tmpnef2d;
boost::shared_ptr<CGAL_Nef_polyhedron2> output_nefpoly2d;
CGAL::Direction_3<CGAL_Kernel3> up;
ZRemover()
{
output_nefpoly2d.reset( new CGAL_Nef_polyhedron2() );
boundary = CGAL_Nef_polyhedron2::INCLUDED;
up = CGAL::Direction_3<CGAL_Kernel3>(0,0,1);
}
void visit( CGAL_Nef_polyhedron3::Vertex_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::Halfedge_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::SHalfedge_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::SHalfloop_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::SFace_const_handle ) {}
void visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet );
};
void ZRemover::visit(CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet)
{
PRINTDB(" <!-- ZRemover Halffacet visit. Mark: %i --> ",hfacet->mark());
if (hfacet->plane().orthogonal_direction() != this->up) {
PRINTD(" <!-- ZRemover down-facing half-facet. skipping -->");
PRINTD(" <!-- ZRemover Halffacet visit end-->");
return;
}
// possible optimization - throw out facets that are vertically oriented
CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator fci;
int contour_counter = 0;
CGAL_forall_facet_cycles_of(fci, hfacet) {
if (fci.is_shalfedge()) {
PRINTD(" <!-- ZRemover Halffacet cycle begin -->");
CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(fci), cend(c1);
std::vector<CGAL_Nef_polyhedron2::Explorer::Point> contour;
CGAL_For_all(c1, cend) {
CGAL_Nef_polyhedron3::Point_3 point3d = c1->source()->target()->point();
CGAL_Nef_polyhedron2::Explorer::Point point2d(CGAL::to_double(point3d.x()),
CGAL::to_double(point3d.y()));
contour.push_back(point2d);
}
if (contour.size()==0) continue;
if (OpenSCAD::debug!="")
PRINTDB(" <!-- is_simple_2: %i -->", CGAL::is_simple_2(contour.begin(), contour.end()));
tmpnef2d.reset(new CGAL_Nef_polyhedron2(contour.begin(), contour.end(), boundary));
if (contour_counter == 0) {
PRINTDB(" <!-- contour is a body. make union(). %i points -->", contour.size());
*(output_nefpoly2d) += *(tmpnef2d);
} else {
PRINTDB(" <!-- contour is a hole. make intersection(). %i points -->", contour.size());
*(output_nefpoly2d) *= *(tmpnef2d);
}
/*log << "\n<!-- ======== output tmp nef: ==== -->\n"
<< OpenSCAD::dump_svg(*tmpnef2d) << "\n"
<< "\n<!-- ======== output accumulator: ==== -->\n"
<< OpenSCAD::dump_svg(*output_nefpoly2d) << "\n";*/
contour_counter++;
} else {
PRINTD(" <!-- ZRemover trivial facet cycle skipped -->");
}
PRINTD(" <!-- ZRemover Halffacet cycle end -->");
}
PRINTD(" <!-- ZRemover Halffacet visit end -->");
}
namespace CGALUtils {
Polygon2d *project(const CGAL_Nef_polyhedron &N, bool cut)
{
Polygon2d *poly = NULL;
if (N.getDimension() != 3) return poly;
CGAL_Nef_polyhedron newN;
if (cut) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Nef_polyhedron3::Plane_3 xy_plane = CGAL_Nef_polyhedron3::Plane_3(0,0,1,0);
newN.p3.reset(new CGAL_Nef_polyhedron3(N.p3->intersection(xy_plane, CGAL_Nef_polyhedron3::PLANE_ONLY)));
}
catch (const CGAL::Failure_exception &e) {
PRINTDB("CGALUtils::project during plane intersection: %s", e.what());
try {
PRINTD("Trying alternative intersection using very large thin box: ");
std::vector<CGAL_Point_3> pts;
// dont use z of 0. there are bugs in CGAL.
double inf = 1e8;
double eps = 0.001;
CGAL_Point_3 minpt(-inf, -inf, -eps);
CGAL_Point_3 maxpt( inf, inf, eps);
CGAL_Iso_cuboid_3 bigcuboid(minpt, maxpt);
for (int i=0;i<8;i++) pts.push_back(bigcuboid.vertex(i));
CGAL_Polyhedron bigbox;
CGAL::convex_hull_3(pts.begin(), pts.end(), bigbox);
CGAL_Nef_polyhedron3 nef_bigbox(bigbox);
newN.p3.reset(new CGAL_Nef_polyhedron3(nef_bigbox.intersection(*N.p3)));
}
catch (const CGAL::Failure_exception &e) {
PRINTB("ERROR: CGAL error in CGALUtils::project during bigbox intersection: %s", e.what());
}
}
if (!newN.p3 || newN.p3->is_empty()) {
CGAL::set_error_behaviour(old_behaviour);
PRINT("WARNING: projection() failed.");
return poly;
}
PRINTDB("%s",OpenSCAD::svg_header(480, 100000));
try {
ZRemover zremover;
CGAL_Nef_polyhedron3::Volume_const_iterator i;
CGAL_Nef_polyhedron3::Shell_entry_const_iterator j;
CGAL_Nef_polyhedron3::SFace_const_handle sface_handle;
for (i = newN.p3->volumes_begin(); i != newN.p3->volumes_end(); ++i) {
PRINTDB("<!-- volume. mark: %s -->",i->mark());
for (j = i->shells_begin(); j != i->shells_end(); ++j) {
PRINTDB("<!-- shell. (vol mark was: %i)", i->mark());;
sface_handle = CGAL_Nef_polyhedron3::SFace_const_handle(j);
newN.p3->visit_shell_objects(sface_handle , zremover);
PRINTD("<!-- shell. end. -->");
}
PRINTD("<!-- volume end. -->");
}
poly = convertToPolygon2d(*zremover.output_nefpoly2d);
} catch (const CGAL::Failure_exception &e) {
PRINTB("ERROR: CGAL error in CGALUtils::project while flattening: %s", e.what());
}
PRINTD("</svg>");
CGAL::set_error_behaviour(old_behaviour);
}
// In projection mode all the triangles are projected manually into the XY plane
else {
PolySet ps(3);
bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N.p3, ps);
if (err) {
PRINT("ERROR: Nef->PolySet failed");
return poly;
}
poly = PolysetUtils::project(ps);
}
return poly;
}
} // namespace
#endif // ENABLE_CGAL

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,13 @@ typedef CGAL::Point_3<K> Vertex3K;
typedef std::vector<Vertex3K> PolygonK; typedef std::vector<Vertex3K> PolygonK;
typedef std::vector<PolygonK> PolyholeK; typedef std::vector<PolygonK> PolyholeK;
namespace /* anonymous */ {
template<typename Result, typename V>
Result vector_convert(V const& v) {
return Result(CGAL::to_double(v[0]),CGAL::to_double(v[1]),CGAL::to_double(v[2]));
}
}
namespace CGALUtils { namespace CGALUtils {
bool applyHull(const Geometry::ChildList &children, PolySet &P); bool applyHull(const Geometry::ChildList &children, PolySet &P);
CGAL_Nef_polyhedron *applyOperator(const Geometry::ChildList &children, OpenSCADOperator op); CGAL_Nef_polyhedron *applyOperator(const Geometry::ChildList &children, OpenSCADOperator op);

View file

@ -1,4 +1,5 @@
#include "clipper-utils.h" #include "clipper-utils.h"
#include "printutils.h"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
namespace ClipperUtils { namespace ClipperUtils {
@ -30,7 +31,15 @@ namespace ClipperUtils {
ClipperLib::PolyTree sanitize(const ClipperLib::Paths &paths) { ClipperLib::PolyTree sanitize(const ClipperLib::Paths &paths) {
ClipperLib::PolyTree result; ClipperLib::PolyTree result;
ClipperLib::Clipper clipper; ClipperLib::Clipper clipper;
clipper.AddPaths(paths, ClipperLib::ptSubject, true); try {
clipper.AddPaths(paths, ClipperLib::ptSubject, true);
}
catch(...) {
// Most likely caught a RangeTest exception from clipper
// Note that Clipper up to v6.2.1 incorrectly throws
// an exception of type char* rather than a clipperException()
PRINT("WARNING: Range check failed for polygon. skipping");
}
clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftEvenOdd); clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftEvenOdd);
return result; return result;
} }

View file

@ -50,6 +50,8 @@ private:
ColorModule::ColorModule() ColorModule::ColorModule()
{ {
// Colors extracted from https://drafts.csswg.org/css-color/ on 2015-08-02
// CSS Color Module Level 4 - Editors Draft, 29 May 2015
webcolors = map_list_of webcolors = map_list_of
("aliceblue", Color4f(240, 248, 255)) ("aliceblue", Color4f(240, 248, 255))
("antiquewhite", Color4f(250, 235, 215)) ("antiquewhite", Color4f(250, 235, 215))
@ -170,6 +172,7 @@ ColorModule::ColorModule()
("plum", Color4f(221, 160, 221)) ("plum", Color4f(221, 160, 221))
("powderblue", Color4f(176, 224, 230)) ("powderblue", Color4f(176, 224, 230))
("purple", Color4f(128, 0, 128)) ("purple", Color4f(128, 0, 128))
("rebeccapurple", Color4f(102, 51, 153))
("red", Color4f(255, 0, 0)) ("red", Color4f(255, 0, 0))
("rosybrown", Color4f(188, 143, 143)) ("rosybrown", Color4f(188, 143, 143))
("royalblue", Color4f(65, 105, 225)) ("royalblue", Color4f(65, 105, 225))
@ -191,7 +194,6 @@ ColorModule::ColorModule()
("teal", Color4f(0, 128, 128)) ("teal", Color4f(0, 128, 128))
("thistle", Color4f(216, 191, 216)) ("thistle", Color4f(216, 191, 216))
("tomato", Color4f(255, 99, 71)) ("tomato", Color4f(255, 99, 71))
("transparent", Color4f(0, 0, 0, 0))
("turquoise", Color4f(64, 224, 208)) ("turquoise", Color4f(64, 224, 208))
("violet", Color4f(238, 130, 238)) ("violet", Color4f(238, 130, 238))
("wheat", Color4f(245, 222, 179)) ("wheat", Color4f(245, 222, 179))
@ -199,6 +201,9 @@ ColorModule::ColorModule()
("whitesmoke", Color4f(245, 245, 245)) ("whitesmoke", Color4f(245, 245, 245))
("yellow", Color4f(255, 255, 0)) ("yellow", Color4f(255, 255, 0))
("yellowgreen", Color4f(154, 205, 50)) ("yellowgreen", Color4f(154, 205, 50))
// additional OpenSCAD specific entry
("transparent", Color4f(0, 0, 0, 0))
.convert_to_container<boost::unordered_map<std::string, Color4f> >(); .convert_to_container<boost::unordered_map<std::string, Color4f> >();
} }
@ -224,7 +229,7 @@ AbstractNode *ColorModule::instantiate(const Context *ctx, const ModuleInstantia
ValuePtr v = c.lookup_variable("c"); ValuePtr v = c.lookup_variable("c");
if (v->type() == Value::VECTOR) { if (v->type() == Value::VECTOR) {
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
node->color[i] = i < v->toVector().size() ? v->toVector()[i].toDouble() : 1.0; node->color[i] = i < v->toVector().size() ? v->toVector()[i]->toDouble() : 1.0;
if (node->color[i] > 1) if (node->color[i] > 1)
PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]); PRINTB_NOCACHE("WARNING: color() expects numbers between 0.0 and 1.0. Value of %.1f is too large.", node->color[i]);
} }

View file

@ -37,6 +37,7 @@ RenderColorScheme::RenderColorScheme() : _path("")
_show_in_gui = true; _show_in_gui = true;
_color_scheme.insert(ColorScheme::value_type(BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5))); _color_scheme.insert(ColorScheme::value_type(BACKGROUND_COLOR, Color4f(0xff, 0xff, 0xe5)));
_color_scheme.insert(ColorScheme::value_type(AXES_COLOR, Color4f(0x00, 0x00, 0x00)));
_color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))); _color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)));
_color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51))); _color_scheme.insert(ColorScheme::value_type(OPENCSG_FACE_BACK_COLOR, Color4f(0x9d, 0xcb, 0x51)));
_color_scheme.insert(ColorScheme::value_type(CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c))); _color_scheme.insert(ColorScheme::value_type(CGAL_FACE_FRONT_COLOR, Color4f(0xf9, 0xd7, 0x2c)));
@ -57,6 +58,7 @@ RenderColorScheme::RenderColorScheme(fs::path path) : _path(path)
_show_in_gui = pt.get<bool>("show-in-gui"); _show_in_gui = pt.get<bool>("show-in-gui");
addColor(BACKGROUND_COLOR, "background"); addColor(BACKGROUND_COLOR, "background");
addColor(AXES_COLOR, "axes-color");
addColor(OPENCSG_FACE_FRONT_COLOR, "opencsg-face-front"); addColor(OPENCSG_FACE_FRONT_COLOR, "opencsg-face-front");
addColor(OPENCSG_FACE_BACK_COLOR, "opencsg-face-back"); addColor(OPENCSG_FACE_BACK_COLOR, "opencsg-face-back");
addColor(CGAL_FACE_FRONT_COLOR, "cgal-face-front"); addColor(CGAL_FACE_FRONT_COLOR, "cgal-face-front");
@ -67,7 +69,7 @@ RenderColorScheme::RenderColorScheme(fs::path path) : _path(path)
addColor(CGAL_EDGE_2D_COLOR, "cgal-edge-2d"); addColor(CGAL_EDGE_2D_COLOR, "cgal-edge-2d");
addColor(CROSSHAIR_COLOR, "crosshair"); addColor(CROSSHAIR_COLOR, "crosshair");
} catch (const std::exception & e) { } catch (const std::exception & e) {
PRINTB("Error reading color scheme file '%s': %s", path.c_str() % e.what()); PRINTB("Error reading color scheme file '%s': %s", boosty::stringy(path).c_str() % e.what());
_error = e.what(); _error = e.what();
_name = ""; _name = "";
_index = 0; _index = 0;
@ -261,7 +263,7 @@ void ColorMap::enumerateColorSchemesInPath(colorscheme_set_t &result_set, const
{ {
const fs::path color_schemes = basePath / "color-schemes" / "render"; const fs::path color_schemes = basePath / "color-schemes" / "render";
PRINTDB("Enumerating color schemes from '%s'", color_schemes.string().c_str()); PRINTDB("Enumerating color schemes from '%s'", boosty::stringy(color_schemes).c_str());
fs::directory_iterator end_iter; fs::directory_iterator end_iter;
@ -272,7 +274,7 @@ void ColorMap::enumerateColorSchemesInPath(colorscheme_set_t &result_set, const
} }
const fs::path path = (*dir_iter).path(); const fs::path path = (*dir_iter).path();
if (!(path.extension().string() == ".json")) { if (!(path.extension() == ".json")) {
continue; continue;
} }

View file

@ -13,6 +13,7 @@ namespace fs = boost::filesystem;
enum RenderColor { enum RenderColor {
BACKGROUND_COLOR, BACKGROUND_COLOR,
AXES_COLOR,
OPENCSG_FACE_FRONT_COLOR, OPENCSG_FACE_FRONT_COLOR,
OPENCSG_FACE_BACK_COLOR, OPENCSG_FACE_BACK_COLOR,
CGAL_FACE_FRONT_COLOR, CGAL_FACE_FRONT_COLOR,

View file

@ -63,7 +63,7 @@ public: // methods
static const EvalContext* getLastModuleCtx(const EvalContext *evalctx); static const EvalContext* getLastModuleCtx(const EvalContext *evalctx);
static AbstractNode* getChild(const Value &value, const EvalContext* modulectx); static AbstractNode* getChild(const ValuePtr &value, const EvalContext* modulectx);
private: // data private: // data
Type type; Type type;
@ -78,15 +78,15 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
ValuePtr it_values = evalctx->getArgValue(l, ctx); ValuePtr it_values = evalctx->getArgValue(l, ctx);
Context c(ctx); Context c(ctx);
if (it_values->type() == Value::RANGE) { if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values->toRange(); RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps(); boost::uint32_t steps = range.numValues();
if (steps >= 10000) { if (steps >= 10000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else { } else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { for (RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it)); c.set_variable(it_name, ValuePtr(*it));
for_eval(node, inst, l+1, &c, evalctx); for_eval(node, inst, l+1, &c, evalctx);
} }
} }
} }
else if (it_values->type() == Value::VECTOR) { else if (it_values->type() == Value::VECTOR) {
@ -133,17 +133,17 @@ const EvalContext* ControlModule::getLastModuleCtx(const EvalContext *evalctx)
} }
// static // static
AbstractNode* ControlModule::getChild(const Value& value, const EvalContext* modulectx) AbstractNode* ControlModule::getChild(const ValuePtr &value, const EvalContext* modulectx)
{ {
if (value.type()!=Value::NUMBER) { if (value->type()!=Value::NUMBER) {
// Invalid parameter // Invalid parameter
// (e.g. first child of difference is invalid) // (e.g. first child of difference is invalid)
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value.toString()); PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value->toString());
return NULL; return NULL;
} }
double v; double v;
if (!value.getDouble(v)) { if (!value->getDouble(v)) {
PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value.toString()); PRINTB("WARNING: Bad parameter type (%s) for children, only accept: empty, number, vector, range.", value->toString());
return NULL; return NULL;
} }
@ -223,12 +223,12 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
// one (or more ignored) parameter // one (or more ignored) parameter
ValuePtr value = evalctx->getArgValue(0); ValuePtr value = evalctx->getArgValue(0);
if (value->type() == Value::NUMBER) { if (value->type() == Value::NUMBER) {
return getChild(*value, modulectx); return getChild(value, modulectx);
} }
else if (value->type() == Value::VECTOR) { else if (value->type() == Value::VECTOR) {
AbstractNode* node = new AbstractNode(inst); AbstractNode* node = new AbstractNode(inst);
const Value::VectorType& vect = value->toVector(); const Value::VectorType& vect = value->toVector();
foreach (const Value::VectorType::value_type& vectvalue, vect) { foreach (const ValuePtr &vectvalue, vect) {
AbstractNode* childnode = getChild(vectvalue,modulectx); AbstractNode* childnode = getChild(vectvalue,modulectx);
if (childnode==NULL) continue; // error if (childnode==NULL) continue; // error
node->children.push_back(childnode); node->children.push_back(childnode);
@ -236,15 +236,15 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
return node; return node;
} }
else if (value->type() == Value::RANGE) { else if (value->type() == Value::RANGE) {
AbstractNode* node = new AbstractNode(inst); RangeType range = value->toRange();
Value::RangeType range = value->toRange(); boost::uint32_t steps = range.numValues();
boost::uint32_t steps = range.nbsteps();
if (steps >= 10000) { if (steps >= 10000) {
PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps); PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps);
return NULL; return NULL;
} }
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { AbstractNode* node = new AbstractNode(inst);
AbstractNode* childnode = getChild(Value(*it),modulectx); // with error cases for (RangeType::iterator it = range.begin();it != range.end();it++) {
AbstractNode* childnode = getChild(ValuePtr(*it),modulectx); // with error cases
if (childnode==NULL) continue; // error if (childnode==NULL) continue; // error
node->children.push_back(childnode); node->children.push_back(childnode);
} }

View file

@ -68,7 +68,7 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, shared_ptr<CSGTerm> left
} }
} }
// Pruning the tree. For details, see: // Pruning the tree. For details, see "Solid Modeling" by Goldfeather:
// http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf // http://www.cc.gatech.edu/~turk/my_papers/pxpl_csg.pdf
const BoundingBox &leftbox = left->getBoundingBox(); const BoundingBox &leftbox = left->getBoundingBox();
const BoundingBox &rightbox = right->getBoundingBox(); const BoundingBox &rightbox = right->getBoundingBox();

View file

@ -200,8 +200,8 @@ ValuePtr builtin_dxf_cross(const Context *ctx, const EvalContext *evalctx)
double x = x1 + ua*(x2 - x1); double x = x1 + ua*(x2 - x1);
double y = y1 + ua*(y2 - y1); double y = y1 + ua*(y2 - y1);
Value::VectorType ret; Value::VectorType ret;
ret.push_back(Value(x)); ret.push_back(ValuePtr(x));
ret.push_back(Value(y)); ret.push_back(ValuePtr(y));
return dxf_cross_cache[key] = ValuePtr(ret); return dxf_cross_cache[key] = ValuePtr(ret);
} }
} }

View file

@ -106,7 +106,7 @@ void exportFileByName(const class Geometry *root_geom, FileFormat format,
{ {
std::ofstream fstream(name2open); std::ofstream fstream(name2open);
if (!fstream.is_open()) { if (!fstream.is_open()) {
PRINTB("Can't open file \"%s\" for export", name2display); PRINTB(_("Can't open file \"%s\" for export"), name2display);
} else { } else {
bool onerror = false; bool onerror = false;
fstream.exceptions(std::ios::badbit|std::ios::failbit); fstream.exceptions(std::ios::badbit|std::ios::failbit);
@ -121,7 +121,7 @@ void exportFileByName(const class Geometry *root_geom, FileFormat format,
onerror = true; onerror = true;
} }
if (onerror) { if (onerror) {
PRINTB("ERROR: \"%s\" write error. (Disk full?)", name2display); PRINTB(_("ERROR: \"%s\" write error. (Disk full?)"), name2display);
} }
} }
} }
@ -424,6 +424,7 @@ void export_amf(const CGAL_Nef_polyhedron *root_N, std::ostream &output)
coords = strtok(NULL, " "); coords = strtok(NULL, " ");
output << " <z>" << coords << "</z>\r\n"; output << " <z>" << coords << "</z>\r\n";
output << " </coordinates></vertex>\r\n"; output << " </coordinates></vertex>\r\n";
delete[] chrs;
} }
output << " </vertices>\r\n"; output << " </vertices>\r\n";
output << " <volume>\r\n"; output << " <volume>\r\n";

View file

@ -41,12 +41,12 @@ namespace {
Value::VectorType flatten(Value::VectorType const& vec) { Value::VectorType flatten(Value::VectorType const& vec) {
int n = 0; int n = 0;
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
assert(vec[i].type() == Value::VECTOR); assert(vec[i]->type() == Value::VECTOR);
n += vec[i].toVector().size(); n += vec[i]->toVector().size();
} }
Value::VectorType ret; ret.reserve(n); Value::VectorType ret; ret.reserve(n);
for (unsigned int i = 0; i < vec.size(); i++) { for (unsigned int i = 0; i < vec.size(); i++) {
std::copy(vec[i].toVector().begin(),vec[i].toVector().end(),std::back_inserter(ret)); std::copy(vec[i]->toVector().begin(),vec[i]->toVector().end(),std::back_inserter(ret));
} }
return ret; return ret;
} }
@ -357,7 +357,7 @@ ExpressionConst::ExpressionConst(const ValuePtr &val) : const_value(val)
ValuePtr ExpressionConst::evaluate(const class Context *) const ValuePtr ExpressionConst::evaluate(const class Context *) const
{ {
return ValuePtr(this->const_value); return this->const_value;
} }
void ExpressionConst::print(std::ostream &stream) const void ExpressionConst::print(std::ostream &stream) const
@ -380,12 +380,12 @@ ValuePtr ExpressionRange::evaluate(const Context *context) const
ValuePtr v2 = this->second->evaluate(context); ValuePtr v2 = this->second->evaluate(context);
if (v2->type() == Value::NUMBER) { if (v2->type() == Value::NUMBER) {
if (this->children.size() == 2) { if (this->children.size() == 2) {
Value::RangeType range(v1->toDouble(), v2->toDouble()); RangeType range(v1->toDouble(), v2->toDouble());
return ValuePtr(range); return ValuePtr(range);
} else { } else {
ValuePtr v3 = this->third->evaluate(context); ValuePtr v3 = this->third->evaluate(context);
if (v3->type() == Value::NUMBER) { if (v3->type() == Value::NUMBER) {
Value::RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble()); RangeType range(v1->toDouble(), v2->toDouble(), v3->toDouble());
return ValuePtr(range); return ValuePtr(range);
} }
} }
@ -409,7 +409,8 @@ ValuePtr ExpressionVector::evaluate(const Context *context) const
{ {
Value::VectorType vec; Value::VectorType vec;
BOOST_FOREACH(const Expression *e, this->children) { BOOST_FOREACH(const Expression *e, this->children) {
vec.push_back(*(e->evaluate(context))); ValuePtr tmpval = e->evaluate(context);
vec.push_back(tmpval);
} }
return ValuePtr(vec); return ValuePtr(vec);
} }
@ -545,7 +546,7 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
if (this->second->isListComprehension()) { if (this->second->isListComprehension()) {
return this->second->evaluate(context); return this->second->evaluate(context);
} else { } else {
vec.push_back((*this->second->evaluate(context))); vec.push_back(this->second->evaluate(context));
} }
} }
return ValuePtr(vec); return ValuePtr(vec);
@ -561,26 +562,26 @@ ValuePtr ExpressionLc::evaluate(const Context *context) const
Context c(context); Context c(context);
if (it_values->type() == Value::RANGE) { if (it_values->type() == Value::RANGE) {
Value::RangeType range = it_values->toRange(); RangeType range = it_values->toRange();
boost::uint32_t steps = range.nbsteps(); boost::uint32_t steps = range.numValues();
if (steps >= 1000000) { if (steps >= 1000000) {
PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps); PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
} else { } else {
for (Value::RangeType::iterator it = range.begin();it != range.end();it++) { for (RangeType::iterator it = range.begin();it != range.end();it++) {
c.set_variable(it_name, ValuePtr(*it)); c.set_variable(it_name, ValuePtr(*it));
vec.push_back((*this->first->evaluate(&c))); vec.push_back(this->first->evaluate(&c));
} }
} }
} }
else if (it_values->type() == Value::VECTOR) { else if (it_values->type() == Value::VECTOR) {
for (size_t i = 0; i < it_values->toVector().size(); i++) { for (size_t i = 0; i < it_values->toVector().size(); i++) {
c.set_variable(it_name, it_values->toVector()[i]); c.set_variable(it_name, it_values->toVector()[i]);
vec.push_back((*this->first->evaluate(&c))); vec.push_back(this->first->evaluate(&c));
} }
} }
else if (it_values->type() != Value::UNDEFINED) { else if (it_values->type() != Value::UNDEFINED) {
c.set_variable(it_name, it_values); c.set_variable(it_name, it_values);
vec.push_back((*this->first->evaluate(&c))); vec.push_back(this->first->evaluate(&c));
} }
if (this->first->isListComprehension()) { if (this->first->isListComprehension()) {
return ValuePtr(flatten(vec)); return ValuePtr(flatten(vec));

View file

@ -24,13 +24,13 @@
* *
*/ */
#include "mathc99.h"
#include "function.h" #include "function.h"
#include "expression.h" #include "expression.h"
#include "evalcontext.h" #include "evalcontext.h"
#include "builtin.h" #include "builtin.h"
#include <sstream> #include <sstream>
#include <ctime> #include <ctime>
#include "mathc99.h"
#include <limits> #include <limits>
#include <algorithm> #include <algorithm>
#include "stl-utils.h" #include "stl-utils.h"
@ -50,10 +50,13 @@ using boost::math::isinf;
auto/bind()s for random function objects, but we are supporting older systems. auto/bind()s for random function objects, but we are supporting older systems.
*/ */
#include"boost-utils.h"
#include <boost/random/mersenne_twister.hpp> #include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real.hpp> #include <boost/random/uniform_real.hpp>
/*Unicode support for string lengths and array accesses*/ /*Unicode support for string lengths and array accesses*/
#include <glib.h> #include <glib.h>
// hash double
#include "linalg.h"
#ifdef __WIN32__ #ifdef __WIN32__
#include <process.h> #include <process.h>
@ -238,34 +241,51 @@ ValuePtr builtin_rands(const Context *, const EvalContext *evalctx)
if (v0->type() != Value::NUMBER) goto quit; if (v0->type() != Value::NUMBER) goto quit;
double min = v0->toDouble(); double min = v0->toDouble();
if (boost::math::isinf(min)) {
PRINT("WARNING: rands() range min cannot be infinite");
min = -std::numeric_limits<double>::max()/2;
PRINTB("WARNING: resetting to %f",min);
}
ValuePtr v1 = evalctx->getArgValue(1); ValuePtr v1 = evalctx->getArgValue(1);
if (v1->type() != Value::NUMBER) goto quit; if (v1->type() != Value::NUMBER) goto quit;
double max = v1->toDouble(); double max = v1->toDouble();
if (boost::math::isinf(max)) {
PRINT("WARNING: rands() range max cannot be infinite");
max = std::numeric_limits<double>::max()/2;
PRINTB("WARNING: resetting to %f",max);
}
if (max < min) { if (max < min) {
register double tmp = min; min = max; max = tmp; register double tmp = min; min = max; max = tmp;
} }
ValuePtr v2 = evalctx->getArgValue(2); ValuePtr v2 = evalctx->getArgValue(2);
if (v2->type() != Value::NUMBER) goto quit; if (v2->type() != Value::NUMBER) goto quit;
size_t numresults = std::max(0, static_cast<int>(v2->toDouble())); double numresultsd = std::abs( v2->toDouble() );
if (boost::math::isinf(numresultsd)) {
PRINT("WARNING: rands() cannot create an infinite number of results");
PRINT("WARNING: resetting number of results to 1");
numresultsd = 1;
}
size_t numresults = boost_numeric_cast<size_t,double>( numresultsd );
bool deterministic = false; bool deterministic = false;
if (n > 3) { if (n > 3) {
ValuePtr v3 = evalctx->getArgValue(3); ValuePtr v3 = evalctx->getArgValue(3);
if (v3->type() != Value::NUMBER) goto quit; if (v3->type() != Value::NUMBER) goto quit;
deterministic_rng.seed((unsigned int) v3->toDouble()); uint32_t seed = static_cast<uint32_t>(hash_floating_point( v3->toDouble() ));
deterministic_rng.seed( seed );
deterministic = true; deterministic = true;
} }
Value::VectorType vec; Value::VectorType vec;
if (min==max) { // Boost doesn't allow min == max if (min==max) { // Boost doesn't allow min == max
for (size_t i=0; i < numresults; i++) for (size_t i=0; i < numresults; i++)
vec.push_back( Value( min ) ); vec.push_back(ValuePtr(min));
} else { } else {
boost::uniform_real<> distributor( min, max ); boost::uniform_real<> distributor( min, max );
for (size_t i=0; i < numresults; i++) { for (size_t i=0; i < numresults; i++) {
if ( deterministic ) { if ( deterministic ) {
vec.push_back(Value(distributor(deterministic_rng))); vec.push_back(ValuePtr(distributor(deterministic_rng)));
} else { } else {
vec.push_back(Value(distributor(lessdeterministic_rng))); vec.push_back(ValuePtr(distributor(lessdeterministic_rng)));
} }
} }
} }
@ -285,11 +305,11 @@ ValuePtr builtin_min(const Context *, const EvalContext *evalctx)
ValuePtr v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) { if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value min = v0->toVector()[0]; ValuePtr min = v0->toVector()[0];
for (size_t i = 1; i < v0->toVector().size(); i++) { for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0->toVector()[i] < min) min = v0->toVector()[i]; if (v0->toVector()[i] < min) min = v0->toVector()[i];
} }
return ValuePtr(min); return min;
} }
if (v0->type() == Value::NUMBER) { if (v0->type() == Value::NUMBER) {
double val = v0->toDouble(); double val = v0->toDouble();
@ -317,11 +337,11 @@ ValuePtr builtin_max(const Context *, const EvalContext *evalctx)
ValuePtr v0 = evalctx->getArgValue(0); ValuePtr v0 = evalctx->getArgValue(0);
if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) { if (n == 1 && v0->type() == Value::VECTOR && !v0->toVector().empty()) {
Value max = v0->toVector()[0]; ValuePtr max = v0->toVector()[0];
for (size_t i = 1; i < v0->toVector().size(); i++) { for (size_t i = 1; i < v0->toVector().size(); i++) {
if (v0->toVector()[i] > max) max = v0->toVector()[i]; if (v0->toVector()[i] > max) max = v0->toVector()[i];
} }
return ValuePtr(max); return max;
} }
if (v0->type() == Value::NUMBER) { if (v0->type() == Value::NUMBER) {
double val = v0->toDouble(); double val = v0->toDouble();
@ -614,14 +634,13 @@ ValuePtr builtin_concat(const Context *, const EvalContext *evalctx)
Value::VectorType result; Value::VectorType result;
for (size_t i = 0; i < evalctx->numArgs(); i++) { for (size_t i = 0; i < evalctx->numArgs(); i++) {
ValuePtr v = evalctx->getArgValue(i); ValuePtr val = evalctx->getArgValue(i);
if (v->type() == Value::VECTOR) { if (val->type() == Value::VECTOR) {
Value::VectorType vec = v->toVector(); BOOST_FOREACH(const ValuePtr &v, val->toVector()) {
for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) { result.push_back(v);
result.push_back(*it);
} }
} else { } else {
result.push_back(*v); result.push_back(val);
} }
} }
return ValuePtr(result); return ValuePtr(result);
@ -636,13 +655,13 @@ ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx)
ValuePtr v1 = evalctx->getArgValue(1); ValuePtr v1 = evalctx->getArgValue(1);
const Value::VectorType &vec = v1->toVector(); const Value::VectorType &vec = v1->toVector();
if (vec[0].toVector().size() < 2) // Second must be a vector of vectors if (vec[0]->toVector().size() < 2) // Second must be a vector of vectors
return ValuePtr::undefined; return ValuePtr::undefined;
if (!vec[0].getVec2(low_p, low_v) || !vec[0].getVec2(high_p, high_v)) if (!vec[0]->getVec2(low_p, low_v) || !vec[0]->getVec2(high_p, high_v))
return ValuePtr::undefined; return ValuePtr::undefined;
for (size_t i = 1; i < vec.size(); i++) { for (size_t i = 1; i < vec.size(); i++) {
double this_p, this_v; double this_p, this_v;
if (vec[i].getVec2(this_p, this_v)) { if (vec[i]->getVec2(this_p, this_v)) {
if (this_p <= p && (this_p > low_p || low_p > p)) { if (this_p <= p && (this_p > low_p || low_p > p)) {
low_p = this_p; low_p = this_p;
low_v = this_v; low_v = this_v;
@ -727,10 +746,10 @@ static Value::VectorType search(const std::string &find, const std::string &tabl
if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) { if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
matchCount++; matchCount++;
if (num_returns_per_match == 1) { if (num_returns_per_match == 1) {
returnvec.push_back(Value(double(j))); returnvec.push_back(ValuePtr(double(j)));
break; break;
} else { } else {
resultvec.push_back(Value(double(j))); resultvec.push_back(ValuePtr(double(j)));
} }
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) { if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) {
break; break;
@ -740,10 +759,9 @@ static Value::VectorType search(const std::string &find, const std::string &tabl
if (matchCount == 0) { if (matchCount == 0) {
gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into gchar utf8_of_cp[6] = ""; //A buffer for a single unicode character to be copied into
if (ptr_ft) g_utf8_strncpy(utf8_of_cp, ptr_ft, 1); if (ptr_ft) g_utf8_strncpy(utf8_of_cp, ptr_ft, 1);
PRINTB(" WARNING: search term not found: \"%s\"", utf8_of_cp);
} }
if (num_returns_per_match == 0 || num_returns_per_match > 1) { if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec)); returnvec.push_back(ValuePtr(resultvec));
} }
} }
return returnvec; return returnvec;
@ -761,19 +779,19 @@ static Value::VectorType search(const std::string &find, const Value::VectorType
Value::VectorType resultvec; Value::VectorType resultvec;
const gchar *ptr_ft = g_utf8_offset_to_pointer(find.c_str(), i); const gchar *ptr_ft = g_utf8_offset_to_pointer(find.c_str(), i);
for (size_t j = 0; j < searchTableSize; j++) { for (size_t j = 0; j < searchTableSize; j++) {
Value::VectorType entryVec = table[j].toVector(); const Value::VectorType &entryVec = table[j]->toVector();
if (entryVec.size() <= index_col_num) { if (entryVec.size() <= index_col_num) {
PRINTB("WARNING: Invalid entry in search vector at index %d, required number of values in the entry: %d. Invalid entry: %s", j % (index_col_num + 1) % table[j]); PRINTB("WARNING: Invalid entry in search vector at index %d, required number of values in the entry: %d. Invalid entry: %s", j % (index_col_num + 1) % table[j]);
return Value::VectorType(); return Value::VectorType();
} }
const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num].toString().c_str(), 0); const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num]->toString().c_str(), 0);
if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) { if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) {
matchCount++; matchCount++;
if (num_returns_per_match == 1) { if (num_returns_per_match == 1) {
returnvec.push_back(Value(double(j))); returnvec.push_back(ValuePtr(double(j)));
break; break;
} else { } else {
resultvec.push_back(Value(double(j))); resultvec.push_back(ValuePtr(double(j)));
} }
if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) { if (num_returns_per_match > 1 && matchCount >= num_returns_per_match) {
break; break;
@ -786,7 +804,7 @@ static Value::VectorType search(const std::string &find, const Value::VectorType
PRINTB(" WARNING: search term not found: \"%s\"", utf8_of_cp); PRINTB(" WARNING: search term not found: \"%s\"", utf8_of_cp);
} }
if (num_returns_per_match == 0 || num_returns_per_match > 1) { if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(Value(resultvec)); returnvec.push_back(ValuePtr(resultvec));
} }
} }
return returnvec; return returnvec;
@ -807,12 +825,12 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
unsigned int matchCount = 0; unsigned int matchCount = 0;
for (size_t j = 0; j < searchTable->toVector().size(); j++) { for (size_t j = 0; j < searchTable->toVector().size(); j++) {
const Value &search_element = searchTable->toVector()[j]; const ValuePtr &search_element = searchTable->toVector()[j];
if ((index_col_num == 0 && *findThis == search_element) || if ((index_col_num == 0 && findThis == search_element) ||
(index_col_num < search_element.toVector().size() && (index_col_num < search_element->toVector().size() &&
*findThis == search_element.toVector()[index_col_num])) { findThis == search_element->toVector()[index_col_num])) {
returnvec.push_back(Value(double(j))); returnvec.push_back(ValuePtr(double(j)));
matchCount++; matchCount++;
if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break; if (num_returns_per_match != 0 && matchCount >= num_returns_per_match) break;
} }
@ -829,16 +847,16 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
unsigned int matchCount = 0; unsigned int matchCount = 0;
Value::VectorType resultvec; Value::VectorType resultvec;
Value const& find_value = findThis->toVector()[i]; const ValuePtr &find_value = findThis->toVector()[i];
for (size_t j = 0; j < searchTable->toVector().size(); j++) { for (size_t j = 0; j < searchTable->toVector().size(); j++) {
Value const& search_element = searchTable->toVector()[j]; const ValuePtr &search_element = searchTable->toVector()[j];
if ((index_col_num == 0 && find_value == search_element) || if ((index_col_num == 0 && find_value == search_element) ||
(index_col_num < search_element.toVector().size() && (index_col_num < search_element->toVector().size() &&
find_value == search_element.toVector()[index_col_num])) { find_value == search_element->toVector()[index_col_num])) {
Value resultValue((double(j))); ValuePtr resultValue((double(j)));
matchCount++; matchCount++;
if (num_returns_per_match == 1) { if (num_returns_per_match == 1) {
returnvec.push_back(resultValue); returnvec.push_back(resultValue);
@ -850,20 +868,13 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx)
} }
} }
if (num_returns_per_match == 1 && matchCount == 0) { if (num_returns_per_match == 1 && matchCount == 0) {
if (findThis->toVector()[i].type() == Value::NUMBER) { returnvec.push_back(ValuePtr(resultvec));
PRINTB(" WARNING: search term not found: %s",findThis->toVector()[i].toDouble());
}
else if (findThis->toVector()[i].type() == Value::STRING) {
PRINTB(" WARNING: search term not found: \"%s\"",findThis->toVector()[i].toString());
}
returnvec.push_back(resultvec);
} }
if (num_returns_per_match == 0 || num_returns_per_match > 1) { if (num_returns_per_match == 0 || num_returns_per_match > 1) {
returnvec.push_back(resultvec); returnvec.push_back(ValuePtr(resultvec));
} }
} }
} else { } else {
PRINTB(" WARNING: search: none performed on input %s", findThis);
return ValuePtr::undefined; return ValuePtr::undefined;
} }
return ValuePtr(returnvec); return ValuePtr(returnvec);
@ -927,12 +938,12 @@ ValuePtr builtin_norm(const Context *, const EvalContext *evalctx)
ValuePtr val = evalctx->getArgValue(0); ValuePtr val = evalctx->getArgValue(0);
if (val->type() == Value::VECTOR) { if (val->type() == Value::VECTOR) {
double sum = 0; double sum = 0;
Value::VectorType v = val->toVector(); const Value::VectorType &v = val->toVector();
size_t n = v.size(); size_t n = v.size();
for (size_t i = 0; i < n; i++) for (size_t i = 0; i < n; i++)
if (v[i].type() == Value::NUMBER) { if (v[i]->type() == Value::NUMBER) {
// sum += pow(v[i].toDouble(),2); // sum += pow(v[i].toDouble(),2);
register double x = v[i].toDouble(); register double x = v[i]->toDouble();
sum += x*x; sum += x*x;
} else { } else {
PRINT("WARNING: Incorrect arguments to norm()"); PRINT("WARNING: Incorrect arguments to norm()");
@ -958,10 +969,10 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
return ValuePtr::undefined; return ValuePtr::undefined;
} }
Value::VectorType v0 = arg0->toVector(); const Value::VectorType &v0 = arg0->toVector();
Value::VectorType v1 = arg1->toVector(); const Value::VectorType &v1 = arg1->toVector();
if ((v0.size() == 2) && (v1.size() == 2)) { if ((v0.size() == 2) && (v1.size() == 2)) {
return ValuePtr(Value(v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble())); return ValuePtr(v0[0]->toDouble() * v1[1]->toDouble() - v0[1]->toDouble() * v1[0]->toDouble());
} }
if ((v0.size() != 3) || (v1.size() != 3)) { if ((v0.size() != 3) || (v1.size() != 3)) {
@ -969,12 +980,12 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
return ValuePtr::undefined; return ValuePtr::undefined;
} }
for (unsigned int a = 0;a < 3;a++) { for (unsigned int a = 0;a < 3;a++) {
if ((v0[a].type() != Value::NUMBER) || (v1[a].type() != Value::NUMBER)) { if ((v0[a]->type() != Value::NUMBER) || (v1[a]->type() != Value::NUMBER)) {
PRINT("WARNING: Invalid value in parameter vector for cross()"); PRINT("WARNING: Invalid value in parameter vector for cross()");
return ValuePtr::undefined; return ValuePtr::undefined;
} }
double d0 = v0[a].toDouble(); double d0 = v0[a]->toDouble();
double d1 = v1[a].toDouble(); double d1 = v1[a]->toDouble();
if (boost::math::isnan(d0) || boost::math::isnan(d1)) { if (boost::math::isnan(d0) || boost::math::isnan(d1)) {
PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()"); PRINT("WARNING: Invalid value (NaN) in parameter vector for cross()");
return ValuePtr::undefined; return ValuePtr::undefined;
@ -985,14 +996,14 @@ ValuePtr builtin_cross(const Context *, const EvalContext *evalctx)
} }
} }
double x = v0[1].toDouble() * v1[2].toDouble() - v0[2].toDouble() * v1[1].toDouble(); double x = v0[1]->toDouble() * v1[2]->toDouble() - v0[2]->toDouble() * v1[1]->toDouble();
double y = v0[2].toDouble() * v1[0].toDouble() - v0[0].toDouble() * v1[2].toDouble(); double y = v0[2]->toDouble() * v1[0]->toDouble() - v0[0]->toDouble() * v1[2]->toDouble();
double z = v0[0].toDouble() * v1[1].toDouble() - v0[1].toDouble() * v1[0].toDouble(); double z = v0[0]->toDouble() * v1[1]->toDouble() - v0[1]->toDouble() * v1[0]->toDouble();
Value::VectorType result; Value::VectorType result;
result.push_back(Value(x)); result.push_back(ValuePtr(x));
result.push_back(Value(y)); result.push_back(ValuePtr(y));
result.push_back(Value(z)); result.push_back(ValuePtr(z));
return ValuePtr(result); return ValuePtr(result);
} }

View file

@ -3,7 +3,7 @@
#include "mathc99.h" #include "mathc99.h"
#include "linalg.h" #include "linalg.h"
#ifdef WIN32 #ifdef _WIN32
typedef __int64 int64_t; typedef __int64 int64_t;
#else #else
#include <stdint.h> #include <stdint.h>

View file

@ -319,10 +319,7 @@ std::string ImportNode::toString() const
"scale = " << this->scale << ", " "scale = " << this->scale << ", "
"convexity = " << this->convexity << ", " "convexity = " << this->convexity << ", "
"$fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs "$fn = " << this->fn << ", $fa = " << this->fa << ", $fs = " << this->fs
#ifndef OPENSCAD_TESTING
// timestamp is needed for caching, but disturbs the test framework
<< ", " "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0) << ", " "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0)
#endif
<< ")"; << ")";

View file

@ -46,3 +46,72 @@ bool matrix_contains_nan( const Transform3d &m )
} }
return false; return false;
} }
/* Hash a floating point number, copied almost line by line from
Python's pyhash.c, originally by the Python team, Mark Dickinson, et al.
The copyright License for this code can be found in under
../doc/Python-LICENSE.TXT. Changes from the original code include
de-scattering typedefs, and removing the -1 special return case.
This is designed so srand() will work better with floating point
numbers. An oversimplified explanation is that the code calculates the
Remainder of the input divided by 2^31, in a very portable way. See also:
http://bob.ippoli.to/archives/2010/03/23/py3k-unified-numeric-hash/
https://github.com/python/cpython/blob/master/Python/pyhash.c
https://github.com/python/cpython/blob/master/Include/pyhash.h
http://stackoverflow.com/questions/4238122/hash-function-for-floats
http://betterexplained.com/articles/fun-with-modular-arithmetic/
*/
typedef int32_t Py_hash_t;
typedef uint32_t Py_uhash_t;
typedef double Float_t;
Py_hash_t hash_floating_point(Float_t v)
{
int _PyHASH_BITS = 31;
//if (sizeof(Py_uhash_t)==8) _PyHASH_BITS=61;
Py_uhash_t _PyHASH_MODULUS = (((Py_uhash_t)1 << _PyHASH_BITS) - 1);
Py_uhash_t _PyHASH_INF = 314159;
Py_uhash_t _PyHASH_NAN = 0;
int e, sign;
Float_t m;
Py_uhash_t x, y;
if (!std::isfinite(v)) {
if (std::isinf(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
else
return _PyHASH_NAN;
}
m = frexp(v, &e);
sign = 1;
if (m < 0) {
sign = -1;
m = -m;
}
/* process 28 bits at a time; this should work well both for binary
and hexadecimal floating point. */
x = 0;
while (m) {
x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28);
m *= 268435456.0; // 2**28
e -= 28;
y = (Py_uhash_t)m; /* pull out integer part */
m -= y;
x += y;
if (x >= _PyHASH_MODULUS)
x -= _PyHASH_MODULUS;
}
/* adjust for the exponent; first reduce it modulo _PyHASH_BITS */
e = e >= 0 ? e % _PyHASH_BITS : _PyHASH_BITS-1-((-1-e) % _PyHASH_BITS);
x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e);
x = x * sign;
return (Py_hash_t)x;
}

View file

@ -4,6 +4,7 @@
#include <Eigen/Geometry> #include <Eigen/Geometry>
#include <Eigen/Dense> #include <Eigen/Dense>
#include <Eigen/StdVector> #include <Eigen/StdVector>
#include <boost/cstdint.hpp>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d) EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)
using Eigen::Vector2d; using Eigen::Vector2d;
@ -23,6 +24,7 @@ using Eigen::Matrix4d;
bool matrix_contains_infinity( const Transform3d &m ); bool matrix_contains_infinity( const Transform3d &m );
bool matrix_contains_nan( const Transform3d &m ); bool matrix_contains_nan( const Transform3d &m );
int32_t hash_floating_point( double v );
template<typename Derived> bool is_finite(const Eigen::MatrixBase<Derived>& x) { template<typename Derived> bool is_finite(const Eigen::MatrixBase<Derived>& x) {
return ( (x - x).array() == (x - x).array()).all(); return ( (x - x).array() == (x - x).array()).all();

View file

@ -90,13 +90,13 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
node->layername = layer->isUndefined() ? "" : layer->toString(); node->layername = layer->isUndefined() ? "" : layer->toString();
node->height = 100; node->height = 100;
height->getDouble(node->height); height->getFiniteDouble(node->height);
node->convexity = (int)convexity->toDouble(); node->convexity = (int)convexity->toDouble();
origin->getVec2(node->origin_x, node->origin_y); origin->getVec2(node->origin_x, node->origin_y, true);
node->scale_x = node->scale_y = 1; node->scale_x = node->scale_y = 1;
scale->getDouble(node->scale_x); scale->getFiniteDouble(node->scale_x);
scale->getDouble(node->scale_y); scale->getFiniteDouble(node->scale_y);
scale->getVec2(node->scale_x, node->scale_y); scale->getVec2(node->scale_x, node->scale_y, true);
if (center->type() == Value::BOOL) if (center->type() == Value::BOOL)
node->center = center->toBool(); node->center = center->toBool();
@ -109,17 +109,17 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI
if (node->scale_x < 0) node->scale_x = 0; if (node->scale_x < 0) node->scale_x = 0;
if (node->scale_y < 0) node->scale_y = 0; if (node->scale_y < 0) node->scale_y = 0;
if (slices->type() == Value::NUMBER) node->slices = (int)slices->toDouble(); double slicesVal = 0;
slices->getFiniteDouble(slicesVal);
node->slices = (int)slicesVal;
if (twist->type() == Value::NUMBER) { node->twist = 0.0;
node->twist = twist->toDouble(); twist->getFiniteDouble(node->twist);
if (node->twist != 0.0) { if (node->twist != 0.0) {
if (node->slices == 0) { if (node->slices == 0) {
node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height, node->slices = (int)fmax(2, fabs(Calc::get_fragments_from_r(node->height, node->fn, node->fs, node->fa) * node->twist / 360));
node->fn, node->fs, node->fa) * node->twist / 360));
}
node->has_twist = true;
} }
node->has_twist = true;
} }
node->slices = std::max(node->slices, 1); node->slices = std::max(node->slices, 1);
@ -142,10 +142,7 @@ std::string LinearExtrudeNode::toString() const
"file = " << this->filename << ", " "file = " << this->filename << ", "
"layer = " << QuotedString(this->layername) << ", " "layer = " << QuotedString(this->layername) << ", "
"origin = [" << this->origin_x << ", " << this->origin_y << "], " "origin = [" << this->origin_x << ", " << this->origin_y << "], "
#ifndef OPENSCAD_TESTING
// timestamp is needed for caching, but disturbs the test framework
<< "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0) << ", " << "timestamp = " << (fs::exists(path) ? fs::last_write_time(path) : 0) << ", "
#endif
; ;
} }
stream << stream <<

View file

@ -93,6 +93,16 @@
#include <QClipboard> #include <QClipboard>
#include <QDesktopWidget> #include <QDesktopWidget>
#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
// Set dummy for Qt versions that do not have QSaveFile
#define QT_FILE_SAVE_CLASS QFile
#define QT_FILE_SAVE_COMMIT true
#else
#include <QSaveFile>
#define QT_FILE_SAVE_CLASS QSaveFile
#define QT_FILE_SAVE_COMMIT if (saveOk) { saveOk = file.commit(); } else { file.cancelWriting(); }
#endif
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
@ -243,9 +253,11 @@ MainWindow::MainWindow(const QString &filename)
background_chain = NULL; background_chain = NULL;
root_node = NULL; root_node = NULL;
tval = 0; this->anim_step = 0;
fps = 0; this->anim_numsteps = 0;
fsteps = 1; this->anim_tval = 0.0;
this->anim_dumping = false;
this->anim_dump_start_step = 0;
const QString importStatement = "import(\"%1\");\n"; const QString importStatement = "import(\"%1\");\n";
const QString surfaceStatement = "surface(\"%1\");\n"; const QString surfaceStatement = "surface(\"%1\");\n";
@ -279,8 +291,10 @@ MainWindow::MainWindow(const QString &filename)
waitAfterReloadTimer->setInterval(200); waitAfterReloadTimer->setInterval(200);
connect(waitAfterReloadTimer, SIGNAL(timeout()), this, SLOT(waitAfterReload())); connect(waitAfterReloadTimer, SIGNAL(timeout()), this, SLOT(waitAfterReload()));
connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(actionRenderPreview())); connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimTval()));
connect(this->e_fps, SIGNAL(textChanged(QString)), this, SLOT(updatedFps())); connect(this->e_fps, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimFps()));
connect(this->e_fsteps, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimSteps()));
connect(this->e_dump, SIGNAL(toggled(bool)), this, SLOT(updatedAnimDump(bool)));
animate_panel->hide(); animate_panel->hide();
find_panel->hide(); find_panel->hide();
@ -325,6 +339,7 @@ MainWindow::MainWindow(const QString &filename)
connect(this->editActionCut, SIGNAL(triggered()), editor, SLOT(cut())); connect(this->editActionCut, SIGNAL(triggered()), editor, SLOT(cut()));
connect(this->editActionCopy, SIGNAL(triggered()), editor, SLOT(copy())); connect(this->editActionCopy, SIGNAL(triggered()), editor, SLOT(copy()));
connect(this->editActionPaste, SIGNAL(triggered()), editor, SLOT(paste())); connect(this->editActionPaste, SIGNAL(triggered()), editor, SLOT(paste()));
connect(this->editActionCopyViewport, SIGNAL(triggered()), this, SLOT(actionCopyViewport()));
connect(this->editActionIndent, SIGNAL(triggered()), editor, SLOT(indentSelection())); connect(this->editActionIndent, SIGNAL(triggered()), editor, SLOT(indentSelection()));
connect(this->editActionUnindent, SIGNAL(triggered()), editor, SLOT(unindentSelection())); connect(this->editActionUnindent, SIGNAL(triggered()), editor, SLOT(unindentSelection()));
connect(this->editActionComment, SIGNAL(triggered()), editor, SLOT(commentSelection())); connect(this->editActionComment, SIGNAL(triggered()), editor, SLOT(commentSelection()));
@ -814,33 +829,67 @@ void MainWindow::updateRecentFiles()
} }
} }
void MainWindow::updatedFps() void MainWindow::updatedAnimTval()
{
bool t_ok;
double t = this->e_tval->text().toDouble(&t_ok);
// Clamp t to 0-1
if (t_ok) {
this->anim_tval = t < 0 ? 0.0 : ((t > 1.0) ? 1.0 : t);
}
else {
this->anim_tval = 0.0;
}
actionRenderPreview();
}
void MainWindow::updatedAnimFps()
{ {
bool fps_ok; bool fps_ok;
double fps = this->e_fps->text().toDouble(&fps_ok); double fps = this->e_fps->text().toDouble(&fps_ok);
animate_timer->stop(); animate_timer->stop();
if (fps_ok && fps > 0) { if (fps_ok && fps > 0) {
this->anim_step = int(this->anim_tval * this->anim_numsteps) % this->anim_numsteps;
animate_timer->setSingleShot(false); animate_timer->setSingleShot(false);
animate_timer->setInterval(int(1000 / this->e_fps->text().toDouble())); animate_timer->setInterval(int(1000 / fps));
animate_timer->start(); animate_timer->start();
} }
} }
void MainWindow::updatedAnimSteps()
{
bool steps_ok;
int numsteps = this->e_fsteps->text().toInt(&steps_ok);
if (steps_ok) {
this->anim_numsteps = numsteps;
}
else {
this->anim_numsteps = 0;
}
anim_dumping=false;
}
void MainWindow::updatedAnimDump(bool checked)
{
if (!checked) this->anim_dumping = false;
}
// Only called from animate_timer
void MainWindow::updateTVal() void MainWindow::updateTVal()
{ {
bool fps_ok; if (this->anim_numsteps == 0) return;
double fps = this->e_fps->text().toDouble(&fps_ok);
if (fps_ok) { if (this->anim_numsteps > 1) {
if (fps <= 0) { this->anim_step = (this->anim_step + 1) % this->anim_numsteps;
actionReloadRenderPreview(); this->anim_tval = 1.0 * this->anim_step / this->anim_numsteps;
} else {
double s = this->e_fsteps->text().toDouble();
double t = this->e_tval->text().toDouble() + 1/s;
QString txt;
txt.sprintf("%.5f", t >= 1.0 ? 0.0 : t);
this->e_tval->setText(txt);
}
} }
else if (this->anim_numsteps > 0) {
this->anim_step = 0;
this->anim_tval = 0.0;
}
QString txt;
txt.sprintf("%.5f", this->anim_tval);
this->e_tval->setText(txt);
} }
void MainWindow::refreshDocument() void MainWindow::refreshDocument()
@ -1024,8 +1073,10 @@ void MainWindow::instantiateRoot()
// Invalidate renderers before we kill the CSG tree // Invalidate renderers before we kill the CSG tree
this->qglview->setRenderer(NULL); this->qglview->setRenderer(NULL);
#ifdef ENABLE_OPENCSG
delete this->opencsgRenderer; delete this->opencsgRenderer;
this->opencsgRenderer = NULL; this->opencsgRenderer = NULL;
#endif
delete this->thrownTogetherRenderer; delete this->thrownTogetherRenderer;
this->thrownTogetherRenderer = NULL; this->thrownTogetherRenderer = NULL;
@ -1107,9 +1158,11 @@ void MainWindow::compileCSG(bool procevents)
#else #else
// FIXME: Will we support this? // FIXME: Will we support this?
#endif #endif
#ifdef ENABLE_OPENCSG
CSGTermEvaluator csgrenderer(this->tree, &geomevaluator); CSGTermEvaluator csgrenderer(this->tree, &geomevaluator);
if (procevents) QApplication::processEvents(); if (procevents) QApplication::processEvents();
this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms);
#endif
GeometryCache::instance()->print(); GeometryCache::instance()->print();
#ifdef ENABLE_CGAL #ifdef ENABLE_CGAL
CGALCache::instance()->print(); CGALCache::instance()->print();
@ -1169,6 +1222,7 @@ void MainWindow::compileCSG(bool procevents)
PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size()); PRINTB("WARNING: Normalized tree has %d elements!", this->root_chain->objects.size());
PRINT("WARNING: OpenCSG rendering has been disabled."); PRINT("WARNING: OpenCSG rendering has been disabled.");
} }
#ifdef ENABLE_OPENCSG
else { else {
PRINTB("Normalized CSG tree has %d elements", PRINTB("Normalized CSG tree has %d elements",
(this->root_chain ? this->root_chain->objects.size() : 0)); (this->root_chain ? this->root_chain->objects.size() : 0));
@ -1177,6 +1231,7 @@ void MainWindow::compileCSG(bool procevents)
this->background_chain, this->background_chain,
this->qglview->shaderinfo); this->qglview->shaderinfo);
} }
#endif
this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain, this->thrownTogetherRenderer = new ThrownTogetherRenderer(this->root_chain,
this->highlights_chain, this->highlights_chain,
this->background_chain); this->background_chain);
@ -1321,6 +1376,16 @@ void MainWindow::saveBackup()
return writeBackup(this->tempFile); return writeBackup(this->tempFile);
} }
void MainWindow::saveError(const QIODevice &file, const std::string &msg) {
const std::string messageFormat = msg + " %s (%s)";
const char *fileName = this->fileName.toLocal8Bit().constData();
PRINTB(messageFormat.c_str(), fileName % file.errorString().toLocal8Bit().constData());
const std::string dialogFormatStr = msg + "\n\"%1\"\n(%2)";
const QString dialogFormat(dialogFormatStr.c_str());
QMessageBox::warning(this, windowTitle(), dialogFormat.arg(this->fileName).arg(file.errorString()));
}
/*! /*!
Save current document. Save current document.
Should _always_ write to disk, since this is called by SaveAs - i.e. don't try to be Should _always_ write to disk, since this is called by SaveAs - i.e. don't try to be
@ -1330,26 +1395,37 @@ void MainWindow::actionSave()
{ {
if (this->fileName.isEmpty()) { if (this->fileName.isEmpty()) {
actionSaveAs(); actionSaveAs();
return;
}
setCurrentOutput();
// If available (>= Qt 5.1), use QSaveFile to ensure the file is not
// destroyed if the device is full. Unfortunately this is not working
// as advertised (at least in Qt 5.3) as it does not detect the device
// full properly and happily commits a 0 byte file.
// Checking the QTextStream status flag after flush() seems to catch
// this condition.
QT_FILE_SAVE_CLASS file(this->fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
saveError(file, _("Failed to open file for writing"));
} }
else { else {
setCurrentOutput(); QTextStream writer(&file);
QFile file(this->fileName); writer.setCodec("UTF-8");
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { writer << this->editor->toPlainText();
PRINTB("Failed to open file for writing: %s (%s)", writer.flush();
this->fileName.toLocal8Bit().constData() % file.errorString().toLocal8Bit().constData()); bool saveOk = writer.status() == QTextStream::Ok;
QMessageBox::warning(this, windowTitle(), tr("Failed to open file for writing:\n %1 (%2)") QT_FILE_SAVE_COMMIT;
.arg(this->fileName).arg(file.errorString())); if (saveOk) {
} PRINTB(_("Saved design '%s'."), this->fileName.toLocal8Bit().constData());
else {
QTextStream writer(&file);
writer.setCodec("UTF-8");
writer << this->editor->toPlainText();
PRINTB("Saved design '%s'.", this->fileName.toLocal8Bit().constData());
this->editor->setContentModified(false); this->editor->setContentModified(false);
} else {
saveError(file, _("Error saving design"));
} }
clearCurrentOutput();
updateRecentFiles();
} }
clearCurrentOutput();
updateRecentFiles();
} }
void MainWindow::actionSaveAs() void MainWindow::actionSaveAs()
@ -1538,18 +1614,18 @@ bool MainWindow::eventFilter(QObject* obj, QEvent *event)
void MainWindow::updateTemporalVariables() void MainWindow::updateTemporalVariables()
{ {
this->top_ctx.set_variable("$t", ValuePtr(this->e_tval->text().toDouble())); this->top_ctx.set_variable("$t", ValuePtr(this->anim_tval));
Value::VectorType vpt; Value::VectorType vpt;
vpt.push_back(Value(-qglview->cam.object_trans.x())); vpt.push_back(ValuePtr(-qglview->cam.object_trans.x()));
vpt.push_back(Value(-qglview->cam.object_trans.y())); vpt.push_back(ValuePtr(-qglview->cam.object_trans.y()));
vpt.push_back(Value(-qglview->cam.object_trans.z())); vpt.push_back(ValuePtr(-qglview->cam.object_trans.z()));
this->top_ctx.set_variable("$vpt", Value(vpt)); this->top_ctx.set_variable("$vpt", ValuePtr(vpt));
Value::VectorType vpr; Value::VectorType vpr;
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.x() + 90, 360))); vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.x() + 90, 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.y(), 360))); vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.y(), 360)));
vpr.push_back(Value(fmodf(360 - qglview->cam.object_rot.z(), 360))); vpr.push_back(ValuePtr(fmodf(360 - qglview->cam.object_rot.z(), 360)));
top_ctx.set_variable("$vpr", ValuePtr(vpr)); top_ctx.set_variable("$vpr", ValuePtr(vpr));
top_ctx.set_variable("$vpd", ValuePtr(qglview->cam.zoomValue())); top_ctx.set_variable("$vpd", ValuePtr(qglview->cam.zoomValue()));
@ -1755,15 +1831,22 @@ void MainWindow::csgRender()
#endif #endif
} }
if (viewActionAnimate->isChecked() && e_dump->isChecked()) { if (e_dump->isChecked() && animate_timer->isActive()) {
// Force reading from front buffer. Some configurations will read from the back buffer here. if (anim_dumping && anim_dump_start_step == anim_step) {
glReadBuffer(GL_FRONT); anim_dumping=false;
QImage img = this->qglview->grabFrameBuffer(); e_dump->setChecked(false);
QString filename; } else {
double s = this->e_fsteps->text().toDouble(); if (!anim_dumping) {
double t = this->e_tval->text().toDouble(); anim_dumping = true;
filename.sprintf("frame%05d.png", int(round(s*t))); anim_dump_start_step = anim_step;
img.save(filename, "PNG"); }
// Force reading from front buffer. Some configurations will read from the back buffer here.
glReadBuffer(GL_FRONT);
QImage img = this->qglview->grabFrameBuffer();
QString filename;
filename.sprintf("frame%05d.png", this->anim_step);
img.save(filename, "PNG");
}
} }
compileEnded(); compileEnded();
@ -2053,8 +2136,9 @@ void MainWindow::actionExport(export_type_e, QString, QString)
assert(false && "Unknown export type"); assert(false && "Unknown export type");
break; break;
} }
exportFileByName(this->root_geom.get(), format, export_filename.toUtf8(), exportFileByName(this->root_geom.get(), format,
export_filename.toLocal8Bit().constData()); export_filename.toLocal8Bit().constData(),
export_filename.toUtf8());
PRINTB("%s export finished.", type_name); PRINTB("%s export finished.", type_name);
clearCurrentOutput(); clearCurrentOutput();
@ -2184,6 +2268,13 @@ void MainWindow::actionExportImage()
return; return;
} }
void MainWindow::actionCopyViewport()
{
const QImage & image = qglview->grabFrame();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setImage(image);
}
void MainWindow::actionFlushCaches() void MainWindow::actionFlushCaches()
{ {
GeometryCache::instance()->clear(); GeometryCache::instance()->clear();
@ -2299,7 +2390,7 @@ void MainWindow::viewModeAnimate()
if (viewActionAnimate->isChecked()) { if (viewActionAnimate->isChecked()) {
animate_panel->show(); animate_panel->show();
actionRenderPreview(); actionRenderPreview();
updatedFps(); updatedAnimFps();
} else { } else {
animate_panel->hide(); animate_panel->hide();
animate_timer->stop(); animate_timer->stop();

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
#ifdef WIN32 #if defined(_MSC_VER)
// only for native windows builds, not MXE
#include <cmath> #include <cmath>
//for native win32 builds we need to provide C99 math functions by ourselves //for native win32 builds we need to provide C99 math functions by ourselves
@ -11,6 +13,7 @@ float fmax(float a, float b);
#else #else
#define _USE_MATH_DEFINES
#include <math.h> #include <math.h>
#endif #endif

View file

@ -1,3 +1,4 @@
#include "mathc99.h"
#include "modcontext.h" #include "modcontext.h"
#include "module.h" #include "module.h"
#include "expression.h" #include "expression.h"

View file

@ -272,12 +272,10 @@ Camera get_camera(po::variables_map vm)
return camera; return camera;
} }
#ifdef OPENSCAD_TESTING #ifndef OPENSCAD_NOGUI
#undef OPENSCAD_QTGUI
#else
#define OPENSCAD_QTGUI 1
#include <QApplication> #include <QApplication>
#include <QSettings> #include <QSettings>
#define OPENSCAD_QTGUI 1
#endif #endif
static bool checkAndExport(shared_ptr<const Geometry> root_geom, unsigned nd, static bool checkAndExport(shared_ptr<const Geometry> root_geom, unsigned nd,
enum FileFormat format, const char *filename) enum FileFormat format, const char *filename)
@ -383,7 +381,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
AbstractNode *absolute_root_node; AbstractNode *absolute_root_node;
shared_ptr<const Geometry> root_geom; shared_ptr<const Geometry> root_geom;
handle_dep(filename.c_str()); handle_dep(filename);
std::ifstream ifs(filename.c_str()); std::ifstream ifs(filename.c_str());
if (!ifs.is_open()) { if (!ifs.is_open()) {
@ -800,6 +798,7 @@ int main(int argc, char **argv)
("projection", po::value<string>(), "(o)rtho or (p)erspective when exporting png") ("projection", po::value<string>(), "(o)rtho or (p)erspective when exporting png")
("colorscheme", po::value<string>(), "colorscheme") ("colorscheme", po::value<string>(), "colorscheme")
("debug", po::value<string>(), "special debug info") ("debug", po::value<string>(), "special debug info")
("quiet,q", "quiet mode (don't print anything *except* errors)")
("o,o", po::value<string>(), "out-file") ("o,o", po::value<string>(), "out-file")
("s,s", po::value<string>(), "stl-file") ("s,s", po::value<string>(), "stl-file")
("x,x", po::value<string>(), "dxf-file") ("x,x", po::value<string>(), "dxf-file")
@ -835,6 +834,9 @@ int main(int argc, char **argv)
OpenSCAD::debug = vm["debug"].as<string>(); OpenSCAD::debug = vm["debug"].as<string>();
PRINTB("Debug on. --debug=%s",OpenSCAD::debug); PRINTB("Debug on. --debug=%s",OpenSCAD::debug);
} }
if (vm.count("quiet")) {
OpenSCAD::quiet = true;
}
if (vm.count("help")) help(argv[0]); if (vm.count("help")) help(argv[0]);
if (vm.count("version")) version(); if (vm.count("version")) version();
if (vm.count("info")) arg_info = true; if (vm.count("info")) arg_info = true;

View file

@ -102,9 +102,7 @@ void parser_init()
} }
} }
#ifndef OPENSCAD_TESTING
add_librarydir(PlatformUtils::userLibraryPath()); add_librarydir(PlatformUtils::userLibraryPath());
#endif
add_librarydir(boosty::absolute(PlatformUtils::resourcePath("libraries")).string()); add_librarydir(boosty::absolute(PlatformUtils::resourcePath("libraries")).string());
} }

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