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) 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; return shape.final_shape;
HealedExPolygons result = ::union_with_delta(shape.shapes_with_ids, delta, max_heal_iteration); shape.final_shape = ::union_with_delta(shape.shapes_with_ids, delta, max_heal_iteration);
shape.is_healed = result.is_healed;
for (const ExPolygonsWithId &e : shape.shapes_with_ids) for (const ExPolygonsWithId &e : shape.shapes_with_ids)
if (!e.is_healed) if (!e.is_healed)
shape.is_healed = false; shape.final_shape.is_healed = false;
shape.final_shape = std::move(result.expolygons); // cached return shape.final_shape.expolygons;
return shape.final_shape;
} }
void Slic3r::translate(ExPolygonsWithIds &expolygons_with_ids, const Point &p) void Slic3r::translate(ExPolygonsWithIds &expolygons_with_ids, const Point &p)

View File

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

View File

@ -16,8 +16,7 @@
namespace Slic3r { namespace Slic3r {
struct EmbossProjection struct EmbossProjection{
{
// Emboss depth, Size in local Z direction // Emboss depth, Size in local Z direction
double depth = 1.; // [in loacal mm] double depth = 1.; // [in loacal mm]
// NOTE: User should see and modify mainly world size not local // 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 // Flag that result volume use surface cutted from source objects
bool use_surface = false; 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 { bool operator==(const EmbossProjection &other) const {
return depth == other.depth && use_surface == other.use_surface; 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); } 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 // Help structure to identify expolygons grups
// e.g. emboss -> per glyph -> identify character // e.g. emboss -> per glyph -> identify character
struct ExPolygonsWithId struct ExPolygonsWithId
@ -74,7 +64,12 @@ struct EmbossShape
{ {
// shapes to to emboss separately over surface // shapes to to emboss separately over surface
ExPolygonsWithIds shapes_with_ids; 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 // scale of shape, multiplier to get 3d point in mm from integer shape
double scale = SCALING_FACTOR; double scale = SCALING_FACTOR;
@ -124,29 +119,25 @@ struct EmbossShape
// When embossing shape is made by svg file this is source data // When embossing shape is made by svg file this is source data
std::optional<SvgFile> svg_file; 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 // undo / redo stack recovery
template<class Archive> void save(Archive &ar) const template<class Archive> void save(Archive &ar) const
{ {
// final_shape is not neccessary to store - it is only cache // 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); cereal::save(ar, fix_3mf_tr);
} }
template<class Archive> void load(Archive &ar) 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); cereal::load(ar, fix_3mf_tr);
} }
}; };
} // namespace Slic3r } // namespace Slic3r
// Serialization through the Cereal library // Serialization through the Cereal library
namespace cereal { 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::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 }; // namespace cereal
#endif // slic3r_EmbossShape_hpp_ #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 << "\" "; stream << SHAPE_SCALE_ATTR << "=\"" << es.scale << "\" ";
if (!es.is_healed) if (!es.final_shape.is_healed)
stream << UNHEALED_ATTR << "=\"" << 1 << "\" "; stream << UNHEALED_ATTR << "=\"" << 1 << "\" ";
// projection // 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 = 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); 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}; 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; res += '\n' + message;
}; };
if (!shape.is_healed) { if (!shape.final_shape.is_healed) {
for (const ExPolygonsWithId &i : shape.shapes_with_ids) for (const ExPolygonsWithId &i : shape.shapes_with_ids)
if (!i.is_healed) if (!i.is_healed)
add_warning(i.id, _u8L("Path can't be healed from selfintersection and multiple points.")); 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); m_filename_preview = get_file_name(svg.path_in_3mf);
} }
if (m_filename_preview.empty()){ if (m_filename_preview.empty())
assert(false); // TRN - Preview of filename after clear local filepath.
m_filename_preview = "unknown"; m_filename_preview = _u8L("Without filename");
} else {
m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width); m_filename_preview = ImGuiWrapper::trunc(m_filename_preview, m_gui_cfg->input_width);
}
} }
if (!m_shape_warnings.empty()){ if (!m_shape_warnings.empty()){
@ -1539,8 +1538,7 @@ void GLGizmoSVG::draw_filename(){
// set .svg_file.path_in_3mf to remember file name // set .svg_file.path_in_3mf to remember file name
m_volume->emboss_shape->svg_file->path.clear(); m_volume->emboss_shape->svg_file->path.clear();
m_volume_shape.svg_file->path.clear(); m_volume_shape.svg_file->path.clear();
// TRN - Preview of filename after clear local filepath. m_filename_preview.clear();
m_filename_preview = _u8L("No-name SVG");
} else if (ImGui::IsItemHovered()) { } else if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", _u8L("Do NOT save local path to 3MF file.\n" ImGui::SetTooltip("%s", _u8L("Do NOT save local path to 3MF file.\n"
"Also disables 'reload from disk' option.").c_str()); "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); 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.svg_file = std::move(es_.svg_file);
m_volume_shape.shapes_with_ids = std::move(es_.shapes_with_ids); 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); 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); init_texture(m_texture, m_volume_shape.shapes_with_ids, m_gui_cfg->texture_max_size_px, m_shape_warnings);
process(); process();
@ -1805,7 +1804,7 @@ void GLGizmoSVG::draw_size()
if (img != NULL){ if (img != NULL){
NSVGLineParams params{get_tesselation_tolerance(get_scale_for_tolerance())}; NSVGLineParams params{get_tesselation_tolerance(get_scale_for_tolerance())};
m_volume_shape.shapes_with_ids = create_shape_with_ids(*img, params); 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(); process();
} }
} }