mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	WIP: Merged commits from stable between 1.41.2-beta and 1.42.2 final.
Changes in SupportMaterial.cpp, TriangleMesh.cpp and 01_trianglemesh.t are yet to be merged. WIP: Refactoring of layer height editing. Removed layer_height_ranges from PrintObject, as the Print/PrintObject now hold their copies of Model/ModelObject.
This commit is contained in:
		
							parent
							
								
									2ed77aadde
								
							
						
					
					
						commit
						52db7b055a
					
				
					 12 changed files with 231 additions and 40 deletions
				
			
		|  | @ -9,7 +9,9 @@ | |||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| #include "libslic3r.h" | ||||
| #include "ClipperUtils.hpp" | ||||
| #include "EdgeGrid.hpp" | ||||
| #include "SVG.hpp" | ||||
| 
 | ||||
| #if 0 | ||||
| // Enable debugging and assert in this file.
 | ||||
|  | @ -756,8 +758,8 @@ void EdgeGrid::Grid::calculate_sdf() | |||
| 	float search_radius = float(m_resolution<<1); | ||||
| 	m_signed_distance_field.assign(nrows * ncols, search_radius); | ||||
| 	// For each cell:
 | ||||
| 	for (size_t r = 0; r < m_rows; ++ r) { | ||||
| 		for (size_t c = 0; c < m_cols; ++ c) { | ||||
| 	for (int r = 0; r < (int)m_rows; ++ r) { | ||||
| 		for (int c = 0; c < (int)m_cols; ++ c) { | ||||
| 			const Cell &cell = m_cells[r * m_cols + c]; | ||||
| 			// For each segment in the cell:
 | ||||
| 			for (size_t i = cell.begin; i != cell.end; ++ i) { | ||||
|  | @ -842,6 +844,8 @@ void EdgeGrid::Grid::calculate_sdf() | |||
| #if 0 | ||||
| 	static int iRun = 0; | ||||
| 	++ iRun; | ||||
|     if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) | ||||
|         wxImage::AddHandler(new wxPNGHandler); | ||||
| //#ifdef SLIC3R_GUI
 | ||||
| 	{  | ||||
| 		wxImage img(ncols, nrows); | ||||
|  | @ -1356,9 +1360,101 @@ Polygons EdgeGrid::Grid::contours_simplified(coord_t offset, bool fill_holes) co | |||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| inline int segments_could_intersect( | ||||
| 	const Slic3r::Point &ip1, const Slic3r::Point &ip2,  | ||||
| 	const Slic3r::Point &jp1, const Slic3r::Point &jp2) | ||||
| { | ||||
| 	Vec2i64 iv   = (ip2 - ip1).cast<int64_t>(); | ||||
| 	Vec2i64 vij1 = (jp1 - ip1).cast<int64_t>(); | ||||
| 	Vec2i64 vij2 = (jp2 - ip1).cast<int64_t>(); | ||||
| 	int64_t tij1 = cross2(iv, vij1); | ||||
| 	int64_t tij2 = cross2(iv, vij2); | ||||
| 	int     sij1 = (tij1 > 0) ? 1 : ((tij1 < 0) ? -1 : 0); // signum
 | ||||
| 	int     sij2 = (tij2 > 0) ? 1 : ((tij2 < 0) ? -1 : 0); | ||||
| 	return sij1 * sij2; | ||||
| } | ||||
| 
 | ||||
| inline bool segments_intersect( | ||||
| 	const Slic3r::Point &ip1, const Slic3r::Point &ip2,  | ||||
| 	const Slic3r::Point &jp1, const Slic3r::Point &jp2) | ||||
| { | ||||
| 	return segments_could_intersect(ip1, ip2, jp1, jp2) <= 0 &&  | ||||
| 		   segments_could_intersect(jp1, jp2, ip1, ip2) <= 0; | ||||
| } | ||||
| 
 | ||||
| std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>> EdgeGrid::Grid::intersecting_edges() const | ||||
| { | ||||
| 	std::vector<std::pair<ContourEdge, ContourEdge>> out; | ||||
| 	// For each cell:
 | ||||
| 	for (int r = 0; r < (int)m_rows; ++ r) { | ||||
| 		for (int c = 0; c < (int)m_cols; ++ c) { | ||||
| 			const Cell &cell = m_cells[r * m_cols + c]; | ||||
| 			// For each pair of segments in the cell:
 | ||||
| 			for (size_t i = cell.begin; i != cell.end; ++ i) { | ||||
| 				const Slic3r::Points &ipts = *m_contours[m_cell_data[i].first]; | ||||
| 				size_t ipt = m_cell_data[i].second; | ||||
| 				// End points of the line segment and their vector.
 | ||||
| 				const Slic3r::Point &ip1 = ipts[ipt]; | ||||
| 				const Slic3r::Point &ip2 = ipts[(ipt + 1 == ipts.size()) ? 0 : ipt + 1]; | ||||
| 				for (size_t j = i + 1; j != cell.end; ++ j) { | ||||
| 					const Slic3r::Points &jpts = *m_contours[m_cell_data[j].first]; | ||||
| 					size_t 				  jpt  = m_cell_data[j].second; | ||||
| 					// End points of the line segment and their vector.
 | ||||
| 					const Slic3r::Point  &jp1  = jpts[jpt]; | ||||
| 					const Slic3r::Point  &jp2  = jpts[(jpt + 1 == jpts.size()) ? 0 : jpt + 1]; | ||||
| 					if (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2)) | ||||
| 						// Segments of the same contour share a common vertex.
 | ||||
| 						continue; | ||||
| 					if (segments_intersect(ip1, ip2, jp1, jp2)) { | ||||
| 						// The two segments intersect. Add them to the output.
 | ||||
| 						int jfirst = (&jpts < &ipts) || (&jpts == &ipts && jpt < ipt); | ||||
| 						out.emplace_back(jfirst ?  | ||||
| 							std::make_pair(std::make_pair(&ipts, ipt), std::make_pair(&jpts, jpt)) :  | ||||
| 							std::make_pair(std::make_pair(&ipts, ipt), std::make_pair(&jpts, jpt))); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	Slic3r::sort_remove_duplicates(out); | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| bool EdgeGrid::Grid::has_intersecting_edges() const | ||||
| { | ||||
| 	// For each cell:
 | ||||
| 	for (int r = 0; r < (int)m_rows; ++ r) { | ||||
| 		for (int c = 0; c < (int)m_cols; ++ c) { | ||||
| 			const Cell &cell = m_cells[r * m_cols + c]; | ||||
| 			// For each pair of segments in the cell:
 | ||||
| 			for (size_t i = cell.begin; i != cell.end; ++ i) { | ||||
| 				const Slic3r::Points &ipts = *m_contours[m_cell_data[i].first]; | ||||
| 				size_t ipt = m_cell_data[i].second; | ||||
| 				// End points of the line segment and their vector.
 | ||||
| 				const Slic3r::Point &ip1 = ipts[ipt]; | ||||
| 				const Slic3r::Point &ip2 = ipts[(ipt + 1 == ipts.size()) ? 0 : ipt + 1]; | ||||
| 				for (size_t j = i + 1; j != cell.end; ++ j) { | ||||
| 					const Slic3r::Points &jpts = *m_contours[m_cell_data[j].first]; | ||||
| 					size_t 				  jpt  = m_cell_data[j].second; | ||||
| 					// End points of the line segment and their vector.
 | ||||
| 					const Slic3r::Point  &jp1  = jpts[jpt]; | ||||
| 					const Slic3r::Point  &jp2  = jpts[(jpt + 1 == jpts.size()) ? 0 : jpt + 1]; | ||||
| 					if (! (&ipts == &jpts && (&ip1 == &jp2 || &jp1 == &ip2)) &&  | ||||
| 						segments_intersect(ip1, ip2, jp1, jp2)) | ||||
| 						return true; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coord_t resolution, const char *path) | ||||
| { | ||||
|     if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) | ||||
|         wxImage::AddHandler(new wxPNGHandler); | ||||
| 
 | ||||
| 	unsigned int w = (bbox.max(0) - bbox.min(0) + resolution - 1) / resolution; | ||||
| 	unsigned int h = (bbox.max(1) - bbox.min(1) + resolution - 1) / resolution; | ||||
| 	wxImage img(w, h); | ||||
|  | @ -1450,4 +1546,59 @@ void EdgeGrid::save_png(const EdgeGrid::Grid &grid, const BoundingBox &bbox, coo | |||
| } | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| // Find all pairs of intersectiong edges from the set of polygons.
 | ||||
| std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>> intersecting_edges(const Polygons &polygons) | ||||
| { | ||||
| 	double len = 0; | ||||
| 	size_t cnt = 0; | ||||
| 	BoundingBox bbox; | ||||
| 	for (const Polygon &poly : polygons) { | ||||
| 		if (poly.points.size() < 2) | ||||
| 			continue; | ||||
| 		for (size_t i = 0; i < poly.points.size(); ++ i) { | ||||
| 			bbox.merge(poly.points[i]); | ||||
| 			size_t j = (i == 0) ? (poly.points.size() - 1) : i - 1; | ||||
| 			len += (poly.points[j] - poly.points[i]).cast<double>().norm(); | ||||
| 			++ cnt; | ||||
| 		} | ||||
| 	} | ||||
| 	len /= double(cnt); | ||||
| 	bbox.offset(20); | ||||
| 	EdgeGrid::Grid grid; | ||||
| 	grid.set_bbox(bbox); | ||||
| 	grid.create(polygons, len); | ||||
| 	return grid.intersecting_edges(); | ||||
| } | ||||
| 
 | ||||
| // Find all pairs of intersectiong edges from the set of polygons, highlight them in an SVG.
 | ||||
| void export_intersections_to_svg(const std::string &filename, const Polygons &polygons) | ||||
| { | ||||
| 	std::vector<std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge>> intersections = intersecting_edges(polygons); | ||||
|     BoundingBox bbox = get_extents(polygons); | ||||
|     SVG svg(filename.c_str(), bbox); | ||||
|     svg.draw(union_ex(polygons), "gray", 0.25f); | ||||
|     svg.draw_outline(polygons, "black"); | ||||
|     std::set<const Points*> intersecting_contours; | ||||
|     for (const std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge> &ie : intersections) { | ||||
|     	intersecting_contours.insert(ie.first.first); | ||||
|     	intersecting_contours.insert(ie.second.first); | ||||
|     } | ||||
|     // Highlight the contours with intersections.
 | ||||
|     coord_t line_width = coord_t(scale_(0.01)); | ||||
|     for (const Points *ic : intersecting_contours) { | ||||
| 	    svg.draw_outline(Polygon(*ic), "green"); | ||||
| 	    svg.draw_outline(Polygon(*ic), "black", line_width); | ||||
|     } | ||||
| 	// Paint the intersections.
 | ||||
|     for (const std::pair<EdgeGrid::Grid::ContourEdge, EdgeGrid::Grid::ContourEdge> &intersecting_edges : intersections) { | ||||
|     	auto edge = [](const EdgeGrid::Grid::ContourEdge &e) { | ||||
|     		return Line(e.first->at(e.second), | ||||
|     					e.first->at((e.second + 1 == e.first->size()) ? 0 : e.second + 1)); | ||||
|     	}; | ||||
|         svg.draw(edge(intersecting_edges.first), "red", line_width); | ||||
|         svg.draw(edge(intersecting_edges.second), "red", line_width); | ||||
|     } | ||||
|     svg.Close(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ void FillGyroid::_fill_surface_single( | |||
|     // no rotation is supported for this infill pattern (yet)
 | ||||
|     BoundingBox bb = expolygon.contour.bounding_box(); | ||||
|     // Density adjusted to have a good %of weight.
 | ||||
|     double      density_adjusted = std::max(0., params.density * 2.); | ||||
|     double      density_adjusted = std::max(0., params.density * 2.44); | ||||
|     // Distance between the gyroid waves in scaled coordinates.
 | ||||
|     coord_t     distance = coord_t(scale_(this->spacing) / density_adjusted); | ||||
| 
 | ||||
|  |  | |||
|  | @ -545,7 +545,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( | |||
| 	m_print_brim = true; | ||||
| 
 | ||||
|     // Ask our writer about how much material was consumed:
 | ||||
|     m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|     	m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	ToolChangeResult result; | ||||
|     result.priming      = true; | ||||
|  | @ -698,7 +699,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo | |||
|     m_print_brim = false;  // Mark the brim as extruded
 | ||||
| 
 | ||||
|     // Ask our writer about how much material was consumed:
 | ||||
|     m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|     	m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	ToolChangeResult result; | ||||
|     result.priming      = false; | ||||
|  | @ -868,7 +870,8 @@ void WipeTowerPrusaMM::toolchange_Change( | |||
| 	material_type 		new_material) | ||||
| { | ||||
|     // Ask the writer about how much of the old filament we consumed:
 | ||||
|     m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
|     if (m_current_tool < m_used_filament_length.size()) | ||||
|     	m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); | ||||
| 
 | ||||
| 	// Speed override for the material. Go slow for flex and soluble materials.
 | ||||
| 	int speed_override; | ||||
|  |  | |||
|  | @ -521,10 +521,14 @@ void Model::adjust_min_z() | |||
| unsigned int Model::get_auto_extruder_id(unsigned int max_extruders) | ||||
| { | ||||
|     unsigned int id = s_auto_extruder_id; | ||||
| 
 | ||||
|     if (++s_auto_extruder_id > max_extruders) | ||||
|     if (id > max_extruders) { | ||||
|         // The current counter is invalid, likely due to switching the printer profiles
 | ||||
|         // to a profile with a lower number of extruders.
 | ||||
|         reset_auto_extruder_id(); | ||||
| 
 | ||||
|         id = s_auto_extruder_id; | ||||
|     } else if (++ s_auto_extruder_id > max_extruders) { | ||||
|         reset_auto_extruder_id(); | ||||
|     } | ||||
|     return id; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -107,6 +107,23 @@ extern BoundingBox get_extents(const MultiPoint &mp); | |||
| extern BoundingBox get_extents_rotated(const std::vector<Point> &points, double angle); | ||||
| extern BoundingBox get_extents_rotated(const MultiPoint &mp, double angle); | ||||
| 
 | ||||
| inline double length(const Points &pts) { | ||||
|     double total = 0; | ||||
|     if (! pts.empty()) { | ||||
|         auto it = pts.begin(); | ||||
|         for (auto it_prev = it ++; it != pts.end(); ++ it, ++ it_prev) | ||||
|             total += (*it - *it_prev).cast<double>().norm(); | ||||
|     } | ||||
|     return total; | ||||
| } | ||||
| 
 | ||||
| inline double area(const Points &polygon) { | ||||
|     double area = 0.; | ||||
|     for (size_t i = 0, j = polygon.size() - 1; i < polygon.size(); j = i ++) | ||||
| 		area += double(polygon[i](0) + polygon[j](0)) * double(polygon[i](1) - polygon[j](1)); | ||||
|     return area; | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -187,6 +187,24 @@ public: | |||
|             m_map.emplace(std::make_pair(Vec2crd(pt->x()>>m_grid_log2, pt->y()>>m_grid_log2), std::move(value))); | ||||
|     } | ||||
| 
 | ||||
|     // Erase a data point equal to value. (ValueType has to declare the operator==).
 | ||||
|     // Returns true if the data point equal to value was found and removed.
 | ||||
|     bool erase(const ValueType &value) { | ||||
|         const Point *pt = m_point_accessor(value); | ||||
|         if (pt != nullptr) { | ||||
|             // Range of fragment starts around grid_corner, close to pt.
 | ||||
|             auto range = m_map.equal_range(Point(pt->x>>m_grid_log2, pt->y>>m_grid_log2)); | ||||
|             // Remove the first item.
 | ||||
|             for (auto it = range.first; it != range.second; ++ it) { | ||||
|                 if (it->second == value) { | ||||
|                     m_map.erase(it); | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // Return a pair of <ValueType*, distance_squared>
 | ||||
|     std::pair<const ValueType*, double> find(const Vec2crd &pt) { | ||||
|         // Iterate over 4 closest grid cells around pt,
 | ||||
|  | @ -214,7 +232,7 @@ public: | |||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return (value_min != nullptr && dist_min < coordf_t(m_search_radius * m_search_radius)) ?  | ||||
|         return (value_min != nullptr && dist_min < coordf_t(m_search_radius) * coordf_t(m_search_radius)) ?  | ||||
|             std::make_pair(value_min, dist_min) :  | ||||
|             std::make_pair(nullptr, std::numeric_limits<double>::max()); | ||||
|     } | ||||
|  |  | |||
|  | @ -81,8 +81,8 @@ extern BoundingBox get_extents(const Polylines &polylines); | |||
| 
 | ||||
| inline double total_length(const Polylines &polylines) { | ||||
|     double total = 0; | ||||
|     for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it) | ||||
|         total += it->length(); | ||||
|     for (const Polyline &pl : polylines) | ||||
|         total += pl.length(); | ||||
|     return total; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -281,16 +281,17 @@ bool Print::is_step_done(PrintObjectStep step) const | |||
| std::vector<unsigned int> Print::object_extruders() const | ||||
| { | ||||
|     std::vector<unsigned int> extruders; | ||||
|     extruders.reserve(m_regions.size() * 3); | ||||
|      | ||||
|     for (PrintRegion* region : m_regions) { | ||||
|     for (const PrintRegion *region : m_regions) { | ||||
|         // these checks reflect the same logic used in the GUI for enabling/disabling
 | ||||
|         // extruder selection fields
 | ||||
|         if (region->config().perimeters.value > 0 || m_config.brim_width.value > 0) | ||||
|             extruders.push_back(region->config().perimeter_extruder - 1); | ||||
|             extruders.emplace_back(region->config().perimeter_extruder - 1); | ||||
|         if (region->config().fill_density.value > 0) | ||||
|             extruders.push_back(region->config().infill_extruder - 1); | ||||
|             extruders.emplace_back(region->config().infill_extruder - 1); | ||||
|         if (region->config().top_solid_layers.value > 0 || region->config().bottom_solid_layers.value > 0) | ||||
|             extruders.push_back(region->config().solid_infill_extruder - 1); | ||||
|             extruders.emplace_back(region->config().solid_infill_extruder - 1); | ||||
|     } | ||||
|      | ||||
|     sort_remove_duplicates(extruders); | ||||
|  | @ -480,14 +481,6 @@ bool Print::apply_config(DynamicPrintConfig config) | |||
|         PrintObjectConfig new_config = this->default_object_config(); | ||||
|         // we override the new config with object-specific options
 | ||||
|         normalize_and_apply_config(new_config, object->model_object()->config); | ||||
|         // Force a refresh of a variable layer height profile at the PrintObject if it is not valid.
 | ||||
|         if (! object->layer_height_profile_valid) { | ||||
|             // The layer_height_profile is not valid for some reason (updated by the user or invalidated due to some option change).
 | ||||
|             // Invalidate the slicing step, which in turn invalidates everything.
 | ||||
|             object->invalidate_step(posSlice); | ||||
|             // Trigger recalculation.
 | ||||
|             invalidated = true; | ||||
|         } | ||||
|         // check whether the new config is different from the current one
 | ||||
|         t_config_option_keys diff = object->config().diff(new_config); | ||||
|         object->config_apply_only(new_config, diff, true); | ||||
|  | @ -567,8 +560,7 @@ exit_for_rearrange_regions: | |||
| 
 | ||||
|     // Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
 | ||||
|     for (PrintObject *object : m_objects) | ||||
|         if (! object->layer_height_profile_valid) | ||||
|             object->update_layer_height_profile(); | ||||
|         object->update_layer_height_profile(); | ||||
|      | ||||
|     return invalidated; | ||||
| } | ||||
|  | @ -1141,6 +1133,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co | |||
|     // Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
 | ||||
|     for (PrintObject *object : m_objects) | ||||
|         if (! object->layer_height_profile_valid) | ||||
|             // No need to call the next line as the step should already be invalidated above.
 | ||||
|             // update_apply_status(object->invalidate_step(posSlice));
 | ||||
|             object->update_layer_height_profile(); | ||||
| 
 | ||||
|     //FIXME there may be a race condition with the G-code export running at the background thread.
 | ||||
|  | @ -1165,6 +1159,7 @@ bool Print::has_skirt() const | |||
|         || this->has_infinite_skirt(); | ||||
| } | ||||
| 
 | ||||
| // Precondition: Print::validate() requires the Print::apply() to be called its invocation.
 | ||||
| std::string Print::validate() const | ||||
| { | ||||
|     if (m_objects.empty()) | ||||
|  | @ -1253,12 +1248,10 @@ std::string Print::validate() const | |||
|                 return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance"); | ||||
|             if (! equal_layering(slicing_params, slicing_params0)) | ||||
|                 return L("The Wipe Tower is only supported for multiple objects if they are sliced equally."); | ||||
|             bool was_layer_height_profile_valid = object->layer_height_profile_valid; | ||||
|             object->update_layer_height_profile(); | ||||
|             object->layer_height_profile_valid = was_layer_height_profile_valid; | ||||
| 
 | ||||
|             if ( m_config.variable_layer_height ) { // comparing layer height profiles
 | ||||
|                 bool failed = false; | ||||
|                 // layer_height_profile should be set by Print::apply().
 | ||||
|                 if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size() ) { | ||||
|                     int i = 0; | ||||
|                     while ( i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) { | ||||
|  |  | |||
|  | @ -78,7 +78,6 @@ private: // Prevents erroneous use by other classes. | |||
| public: | ||||
|     // vector of (vectors of volume ids), indexed by region_id
 | ||||
|     std::vector<std::vector<int>> region_volumes; | ||||
|     t_layer_height_ranges   layer_height_ranges; | ||||
| 
 | ||||
|     // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
 | ||||
|     // The pairs of <z, layer_height> are packed into a 1D array to simplify handling by the Perl XS.
 | ||||
|  |  | |||
|  | @ -65,7 +65,6 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta | |||
|         this->set_copies(copies); | ||||
|     } | ||||
| 
 | ||||
|     this->layer_height_ranges = model_object->layer_height_ranges; | ||||
|     this->layer_height_profile = model_object->layer_height_profile; | ||||
| } | ||||
| 
 | ||||
|  | @ -1109,7 +1108,7 @@ void PrintObject::discover_vertical_shells() | |||
| #if 1 | ||||
|                     // Intentionally inflate a bit more than how much the region has been shrunk, 
 | ||||
|                     // so there will be some overlap between this solid infill and the other infill regions (mainly the sparse infill).
 | ||||
|                     shell = offset2(shell, - 0.5f * min_perimeter_infill_spacing, 0.8f * min_perimeter_infill_spacing, ClipperLib::jtSquare); | ||||
|                     shell = offset(offset_ex(union_ex(shell), - 0.5f * min_perimeter_infill_spacing), 0.8f * min_perimeter_infill_spacing, ClipperLib::jtSquare); | ||||
|                     if (shell.empty()) | ||||
|                         continue; | ||||
| #else | ||||
|  | @ -1330,7 +1329,7 @@ bool PrintObject::update_layer_height_profile(std::vector<coordf_t> &layer_heigh | |||
|     bool updated = false; | ||||
| 
 | ||||
|     // If the layer height profile is not set, try to use the one stored at the ModelObject.
 | ||||
|     if (layer_height_profile.empty() && layer_height_profile.data() != this->model_object()->layer_height_profile.data()) { | ||||
|     if (layer_height_profile.empty()) { | ||||
|         layer_height_profile = this->model_object()->layer_height_profile; | ||||
|         updated = true; | ||||
|     } | ||||
|  | @ -1347,10 +1346,9 @@ bool PrintObject::update_layer_height_profile(std::vector<coordf_t> &layer_heigh | |||
|     if (layer_height_profile.empty()) { | ||||
|         if (0) | ||||
| //        if (this->layer_height_profile.empty())
 | ||||
|             layer_height_profile = layer_height_profile_adaptive(slicing_params, this->layer_height_ranges, | ||||
|                 this->model_object()->volumes); | ||||
| 			layer_height_profile = layer_height_profile_adaptive(slicing_params, this->model_object()->layer_height_ranges, this->model_object()->volumes); | ||||
|         else | ||||
|             layer_height_profile = layer_height_profile_from_ranges(slicing_params, this->layer_height_ranges); | ||||
| 			layer_height_profile = layer_height_profile_from_ranges(slicing_params, this->model_object()->layer_height_ranges); | ||||
|         updated = true; | ||||
|     } | ||||
|     return updated; | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ | |||
| #include <boost/property_tree/ini_parser.hpp> | ||||
| #include <boost/property_tree/ptree.hpp> | ||||
| #include <boost/algorithm/string/predicate.hpp> | ||||
| #include <boost/format.hpp> | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -125,8 +126,13 @@ void AppConfig::load() | |||
| 
 | ||||
| void AppConfig::save() | ||||
| { | ||||
|     // The config is first written to a file with a PID suffix and then moved
 | ||||
|     // to avoid race conditions with multiple instances of Slic3r
 | ||||
|     const auto path = config_path(); | ||||
|     std::string path_pid = (boost::format("%1%.%2%") % path % get_current_pid()).str(); | ||||
| 
 | ||||
|     boost::nowide::ofstream c; | ||||
|     c.open(AppConfig::config_path(), std::ios::out | std::ios::trunc); | ||||
|     c.open(path_pid, std::ios::out | std::ios::trunc); | ||||
|     c << "# " << Slic3r::header_slic3r_generated() << std::endl; | ||||
|     // Make sure the "no" category is written first.
 | ||||
|     for (const std::pair<std::string, std::string> &kvp : m_storage[""]) | ||||
|  | @ -155,6 +161,8 @@ void AppConfig::save() | |||
|         } | ||||
|     } | ||||
|     c.close(); | ||||
| 
 | ||||
|     rename_file(path_pid, path); | ||||
|     m_dirty = false; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -323,17 +323,17 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : | |||
|                 double brim_width = config->opt_float("brim_width"); | ||||
|                 if (boost::any_cast<bool>(value) == true) | ||||
|                 { | ||||
|                     new_val = m_brim_width == 0.0 ? 10 : | ||||
|                     new_val = m_brim_width == 0.0 ? 5 : | ||||
|                         m_brim_width < 0.0 ? m_brim_width * (-1) : | ||||
|                         m_brim_width; | ||||
|                 } | ||||
|                 else{ | ||||
|                 else { | ||||
|                     m_brim_width = brim_width * (-1); | ||||
|                     new_val = 0; | ||||
|                 } | ||||
|                 new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); | ||||
|             } | ||||
|             else{ //(opt_key == "support")
 | ||||
|             else { //(opt_key == "support")
 | ||||
|                 const wxString& selection = boost::any_cast<wxString>(value); | ||||
| 
 | ||||
|                 auto support_material = selection == _("None") ? false : true; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv