diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 331701f2786ae6147ed6a96c671957a59877285c..be05ff36d414a9d3b0bc40543e29a0cf329d8586 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -663,6 +663,18 @@ SPCurve::nodes_in_path() const // and therefore any path has at least one valid node size_t psize = std::max(1, it.size_closed()); nr += psize; + if (it.closed()) { + const Geom::Curve &closingline = it.back_closed(); + // the closing line segment is always of type + // Geom::LineSegment. + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for + // *exact* zero length, which goes wrong for relative coordinates and + // rounding errors... + // the closing line segment has zero-length. So stop before that one! + nr -= 1; + } + } } return nr; diff --git a/src/helper/geom-pathvectorsatellites.cpp b/src/helper/geom-pathvectorsatellites.cpp index 1c06dc8b02e8b8ce98456ff812047fa40405e580..dd625b1f10a25e85c174f6f4d567bb8bc886d003 100644 --- a/src/helper/geom-pathvectorsatellites.cpp +++ b/src/helper/geom-pathvectorsatellites.cpp @@ -112,7 +112,7 @@ void PathVectorSatellites::updateAmount(double radius, bool apply_no_radius, boo for (size_t j = 0; j < _satellites[i].size(); ++j) { boost::optional previous_index = boost::none; if (j == 0 && _pathvector[i].closed()) { - previous_index = _pathvector[i].size_closed() - 1; + previous_index = count_path_nodes(_pathvector[i]) - 1; } else if (!_pathvector[i].closed() || j != 0) { previous_index = j - 1; } @@ -120,7 +120,7 @@ void PathVectorSatellites::updateAmount(double radius, bool apply_no_radius, boo _satellites[i][j].amount = 0; continue; } - if (_pathvector[i].size_closed() == j) { + if (count_path_nodes(_pathvector[i]) == j) { continue; } if ((!apply_no_radius && _satellites[i][j].amount == 0) || @@ -155,7 +155,7 @@ void PathVectorSatellites::convertUnit(Glib::ustring in, Glib::ustring to, bool _satellites[i][j].amount = 0; continue; } - if (_pathvector[i].size_closed() == j) { + if (count_path_nodes(_pathvector[i]) == j) { continue; } if ((!apply_no_radius && _satellites[i][j].amount == 0) || @@ -178,7 +178,7 @@ void PathVectorSatellites::updateSatelliteType(SatelliteType satellitetype, bool { continue; } - if (_pathvector[i].size_closed() == j) { + if (count_path_nodes(_pathvector[i]) == j) { if (!only_selected) { _satellites[i][j].satellite_type = satellitetype; } @@ -209,11 +209,11 @@ void PathVectorSatellites::recalculateForNewPathVector(Geom::PathVector const pa size_t previous_number_nodes = getTotalSatellites(); for (const auto & i : pathv) { std::vector path_satellites; - size_t count = i.size_closed(); + size_t count = count_path_nodes(i); for (size_t j = 0; j < count; j++) { found = false; for (size_t k = 0; k < _pathvector.size(); k++) { - size_t count2 = _pathvector[k].size_closed(); + size_t count2 = count_path_nodes(_pathvector[k]); for (size_t l = 0; l < count2; l++) { if (Geom::are_near(_pathvector[k][l].initialPoint(), i[j].initialPoint())) { path_satellites.push_back(_satellites[k][l]); diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 32119f2a348a17209502dd67e2a8832f12780ea1..06768fee42fcc851062067687565130623a6f9d0 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -603,7 +603,24 @@ size_t count_pathvector_nodes(Geom::PathVector const &pathv) { size_t tot = 0; for (auto subpath : pathv) { - tot += subpath.size_closed(); + tot += count_path_nodes(subpath); + } + return tot; +} +size_t count_path_nodes(Geom::Path const &path) +{ + size_t tot = path.size_closed(); + if (path.closed()) { + const Geom::Curve &closingline = path.back_closed(); + // the closing line segment is always of type + // Geom::LineSegment. + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + // closingline.isDegenerate() did not work, because it only checks for + // *exact* zero length, which goes wrong for relative coordinates and + // rounding errors... + // the closing line segment has zero-length. So stop before that one! + tot -= 1; + } } return tot; } diff --git a/src/helper/geom.h b/src/helper/geom.h index af8cc03d16aa7eac21276065e21c1088a4b2aff6..58f323efee45eb133d8512d2c2b530dac77e04ec 100644 --- a/src/helper/geom.h +++ b/src/helper/geom.h @@ -26,7 +26,8 @@ void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geo Geom::Rect *bbox, int *wind, Geom::Coord *dist, Geom::Coord tolerance, Geom::Rect const *viewbox); -size_t count_pathvector_nodes(Geom::PathVector const &pathv ); +size_t count_pathvector_nodes(Geom::PathVector const &pathv ); +size_t count_path_nodes(Geom::Path const &path); Geom::PathVector pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv ); Geom::PathVector pathv_to_linear( Geom::PathVector const &pathv, double maxdisp ); Geom::PathVector pathv_to_cubicbezier( Geom::PathVector const &pathv); diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index b5247c98d7b7d5b44b87fd5c9a44dde38626f6f0..95e995e823763dac2f458c48a2222502859a4254 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -15,9 +15,10 @@ #include "helper/geom-curves.h" #include "helper/geom-satellite.h" -#include <2geom/elliptical-arc.h> -#include "knotholder.h" #include "display/curve.h" +#include "knotholder.h" +#include "ui/tools/tool-base.h" +#include <2geom/elliptical-arc.h> #include #include "object/sp-shape.h" @@ -111,7 +112,7 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) } Geom::PathVector pathvres; for (const auto & path_it : pathv) { - if (path_it.empty() || path_it.size_closed() < 2) { + if (path_it.empty() || count_path_nodes(path_it) < 2) { continue; } std::vector subpath_satellites; @@ -324,7 +325,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(pathvector_before_effect); Geom::PathVector pathvres; for (const auto &path_it : pathv) { - if (path_it.empty() || path_it.size_closed() < 2) { + if (path_it.empty() || count_path_nodes(path_it) < 2) { continue; } Geom::Path::const_iterator curve_it = path_it.begin(); @@ -355,8 +356,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) pathresult.close(path_it.closed()); pathvres.push_back(pathresult); pathresult.clear(); - } - //if are different sizes call to recalculate + } // if are different sizes call to recalculate Satellites satellites = satellites_param.data(); if (satellites.empty()) { doOnApply(lpeItem); // dont want _impl to not update versioning @@ -390,6 +390,10 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) _pathvector_satellites->recalculateForNewPathVector(pathvres, satellite); satellites = _pathvector_satellites->getSatellites(); write = true; + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + SP_ACTIVE_DESKTOP->event_context->_delayed_snap_event = nullptr; + } } } if (_degenerate_hide) { @@ -399,7 +403,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) } for (size_t i = 0; i < satellites.size(); ++i) { for (size_t j = 0; j < satellites[i].size(); ++j) { - if (j >= pathvres[i].size_closed()) { + if (j >= count_path_nodes(pathvres[i])) { // we are on the end of a open path // for the moment we dont want to use // this satellite so simplest do nothing with it @@ -424,7 +428,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) } if (!pathvres[i].closed()) { satellites[i][0].amount = 0; - satellites[i][pathvres[i].size_closed() -1].amount = 0; + satellites[i][count_path_nodes(pathvres[i]) - 1].amount = 0; } } if (!_pathvector_satellites) { @@ -498,12 +502,12 @@ LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) } while (curve_it1 != curve_endit) { size_t next_index = curve + 1; - if (curve == pathv[path].size_closed() - 1 && pathv[path].closed()) { + if (curve == count_path_nodes(pathv[path]) - 1 && pathv[path].closed()) { next_index = 0; } //append last extreme of paths on open paths - if (curve == pathv[path].size_closed() - 1 && !pathv[path].closed()) { // the path is open and we are at - // end of path + if (curve == count_path_nodes(pathv[path]) - 1 && !pathv[path].closed()) { // the path is open and we are at + // end of path if (time0 != 1) { //Previous satellite not at 100% amount Geom::Curve *last_curve = curve_it1->portion(time0, 1); last_curve->setInitial(tmp_path.finalPoint()); diff --git a/src/live_effects/lpe-transform_2pts.cpp b/src/live_effects/lpe-transform_2pts.cpp index 0c13ab4ad3051735399ff34e9695f44ba0e1d03e..92bee07d0bbbb9927ae1de0e7fb4b8b2fa80f931 100644 --- a/src/live_effects/lpe-transform_2pts.cpp +++ b/src/live_effects/lpe-transform_2pts.cpp @@ -13,12 +13,13 @@ #include -#include "live_effects/lpe-transform_2pts.h" #include "display/curve.h" -#include "ui/icon-names.h" +#include "helper/geom.h" +#include "live_effects/lpe-transform_2pts.h" +#include "object/sp-path.h" #include "svg/svg.h" +#include "ui/icon-names.h" #include "verbs.h" -#include "object/sp-path.h" // TODO due to internal breakage in glibmm headers, this must be last: #include @@ -208,7 +209,7 @@ LPETransform2Pts::nodeCount(Geom::PathVector pathvector) const { size_t n = 0; for (auto & it : pathvector) { - n += it.size_closed(); + n += count_path_nodes(it); } return n; } diff --git a/src/live_effects/parameter/satellitesarray.cpp b/src/live_effects/parameter/satellitesarray.cpp index 4362a4f1ad6d4abec6f1fd9dcb487ca6392a097b..2a43a9037255b8a126feb33549bf932c24cb2e95 100644 --- a/src/live_effects/parameter/satellitesarray.cpp +++ b/src/live_effects/parameter/satellitesarray.cpp @@ -8,9 +8,10 @@ */ #include "live_effects/parameter/satellitesarray.h" -#include "live_effects/lpe-fillet-chamfer.h" +#include "helper/geom.h" #include "knotholder.h" #include "live_effects/effect.h" +#include "live_effects/lpe-fillet-chamfer.h" #include "ui/dialog/lpe-fillet-chamfer-properties.h" #include "ui/shape-editor.h" #include "ui/tools-switch.h" @@ -123,9 +124,9 @@ void SatellitesArrayParam::updateCanvasIndicators(bool mirror) if (_vector[i][j].hidden || //Ignore if hidden (!_vector[i][j].has_mirror && mirror == true) || //Ignore if not have mirror and we are in mirror loop _vector[i][j].amount == 0 || //no helper in 0 value - j >= pathv[i].size_closed() || //ignore last satellite in open paths with fillet chamfer effect + j >= count_path_nodes(pathv[i]) || //ignore last satellite in open paths with fillet chamfer effect (!pathv[i].closed() && j == 0) || //ignore first satellites on open paths - pathv[i].size_closed() == 2) + count_path_nodes(pathv[i]) == 2) { continue; } @@ -136,7 +137,7 @@ void SatellitesArrayParam::updateCanvasIndicators(bool mirror) double length_out = curve_in->length(); gint previous_index = j - 1; //Always are previous index because we skip first satellite on open paths if (j == 0 && pathv[i].closed()) { - previous_index = pathv[i].size_closed() - 1; + previous_index = count_path_nodes(pathv[i]) - 1; } if ( previous_index < 0 ) { return; @@ -298,13 +299,13 @@ void FilletChamferKnotHolderEntity::knot_set(Geom::Point const &p, if (satellite.hidden || (!pathv[satelite_index].closed() && (subsatelite_index == 0||//ignore first satellites on open paths - pathv[satelite_index].size_closed() - 1 == subsatelite_index))) //ignore last satellite in open paths with fillet chamfer effect + count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index))) //ignore last satellite in open paths with fillet chamfer effect { return; } gint previous_index = subsatelite_index - 1; if (subsatelite_index == 0 && pathv[satelite_index].closed()) { - previous_index = pathv[satelite_index].size_closed() - 1; + previous_index = count_path_nodes(pathv[satelite_index]) - 1; } if ( previous_index < 0 ) { return; @@ -376,7 +377,7 @@ Geom::Point FilletChamferKnotHolderEntity::knot_get() const Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); if (satellite.hidden || (!pathv[satelite_index].closed() && (subsatelite_index == 0 || - subsatelite_index == pathv[satelite_index].size_closed() - 1))) //ignore first and last satellites on open paths + subsatelite_index == count_path_nodes(pathv[satelite_index]) - 1))) //ignore first and last satellites on open paths { return Geom::Point(Geom::infinity(), Geom::infinity()); } @@ -384,7 +385,7 @@ Geom::Point FilletChamferKnotHolderEntity::knot_get() const if (is_mirror) { gint previous_index = subsatelite_index - 1; if (subsatelite_index == 0 && pathv[satelite_index].closed()) { - previous_index = pathv[satelite_index].size_closed() - 1; + previous_index = count_path_nodes(pathv[satelite_index]) - 1; } if ( previous_index < 0 ) { return Geom::Point(Geom::infinity(), Geom::infinity()); @@ -432,7 +433,7 @@ void FilletChamferKnotHolderEntity::knot_click(guint state) Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); if (!pathv[satelite_index].closed() && (subsatelite_index == 0 || - pathv[satelite_index].size_closed() - 1 == subsatelite_index)) //ignore last satellite in open paths with fillet chamfer effect + count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index)) //ignore last satellite in open paths with fillet chamfer effect { return; } @@ -484,7 +485,7 @@ void FilletChamferKnotHolderEntity::knot_click(guint state) double amount = _pparam->_vector[satelite_index][subsatelite_index].amount; gint previous_index = subsatelite_index - 1; if (subsatelite_index == 0 && pathv[satelite_index].closed()) { - previous_index = pathv[satelite_index].size_closed() - 1; + previous_index = count_path_nodes(pathv[satelite_index]) - 1; } if ( previous_index < 0 ) { return; @@ -529,7 +530,7 @@ void FilletChamferKnotHolderEntity::knot_set_offset(Satellite satellite) Geom::PathVector pathv = _pparam->_last_pathvector_satellites->getPathVector(); if (satellite.hidden || (!pathv[satelite_index].closed() && - (subsatelite_index == 0 || pathv[satelite_index].size_closed() - 1 == subsatelite_index))) //ignore last satellite in open paths with fillet chamfer effect + (subsatelite_index == 0 || count_path_nodes(pathv[satelite_index]) - 1 == subsatelite_index))) //ignore last satellite in open paths with fillet chamfer effect { return; } @@ -538,7 +539,7 @@ void FilletChamferKnotHolderEntity::knot_set_offset(Satellite satellite) if (!_pparam->_use_distance && !satellite.is_time) { gint previous_index = subsatelite_index - 1; if (subsatelite_index == 0 && pathv[satelite_index].closed()) { - previous_index = pathv[satelite_index].size_closed() - 1; + previous_index = count_path_nodes(pathv[satelite_index]) - 1; } if ( previous_index < 0 ) { return;