Working small-to-normal support merging

Fixed fatal bug with anchors for mini supports

Make the optimization cleaner in support generatior

Much better widening behaviour

Add an optimizer interface and the NLopt implementation into libslic3r

New optimizer based only on nlopt C interfase
Fix build and tests
This commit is contained in:
tamasmeszaros 2020-07-16 11:49:30 +02:00
parent 8cb115a035
commit 927b81ea97
9 changed files with 831 additions and 395 deletions

View file

@ -87,7 +87,7 @@ public:
inline Vec3d position() const { return m_source + m_dir * m_t; }
inline int face() const { return m_face_id; }
inline bool is_valid() const { return m_mesh != nullptr; }
inline bool is_hit() const { return !std::isinf(m_t); }
inline bool is_hit() const { return m_face_id >= 0 && !std::isinf(m_t); }
inline const Vec3d& normal() const {
assert(is_valid());

View file

@ -156,6 +156,11 @@ const TriangleMesh &SupportTreeBuilder::merged_mesh(size_t steps) const
merged.merge(get_mesh(bs, steps));
}
for (auto &bs : m_diffbridges) {
if (ctl().stopcondition()) break;
merged.merge(get_mesh(bs, steps));
}
for (auto &anch : m_anchors) {
if (ctl().stopcondition()) break;
merged.merge(get_mesh(anch, steps));

View file

@ -177,6 +177,14 @@ struct Bridge: public SupportTreeNode {
Vec3d get_dir() const { return (endp - startp).normalized(); }
};
struct DiffBridge: public Bridge {
double end_r;
DiffBridge(const Vec3d &p_s, const Vec3d &p_e, double r_s, double r_e)
: Bridge{p_s, p_e, r_s}, end_r{r_e}
{}
};
// A wrapper struct around the pad
struct Pad {
TriangleMesh tmesh;
@ -210,14 +218,15 @@ struct Pad {
// merged mesh. It can be retrieved using a dedicated method (pad())
class SupportTreeBuilder: public SupportTree {
// For heads it is beneficial to use the same IDs as for the support points.
std::vector<Head> m_heads;
std::vector<size_t> m_head_indices;
std::vector<Pillar> m_pillars;
std::vector<Junction> m_junctions;
std::vector<Bridge> m_bridges;
std::vector<Bridge> m_crossbridges;
std::vector<Pedestal> m_pedestals;
std::vector<Anchor> m_anchors;
std::vector<Head> m_heads;
std::vector<size_t> m_head_indices;
std::vector<Pillar> m_pillars;
std::vector<Junction> m_junctions;
std::vector<Bridge> m_bridges;
std::vector<Bridge> m_crossbridges;
std::vector<DiffBridge> m_diffbridges;
std::vector<Pedestal> m_pedestals;
std::vector<Anchor> m_anchors;
Pad m_pad;
@ -228,8 +237,8 @@ class SupportTreeBuilder: public SupportTree {
mutable bool m_meshcache_valid = false;
mutable double m_model_height = 0; // the full height of the model
template<class...Args>
const Bridge& _add_bridge(std::vector<Bridge> &br, Args&&... args)
template<class BridgeT, class...Args>
const BridgeT& _add_bridge(std::vector<BridgeT> &br, Args&&... args)
{
std::lock_guard<Mutex> lk(m_mutex);
br.emplace_back(std::forward<Args>(args)...);
@ -331,17 +340,6 @@ public:
return pillar.id;
}
const Pillar& head_pillar(unsigned headid) const
{
std::lock_guard<Mutex> lk(m_mutex);
assert(headid < m_head_indices.size());
const Head& h = m_heads[m_head_indices[headid]];
assert(h.pillar_id >= 0 && h.pillar_id < long(m_pillars.size()));
return m_pillars[size_t(h.pillar_id)];
}
template<class...Args> const Junction& add_junction(Args&&... args)
{
std::lock_guard<Mutex> lk(m_mutex);
@ -374,6 +372,11 @@ public:
{
return _add_bridge(m_crossbridges, std::forward<Args>(args)...);
}
template<class...Args> const DiffBridge& add_diffbridge(Args&&... args)
{
return _add_bridge(m_diffbridges, std::forward<Args>(args)...);
}
Head &head(unsigned id)
{

File diff suppressed because it is too large Load diff

View file

@ -45,6 +45,11 @@ inline Vec3d spheric_to_dir(const std::pair<double, double> &v)
return spheric_to_dir(v.first, v.second);
}
inline Vec3d spheric_to_dir(const std::array<double, 2> &v)
{
return spheric_to_dir(v[0], v[1]);
}
// Give points on a 3D ring with given center, radius and orientation
// method based on:
// https://math.stackexchange.com/questions/73237/parametric-equation-of-a-circle-in-3d-space
@ -249,7 +254,8 @@ class SupportTreeBuildsteps {
double width)
{
return pinhead_mesh_intersect(s, dir, r_pin, r_back, width,
m_cfg.safety_distance_mm);
r_back * m_cfg.safety_distance_mm /
m_cfg.head_back_radius_mm);
}
// Checking bridge (pillar and stick as well) intersection with the model.
@ -271,7 +277,9 @@ class SupportTreeBuildsteps {
const Vec3d& dir,
double r)
{
return bridge_mesh_intersect(s, dir, r, m_cfg.safety_distance_mm);
return bridge_mesh_intersect(s, dir, r,
r * m_cfg.safety_distance_mm /
m_cfg.head_back_radius_mm);
}
template<class...Args>
@ -311,6 +319,11 @@ class SupportTreeBuildsteps {
m_builder.add_pillar_base(pid, m_cfg.base_height_mm, m_cfg.base_radius_mm);
}
std::optional<DiffBridge> search_widening_path(const Vec3d &jp,
const Vec3d &dir,
double radius,
double new_radius);
public:
SupportTreeBuildsteps(SupportTreeBuilder & builder, const SupportableMesh &sm);

View file

@ -94,6 +94,24 @@ inline Contour3D get_mesh(const Bridge &br, size_t steps)
return mesh;
}
inline Contour3D get_mesh(const DiffBridge &br, size_t steps)
{
double h = br.get_length();
Contour3D mesh = halfcone(h, br.r, br.end_r, Vec3d::Zero(), steps);
using Quaternion = Eigen::Quaternion<double>;
// We rotate the head to the specified direction. The head's pointing
// side is facing upwards so this means that it would hold a support
// point with a normal pointing straight down. This is the reason of
// the -1 z coordinate
auto quatern = Quaternion::FromTwoVectors(Vec3d{0, 0, 1}, br.get_dir());
for(auto& p : mesh.points) p = quatern * p + br.startp;
return mesh;
}
}} // namespace Slic3r::sla
#endif // SUPPORTTREEMESHER_HPP