mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_sequential_limits
This commit is contained in:
		
						commit
						33d489df30
					
				
					 7 changed files with 97 additions and 108 deletions
				
			
		|  | @ -212,36 +212,32 @@ static bool sort_pointfs(const Vec3d& a, const Vec3d& b) | |||
| } | ||||
| 
 | ||||
| // This implementation is based on Andrew's monotone chain 2D convex hull algorithm
 | ||||
| Polygon convex_hull(Points points) | ||||
| Polygon convex_hull(Points pts) | ||||
| { | ||||
|     assert(points.size() >= 3); | ||||
|     // sort input points
 | ||||
|     std::sort(points.begin(), points.end(), sort_points); | ||||
|     std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); }); | ||||
|     pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end()); | ||||
| 
 | ||||
|     int n = points.size(), k = 0; | ||||
|     Polygon hull; | ||||
| 
 | ||||
|     int n = (int)pts.size(); | ||||
|     if (n >= 3) { | ||||
|         int k = 0; | ||||
|         hull.points.resize(2 * n); | ||||
| 
 | ||||
|         // Build lower hull
 | ||||
|         for (int i = 0; i < n; i++) { | ||||
|             while (k >= 2 && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--; | ||||
|             hull[k++] = points[i]; | ||||
|         for (int i = 0; i < n; ++ i) { | ||||
|             while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) | ||||
|                 -- k; | ||||
|             hull[k ++] = pts[i]; | ||||
|         } | ||||
| 
 | ||||
|         // Build upper hull
 | ||||
|         for (int i = n-2, t = k+1; i >= 0; i--) { | ||||
|             while (k >= t && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--; | ||||
|             hull[k++] = points[i]; | ||||
|             while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) | ||||
|                 -- k; | ||||
|             hull[k ++] = pts[i]; | ||||
|         } | ||||
| 
 | ||||
|         hull.points.resize(k); | ||||
| 
 | ||||
|         assert(hull.points.front() == hull.points.back()); | ||||
|         hull.points.pop_back(); | ||||
|     } | ||||
|      | ||||
|     return hull; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| #include "libslic3r.h" | ||||
| #include "Exception.hpp" | ||||
| #include "Model.hpp" | ||||
| #include "ModelArrange.hpp" | ||||
|  | @ -889,35 +890,22 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_ | |||
| // Calculate 2D convex hull of of a projection of the transformed printable volumes into the XY plane.
 | ||||
| // This method is cheap in that it does not make any unnecessary copy of the volume meshes.
 | ||||
| // This method is used by the auto arrange function.
 | ||||
| #if ENABLE_ALLOW_NEGATIVE_Z | ||||
| Polygon ModelObject::convex_hull_2d(const Transform3d& trafo_instance) const | ||||
| { | ||||
|     Points pts; | ||||
|     for (const ModelVolume* v : volumes) { | ||||
|         if (v->is_model_part()) | ||||
|             append(pts, its_convex_hull_2d_above(v->mesh().its, (trafo_instance * v->get_matrix()).cast<float>(), 0.0f).points); | ||||
|     } | ||||
|     return Geometry::convex_hull(std::move(pts)); | ||||
| } | ||||
| #else | ||||
| Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const | ||||
| { | ||||
|     Points pts; | ||||
|     for (const ModelVolume *v : this->volumes) | ||||
|         if (v->is_model_part()) { | ||||
| #if ENABLE_ALLOW_NEGATIVE_Z | ||||
|             const Transform3d trafo = trafo_instance * v->get_matrix(); | ||||
|             const TriangleMesh& hull_3d = v->get_convex_hull(); | ||||
|             const indexed_triangle_set& its = hull_3d.its; | ||||
|             if (its.vertices.empty()) { | ||||
|                 // Using the STL faces.
 | ||||
|                 const stl_file& stl = hull_3d.stl; | ||||
|                 for (const stl_facet& facet : stl.facet_start) { | ||||
|                     for (size_t j = 0; j < 3; ++j) { | ||||
|                         const Vec3d p = trafo * facet.vertex[j].cast<double>(); | ||||
|                         if (p.z() >= 0.0) | ||||
|                             pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else { | ||||
|                 // Using the shared vertices should be a bit quicker than using the STL faces.
 | ||||
|                 for (size_t i = 0; i < its.vertices.size(); ++i) { | ||||
|                     const Vec3d p = trafo * its.vertices[i].cast<double>(); | ||||
|                     if (p.z() >= 0.0) | ||||
|                         pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); | ||||
|                 } | ||||
|             } | ||||
| #else | ||||
|             Transform3d trafo = trafo_instance * v->get_matrix(); | ||||
| 			const indexed_triangle_set &its = v->mesh().its; | ||||
| 			if (its.vertices.empty()) { | ||||
|  | @ -935,34 +923,10 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const | |||
|                         pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); | ||||
|                 } | ||||
|             } | ||||
| #endif // ENABLE_ALLOW_NEGATIVE_Z
 | ||||
|         } | ||||
|     std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); }); | ||||
|     pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end()); | ||||
| 
 | ||||
|     Polygon hull; | ||||
|     int n = (int)pts.size(); | ||||
|     if (n >= 3) { | ||||
|         int k = 0; | ||||
|         hull.points.resize(2 * n); | ||||
|         // Build lower hull
 | ||||
|         for (int i = 0; i < n; ++ i) { | ||||
|             while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) | ||||
|                 -- k; | ||||
|             hull[k ++] = pts[i]; | ||||
|         } | ||||
|         // Build upper hull
 | ||||
|         for (int i = n-2, t = k+1; i >= 0; i--) { | ||||
|             while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0) | ||||
|                 -- k; | ||||
|             hull[k ++] = pts[i]; | ||||
|         } | ||||
|         hull.points.resize(k); | ||||
|         assert(hull.points.front() == hull.points.back()); | ||||
|         hull.points.pop_back(); | ||||
|     } | ||||
|     return hull; | ||||
|     return Geometry::convex_hull(std::move(pts)); | ||||
| } | ||||
| #endif // ENABLE_ALLOW_NEGATIVE_Z
 | ||||
| 
 | ||||
| void ModelObject::center_around_origin(bool include_modifiers) | ||||
| { | ||||
|  |  | |||
|  | @ -117,7 +117,9 @@ bool Point::nearest_point(const Points &points, Point* point) const | |||
|  */ | ||||
| double Point::ccw(const Point &p1, const Point &p2) const | ||||
| { | ||||
|     return (double)(p2(0) - p1(0))*(double)((*this)(1) - p1(1)) - (double)(p2(1) - p1(1))*(double)((*this)(0) - p1(0)); | ||||
|     static_assert(sizeof(coord_t) == 4, "Point::ccw() requires a 32 bit coord_t"); | ||||
|     return cross2((p2 - p1).cast<int64_t>(), (*this - p1).cast<int64_t>()); | ||||
| //    return cross2((p2 - p1).cast<double>(), (*this - p1).cast<double>());
 | ||||
| } | ||||
| 
 | ||||
| double Point::ccw(const Line &line) const | ||||
|  | @ -129,9 +131,9 @@ double Point::ccw(const Line &line) const | |||
| // i.e. this assumes a CCW rotation from p1 to p2 around this
 | ||||
| double Point::ccw_angle(const Point &p1, const Point &p2) const | ||||
| { | ||||
|     double angle = atan2(p1(0) - (*this)(0), p1(1) - (*this)(1)) | ||||
|                  - atan2(p2(0) - (*this)(0), p2(1) - (*this)(1)); | ||||
|      | ||||
|     //FIXME this calculates an atan2 twice! Project one vector into the other!
 | ||||
|     double angle = atan2(p1.x() - (*this).x(), p1.y() - (*this).y()) | ||||
|                  - atan2(p2.x() - (*this).x(), p2.y() - (*this).y()); | ||||
|     // we only want to return only positive angles
 | ||||
|     return angle <= 0 ? angle + 2*PI : angle; | ||||
| } | ||||
|  | @ -201,12 +203,12 @@ int orient(const Vec2crd &p1, const Vec2crd &p2, const Vec2crd &p3) | |||
| { | ||||
|     Slic3r::Vector v1(p2 - p1); | ||||
|     Slic3r::Vector v2(p3 - p1); | ||||
|     return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); | ||||
|     return Int128::sign_determinant_2x2_filtered(v1.x(), v1.y(), v2.x(), v2.y()); | ||||
| } | ||||
| 
 | ||||
| int cross(const Vec2crd &v1, const Vec2crd &v2) | ||||
| { | ||||
|     return Int128::sign_determinant_2x2_filtered(v1(0), v1(1), v2(0), v2(1)); | ||||
|     return Int128::sign_determinant_2x2_filtered(v1.x(), v1.y(), v2.x(), v2.y()); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -611,7 +611,7 @@ TriangleMesh TriangleMesh::convex_hull_3d() const | |||
|     return output_mesh; | ||||
| } | ||||
| 
 | ||||
| std::vector<ExPolygons> TriangleMesh::slice(const std::vector<double> &z) | ||||
| std::vector<ExPolygons> TriangleMesh::slice(const std::vector<double> &z) const | ||||
| { | ||||
|     // convert doubles to floats
 | ||||
|     std::vector<float> z_f(z.begin(), z.end()); | ||||
|  | @ -900,25 +900,42 @@ void its_shrink_to_fit(indexed_triangle_set &its) | |||
| } | ||||
| 
 | ||||
| template<typename TransformVertex> | ||||
| Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z) | ||||
| void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z, Points &all_pts) | ||||
| { | ||||
|     Points all_pts; | ||||
|     all_pts.reserve(all_pts.size() + its.indices.size() * 3); | ||||
|     for (const stl_triangle_vertex_indices &tri : its.indices) { | ||||
|         const Vec3f pts[3] = { transform_fn(its.vertices[tri(0)]), transform_fn(its.vertices[tri(1)]), transform_fn(its.vertices[tri(2)]) }; | ||||
|         int iprev = 3; | ||||
|         int iprev = 2; | ||||
|         for (int iedge = 0; iedge < 3; ++ iedge) { | ||||
|             const Vec3f &p1 = pts[iprev]; | ||||
|             const Vec3f &p2 = pts[iedge]; | ||||
|             if ((p1.z() < z && p2.z() > z) || (p2.z() < z && p1.z() > z)) { | ||||
|                 // Edge crosses the z plane. Calculate intersection point with the plane.
 | ||||
|                 float t = z / (p2.z() - p1.z()); | ||||
|                 all_pts.emplace_back(scaled<coord_t>(p1.x() + (p2.x() - p1.x()) * t), scaled<coord_t>(p2.x() + (p2.y() - p2.y()) * t)); | ||||
|                 float t = (z - p1.z()) / (p2.z() - p1.z()); | ||||
|                 all_pts.emplace_back(scaled<coord_t>(p1.x() + (p2.x() - p1.x()) * t), scaled<coord_t>(p1.y() + (p2.y() - p1.y()) * t)); | ||||
|             } | ||||
|             if (p2.z() > z) | ||||
|                 all_pts.emplace_back(scaled<coord_t>(p2.x()), scaled<coord_t>(p2.y())); | ||||
|             iprev = iedge; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Matrix3f &m, const float z, Points &all_pts) | ||||
| { | ||||
|     return its_collect_mesh_projection_points_above(its, [m](const Vec3f &p){ return m * p; }, z, all_pts); | ||||
| } | ||||
| 
 | ||||
| void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Transform3f &t, const float z, Points &all_pts) | ||||
| { | ||||
|     return its_collect_mesh_projection_points_above(its, [t](const Vec3f &p){ return t * p; }, z, all_pts); | ||||
| } | ||||
| 
 | ||||
| template<typename TransformVertex> | ||||
| Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const TransformVertex &transform_fn, const float z) | ||||
| { | ||||
|     Points all_pts; | ||||
|     its_collect_mesh_projection_points_above(its, transform_fn, z, all_pts); | ||||
|     return Geometry::convex_hull(std::move(all_pts)); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,7 +65,7 @@ public: | |||
|     // Returns the convex hull of this TriangleMesh
 | ||||
|     TriangleMesh convex_hull_3d() const; | ||||
|     // Slice this mesh at the provided Z levels and return the vector
 | ||||
|     std::vector<ExPolygons> slice(const std::vector<double>& z); | ||||
|     std::vector<ExPolygons> slice(const std::vector<double>& z) const; | ||||
|     void reset_repair_stats(); | ||||
|     bool needed_repair() const; | ||||
|     void require_shared_vertices(); | ||||
|  | @ -113,6 +113,11 @@ int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit = true | |||
| // Shrink the vectors of its.vertices and its.faces to a minimum size by reallocating the two vectors.
 | ||||
| void its_shrink_to_fit(indexed_triangle_set &its); | ||||
| 
 | ||||
| // For convex hull calculation: Transform mesh, trim it by the Z plane and collect all vertices. Duplicate vertices will be produced.
 | ||||
| void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Matrix3f &m, const float z, Points &all_pts); | ||||
| void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, const Transform3f &t, const float z, Points &all_pts); | ||||
| 
 | ||||
| // Calculate 2D convex hull of a transformed and clipped mesh. Uses the function above.
 | ||||
| Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Matrix3f &m, const float z); | ||||
| Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Transform3f &t, const float z); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1075,7 +1075,7 @@ std::vector<Polygons> slice_mesh( | |||
|                 auto t = params.trafo; | ||||
|                 t.prescale(Vec3d(s, s, 1.)); | ||||
|                 auto tf = t.cast<float>(); | ||||
|                 slice_make_lines(mesh.vertices, [tf](const Vec3f &p) { return tf * p; }, mesh.indices, facets_edges, zs, throw_on_cancel); | ||||
|                 lines = slice_make_lines(mesh.vertices, [tf](const Vec3f &p) { return tf * p; }, mesh.indices, facets_edges, zs, throw_on_cancel); | ||||
|             } | ||||
|         } else { | ||||
|             // Copy and scale vertices in XY, don't scale in Z.
 | ||||
|  | @ -1179,6 +1179,7 @@ std::vector<ExPolygons> slice_mesh_ex( | |||
|     return layers; | ||||
| } | ||||
| 
 | ||||
| // Remove duplicates of slice_vertices, optionally triangulate the cut.
 | ||||
| static void triangulate_slice( | ||||
|     indexed_triangle_set    &its,  | ||||
|     IntersectionLines       &lines,  | ||||
|  | @ -1186,7 +1187,8 @@ static void triangulate_slice( | |||
|     // Vertices of the original (unsliced) mesh. Newly added vertices are those on the slice.
 | ||||
|     int                      num_original_vertices, | ||||
|     // Z height of the slice.
 | ||||
|     float                    z) | ||||
|     float                    z,  | ||||
|     bool                     triangulate) | ||||
| { | ||||
|     sort_remove_duplicates(slice_vertices); | ||||
| 
 | ||||
|  | @ -1230,33 +1232,35 @@ static void triangulate_slice( | |||
|                     f(i) = map_duplicate_vertex[f(i) - num_original_vertices]; | ||||
|     } | ||||
| 
 | ||||
|     size_t idx_vertex_new_first = its.vertices.size(); | ||||
|     Pointf3s triangles = triangulate_expolygons_3d(make_expolygons_simple(lines), z, true); | ||||
|     for (size_t i = 0; i < triangles.size(); ) { | ||||
|         stl_triangle_vertex_indices facet; | ||||
|         for (size_t j = 0; j < 3; ++ j) { | ||||
|             Vec3f v = triangles[i ++].cast<float>(); | ||||
|             auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(),  | ||||
|                 [&v](const std::pair<Vec2f, int> &l) { return l.first.x() < v.x() || (l.first.x() == v.x() && l.first.y() < v.y()); }); | ||||
|             int   idx = -1; | ||||
|             if (it != map_vertex_to_index.end() && it->first.x() == v.x() && it->first.y() == v.y()) | ||||
|                 idx = it->second; | ||||
|             else { | ||||
|                 // Try to find the vertex in the list of newly added vertices. Those vertices are not matched on the cut and they shall be rare.
 | ||||
|                 for (size_t k = idx_vertex_new_first; k < its.vertices.size(); ++ k) | ||||
|                     if (its.vertices[k] == v) { | ||||
|                         idx = int(k); | ||||
|                         break; | ||||
|     if (triangulate) { | ||||
|         size_t idx_vertex_new_first = its.vertices.size(); | ||||
|         Pointf3s triangles = triangulate_expolygons_3d(make_expolygons_simple(lines), z, true); | ||||
|         for (size_t i = 0; i < triangles.size(); ) { | ||||
|             stl_triangle_vertex_indices facet; | ||||
|             for (size_t j = 0; j < 3; ++ j) { | ||||
|                 Vec3f v = triangles[i ++].cast<float>(); | ||||
|                 auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(),  | ||||
|                     [&v](const std::pair<Vec2f, int> &l) { return l.first.x() < v.x() || (l.first.x() == v.x() && l.first.y() < v.y()); }); | ||||
|                 int   idx = -1; | ||||
|                 if (it != map_vertex_to_index.end() && it->first.x() == v.x() && it->first.y() == v.y()) | ||||
|                     idx = it->second; | ||||
|                 else { | ||||
|                     // Try to find the vertex in the list of newly added vertices. Those vertices are not matched on the cut and they shall be rare.
 | ||||
|                     for (size_t k = idx_vertex_new_first; k < its.vertices.size(); ++ k) | ||||
|                         if (its.vertices[k] == v) { | ||||
|                             idx = int(k); | ||||
|                             break; | ||||
|                         } | ||||
|                     if (idx == -1) { | ||||
|                         idx = int(its.vertices.size()); | ||||
|                         its.vertices.emplace_back(v); | ||||
|                     } | ||||
|                 if (idx == -1) { | ||||
|                     idx = int(its.vertices.size()); | ||||
|                     its.vertices.emplace_back(v); | ||||
|                 } | ||||
|                 facet(j) = idx; | ||||
|             } | ||||
|             facet(j) = idx; | ||||
|             if (facet(0) != facet(1) && facet(0) != facet(2) && facet(1) != facet(2)) | ||||
|                 its.indices.emplace_back(facet); | ||||
|         } | ||||
|         if (facet(0) != facet(1) && facet(0) != facet(2) && facet(1) != facet(2)) | ||||
|             its.indices.emplace_back(facet); | ||||
|     } | ||||
| 
 | ||||
|     // Remove vertices, which are not referenced by any face.
 | ||||
|  | @ -1266,7 +1270,7 @@ static void triangulate_slice( | |||
|     // its_remove_degenerate_faces(its);
 | ||||
| } | ||||
| 
 | ||||
| void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, indexed_triangle_set *lower) | ||||
| void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *upper, indexed_triangle_set *lower, bool triangulate_caps) | ||||
| { | ||||
|     assert(upper || lower); | ||||
|     if (upper == nullptr && lower == nullptr) | ||||
|  | @ -1413,10 +1417,10 @@ void cut_mesh(const indexed_triangle_set &mesh, float z, indexed_triangle_set *u | |||
|     } | ||||
|      | ||||
|     if (upper != nullptr) | ||||
|         triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z); | ||||
|         triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps); | ||||
| 
 | ||||
|     if (lower != nullptr) | ||||
|         triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z); | ||||
|         triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -76,7 +76,8 @@ void                            cut_mesh( | |||
|     const indexed_triangle_set      &mesh, | ||||
|     float                            z, | ||||
|     indexed_triangle_set            *upper, | ||||
|     indexed_triangle_set            *lower); | ||||
|     indexed_triangle_set            *lower, | ||||
|     bool                             triangulate_caps = true); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 enricoturri1966
						enricoturri1966