Put together final_shape and flag final shape is healed.

+ Regenerate final shape on reload from disk
This commit is contained in:
Filip Sykala - NTB T15p 2023-11-02 08:00:29 +01:00
parent 8b8f161dce
commit 4bfcbdb019
5 changed files with 40 additions and 53 deletions

View File

@ -1263,17 +1263,14 @@ HealedExPolygons union_with_delta(const ExPolygonsWithIds &shapes, float delta,
ExPolygons Slic3r::union_with_delta(EmbossShape &shape, float delta, unsigned max_heal_iteration)
{
if (!shape.final_shape.empty())
if (!shape.final_shape.expolygons.empty())
return shape.final_shape;
HealedExPolygons result = ::union_with_delta(shape.shapes_with_ids, delta, max_heal_iteration);
shape.is_healed = result.is_healed;
shape.final_shape = ::union_with_delta(shape.shapes_with_ids, delta, max_heal_iteration);
for (const ExPolygonsWithId &e : shape.shapes_with_ids)
if (!e.is_healed)
shape.is_healed = false;
shape.final_shape = std::move(result.expolygons); // cached
return shape.final_shape;
shape.final_shape.is_healed = false;
return shape.final_shape.expolygons;
}
void Slic3r::translate(ExPolygonsWithIds &expolygons_with_ids, const Point &p)

View File

@ -18,13 +18,6 @@
namespace Slic3r {
// Extend expolygons with information whether it was successfull healed
struct HealedExPolygons{
ExPolygons expolygons;
bool is_healed;
operator ExPolygons&() { return expolygons; }
};
/// <summary>
/// class with only static function add ability to engraved OR raised
/// text OR polygons onto model surface

View File

@ -16,8 +16,7 @@
namespace Slic3r {
struct EmbossProjection
{
struct EmbossProjection{
// Emboss depth, Size in local Z direction
double depth = 1.; // [in loacal mm]
// NOTE: User should see and modify mainly world size not local
@ -25,22 +24,6 @@ struct EmbossProjection
// Flag that result volume use surface cutted from source objects
bool use_surface = false;
// enum class Align {
// left,
// right,
// center,
// top_left,
// top_right,
// top_center,
// bottom_left,
// bottom_right,
// bottom_center
// };
//// change pivot of volume
//// When not set, center is used and is not stored
// std::optional<Align> align;
// compare TextStyle
bool operator==(const EmbossProjection &other) const {
return depth == other.depth && use_surface == other.use_surface;
}
@ -49,6 +32,13 @@ struct EmbossProjection
template<class Archive> void serialize(Archive &ar) { ar(depth, use_surface); }
};
// Extend expolygons with information whether it was successfull healed
struct HealedExPolygons{
ExPolygons expolygons;
bool is_healed;
operator ExPolygons&() { return expolygons; }
};
// Help structure to identify expolygons grups
// e.g. emboss -> per glyph -> identify character
struct ExPolygonsWithId
@ -74,7 +64,12 @@ struct EmbossShape
{
// shapes to to emboss separately over surface
ExPolygonsWithIds shapes_with_ids;
ExPolygons final_shape; // When not set it is calculated from ExPolygonsWithIds
// Only cache for final shape
// It is calculated from ExPolygonsWithIds
// Flag is_healed --> whether union of shapes is healed
// Healed mean without selfintersection and point duplication
HealedExPolygons final_shape;
// scale of shape, multiplier to get 3d point in mm from integer shape
double scale = SCALING_FACTOR;
@ -124,29 +119,25 @@ struct EmbossShape
// When embossing shape is made by svg file this is source data
std::optional<SvgFile> svg_file;
// flag whether during cration of union expolygon final shape was fully correct
// correct mean without selfintersection and duplicate(double) points
bool is_healed = true;
// undo / redo stack recovery
template<class Archive> void save(Archive &ar) const
{
// final_shape is not neccessary to store - it is only cache
ar(shapes_with_ids, scale, projection, is_healed, svg_file);
ar(shapes_with_ids, final_shape, scale, projection, svg_file);
cereal::save(ar, fix_3mf_tr);
}
template<class Archive> void load(Archive &ar)
{
ar(shapes_with_ids, scale, projection, is_healed, svg_file);
ar(shapes_with_ids, final_shape, scale, projection, svg_file);
cereal::load(ar, fix_3mf_tr);
}
};
} // namespace Slic3r
// Serialization through the Cereal library
namespace cereal {
template<class Archive> void serialize(Archive &ar, Slic3r::ExPolygonsWithId &o) { ar(o.id, o.expoly, o.is_healed); }
template<class Archive> void serialize(Archive &ar, Slic3r::HealedExPolygons &o) { ar(o.expolygons, o.is_healed); }
}; // namespace cereal
#endif // slic3r_EmbossShape_hpp_

View File

@ -3872,7 +3872,7 @@ void to_xml(std::stringstream &stream, const EmbossShape &es, const ModelVolume
stream << SHAPE_SCALE_ATTR << "=\"" << es.scale << "\" ";
if (!es.is_healed)
if (!es.final_shape.is_healed)
stream << UNHEALED_ATTR << "=\"" << 1 << "\" ";
// projection
@ -3912,10 +3912,17 @@ std::optional<EmbossShape> read_emboss_shape(const char **attributes, unsigned i
std::string file_path = get_attribute_value_string(attributes, num_attributes, SVG_FILE_PATH_ATTR);
std::string file_path_3mf = get_attribute_value_string(attributes, num_attributes, SVG_FILE_PATH_IN_3MF_ATTR);
ExPolygonsWithIds shapes; // TODO: need to implement
// MayBe: store also shapes to not store svg
// But be carefull curve will be lost -> scale will not change sampling
// shapes could be loaded from SVG
ExPolygonsWithIds shapes;
// final shape could be calculated from shapes
HealedExPolygons final_shape;
final_shape.is_healed = is_healed;
EmbossShape::SvgFile svg{file_path, file_path_3mf};
return EmbossShape{shapes, {}, scale, std::move(projection), std::move(fix_tr_mat), std::move(svg), is_healed};
return EmbossShape{std::move(shapes), std::move(final_shape), scale, std::move(projection), std::move(fix_tr_mat), std::move(svg)};
}

View File

@ -1127,7 +1127,7 @@ std::vector<std::string> create_shape_warnings(const EmbossShape &shape, float s
res += '\n' + message;
};
if (!shape.is_healed) {
if (!shape.final_shape.is_healed) {
for (const ExPolygonsWithId &i : shape.shapes_with_ids)
if (!i.is_healed)
add_warning(i.id, _u8L("Path can't be healed from selfintersection and multiple points."));
@ -1455,12 +1455,11 @@ void GLGizmoSVG::draw_filename(){
m_filename_preview = get_file_name(svg.path_in_3mf);
}
if (m_filename_preview.empty()){
assert(false);
m_filename_preview = "unknown";
} else {
m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width);
}
if (m_filename_preview.empty())
// TRN - Preview of filename after clear local filepath.
m_filename_preview = _u8L("Without filename");
m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width);
}
if (!m_shape_warnings.empty()){
@ -1539,8 +1538,7 @@ void GLGizmoSVG::draw_filename(){
// set .svg_file.path_in_3mf to remember file name
m_volume->emboss_shape->svg_file->path.clear();
m_volume_shape.svg_file->path.clear();
// TRN - Preview of filename after clear local filepath.
m_filename_preview = _u8L("No-name SVG");
m_filename_preview.clear();
} else if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", _u8L("Do NOT save local path to 3MF file.\n"
"Also disables 'reload from disk' option.").c_str());
@ -1636,6 +1634,7 @@ void GLGizmoSVG::draw_filename(){
EmbossShape es_ = select_shape(m_volume_shape.svg_file->path, tes_tol);
m_volume_shape.svg_file = std::move(es_.svg_file);
m_volume_shape.shapes_with_ids = std::move(es_.shapes_with_ids);
m_volume_shape.final_shape = {}; // clear cache
m_shape_warnings = create_shape_warnings(m_volume_shape, scale);
init_texture(m_texture, m_volume_shape.shapes_with_ids, m_gui_cfg->texture_max_size_px, m_shape_warnings);
process();
@ -1805,7 +1804,7 @@ void GLGizmoSVG::draw_size()
if (img != NULL){
NSVGLineParams params{get_tesselation_tolerance(get_scale_for_tolerance())};
m_volume_shape.shapes_with_ids = create_shape_with_ids(*img, params);
m_volume_shape.final_shape.clear();
m_volume_shape.final_shape = {}; // reset cache for final shape
process();
}
}