mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-10 01:01:57 +00:00
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp. * Ignore minilzo's Config Headers in clang-tidy lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes. * Add Missing Includes Across the Remaining Sources and Tests Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo. * Make the GUI and Test Headers Compile on Their Own Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone. * Keep Windows and nanosvg Setup Ahead of the Added Includes OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build. * Add the GUI Includes the First Pass Missed Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass. * Keep the Added Test Includes Below the NOMINMAX Guard test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
110 lines
4.3 KiB
C++
110 lines
4.3 KiB
C++
#pragma once
|
|
#include "libslic3r/libslic3r.h"
|
|
#include <pybind11/pybind11.h>
|
|
#include <pybind11/numpy.h>
|
|
#include "libslic3r/Config.hpp" // ConfigBase
|
|
#include "libslic3r/Point.hpp" // Point/Point3 packing asserts, Vec3d, Transform3d
|
|
#include <pybind11/pytypes.h>
|
|
#include <pybind11/cast.h>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace Slic3r {
|
|
|
|
// Point/Point3 must be tightly packed for zero-copy views. coord_t = int64_t.
|
|
static_assert(sizeof(Point) == 2 * sizeof(coord_t), "Point must be 2 packed coord_t");
|
|
static_assert(sizeof(Point3) == 3 * sizeof(coord_t), "Point3 must be 3 packed coord_t");
|
|
|
|
// Run a builder that constructs numpy objects, translating the "numpy missing"
|
|
// ImportError into an actionable message (plugins must declare numpy as a dep).
|
|
template<typename Builder>
|
|
pybind11::object with_numpy(Builder&& build)
|
|
{
|
|
namespace py = pybind11;
|
|
try {
|
|
return std::forward<Builder>(build)();
|
|
} catch (py::error_already_set& err) {
|
|
if (err.matches(PyExc_ImportError))
|
|
throw py::import_error("numpy is required to access geometry/mesh arrays; "
|
|
"add dependencies = [\"numpy\"] to your plugin metadata");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Zero-copy, read-only (rows, N) numpy view over `data`, whose lifetime is tied
|
|
// to `base` (the array's base object). T is the element scalar (coord_t = int64
|
|
// for slicing coords, float for mesh vertices). rows == 0 / null data yields a
|
|
// fresh empty (0, N) array with no base.
|
|
template<typename T, int N>
|
|
pybind11::array make_readonly_rows(pybind11::handle base, const T* data, pybind11::ssize_t rows)
|
|
{
|
|
namespace py = pybind11;
|
|
if (rows == 0 || data == nullptr) {
|
|
py::array_t<T> empty(std::vector<py::ssize_t>{ 0, (py::ssize_t) N });
|
|
// Mark the fresh empty array read-only so every return path of this
|
|
// helper yields a read-only view.
|
|
empty.attr("setflags")(py::arg("write") = false);
|
|
return std::move(empty);
|
|
}
|
|
py::array_t<T> arr(
|
|
{ rows, (py::ssize_t) N },
|
|
{ (py::ssize_t)(N * sizeof(T)), (py::ssize_t) sizeof(T) },
|
|
data, base);
|
|
// A base-carrying array is writable by default in pybind11; force read-only.
|
|
arr.attr("setflags")(py::arg("write") = false);
|
|
return std::move(arr);
|
|
}
|
|
|
|
// Zero-copy, WRITABLE (rows, N) numpy view over `data`, lifetime tied to `base`.
|
|
// Twin of make_readonly_rows: a base-carrying pybind array is writable by default,
|
|
// so we simply do not clear the write flag. Writing through the view mutates the
|
|
// underlying C++ buffer in place. rows == 0 / null data yields a fresh empty (0, N)
|
|
// array (writable, no base).
|
|
template<typename T, int N>
|
|
pybind11::array make_writable_rows(pybind11::handle base, T* data, pybind11::ssize_t rows)
|
|
{
|
|
namespace py = pybind11;
|
|
if (rows == 0 || data == nullptr)
|
|
return py::array_t<T>(std::vector<py::ssize_t>{ 0, (py::ssize_t) N });
|
|
return py::array_t<T>(
|
|
{ rows, (py::ssize_t) N },
|
|
{ (py::ssize_t)(N * sizeof(T)), (py::ssize_t) sizeof(T) },
|
|
data, base);
|
|
}
|
|
|
|
// Serialize one config key to a Python string, or None if the key is absent.
|
|
// Works on any ConfigBase (resolved DynamicPrintConfig snapshots,
|
|
// PrintObjectConfig, PrintRegionConfig, preset configs).
|
|
inline pybind11::object config_value_or_none(const ConfigBase& config, const std::string& key)
|
|
{
|
|
if (!config.has(key))
|
|
return pybind11::none();
|
|
return pybind11::cast(config.opt_serialize(key));
|
|
}
|
|
|
|
// Plugins receive 3D vectors as plain Python tuples (x, y, z) so the API stays
|
|
// Pythonic and free of an Eigen/numpy runtime dependency.
|
|
inline pybind11::tuple vec3_to_tuple(const Vec3d& v)
|
|
{
|
|
return pybind11::make_tuple(v.x(), v.y(), v.z());
|
|
}
|
|
|
|
// 4x4 row-major float64 copy of an affine transform. Eigen stores column-major,
|
|
// so fill element-wise to produce correct C-order data. Requires numpy.
|
|
inline pybind11::object mat4_to_numpy(const Transform3d& transform)
|
|
{
|
|
namespace py = pybind11;
|
|
return with_numpy([&] {
|
|
py::array_t<double> array({ py::ssize_t(4), py::ssize_t(4) });
|
|
auto view = array.mutable_unchecked<2>();
|
|
const auto& matrix = transform.matrix();
|
|
for (int i = 0; i < 4; ++i)
|
|
for (int j = 0; j < 4; ++j)
|
|
view(i, j) = matrix(i, j);
|
|
return py::object(std::move(array));
|
|
});
|
|
}
|
|
|
|
} // namespace Slic3r
|