From 8bff31d0528cd454ae93c7967b4d76151b656003 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 27 Feb 2024 22:30:39 -0500 Subject: [PATCH] Rename --render=cgal to --render=force to force-convert to the current backend-specific geometry (#4822) * Renamed createMutableManifold*() to createManifold*(): No need to create mutable objects --- src/geometry/GeometryUtils.cc | 47 ++++++++++++++- src/geometry/GeometryUtils.h | 5 ++ src/geometry/manifold/ManifoldGeometry.cc | 49 ++++++++++----- src/geometry/manifold/ManifoldGeometry.h | 13 +++- .../manifold/manifold-applyops-minkowski.cc | 8 +-- src/geometry/manifold/manifold-applyops.cc | 22 +++---- src/geometry/manifold/manifoldutils.cc | 21 +++---- src/geometry/manifold/manifoldutils.h | 8 +-- src/io/export.h | 2 +- src/openscad.cc | 59 +++++++++++-------- tests/CMakeLists.txt | 32 +++++----- tests/export_import_pngtest.py | 6 +- 12 files changed, 178 insertions(+), 94 deletions(-) diff --git a/src/geometry/GeometryUtils.cc b/src/geometry/GeometryUtils.cc index 05d2bb8a95..f999a8819b 100644 --- a/src/geometry/GeometryUtils.cc +++ b/src/geometry/GeometryUtils.cc @@ -2,9 +2,16 @@ #include "ext/libtess2/Include/tesselator.h" #include "printutils.h" #include "Reindexer.h" -#include +#include "Feature.h" +#include "manifoldutils.h" +#include "PolySet.h" +#ifdef ENABLE_CGAL +#include "cgalutils.h" +#include "CGALHybridPolyhedron.h" +#endif #include #include +#include #include @@ -498,3 +505,41 @@ Transform3d GeometryUtils::getResizeTransform(const BoundingBox &bbox, const Vec return t; } + +// Return or force creation of backend-specific geometry. +// Will prefer Manifold if multiple backends are enabled. +// geom must be a 3D PolySet or the correct backend-specific geometry. +std::shared_ptr GeometryUtils::getBackendSpecificGeometry(const std::shared_ptr& geom) +{ +#if ENABLE_MANIFOLD + if (Feature::ExperimentalManifold.is_enabled()) { + if (const auto ps = std::dynamic_pointer_cast(geom)) { + return ManifoldUtils::createManifoldFromPolySet(*ps); + } else if (auto mani = std::dynamic_pointer_cast(geom)) { + return geom; + } else { + assert(false && "Unexpected geometry"); + } + } +#endif +#if ENABLE_CGAL + if (Feature::ExperimentalFastCsg.is_enabled()) { + if (auto ps = std::dynamic_pointer_cast(geom)) { + return CGALUtils::createHybridPolyhedronFromPolySet(*ps); + } else if (auto poly = std::dynamic_pointer_cast(geom)) { + return geom; + } else { + assert(false && "Unexpected geometry"); + } + } else { + if (auto ps = std::dynamic_pointer_cast(geom)) { + return CGALUtils::createNefPolyhedronFromPolySet(*ps); + } else if (auto poly = std::dynamic_pointer_cast(geom)) { + return geom; + } else { + assert(false && "Unexpected geometry"); + } + } +#endif + return nullptr; +} diff --git a/src/geometry/GeometryUtils.h b/src/geometry/GeometryUtils.h index 444ba4c5d3..81e66914d6 100644 --- a/src/geometry/GeometryUtils.h +++ b/src/geometry/GeometryUtils.h @@ -1,8 +1,10 @@ #pragma once #include "linalg.h" +#include "Geometry.h" #include #include +#include using Polygon = std::vector; using Polygons = std::vector; @@ -29,6 +31,7 @@ struct IndexedPolyMesh { }; namespace GeometryUtils { + bool tessellatePolygon(const Polygon& polygon, Polygons& triangles, const Vector3f *normal = nullptr); @@ -41,4 +44,6 @@ int findUnconnectedEdges(const std::vector>& polygons); int findUnconnectedEdges(const std::vector& triangles); Transform3d getResizeTransform(const BoundingBox &bbox, const Vector3d& newsize, const Eigen::Matrix& autosize); +std::shared_ptr getBackendSpecificGeometry(const std::shared_ptr& geom); + } diff --git a/src/geometry/manifold/ManifoldGeometry.cc b/src/geometry/manifold/ManifoldGeometry.cc index b220594cc2..2303f6b6cb 100644 --- a/src/geometry/manifold/ManifoldGeometry.cc +++ b/src/geometry/manifold/ManifoldGeometry.cc @@ -160,41 +160,60 @@ std::shared_ptr ManifoldGeometry::toPolyhedron() const template std::shared_ptr> ManifoldGeometry::toPolyhedron() const; #endif -std::shared_ptr binOp(ManifoldGeometry& lhs, ManifoldGeometry& rhs, manifold::OpType opType) { - return std::make_shared(lhs.getManifold().Boolean(rhs.getManifold(), opType)); +std::shared_ptr binOp(const manifold::Manifold& lhs, const manifold::Manifold& rhs, manifold::OpType opType) { + return std::make_shared(lhs.Boolean(rhs, opType)); +} + +ManifoldGeometry ManifoldGeometry::operator+(const ManifoldGeometry& other) const { + return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Add)}; } void ManifoldGeometry::operator+=(ManifoldGeometry& other) { - manifold_ = binOp(*this, other, manifold::OpType::Add); + manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Add); +} + +ManifoldGeometry ManifoldGeometry::operator*(const ManifoldGeometry& other) const { + return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Intersect)}; } void ManifoldGeometry::operator*=(ManifoldGeometry& other) { - manifold_ = binOp(*this, other, manifold::OpType::Intersect); + manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Intersect); +} + +ManifoldGeometry ManifoldGeometry::operator-(const ManifoldGeometry& other) const { + return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Subtract)}; } void ManifoldGeometry::operator-=(ManifoldGeometry& other) { - manifold_ = binOp(*this, other, manifold::OpType::Subtract); + manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Subtract); } -void ManifoldGeometry::minkowski(ManifoldGeometry& other) { +std::shared_ptr minkowskiOp(const ManifoldGeometry& lhs, const ManifoldGeometry& rhs) { // FIXME: How to deal with operation not supported? #ifdef ENABLE_CGAL - auto lhs = std::shared_ptr(CGALUtils::createNefPolyhedronFromPolySet(*this->toPolySet())); - auto rhs = std::shared_ptr(CGALUtils::createNefPolyhedronFromPolySet(*other.toPolySet())); - if (lhs->isEmpty() || rhs->isEmpty()) { - clear(); - return; + auto lhs_nef = std::shared_ptr(CGALUtils::createNefPolyhedronFromPolySet(*lhs.toPolySet())); + auto rhs_nef = std::shared_ptr(CGALUtils::createNefPolyhedronFromPolySet(*rhs.toPolySet())); + if (lhs_nef->isEmpty() || rhs_nef->isEmpty()) { + return {}; } - lhs->minkowski(*rhs); + lhs_nef->minkowski(*rhs_nef); - auto ps = PolySetUtils::getGeometryAsPolySet(lhs); - if (!ps) clear(); + auto ps = PolySetUtils::getGeometryAsPolySet(lhs_nef); + if (!ps) return {}; else { - manifold_ = ManifoldUtils::trustedPolySetToManifold(*ps); + return ManifoldUtils::trustedPolySetToManifold(*ps); } #endif } +void ManifoldGeometry::minkowski(ManifoldGeometry& other) { + manifold_ = minkowskiOp(*this, other); +} + +ManifoldGeometry ManifoldGeometry::minkowski(const ManifoldGeometry& other) const { + return {minkowskiOp(*this, other)}; +} + void ManifoldGeometry::transform(const Transform3d& mat) { glm::mat4x3 glMat( // Column-major ordering diff --git a/src/geometry/manifold/ManifoldGeometry.h b/src/geometry/manifold/ManifoldGeometry.h index c1f8e8566c..a65e4db3cb 100644 --- a/src/geometry/manifold/ManifoldGeometry.h +++ b/src/geometry/manifold/ManifoldGeometry.h @@ -47,6 +47,17 @@ class ManifoldGeometry : public Geometry void operator-=(ManifoldGeometry& other); /*! In-place minkowksi operation. */ void minkowski(ManifoldGeometry& other); + + /*! union. */ + ManifoldGeometry operator+(const ManifoldGeometry& other) const; + /*! intersection. */ + ManifoldGeometry operator*(const ManifoldGeometry& other) const; + /*! difference. */ + ManifoldGeometry operator-(const ManifoldGeometry& other) const; + /*! minkowksi operation. */ + ManifoldGeometry minkowski(const ManifoldGeometry& other) const; + + void transform(const Transform3d& mat) override; void resize(const Vector3d& newsize, const Eigen::Matrix& autosize) override; @@ -56,5 +67,5 @@ class ManifoldGeometry : public Geometry const manifold::Manifold& getManifold() const; private: - std::shared_ptr manifold_; + std::shared_ptr manifold_; }; diff --git a/src/geometry/manifold/manifold-applyops-minkowski.cc b/src/geometry/manifold/manifold-applyops-minkowski.cc index 6350edc246..8970511fcd 100644 --- a/src/geometry/manifold/manifold-applyops-minkowski.cc +++ b/src/geometry/manifold/manifold-applyops-minkowski.cc @@ -111,9 +111,9 @@ std::shared_ptr applyMinkowskiManifold(const Geometry::Geometrie std::vector minkowski_points; minkowski_points.reserve(points0.size() * points1.size()); - for (size_t i = 0; i < points0.size(); ++i) { - for (size_t j = 0; j < points1.size(); ++j) { - minkowski_points.push_back(points0[i] + (points1[j] - CGAL::ORIGIN)); + for (const auto& p0 : points0) { + for (const auto p1 : points1) { + minkowski_points.push_back(p0 + (p1 - CGAL::ORIGIN)); } } @@ -175,7 +175,7 @@ std::shared_ptr applyMinkowskiManifold(const Geometry::Geometrie t.reset(); CGALUtils::triangulateFaces(mesh); - return ManifoldUtils::createMutableManifoldFromSurfaceMesh(mesh); + return ManifoldUtils::createManifoldFromSurfaceMesh(mesh); }; std::vector> result_parts(part_points[0].size() * part_points[1].size()); diff --git a/src/geometry/manifold/manifold-applyops.cc b/src/geometry/manifold/manifold-applyops.cc index 7b176db548..6b84bc0818 100644 --- a/src/geometry/manifold/manifold-applyops.cc +++ b/src/geometry/manifold/manifold-applyops.cc @@ -22,52 +22,52 @@ Location getLocation(const std::shared_ptr& node) */ std::shared_ptr applyOperator3DManifold(const Geometry::Geometries& children, OpenSCADOperator op) { - auto N = std::make_shared(); + std::shared_ptr geom; bool foundFirst = false; for (const auto& item : children) { - auto chN = item.second ? createMutableManifoldFromGeometry(item.second) : nullptr; + auto chN = item.second ? createManifoldFromGeometry(item.second) : nullptr; // Intersecting something with nothing results in nothing if (!chN || chN->isEmpty()) { if (op == OpenSCADOperator::INTERSECTION) { - N = nullptr; + geom = nullptr; break; } if (op == OpenSCADOperator::DIFFERENCE && !foundFirst) { - N = nullptr; + geom = nullptr; break; } continue; } - // Initialize N with first expected geometric object + // Initialize geom with first expected geometric object if (!foundFirst) { - N = chN; + geom = std::make_shared(*chN); foundFirst = true; continue; } switch (op) { case OpenSCADOperator::UNION: - *N += *chN; + *geom = *geom + *chN; break; case OpenSCADOperator::INTERSECTION: - *N *= *chN; + *geom = *geom * *chN; break; case OpenSCADOperator::DIFFERENCE: - *N -= *chN; + *geom = *geom - *chN; break; case OpenSCADOperator::MINKOWSKI: - N->minkowski(*chN); + *geom = geom->minkowski(*chN); break; default: LOG(message_group::Error, "Unsupported CGAL operator: %1$d", static_cast(op)); } if (item.first) item.first->progress_report(); } - return N; + return geom; } }; // namespace ManifoldUtils diff --git a/src/geometry/manifold/manifoldutils.cc b/src/geometry/manifold/manifoldutils.cc index e259e54802..9b2ed4809b 100644 --- a/src/geometry/manifold/manifoldutils.cc +++ b/src/geometry/manifold/manifoldutils.cc @@ -66,7 +66,7 @@ std::shared_ptr trustedPolySetToManifold(const PolySet& ps) } template -std::shared_ptr createMutableManifoldFromSurfaceMesh(const TriangleMesh& tm) +std::shared_ptr createManifoldFromSurfaceMesh(const TriangleMesh& tm) { typedef typename TriangleMesh::Vertex_index vertex_descriptor; @@ -102,11 +102,11 @@ std::shared_ptr createMutableManifoldFromSurfaceMesh(const Tri } #ifdef ENABLE_CGAL -template std::shared_ptr createMutableManifoldFromSurfaceMesh(const CGAL::Surface_mesh> &tm); -template std::shared_ptr createMutableManifoldFromSurfaceMesh(const CGAL_DoubleMesh &tm); +template std::shared_ptr createManifoldFromSurfaceMesh(const CGAL::Surface_mesh> &tm); +template std::shared_ptr createManifoldFromSurfaceMesh(const CGAL_DoubleMesh &tm); #endif -std::shared_ptr createMutableManifoldFromPolySet(const PolySet& ps) +std::shared_ptr createManifoldFromPolySet(const PolySet& ps) { #ifdef ENABLE_CGAL PolySet psq(ps); @@ -141,22 +141,19 @@ std::shared_ptr createMutableManifoldFromPolySet(const PolySet } } - return createMutableManifoldFromSurfaceMesh(m); + return createManifoldFromSurfaceMesh(m); #else return std::make_shared(); #endif } -std::shared_ptr createMutableManifoldFromGeometry(const std::shared_ptr& geom) { +std::shared_ptr createManifoldFromGeometry(const std::shared_ptr& geom) { if (auto mani = std::dynamic_pointer_cast(geom)) { - return std::make_shared(*mani); + return mani; } - - auto ps = PolySetUtils::getGeometryAsPolySet(geom); - if (ps) { - return createMutableManifoldFromPolySet(*ps); + if (auto ps = PolySetUtils::getGeometryAsPolySet(geom)) { + return createManifoldFromPolySet(*ps); } - return nullptr; } diff --git a/src/geometry/manifold/manifoldutils.h b/src/geometry/manifold/manifoldutils.h index 3b7ec19513..3a23d61cf5 100644 --- a/src/geometry/manifold/manifoldutils.h +++ b/src/geometry/manifold/manifoldutils.h @@ -16,14 +16,14 @@ namespace ManifoldUtils { const char* statusToString(manifold::Manifold::Error status); - /*! If the PolySet isn't trusted, use createMutableManifoldFromPolySet which will triangulate and reorient it. */ + /*! If the PolySet isn't trusted, use createManifoldFromPolySet which will triangulate and reorient it. */ std::shared_ptr trustedPolySetToManifold(const PolySet& ps); - std::shared_ptr createMutableManifoldFromPolySet(const PolySet& ps); - std::shared_ptr createMutableManifoldFromGeometry(const std::shared_ptr& geom); + std::shared_ptr createManifoldFromPolySet(const PolySet& ps); + std::shared_ptr createManifoldFromGeometry(const std::shared_ptr& geom); template - std::shared_ptr createMutableManifoldFromSurfaceMesh(const TriangleMesh& mesh); + std::shared_ptr createManifoldFromSurfaceMesh(const TriangleMesh& mesh); std::shared_ptr applyOperator3DManifold(const Geometry::Geometries& children, OpenSCADOperator op); diff --git a/src/io/export.h b/src/io/export.h index e4ef0b768f..974ded5994 100644 --- a/src/io/export.h +++ b/src/io/export.h @@ -115,7 +115,7 @@ void export_nef3(const std::shared_ptr& geom, std::ostream& outp enum class Previewer { OPENCSG, THROWNTOGETHER }; -enum class RenderType { GEOMETRY, CGAL, OPENCSG, THROWNTOGETHER }; +enum class RenderType { GEOMETRY, BACKEND_SPECIFIC, OPENCSG, THROWNTOGETHER }; struct ExportFileFormatOptions { const std::map exportFileFormats{ diff --git a/src/openscad.cc b/src/openscad.cc index 3989ab36da..b3442aefb6 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -52,6 +52,10 @@ #include #include +#ifdef ENABLE_MANIFOLD +#include "manifoldutils.h" +#endif + #ifdef ENABLE_CGAL #include "CGAL_Nef_polyhedron.h" #include "cgalutils.h" @@ -334,7 +338,7 @@ struct CommandLine const std::string summaryFile; }; -int do_export(const CommandLine& cmd, const RenderVariables& render_variables, FileFormat curFormat, SourceFile *root_file); +int do_export(const CommandLine& cmd, const RenderVariables& render_variables, FileFormat export_format, SourceFile *root_file); int cmdline(const CommandLine& cmd) { @@ -475,7 +479,7 @@ int cmdline(const CommandLine& cmd) } } -int do_export(const CommandLine& cmd, const RenderVariables& render_variables, FileFormat curFormat, SourceFile *root_file) +int do_export(const CommandLine& cmd, const RenderVariables& render_variables, FileFormat export_format, SourceFile *root_file) { auto filename_str = fs::path(cmd.output_file).generic_string(); auto fpath = fs::absolute(fs::path(cmd.filename)); @@ -525,7 +529,7 @@ int do_export(const CommandLine& cmd, const RenderVariables& render_variables, F } Tree tree(root_node, fparent.string()); - if (curFormat == FileFormat::CSG) { + if (export_format == FileFormat::CSG) { // https://github.com/openscad/openscad/issues/128 // When I use the csg ouptput from the command line the paths in 'import' // statements become relative. But unfortunately they become relative to @@ -536,17 +540,17 @@ int do_export(const CommandLine& cmd, const RenderVariables& render_variables, F stream << tree.getString(*root_node, "\t") << "\n"; }); fs::current_path(cmd.original_path); - } else if (curFormat == FileFormat::AST) { + } else if (export_format == FileFormat::AST) { fs::current_path(fparent); // Force exported filenames to be relative to document path with_output(cmd.is_stdout, filename_str, [root_file](std::ostream& stream) { stream << root_file->dump(""); }); fs::current_path(cmd.original_path); - } else if (curFormat == FileFormat::PARAM) { + } else if (export_format == FileFormat::PARAM) { with_output(cmd.is_stdout, filename_str, [&root_file, &fpath](std::ostream& stream) { export_param(root_file, fpath, stream); }); - } else if (curFormat == FileFormat::TERM) { + } else if (export_format == FileFormat::TERM) { CSGTreeEvaluator csgRenderer(tree); auto root_raw_term = csgRenderer.buildCSGTree(*root_node); with_output(cmd.is_stdout, filename_str, [root_raw_term](std::ostream& stream) { @@ -556,7 +560,7 @@ int do_export(const CommandLine& cmd, const RenderVariables& render_variables, F stream << root_raw_term->dump() << "\n"; } }); - } else if (curFormat == FileFormat::ECHO) { + } else if (export_format == FileFormat::ECHO) { // echo -> don't need to evaluate any geometry } else { // start measuring render time @@ -564,55 +568,54 @@ int do_export(const CommandLine& cmd, const RenderVariables& render_variables, F GeometryEvaluator geomevaluator(tree); unique_ptr glview; std::shared_ptr root_geom; - if ((curFormat == FileFormat::ECHO || curFormat == FileFormat::PNG) && (cmd.viewOptions.renderer == RenderType::OPENCSG || cmd.viewOptions.renderer == RenderType::THROWNTOGETHER)) { + if ((export_format == FileFormat::ECHO || export_format == FileFormat::PNG) && (cmd.viewOptions.renderer == RenderType::OPENCSG || cmd.viewOptions.renderer == RenderType::THROWNTOGETHER)) { // OpenCSG or throwntogether png -> just render a preview glview = prepare_preview(tree, cmd.viewOptions, camera); if (!glview) return 1; - } -#ifdef ENABLE_CGAL - else { + } else { // Force creation of concrete geometry (mostly for testing) // FIXME: Consider adding MANIFOLD as a valid --render argument and ViewOption, to be able to distinguish from CGAL constexpr bool allownef = true; root_geom = geomevaluator.evaluateGeometry(*tree.root(), allownef); if (root_geom) { - if (cmd.viewOptions.renderer == RenderType::CGAL && root_geom->getDimension() == 3) { + if (cmd.viewOptions.renderer == RenderType::BACKEND_SPECIFIC && root_geom->getDimension() == 3) { if (auto geomlist = std::dynamic_pointer_cast(root_geom)) { auto flatlist = geomlist->flatten(); for (auto& child : flatlist) { if (child.second->getDimension() == 3) { - child.second = CGALUtils::getNefPolyhedronFromGeometry(child.second); + child.second = GeometryUtils::getBackendSpecificGeometry(child.second); } } root_geom = std::make_shared(flatlist); } else { - root_geom = CGALUtils::getNefPolyhedronFromGeometry(root_geom); + root_geom = GeometryUtils::getBackendSpecificGeometry(root_geom); } - LOG("Converted to Nef polyhedron"); + LOG("Converted to backend-specific geometry"); } } else { - // FIXME: The default geometry doesn't need to be a Nef polyhedron. Why not make it a PolySet? - root_geom = std::make_shared(); + root_geom = std::make_shared(3); + if (cmd.viewOptions.renderer == RenderType::BACKEND_SPECIFIC) { + root_geom = GeometryUtils::getBackendSpecificGeometry(root_geom); + } } } -#endif - if (is3D(curFormat)) { - if (!checkAndExport(root_geom, 3, curFormat, cmd.is_stdout, filename_str)) { + if (is3D(export_format)) { + if (!checkAndExport(root_geom, 3, export_format, cmd.is_stdout, filename_str)) { return 1; } } - if (is2D(curFormat)) { - if (!checkAndExport(root_geom, 2, curFormat, cmd.is_stdout, filename_str)) { + if (is2D(export_format)) { + if (!checkAndExport(root_geom, 2, export_format, cmd.is_stdout, filename_str)) { return 1; } } - if (curFormat == FileFormat::PNG) { + if (export_format == FileFormat::PNG) { bool success = true; bool wrote = with_output(cmd.is_stdout, filename_str, [&success, &root_geom, &cmd, &camera, &glview](std::ostream& stream) { - if (cmd.viewOptions.renderer == RenderType::CGAL || cmd.viewOptions.renderer == RenderType::GEOMETRY) { + if (cmd.viewOptions.renderer == RenderType::BACKEND_SPECIFIC || cmd.viewOptions.renderer == RenderType::GEOMETRY) { success = export_png(root_geom, cmd.viewOptions, camera, stream); } else { success = export_png(*glview, stream); @@ -1078,8 +1081,12 @@ int main(int argc, char **argv) if (vm.count("preview")) { if (vm["preview"].as() == "throwntogether") viewOptions.renderer = RenderType::THROWNTOGETHER; } else if (vm.count("render")) { - if (vm["render"].as() == "cgal") viewOptions.renderer = RenderType::CGAL; - else viewOptions.renderer = RenderType::GEOMETRY; + // Note: "cgal" is here for backwards compatibility, can probably be removed soon + if (vm["render"].as() == "cgal" || vm["render"].as() == "force") { + viewOptions.renderer = RenderType::BACKEND_SPECIFIC; + } else { + viewOptions.renderer = RenderType::GEOMETRY; + } } viewOptions.previewer = (viewOptions.renderer == RenderType::THROWNTOGETHER) ? Previewer::THROWNTOGETHER : Previewer::OPENCSG; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5c1b40af4c..2f8f4d42f7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -928,10 +928,10 @@ set_test_config(Examples FILES ${EXAMPLE_2D_FILES} PREFIXES dxfpngtest) # o csgpngtest: 1) Export to .csg, 2) import .csg and export to PNG (--render) # o monotonepngtest: Same as cgalpngtest but with the "Monotone" color scheme # o stlpngtest: Export to STL, Re-import and render to PNG (--render) -# o stlcgalpngtest: Export to STL, Re-import and render to PNG (--render=cgal) +# o stlcgalpngtest: Export to STL, Re-import and render to PNG (--render=force) # o offpngtest: Export to OFF, Re-import and render to PNG (--render) -# o offcgalpngtest: Export to STL, Re-import and render to PNG (--render=cgal) -# o dxfpngtest: Export to DXF, Re-import and render to PNG (--render=cgal) +# o offcgalpngtest: Export to STL, Re-import and render to PNG (--render=force) +# o dxfpngtest: Export to DXF, Re-import and render to PNG (--render=force) # add_cmdline_test(astdumptest OPENSCAD SUFFIX ast FILES @@ -1004,10 +1004,10 @@ add_cmdline_test(lazyunion-dump EXPERIMENTAL OPENSCAD SUFFIX csg FILES ${ add_cmdline_test(lazyunion-opencsg EXPERIMENTAL OPENSCAD SUFFIX png FILES ${LAZYUNION_FILES} ARGS --enable=lazy-union) add_cmdline_test(lazyunion-cgalpng EXPERIMENTAL OPENSCAD SUFFIX png FILES ${LAZYUNION_FILES} ARGS --enable=lazy-union --render) add_cmdline_test(lazyunion-monotonepng EXPERIMENTAL OPENSCAD SUFFIX png FILES ${LAZYUNION_3D_FILES} ARGS --colorscheme=Monotone --enable=lazy-union --render ) -add_cmdline_test(lazyunion-stlpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_3D_FILES} EXPECTEDDIR lazyunion-monotonepng ARGS ${OPENSCAD_ARG} --format=STL --enable=lazy-union --render=cgal) -add_cmdline_test(lazyunion-offpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_3D_FILES} EXPECTEDDIR lazyunion-monotonepng ARGS ${OPENSCAD_ARG} --format=OFF --enable=lazy-union --render=cgal) -add_cmdline_test(lazyunion-dxfpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_2D_FILES} EXPECTEDDIR lazyunion-cgalpng ARGS ${OPENSCAD_ARG} --format=DXF --enable=lazy-union --render=cgal) -add_cmdline_test(lazyunion-svgpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_2D_FILES} EXPECTEDDIR lazyunion-cgalpng ARGS ${OPENSCAD_ARG} --format=SVG --enable=lazy-union --render=cgal) +add_cmdline_test(lazyunion-stlpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_3D_FILES} EXPECTEDDIR lazyunion-monotonepng ARGS ${OPENSCAD_ARG} --format=STL --enable=lazy-union --render=force) +add_cmdline_test(lazyunion-offpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_3D_FILES} EXPECTEDDIR lazyunion-monotonepng ARGS ${OPENSCAD_ARG} --format=OFF --enable=lazy-union --render=force) +add_cmdline_test(lazyunion-dxfpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_2D_FILES} EXPECTEDDIR lazyunion-cgalpng ARGS ${OPENSCAD_ARG} --format=DXF --enable=lazy-union --render=force) +add_cmdline_test(lazyunion-svgpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${LAZYUNION_2D_FILES} EXPECTEDDIR lazyunion-cgalpng ARGS ${OPENSCAD_ARG} --format=SVG --enable=lazy-union --render=force) add_cmdline_test(manifold-cgalpng EXPERIMENTAL OPENSCAD SUFFIX png FILES ${SCADFILES_WITH_DIFFERENT_MANIFOLD_EXPECTATIONS} ARGS --enable=manifold --render) @@ -1021,8 +1021,8 @@ add_cmdline_test(offpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP add_cmdline_test(amfpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_3D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=AMF) add_cmdline_test(3mfpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_3D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=3MF) add_cmdline_test(objpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_3D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=OBJ) -add_cmdline_test(dxfpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_2D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=DXF --render=cgal) -add_cmdline_test(svgpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_2D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=SVG --render=cgal) +add_cmdline_test(dxfpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_2D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=DXF --render=force) +add_cmdline_test(svgpngtest SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXP_IMP_2D_TEST} EXPECTEDDIR monotonepngtest ARGS ${OPENSCAD_ARG} --format=SVG --render=force) add_cmdline_test(pdfexporttest SCRIPT ${EXPORT_PNGTEST_PY} SUFFIX png FILES ${SCAD_PDF_FILES} EXPECTEDDIR pdfexporttest ARGS ${OPENSCAD_ARG} --format=PDF KERNEL Square:2) # Corner-case Export/Import tests @@ -1037,14 +1037,14 @@ add_cmdline_test(stlpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCA # cgalstlpngtest: CGAL STL output, normal rendering add_cmdline_test(stlcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=STL --require-manifold --render EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGAL_TEST_FILES}) # cgalstlcgalpngtest: CGAL STL output, CGAL rendering -add_cmdline_test(cgalstlcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=ASCIISTL --require-manifold --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGALCGAL_TEST_FILES}) +add_cmdline_test(cgalstlcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=ASCIISTL --require-manifold --render=force EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGALCGAL_TEST_FILES}) # cgalbinstlcgalpngtest: CGAL binary STL output, CGAL rendering -add_cmdline_test(cgalbinstlcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=BINSTL --require-manifold --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGALCGAL_TEST_FILES}) +add_cmdline_test(cgalbinstlcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=BINSTL --require-manifold --render=force EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGALCGAL_TEST_FILES}) add_cmdline_test(offpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=OFF --render EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_TEST_FILES}) -add_cmdline_test(offcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=OFF --render=cgal EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGAL_TEST_FILES}) -add_cmdline_test(dxfpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=DXF --render=cgal EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D} ${SCAD_DXF_FILES}) -add_cmdline_test(svgpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=SVG --render=cgal EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D} ${SCAD_SVG_FILES}) +add_cmdline_test(offcgalpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=OFF --render=force EXPECTEDDIR monotonepngtest SUFFIX png FILES ${EXPORT3D_CGAL_TEST_FILES}) +add_cmdline_test(dxfpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=DXF --render=force EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D} ${SCAD_DXF_FILES}) +add_cmdline_test(svgpngtest SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=SVG --render=force EXPECTEDDIR cgalpngtest SUFFIX png FILES ${FILES_2D} ${SCAD_SVG_FILES}) # Failing tests add_failing_test(stlfailedtest SUFFIX stl FILES ${TEST_SCAD_DIR}/misc/empty-union.scad ARGS --retval=1) @@ -1175,8 +1175,8 @@ add_cmdline_test(opencsgtest EXPERIMENTAL OPENSCAD FILES ${EXPERIMENTAL_T add_cmdline_test(throwntogethertest EXPERIMENTAL OPENSCAD FILES ${EXPERIMENTAL_TEXTMETRICS_FILES} ARGS --preview=throwntogether --enable=textmetrics SUFFIX png) add_cmdline_test(csgpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} SUFFIX png FILES ${EXPERIMENTAL_TEXTMETRICS_FILES} EXPECTEDDIR cgalpngtest ARGS ${OPENSCAD_ARG} --format=csg --render --enable=textmetrics) add_cmdline_test(cgalpngtest EXPERIMENTAL OPENSCAD FILES ${EXPERIMENTAL_TEXTMETRICS_FILES} SUFFIX png ARGS --render --enable=textmetrics) -add_cmdline_test(dxfpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=DXF --render=cgal --enable=textmetrics EXPECTEDDIR cgalpngtest SUFFIX png FILES ${EXPERIMENTAL_TEXTMETRICS_FILES}) -add_cmdline_test(svgpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=SVG --render=cgal --enable=textmetrics EXPECTEDDIR cgalpngtest SUFFIX png FILES ${EXPERIMENTAL_TEXTMETRICS_FILES}) +add_cmdline_test(dxfpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=DXF --render=force --enable=textmetrics EXPECTEDDIR cgalpngtest SUFFIX png FILES ${EXPERIMENTAL_TEXTMETRICS_FILES}) +add_cmdline_test(svgpngtest EXPERIMENTAL SCRIPT ${EX_IM_PNGTEST_PY} ARGS ${OPENSCAD_ARG} --format=SVG --render=force --enable=textmetrics EXPECTEDDIR cgalpngtest SUFFIX png FILES ${EXPERIMENTAL_TEXTMETRICS_FILES}) ############################ diff --git a/tests/export_import_pngtest.py b/tests/export_import_pngtest.py index 4aacb55cfd..b93b493b60 100644 --- a/tests/export_import_pngtest.py +++ b/tests/export_import_pngtest.py @@ -14,7 +14,7 @@ # # All the optional openscad args are passed on to OpenSCAD both in step 2 and 4. # Exception: In any --render arguments are passed, the first pass (step 2) will always -# be run with --render=cgal while the second pass (step 4) will use the passed --render +# be run with --render=force while the second pass (step 4) will use the passed --render # argument. # # This script should return 0 on success, not-0 on error. @@ -99,9 +99,9 @@ def createImport(inputfile, scadfile): # # First run: Just export the given filetype -# For any --render arguments to --render=cgal +# For any --render arguments to --render=force # -tmpargs = ['--render=cgal' if arg.startswith('--render') else arg for arg in remaining_args] +tmpargs = ['--render=force' if arg.startswith('--render') else arg for arg in remaining_args] if export_format is not None: tmpargs.extend(['--export-format', export_format])