mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	Added clipping of finite Voronoi edges that have coordinates that don't fit inside type coord_t.
This commit is contained in:
		
							parent
							
								
									93b86da770
								
							
						
					
					
						commit
						b16aada962
					
				
					 1 changed files with 59 additions and 32 deletions
				
			
		|  | @ -5,6 +5,7 @@ | |||
| #include "Print.hpp" | ||||
| #include "VoronoiVisualUtils.hpp" | ||||
| #include "MutablePolygon.hpp" | ||||
| #include "format.hpp" | ||||
| 
 | ||||
| #include <utility> | ||||
| #include <cfloat> | ||||
|  | @ -502,11 +503,13 @@ static std::vector<std::vector<ColoredLine>> colorize_polygons(const std::vector | |||
| 
 | ||||
| using boost::polygon::voronoi_diagram; | ||||
| 
 | ||||
| static inline Point mk_point(const Voronoi::VD::vertex_type *point) { return Point(coord_t(point->x()), coord_t(point->y())); } | ||||
| static inline Point mk_point(const Voronoi::VD::vertex_type *point) { return {coord_t(point->x()), coord_t(point->y())}; } | ||||
| 
 | ||||
| static inline Point mk_point(const Voronoi::Internal::point_type &point) { return Point(coord_t(point.x()), coord_t(point.y())); } | ||||
| static inline Point mk_point(const Voronoi::Internal::point_type &point) { return {coord_t(point.x()), coord_t(point.y())}; } | ||||
| 
 | ||||
| static inline Point mk_point(const voronoi_diagram<double>::vertex_type &point) { return Point(coord_t(point.x()), coord_t(point.y())); } | ||||
| static inline Point mk_point(const voronoi_diagram<double>::vertex_type &point) { return {coord_t(point.x()), coord_t(point.y())}; } | ||||
| 
 | ||||
| static inline Vec2d mk_vec2(const voronoi_diagram<double>::vertex_type *point) { return {point->x(), point->y()}; } | ||||
| 
 | ||||
| struct MMU_Graph | ||||
| { | ||||
|  | @ -796,6 +799,27 @@ static inline void init_polygon_indices(const MMU_Graph | |||
|     } | ||||
| } | ||||
| 
 | ||||
| // Voronoi edges produced by Voronoi generator cloud have coordinates that don't fit inside coord_t (int32_t).
 | ||||
| // Because of that, this function tries to clip edges that have one endpoint of the edge inside the BoundingBox.
 | ||||
| static inline Line clip_finite_voronoi_edge(const Voronoi::VD::edge_type &edge, const BoundingBoxf &bbox) | ||||
| { | ||||
|     assert(edge.is_finite()); | ||||
|     Vec2d v0          = mk_vec2(edge.vertex0()); | ||||
|     Vec2d v1          = mk_vec2(edge.vertex1()); | ||||
|     bool  contains_v0 = bbox.contains(v0); | ||||
|     bool  contains_v1 = bbox.contains(v1); | ||||
|     if ((contains_v0 && contains_v1) || (!contains_v0 && !contains_v1)) | ||||
|         return {mk_point(edge.vertex0()), mk_point(edge.vertex1())}; | ||||
| 
 | ||||
|     Vec2d vector = (v1 - v0).normalized() * bbox.size().norm(); | ||||
|     if (!contains_v0) | ||||
|         v0 = (v1 - vector); | ||||
|     else | ||||
|         v1 = (v0 + vector); | ||||
| 
 | ||||
|     return {v0.cast<coord_t>(), v1.cast<coord_t>()}; | ||||
| } | ||||
| 
 | ||||
| static MMU_Graph build_graph(size_t layer_idx, const std::vector<std::vector<ColoredLine>> &color_poly) | ||||
| { | ||||
|     Geometry::VoronoiDiagram vd; | ||||
|  | @ -852,7 +876,8 @@ static MMU_Graph build_graph(size_t layer_idx, const std::vector<std::vector<Col | |||
|     }; | ||||
| 
 | ||||
|     bbox.offset(scale_(10.)); | ||||
|     const double bbox_dim_max = double(std::max(bbox.size().x(), bbox.size().y())); | ||||
|     const BoundingBoxf bbox_clip(bbox.min.cast<double>(), bbox.max.cast<double>()); | ||||
|     const double       bbox_dim_max = double(std::max(bbox.size().x(), bbox.size().y())); | ||||
| 
 | ||||
|     // Make a copy of the input segments with the double type.
 | ||||
|     std::vector<Voronoi::Internal::segment_type> segments; | ||||
|  | @ -890,72 +915,74 @@ static MMU_Graph build_graph(size_t layer_idx, const std::vector<std::vector<Col | |||
|                 } | ||||
|             } | ||||
|         } else if (edge_it->is_finite()) { | ||||
|             const Point  v0       = mk_point(edge_it->vertex0()); | ||||
|             const Point  v1       = mk_point(edge_it->vertex1()); | ||||
|             const size_t from_idx = edge_it->vertex0()->color(); | ||||
|             const size_t to_idx   = edge_it->vertex1()->color(); | ||||
| 
 | ||||
|             // Both points are on contour, so skip them. In cases of duplicate Voronoi vertices, skip edges between the same two points.
 | ||||
|             if (graph.is_edge_connecting_two_contour_vertices(edge_it) || (edge_it->vertex0()->color() == edge_it->vertex1()->color())) continue; | ||||
|             if (graph.is_edge_connecting_two_contour_vertices(edge_it) || (edge_it->vertex0()->color() == edge_it->vertex1()->color())) | ||||
|                 continue; | ||||
| 
 | ||||
|             const Line        edge_line(v0, v1); | ||||
|             const Line        edge_line         = clip_finite_voronoi_edge(*edge_it, bbox_clip); | ||||
|             const Line        contour_line      = lines_colored[edge_it->cell()->source_index()].line; | ||||
|             const ColoredLine colored_line      = lines_colored[edge_it->cell()->source_index()]; | ||||
|             const ColoredLine contour_line_prev = get_prev_contour_line(edge_it); | ||||
|             const ColoredLine contour_line_next = get_next_contour_line(edge_it); | ||||
| 
 | ||||
|             Point intersection; | ||||
|             if (edge_it->vertex0()->color() >= graph.nodes_count() || edge_it->vertex1()->color() >= graph.nodes_count()) { | ||||
| //                if(edge_it->vertex0()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex0())) {
 | ||||
| //
 | ||||
| //                }
 | ||||
|                 if (edge_it->vertex1()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex1())) { | ||||
|                     Line contour_line_twin = lines_colored[edge_it->twin()->cell()->source_index()].line; | ||||
|                 enum class Vertex { VERTEX0, VERTEX1 }; | ||||
|                 auto append_edge_if_intersects_with_contour = [&graph, &lines_colored, &edge_line, &contour_line](const voronoi_diagram<double>::const_edge_iterator &edge_iterator, const Vertex vertex) { | ||||
|                     Point intersection; | ||||
|                     Line  contour_line_twin = lines_colored[edge_iterator->twin()->cell()->source_index()].line; | ||||
|                     if (line_intersection_with_epsilon(contour_line_twin, edge_line, &intersection)) { | ||||
|                         const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_it->twin()->cell()->source_index()); | ||||
|                         const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_iterator->twin()->cell()->source_index()); | ||||
|                         const size_t          to_idx_l  = is_point_closer_to_beginning_of_line(contour_line_twin, intersection) ? graph_arc.from_idx : | ||||
|                                                                                                                                   graph_arc.to_idx; | ||||
|                         graph.append_edge(edge_it->vertex1()->color(), to_idx_l); | ||||
|                         graph.append_edge(vertex == Vertex::VERTEX0 ? edge_iterator->vertex0()->color() : edge_iterator->vertex1()->color(), to_idx_l); | ||||
|                     } else if (line_intersection_with_epsilon(contour_line, edge_line, &intersection)) { | ||||
|                         const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_it->cell()->source_index()); | ||||
|                         const MMU_Graph::Arc &graph_arc = graph.get_border_arc(edge_iterator->cell()->source_index()); | ||||
|                         const size_t to_idx_l = is_point_closer_to_beginning_of_line(contour_line, intersection) ? graph_arc.from_idx : graph_arc.to_idx; | ||||
|                         graph.append_edge(edge_it->vertex1()->color(), to_idx_l); | ||||
|                         graph.append_edge(vertex == Vertex::VERTEX0 ? edge_iterator->vertex0()->color() : edge_iterator->vertex1()->color(), to_idx_l); | ||||
|                     } | ||||
|                     mark_processed(edge_it); | ||||
|                 } | ||||
|                     mark_processed(edge_iterator); | ||||
|                 }; | ||||
| 
 | ||||
|                 if (edge_it->vertex0()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex0())) | ||||
|                     append_edge_if_intersects_with_contour(edge_it, Vertex::VERTEX0); | ||||
| 
 | ||||
|                 if (edge_it->vertex1()->color() < graph.nodes_count() && !graph.is_vertex_on_contour(edge_it->vertex1())) | ||||
|                     append_edge_if_intersects_with_contour(edge_it, Vertex::VERTEX1); | ||||
|             } else if (graph.is_edge_attach_to_contour(edge_it)) { | ||||
|                 mark_processed(edge_it); | ||||
|                 // Skip edges witch connection two points on a contour
 | ||||
|                 if (graph.is_edge_connecting_two_contour_vertices(edge_it)) | ||||
|                     continue; | ||||
| 
 | ||||
|                 const size_t from_idx = edge_it->vertex0()->color(); | ||||
|                 const size_t to_idx   = edge_it->vertex1()->color(); | ||||
|                 if (graph.is_vertex_on_contour(edge_it->vertex0())) { | ||||
|                     if (is_point_closer_to_beginning_of_line(contour_line, v0)) { | ||||
|                         if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, v1)) { | ||||
|                     if (is_point_closer_to_beginning_of_line(contour_line, edge_line.a)) { | ||||
|                         if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, edge_line.b)) { | ||||
|                             graph.append_edge(from_idx, to_idx); | ||||
|                             force_edge_adding[colored_line.poly_idx] = false; | ||||
|                         } | ||||
|                     } else { | ||||
|                         if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, v1)) { | ||||
|                         if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, edge_line.b)) { | ||||
|                             graph.append_edge(from_idx, to_idx); | ||||
|                             force_edge_adding[colored_line.poly_idx] = false; | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|                     assert(graph.is_vertex_on_contour(edge_it->vertex1())); | ||||
|                     if (is_point_closer_to_beginning_of_line(contour_line, v1)) { | ||||
|                         if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, v0)) { | ||||
|                     if (is_point_closer_to_beginning_of_line(contour_line, edge_line.b)) { | ||||
|                         if ((!has_same_color(contour_line_prev, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line_prev.line, contour_line, edge_line.a)) { | ||||
|                             graph.append_edge(from_idx, to_idx); | ||||
|                             force_edge_adding[colored_line.poly_idx] = false; | ||||
|                         } | ||||
|                     } else { | ||||
|                         if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, v0)) { | ||||
|                         if ((!has_same_color(contour_line_next, colored_line) || force_edge_adding[colored_line.poly_idx]) && points_inside(contour_line, contour_line_next.line, edge_line.a)) { | ||||
|                             graph.append_edge(from_idx, to_idx); | ||||
|                             force_edge_adding[colored_line.poly_idx] = false; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } else if (line_intersection_with_epsilon(contour_line, edge_line, &intersection)) { | ||||
|             } else if (Point intersection; line_intersection_with_epsilon(contour_line, edge_line, &intersection)) { | ||||
|                 mark_processed(edge_it); | ||||
|                 Point real_v0 = graph.nodes[edge_it->vertex0()->color()].point; | ||||
|                 Point real_v1 = graph.nodes[edge_it->vertex1()->color()].point; | ||||
|  | @ -1202,7 +1229,7 @@ static void cut_segmented_layers(const std::vector<ExPolygons> | |||
|     BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - end"; | ||||
| } | ||||
| 
 | ||||
| // #define MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
 | ||||
| //#define MMU_SEGMENTATION_DEBUG_TOP_BOTTOM
 | ||||
| 
 | ||||
| // Returns MMU segmentation of top and bottom layers based on painting in MMU segmentation gizmo
 | ||||
| static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bottom_layers(const PrintObject             &print_object, | ||||
|  | @ -1671,7 +1698,7 @@ static void export_regions_to_svg(const std::string &path, const std::vector<std | |||
| 
 | ||||
|     svg.draw_outline(lslices, "green", "lime", stroke_width); | ||||
|     for (const std::pair<ExPolygon, size_t> ®ion : regions) { | ||||
|         int region_color = region.second; | ||||
|         int region_color = int(region.second); | ||||
|         if (region_color >= 0 && region_color < int(colors.size())) | ||||
|             svg.draw(region.first, colors[region_color]); | ||||
|         else | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukáš Hejl
						Lukáš Hejl