From 50e79a6817f3d125005dbaab0b95b78a973002a8 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 5 Dec 2014 20:54:01 +0100 Subject: [PATCH 01/35] Fix evaluation of ! expressions. --- src/value.cc | 5 + src/value.h | 1 + .../misc/expression-evaluation-tests.scad | 41 ++ tests/CMakeLists.txt | 1 + .../expression-evaluation-tests-expected.echo | 361 ++++++++++++++++++ 5 files changed, 409 insertions(+) create mode 100644 testdata/scad/misc/expression-evaluation-tests.scad create mode 100644 tests/regression/echotest/expression-evaluation-tests-expected.echo diff --git a/src/value.cc b/src/value.cc index 3180f2b0..d3eea01a 100644 --- a/src/value.cc +++ b/src/value.cc @@ -877,6 +877,11 @@ ValuePtr ValuePtr::operator-() const return ValuePtr(-**this); } +ValuePtr ValuePtr::operator!() const +{ + return ValuePtr(!**this); +} + ValuePtr ValuePtr::operator[](const ValuePtr &v) const { return ValuePtr((**this)[*v]); diff --git a/src/value.h b/src/value.h index bfd08376..e3822309 100644 --- a/src/value.h +++ b/src/value.h @@ -187,6 +187,7 @@ public: bool operator>=(const ValuePtr &v) const; bool operator>(const ValuePtr &v) const; ValuePtr operator-() const; + ValuePtr operator!() const; ValuePtr operator[](const ValuePtr &v) const; ValuePtr operator+(const ValuePtr &v) const; ValuePtr operator-(const ValuePtr &v) const; diff --git a/testdata/scad/misc/expression-evaluation-tests.scad b/testdata/scad/misc/expression-evaluation-tests.scad new file mode 100644 index 00000000..0dd5ff37 --- /dev/null +++ b/testdata/scad/misc/expression-evaluation-tests.scad @@ -0,0 +1,41 @@ +values = [ + undef, // special undefined value + 1/0, // infinity + -1/0, // -infinity + 0/0, // not a number + 0, -4.2, -2, 3, 42.42, 242, // number + true, false, // boolean + "", "text", // string + [], [ 0 ], [ 1 ], // vector + [ 0 : 0 ], [ 1 : 2 ] // range +]; + +array = [ "a", "b", "c", "d" ]; + +for (v = values) { + echo(v = v, op = "not v", result = !v); + echo(v = v, op = "-v", result = -v); + echo(v = v, op = "v *", result = v * 3); + echo(v = v, op = "* v", result = 2 * v); + echo(v = v, op = "v /", result = v / 3); + echo(v = v, op = "/ v", result = 2 / v); + echo(v = v, op = "v %", result = v % 3); + echo(v = v, op = "% v", result = 2 % v); + echo(v = v, op = "v +", result = v + 3); + echo(v = v, op = "+ v", result = 2 + v); + echo(v = v, op = "v -", result = v - 3); + echo(v = v, op = "- v", result = 2 - v); + echo(v = v, op = "v and true", result = v && true); + echo(v = v, op = "v and false", result = v && false); + echo(v = v, op = "v or true", result = v || true); + echo(v = v, op = "v or false", result = v || false); +// echo(v = v, op = "<", result = v < 3); +// echo(v = v, op = "<=", result = v <= 3); +// echo(v = v, op = "==", result = v == 3); +// echo(v = v, op = "!=", result = v != 3); +// echo(v = v, op = ">=", result = v >= 3); +// echo(v = v, op = ">", result = v > 3); + echo(v = v, op = "[v]", result = array[v]); + echo(v = v, op = "v[0]", result = v[0]); + echo(v = v, op = "v[4]", result = v[4]); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index be237330..e190b10c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1025,6 +1025,7 @@ list(APPEND EXAMPLE_FILES ${EXAMPLE_3D_FILES} ${EXAMPLE_2D_FILES}) list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/for-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/expression-evaluation-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/echo-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/parser-tests.scad diff --git a/tests/regression/echotest/expression-evaluation-tests-expected.echo b/tests/regression/echotest/expression-evaluation-tests-expected.echo new file mode 100644 index 00000000..49f91f0d --- /dev/null +++ b/tests/regression/echotest/expression-evaluation-tests-expected.echo @@ -0,0 +1,361 @@ +ECHO: v = undef, op = "not v", result = true +ECHO: v = undef, op = "-v", result = undef +ECHO: v = undef, op = "v *", result = undef +ECHO: v = undef, op = "* v", result = undef +ECHO: v = undef, op = "v /", result = undef +ECHO: v = undef, op = "/ v", result = undef +ECHO: v = undef, op = "v %", result = undef +ECHO: v = undef, op = "% v", result = undef +ECHO: v = undef, op = "v +", result = undef +ECHO: v = undef, op = "+ v", result = undef +ECHO: v = undef, op = "v -", result = undef +ECHO: v = undef, op = "- v", result = undef +ECHO: v = undef, op = "v and true", result = false +ECHO: v = undef, op = "v and false", result = false +ECHO: v = undef, op = "v or true", result = true +ECHO: v = undef, op = "v or false", result = false +ECHO: v = undef, op = "[v]", result = undef +ECHO: v = undef, op = "v[0]", result = undef +ECHO: v = undef, op = "v[4]", result = undef +ECHO: v = inf, op = "not v", result = false +ECHO: v = inf, op = "-v", result = -inf +ECHO: v = inf, op = "v *", result = inf +ECHO: v = inf, op = "* v", result = inf +ECHO: v = inf, op = "v /", result = inf +ECHO: v = inf, op = "/ v", result = 0 +ECHO: v = inf, op = "v %", result = nan +ECHO: v = inf, op = "% v", result = 2 +ECHO: v = inf, op = "v +", result = inf +ECHO: v = inf, op = "+ v", result = inf +ECHO: v = inf, op = "v -", result = inf +ECHO: v = inf, op = "- v", result = -inf +ECHO: v = inf, op = "v and true", result = true +ECHO: v = inf, op = "v and false", result = false +ECHO: v = inf, op = "v or true", result = true +ECHO: v = inf, op = "v or false", result = true +ECHO: v = inf, op = "[v]", result = undef +ECHO: v = inf, op = "v[0]", result = undef +ECHO: v = inf, op = "v[4]", result = undef +ECHO: v = -inf, op = "not v", result = false +ECHO: v = -inf, op = "-v", result = inf +ECHO: v = -inf, op = "v *", result = -inf +ECHO: v = -inf, op = "* v", result = -inf +ECHO: v = -inf, op = "v /", result = -inf +ECHO: v = -inf, op = "/ v", result = 0 +ECHO: v = -inf, op = "v %", result = nan +ECHO: v = -inf, op = "% v", result = 2 +ECHO: v = -inf, op = "v +", result = -inf +ECHO: v = -inf, op = "+ v", result = -inf +ECHO: v = -inf, op = "v -", result = -inf +ECHO: v = -inf, op = "- v", result = inf +ECHO: v = -inf, op = "v and true", result = true +ECHO: v = -inf, op = "v and false", result = false +ECHO: v = -inf, op = "v or true", result = true +ECHO: v = -inf, op = "v or false", result = true +ECHO: v = -inf, op = "[v]", result = undef +ECHO: v = -inf, op = "v[0]", result = undef +ECHO: v = -inf, op = "v[4]", result = undef +ECHO: v = nan, op = "not v", result = false +ECHO: v = nan, op = "-v", result = nan +ECHO: v = nan, op = "v *", result = nan +ECHO: v = nan, op = "* v", result = nan +ECHO: v = nan, op = "v /", result = nan +ECHO: v = nan, op = "/ v", result = nan +ECHO: v = nan, op = "v %", result = nan +ECHO: v = nan, op = "% v", result = nan +ECHO: v = nan, op = "v +", result = nan +ECHO: v = nan, op = "+ v", result = nan +ECHO: v = nan, op = "v -", result = nan +ECHO: v = nan, op = "- v", result = nan +ECHO: v = nan, op = "v and true", result = true +ECHO: v = nan, op = "v and false", result = false +ECHO: v = nan, op = "v or true", result = true +ECHO: v = nan, op = "v or false", result = true +ECHO: v = nan, op = "[v]", result = undef +ECHO: v = nan, op = "v[0]", result = undef +ECHO: v = nan, op = "v[4]", result = undef +ECHO: v = 0, op = "not v", result = true +ECHO: v = 0, op = "-v", result = 0 +ECHO: v = 0, op = "v *", result = 0 +ECHO: v = 0, op = "* v", result = 0 +ECHO: v = 0, op = "v /", result = 0 +ECHO: v = 0, op = "/ v", result = inf +ECHO: v = 0, op = "v %", result = 0 +ECHO: v = 0, op = "% v", result = nan +ECHO: v = 0, op = "v +", result = 3 +ECHO: v = 0, op = "+ v", result = 2 +ECHO: v = 0, op = "v -", result = -3 +ECHO: v = 0, op = "- v", result = 2 +ECHO: v = 0, op = "v and true", result = false +ECHO: v = 0, op = "v and false", result = false +ECHO: v = 0, op = "v or true", result = true +ECHO: v = 0, op = "v or false", result = false +ECHO: v = 0, op = "[v]", result = "a" +ECHO: v = 0, op = "v[0]", result = undef +ECHO: v = 0, op = "v[4]", result = undef +ECHO: v = -4.2, op = "not v", result = false +ECHO: v = -4.2, op = "-v", result = 4.2 +ECHO: v = -4.2, op = "v *", result = -12.6 +ECHO: v = -4.2, op = "* v", result = -8.4 +ECHO: v = -4.2, op = "v /", result = -1.4 +ECHO: v = -4.2, op = "/ v", result = -0.47619047619 +ECHO: v = -4.2, op = "v %", result = -1.2 +ECHO: v = -4.2, op = "% v", result = 2 +ECHO: v = -4.2, op = "v +", result = -1.2 +ECHO: v = -4.2, op = "+ v", result = -2.2 +ECHO: v = -4.2, op = "v -", result = -7.2 +ECHO: v = -4.2, op = "- v", result = 6.2 +ECHO: v = -4.2, op = "v and true", result = true +ECHO: v = -4.2, op = "v and false", result = false +ECHO: v = -4.2, op = "v or true", result = true +ECHO: v = -4.2, op = "v or false", result = true +ECHO: v = -4.2, op = "[v]", result = undef +ECHO: v = -4.2, op = "v[0]", result = undef +ECHO: v = -4.2, op = "v[4]", result = undef +ECHO: v = -2, op = "not v", result = false +ECHO: v = -2, op = "-v", result = 2 +ECHO: v = -2, op = "v *", result = -6 +ECHO: v = -2, op = "* v", result = -4 +ECHO: v = -2, op = "v /", result = -0.66666666666 +ECHO: v = -2, op = "/ v", result = -1 +ECHO: v = -2, op = "v %", result = -2 +ECHO: v = -2, op = "% v", result = 0 +ECHO: v = -2, op = "v +", result = 1 +ECHO: v = -2, op = "+ v", result = 0 +ECHO: v = -2, op = "v -", result = -5 +ECHO: v = -2, op = "- v", result = 4 +ECHO: v = -2, op = "v and true", result = true +ECHO: v = -2, op = "v and false", result = false +ECHO: v = -2, op = "v or true", result = true +ECHO: v = -2, op = "v or false", result = true +ECHO: v = -2, op = "[v]", result = undef +ECHO: v = -2, op = "v[0]", result = undef +ECHO: v = -2, op = "v[4]", result = undef +ECHO: v = 3, op = "not v", result = false +ECHO: v = 3, op = "-v", result = -3 +ECHO: v = 3, op = "v *", result = 9 +ECHO: v = 3, op = "* v", result = 6 +ECHO: v = 3, op = "v /", result = 1 +ECHO: v = 3, op = "/ v", result = 0.66666666666 +ECHO: v = 3, op = "v %", result = 0 +ECHO: v = 3, op = "% v", result = 2 +ECHO: v = 3, op = "v +", result = 6 +ECHO: v = 3, op = "+ v", result = 5 +ECHO: v = 3, op = "v -", result = 0 +ECHO: v = 3, op = "- v", result = -1 +ECHO: v = 3, op = "v and true", result = true +ECHO: v = 3, op = "v and false", result = false +ECHO: v = 3, op = "v or true", result = true +ECHO: v = 3, op = "v or false", result = true +ECHO: v = 3, op = "[v]", result = "d" +ECHO: v = 3, op = "v[0]", result = undef +ECHO: v = 3, op = "v[4]", result = undef +ECHO: v = 42.42, op = "not v", result = false +ECHO: v = 42.42, op = "-v", result = -42.42 +ECHO: v = 42.42, op = "v *", result = 127.26 +ECHO: v = 42.42, op = "* v", result = 84.84 +ECHO: v = 42.42, op = "v /", result = 14.14 +ECHO: v = 42.42, op = "/ v", result = 0.0471475719 +ECHO: v = 42.42, op = "v %", result = 0.42 +ECHO: v = 42.42, op = "% v", result = 2 +ECHO: v = 42.42, op = "v +", result = 45.42 +ECHO: v = 42.42, op = "+ v", result = 44.42 +ECHO: v = 42.42, op = "v -", result = 39.42 +ECHO: v = 42.42, op = "- v", result = -40.42 +ECHO: v = 42.42, op = "v and true", result = true +ECHO: v = 42.42, op = "v and false", result = false +ECHO: v = 42.42, op = "v or true", result = true +ECHO: v = 42.42, op = "v or false", result = true +ECHO: v = 42.42, op = "[v]", result = undef +ECHO: v = 42.42, op = "v[0]", result = undef +ECHO: v = 42.42, op = "v[4]", result = undef +ECHO: v = 242, op = "not v", result = false +ECHO: v = 242, op = "-v", result = -242 +ECHO: v = 242, op = "v *", result = 726 +ECHO: v = 242, op = "* v", result = 484 +ECHO: v = 242, op = "v /", result = 80.66666666666 +ECHO: v = 242, op = "/ v", result = 0.00826446281 +ECHO: v = 242, op = "v %", result = 2 +ECHO: v = 242, op = "% v", result = 2 +ECHO: v = 242, op = "v +", result = 245 +ECHO: v = 242, op = "+ v", result = 244 +ECHO: v = 242, op = "v -", result = 239 +ECHO: v = 242, op = "- v", result = -240 +ECHO: v = 242, op = "v and true", result = true +ECHO: v = 242, op = "v and false", result = false +ECHO: v = 242, op = "v or true", result = true +ECHO: v = 242, op = "v or false", result = true +ECHO: v = 242, op = "[v]", result = undef +ECHO: v = 242, op = "v[0]", result = undef +ECHO: v = 242, op = "v[4]", result = undef +ECHO: v = true, op = "not v", result = false +ECHO: v = true, op = "-v", result = undef +ECHO: v = true, op = "v *", result = undef +ECHO: v = true, op = "* v", result = undef +ECHO: v = true, op = "v /", result = undef +ECHO: v = true, op = "/ v", result = undef +ECHO: v = true, op = "v %", result = undef +ECHO: v = true, op = "% v", result = undef +ECHO: v = true, op = "v +", result = undef +ECHO: v = true, op = "+ v", result = undef +ECHO: v = true, op = "v -", result = undef +ECHO: v = true, op = "- v", result = undef +ECHO: v = true, op = "v and true", result = true +ECHO: v = true, op = "v and false", result = false +ECHO: v = true, op = "v or true", result = true +ECHO: v = true, op = "v or false", result = true +ECHO: v = true, op = "[v]", result = undef +ECHO: v = true, op = "v[0]", result = undef +ECHO: v = true, op = "v[4]", result = undef +ECHO: v = false, op = "not v", result = true +ECHO: v = false, op = "-v", result = undef +ECHO: v = false, op = "v *", result = undef +ECHO: v = false, op = "* v", result = undef +ECHO: v = false, op = "v /", result = undef +ECHO: v = false, op = "/ v", result = undef +ECHO: v = false, op = "v %", result = undef +ECHO: v = false, op = "% v", result = undef +ECHO: v = false, op = "v +", result = undef +ECHO: v = false, op = "+ v", result = undef +ECHO: v = false, op = "v -", result = undef +ECHO: v = false, op = "- v", result = undef +ECHO: v = false, op = "v and true", result = false +ECHO: v = false, op = "v and false", result = false +ECHO: v = false, op = "v or true", result = true +ECHO: v = false, op = "v or false", result = false +ECHO: v = false, op = "[v]", result = undef +ECHO: v = false, op = "v[0]", result = undef +ECHO: v = false, op = "v[4]", result = undef +ECHO: v = "", op = "not v", result = true +ECHO: v = "", op = "-v", result = undef +ECHO: v = "", op = "v *", result = undef +ECHO: v = "", op = "* v", result = undef +ECHO: v = "", op = "v /", result = undef +ECHO: v = "", op = "/ v", result = undef +ECHO: v = "", op = "v %", result = undef +ECHO: v = "", op = "% v", result = undef +ECHO: v = "", op = "v +", result = undef +ECHO: v = "", op = "+ v", result = undef +ECHO: v = "", op = "v -", result = undef +ECHO: v = "", op = "- v", result = undef +ECHO: v = "", op = "v and true", result = false +ECHO: v = "", op = "v and false", result = false +ECHO: v = "", op = "v or true", result = true +ECHO: v = "", op = "v or false", result = false +ECHO: v = "", op = "[v]", result = undef +ECHO: v = "", op = "v[0]", result = undef +ECHO: v = "", op = "v[4]", result = undef +ECHO: v = "text", op = "not v", result = false +ECHO: v = "text", op = "-v", result = undef +ECHO: v = "text", op = "v *", result = undef +ECHO: v = "text", op = "* v", result = undef +ECHO: v = "text", op = "v /", result = undef +ECHO: v = "text", op = "/ v", result = undef +ECHO: v = "text", op = "v %", result = undef +ECHO: v = "text", op = "% v", result = undef +ECHO: v = "text", op = "v +", result = undef +ECHO: v = "text", op = "+ v", result = undef +ECHO: v = "text", op = "v -", result = undef +ECHO: v = "text", op = "- v", result = undef +ECHO: v = "text", op = "v and true", result = true +ECHO: v = "text", op = "v and false", result = false +ECHO: v = "text", op = "v or true", result = true +ECHO: v = "text", op = "v or false", result = true +ECHO: v = "text", op = "[v]", result = undef +ECHO: v = "text", op = "v[0]", result = "t" +ECHO: v = "text", op = "v[4]", result = undef +ECHO: v = [], op = "not v", result = true +ECHO: v = [], op = "-v", result = [] +ECHO: v = [], op = "v *", result = [] +ECHO: v = [], op = "* v", result = [] +ECHO: v = [], op = "v /", result = [] +ECHO: v = [], op = "/ v", result = [] +ECHO: v = [], op = "v %", result = undef +ECHO: v = [], op = "% v", result = undef +ECHO: v = [], op = "v +", result = undef +ECHO: v = [], op = "+ v", result = undef +ECHO: v = [], op = "v -", result = undef +ECHO: v = [], op = "- v", result = undef +ECHO: v = [], op = "v and true", result = false +ECHO: v = [], op = "v and false", result = false +ECHO: v = [], op = "v or true", result = true +ECHO: v = [], op = "v or false", result = false +ECHO: v = [], op = "[v]", result = undef +ECHO: v = [], op = "v[0]", result = undef +ECHO: v = [], op = "v[4]", result = undef +ECHO: v = [0], op = "not v", result = false +ECHO: v = [0], op = "-v", result = [0] +ECHO: v = [0], op = "v *", result = [0] +ECHO: v = [0], op = "* v", result = [0] +ECHO: v = [0], op = "v /", result = [0] +ECHO: v = [0], op = "/ v", result = [inf] +ECHO: v = [0], op = "v %", result = undef +ECHO: v = [0], op = "% v", result = undef +ECHO: v = [0], op = "v +", result = undef +ECHO: v = [0], op = "+ v", result = undef +ECHO: v = [0], op = "v -", result = undef +ECHO: v = [0], op = "- v", result = undef +ECHO: v = [0], op = "v and true", result = true +ECHO: v = [0], op = "v and false", result = false +ECHO: v = [0], op = "v or true", result = true +ECHO: v = [0], op = "v or false", result = true +ECHO: v = [0], op = "[v]", result = undef +ECHO: v = [0], op = "v[0]", result = 0 +ECHO: v = [0], op = "v[4]", result = undef +ECHO: v = [1], op = "not v", result = false +ECHO: v = [1], op = "-v", result = [-1] +ECHO: v = [1], op = "v *", result = [3] +ECHO: v = [1], op = "* v", result = [2] +ECHO: v = [1], op = "v /", result = [0.33333333333] +ECHO: v = [1], op = "/ v", result = [2] +ECHO: v = [1], op = "v %", result = undef +ECHO: v = [1], op = "% v", result = undef +ECHO: v = [1], op = "v +", result = undef +ECHO: v = [1], op = "+ v", result = undef +ECHO: v = [1], op = "v -", result = undef +ECHO: v = [1], op = "- v", result = undef +ECHO: v = [1], op = "v and true", result = true +ECHO: v = [1], op = "v and false", result = false +ECHO: v = [1], op = "v or true", result = true +ECHO: v = [1], op = "v or false", result = true +ECHO: v = [1], op = "[v]", result = undef +ECHO: v = [1], op = "v[0]", result = 1 +ECHO: v = [1], op = "v[4]", result = undef +ECHO: v = [0 : 1 : 0], op = "not v", result = false +ECHO: v = [0 : 1 : 0], op = "-v", result = undef +ECHO: v = [0 : 1 : 0], op = "v *", result = undef +ECHO: v = [0 : 1 : 0], op = "* v", result = undef +ECHO: v = [0 : 1 : 0], op = "v /", result = undef +ECHO: v = [0 : 1 : 0], op = "/ v", result = undef +ECHO: v = [0 : 1 : 0], op = "v %", result = undef +ECHO: v = [0 : 1 : 0], op = "% v", result = undef +ECHO: v = [0 : 1 : 0], op = "v +", result = undef +ECHO: v = [0 : 1 : 0], op = "+ v", result = undef +ECHO: v = [0 : 1 : 0], op = "v -", result = undef +ECHO: v = [0 : 1 : 0], op = "- v", result = undef +ECHO: v = [0 : 1 : 0], op = "v and true", result = true +ECHO: v = [0 : 1 : 0], op = "v and false", result = false +ECHO: v = [0 : 1 : 0], op = "v or true", result = true +ECHO: v = [0 : 1 : 0], op = "v or false", result = true +ECHO: v = [0 : 1 : 0], op = "[v]", result = undef +ECHO: v = [0 : 1 : 0], op = "v[0]", result = 0 +ECHO: v = [0 : 1 : 0], op = "v[4]", result = undef +ECHO: v = [1 : 1 : 2], op = "not v", result = false +ECHO: v = [1 : 1 : 2], op = "-v", result = undef +ECHO: v = [1 : 1 : 2], op = "v *", result = undef +ECHO: v = [1 : 1 : 2], op = "* v", result = undef +ECHO: v = [1 : 1 : 2], op = "v /", result = undef +ECHO: v = [1 : 1 : 2], op = "/ v", result = undef +ECHO: v = [1 : 1 : 2], op = "v %", result = undef +ECHO: v = [1 : 1 : 2], op = "% v", result = undef +ECHO: v = [1 : 1 : 2], op = "v +", result = undef +ECHO: v = [1 : 1 : 2], op = "+ v", result = undef +ECHO: v = [1 : 1 : 2], op = "v -", result = undef +ECHO: v = [1 : 1 : 2], op = "- v", result = undef +ECHO: v = [1 : 1 : 2], op = "v and true", result = true +ECHO: v = [1 : 1 : 2], op = "v and false", result = false +ECHO: v = [1 : 1 : 2], op = "v or true", result = true +ECHO: v = [1 : 1 : 2], op = "v or false", result = true +ECHO: v = [1 : 1 : 2], op = "[v]", result = undef +ECHO: v = [1 : 1 : 2], op = "v[0]", result = 1 +ECHO: v = [1 : 1 : 2], op = "v[4]", result = undef From 2f4171f50675c59f0fe486dc67be293998d0483c Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 6 Dec 2014 19:23:19 +0100 Subject: [PATCH 02/35] Add optional target suffix for the binary / installation folder. This is mainly intended to be used for building snapshot binaries that are able to install in parallel to a release build. E.g. by using the parameter "SUFFIX=-nightly" for qmake, the target binary will be called openscad-nightly and the resource base folder /usr/share/openscad-nightly. --- openscad.pro | 28 +++++++++++++++++----------- src/PlatformUtils.cc | 10 ++++++++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/openscad.pro b/openscad.pro index 5fdcab29..a0ab8b42 100644 --- a/openscad.pro +++ b/openscad.pro @@ -12,6 +12,10 @@ # # PREFIX defines the base installation folder # +# SUFFIX defines an optional suffix for the binary and the +# resource folder. E.g. using SUFFIX=-nightly will name the +# resulting binary openscad-nightly. +# # Please see the 'Building' sections of the OpenSCAD user manual # for updated tips & workarounds. # @@ -78,8 +82,10 @@ macx { TARGET = OpenSCAD } else { - TARGET = openscad + TARGET = openscad$${SUFFIX} } +FULLNAME = openscad$${SUFFIX} +!isEmpty(SUFFIX): DEFINES += INSTALL_SUFFIX="\"\\\"$${SUFFIX}\\\"\"" macx { ICON = icons/OpenSCAD.icns @@ -491,7 +497,7 @@ QMAKE_POST_LINK += $$PWD/scripts/translation-make.sh # Create install targets for the languages defined in LINGUAS LINGUAS = $$cat(locale/LINGUAS) -LOCALE_PREFIX = $$PREFIX/share/openscad/locale +LOCALE_PREFIX = "$$PREFIX/share/$${FULLNAME}/locale" for(language, LINGUAS) { catalog = locale/$$language/LC_MESSAGES/openscad.mo exists($$catalog) { @@ -505,40 +511,40 @@ for(language, LINGUAS) { } } -examples.path = $$PREFIX/share/openscad/examples/ +examples.path = "$$PREFIX/share/$${FULLNAME}/examples/" examples.files = examples/* INSTALLS += examples -libraries.path = $$PREFIX/share/openscad/libraries/ +libraries.path = "$$PREFIX/share/$${FULLNAME}/libraries/" libraries.files = libraries/* INSTALLS += libraries -fonts.path = $$PREFIX/share/openscad/fonts/ +fonts.path = "$$PREFIX/share/$${FULLNAME}/fonts/" fonts.files = fonts/* INSTALLS += fonts -colorschemes.path = $$PREFIX/share/openscad/color-schemes/ +colorschemes.path = "$$PREFIX/share/$${FULLNAME}/color-schemes/" colorschemes.files = color-schemes/* INSTALLS += colorschemes applications.path = $$PREFIX/share/applications -applications.files = icons/openscad.desktop +applications.extra = cp -f icons/openscad.desktop \"$$applications.path/$${FULLNAME}.desktop\" INSTALLS += applications mimexml.path = $$PREFIX/share/mime/packages -mimexml.files = icons/openscad.xml +mimexml.extra = cp -f icons/openscad.xml \"$$mimexml.path/$${FULLNAME}.xml\" INSTALLS += mimexml appdata.path = $$PREFIX/share/appdata -appdata.files = openscad.appdata.xml +appdata.extra = cp -f openscad.appdata.xml \"$$appdata.path/$${FULLNAME}.appdata.xml\" INSTALLS += appdata icons.path = $$PREFIX/share/pixmaps -icons.files = icons/openscad.png +icons.extra = cp -f icons/openscad.png \"$$icons.path/$${FULLNAME}.png\" INSTALLS += icons man.path = $$PREFIX/share/man/man1 -man.files = doc/openscad.1 +man.extra = cp -f doc/openscad.1 \"$$man.path/$${FULLNAME}.1\" INSTALLS += man CONFIG(winconsole) { diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index 2dc524ea..2ebc9950 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -2,6 +2,12 @@ #include "PlatformUtils.h" +#ifdef INSTALL_SUFFIX +#define RESOURCE_FOLDER(path) path INSTALL_SUFFIX +#else +#define RESOURCE_FOLDER(path) path +#endif + extern std::vector librarypath; extern std::vector fontpath; @@ -28,8 +34,8 @@ static std::string lookupResourcesPath() }; #else const char *searchpath[] = { - "../share/openscad", - "../../share/openscad", + RESOURCE_FOLDER("../share/openscad"), + RESOURCE_FOLDER("../../share/openscad"), ".", "..", "../..", From dcd0f232778024c0996f9f5ec95887f6214972b2 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 6 Dec 2014 21:31:37 +0100 Subject: [PATCH 03/35] Fix make install with INSTALL_ROOT set, e.g. used by Debian package build. --- openscad.pro | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openscad.pro b/openscad.pro index a0ab8b42..cedeb86d 100644 --- a/openscad.pro +++ b/openscad.pro @@ -528,23 +528,23 @@ colorschemes.files = color-schemes/* INSTALLS += colorschemes applications.path = $$PREFIX/share/applications -applications.extra = cp -f icons/openscad.desktop \"$$applications.path/$${FULLNAME}.desktop\" +applications.extra = cp -f icons/openscad.desktop \"\$(INSTALL_ROOT)$${applications.path}/$${FULLNAME}.desktop\" INSTALLS += applications mimexml.path = $$PREFIX/share/mime/packages -mimexml.extra = cp -f icons/openscad.xml \"$$mimexml.path/$${FULLNAME}.xml\" +mimexml.extra = cp -f icons/openscad.xml \"\$(INSTALL_ROOT)$${mimexml.path}/$${FULLNAME}.xml\" INSTALLS += mimexml appdata.path = $$PREFIX/share/appdata -appdata.extra = cp -f openscad.appdata.xml \"$$appdata.path/$${FULLNAME}.appdata.xml\" +appdata.extra = cp -f openscad.appdata.xml \"\$(INSTALL_ROOT)$${appdata.path}/$${FULLNAME}.appdata.xml\" INSTALLS += appdata icons.path = $$PREFIX/share/pixmaps -icons.extra = cp -f icons/openscad.png \"$$icons.path/$${FULLNAME}.png\" +icons.extra = cp -f icons/openscad.png \"\$(INSTALL_ROOT)$${icons.path}/$${FULLNAME}.png\" INSTALLS += icons man.path = $$PREFIX/share/man/man1 -man.extra = cp -f doc/openscad.1 \"$$man.path/$${FULLNAME}.1\" +man.extra = cp -f doc/openscad.1 \"\$(INSTALL_ROOT)$${man.path}/$${FULLNAME}.1\" INSTALLS += man CONFIG(winconsole) { From 04c194f6d65ec00de7c72a91addab75152b914ba Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 7 Dec 2014 03:38:02 +0100 Subject: [PATCH 04/35] Update .desktop file to include the install SUFFIX. --- openscad.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openscad.pro b/openscad.pro index cedeb86d..57a19ccf 100644 --- a/openscad.pro +++ b/openscad.pro @@ -528,7 +528,7 @@ colorschemes.files = color-schemes/* INSTALLS += colorschemes applications.path = $$PREFIX/share/applications -applications.extra = cp -f icons/openscad.desktop \"\$(INSTALL_ROOT)$${applications.path}/$${FULLNAME}.desktop\" +applications.extra = cat icons/openscad.desktop | sed -e \"'s/^Icon=openscad/Icon=$${FULLNAME}/; s/^Exec=openscad/Exec=$${FULLNAME}/'\" > \"\$(INSTALL_ROOT)$${applications.path}/$${FULLNAME}.desktop\" INSTALLS += applications mimexml.path = $$PREFIX/share/mime/packages From 771526b5ae2969bc6dce24543d8023b9695380cc Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 7 Dec 2014 03:39:01 +0100 Subject: [PATCH 05/35] Fix install target for translation files. --- openscad.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openscad.pro b/openscad.pro index 57a19ccf..ca298dda 100644 --- a/openscad.pro +++ b/openscad.pro @@ -500,7 +500,7 @@ LINGUAS = $$cat(locale/LINGUAS) LOCALE_PREFIX = "$$PREFIX/share/$${FULLNAME}/locale" for(language, LINGUAS) { catalog = locale/$$language/LC_MESSAGES/openscad.mo - exists($$catalog) { + exists(locale/$${language}.po) { translation_path = translation_$${language}.path translation_files = translation_$${language}.files translation_depends = translation_$${language}.depends From 399895bbfe8fb5d20e94d3a5c6967779eed521fa Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 7 Dec 2014 05:46:07 +0100 Subject: [PATCH 06/35] Fix translation file install target when running qmake on clean source. --- openscad.pro | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openscad.pro b/openscad.pro index ca298dda..cf374a44 100644 --- a/openscad.pro +++ b/openscad.pro @@ -499,13 +499,16 @@ QMAKE_POST_LINK += $$PWD/scripts/translation-make.sh LINGUAS = $$cat(locale/LINGUAS) LOCALE_PREFIX = "$$PREFIX/share/$${FULLNAME}/locale" for(language, LINGUAS) { - catalog = locale/$$language/LC_MESSAGES/openscad.mo + catalogdir = locale/$$language/LC_MESSAGES exists(locale/$${language}.po) { + # Use .extra and copy manually as the source path might not exist, + # e.g. on a clean checkout. In that case qmake would not create + # the needed targets in the generated Makefile. translation_path = translation_$${language}.path - translation_files = translation_$${language}.files + translation_extra = translation_$${language}.extra translation_depends = translation_$${language}.depends $$translation_path = $$LOCALE_PREFIX/$$language/LC_MESSAGES/ - $$translation_files = $$catalog + $$translation_extra = cp -f $${catalogdir}/openscad.mo \"\$(INSTALL_ROOT)$$LOCALE_PREFIX/$$language/LC_MESSAGES/openscad.mo\" $$translation_depends = locale/$${language}.po INSTALLS += translation_$$language } From 82b599e8baa097fe561af6775a5a56a621f372ce Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 7 Dec 2014 18:07:53 -0500 Subject: [PATCH 07/35] Bumped Qt to 5.3.2 --- scripts/macosx-build-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index e91123cc..952256e2 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -770,7 +770,7 @@ fi echo "Using basedir:" $BASEDIR mkdir -p $SRCDIR $DEPLOYDIR -build_qt5 5.3.1 +build_qt5 5.3.2 build_qscintilla 2.8.4 # NB! For eigen, also update the path in the function build_eigen 3.2.1 From a606fe39b6bfb37414c4ecfa33c39cbc204c0be7 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 7 Dec 2014 19:38:48 -0500 Subject: [PATCH 08/35] Minor testcase tweak --- testdata/scad/2D/features/scale2D-tests.scad | 4 ++-- .../dumptest/scale2D-tests-expected.csg | 20 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/testdata/scad/2D/features/scale2D-tests.scad b/testdata/scad/2D/features/scale2D-tests.scad index 87b22784..385809c7 100644 --- a/testdata/scad/2D/features/scale2D-tests.scad +++ b/testdata/scad/2D/features/scale2D-tests.scad @@ -6,5 +6,5 @@ translate([5,0,0]) scale([2,4/3]) obj2D(); translate([10,0,0]) scale(2) obj2D(); // Scale by zero; 2D object -linear_extrude() scale([0,0]) obj2D(); -linear_extrude() scale([0,1]) obj2D(); +translate([-5,0,0]) linear_extrude() scale([0,0]) obj2D(); +translate([-5,0,0]) linear_extrude() scale([0,1]) obj2D(); diff --git a/tests/regression/dumptest/scale2D-tests-expected.csg b/tests/regression/dumptest/scale2D-tests-expected.csg index b20a9757..5d0b7866 100644 --- a/tests/regression/dumptest/scale2D-tests-expected.csg +++ b/tests/regression/dumptest/scale2D-tests-expected.csg @@ -18,17 +18,21 @@ group() { } } } - linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { - multmatrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - group() { - square(size = [2, 3], center = true); + multmatrix([[1, 0, 0, -5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + square(size = [2, 3], center = true); + } } } } - linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { - multmatrix([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - group() { - square(size = [2, 3], center = true); + multmatrix([[1, 0, 0, -5], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + square(size = [2, 3], center = true); + } } } } From 5695d7f445b6b2feb2d9a8b8b04c0d4de6e1b998 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 7 Dec 2014 19:47:43 -0500 Subject: [PATCH 09/35] #1055 added testcase --- .../3D/features/scale-mirror2D-3D-tests.scad | 7 ++++ .../scale-mirror2D-3D-tests-expected.png | Bin 0 -> 7403 bytes .../scale-mirror2D-3D-tests-expected.csg | 36 ++++++++++++++++++ .../scale-mirror2D-3D-tests-expected.png | Bin 0 -> 7699 bytes .../scale-mirror2D-3D-tests-expected.png | Bin 0 -> 7716 bytes 5 files changed, 43 insertions(+) create mode 100644 testdata/scad/3D/features/scale-mirror2D-3D-tests.scad create mode 100644 tests/regression/cgalpngtest/scale-mirror2D-3D-tests-expected.png create mode 100644 tests/regression/dumptest/scale-mirror2D-3D-tests-expected.csg create mode 100644 tests/regression/opencsgtest/scale-mirror2D-3D-tests-expected.png create mode 100644 tests/regression/throwntogethertest/scale-mirror2D-3D-tests-expected.png diff --git a/testdata/scad/3D/features/scale-mirror2D-3D-tests.scad b/testdata/scad/3D/features/scale-mirror2D-3D-tests.scad new file mode 100644 index 00000000..bca2450f --- /dev/null +++ b/testdata/scad/3D/features/scale-mirror2D-3D-tests.scad @@ -0,0 +1,7 @@ +module obj2D() polygon([[-0.5,-0.5], [1,-0.5], [1,1], [-0.5, 0.5]]) +square([2,3], center=true); + +linear_extrude(1) scale([1, -1]) obj2D(); +translate([3,0,0]) linear_extrude(1) scale([-1, -0.5]) obj2D(); +translate([0,3,0]) linear_extrude(1) mirror() obj2D(); +translate([2,3,0]) linear_extrude(1) mirror([0,1]) obj2D(); diff --git a/tests/regression/cgalpngtest/scale-mirror2D-3D-tests-expected.png b/tests/regression/cgalpngtest/scale-mirror2D-3D-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..5d85630a9a8777ed8340f33951b2e7aa393b9147 GIT binary patch literal 7403 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 literal 0 HcmV?d00001 diff --git a/tests/regression/dumptest/scale-mirror2D-3D-tests-expected.csg b/tests/regression/dumptest/scale-mirror2D-3D-tests-expected.csg new file mode 100644 index 00000000..2293a339 --- /dev/null +++ b/tests/regression/dumptest/scale-mirror2D-3D-tests-expected.csg @@ -0,0 +1,36 @@ +group() { + linear_extrude(height = 1, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + polygon(points = [[-0.5, -0.5], [1, -0.5], [1, 1], [-0.5, 0.5]], paths = undef, convexity = 1); + } + } + } + multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 1, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[-1, 0, 0, 0], [0, -0.5, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + polygon(points = [[-0.5, -0.5], [1, -0.5], [1, 1], [-0.5, 0.5]], paths = undef, convexity = 1); + } + } + } + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 3], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 1, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + polygon(points = [[-0.5, -0.5], [1, -0.5], [1, 1], [-0.5, 0.5]], paths = undef, convexity = 1); + } + } + } + } + multmatrix([[1, 0, 0, 2], [0, 1, 0, 3], [0, 0, 1, 0], [0, 0, 0, 1]]) { + linear_extrude(height = 1, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + group() { + polygon(points = [[-0.5, -0.5], [1, -0.5], [1, 1], [-0.5, 0.5]], paths = undef, convexity = 1); + } + } + } + } +} diff --git a/tests/regression/opencsgtest/scale-mirror2D-3D-tests-expected.png b/tests/regression/opencsgtest/scale-mirror2D-3D-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..6521e4afc85dfde89cd86ea5dbfedb082a356ebc GIT binary patch literal 7699 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 KKU8{<81ru!pyFKs literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/scale-mirror2D-3D-tests-expected.png b/tests/regression/throwntogethertest/scale-mirror2D-3D-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..471748a7afb4cc9fc338abeb326d3f2af9312675 GIT binary patch literal 7716 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 Date: Sun, 7 Dec 2014 19:54:31 -0500 Subject: [PATCH 10/35] #1055 Doc: Clarify sanitized polygons --- src/Polygon2d.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Polygon2d.cc b/src/Polygon2d.cc index 8152c7f9..aeb22b22 100644 --- a/src/Polygon2d.cc +++ b/src/Polygon2d.cc @@ -11,8 +11,10 @@ We can store sanitized vs. unsanitized polygons. Sanitized polygons will have opposite winding order for holes and is guaranteed to not - have intersecting geometry. Sanitization is typically done by ClipperUtils, but - if you create geometry which you know is sanitized, the flag can be set manually. + have intersecting geometry. The winding order will be counter-clockwise + for positive outlines and clockwise for holes. Sanitization is typically + done by ClipperUtils, but if you create geometry which you know is sanitized, + the flag can be set manually. */ size_t Polygon2d::memsize() const From ccea6fdde90d0c2e8cc6a15381266399ce3bdce8 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 7 Dec 2014 20:09:45 -0500 Subject: [PATCH 11/35] Bugfix: 2D scale or mirror sometimes caused flipped normals which caused larger issues downstream. Fixes #1055 --- src/GeometryEvaluator.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 71b52a81..40250c68 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -547,7 +547,12 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node) node.matrix(1,0), node.matrix(1,1), node.matrix(1,3), node.matrix(3,0), node.matrix(3,1), node.matrix(3,3); newpoly->transform(mat2); - geom = newpoly; + // A 2D transformation may flip the winding order of a polygon. + // If that happens with a sanitized polygon, we need to reverse + // the winding order for it to be correct. + if (newpoly->isSanitized() && mat2.matrix().determinant() <= 0) { + geom.reset(ClipperUtils::sanitize(*newpoly)); + } } else if (geom->getDimension() == 3) { shared_ptr ps = dynamic_pointer_cast(geom); From 94aabb05b541328c50dcc65c22b46e69624fb7bf Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Dec 2014 00:57:28 -0500 Subject: [PATCH 12/35] #1054 Fixed memory leak --- src/GeometryEvaluator.cc | 4 ++-- src/cgalutils.cc | 13 +++++++------ src/cgalutils.h | 5 +++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 40250c68..94130ce9 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -123,8 +123,7 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr if (op == OPENSCAD_MINKOWSKI) return ResultObject(CGALUtils::applyMinkowski(children)); - CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron; - CGALUtils::applyOperator(children, *N, op); + CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(children, op); return ResultObject(N); } @@ -354,6 +353,7 @@ void GeometryEvaluator::addToParent(const State &state, // Root node, insert into cache smartCacheInsert(node, geom); this->root = geom; + assert(this->visitedchildren.empty()); } } diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 5693ed60..50f87187 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -603,8 +603,7 @@ namespace CGALUtils { fake_children.push_back(std::make_pair((const AbstractNode*)NULL, shared_ptr(createNefPolyhedronFromGeometry(ps)))); } - CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron; - CGALUtils::applyOperator(fake_children, *N, OPENSCAD_UNION); + CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(fake_children, OPENSCAD_UNION); t.stop(); PRINTDB("Minkowski: Union done: %f s",t.time()); t.reset(); @@ -623,8 +622,7 @@ namespace CGALUtils { // If anything throws we simply fall back to Nef Minkowski PRINTD("Minkowski: Falling back to Nef Minkowski"); - CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron; - applyOperator(children, *N, OPENSCAD_MINKOWSKI); + CGAL_Nef_polyhedron *N = applyOperator(children, OPENSCAD_MINKOWSKI); return N; } } @@ -633,7 +631,7 @@ namespace CGALUtils { Applies op to all children and stores the result in dest. The child list should be guaranteed to contain non-NULL 3D or empty Geometry objects */ - void applyOperator(const Geometry::ChildList &children, CGAL_Nef_polyhedron &dest, OpenSCADOperator op) + CGAL_Nef_polyhedron *applyOperator(const Geometry::ChildList &children, OpenSCADOperator op) { // Speeds up n-ary union operations significantly CGAL::Nef_nary_union_3 nary_union; @@ -720,13 +718,15 @@ namespace CGALUtils { } CGAL::set_error_behaviour(old_behaviour); } - if (N) dest = *N; + return N; } /*! Modifies target by applying op to target and src: target = target [op] src */ +//FIXME: Old, can be removed: +#if 0 void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op) { if (target.getDimension() != 2 && target.getDimension() != 3) { @@ -772,6 +772,7 @@ namespace CGALUtils { } CGAL::set_error_behaviour(old_behaviour); } +#endif static void add_outline_to_poly(CGAL_Nef_polyhedron2::Explorer &explorer, CGAL_Nef_polyhedron2::Explorer::Halfedge_around_face_const_circulator circ, diff --git a/src/cgalutils.h b/src/cgalutils.h index 225e93f1..364ff80e 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -13,8 +13,9 @@ typedef std::vector PolyholeK; namespace CGALUtils { bool applyHull(const Geometry::ChildList &children, PolySet &P); - void applyOperator(const Geometry::ChildList &children, CGAL_Nef_polyhedron &dest, OpenSCADOperator op); - void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op); + CGAL_Nef_polyhedron *applyOperator(const Geometry::ChildList &children, OpenSCADOperator op); + //FIXME: Old, can be removed: + //void applyBinaryOperator(CGAL_Nef_polyhedron &target, const CGAL_Nef_polyhedron &src, OpenSCADOperator op); Polygon2d *project(const CGAL_Nef_polyhedron &N, bool cut); CGAL_Iso_cuboid_3 boundingBox(const CGAL_Nef_polyhedron3 &N); bool is_approximately_convex(const PolySet &ps); From 342af594adc9b7a7ad495aee1335fc0447ff7637 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Mon, 8 Dec 2014 18:54:39 +0100 Subject: [PATCH 13/35] Disable vertical refresh syncing. --- src/openscad.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/openscad.cc b/src/openscad.cc index 5080b814..54349f7f 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -625,14 +625,20 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha updater->init(); #endif + QGLFormat fmt; #if 0 /*** disabled by clifford wolf: adds rendering artefacts with OpenCSG ***/ // turn on anti-aliasing - QGLFormat f; - f.setSampleBuffers(true); - f.setSamples(4); - QGLFormat::setDefaultFormat(f); + fmt.setSampleBuffers(true); + fmt.setSamples(4); #endif - + // The default SwapInterval causes very bad interactive behavior as + // waiting for the buffer swap seems to block mouse events. So the + // effect is that we can process mouse events at the frequency of + // the screen retrace interval causing them to queue up. + // (see https://bugreports.qt-project.org/browse/QTBUG-39370 + fmt.setSwapInterval(0); + QGLFormat::setDefaultFormat(fmt); + set_render_color_scheme(arg_colorscheme, false); bool noInputFiles = false; From 0a049f7ab2e159d00fe572c87096ca21e8fb90ba Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Dec 2014 17:53:19 -0500 Subject: [PATCH 14/35] removed fixed fixme --- testdata/scad/3D/features/transform-tests.scad | 2 -- 1 file changed, 2 deletions(-) diff --git a/testdata/scad/3D/features/transform-tests.scad b/testdata/scad/3D/features/transform-tests.scad index e2dd71e1..0c922c78 100644 --- a/testdata/scad/3D/features/transform-tests.scad +++ b/testdata/scad/3D/features/transform-tests.scad @@ -15,5 +15,3 @@ multmatrix([[1,0.4,0.1,-25], [0.4,0.8,0,-25], [0.2,0.2,0.5,0], [0,0,0,1]]) mycyl(); - -//FIXME: mirror() and scale() \ No newline at end of file From c03350e3cb5ad993e96699fe69373269561f04a4 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Dec 2014 17:53:40 -0500 Subject: [PATCH 15/35] Added more nullspace tests --- .../scad/3D/features/nullspace-difference.scad | 4 ++++ .../3D/features/nullspace-intersection.scad | 4 ++++ .../nullspace-minkowski-intersection.scad | 10 ++++++++++ .../scad/3D/features/nullspace-minkowski.scad | 7 +++++++ .../3D/features/nullspace-minkowski.scad.csg | 13 +++++++++++++ .../nullspace-difference-expected.png | Bin 0 -> 4408 bytes .../nullspace-intersection-expected.png | Bin 0 -> 4408 bytes .../nullspace-minkowski-expected.png | Bin 0 -> 4408 bytes ...ullspace-minkowski-intersection-expected.png | Bin 0 -> 4408 bytes .../dumptest/nullspace-difference-expected.csg | 6 ++++++ .../nullspace-intersection-expected.csg | 10 ++++++++++ .../dumptest/nullspace-minkowski-expected.csg | 13 +++++++++++++ ...ullspace-minkowski-intersection-expected.csg | 16 ++++++++++++++++ .../nullspace-difference-expected.png | Bin 0 -> 4408 bytes .../nullspace-intersection-expected.png | Bin 0 -> 4408 bytes .../nullspace-minkowski-expected.png | Bin 0 -> 4408 bytes ...ullspace-minkowski-intersection-expected.png | Bin 0 -> 4408 bytes .../nullspace-difference-expected.png | Bin 0 -> 4408 bytes .../nullspace-intersection-expected.png | Bin 0 -> 4408 bytes .../nullspace-minkowski-expected.png | Bin 0 -> 4408 bytes ...ullspace-minkowski-intersection-expected.png | Bin 0 -> 4408 bytes 21 files changed, 83 insertions(+) create mode 100644 testdata/scad/3D/features/nullspace-difference.scad create mode 100644 testdata/scad/3D/features/nullspace-intersection.scad create mode 100644 testdata/scad/3D/features/nullspace-minkowski-intersection.scad create mode 100644 testdata/scad/3D/features/nullspace-minkowski.scad create mode 100644 testdata/scad/3D/features/nullspace-minkowski.scad.csg create mode 100644 tests/regression/cgalpngtest/nullspace-difference-expected.png create mode 100644 tests/regression/cgalpngtest/nullspace-intersection-expected.png create mode 100644 tests/regression/cgalpngtest/nullspace-minkowski-expected.png create mode 100644 tests/regression/cgalpngtest/nullspace-minkowski-intersection-expected.png create mode 100644 tests/regression/dumptest/nullspace-difference-expected.csg create mode 100644 tests/regression/dumptest/nullspace-intersection-expected.csg create mode 100644 tests/regression/dumptest/nullspace-minkowski-expected.csg create mode 100644 tests/regression/dumptest/nullspace-minkowski-intersection-expected.csg create mode 100644 tests/regression/opencsgtest/nullspace-difference-expected.png create mode 100644 tests/regression/opencsgtest/nullspace-intersection-expected.png create mode 100644 tests/regression/opencsgtest/nullspace-minkowski-expected.png create mode 100644 tests/regression/opencsgtest/nullspace-minkowski-intersection-expected.png create mode 100644 tests/regression/throwntogethertest/nullspace-difference-expected.png create mode 100644 tests/regression/throwntogethertest/nullspace-intersection-expected.png create mode 100644 tests/regression/throwntogethertest/nullspace-minkowski-expected.png create mode 100644 tests/regression/throwntogethertest/nullspace-minkowski-intersection-expected.png diff --git a/testdata/scad/3D/features/nullspace-difference.scad b/testdata/scad/3D/features/nullspace-difference.scad new file mode 100644 index 00000000..7db36eae --- /dev/null +++ b/testdata/scad/3D/features/nullspace-difference.scad @@ -0,0 +1,4 @@ +difference() { + cube(1, center=true); + cube(2, center=true); +} diff --git a/testdata/scad/3D/features/nullspace-intersection.scad b/testdata/scad/3D/features/nullspace-intersection.scad new file mode 100644 index 00000000..b58b3e0e --- /dev/null +++ b/testdata/scad/3D/features/nullspace-intersection.scad @@ -0,0 +1,4 @@ +intersection() { + translate([-2,0,0]) cube(1); + translate([2,0,0]) cube(1); +} diff --git a/testdata/scad/3D/features/nullspace-minkowski-intersection.scad b/testdata/scad/3D/features/nullspace-minkowski-intersection.scad new file mode 100644 index 00000000..617eae82 --- /dev/null +++ b/testdata/scad/3D/features/nullspace-minkowski-intersection.scad @@ -0,0 +1,10 @@ +intersection() { + minkowski() { + intersection() { + translate([-2,0,0]) cube(1); + translate([2,0,0]) cube(1); + } + cube(); + } + cube(); +} diff --git a/testdata/scad/3D/features/nullspace-minkowski.scad b/testdata/scad/3D/features/nullspace-minkowski.scad new file mode 100644 index 00000000..c1cb6b50 --- /dev/null +++ b/testdata/scad/3D/features/nullspace-minkowski.scad @@ -0,0 +1,7 @@ +minkowski() { + intersection() { + translate([-2,0,0]) cube(1); + translate([2,0,0]) cube(1); + } + cube(); +} diff --git a/testdata/scad/3D/features/nullspace-minkowski.scad.csg b/testdata/scad/3D/features/nullspace-minkowski.scad.csg new file mode 100644 index 00000000..e387596e --- /dev/null +++ b/testdata/scad/3D/features/nullspace-minkowski.scad.csg @@ -0,0 +1,13 @@ +group() { + minkowski(convexity = 0) { + intersection() { + multmatrix([[1, 0, 0, -2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [1, 1, 1], center = false); + } + multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [1, 1, 1], center = false); + } + } + cube(size = [1, 1, 1], center = false); + } +} diff --git a/tests/regression/cgalpngtest/nullspace-difference-expected.png b/tests/regression/cgalpngtest/nullspace-difference-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..08ee92b2216f45ca6b83efbc3b78c9fdabf45a71 GIT binary patch literal 4408 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 Date: Mon, 8 Dec 2014 18:24:09 -0500 Subject: [PATCH 16/35] Disabled less useful test --- tests/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e190b10c..0a3ff6ab 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1124,6 +1124,7 @@ disable_tests( # Not useful throwntogethertest_internal-cavity throwntogethertest_internal-cavity-polyhedron + throwntogethertest_nullspace-difference # these take too long, for little relative gain in testing stlpngtest_iteration From 2462799655b0b2f49655204303f10a65e11309bb Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 8 Dec 2014 18:25:48 -0500 Subject: [PATCH 17/35] Handle a bunch of nullspace corner cases. Fixes #1029 --- src/CGAL_Nef_polyhedron.cc | 5 ++++ src/CGAL_Nef_polyhedron.h | 2 +- src/CsgInfo.h | 13 +-------- src/GeometryEvaluator.cc | 12 ++++++--- src/cgalutils.cc | 4 +-- src/export_png.cc | 5 +--- src/mainwin.cc | 27 +++++++++---------- .../3D/features/nullspace-minkowski.scad.csg | 13 --------- 8 files changed, 30 insertions(+), 51 deletions(-) delete mode 100644 testdata/scad/3D/features/nullspace-minkowski.scad.csg diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index dfe16536..d49521e0 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -48,6 +48,11 @@ size_t CGAL_Nef_polyhedron::memsize() const return memsize; } +bool CGAL_Nef_polyhedron::isEmpty() const +{ + return !this->p3 || this->p3->is_empty(); +} + /*! Creates a new PolySet and initializes it with the data from this polyhedron diff --git a/src/CGAL_Nef_polyhedron.h b/src/CGAL_Nef_polyhedron.h index f3585469..2d7b37d6 100644 --- a/src/CGAL_Nef_polyhedron.h +++ b/src/CGAL_Nef_polyhedron.h @@ -19,7 +19,7 @@ public: virtual std::string dump() const; virtual unsigned int getDimension() const { return 3; } // Empty means it is a geometric node which has zero area/volume - virtual bool isEmpty() const { return !p3; } + virtual bool isEmpty() const; virtual Geometry *copy() const { return new CGAL_Nef_polyhedron(*this); } void reset() { p3.reset(); } diff --git a/src/CsgInfo.h b/src/CsgInfo.h index c50ab4d4..8a3512c8 100644 --- a/src/CsgInfo.h +++ b/src/CsgInfo.h @@ -12,13 +12,8 @@ class CsgInfo { public: - CsgInfo() + CsgInfo() : glview(NULL), root_chain(NULL), highlights_chain(NULL), background_chain(NULL), progress_function(NULL) { - root_chain = NULL; - highlights_chain = NULL; - background_chain = NULL; - glview = NULL; - progress_function = NULL; normalizelimit = RenderSettings::inst()->openCSGTermLimit; } OffscreenView *glview; @@ -43,12 +38,6 @@ public: CSGTermEvaluator evaluator(tree, &geomevaluator); boost::shared_ptr root_raw_term = evaluator.evaluateCSGTerm( *root_node, this->highlight_terms, this->background_terms ); - if (!root_raw_term && this->background_terms.empty()) { - PRINT("Error: CSG generation failed! (no objects found)"); - call_progress_function(); - return false; - } - PRINT("Compiling design (CSG Products normalization)..."); call_progress_function(); CSGTermNormalizer normalizer( normalizelimit ); diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 94130ce9..24118c1f 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -63,10 +63,12 @@ shared_ptr GeometryEvaluator::evaluateGeometry(const AbstractNod PolySet *ps = new PolySet(3); ps->setConvexity(N->getConvexity()); this->root.reset(ps); - bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *ps); - if (err) { - PRINT("ERROR: Nef->PolySet failed"); - } + if (!N->isEmpty()) { + bool err = CGALUtils::createPolySetFromNefPolyhedron3(*N->p3, *ps); + if (err) { + PRINT("ERROR: Nef->PolySet failed"); + } + } smartCacheInsert(node, this->root); } @@ -124,6 +126,8 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr if (op == OPENSCAD_MINKOWSKI) return ResultObject(CGALUtils::applyMinkowski(children)); CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(children, op); + // FIXME: Clarify when we can return NULL and what that means + if (!N) N = new CGAL_Nef_polyhedron; return ResultObject(N); } diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 50f87187..41c5f192 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -609,7 +609,7 @@ namespace CGALUtils { t.reset(); operands[0] = N; } else { - return NULL; + operands[0] = new CGAL_Nef_polyhedron(); } } @@ -628,7 +628,7 @@ namespace CGALUtils { } /*! - Applies op to all children and stores the result in dest. + 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) diff --git a/src/export_png.cc b/src/export_png.cc index 69770547..80dda0ca 100644 --- a/src/export_png.cc +++ b/src/export_png.cc @@ -53,10 +53,7 @@ void export_png_preview_common(Tree &tree, Camera &cam, std::ostream &output, Pr { PRINTD("export_png_preview_common"); CsgInfo csgInfo = CsgInfo(); - if (!csgInfo.compile_chains(tree)) { - fprintf(stderr,"Couldn't initialize CSG chains\n"); - return; - } + csgInfo.compile_chains(tree); try { csgInfo.glview = new OffscreenView(cam.pixel_width, cam.pixel_height); diff --git a/src/mainwin.cc b/src/mainwin.cc index 92d64a16..a4601f59 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1051,9 +1051,6 @@ void MainWindow::compileCSG(bool procevents) CSGTermEvaluator csgrenderer(this->tree, &geomevaluator); if (procevents) QApplication::processEvents(); this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); - if (!root_raw_term && background_terms.empty()) { - PRINT("ERROR: CSG generation failed! (no objects found)"); - } GeometryCache::instance()->print(); #ifdef ENABLE_CGAL CGALCache::instance()->print(); @@ -1768,8 +1765,8 @@ void MainWindow::actionRenderDone(shared_ptr root_geom) int s = this->progresswidget->elapsedTime() / 1000; PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60)); - if (const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get())) { - if (!N->isEmpty()) { + if (root_geom && !root_geom->isEmpty()) { + if (const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get())) { if (N->getDimension() == 3) { PRINT(" Top level object is a 3D object:"); PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no")); @@ -1781,16 +1778,16 @@ void MainWindow::actionRenderDone(shared_ptr root_geom) PRINTB(" Volumes: %6d", N->p3->number_of_volumes()); } } - } - else if (const PolySet *ps = dynamic_cast(root_geom.get())) { - assert(ps->getDimension() == 3); - PRINT(" Top level object is a 3D object:"); - PRINTB(" Facets: %6d", ps->numPolygons()); - } else if (const Polygon2d *poly = dynamic_cast(root_geom.get())) { - PRINT(" Top level object is a 2D object:"); - PRINTB(" Contours: %6d", poly->outlines().size()); - } else { - assert(false && "Unknown geometry type"); + else if (const PolySet *ps = dynamic_cast(root_geom.get())) { + assert(ps->getDimension() == 3); + PRINT(" Top level object is a 3D object:"); + PRINTB(" Facets: %6d", ps->numPolygons()); + } else if (const Polygon2d *poly = dynamic_cast(root_geom.get())) { + PRINT(" Top level object is a 2D object:"); + PRINTB(" Contours: %6d", poly->outlines().size()); + } else { + assert(false && "Unknown geometry type"); + } } PRINT("Rendering finished."); diff --git a/testdata/scad/3D/features/nullspace-minkowski.scad.csg b/testdata/scad/3D/features/nullspace-minkowski.scad.csg deleted file mode 100644 index e387596e..00000000 --- a/testdata/scad/3D/features/nullspace-minkowski.scad.csg +++ /dev/null @@ -1,13 +0,0 @@ -group() { - minkowski(convexity = 0) { - intersection() { - multmatrix([[1, 0, 0, -2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - cube(size = [1, 1, 1], center = false); - } - multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - cube(size = [1, 1, 1], center = false); - } - } - cube(size = [1, 1, 1], center = false); - } -} From f4a6da7fb0e74766fbdc404c2ff388dce776910c Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Tue, 9 Dec 2014 19:13:56 +0100 Subject: [PATCH 18/35] Try to detect if compiling with a 32bit or 64bit compiler. --- src/LibraryInfo.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/LibraryInfo.cc b/src/LibraryInfo.cc index 83f3875c..71e36971 100644 --- a/src/LibraryInfo.cc +++ b/src/LibraryInfo.cc @@ -29,12 +29,20 @@ std::string LibraryInfo::info() { std::stringstream s; +#if defined(__x86_64__) || defined(_M_X64) + std::string bits(" 64bit"); +#elif defined(__i386) || defined(_M_IX86) + std::string bits(" 32bit"); +#else + std::string bits(""); +#endif + #if defined(__GNUG__) && !defined(__clang__) - std::string compiler_info( "GCC " + std::string(TOSTRING(__VERSION__)) ); + std::string compiler_info( "GCC " + std::string(TOSTRING(__VERSION__)) + bits); #elif defined(_MSC_VER) - std::string compiler_info( "MSVC " + std::string(TOSTRING(_MSC_FULL_VER)) ); + std::string compiler_info( "MSVC " + std::string(TOSTRING(_MSC_FULL_VER)) + bits); #elif defined(__clang__) - std::string compiler_info( "Clang " + std::string(TOSTRING(__clang_version__)) ); + std::string compiler_info( "Clang " + std::string(TOSTRING(__clang_version__)) + bits); #else std::string compiler_info( "unknown compiler" ); #endif From f7816e02cd720b95cac4b415706c5d8ade94d87f Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Tue, 9 Dec 2014 19:14:43 +0100 Subject: [PATCH 19/35] Add system info (OS / CPUs/ RAM / Distribution (when on Linux)). --- src/LibraryInfo.cc | 1 + src/PlatformUtils-mac.mm | 42 +++++++++++++++ src/PlatformUtils-posix.cc | 102 +++++++++++++++++++++++++++++++++++++ src/PlatformUtils-win.cc | 90 ++++++++++++++++++++++++++++++++ src/PlatformUtils.cc | 23 +++++++++ src/PlatformUtils.h | 20 ++++++++ 6 files changed, 278 insertions(+) diff --git a/src/LibraryInfo.cc b/src/LibraryInfo.cc index 71e36971..52facbb1 100644 --- a/src/LibraryInfo.cc +++ b/src/LibraryInfo.cc @@ -88,6 +88,7 @@ std::string LibraryInfo::info() const char *env_font_path = getenv("OPENSCAD_FONT_PATH"); s << "OpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) + << "\nSystem information: " << PlatformUtils::sysinfo() << "\nCompiler, build date: " << compiler_info << ", " << __DATE__ << "\nBoost version: " << BOOST_LIB_VERSION << "\nEigen version: " << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION diff --git a/src/PlatformUtils-mac.mm b/src/PlatformUtils-mac.mm index cb93e522..20e72321 100644 --- a/src/PlatformUtils-mac.mm +++ b/src/PlatformUtils-mac.mm @@ -35,5 +35,47 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +std::string PlatformUtils::sysinfo() +{ + std::string result; + +#if 0 + struct utsname osinfo; + if (uname(&osinfo) == 0) { + result += osinfo.sysname; + result += " "; + result += osinfo.release; + result += " "; + result += osinfo.version; + result += " "; + result += osinfo.machine; + } else { +#endif + result += "Unknown MacOS"; +#if 0 + } + + long numcpu = sysconf(_SC_NPROCESSORS_ONLN); + if (numcpu > 0) { + result += " "; + result += boost::lexical_cast(numcpu); + result += " CPU"; + if (numcpu > 1) { + result += "s"; + } + } + + long pages = sysconf(_SC_PHYS_PAGES); + long pagesize = sysconf(_SC_PAGE_SIZE); + if ((pages > 0) && (pagesize > 0)) { + result += " "; + result += PlatformUtils::toMemorySizeString(pages * pagesize, 2); + result += " RAM"; + } +#endif + + return result; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-posix.cc b/src/PlatformUtils-posix.cc index 3854a5e7..dbeaa411 100644 --- a/src/PlatformUtils-posix.cc +++ b/src/PlatformUtils-posix.cc @@ -1,4 +1,13 @@ +#include +#include +#include +#include #include +#include + +#include +#include +#include #include "PlatformUtils.h" #include "boosty.h" @@ -60,5 +69,98 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +/** + * Check /etc/os-release as defined by systemd. + * @see http://0pointer.de/blog/projects/os-release.html + * @see http://www.freedesktop.org/software/systemd/man/os-release.html + * @return the PRETTY_NAME from the os-release file or an empty string. + */ +static std::string checkOsRelease() +{ + std::ifstream os_release_stream("/etc/os-release"); + std::string os_release((std::istreambuf_iterator(os_release_stream)), std::istreambuf_iterator()); + + boost::smatch results; + boost::regex pretty_name("^PRETTY_NAME=\"([^\"]+)\""); + if (boost::regex_search(os_release, results, pretty_name)) { + return results[1]; + } + + return ""; +} + +static std::string checkEtcIssue() +{ + std::ifstream issue_stream("/etc/issue"); + std::string issue((std::istreambuf_iterator(issue_stream)), std::istreambuf_iterator()); + + boost::regex nl("\n.*$"); + issue = boost::regex_replace(issue, nl, ""); + boost::regex esc("\\\\."); + issue = boost::regex_replace(issue, esc, ""); + boost::algorithm::trim(issue); + + return issue; +} + +static std::string detectDistribution() +{ + std::string osrelease = checkOsRelease(); + if (!osrelease.empty()) { + return osrelease; + } + + std::string etcissue = checkEtcIssue(); + if (!etcissue.empty()) { + return etcissue; + } + + return ""; +} + +std::string PlatformUtils::sysinfo() +{ + std::string result; + + struct utsname osinfo; + if (uname(&osinfo) == 0) { + result += osinfo.sysname; + result += " "; + result += osinfo.release; + result += " "; + result += osinfo.version; + result += " "; + result += osinfo.machine; + } else { + result += "Unknown Linux"; + } + + long numcpu = sysconf(_SC_NPROCESSORS_ONLN); + if (numcpu > 0) { + result += " "; + result += boost::lexical_cast(numcpu); + result += " CPU"; + if (numcpu > 1) { + result += "s"; + } + } + + long pages = sysconf(_SC_PHYS_PAGES); + long pagesize = sysconf(_SC_PAGE_SIZE); + if ((pages > 0) && (pagesize > 0)) { + result += " "; + result += PlatformUtils::toMemorySizeString(pages * pagesize, 2); + result += " RAM"; + } + + std::string distribution = detectDistribution(); + if (!distribution.empty()) { + result += " "; + result += distribution; + } + + return result; +} + void PlatformUtils::ensureStdIO(void) {} diff --git a/src/PlatformUtils-win.cc b/src/PlatformUtils-win.cc index c83855d0..1f07b683 100644 --- a/src/PlatformUtils-win.cc +++ b/src/PlatformUtils-win.cc @@ -98,6 +98,96 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx +static BOOL IsWow64() +{ + BOOL bIsWow64 = FALSE; + + //IsWow64Process is not available on all supported versions of Windows. + //Use GetModuleHandle to get a handle to the DLL that contains the function + //and GetProcAddress to get a pointer to the function if available. + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); + + if (NULL != fnIsWow64Process) { + if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) + { + return false; + } + } + return bIsWow64; +} + +std::string PlatformUtils::sysinfo() +{ + std::string result; + + OSVERSIONINFOEX osinfo; + osinfo.dwOSVersionInfoSize = sizeof(osinfo); + if (GetVersionEx((OSVERSIONINFO*)&osinfo) == 0) { + result += "Unknown Windows"; + } else { + unsigned int version = osinfo.dwMajorVersion * 1000 + osinfo.dwMinorVersion; + if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { + switch (version) { + case 5000: + result += "Windows 2000"; + break; + case 5001: + result += "Windows XP"; + break; + case 5002: + result += "Windows Server 2003"; + break; + case 6000: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008"); + break; + case 6001: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2"); + break; + case 6002: + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012"); + break; + case 6003: + // For applications that have been manifested for Windows 8.1. + result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"); + break; + } + boost::format fmt(" (v%d.%d)"); + fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + result += fmt.str(); + } else { + boost::format fmt("Unknown Windows (dwPlatformId = %d, dwMajorVersion = %d, dwMinorVersion = %d"); + fmt % osinfo.dwPlatformId % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + result += fmt.str(); + } + } + + SYSTEM_INFO systeminfo; + bool isWow64 = IsWow64(); + if (isWow64) { + GetNativeSystemInfo(&systeminfo); + } else { + GetSystemInfo(&systeminfo); + } + + int numcpu = systeminfo.dwNumberOfProcessors; + boost::format fmt(" %d CPU%s%s"); + fmt % numcpu % (numcpu > 1 ? "s" : "") % (isWow64 ? " WOW64" : ""); + result += fmt.str(); + + MEMORYSTATUSEX memoryinfo; + memoryinfo.dwLength = sizeof(memoryinfo); + if (GlobalMemoryStatusEx(&memoryinfo) != 0) { + result += " "; + result += PlatformUtils::toMemorySizeString(memoryinfo.ullTotalPhys, 2); + result += " RAM"; + } + + return result; +} + #include #include #include diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc index 2ebc9950..a15a0a3c 100644 --- a/src/PlatformUtils.cc +++ b/src/PlatformUtils.cc @@ -1,4 +1,5 @@ #include +#include #include "PlatformUtils.h" @@ -190,3 +191,25 @@ int PlatformUtils::setenv(const char *name, const char *value, int overwrite) return ::setenv(name, value, overwrite); #endif } + +std::string PlatformUtils::toMemorySizeString(unsigned long bytes, int digits) +{ + static const char *units[] = { "B", "kB", "MB", "GB", "TB", NULL }; + + int idx = 0; + double val = bytes; + while (true) { + if (val < 1024.0) { + break; + } + if (units[idx + 1] == NULL) { + break; + } + idx++; + val /= 1024.0; + } + + boost::format fmt("%f %s"); + fmt % boost::io::group(std::setprecision(digits), val) % units[idx]; + return fmt.str(); +} diff --git a/src/PlatformUtils.h b/src/PlatformUtils.h index a5c2ec91..5210dc85 100644 --- a/src/PlatformUtils.h +++ b/src/PlatformUtils.h @@ -34,6 +34,20 @@ namespace PlatformUtils { std::string backupPath(); bool createBackupPath(); + /** + * Return a human readable text describing the operating system + * the application is currently running on. This is mainly intended + * to provide information for bug reports (e.g. to be included in + * the LibraryInfoDialog). + * + * If there is some error to retrieve the details, at least the + * OS type is reported based on what platform the application was + * built for. + * + * @return system information. + */ + std::string sysinfo(); + /** * Platform abstraction to set environment variables. Windows/MinGW * does not support setenv(), but needs _putenv(). @@ -65,4 +79,10 @@ namespace PlatformUtils { * Currently limited to MS Windows GUI application console only. */ void ensureStdIO(void); + + /** + * Convert the number of bytes to a human readable string with + * a given number of digits. + */ + std::string toMemorySizeString(unsigned long bytes, int digits); } From ba8446e8bfbf770926a13b2d312187077adcb368 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Tue, 9 Dec 2014 22:06:06 +0100 Subject: [PATCH 20/35] Remove qtaccessiblewidgets as QTPLUGIN. MXE now ships Qt-5.4.0-rc which has accessibility built-in. All other platforms did not have it enabled so far. --- openscad.pro | 3 --- 1 file changed, 3 deletions(-) diff --git a/openscad.pro b/openscad.pro index cf374a44..d745c708 100644 --- a/openscad.pro +++ b/openscad.pro @@ -116,7 +116,6 @@ macx { win* { RC_FILE = openscad_win32.rc - QTPLUGIN += qtaccessiblewidgets } CONFIG += qt @@ -130,8 +129,6 @@ unix:!macx { QMAKE_LIBS_OPENGL *= -lX11 } -#QTPLUGIN += qtaccessiblewidgets - netbsd* { QMAKE_LFLAGS += -L/usr/X11R7/lib QMAKE_LFLAGS += -Wl,-R/usr/X11R7/lib From 6d9329966a77a73193acfea6d8d410dd5da8d071 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Dec 2014 16:42:02 -0500 Subject: [PATCH 21/35] #1061 fixed test build behaving differently from GUI build due to ENABLE_CGAL flag not being passed to all relevant sources. Added testcase --- src/polyset-utils.cc | 15 +++++++++++++++ src/polyset-utils.h | 1 + src/polyset.cc | 15 +++------------ testdata/scad/bugs/issue1061.scad | 1 + tests/CMakeLists.txt | 16 +++++++++------- .../cgalpngtest/issue1061-expected.png | Bin 0 -> 10709 bytes .../monotonepngtest/issue1061-expected.png | Bin 0 -> 10709 bytes .../opencsgtest/issue1061-expected.png | Bin 0 -> 11401 bytes 8 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 testdata/scad/bugs/issue1061.scad create mode 100644 tests/regression/cgalpngtest/issue1061-expected.png create mode 100644 tests/regression/monotonepngtest/issue1061-expected.png create mode 100644 tests/regression/opencsgtest/issue1061-expected.png diff --git a/src/polyset-utils.cc b/src/polyset-utils.cc index 5587be6e..b3bba6d7 100644 --- a/src/polyset-utils.cc +++ b/src/polyset-utils.cc @@ -2,7 +2,9 @@ #include "polyset.h" #include "Polygon2d.h" #include "printutils.h" +#ifdef ENABLE_CGAL #include "cgalutils.h" +#endif #include @@ -45,6 +47,7 @@ namespace PolysetUtils { The tessellation will be robust wrt. degenerate and self-intersecting */ void tessellate_faces(const PolySet &inps, PolySet &outps) { +#ifdef ENABLE_CGAL int degeneratePolygons = 0; for (size_t i = 0; i < inps.polygons.size(); i++) { const Polygon pgon = inps.polygons[i]; @@ -76,5 +79,17 @@ namespace PolysetUtils { } } if (degeneratePolygons > 0) PRINT("WARNING: PolySet has degenerate polygons"); +#else + assert(false); +#endif } + + bool is_approximately_convex(const PolySet &ps) { +#ifdef ENABLE_CGAL + return CGALUtils::is_approximately_convex(ps); +#else + return false; +#endif + } + } diff --git a/src/polyset-utils.h b/src/polyset-utils.h index 2bdaca03..41364f07 100644 --- a/src/polyset-utils.h +++ b/src/polyset-utils.h @@ -7,5 +7,6 @@ namespace PolysetUtils { Polygon2d *project(const PolySet &ps); void tessellate_faces(const PolySet &inps, PolySet &outps); + bool is_approximately_convex(const PolySet &ps); }; diff --git a/src/polyset.cc b/src/polyset.cc index 0dfc2ba8..fc8e7e04 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -25,6 +25,7 @@ */ #include "polyset.h" +#include "polyset-utils.h" #include "linalg.h" #include "printutils.h" #include @@ -140,20 +141,10 @@ void PolySet::transform(const Transform3d &mat) } } -namespace CGALUtils { - extern bool is_approximately_convex(const PolySet &ps); -} - bool PolySet::is_convex() const { - if (convex) return true; + if (convex) return true; if (!convex) return false; - -#ifdef ENABLE_CGAL - convex = CGALUtils::is_approximately_convex(*this); - return convex; -#else - return false; -#endif + return PolysetUtils::is_approximately_convex(*this); } void PolySet::resize(Vector3d newsize, const Eigen::Matrix &autosize) diff --git a/testdata/scad/bugs/issue1061.scad b/testdata/scad/bugs/issue1061.scad new file mode 100644 index 00000000..70cc35cc --- /dev/null +++ b/testdata/scad/bugs/issue1061.scad @@ -0,0 +1 @@ +polyhedron(points = [[-5, -5, 0], [-5, 5, 0], [5, 5, 0], [5, -5, 0], [-1.87866, -4.21311, 3], [-4.21311, 5.51058, 3], [5.51058, 7.84504, 3], [7.84504, -1.87866, 3], [1.05099, -3.48892, 6], [-3.48892, 5.42115, 6], [5.42115, 9.96105, 6], [9.96105, 1.05099, 6], [3.39596, -3.09852, 9], [-3.09852, 4.50554, 9], [4.50554, 11, 9], [11, 3.39596, 9], [4.91038, -3.17979, 12], [-3.17979, 2.69807, 12], [2.69807, 10.7882, 12], [10.7882, 4.91038, 12], [5.53441, -3.70439, 15], [-3.70439, 0.122447, 15], [0.122447, 9.36124, 15], [9.36124, 5.53441, 15], [5.39234, -4.48455, 18], [-4.48455, -2.9202, 18], [-2.9202, 6.95668, 18], [6.95668, 5.39234, 18]], faces = [[0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7], [4, 5, 9, 8], [5, 6, 10, 9], [6, 7, 11, 10], [7, 4, 8, 11], [8, 9, 13, 12], [9, 10, 14, 13], [10, 11, 15, 14], [11, 8, 12, 15], [12, 13, 17, 16], [13, 14, 18, 17], [14, 15, 19, 18], [15, 12, 16, 19], [16, 17, 21, 20], [17, 18, 22, 21], [18, 19, 23, 22], [19, 16, 20, 23], [20, 21, 25, 24], [21, 22, 26, 25], [22, 23, 27, 26], [23, 20, 24, 27], [3, 2, 1, 0], [24, 25, 26, 27]]); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0a3ff6ab..d9b643e8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -632,7 +632,6 @@ set(CORE_SOURCES ../src/csgtermnormalizer.cc ../src/Geometry.cc ../src/Polygon2d.cc - ../src/polyset.cc ../src/csgops.cc ../src/transform.cc ../src/color.cc @@ -666,7 +665,10 @@ set(NOCGAL_SOURCES ../src/builtin.cc ../src/import.cc ../src/export.cc - ../src/LibraryInfo.cc) + ../src/LibraryInfo.cc + ../src/polyset.cc + ../src/polyset-utils.cc) + set(CGAL_SOURCES ${NOCGAL_SOURCES} @@ -678,7 +680,6 @@ set(CGAL_SOURCES ../src/CGALCache.cc ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/Polygon2d-CGAL.cc - ../src/polyset-utils.cc ../src/svg.cc ../src/GeometryEvaluator.cc) @@ -749,20 +750,20 @@ set_target_properties(tests-offscreen PROPERTIES COMPILE_FLAGS "${ENABLE_OPENCSG # modulecachetest # add_executable(modulecachetest modulecachetest.cc) -target_link_libraries(modulecachetest tests-nocgal) +target_link_libraries(modulecachetest tests-nocgal ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY}) # # csgtexttest # add_executable(csgtexttest csgtexttest.cc CSGTextRenderer.cc CSGTextCache.cc) -target_link_libraries(csgtexttest tests-nocgal) +target_link_libraries(csgtexttest tests-nocgal ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY}) # # cgalcachetest # add_executable(cgalcachetest cgalcachetest.cc) set_target_properties(cgalcachetest PROPERTIES COMPILE_FLAGS "-DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}") -target_link_libraries(cgalcachetest tests-cgal) +target_link_libraries(cgalcachetest tests-cgal ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY}) # # openscad no-qt @@ -1213,7 +1214,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue964b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue990.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1004.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1005.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1005.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1061.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) list(APPEND ALL_2D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) diff --git a/tests/regression/cgalpngtest/issue1061-expected.png b/tests/regression/cgalpngtest/issue1061-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..78bd8525d0e2ef89c7874f2d97f9afbf5f0c0804 GIT binary patch literal 10709 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 J_jk~v{tqGIDNO(X literal 0 HcmV?d00001 From 845bd5706efa877e2cf5c0cb912ee3bfe934d7b3 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Tue, 9 Dec 2014 22:46:09 +0100 Subject: [PATCH 22/35] Guard against reading huge files. --- src/PlatformUtils-posix.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/PlatformUtils-posix.cc b/src/PlatformUtils-posix.cc index dbeaa411..c3767fa7 100644 --- a/src/PlatformUtils-posix.cc +++ b/src/PlatformUtils-posix.cc @@ -69,6 +69,19 @@ unsigned long PlatformUtils::stackLimit() return STACK_LIMIT_DEFAULT; } +static std::string readText(const std::string &path) +{ + std::ifstream s(path.c_str()); + s.seekg(0, std::ios::end); + if (s.fail() || s.tellg() > 4096) { + return ""; + } + s.seekg(0, std::ios::beg); + + std::string text((std::istreambuf_iterator(s)), std::istreambuf_iterator()); + return text; +} + /** * Check /etc/os-release as defined by systemd. * @see http://0pointer.de/blog/projects/os-release.html @@ -77,8 +90,7 @@ unsigned long PlatformUtils::stackLimit() */ static std::string checkOsRelease() { - std::ifstream os_release_stream("/etc/os-release"); - std::string os_release((std::istreambuf_iterator(os_release_stream)), std::istreambuf_iterator()); + std::string os_release(readText("/etc/os-release")); boost::smatch results; boost::regex pretty_name("^PRETTY_NAME=\"([^\"]+)\""); @@ -91,8 +103,7 @@ static std::string checkOsRelease() static std::string checkEtcIssue() { - std::ifstream issue_stream("/etc/issue"); - std::string issue((std::istreambuf_iterator(issue_stream)), std::istreambuf_iterator()); + std::string issue(readText("/etc/issue")); boost::regex nl("\n.*$"); issue = boost::regex_replace(issue, nl, ""); From 7e728fac6a347c1fd21428540765802b1f785afe Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Dec 2014 16:53:11 -0500 Subject: [PATCH 23/35] Improve polyset convexity check by tessellating polygons prior to testing. Fixes #1061 --- src/cgalutils.cc | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 41c5f192..cc8d870f 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -273,7 +273,11 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) if (ps.isEmpty()) return new CGAL_Nef_polyhedron(); assert(ps.getDimension() == 3); - if (ps.is_convex()) { + // Since is_convex doesn't work well with non-planar faces, + // we tessellate the polyset before checking. + PolySet ps_tri(3); + PolysetUtils::tessellate_faces(ps, ps_tri); + if (ps_tri.is_convex()) { typedef CGAL::Exact_predicates_inexact_constructions_kernel K; // Collect point cloud std::set points; @@ -316,10 +320,8 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) } } if (plane_error) try { - PolySet ps2(3); CGAL_Polyhedron P; - PolysetUtils::tessellate_faces(ps, ps2); - bool err = CGALUtils::createPolyhedronFromPolySet(ps2,P); + bool err = CGALUtils::createPolyhedronFromPolySet(ps_tri, P); if (!err) N = new CGAL_Nef_polyhedron3(P); } catch (const CGAL::Assertion_exception &e) { @@ -933,6 +935,13 @@ namespace CGALUtils { }; + /*! + Check if all faces of a polyset is within 0.1 degree of being convex. + + NB! This function can give false positives if the polyset contains + non-planar faces. To be on the safe side, consider passing a tessellated polyset. + See issue #1061. + */ bool is_approximately_convex(const PolySet &ps) { const double angle_threshold = cos(.1/180*M_PI); // .1° From 73b6700b693b95f60d98bbdd4e08562c124f5b8b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 9 Dec 2014 17:46:03 -0500 Subject: [PATCH 24/35] Empty polysets are convex. Fixes crash in is_approximately_convex() --- src/polyset.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyset.cc b/src/polyset.cc index fc8e7e04..ad6b6e59 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -142,7 +142,7 @@ void PolySet::transform(const Transform3d &mat) } bool PolySet::is_convex() const { - if (convex) return true; + if (convex || this->isEmpty()) return true; if (!convex) return false; return PolysetUtils::is_approximately_convex(*this); } From 39612397fa12c590594703c6d9c062458748c6d6 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 10 Dec 2014 22:44:39 -0500 Subject: [PATCH 25/35] #1057 Sysinfo for Mac OS X --- src/PlatformUtils-mac.mm | 65 +++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/PlatformUtils-mac.mm b/src/PlatformUtils-mac.mm index 20e72321..45157921 100644 --- a/src/PlatformUtils-mac.mm +++ b/src/PlatformUtils-mac.mm @@ -1,5 +1,8 @@ #include "PlatformUtils.h" #import +#include +#include +#include std::string PlatformUtils::pathSeparatorChar() { @@ -37,44 +40,30 @@ unsigned long PlatformUtils::stackLimit() std::string PlatformUtils::sysinfo() { - std::string result; - -#if 0 - struct utsname osinfo; - if (uname(&osinfo) == 0) { - result += osinfo.sysname; - result += " "; - result += osinfo.release; - result += " "; - result += osinfo.version; - result += " "; - result += osinfo.machine; - } else { -#endif - result += "Unknown MacOS"; -#if 0 - } - - long numcpu = sysconf(_SC_NPROCESSORS_ONLN); - if (numcpu > 0) { - result += " "; - result += boost::lexical_cast(numcpu); - result += " CPU"; - if (numcpu > 1) { - result += "s"; - } - } - - long pages = sysconf(_SC_PHYS_PAGES); - long pagesize = sysconf(_SC_PAGE_SIZE); - if ((pages > 0) && (pagesize > 0)) { - result += " "; - result += PlatformUtils::toMemorySizeString(pages * pagesize, 2); - result += " RAM"; - } -#endif - - return result; + std::string result; + + result += "Mac OS X "; + result += [[[NSProcessInfo processInfo] operatingSystemVersionString] UTF8String]; + + int mib[2]; + int64_t physical_memory; + int32_t numcpu; + size_t length64 = sizeof(int64_t); + size_t length32 = sizeof(int32_t);; + + sysctlbyname("hw.memsize", &physical_memory, &length64, NULL, 0); + sysctlbyname("hw.physicalcpu", &numcpu, &length32, NULL, 0); + + result += " "; + result += boost::lexical_cast(numcpu); + result += " CPU"; + if (numcpu > 1) result += "s"; + + result += " "; + result += PlatformUtils::toMemorySizeString(physical_memory, 2); + result += " RAM"; + + return result; } void PlatformUtils::ensureStdIO(void) {} From dd274b744a8fe77620edb5df4219296577ff4182 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 11 Dec 2014 19:42:35 +0100 Subject: [PATCH 26/35] Fix download urls for freetype and ragel; bump freetype to 2.5.4. --- scripts/macosx-build-dependencies.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 952256e2..86bb3c7b 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -515,7 +515,7 @@ build_freetype() cd "$BASEDIR"/src rm -rf "freetype-$version" if [ ! -f "freetype-$version.tar.gz" ]; then - curl --insecure -LO "http://download.savannah.gnu.org/releases/freetype/freetype-$version.tar.gz" + curl --insecure -LO "http://downloads.sourceforge.net/project/freetype/freetype2/$version/freetype-$version.tar.gz" fi tar xzf "freetype-$version.tar.gz" cd "freetype-$version" @@ -655,7 +655,7 @@ build_ragel() cd "$BASEDIR"/src rm -rf "ragel-$version" if [ ! -f "ragel-$version.tar.gz" ]; then - curl --insecure -LO "http://www.colm.net/wp-content/uploads/2014/10/ragel-$version.tar.gz" + curl --insecure -LO "http://www.colm.net/files/ragel/ragel-$version.tar.gz" fi tar xzf "ragel-$version.tar.gz" cd "ragel-$version" @@ -784,7 +784,7 @@ build_gettext 0.18.3.2 build_libffi 3.1 build_glib2 2.40.0 build_opencsg 1.4.0 -build_freetype 2.5.3 --without-png +build_freetype 2.5.4 --without-png build_ragel 6.9 build_harfbuzz 0.9.35 "--with-coretext=auto --with-glib=no" export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" From 9863aa9ab275857146cb75017bed4e7505d88402 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 16:09:55 -0500 Subject: [PATCH 27/35] #1051 Detect recursion after 1M tail recursion iterations --- src/func.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/func.cc b/src/func.cc index c7e26193..e6830099 100644 --- a/src/func.cc +++ b/src/func.cc @@ -36,6 +36,7 @@ #include "stl-utils.h" #include "printutils.h" #include "stackcheck.h" +#include "exceptions.h" #include #include @@ -150,9 +151,12 @@ ValuePtr FunctionTailRecursion::evaluate(const Context *ctx, const EvalContext * EvalContext ec(&c, call->call_arguments); Context tmp(&c); + unsigned int counter = 0; while (invert ^ expr->first->evaluate(&c)) { tmp.setVariables(definition_arguments, &ec); c.apply_variables(tmp); + + if (counter++ == 1000000) throw RecursionException("function", this->name); } ValuePtr result = endexpr->evaluate(&c); From 0a10aca8aaf49383a85cb35e7466608bc8f81d01 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 16:37:27 -0500 Subject: [PATCH 28/35] #1051 Suppress warning and error output after 5 equal messages --- src/printutils.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/printutils.cc b/src/printutils.cc index 5004c745..4e400ccb 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -2,12 +2,16 @@ #include #include #include +#include +#include std::list print_messages_stack; OutputHandlerFunc *outputhandler = NULL; void *outputhandler_data = NULL; std::string OpenSCAD::debug(""); +boost::circular_buffer lastmessages(5); + void set_output_handler(OutputHandlerFunc *newhandler, void *userdata) { outputhandler = newhandler; @@ -46,6 +50,16 @@ void PRINT(const std::string &msg) void PRINT_NOCACHE(const std::string &msg) { if (msg.empty()) return; + + if (boost::starts_with(msg, "WARNING") || boost::starts_with(msg, "ERROR")) { + int i; + for (i=0;i Date: Thu, 11 Dec 2014 16:58:20 -0500 Subject: [PATCH 29/35] #600 Tag menu action roles to allow translated menu items to move to the correct Mac OS X menu --- src/MainWindow.ui | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 81f6c34b..74365644 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -543,6 +543,9 @@ Ctrl+Q + + QAction::QuitRole + @@ -955,6 +958,9 @@ About + + QAction::AboutRole + @@ -983,6 +989,9 @@ Preferences + + QAction::PreferencesRole + From 255fc1d58dbb0f45e64f2229449f21e15cb628e9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 17:04:33 -0500 Subject: [PATCH 30/35] #1051 updated test results after suppressing repeated error messages --- tests/regression/echotest/dim-all-expected.echo | 3 --- tests/regression/echotest/for-tests-expected.echo | 11 ----------- 2 files changed, 14 deletions(-) diff --git a/tests/regression/echotest/dim-all-expected.echo b/tests/regression/echotest/dim-all-expected.echo index a16c5801..adba64d1 100644 --- a/tests/regression/echotest/dim-all-expected.echo +++ b/tests/regression/echotest/dim-all-expected.echo @@ -8,9 +8,6 @@ WARNING: Unsupported DXF Entity 'LEADER' (1) in "dim-all.dxf". ECHO: ordinateX = -49.17542445724 WARNING: Unsupported DXF Entity 'LEADER' (1) in "dim-all.dxf". ECHO: ordinateY = 30.86974532565 -WARNING: Unsupported DXF Entity 'LEADER' (1) in "dim-all.dxf". ECHO: radius = 60 -WARNING: Unsupported DXF Entity 'LEADER' (1) in "dim-all.dxf". ECHO: diameter = 120 -WARNING: Unsupported DXF Entity 'LEADER' (1) in "dim-all.dxf". ECHO: arc = 59.03624346792 diff --git a/tests/regression/echotest/for-tests-expected.echo b/tests/regression/echotest/for-tests-expected.echo index 39a8d584..d66cebf8 100644 --- a/tests/regression/echotest/for-tests-expected.echo +++ b/tests/regression/echotest/for-tests-expected.echo @@ -11,14 +11,3 @@ ECHO: "INF", 0 WARNING: Bad range parameter in for statement: too many elements (4294967295). ECHO: "-INF", 1 WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). -WARNING: Bad range parameter in for statement: too many elements (4294967295). From 9fe80a3a66afd0843442389254b911ef062e8daf Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 17:23:45 -0500 Subject: [PATCH 31/35] Mac build fix --- src/PlatformUtils-mac.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PlatformUtils-mac.mm b/src/PlatformUtils-mac.mm index 45157921..768d9c09 100644 --- a/src/PlatformUtils-mac.mm +++ b/src/PlatformUtils-mac.mm @@ -1,8 +1,9 @@ #include "PlatformUtils.h" -#import -#include #include #include +#include + +#import std::string PlatformUtils::pathSeparatorChar() { From 1bbbfad5757c7174cf711a7be94a6ec5ed94ab05 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 17:24:35 -0500 Subject: [PATCH 32/35] #964 Added test for checking correct export of nonmanifold objects --- testdata/scad/misc/nonmanifold-polyhedron.scad | 16 ++++++++++++++++ tests/CMakeLists.txt | 5 +++++ .../nonmanifold-polyhedron-expected.png | Bin 0 -> 7957 bytes 3 files changed, 21 insertions(+) create mode 100644 testdata/scad/misc/nonmanifold-polyhedron.scad create mode 100644 tests/regression/monotonepngtest/nonmanifold-polyhedron-expected.png diff --git a/testdata/scad/misc/nonmanifold-polyhedron.scad b/testdata/scad/misc/nonmanifold-polyhedron.scad new file mode 100644 index 00000000..a1b56654 --- /dev/null +++ b/testdata/scad/misc/nonmanifold-polyhedron.scad @@ -0,0 +1,16 @@ +polyhedron(points=[ +[0,0,0], +[10,0,0], +[10,10,0], +[0,10,0], +[0,-20,20], +[10,-20,20], +[10,-20,30], +[0,-20,30] +], +faces = [[0,1,2,3],[4,5,6,7], +[1,2,5,4], +[2,3,6,5], +[3,0,6,5], +[0,1,4,7] +]); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d9b643e8..0cfb1f16 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1116,6 +1116,9 @@ list(APPEND EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/bad-stl-wing.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/rotate_extrude-hole.scad) +list(APPEND EXPORTCSG_TEST_FILES + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/nonmanifold-polyhedron.scad) + disable_tests( # These don't output anything dxfpngtest_text-empty-tests @@ -1313,6 +1316,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake ${TMP}) # o stlpngtest: Export to STL, Re-import and render to PNG (--render=cgal) # o offpngtest: Export to OFF, Re-import and render to PNG (--render=cgal) # o dxfpngtest: Export to DXF, Re-import and render to PNG (--render=cgal) +# o stlcsgpngtest: Export to STL, Re-import and render to PNG (--preview) # add_cmdline_test(moduledumptest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX ast FILES @@ -1356,6 +1360,7 @@ add_cmdline_test(monotonepngtest EXE ${OPENSCAD_BINPATH} ARGS --colorscheme=Mono add_cmdline_test(stlpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_TEST_FILES}) add_cmdline_test(offpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=OFF --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_TEST_FILES}) add_cmdline_test(dxfpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=DXF --render=cgal EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D}) +add_cmdline_test(stlcsgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORTCSG_TEST_FILES}) # diff --git a/tests/regression/monotonepngtest/nonmanifold-polyhedron-expected.png b/tests/regression/monotonepngtest/nonmanifold-polyhedron-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..f3e6fe724a224865300cf4579a988d7dd5be6b38 GIT binary patch literal 7957 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 Date: Thu, 11 Dec 2014 17:27:08 -0500 Subject: [PATCH 33/35] #964 Run correct tests --- tests/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0cfb1f16..885de360 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1220,7 +1220,13 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1005.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1061.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) -list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) +list(REMOVE_ITEM EXPORT3D_TEST_FILES + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue964.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue964b.scad) +list(APPEND EXPORTCSG_TEST_FILES + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue964.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue964b.scad) list(APPEND ALL_2D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) list(APPEND OPENCSGTEST_FILES ${BUGS_FILES}) From 1f032d0d7d67f31158a12da9507f65c30612807e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 17:32:26 -0500 Subject: [PATCH 34/35] #803 Don't install OS X specific file on other platforms --- {fonts => fonts-osx/conf.d}/05-osx-fonts.conf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {fonts => fonts-osx/conf.d}/05-osx-fonts.conf (100%) diff --git a/fonts/05-osx-fonts.conf b/fonts-osx/conf.d/05-osx-fonts.conf similarity index 100% rename from fonts/05-osx-fonts.conf rename to fonts-osx/conf.d/05-osx-fonts.conf From ad69698f97c1be731762bcc12fd8f3ba1c2bb2fc Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 11 Dec 2014 18:01:56 -0500 Subject: [PATCH 35/35] Changed stlcsgpngtest to render, not preview, to be able to reuse monotonepngtest results --- tests/CMakeLists.txt | 6 ++++-- .../nonmanifold-polyhedron-expected.png | Bin 7957 -> 7668 bytes 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 885de360..9c9f84c1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1244,6 +1244,8 @@ foreach(FILE ${BUGS_FILES}) set_test_config(Bugs ${TEST_FULLNAME}) get_test_fullname(stlpngtest ${FILE} TEST_FULLNAME) set_test_config(Bugs ${TEST_FULLNAME}) + get_test_fullname(stlcsgpngtest ${FILE} TEST_FULLNAME) + set_test_config(Bugs ${TEST_FULLNAME}) endforeach() # Examples @@ -1322,7 +1324,7 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake ${TMP}) # o stlpngtest: Export to STL, Re-import and render to PNG (--render=cgal) # o offpngtest: Export to OFF, Re-import and render to PNG (--render=cgal) # o dxfpngtest: Export to DXF, Re-import and render to PNG (--render=cgal) -# o stlcsgpngtest: Export to STL, Re-import and render to PNG (--preview) +# o stlcsgpngtest: Export to STL, Re-import and render to PNG (--render) # add_cmdline_test(moduledumptest EXE ${OPENSCAD_BINPATH} ARGS -o SUFFIX ast FILES @@ -1366,7 +1368,7 @@ add_cmdline_test(monotonepngtest EXE ${OPENSCAD_BINPATH} ARGS --colorscheme=Mono add_cmdline_test(stlpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_TEST_FILES}) add_cmdline_test(offpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=OFF --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_TEST_FILES}) add_cmdline_test(dxfpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=DXF --render=cgal EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D}) -add_cmdline_test(stlcsgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORTCSG_TEST_FILES}) +add_cmdline_test(stlcsgpngtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DIR}/export_import_pngtest.py ARGS --openscad=${OPENSCAD_BINPATH} --format=STL --render EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORTCSG_TEST_FILES}) # diff --git a/tests/regression/monotonepngtest/nonmanifold-polyhedron-expected.png b/tests/regression/monotonepngtest/nonmanifold-polyhedron-expected.png index f3e6fe724a224865300cf4579a988d7dd5be6b38..27adff5c1ede8d05d1054fcf73aea0defc9bfc20 100644 GIT binary patch literal 7668 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 literal 7957 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