Fix bugs and non working tests
Fix failing tests Try to fix build on windows Try to fix failng tests on Mac
This commit is contained in:
parent
184f64f828
commit
301a168b89
7 changed files with 132 additions and 181 deletions
|
@ -1,3 +1,5 @@
|
|||
#define NOMINMAX
|
||||
|
||||
#include <libslic3r/SLA/SupportTreeBuilder.hpp>
|
||||
#include <libslic3r/SLA/SupportTreeBuildsteps.hpp>
|
||||
#include <libslic3r/SLA/SupportTreeMesher.hpp>
|
||||
|
@ -19,77 +21,8 @@ Head::Head(double r_big_mm,
|
|||
, width_mm(length_mm)
|
||||
, penetration_mm(penetration)
|
||||
{
|
||||
// mesh = pinhead(r_pin_mm, r_back_mm, width_mm, steps);
|
||||
|
||||
// To simplify further processing, we translate the mesh so that the
|
||||
// last vertex of the pointing sphere (the pinpoint) will be at (0,0,0)
|
||||
// for(auto& p : mesh.points) p.z() -= (fullwidth() - r_back_mm);
|
||||
}
|
||||
|
||||
//Pillar::Pillar(const Vec3d &endp, double h, double radius, size_t st):
|
||||
// height{h}, r(radius), steps(st), endpt(endp), starts_from_head(false)
|
||||
//{
|
||||
// assert(steps > 0);
|
||||
|
||||
// if(height > EPSILON) { // Endpoint is below the starting point
|
||||
|
||||
// // We just create a bridge geometry with the pillar parameters and
|
||||
// // move the data.
|
||||
// Contour3D body = cylinder(radius, height, st, endp);
|
||||
// mesh.points.swap(body.points);
|
||||
// mesh.faces3.swap(body.faces3);
|
||||
// }
|
||||
//}
|
||||
|
||||
//Pillar &Pillar::add_base(double baseheight, double radius)
|
||||
//{
|
||||
// if(baseheight <= 0) return *this;
|
||||
// if(baseheight > height) baseheight = height;
|
||||
|
||||
// assert(steps >= 0);
|
||||
// auto last = int(steps - 1);
|
||||
|
||||
// if(radius < r ) radius = r;
|
||||
|
||||
// double a = 2*PI/steps;
|
||||
// double z = endpt(Z) + baseheight;
|
||||
|
||||
// for(size_t i = 0; i < steps; ++i) {
|
||||
// double phi = i*a;
|
||||
// double x = endpt(X) + r*std::cos(phi);
|
||||
// double y = endpt(Y) + r*std::sin(phi);
|
||||
// base.points.emplace_back(x, y, z);
|
||||
// }
|
||||
|
||||
// for(size_t i = 0; i < steps; ++i) {
|
||||
// double phi = i*a;
|
||||
// double x = endpt(X) + radius*std::cos(phi);
|
||||
// double y = endpt(Y) + radius*std::sin(phi);
|
||||
// base.points.emplace_back(x, y, z - baseheight);
|
||||
// }
|
||||
|
||||
// auto ep = endpt; ep(Z) += baseheight;
|
||||
// base.points.emplace_back(endpt);
|
||||
// base.points.emplace_back(ep);
|
||||
|
||||
// auto& indices = base.faces3;
|
||||
// auto hcenter = int(base.points.size() - 1);
|
||||
// auto lcenter = int(base.points.size() - 2);
|
||||
// auto offs = int(steps);
|
||||
// for(int i = 0; i < last; ++i) {
|
||||
// indices.emplace_back(i, i + offs, offs + i + 1);
|
||||
// indices.emplace_back(i, offs + i + 1, i + 1);
|
||||
// indices.emplace_back(i, i + 1, hcenter);
|
||||
// indices.emplace_back(lcenter, offs + i + 1, offs + i);
|
||||
// }
|
||||
|
||||
// indices.emplace_back(0, last, offs);
|
||||
// indices.emplace_back(last, offs + last, offs);
|
||||
// indices.emplace_back(hcenter, last, 0);
|
||||
// indices.emplace_back(offs, offs + last, lcenter);
|
||||
// return *this;
|
||||
//}
|
||||
|
||||
Pad::Pad(const TriangleMesh &support_mesh,
|
||||
const ExPolygons & model_contours,
|
||||
double ground_level,
|
||||
|
@ -175,6 +108,18 @@ SupportTreeBuilder &SupportTreeBuilder::operator=(const SupportTreeBuilder &o)
|
|||
return *this;
|
||||
}
|
||||
|
||||
void SupportTreeBuilder::add_pillar_base(long pid, double baseheight, double radius)
|
||||
{
|
||||
std::lock_guard<Mutex> lk(m_mutex);
|
||||
assert(pid >= 0 && size_t(pid) < m_pillars.size());
|
||||
Pillar& pll = m_pillars[size_t(pid)];
|
||||
m_pedestals.emplace_back(pll.endpt, std::min(baseheight, pll.height),
|
||||
std::max(radius, pll.r), pll.r);
|
||||
|
||||
m_pedestals.back().id = m_pedestals.size() - 1;
|
||||
m_meshcache_valid = false;
|
||||
}
|
||||
|
||||
const TriangleMesh &SupportTreeBuilder::merged_mesh(size_t steps) const
|
||||
{
|
||||
if (m_meshcache_valid) return m_meshcache;
|
||||
|
@ -192,6 +137,7 @@ const TriangleMesh &SupportTreeBuilder::merged_mesh(size_t steps) const
|
|||
}
|
||||
|
||||
for (auto &pedest : m_pedestals) {
|
||||
if (ctl().stopcondition()) break;
|
||||
merged.merge(get_mesh(pedest, steps));
|
||||
}
|
||||
|
||||
|
@ -209,7 +155,12 @@ const TriangleMesh &SupportTreeBuilder::merged_mesh(size_t steps) const
|
|||
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));
|
||||
}
|
||||
|
||||
if (ctl().stopcondition()) {
|
||||
// In case of failure we have to return an empty mesh
|
||||
m_meshcache = TriangleMesh();
|
||||
|
|
|
@ -91,12 +91,7 @@ struct Head {
|
|||
const Vec3d &direction = DOWN, // direction (normal to the dull end)
|
||||
const Vec3d &offset = {0, 0, 0} // displacement
|
||||
);
|
||||
|
||||
void transform()
|
||||
{
|
||||
// TODO: remove occurences
|
||||
}
|
||||
|
||||
|
||||
inline double real_width() const
|
||||
{
|
||||
return 2 * r_pin_mm + width_mm + 2 * r_back_mm ;
|
||||
|
@ -119,13 +114,6 @@ struct Head {
|
|||
}
|
||||
};
|
||||
|
||||
struct Join {
|
||||
enum Types {
|
||||
jtPillarBrigde, jtHeadPillar, jtPillarPedestal, jtBridgePedestal,
|
||||
jtPillarAnchor, jtBridgeAnchor
|
||||
};
|
||||
};
|
||||
|
||||
// A junction connecting bridges and pillars
|
||||
struct Junction {
|
||||
double r = 1;
|
||||
|
@ -136,7 +124,6 @@ struct Junction {
|
|||
Junction(const Vec3d &tr, double r_mm) : r(r_mm), pos(tr) {}
|
||||
};
|
||||
|
||||
|
||||
struct Pillar {
|
||||
double height, r;
|
||||
Vec3d endpt;
|
||||
|
@ -162,18 +149,16 @@ struct Pillar {
|
|||
}
|
||||
|
||||
const Vec3d& endpoint() const { return endpt; }
|
||||
|
||||
// Pillar& add_base(double baseheight = 3, double radius = 2);
|
||||
};
|
||||
|
||||
// A base for pillars or bridges that end on the ground
|
||||
struct Pedestal {
|
||||
Vec3d pos;
|
||||
double height, radius;
|
||||
double height, r_bottom, r_top;
|
||||
long id = ID_UNSET;
|
||||
|
||||
Pedestal(const Vec3d &p, double h = 3., double r = 2.)
|
||||
: pos{p}, height{h}, radius{r}
|
||||
Pedestal(const Vec3d &p, double h, double rbottom, double rtop)
|
||||
: pos{p}, height{h}, r_bottom{rbottom}, r_top{rtop}
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -301,15 +286,7 @@ public:
|
|||
return pillar.id;
|
||||
}
|
||||
|
||||
void add_pillar_base(long pid, double baseheight = 3, double radius = 2)
|
||||
{
|
||||
std::lock_guard<Mutex> lk(m_mutex);
|
||||
assert(pid >= 0 && size_t(pid) < m_pillars.size());
|
||||
m_pedestals.emplace_back(m_pillars[size_t(pid)].endpt, baseheight, radius);
|
||||
m_pedestals.back().id = m_pedestals.size() - 1;
|
||||
m_meshcache_valid = false;
|
||||
// m_pillars[size_t(pid)].add_base(baseheight, radius);
|
||||
}
|
||||
void add_pillar_base(long pid, double baseheight = 3, double radius = 2);
|
||||
|
||||
template<class...Args> const Anchor& add_anchor(Args&&...args)
|
||||
{
|
||||
|
|
|
@ -580,7 +580,7 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &jp,
|
|||
bool normal_mode = true;
|
||||
Vec3d dir = sourcedir;
|
||||
|
||||
auto to_floor = [gndlvl](const Vec3d &p) { return Vec3d{p.x(), p.y(), gndlvl}; };
|
||||
auto to_floor = [&gndlvl](const Vec3d &p) { return Vec3d{p.x(), p.y(), gndlvl}; };
|
||||
|
||||
if (m_cfg.object_elevation_mm < EPSILON)
|
||||
{
|
||||
|
@ -599,6 +599,7 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &jp,
|
|||
// Try to move along the established bridge direction to dodge the
|
||||
// forbidden region for the endpoint.
|
||||
double t = -radius;
|
||||
bool succ = true;
|
||||
while (std::sqrt(m_mesh.squared_distance(to_floor(endp))) < min_dist ||
|
||||
!std::isinf(bridge_mesh_distance(endp, DOWN, radius))) {
|
||||
t += radius;
|
||||
|
@ -607,36 +608,58 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &jp,
|
|||
|
||||
if (t > m_cfg.max_bridge_length_mm || endp(Z) < gndlvl) {
|
||||
if (head_id >= 0) m_builder.add_pillar(head_id, 0.);
|
||||
return false;
|
||||
succ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succ) {
|
||||
if (can_add_base) {
|
||||
can_add_base = false;
|
||||
base_r = 0.;
|
||||
gndlvl -= m_mesh.ground_level_offset();
|
||||
min_dist = sd + base_r + EPSILON;
|
||||
endp = {jp(X), jp(Y), gndlvl + radius};
|
||||
|
||||
t = -radius;
|
||||
while (std::sqrt(m_mesh.squared_distance(to_floor(endp))) < min_dist ||
|
||||
!std::isinf(bridge_mesh_distance(endp, DOWN, radius))) {
|
||||
t += radius;
|
||||
endp = jp + t * dir;
|
||||
normal_mode = false;
|
||||
|
||||
if (t > m_cfg.max_bridge_length_mm || endp(Z) < (gndlvl + radius)) {
|
||||
if (head_id >= 0) m_builder.add_pillar(head_id, 0.);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else return false;
|
||||
}
|
||||
}
|
||||
|
||||
double h = (jp - endp).norm();
|
||||
|
||||
// Check if the deduced route is sane and exit with error if not.
|
||||
if (bridge_mesh_distance(jp, dir, radius) < (endp - jp).norm()) {
|
||||
if (bridge_mesh_distance(jp, dir, radius) < h) {
|
||||
if (head_id >= 0) m_builder.add_pillar(head_id, 0.);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Straigh path down, no area to dodge
|
||||
if (normal_mode) {
|
||||
double h = jp.z() - endp.z();
|
||||
pillar_id = head_id >= 0 ? m_builder.add_pillar(head_id, h) :
|
||||
m_builder.add_pillar(jp, h, radius);
|
||||
m_builder.add_pillar(endp, h, radius);
|
||||
|
||||
if (can_add_base)
|
||||
m_builder.add_pillar_base(pillar_id, m_cfg.base_height_mm,
|
||||
m_cfg.base_radius_mm);
|
||||
add_pillar_base(pillar_id);
|
||||
} else {
|
||||
|
||||
// Insert the bridge to get around the forbidden area
|
||||
// Vec3d pgnd{endp.x(), endp.y(), gndlvl};
|
||||
double h = endp.z() - gndlvl;
|
||||
pillar_id = m_builder.add_pillar(endp, h, radius);
|
||||
Vec3d pgnd{endp.x(), endp.y(), gndlvl};
|
||||
pillar_id = m_builder.add_pillar(pgnd, endp.z() - gndlvl, radius);
|
||||
|
||||
if (can_add_base)
|
||||
m_builder.add_pillar_base(pillar_id, m_cfg.base_height_mm,
|
||||
m_cfg.base_radius_mm);
|
||||
add_pillar_base(pillar_id);
|
||||
|
||||
m_builder.add_bridge(jp, endp, radius);
|
||||
m_builder.add_junction(endp, radius);
|
||||
|
@ -912,11 +935,8 @@ void SupportTreeBuildsteps::routing_to_ground()
|
|||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< "Pillar cannot be created for support point id: " << hid;
|
||||
m_iheads_onmodel.emplace_back(h.id);
|
||||
// h.invalidate();
|
||||
continue;
|
||||
}
|
||||
|
||||
h.transform();
|
||||
}
|
||||
|
||||
// now we will go through the clusters ones again and connect the
|
||||
|
@ -939,7 +959,6 @@ void SupportTreeBuildsteps::routing_to_ground()
|
|||
if (c == cidx) continue;
|
||||
|
||||
auto &sidehead = m_builder.head(c);
|
||||
sidehead.transform();
|
||||
|
||||
if (!connect_to_nearpillar(sidehead, centerpillarID) &&
|
||||
!search_pillar_and_connect(sidehead)) {
|
||||
|
@ -1016,6 +1035,12 @@ bool SupportTreeBuildsteps::connect_to_model_body(Head &head)
|
|||
if (it == m_head_to_ground_scans.end()) return false;
|
||||
|
||||
auto &hit = it->second;
|
||||
|
||||
if (!hit.is_hit()) {
|
||||
// TODO scan for potential anchor points on model surface
|
||||
return false;
|
||||
}
|
||||
|
||||
Vec3d hjp = head.junction_point();
|
||||
double zangle = std::asin(hit.direction()(Z));
|
||||
zangle = std::max(zangle, PI/4);
|
||||
|
@ -1033,13 +1058,11 @@ bool SupportTreeBuildsteps::connect_to_model_body(Head &head)
|
|||
Vec3d hitp = std::abs(hitdiff) < 2*head.r_back_mm?
|
||||
center_hit.position() : hit.position();
|
||||
|
||||
head.transform();
|
||||
|
||||
long pillar_id = m_builder.add_pillar(head.id, hit.distance() + h);
|
||||
long pillar_id = m_builder.add_pillar(head.id, hjp.z() - endp.z());
|
||||
Pillar &pill = m_builder.pillar(pillar_id);
|
||||
|
||||
Vec3d taildir = endp - hitp;
|
||||
double dist = distance(endp, hitp) + m_cfg.head_penetration_mm;
|
||||
double dist = (hitp - endp).norm() + m_cfg.head_penetration_mm;
|
||||
double w = dist - 2 * head.r_pin_mm - head.r_back_mm;
|
||||
|
||||
if (w < 0.) {
|
||||
|
@ -1050,12 +1073,6 @@ bool SupportTreeBuildsteps::connect_to_model_body(Head &head)
|
|||
m_builder.add_anchor(head.r_back_mm, head.r_pin_mm, w,
|
||||
m_cfg.head_penetration_mm, taildir, hitp);
|
||||
|
||||
// Head tailhead(head.r_back_mm, head.r_pin_mm, w,
|
||||
// m_cfg.head_penetration_mm, taildir, hitp);
|
||||
|
||||
// tailhead.transform();
|
||||
// pill.base = tailhead.mesh;
|
||||
|
||||
m_pillar_index.guarded_insert(pill.endpoint(), pill.id);
|
||||
|
||||
return true;
|
||||
|
@ -1111,11 +1128,11 @@ void SupportTreeBuildsteps::routing_to_model()
|
|||
auto& head = m_builder.head(idx);
|
||||
|
||||
// Search nearby pillar
|
||||
if (search_pillar_and_connect(head)) { head.transform(); return; }
|
||||
if (search_pillar_and_connect(head)) { return; }
|
||||
|
||||
// Cannot connect to nearby pillar. We will try to search for
|
||||
// a route to the ground.
|
||||
if (connect_to_ground(head)) { head.transform(); return; }
|
||||
if (connect_to_ground(head)) { return; }
|
||||
|
||||
// No route to the ground, so connect to the model body as a last resort
|
||||
if (connect_to_model_body(head)) { return; }
|
||||
|
@ -1300,12 +1317,14 @@ void SupportTreeBuildsteps::interconnect_pillars()
|
|||
|
||||
if (found)
|
||||
for (unsigned n = 0; n < needpillars; n++) {
|
||||
Vec3d s = spts[n];
|
||||
Pillar p(s, s.z() - gnd, pillar().r);
|
||||
// p.add_base(m_cfg.base_height_mm, m_cfg.base_radius_mm);
|
||||
Vec3d s = spts[n];
|
||||
Pillar p(Vec3d{s.x(), s.y(), gnd}, s.z() - gnd, pillar().r);
|
||||
|
||||
if (interconnect(pillar(), p)) {
|
||||
Pillar &pp = m_builder.pillar(m_builder.add_pillar(p));
|
||||
|
||||
add_pillar_base(pp.id);
|
||||
|
||||
m_pillar_index.insert(pp.endpoint(), unsigned(pp.id));
|
||||
|
||||
m_builder.add_junction(s, pillar().r);
|
||||
|
|
|
@ -17,9 +17,7 @@ enum { // For indexing Eigen vectors as v(X), v(Y), v(Z) instead of numbers
|
|||
X, Y, Z
|
||||
};
|
||||
|
||||
inline Vec2d to_vec2(const Vec3d& v3) {
|
||||
return {v3(X), v3(Y)};
|
||||
}
|
||||
inline Vec2d to_vec2(const Vec3d &v3) { return {v3(X), v3(Y)}; }
|
||||
|
||||
inline std::pair<double, double> dir_to_spheric(const Vec3d &n, double norm = 1.)
|
||||
{
|
||||
|
@ -47,7 +45,6 @@ inline Vec3d spheric_to_dir(const std::pair<double, double> &v)
|
|||
return spheric_to_dir(v.first, v.second);
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
|
@ -297,8 +294,12 @@ class SupportTreeBuildsteps {
|
|||
const Vec3d &sourcedir,
|
||||
double radius,
|
||||
long head_id = ID_UNSET);
|
||||
|
||||
|
||||
|
||||
void add_pillar_base(long pid)
|
||||
{
|
||||
m_builder.add_pillar_base(pid, m_cfg.base_height_mm, m_cfg.base_radius_mm);
|
||||
}
|
||||
|
||||
public:
|
||||
SupportTreeBuildsteps(SupportTreeBuilder & builder, const SupportableMesh &sm);
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ Contour3D sphere(double rho, Portion portion, double fa) {
|
|||
|
||||
Contour3D cylinder(double r, double h, size_t ssteps, const Vec3d &sp)
|
||||
{
|
||||
assert(steps > 0);
|
||||
assert(ssteps > 0);
|
||||
|
||||
Contour3D ret;
|
||||
|
||||
|
@ -157,7 +157,7 @@ Contour3D cylinder(double r, double h, size_t ssteps, const Vec3d &sp)
|
|||
Contour3D pinhead(double r_pin, double r_back, double length, size_t steps)
|
||||
{
|
||||
assert(steps > 0);
|
||||
assert(length > 0.);
|
||||
assert(length >= 0.);
|
||||
assert(r_back > 0.);
|
||||
assert(r_pin > 0.);
|
||||
|
||||
|
@ -167,7 +167,7 @@ Contour3D pinhead(double r_pin, double r_back, double length, size_t steps)
|
|||
// both circles perfectly.
|
||||
|
||||
// Set up the model detail level
|
||||
const double detail = 2*PI/steps;
|
||||
const double detail = 2 * PI / steps;
|
||||
|
||||
// We don't generate whole circles. Instead, we generate only the
|
||||
// portions which are visible (not covered by the robe) To know the
|
||||
|
@ -176,26 +176,24 @@ Contour3D pinhead(double r_pin, double r_back, double length, size_t steps)
|
|||
// triangles the following relations:
|
||||
|
||||
// The height of the whole mesh
|
||||
const double h = r_back + r_pin + length;
|
||||
double phi = PI / 2. - std::acos((r_back - r_pin) / h);
|
||||
const double h = r_back + r_pin + length;
|
||||
double phi = PI / 2. - std::acos((r_back - r_pin) / h);
|
||||
|
||||
// To generate a whole circle we would pass a portion of (0, Pi)
|
||||
// To generate only a half horizontal circle we can pass (0, Pi/2)
|
||||
// The calculated phi is an offset to the half circles needed to smooth
|
||||
// the transition from the circle to the robe geometry
|
||||
|
||||
auto&& s1 = sphere(r_back, make_portion(0, PI/2 + phi), detail);
|
||||
auto&& s2 = sphere(r_pin, make_portion(PI/2 + phi, PI), detail);
|
||||
auto &&s1 = sphere(r_back, make_portion(0, PI / 2 + phi), detail);
|
||||
auto &&s2 = sphere(r_pin, make_portion(PI / 2 + phi, PI), detail);
|
||||
|
||||
for(auto& p : s2.points) p.z() += h;
|
||||
for (auto &p : s2.points) p.z() += h;
|
||||
|
||||
mesh.merge(s1);
|
||||
mesh.merge(s2);
|
||||
|
||||
for(size_t idx1 = s1.points.size() - steps, idx2 = s1.points.size();
|
||||
idx1 < s1.points.size() - 1;
|
||||
idx1++, idx2++)
|
||||
{
|
||||
for (size_t idx1 = s1.points.size() - steps, idx2 = s1.points.size();
|
||||
idx1 < s1.points.size() - 1; idx1++, idx2++) {
|
||||
coord_t i1s1 = coord_t(idx1), i1s2 = coord_t(idx2);
|
||||
coord_t i2s1 = i1s1 + 1, i2s2 = i1s2 + 1;
|
||||
|
||||
|
@ -214,43 +212,43 @@ Contour3D pinhead(double r_pin, double r_back, double length, size_t steps)
|
|||
return mesh;
|
||||
}
|
||||
|
||||
Contour3D pedestal(const Vec3d &endpt, double baseheight, double radius, size_t steps)
|
||||
Contour3D halfcone(double baseheight,
|
||||
double r_bottom,
|
||||
double r_top,
|
||||
const Vec3d &pos,
|
||||
size_t steps)
|
||||
{
|
||||
assert(steps > 0);
|
||||
|
||||
if(baseheight <= 0) return {};
|
||||
|
||||
assert(steps >= 0);
|
||||
auto last = int(steps - 1);
|
||||
if (baseheight <= 0 || steps <= 0) return {};
|
||||
|
||||
Contour3D base;
|
||||
|
||||
double a = 2*PI/steps;
|
||||
double z = endpt(Z) + baseheight;
|
||||
|
||||
for(size_t i = 0; i < steps; ++i) {
|
||||
double phi = i*a;
|
||||
double x = endpt(X) + radius * std::cos(phi);
|
||||
double y = endpt(Y) + radius * std::sin(phi);
|
||||
base.points.emplace_back(x, y, z);
|
||||
double a = 2 * PI / steps;
|
||||
auto last = int(steps - 1);
|
||||
Vec3d ep{pos.x(), pos.y(), pos.z() + baseheight};
|
||||
for (size_t i = 0; i < steps; ++i) {
|
||||
double phi = i * a;
|
||||
double x = pos.x() + r_top * std::cos(phi);
|
||||
double y = pos.y() + r_top * std::sin(phi);
|
||||
base.points.emplace_back(x, y, ep.z());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < steps; ++i) {
|
||||
double phi = i*a;
|
||||
double x = endpt(X) + radius*std::cos(phi);
|
||||
double y = endpt(Y) + radius*std::sin(phi);
|
||||
base.points.emplace_back(x, y, z - baseheight);
|
||||
for (size_t i = 0; i < steps; ++i) {
|
||||
double phi = i * a;
|
||||
double x = pos.x() + r_bottom * std::cos(phi);
|
||||
double y = pos.y() + r_bottom * std::sin(phi);
|
||||
base.points.emplace_back(x, y, pos.z());
|
||||
}
|
||||
|
||||
auto ep = endpt; ep(Z) += baseheight;
|
||||
base.points.emplace_back(endpt);
|
||||
base.points.emplace_back(pos);
|
||||
base.points.emplace_back(ep);
|
||||
|
||||
auto& indices = base.faces3;
|
||||
auto hcenter = int(base.points.size() - 1);
|
||||
auto lcenter = int(base.points.size() - 2);
|
||||
auto offs = int(steps);
|
||||
for(int i = 0; i < last; ++i) {
|
||||
auto &indices = base.faces3;
|
||||
auto hcenter = int(base.points.size() - 1);
|
||||
auto lcenter = int(base.points.size() - 2);
|
||||
auto offs = int(steps);
|
||||
for (int i = 0; i < last; ++i) {
|
||||
indices.emplace_back(i, i + offs, offs + i + 1);
|
||||
indices.emplace_back(i, offs + i + 1, i + 1);
|
||||
indices.emplace_back(i, i + 1, hcenter);
|
||||
|
|
|
@ -24,23 +24,28 @@ Contour3D sphere(double rho,
|
|||
// h: Height
|
||||
// ssteps: how many edges will create the base circle
|
||||
// sp: starting point
|
||||
Contour3D cylinder(double r, double h, size_t steps = 45, const Vec3d &sp = Vec3d::Zero());
|
||||
Contour3D cylinder(double r,
|
||||
double h,
|
||||
size_t steps = 45,
|
||||
const Vec3d &sp = Vec3d::Zero());
|
||||
|
||||
Contour3D pinhead(double r_pin, double r_back, double length, size_t steps = 45);
|
||||
|
||||
Contour3D pedestal(const Vec3d &pt, double baseheight, double radius, size_t steps = 45);
|
||||
Contour3D halfcone(double baseheight,
|
||||
double r_bottom,
|
||||
double r_top,
|
||||
const Vec3d &pt = Vec3d::Zero(),
|
||||
size_t steps = 45);
|
||||
|
||||
inline Contour3D get_mesh(const Head &h, size_t steps)
|
||||
{
|
||||
Contour3D mesh = pinhead(h.r_pin_mm, h.r_back_mm, h.width_mm, steps);
|
||||
|
||||
// To simplify further processing, we translate the mesh so that the
|
||||
// last vertex of the pointing sphere (the pinpoint) will be at (0,0,0)
|
||||
for(auto& p : mesh.points) p.z() -= (h.fullwidth() - h.r_back_mm);
|
||||
|
||||
using Quaternion = Eigen::Quaternion<double>;
|
||||
|
||||
// We rotate the head to the specified direction The head's pointing
|
||||
// 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
|
||||
|
@ -64,7 +69,7 @@ inline Contour3D get_mesh(const Pillar &p, size_t steps)
|
|||
|
||||
inline Contour3D get_mesh(const Pedestal &p, size_t steps)
|
||||
{
|
||||
return pedestal(p.pos, p.height, p.radius, steps);
|
||||
return halfcone(p.height, p.r_bottom, p.r_top, p.pos, steps);
|
||||
}
|
||||
|
||||
inline Contour3D get_mesh(const Junction &j, size_t steps)
|
||||
|
@ -89,6 +94,6 @@ inline Contour3D get_mesh(const Bridge &br, size_t steps)
|
|||
return mesh;
|
||||
}
|
||||
|
||||
}}
|
||||
}} // namespace Slic3r::sla
|
||||
|
||||
#endif // SUPPORTTREEMESHER_HPP
|
||||
|
|
|
@ -157,8 +157,8 @@ void test_supports(const std::string &obj_filename,
|
|||
if (std::abs(supportcfg.object_elevation_mm) < EPSILON)
|
||||
allowed_zmin = zmin - 2 * supportcfg.head_back_radius_mm;
|
||||
|
||||
REQUIRE(obb.min.z() >= allowed_zmin);
|
||||
REQUIRE(obb.max.z() <= zmax);
|
||||
REQUIRE(obb.min.z() >= Approx(allowed_zmin));
|
||||
REQUIRE(obb.max.z() <= Approx(zmax));
|
||||
|
||||
// Move out the support tree into the byproducts, we can examine it further
|
||||
// in various tests.
|
||||
|
|
Loading…
Reference in a new issue