FIX:add "split mesh and save relationship" api
jira: none Change-Id: Ib4c225b7fb75a27bd74f1a60b8842cbc4880e4f6
This commit is contained in:
parent
6c48a8e40b
commit
2caffbc573
|
@ -184,6 +184,81 @@ std::vector<indexed_triangle_set> its_split(const Its &its)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Splits a mesh into multiple meshes when possible.
|
||||||
|
template<class Its, class OutputIt, class OutputIt_ship>
|
||||||
|
void its_split_and_keep_relationship(const Its &m, OutputIt out_it, OutputIt_ship out_ship)
|
||||||
|
{
|
||||||
|
using namespace meshsplit_detail;
|
||||||
|
|
||||||
|
const indexed_triangle_set &its = ItsWithNeighborsIndex_<Its>::get_its(m);
|
||||||
|
|
||||||
|
struct VertexConv
|
||||||
|
{
|
||||||
|
size_t part_id = std::numeric_limits<size_t>::max();
|
||||||
|
size_t vertex_image;
|
||||||
|
};
|
||||||
|
std::vector<VertexConv> vidx_conv(its.vertices.size());
|
||||||
|
|
||||||
|
meshsplit_detail::NeighborVisitor visitor(its, meshsplit_detail::ItsWithNeighborsIndex_<Its>::get_index(m));
|
||||||
|
|
||||||
|
std::vector<size_t> facets;
|
||||||
|
for (size_t part_id = 0;; ++part_id) {
|
||||||
|
// Collect all faces of the next patch.
|
||||||
|
facets.clear();
|
||||||
|
visitor.visit([&facets](size_t idx) {
|
||||||
|
facets.emplace_back(idx);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (facets.empty()) break;
|
||||||
|
std::sort(facets.begin(), facets.end());
|
||||||
|
// Create a new mesh for the part that was just split off.
|
||||||
|
indexed_triangle_set mesh;
|
||||||
|
mesh.indices.reserve(facets.size());
|
||||||
|
mesh.vertices.reserve(std::min(facets.size() * 3, its.vertices.size()));
|
||||||
|
std::unordered_map<int, int> relationship;
|
||||||
|
// Assign the facets to the new mesh.
|
||||||
|
for (size_t face_id : facets) {
|
||||||
|
const auto &face = its.indices[face_id];
|
||||||
|
Vec3i new_face;
|
||||||
|
for (size_t v = 0; v < 3; ++v) {
|
||||||
|
auto vi = face(v);
|
||||||
|
|
||||||
|
if (vidx_conv[vi].part_id != part_id) {
|
||||||
|
vidx_conv[vi] = {part_id, mesh.vertices.size()};
|
||||||
|
mesh.vertices.emplace_back(its.vertices[size_t(vi)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_face(v) = vidx_conv[vi].vertex_image;
|
||||||
|
}
|
||||||
|
relationship[mesh.indices.size()] = face_id;
|
||||||
|
mesh.indices.emplace_back(new_face);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_it = std::move(mesh);
|
||||||
|
*out_ship = std::move(relationship);
|
||||||
|
++out_it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class MeshAndShip
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<indexed_triangle_set> itses;
|
||||||
|
std::vector<std::unordered_map<int, int>> ships;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Its>
|
||||||
|
MeshAndShip its_split_and_save_relationship(const Its &its)
|
||||||
|
{
|
||||||
|
auto ret = reserve_vector<indexed_triangle_set>(3);
|
||||||
|
auto ret_ship = reserve_vector<std::unordered_map<int, int>>(3);
|
||||||
|
|
||||||
|
its_split_and_keep_relationship(its, std::back_inserter(ret), std::back_inserter(ret_ship));
|
||||||
|
MeshAndShip mesh_ship;
|
||||||
|
mesh_ship.itses = ret;
|
||||||
|
mesh_ship.ships = ret_ship;
|
||||||
|
return mesh_ship;
|
||||||
|
}
|
||||||
|
|
||||||
template<class Its>
|
template<class Its>
|
||||||
bool its_is_splittable(const Its &m)
|
bool its_is_splittable(const Its &m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3243,9 +3243,12 @@ std::string ModelVolume::type_to_string(const ModelVolumeType t)
|
||||||
// This is useful to assign different materials to different volumes of an object.
|
// This is useful to assign different materials to different volumes of an object.
|
||||||
size_t ModelVolume::split(unsigned int max_extruders)
|
size_t ModelVolume::split(unsigned int max_extruders)
|
||||||
{
|
{
|
||||||
std::vector<TriangleMesh> meshes = this->mesh().split();
|
std::vector<std::unordered_map<int, int>> ships;
|
||||||
|
std::vector<TriangleMesh> meshes = this->mesh().split_and_save_relationship(ships);
|
||||||
if (meshes.size() <= 1)
|
if (meshes.size() <= 1)
|
||||||
return 1;
|
return 1;
|
||||||
|
if (meshes.size() != ships.size())
|
||||||
|
return 1;
|
||||||
// splited volume should not be text object
|
// splited volume should not be text object
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
size_t ivolume = std::find(this->object->volumes.begin(), this->object->volumes.end(), this) - this->object->volumes.begin();
|
||||||
|
@ -3279,17 +3282,23 @@ size_t ModelVolume::split(unsigned int max_extruders)
|
||||||
this->exterior_facets.reset();
|
this->exterior_facets.reset();
|
||||||
this->supported_facets.reset();
|
this->supported_facets.reset();
|
||||||
this->seam_facets.reset();
|
this->seam_facets.reset();
|
||||||
for (size_t i = 0; i < tris_split_strs.size(); i++) {
|
for (size_t i = 0; i < cur_face_count; i++) {
|
||||||
if (i < cur_face_count && tris_split_strs[i].size()>0) {
|
if (ships[idx].find(i) != ships[idx].end()) {
|
||||||
mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[i]);
|
auto index = ships[idx][i];
|
||||||
|
if (tris_split_strs[index].size() > 0) {
|
||||||
|
mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto new_mv =new ModelVolume(object, *this, std::move(mesh));
|
auto new_mv =new ModelVolume(object, *this, std::move(mesh));
|
||||||
this->object->volumes.insert(this->object->volumes.begin() + (++ivolume), new_mv);
|
this->object->volumes.insert(this->object->volumes.begin() + (++ivolume), new_mv);
|
||||||
for (size_t i = last_all_mesh_face_count; i < tris_split_strs.size(); i++) {
|
for (size_t i = 0; i < new_mv->mesh_ptr()->its.indices.size(); i++) {
|
||||||
if (i < last_all_mesh_face_count + cur_face_count && tris_split_strs[i].size() > 0) {
|
if (ships[idx].find(i) != ships[idx].end()) {
|
||||||
new_mv->mmu_segmentation_facets.set_triangle_from_string(i - last_all_mesh_face_count, tris_split_strs[i]);
|
auto index = ships[idx][i];
|
||||||
|
if (tris_split_strs[index].size() > 0) {
|
||||||
|
new_mv->mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,6 +406,29 @@ std::vector<TriangleMesh> TriangleMesh::split() const
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<TriangleMesh> TriangleMesh::split_and_save_relationship(std::vector<std::unordered_map<int, int>> &result) const {
|
||||||
|
auto itss_and_ships = its_split_and_save_relationship<>(this->its);
|
||||||
|
std::vector<TriangleMesh> out;
|
||||||
|
out.reserve(itss_and_ships.itses.size());
|
||||||
|
result.reserve(itss_and_ships.itses.size());
|
||||||
|
unsigned int index = 0;
|
||||||
|
for (indexed_triangle_set &m : itss_and_ships.itses) {
|
||||||
|
// The TriangleMesh constructor shall fill in the mesh statistics including volume.
|
||||||
|
TriangleMesh temp_triangle_mesh(std::move(m));
|
||||||
|
if (abs(temp_triangle_mesh.volume() < 0.01)) { // 0.01mm^3
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (temp_triangle_mesh.volume() < 0) { // Some source mesh parts may be incorrectly oriented. Correct them.
|
||||||
|
temp_triangle_mesh.flip_triangles();
|
||||||
|
}
|
||||||
|
out.emplace_back(temp_triangle_mesh);
|
||||||
|
result.emplace_back(itss_and_ships.ships[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void TriangleMesh::merge(const TriangleMesh &mesh)
|
void TriangleMesh::merge(const TriangleMesh &mesh)
|
||||||
{
|
{
|
||||||
its_merge(this->its, mesh.its);
|
its_merge(this->its, mesh.its);
|
||||||
|
|
|
@ -119,6 +119,7 @@ public:
|
||||||
void align_to_origin();
|
void align_to_origin();
|
||||||
void rotate(double angle, Point* center);
|
void rotate(double angle, Point* center);
|
||||||
std::vector<TriangleMesh> split() const;
|
std::vector<TriangleMesh> split() const;
|
||||||
|
std::vector<TriangleMesh> split_and_save_relationship(std::vector<std::unordered_map<int, int>> &result) const;
|
||||||
void merge(const TriangleMesh &mesh);
|
void merge(const TriangleMesh &mesh);
|
||||||
ExPolygons horizontal_projection() const;
|
ExPolygons horizontal_projection() const;
|
||||||
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
||||||
|
|
Loading…
Reference in New Issue