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;
|
||||
}
|
||||
|
||||
// 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>
|
||||
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.
|
||||
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)
|
||||
return 1;
|
||||
if (meshes.size() != ships.size())
|
||||
return 1;
|
||||
// splited volume should not be text object
|
||||
size_t idx = 0;
|
||||
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->supported_facets.reset();
|
||||
this->seam_facets.reset();
|
||||
for (size_t i = 0; i < tris_split_strs.size(); i++) {
|
||||
if (i < cur_face_count && tris_split_strs[i].size()>0) {
|
||||
mmu_segmentation_facets.set_triangle_from_string(i, tris_split_strs[i]);
|
||||
for (size_t i = 0; i < cur_face_count; i++) {
|
||||
if (ships[idx].find(i) != ships[idx].end()) {
|
||||
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 {
|
||||
auto new_mv =new ModelVolume(object, *this, std::move(mesh));
|
||||
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++) {
|
||||
if (i < last_all_mesh_face_count + cur_face_count && tris_split_strs[i].size() > 0) {
|
||||
new_mv->mmu_segmentation_facets.set_triangle_from_string(i - last_all_mesh_face_count, tris_split_strs[i]);
|
||||
for (size_t i = 0; i < new_mv->mesh_ptr()->its.indices.size(); i++) {
|
||||
if (ships[idx].find(i) != ships[idx].end()) {
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
its_merge(this->its, mesh.its);
|
||||
|
|
|
@ -119,6 +119,7 @@ public:
|
|||
void align_to_origin();
|
||||
void rotate(double angle, Point* center);
|
||||
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);
|
||||
ExPolygons horizontal_projection() const;
|
||||
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
||||
|
|
Loading…
Reference in New Issue