This commit is contained in:
bubnikv 2018-12-17 18:04:37 +01:00
commit 9463351abd
32 changed files with 3358 additions and 342 deletions

View file

@ -1,6 +1,7 @@
#ifndef slic3r_Channel_hpp_
#define slic3r_Channel_hpp_
#include <memory>
#include <deque>
#include <condition_variable>
#include <mutex>
@ -13,32 +14,26 @@ namespace Slic3r {
template<class T> class Channel
{
private:
using UniqueLock = std::unique_lock<std::mutex>;
using Queue = std::deque<T>;
public:
class Guard
using UniqueLock = std::unique_lock<std::mutex>;
template<class Ptr> class Unlocker
{
public:
Guard(UniqueLock lock, const Queue &queue) : m_lock(std::move(lock)), m_queue(queue) {}
Guard(const Guard &other) = delete;
Guard(Guard &&other) = delete;
~Guard() {}
Unlocker(UniqueLock lock) : m_lock(std::move(lock)) {}
Unlocker(const Unlocker &other) noexcept : m_lock(std::move(other.m_lock)) {} // XXX: done beacuse of MSVC 2013 not supporting init of deleter by move
Unlocker(Unlocker &&other) noexcept : m_lock(std::move(other.m_lock)) {}
Unlocker& operator=(const Unlocker &other) = delete;
Unlocker& operator=(Unlocker &&other) { m_lock = std::move(other.m_lock); }
// Access trampolines
size_t size() const noexcept { return m_queue.size(); }
bool empty() const noexcept { return m_queue.empty(); }
typename Queue::const_iterator begin() const noexcept { return m_queue.begin(); }
typename Queue::const_iterator end() const noexcept { return m_queue.end(); }
typename Queue::const_reference operator[](size_t i) const { return m_queue[i]; }
Guard& operator=(const Guard &other) = delete;
Guard& operator=(Guard &&other) = delete;
void operator()(Ptr*) { m_lock.unlock(); }
private:
UniqueLock m_lock;
const Queue &m_queue;
mutable UniqueLock m_lock; // XXX: mutable: see above
};
using Queue = std::deque<T>;
using LockedConstPtr = std::unique_ptr<const Queue, Unlocker<const Queue>>;
using LockedPtr = std::unique_ptr<Queue, Unlocker<Queue>>;
Channel() {}
~Channel() {}
@ -56,7 +51,7 @@ public:
{
{
UniqueLock lock(m_mutex);
m_queue.push_back(std::forward(item));
m_queue.push_back(std::forward<T>(item));
}
if (! silent) { m_condition.notify_one(); }
}
@ -82,19 +77,22 @@ public:
}
}
// Unlocked observers
// Thread unsafe! Keep in mind you need to re-verify the result after acquiring lock!
size_t size() const noexcept { return m_queue.size(); }
bool empty() const noexcept { return m_queue.empty(); }
// Unlocked observers/hints
// Thread unsafe! Keep in mind you need to re-verify the result after locking!
size_t size_hint() const noexcept { return m_queue.size(); }
Guard read() const
LockedConstPtr lock_read() const
{
return Guard(UniqueLock(m_mutex), m_queue);
return LockedConstPtr(&m_queue, Unlocker<const Queue>(UniqueLock(m_mutex)));
}
LockedPtr lock_rw()
{
return LockedPtr(&m_queue, Unlocker<Queue>(UniqueLock(m_mutex)));
}
private:
Queue m_queue;
std::mutex m_mutex;
mutable std::mutex m_mutex;
std::condition_variable m_condition;
};

View file

@ -96,7 +96,6 @@ static void extract_model_from_archive(
const char *model_xml = strstr(scene_xml_data.data(), model_name_tag);
const char *zero_tag = "<zero>";
const char *zero_xml = strstr(scene_xml_data.data(), zero_tag);
float trafo[3][4] = { 0 };
Vec3d instance_rotation = Vec3d::Zero();
Vec3d instance_scaling_factor = Vec3d::Ones();
Vec3d instance_offset = Vec3d::Zero();
@ -124,19 +123,7 @@ static void extract_model_from_archive(
"[%f, %f, %f]", zero, zero+1, zero+2) == 3) {
instance_scaling_factor = Vec3d((double)scale[0], (double)scale[1], (double)scale[2]);
instance_rotation = Vec3d(-(double)rotation[0], -(double)rotation[1], -(double)rotation[2]);
Eigen::Matrix3f mat_rot, mat_scale, mat_trafo;
mat_rot = Eigen::AngleAxisf(-rotation[2], Eigen::Vector3f::UnitZ()) *
Eigen::AngleAxisf(-rotation[1], Eigen::Vector3f::UnitY()) *
Eigen::AngleAxisf(-rotation[0], Eigen::Vector3f::UnitX());
mat_scale = Eigen::Scaling(scale[0], scale[1], scale[2]);
mat_trafo = mat_rot * mat_scale;
for (size_t r = 0; r < 3; ++ r) {
for (size_t c = 0; c < 3; ++ c)
trafo[r][c] += mat_trafo(r, c);
}
instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2]));
// CHECK_ME -> Is the following correct ?
trafo[2][3] = position[2] / (float)instance_scaling_factor(2);
trafo_set = true;
}
const char *group_tag = "<group>";
@ -189,8 +176,6 @@ static void extract_model_from_archive(
// All the faces have been read.
stl_get_size(&stl);
mesh.repair();
// Transform the model.
stl_transform(&stl, &trafo[0][0]);
if (std::abs(stl.stats.min(2)) < EPSILON)
stl.stats.min(2) = 0.;
// Add a mesh to a model.
@ -274,8 +259,6 @@ static void extract_model_from_archive(
memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50);
stl_get_size(&stl);
mesh.repair();
// Transform the model.
stl_transform(&stl, &trafo[0][0]);
// Add a mesh to a model.
if (mesh.facets_count() > 0)
mesh_valid = true;

View file

@ -612,7 +612,9 @@ double ray_mesh_intersect(const Vec3d& s,
const Vec3d& dir,
const EigenMesh3D& m);
PointSet normals(const PointSet& points, const EigenMesh3D& mesh);
PointSet normals(const PointSet& points, const EigenMesh3D& mesh,
double eps = 0.05, // min distance from edges
std::function<void()> throw_on_cancel = [](){});
inline Vec2d to_vec2(const Vec3d& v3) {
return {v3(X), v3(Y)};
@ -1049,7 +1051,7 @@ bool SLASupportTree::generate(const PointSet &points,
tifcl();
// calculate the normals to the triangles belonging to filtered points
auto nmls = sla::normals(filt_pts, mesh);
auto nmls = sla::normals(filt_pts, mesh, cfg.head_front_radius_mm, tifcl);
head_norm.resize(count, 3);
head_pos.resize(count, 3);

View file

@ -1,3 +1,4 @@
#include <cmath>
#include "SLA/SLASupportTree.hpp"
#include "SLA/SLABoilerPlate.hpp"
#include "SLA/SLASpatIndex.hpp"
@ -9,15 +10,8 @@
#include "boost/geometry/index/rtree.hpp"
#include <igl/ray_mesh_intersect.h>
//#if !defined(_MSC_VER) || defined(_WIN64)
#if 1
#define IGL_COMPATIBLE
#endif
#ifdef IGL_COMPATIBLE
#include <igl/point_mesh_squared_distance.h>
#endif
#include <igl/remove_duplicate_vertices.h>
#include "SLASpatIndex.hpp"
#include "ClipperUtils.hpp"
@ -84,33 +78,124 @@ size_t SpatIndex::size() const
return m_impl->m_store.size();
}
PointSet normals(const PointSet& points, const EigenMesh3D& mesh) {
if(points.rows() == 0 || mesh.V.rows() == 0 || mesh.F.rows() == 0) return {};
#ifdef IGL_COMPATIBLE
bool point_on_edge(const Vec3d& p, const Vec3d& e1, const Vec3d& e2,
double eps = 0.05)
{
using Line3D = Eigen::ParametrizedLine<double, 3>;
auto line = Line3D::Through(e1, e2);
double d = line.distance(p);
return std::abs(d) < eps;
}
template<class Vec> double distance(const Vec& pp1, const Vec& pp2) {
auto p = pp2 - pp1;
return std::sqrt(p.transpose() * p);
}
PointSet normals(const PointSet& points, const EigenMesh3D& emesh,
double eps,
std::function<void()> throw_on_cancel) {
if(points.rows() == 0 || emesh.V.rows() == 0 || emesh.F.rows() == 0)
return {};
Eigen::VectorXd dists;
Eigen::VectorXi I;
PointSet C;
// We need to remove duplicate vertices and have a true index triangle
// structure
EigenMesh3D mesh;
Eigen::VectorXi SVI, SVJ;
igl::remove_duplicate_vertices(emesh.V, emesh.F, 1e-6,
mesh.V, SVI, SVJ, mesh.F);
igl::point_mesh_squared_distance( points, mesh.V, mesh.F, dists, I, C);
PointSet ret(I.rows(), 3);
for(int i = 0; i < I.rows(); i++) {
throw_on_cancel();
auto idx = I(i);
auto trindex = mesh.F.row(idx);
auto& p1 = mesh.V.row(trindex(0));
auto& p2 = mesh.V.row(trindex(1));
auto& p3 = mesh.V.row(trindex(2));
const Vec3d& p1 = mesh.V.row(trindex(0));
const Vec3d& p2 = mesh.V.row(trindex(1));
const Vec3d& p3 = mesh.V.row(trindex(2));
Eigen::Vector3d U = p2 - p1;
Eigen::Vector3d V = p3 - p1;
ret.row(i) = U.cross(V).normalized();
// We should check if the point lies on an edge of the hosting triangle.
// If it does than all the other triangles using the same two points
// have to be searched and the final normal should be some kind of
// aggregation of the participating triangle normals. We should also
// consider the cases where the support point lies right on a vertex
// of its triangle. The procedure is the same, get the neighbor
// triangles and calculate an average normal.
const Vec3d& p = C.row(i);
// mark the vertex indices of the edge. ia and ib marks and edge ic
// will mark a single vertex.
int ia = -1, ib = -1, ic = -1;
if(std::abs(distance(p, p1)) < eps) {
ic = trindex(0);
}
else if(std::abs(distance(p, p2)) < eps) {
ic = trindex(1);
}
else if(std::abs(distance(p, p3)) < eps) {
ic = trindex(2);
}
else if(point_on_edge(p, p1, p2, eps)) {
ia = trindex(0); ib = trindex(1);
}
else if(point_on_edge(p, p2, p3, eps)) {
ia = trindex(1); ib = trindex(2);
}
else if(point_on_edge(p, p1, p3, eps)) {
ia = trindex(0); ib = trindex(2);
}
std::vector<Vec3i> neigh;
if(ic >= 0) { // The point is right on a vertex of the triangle
for(int n = 0; n < mesh.F.rows(); ++n) {
throw_on_cancel();
Vec3i ni = mesh.F.row(n);
if((ni(X) == ic || ni(Y) == ic || ni(Z) == ic))
neigh.emplace_back(ni);
}
}
else if(ia >= 0 && ib >= 0) { // the point is on and edge
// now get all the neigboring triangles
for(int n = 0; n < mesh.F.rows(); ++n) {
throw_on_cancel();
Vec3i ni = mesh.F.row(n);
if((ni(X) == ia || ni(Y) == ia || ni(Z) == ia) &&
(ni(X) == ib || ni(Y) == ib || ni(Z) == ib))
neigh.emplace_back(ni);
}
}
if(!neigh.empty()) { // there were neighbors to count with
Vec3d sumnorm(0, 0, 0);
for(const Vec3i& tri : neigh) {
const Vec3d& pt1 = mesh.V.row(tri(0));
const Vec3d& pt2 = mesh.V.row(tri(1));
const Vec3d& pt3 = mesh.V.row(tri(2));
Eigen::Vector3d U = pt2 - pt1;
Eigen::Vector3d V = pt3 - pt1;
sumnorm += U.cross(V).normalized();
}
sumnorm /= neigh.size();
ret.row(i) = sumnorm;
}
else { // point lies safely within its triangle
Eigen::Vector3d U = p2 - p1;
Eigen::Vector3d V = p3 - p1;
ret.row(i) = U.cross(V).normalized();
}
}
return ret;
#else // TODO: do something on 32 bit windows
return {};
#endif
}
double ray_mesh_intersect(const Vec3d& s,
@ -223,7 +308,7 @@ Segments model_boundary(const EigenMesh3D& emesh, double offs)
pp.emplace_back(p);
}
ExPolygons merged = union_ex(offset(pp, float(scale_(offs))), true);
ExPolygons merged = union_ex(Slic3r::offset(pp, float(scale_(offs))), true);
for(auto& expoly : merged) {
auto lines = expoly.lines();