mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merged some of the late changes on slicing robustness
from the 1.41.2 (stable) to the current 1.42.0-alpha3 This should fix a number of errors reported (#1562, #1592, #1614, #1633)
This commit is contained in:
		
							parent
							
								
									8696c70af4
								
							
						
					
					
						commit
						cf8e4fd7b0
					
				
					 2 changed files with 67 additions and 160 deletions
				
			
		|  | @ -19,6 +19,7 @@ | |||
| 
 | ||||
| #include <tbb/parallel_for.h> | ||||
| 
 | ||||
| #include <Eigen/Core> | ||||
| #include <Eigen/Dense> | ||||
| 
 | ||||
| // for SLIC3R_DEBUG_SLICE_PROCESSING
 | ||||
|  | @ -141,11 +142,15 @@ void TriangleMesh::repair() | |||
|     } | ||||
|      | ||||
|     // fill_holes
 | ||||
| #if 0 | ||||
|     // Don't fill holes, the current algorithm does more harm than good on complex holes.
 | ||||
|     // Rather let the slicing algorithm close gaps in 2D slices.
 | ||||
|     if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) { | ||||
|         BOOST_LOG_TRIVIAL(trace) << "\tstl_fill_holes"; | ||||
|         stl_fill_holes(&stl); | ||||
|         stl_clear_error(&stl); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     // normal_directions
 | ||||
|     BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_directions"; | ||||
|  | @ -293,6 +298,7 @@ void TriangleMesh::mirror(const Axis &axis) | |||
| void TriangleMesh::transform(const Transform3d& t) | ||||
| { | ||||
|     stl_transform(&stl, t); | ||||
|     stl_invalidate_shared_vertices(&stl); | ||||
| } | ||||
| 
 | ||||
| void TriangleMesh::align_to_origin() | ||||
|  | @ -399,7 +405,7 @@ TriangleMeshPtrs TriangleMesh::split() const | |||
|         // get the first facet
 | ||||
|         std::queue<int> facet_queue; | ||||
|         std::deque<int> facets; | ||||
|         for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { | ||||
|         for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; ++ facet_idx) { | ||||
|             if (! facet_visited[facet_idx]) { | ||||
|                 // if facet was not seen put it into queue and start searching
 | ||||
|                 facet_queue.push(facet_idx); | ||||
|  | @ -451,9 +457,8 @@ void TriangleMesh::merge(const TriangleMesh &mesh) | |||
|     stl_reallocate(&this->stl); | ||||
|      | ||||
|     // copy facets
 | ||||
|     for (int i = 0; i < mesh.stl.stats.number_of_facets; i++) { | ||||
|     for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) | ||||
|         this->stl.facet_start[number_of_facets + i] = mesh.stl.facet_start[i]; | ||||
|     } | ||||
|      | ||||
|     // update size
 | ||||
|     stl_get_size(&this->stl); | ||||
|  | @ -465,7 +470,7 @@ ExPolygons TriangleMesh::horizontal_projection() const | |||
| { | ||||
|     Polygons pp; | ||||
|     pp.reserve(this->stl.stats.number_of_facets); | ||||
|     for (int i = 0; i < this->stl.stats.number_of_facets; i++) { | ||||
|     for (int i = 0; i < this->stl.stats.number_of_facets; ++ i) { | ||||
|         stl_facet* facet = &this->stl.facet_start[i]; | ||||
|         Polygon p; | ||||
|         p.points.resize(3); | ||||
|  | @ -480,11 +485,7 @@ ExPolygons TriangleMesh::horizontal_projection() const | |||
|     return union_ex(offset(pp, scale_(0.01)), true); | ||||
| } | ||||
| 
 | ||||
| const float* TriangleMesh::first_vertex() const | ||||
| { | ||||
|     return this->stl.facet_start ? &this->stl.facet_start->vertex[0](0) : nullptr; | ||||
| } | ||||
| 
 | ||||
| // 2D convex hull of a 3D mesh projected into the Z=0 plane.
 | ||||
| Polygon TriangleMesh::convex_hull() | ||||
| { | ||||
|     this->require_shared_vertices(); | ||||
|  | @ -510,7 +511,7 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const | |||
| { | ||||
|     bool has_shared = (stl.v_shared != nullptr); | ||||
|     if (!has_shared) | ||||
|         stl_generate_shared_vertices(&stl); | ||||
|         stl_generate_shared_vertices(const_cast<stl_file*>(&stl)); | ||||
| 
 | ||||
|     unsigned int vertices_count = (stl.stats.shared_vertices > 0) ? (unsigned int)stl.stats.shared_vertices : 3 * (unsigned int)stl.stats.number_of_facets; | ||||
| 
 | ||||
|  | @ -549,7 +550,7 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& t) const | |||
|     } | ||||
| 
 | ||||
|     if (!has_shared && (stl.stats.shared_vertices > 0)) | ||||
|         stl_invalidate_shared_vertices(&stl); | ||||
| 		stl_invalidate_shared_vertices(const_cast<stl_file*>(&stl)); | ||||
| 
 | ||||
|     Eigen::MatrixXd dst_vertices(3, vertices_count); | ||||
|     dst_vertices = t * src_vertices.colwise().homogeneous(); | ||||
|  | @ -850,49 +851,27 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin | |||
|      | ||||
|     #ifdef SLIC3R_TRIANGLEMESH_DEBUG | ||||
|     printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx, | ||||
|         facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0](2), | ||||
|         facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1](2), | ||||
|         facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2](2)); | ||||
|         facet.vertex[0](0), facet.vertex[0](1), facet.vertex[0](2), | ||||
|         facet.vertex[1](0), facet.vertex[1](1), facet.vertex[1](2), | ||||
|         facet.vertex[2](0), facet.vertex[2](1), facet.vertex[2](2)); | ||||
|     printf("z: min = %.2f, max = %.2f\n", min_z, max_z); | ||||
|     #endif /* SLIC3R_TRIANGLEMESH_DEBUG */ | ||||
|      | ||||
|     // find layer extents
 | ||||
|     std::vector<float>::const_iterator min_layer, max_layer; | ||||
|     min_layer = std::lower_bound(z.begin(), z.end(), min_z); // first layer whose slice_z is >= min_z
 | ||||
|     max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z); // first layer, whose slice_z is > max_z
 | ||||
|     max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z) - 1; // last layer whose slice_z is <= max_z
 | ||||
|     #ifdef SLIC3R_TRIANGLEMESH_DEBUG | ||||
|     printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin()) - 1); | ||||
|     printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); | ||||
|     #endif /* SLIC3R_TRIANGLEMESH_DEBUG */ | ||||
|      | ||||
|     for (std::vector<float>::const_iterator it = min_layer; it != max_layer; ++it) { | ||||
|     for (std::vector<float>::const_iterator it = min_layer; it != max_layer + 1; ++ it) { | ||||
|         std::vector<float>::size_type layer_idx = it - z.begin(); | ||||
|         IntersectionLine il; | ||||
|         if (this->slice_facet(*it / SCALING_FACTOR, facet, facet_idx, min_z, max_z, &il) == TriangleMeshSlicer::Slicing) { | ||||
|             boost::lock_guard<boost::mutex> l(*lines_mutex); | ||||
|             if (il.edge_type == feHorizontal) { | ||||
|                 // Insert all marked edges of the face. The marked edges do not share an edge with another horizontal face
 | ||||
|                 // (they may not have a nighbor, or their neighbor is vertical)
 | ||||
|                 const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; | ||||
|                 const bool reverse  = this->mesh->stl.facet_start[facet_idx].normal(2) < 0; | ||||
|                 for (int j = 0; j < 3; ++ j) | ||||
|                     if (il.flags & ((IntersectionLine::EDGE0_NO_NEIGHBOR | IntersectionLine::EDGE0_FOLD) << j)) { | ||||
|                         int a_id = vertices[j % 3]; | ||||
|                         int b_id = vertices[(j+1) % 3]; | ||||
|                         if (reverse) | ||||
|                             std::swap(a_id, b_id); | ||||
|                         const stl_vertex &a = this->v_scaled_shared[a_id]; | ||||
|                         const stl_vertex &b = this->v_scaled_shared[b_id]; | ||||
|                         il.a(0)    = a(0); | ||||
|                         il.a(1)    = a(1); | ||||
|                         il.b(0)    = b(0); | ||||
|                         il.b(1)    = b(1); | ||||
|                         il.a_id   = a_id; | ||||
|                         il.b_id   = b_id; | ||||
|                         assert(il.a != il.b); | ||||
|                         // This edge will not be used as a seed for loop extraction if it was added due to a fold of two overlapping horizontal faces.
 | ||||
|                         il.set_no_seed((IntersectionLine::EDGE0_FOLD << j) != 0); | ||||
|                         (*lines)[layer_idx].emplace_back(il); | ||||
|                     } | ||||
|                 // Ignore horizontal triangles. Any valid horizontal triangle must have a vertical triangle connected, otherwise the part has zero volume.
 | ||||
|             } else | ||||
|                 (*lines)[layer_idx].emplace_back(il); | ||||
|         } | ||||
|  | @ -934,21 +913,20 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet( | |||
|     // This is needed to get all intersection lines in a consistent order
 | ||||
|     // (external on the right of the line)
 | ||||
|     const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; | ||||
|     int i = (facet.vertex[1](2) == min_z) ? 1 : ((facet.vertex[2](2) == min_z) ? 2 : 0); | ||||
|     for (int j = i; j - i < 3; ++j ) {  // loop through facet edges
 | ||||
|         int               edge_id  = this->facets_edges[facet_idx * 3 + (j % 3)]; | ||||
|         int               a_id     = vertices[j % 3]; | ||||
|         int               b_id     = vertices[(j+1) % 3]; | ||||
|         const stl_vertex &a = this->v_scaled_shared[a_id]; | ||||
|         const stl_vertex &b = this->v_scaled_shared[b_id]; | ||||
|     int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0); | ||||
|     for (int j = i; j - i < 3; ++j) {  // loop through facet edges
 | ||||
|         int        edge_id  = this->facets_edges[facet_idx * 3 + (j % 3)]; | ||||
|         int        a_id     = vertices[j % 3]; | ||||
|         int        b_id     = vertices[(j+1) % 3]; | ||||
|         const stl_vertex *a = &this->v_scaled_shared[a_id]; | ||||
|         const stl_vertex *b = &this->v_scaled_shared[b_id]; | ||||
|          | ||||
|         // Is edge or face aligned with the cutting plane?
 | ||||
|         if (a(2) == slice_z && b(2) == slice_z) { | ||||
|         if (a->z() == slice_z && b->z() == slice_z) { | ||||
|             // Edge is horizontal and belongs to the current layer.
 | ||||
|             const stl_vertex &v0 = this->v_scaled_shared[vertices[0]]; | ||||
|             const stl_vertex &v1 = this->v_scaled_shared[vertices[1]]; | ||||
|             const stl_vertex &v2 = this->v_scaled_shared[vertices[2]]; | ||||
|             bool              swap = false; | ||||
|             const stl_normal &normal = this->mesh->stl.facet_start[facet_idx].normal; | ||||
|             // We may ignore this edge for slicing purposes, but we may still use it for object cutting.
 | ||||
|             FacetSliceType    result = Slicing; | ||||
|  | @ -956,157 +934,85 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet( | |||
|             if (min_z == max_z) { | ||||
|                 // All three vertices are aligned with slice_z.
 | ||||
|                 line_out->edge_type = feHorizontal; | ||||
|                 // Mark neighbor edges, which do not have a neighbor.
 | ||||
|                 uint32_t edges = 0; | ||||
|                 for (int nbr_idx = 0; nbr_idx != 3; ++ nbr_idx) { | ||||
|                     // If the neighbor with an edge starting with a vertex idx (nbr_idx - 2) shares no
 | ||||
|                     // opposite face, add it to the edges to process when slicing.
 | ||||
|                     if (nbr.neighbor[nbr_idx] == -1) { | ||||
|                         // Mark this edge to be added to the slice.
 | ||||
|                         edges |= (IntersectionLine::EDGE0_NO_NEIGHBOR << nbr_idx); | ||||
|                     } | ||||
| #if 1 | ||||
|                      else if (normal(2) > 0) { | ||||
|                         // Produce edges for opposite faced overlapping horizontal faces aka folds.
 | ||||
|                         // This method often produces connecting lines (noise) at the cutting plane.
 | ||||
|                         // Produce the edges for the top facing face of the pair of top / bottom facing faces.
 | ||||
| 
 | ||||
|                         // Index of a neighbor face.
 | ||||
|                         const int  nbr_face     = nbr.neighbor[nbr_idx]; | ||||
|                         const int *nbr_vertices = this->mesh->stl.v_indices[nbr_face].vertex; | ||||
|                         int idx_vertex_opposite = nbr_vertices[nbr.which_vertex_not[nbr_idx]]; | ||||
|                         const stl_vertex    &c2 = this->v_scaled_shared[idx_vertex_opposite]; | ||||
|                         if (c2(2) == slice_z) { | ||||
|                             // Edge shared by facet_idx and nbr_face.
 | ||||
|                             int               a_id      = vertices[nbr_idx]; | ||||
|                             int               b_id      = vertices[(nbr_idx + 1) % 3]; | ||||
|                             int               c1_id     = vertices[(nbr_idx + 2) % 3]; | ||||
|                             const stl_vertex &a         = this->v_scaled_shared[a_id]; | ||||
|                             const stl_vertex &b         = this->v_scaled_shared[b_id]; | ||||
|                             const stl_vertex &c1        = this->v_scaled_shared[c1_id]; | ||||
|                             // Verify that the two neighbor faces share a common edge.
 | ||||
|                             assert(nbr_vertices[(nbr.which_vertex_not[nbr_idx] + 1) % 3] == b_id); | ||||
|                             assert(nbr_vertices[(nbr.which_vertex_not[nbr_idx] + 2) % 3] == a_id); | ||||
|                             double n1 = (double(c1(0)) - double(a(0))) * (double(b(1)) - double(a(1))) - (double(c1(1)) - double(a(1))) * (double(b(0)) - double(a(0))); | ||||
|                             double n2 = (double(c2(0)) - double(a(0))) * (double(b(1)) - double(a(1))) - (double(c2(1)) - double(a(1))) * (double(b(0)) - double(a(0))); | ||||
|                             if (n1 * n2 > 0) | ||||
|                                 // The two faces overlap. This indicates an invalid mesh geometry (non-manifold),
 | ||||
|                                 // but these are the real world objects, and leaving out these edges leads to missing contours.
 | ||||
|                                 edges |= (IntersectionLine::EDGE0_FOLD << nbr_idx); | ||||
|                          } | ||||
|                     } | ||||
| #endif | ||||
|                 } | ||||
|                 // Use some edges of this triangle for slicing only if at least one of its edge does not have an opposite face.
 | ||||
|                 result = (edges == 0) ? Cutting : Slicing; | ||||
|                 line_out->flags |= edges; | ||||
|                 if (normal(2) < 0) { | ||||
|                 result = Cutting; | ||||
|                 if (normal.z() < 0) { | ||||
|                     // If normal points downwards this is a bottom horizontal facet so we reverse its point order.
 | ||||
|                     swap = true; | ||||
|                     std::swap(a, b); | ||||
|                     std::swap(a_id, b_id); | ||||
|                 } | ||||
|             } else { | ||||
|                 // Two vertices are aligned with the cutting plane, the third vertex is below or above the cutting plane.
 | ||||
|                 int  nbr_idx     = j % 3; | ||||
|                 int  nbr_face    = nbr.neighbor[nbr_idx]; | ||||
|                 // Is the third vertex below the cutting plane?
 | ||||
|                 bool third_below = v0(2) < slice_z || v1(2) < slice_z || v2(2) < slice_z; | ||||
|                 // Is this a concave corner?
 | ||||
|                 if (nbr_face == -1) { | ||||
| #ifdef _DEBUG | ||||
|                     printf("Face has no neighbor!\n"); | ||||
| #endif | ||||
|                 } else { | ||||
|                     assert(this->mesh->stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 1) % 3] == b_id); | ||||
|                     assert(this->mesh->stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 2) % 3] == a_id); | ||||
|                     int idx_vertex_opposite = this->mesh->stl.v_indices[nbr_face].vertex[nbr.which_vertex_not[nbr_idx]]; | ||||
|                     const stl_vertex &c = this->v_scaled_shared[idx_vertex_opposite]; | ||||
|                     if (c(2) == slice_z) { | ||||
|                         double normal_nbr = (double(c(0)) - double(a(0))) * (double(b(1)) - double(a(1))) - (double(c(1)) - double(a(1))) * (double(b(0)) - double(a(0))); | ||||
| #if 0 | ||||
|                         if ((normal_nbr < 0) == third_below) { | ||||
|                             printf("Flipped normal?\n"); | ||||
|                         } | ||||
| #endif | ||||
|                         result = | ||||
|                                 // A vertical face shares edge with a horizontal face. Verify, whether the shared edge makes a convex or concave corner.
 | ||||
|                                 // Unfortunately too often there are flipped normals, which brake our assumption. Let's rather return every edge,
 | ||||
|                                 // and leth the code downstream hopefully handle it.
 | ||||
|     #if 1 | ||||
|                                 // Ignore concave corners for slicing.
 | ||||
|                                 // This method has the unfortunate property, that folds in a horizontal plane create concave corners,
 | ||||
|                                 // leading to broken contours, if these concave corners are not replaced by edges of the folds, see above.
 | ||||
|                                    ((normal_nbr < 0) == third_below) ? Cutting : Slicing; | ||||
|     #else | ||||
|                                 // Use concave corners for slicing. This leads to the test 01_trianglemesh.t "slicing a top tangent plane includes its area" failing,
 | ||||
|                                 // and rightly so.
 | ||||
|                                     Slicing; | ||||
|     #endif | ||||
|                     } else { | ||||
|                         // For a pair of faces touching exactly at the cutting plane, ignore one of them. An arbitrary rule is to ignore the face with a higher index.
 | ||||
|                         result = (facet_idx < nbr_face) ? Slicing : Cutting; | ||||
|                     } | ||||
|                 } | ||||
|                 bool third_below = v0.z() < slice_z || v1.z() < slice_z || v2.z() < slice_z; | ||||
|                 // Two vertices on the cutting plane, the third vertex is below the plane. Consider the edge to be part of the slice
 | ||||
|                 // only if it is the upper edge.
 | ||||
|                 // (the bottom most edge resp. vertex of a triangle is not owned by the triangle, but the top most edge resp. vertex is part of the triangle
 | ||||
|                 // in respect to the cutting plane).
 | ||||
|                 result = third_below ? Slicing : Cutting; | ||||
|                 if (third_below) { | ||||
|                     line_out->edge_type = feTop; | ||||
|                     swap = true; | ||||
|                     std::swap(a, b); | ||||
|                     std::swap(a_id, b_id); | ||||
|                 } else | ||||
|                     line_out->edge_type = feBottom; | ||||
|             } | ||||
|             line_out->a = to_2d(swap ? b : a).cast<coord_t>(); | ||||
|             line_out->b = to_2d(swap ? a : b).cast<coord_t>(); | ||||
|             line_out->a_id = swap ? b_id : a_id; | ||||
|             line_out->b_id = swap ? a_id : b_id; | ||||
|             line_out->a.x()  = a->x(); | ||||
|             line_out->a.y()  = a->y(); | ||||
|             line_out->b.x()  = b->x(); | ||||
|             line_out->b.y()  = b->y(); | ||||
|             line_out->a_id   = a_id; | ||||
|             line_out->b_id   = b_id; | ||||
|             assert(line_out->a != line_out->b); | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         if (a(2) == slice_z) { | ||||
|         if (a->z() == slice_z) { | ||||
|             // Only point a alings with the cutting plane.
 | ||||
|             if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != a_id) { | ||||
|                 point_on_layer = num_points; | ||||
|                 IntersectionPoint &point = points[num_points ++]; | ||||
|                 point(0)       = a(0); | ||||
|                 point(1)       = a(1); | ||||
|                 point.point_id  = a_id; | ||||
|                 point.x()      = a->x(); | ||||
|                 point.y()      = a->y(); | ||||
|                 point.point_id = a_id; | ||||
|             } | ||||
|         } else if (b(2) == slice_z) { | ||||
|         } else if (b->z() == slice_z) { | ||||
|             // Only point b alings with the cutting plane.
 | ||||
|             if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != b_id) { | ||||
|                 point_on_layer = num_points; | ||||
|                 IntersectionPoint &point = points[num_points ++]; | ||||
|                 point(0)       = b(0); | ||||
|                 point(1)       = b(1); | ||||
|                 point.point_id  = b_id; | ||||
|                 point.x()      = b->x(); | ||||
|                 point.y()      = b->y(); | ||||
|                 point.point_id = b_id; | ||||
|             } | ||||
|         } else if ((a(2) < slice_z && b(2) > slice_z) || (b(2) < slice_z && a(2) > slice_z)) { | ||||
|         } else if ((a->z() < slice_z && b->z() > slice_z) || (b->z() < slice_z && a->z() > slice_z)) { | ||||
|             // A general case. The face edge intersects the cutting plane. Calculate the intersection point.
 | ||||
|             assert(a_id != b_id); | ||||
|             // Sort the edge to give a consistent answer.
 | ||||
|             const stl_vertex *pa = &a; | ||||
|             const stl_vertex *pb = &b; | ||||
|             if (a_id > b_id) { | ||||
|                 std::swap(a_id, b_id); | ||||
|                 std::swap(pa, pb); | ||||
|                 std::swap(a, b); | ||||
|             } | ||||
|             IntersectionPoint &point = points[num_points]; | ||||
|             double t = (double(slice_z) - double((*pb)(2))) / (double((*pa)(2)) - double((*pb)(2))); | ||||
| 			double t = (double(slice_z) - double(b->z())) / (double(a->z()) - double(b->z())); | ||||
|             if (t <= 0.) { | ||||
|                 if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != a_id) { | ||||
|                     point(0) = (*pa)(0); | ||||
|                     point(1) = (*pa)(1); | ||||
|                     point.x() = a->x(); | ||||
|                     point.y() = a->y(); | ||||
|                     point_on_layer = num_points ++; | ||||
|                     point.point_id = a_id; | ||||
|                 } | ||||
|             } else if (t >= 1.) { | ||||
|                 if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != b_id) { | ||||
|                     point(0) = (*pb)(0); | ||||
|                     point(1) = (*pb)(1); | ||||
|                     point.x() = b->x(); | ||||
|                     point.y() = b->y(); | ||||
|                     point_on_layer = num_points ++; | ||||
|                     point.point_id = b_id; | ||||
|                 } | ||||
|             } else { | ||||
|                 point(0) = coord_t(floor(double((*pb)(0)) + (double((*pa)(0)) - double((*pb)(0))) * t + 0.5)); | ||||
|                 point(1) = coord_t(floor(double((*pb)(1)) + (double((*pa)(1)) - double((*pb)(1))) * t + 0.5)); | ||||
|                 point.x() = coord_t(floor(double(b->x()) + (double(a->x()) - double(b->x())) * t + 0.5)); | ||||
|                 point.y() = coord_t(floor(double(b->y()) + (double(a->y()) - double(b->y())) * t + 0.5)); | ||||
|                 point.edge_id = edge_id; | ||||
|                 ++ num_points; | ||||
|             } | ||||
|  | @ -1140,7 +1046,7 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet( | |||
|             if (i == line_out->a_id || i == line_out->b_id) | ||||
|                 i = vertices[2]; | ||||
|             assert(i != line_out->a_id && i != line_out->b_id); | ||||
|             line_out->edge_type = (this->v_scaled_shared[i].z < slice_z) ? feTop : feBottom; | ||||
|             line_out->edge_type = (this->v_scaled_shared[i].z() < slice_z) ? feTop : feBottom; | ||||
|         } | ||||
| #endif | ||||
|         return Slicing; | ||||
|  | @ -1488,7 +1394,7 @@ static void chain_open_polylines_close_gaps(std::vector<OpenPolyline> &open_poly | |||
|             std::pair<const OpenPolylineEnd*, double> next_start_and_dist = closest_end_point_lookup.find(end.point()); | ||||
|             const OpenPolylineEnd *next_start = next_start_and_dist.first; | ||||
|             // Check whether we closed this loop.
 | ||||
| 			double current_loop_closing_distance2 = (opl->points.back() - opl->points.front()).cast<double>().squaredNorm(); | ||||
|             double current_loop_closing_distance2 = (opl->points.back() - opl->points.front()).cast<double>().squaredNorm(); | ||||
|             bool   loop_closed = current_loop_closing_distance2 < coordf_t(max_gap_scaled) * coordf_t(max_gap_scaled); | ||||
|             if (next_start != nullptr && loop_closed && current_loop_closing_distance2 < next_start_and_dist.second) { | ||||
|                 // Heuristics to decide, whether to close the loop, or connect another polyline.
 | ||||
|  |  | |||
|  | @ -55,7 +55,8 @@ public: | |||
|     TriangleMeshPtrs split() const; | ||||
|     void merge(const TriangleMesh &mesh); | ||||
|     ExPolygons horizontal_projection() const; | ||||
|     const float* first_vertex() const; | ||||
|     const float* first_vertex() const { return this->stl.facet_start ? &this->stl.facet_start->vertex[0](0) : nullptr; } | ||||
|     // 2D convex hull of a 3D mesh projected into the Z=0 plane.
 | ||||
|     Polygon convex_hull(); | ||||
|     BoundingBoxf3 bounding_box() const; | ||||
|     // Returns the bbox of this TriangleMesh transformed by the given transformation
 | ||||
|  | @ -74,7 +75,7 @@ public: | |||
|     // Count disconnected triangle patches.
 | ||||
|     size_t number_of_patches() const; | ||||
| 
 | ||||
|     mutable stl_file stl; | ||||
|     stl_file stl; | ||||
|     bool repaired; | ||||
|      | ||||
| private: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv