|
|
|
|
@@ -188,7 +188,7 @@ static inline BuildVolume::ObjectState rectangle_test(const indexed_triangle_set
|
|
|
|
|
// Trim the input transformed triangle mesh with print bed and test the remaining vertices with is_inside callback.
|
|
|
|
|
// Return inside / colliding / outside state.
|
|
|
|
|
template<typename InsideFn>
|
|
|
|
|
BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed, InsideFn is_inside)
|
|
|
|
|
BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed, bool convex, InsideFn is_inside)
|
|
|
|
|
{
|
|
|
|
|
size_t num_inside = 0;
|
|
|
|
|
size_t num_above = 0;
|
|
|
|
|
@@ -205,8 +205,10 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
|
|
|
|
|
|
|
|
|
|
const auto sign = [](const stl_vertex& pt) { return pt.z() > world_min_z ? 1 : pt.z() < world_min_z ? -1 : 0; };
|
|
|
|
|
|
|
|
|
|
bool below_outside = false;
|
|
|
|
|
|
|
|
|
|
for (const stl_vertex &v : its.vertices) {
|
|
|
|
|
const stl_vertex pt = trafo * v;
|
|
|
|
|
stl_vertex pt = trafo * v;
|
|
|
|
|
const int s = sign(pt);
|
|
|
|
|
sides.emplace_back(s);
|
|
|
|
|
if (s >= 0) {
|
|
|
|
|
@@ -214,6 +216,10 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
|
|
|
|
|
++ num_above;
|
|
|
|
|
if (is_inside(pt))
|
|
|
|
|
++ num_inside;
|
|
|
|
|
} else if (convex && !below_outside) {
|
|
|
|
|
pt.z() = 0;
|
|
|
|
|
if (!is_inside(pt))
|
|
|
|
|
below_outside = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -225,7 +231,8 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con
|
|
|
|
|
// 2) Calculate intersections of triangle edges with the build surface.
|
|
|
|
|
inside = num_inside > 0;
|
|
|
|
|
outside = num_inside < num_above;
|
|
|
|
|
if (num_above < its.vertices.size() && ! (inside && outside)) {
|
|
|
|
|
// Orca: for convex shape, if everything inside then don't bother check intersection
|
|
|
|
|
if (num_above < its.vertices.size() && !(inside && outside) && (!(inside && !below_outside) || !convex)) {
|
|
|
|
|
// Not completely above the build surface and status may still change by testing edges intersecting the build platform.
|
|
|
|
|
for (const stl_triangle_vertex_indices &tri : its.indices) {
|
|
|
|
|
const int s[3] = { sides[tri(0)], sides[tri(1)], sides[tri(2)] };
|
|
|
|
|
@@ -284,21 +291,21 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i
|
|
|
|
|
// The following test correctly interprets intersection of a non-convex object with a rectangular build volume.
|
|
|
|
|
//return rectangle_test(its, trafo, to_2d(build_volume.min), to_2d(build_volume.max), build_volume.max.z());
|
|
|
|
|
//FIXME This test does NOT correctly interprets intersection of a non-convex object with a rectangular build volume.
|
|
|
|
|
return object_state_templ(its, trafo, may_be_below_bed, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); });
|
|
|
|
|
return object_state_templ(its, trafo, may_be_below_bed, true, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); });
|
|
|
|
|
}
|
|
|
|
|
case BuildVolume_Type::Circle:
|
|
|
|
|
{
|
|
|
|
|
Geometry::Circlef circle { unscaled<float>(m_circle.center), unscaled<float>(m_circle.radius + SceneEpsilon) };
|
|
|
|
|
return m_max_print_height == 0.0 ?
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, [circle](const Vec3f &pt) { return circle.contains(to_2d(pt)); }) :
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); });
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, true, [circle](const Vec3f& pt) { return circle.contains(to_2d(pt)); }) :
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, true, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); });
|
|
|
|
|
}
|
|
|
|
|
case BuildVolume_Type::Convex:
|
|
|
|
|
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
|
|
|
|
|
case BuildVolume_Type::Custom:
|
|
|
|
|
return m_max_print_height == 0.0 ?
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); }) :
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); });
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); }) :
|
|
|
|
|
object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast<double>()); });
|
|
|
|
|
case BuildVolume_Type::Invalid:
|
|
|
|
|
default:
|
|
|
|
|
return ObjectState::Inside;
|
|
|
|
|
|