FIX:add "split mesh and save relationship" api

jira: none
Change-Id: Ib4c225b7fb75a27bd74f1a60b8842cbc4880e4f6
This commit is contained in:
zhou.xu 2024-11-13 14:54:56 +08:00 committed by Lane.Wei
parent 6c48a8e40b
commit 2caffbc573
4 changed files with 115 additions and 7 deletions

View File

@ -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)
{ {

View File

@ -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]);
}
} }
} }
} }

View File

@ -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);

View File

@ -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.