mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Merge branch 'tm_arrange_bugfixes'
This commit is contained in:
		
						commit
						b0e5dda489
					
				
					 5 changed files with 57 additions and 17 deletions
				
			
		|  | @ -167,6 +167,8 @@ struct NfpPConfig { | ||||||
|                        const ItemGroup&              // remaining items
 |                        const ItemGroup&              // remaining items
 | ||||||
|                        )> before_packing; |                        )> before_packing; | ||||||
| 
 | 
 | ||||||
|  |     std::function<void(const ItemGroup &, NfpPConfig &config)> on_preload; | ||||||
|  | 
 | ||||||
|     NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}), |     NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}), | ||||||
|         alignment(Alignment::CENTER), starting_point(Alignment::CENTER) {} |         alignment(Alignment::CENTER), starting_point(Alignment::CENTER) {} | ||||||
| }; | }; | ||||||
|  | @ -577,6 +579,12 @@ public: | ||||||
|         Base::clearItems(); |         Base::clearItems(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void preload(const ItemGroup& packeditems) { | ||||||
|  |         Base::preload(packeditems); | ||||||
|  |         if (config_.on_preload) | ||||||
|  |             config_.on_preload(packeditems, config_); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 
 | 
 | ||||||
|     using Shapes = TMultiShape<RawShape>; |     using Shapes = TMultiShape<RawShape>; | ||||||
|  |  | ||||||
|  | @ -109,6 +109,7 @@ void fill_config(PConf& pcfg, const ArrangeParams ¶ms) { | ||||||
| 
 | 
 | ||||||
| // Apply penalty to object function result. This is used only when alignment
 | // Apply penalty to object function result. This is used only when alignment
 | ||||||
| // after arrange is explicitly disabled (PConfig::Alignment::DONT_ALIGN)
 | // after arrange is explicitly disabled (PConfig::Alignment::DONT_ALIGN)
 | ||||||
|  | // Also, this will only work well for Box shaped beds.
 | ||||||
| static double fixed_overfit(const std::tuple<double, Box>& result, const Box &binbb) | static double fixed_overfit(const std::tuple<double, Box>& result, const Box &binbb) | ||||||
| { | { | ||||||
|     double score = std::get<0>(result); |     double score = std::get<0>(result); | ||||||
|  | @ -348,6 +349,17 @@ public: | ||||||
|          |          | ||||||
|         m_pconf.object_function = get_objfn(); |         m_pconf.object_function = get_objfn(); | ||||||
| 
 | 
 | ||||||
|  |         m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) { | ||||||
|  |             if (items.empty()) return; | ||||||
|  | 
 | ||||||
|  |             cfg.alignment = PConfig::Alignment::DONT_ALIGN; | ||||||
|  |             auto bb = sl::boundingBox(m_bin); | ||||||
|  |             auto bbcenter = bb.center(); | ||||||
|  |             cfg.object_function = [this, bb, bbcenter](const Item &item) { | ||||||
|  |                 return fixed_overfit(objfunc(item, bbcenter), bb); | ||||||
|  |             }; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|         auto on_packed = params.on_packed; |         auto on_packed = params.on_packed; | ||||||
|          |          | ||||||
|         if (progressind || on_packed) |         if (progressind || on_packed) | ||||||
|  | @ -384,13 +396,6 @@ public: | ||||||
|     const PConfig& config() const { return m_pconf; } |     const PConfig& config() const { return m_pconf; } | ||||||
|      |      | ||||||
|     inline void preload(std::vector<Item>& fixeditems) { |     inline void preload(std::vector<Item>& fixeditems) { | ||||||
|         m_pconf.alignment = PConfig::Alignment::DONT_ALIGN; |  | ||||||
|         auto bb = sl::boundingBox(m_bin); |  | ||||||
|         auto bbcenter = bb.center(); |  | ||||||
|         m_pconf.object_function = [this, bb, bbcenter](const Item &item) { |  | ||||||
|             return fixed_overfit(objfunc(item, bbcenter), bb); |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         // Build the rtree for queries to work
 |         // Build the rtree for queries to work
 | ||||||
|          |          | ||||||
|         for(unsigned idx = 0; idx < fixeditems.size(); ++idx) { |         for(unsigned idx = 0; idx < fixeditems.size(); ++idx) { | ||||||
|  | @ -398,7 +403,6 @@ public: | ||||||
|             itm.markAsFixedInBin(itm.binId()); |             itm.markAsFixedInBin(itm.binId()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         m_pck.configure(m_pconf); |  | ||||||
|         m_item_count += fixeditems.size(); |         m_item_count += fixeditems.size(); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -62,6 +62,15 @@ struct ArrangePolygon { | ||||||
| 
 | 
 | ||||||
|     /// Test if arrange() was called previously and gave a successful result.
 |     /// Test if arrange() was called previously and gave a successful result.
 | ||||||
|     bool is_arranged() const { return bed_idx != UNARRANGED; } |     bool is_arranged() const { return bed_idx != UNARRANGED; } | ||||||
|  | 
 | ||||||
|  |     inline ExPolygon transformed_poly() const | ||||||
|  |     { | ||||||
|  |         ExPolygon ret = poly; | ||||||
|  |         ret.rotate(rotation); | ||||||
|  |         ret.translate(translation.x(), translation.y()); | ||||||
|  | 
 | ||||||
|  |         return ret; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| using ArrangePolygons = std::vector<ArrangePolygon>; | using ArrangePolygons = std::vector<ArrangePolygon>; | ||||||
|  |  | ||||||
|  | @ -53,6 +53,9 @@ public: | ||||||
|         return point(0) >= this->min(0) && point(0) <= this->max(0) |         return point(0) >= this->min(0) && point(0) <= this->max(0) | ||||||
|             && point(1) >= this->min(1) && point(1) <= this->max(1); |             && point(1) >= this->min(1) && point(1) <= this->max(1); | ||||||
|     } |     } | ||||||
|  |     bool contains(const BoundingBoxBase<PointClass> &other) const { | ||||||
|  |         return contains(other.min) && contains(other.max); | ||||||
|  |     } | ||||||
|     bool overlap(const BoundingBoxBase<PointClass> &other) const { |     bool overlap(const BoundingBoxBase<PointClass> &other) const { | ||||||
|         return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) || |         return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) || | ||||||
|                   this->max(1) < other.min(1) || this->min(1) > other.max(1)); |                   this->max(1) < other.min(1) || this->min(1) > other.max(1)); | ||||||
|  |  | ||||||
|  | @ -29,7 +29,9 @@ void FillBedJob::prepare() | ||||||
|     for (ModelInstance *inst : model_object->instances) |     for (ModelInstance *inst : model_object->instances) | ||||||
|         if (inst->printable) { |         if (inst->printable) { | ||||||
|             ArrangePolygon ap = get_arrange_poly(PtrWrapper{inst}, m_plater); |             ArrangePolygon ap = get_arrange_poly(PtrWrapper{inst}, m_plater); | ||||||
|             ++ap.priority; // need to be included in the result
 |             // Existing objects need to be included in the result. Only
 | ||||||
|  |             // the needed amount of object will be added, no more.
 | ||||||
|  |             ++ap.priority; | ||||||
|             m_selected.emplace_back(ap); |             m_selected.emplace_back(ap); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -38,11 +40,18 @@ void FillBedJob::prepare() | ||||||
|     m_bedpts = get_bed_shape(*m_plater->config()); |     m_bedpts = get_bed_shape(*m_plater->config()); | ||||||
| 
 | 
 | ||||||
|     auto &objects = m_plater->model().objects; |     auto &objects = m_plater->model().objects; | ||||||
|  |     BoundingBox bedbb = get_extents(m_bedpts); | ||||||
|  | 
 | ||||||
|     for (size_t idx = 0; idx < objects.size(); ++idx) |     for (size_t idx = 0; idx < objects.size(); ++idx) | ||||||
|         if (int(idx) != m_object_idx) |         if (int(idx) != m_object_idx) | ||||||
|             for (ModelInstance *mi : objects[idx]->instances) { |             for (ModelInstance *mi : objects[idx]->instances) { | ||||||
|                 m_unselected.emplace_back(get_arrange_poly(PtrWrapper{mi}, m_plater)); |                 ArrangePolygon ap = get_arrange_poly(PtrWrapper{mi}, m_plater); | ||||||
|                 m_unselected.back().bed_idx = 0; |                 auto ap_bb = ap.transformed_poly().contour.bounding_box(); | ||||||
|  | 
 | ||||||
|  |                 if (ap.bed_idx == 0 && !bedbb.contains(ap_bb)) | ||||||
|  |                     ap.bed_idx = arrangement::UNARRANGED; | ||||||
|  | 
 | ||||||
|  |                 m_unselected.emplace_back(ap); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|     if (auto wt = get_wipe_tower_arrangepoly(*m_plater)) |     if (auto wt = get_wipe_tower_arrangepoly(*m_plater)) | ||||||
|  | @ -55,18 +64,17 @@ void FillBedJob::prepare() | ||||||
|     double unsel_area = std::accumulate(m_unselected.begin(), |     double unsel_area = std::accumulate(m_unselected.begin(), | ||||||
|                                         m_unselected.end(), 0., |                                         m_unselected.end(), 0., | ||||||
|                                         [](double s, const auto &ap) { |                                         [](double s, const auto &ap) { | ||||||
|                                             return s + ap.poly.area(); |                                             return s + (ap.bed_idx == 0) * ap.poly.area(); | ||||||
|                                         }) / sc; |                                         }) / sc; | ||||||
| 
 | 
 | ||||||
|     double fixed_area = unsel_area + m_selected.size() * poly_area; |     double fixed_area = unsel_area + m_selected.size() * poly_area; | ||||||
| 
 |  | ||||||
|     // This is the maximum range, the real number will always be close but less.
 |  | ||||||
|     double bed_area   = Polygon{m_bedpts}.area() / sc; |     double bed_area   = Polygon{m_bedpts}.area() / sc; | ||||||
| 
 | 
 | ||||||
|     m_status_range = (bed_area - fixed_area) / poly_area; |     // This is the maximum number of items, the real number will always be close but less.
 | ||||||
|  |     int needed_items = (bed_area - fixed_area) / poly_area; | ||||||
| 
 | 
 | ||||||
|     ModelInstance *mi = model_object->instances[0]; |     ModelInstance *mi = model_object->instances[0]; | ||||||
|     for (int i = 0; i < m_status_range; ++i) { |     for (int i = 0; i < needed_items; ++i) { | ||||||
|         ArrangePolygon ap; |         ArrangePolygon ap; | ||||||
|         ap.poly = m_selected.front().poly; |         ap.poly = m_selected.front().poly; | ||||||
|         ap.bed_idx = arrangement::UNARRANGED; |         ap.bed_idx = arrangement::UNARRANGED; | ||||||
|  | @ -77,6 +85,14 @@ void FillBedJob::prepare() | ||||||
|         }; |         }; | ||||||
|         m_selected.emplace_back(ap); |         m_selected.emplace_back(ap); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     m_status_range = m_selected.size(); | ||||||
|  | 
 | ||||||
|  |     // The strides have to be removed from the fixed items. For the
 | ||||||
|  |     // arrangeable (selected) items bed_idx is ignored and the
 | ||||||
|  |     // translation is irrelevant.
 | ||||||
|  |     double stride = bed_stride(m_plater); | ||||||
|  |     for (auto &p : m_unselected) p.translation(X) -= p.bed_idx * stride; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FillBedJob::process() | void FillBedJob::process() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 tamasmeszaros
						tamasmeszaros