From fa351a5422a4ff7ee3c8e2877a5992fb79f92c05 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 7 Dec 2019 09:28:22 +0100 Subject: [PATCH] filletchanfer improvements --- src/helper/geom-satellite.cpp | 3 +- src/helper/geom-satellite.h | 5 ++ src/live_effects/lpe-fillet-chamfer.cpp | 33 +++++++- src/live_effects/parameter/array.cpp | 8 +- src/live_effects/parameter/array.h | 2 + .../parameter/satellitesarray.cpp | 84 ++++++++++++++++--- src/live_effects/parameter/satellitesarray.h | 1 + src/ui/control-manager.cpp | 2 +- 8 files changed, 124 insertions(+), 14 deletions(-) diff --git a/src/helper/geom-satellite.cpp b/src/helper/geom-satellite.cpp index 0d8ca832ce..b84f71b479 100644 --- a/src/helper/geom-satellite.cpp +++ b/src/helper/geom-satellite.cpp @@ -37,7 +37,8 @@ Satellite::Satellite(SatelliteType satellite_type) hidden(true), amount(0.0), angle(0.0), - steps(0) + steps(0), + ccw(false) {} Satellite::~Satellite() = default; diff --git a/src/helper/geom-satellite.h b/src/helper/geom-satellite.h index 5fbcae159e..36638689c6 100644 --- a/src/helper/geom-satellite.h +++ b/src/helper/geom-satellite.h @@ -61,6 +61,10 @@ public: { angle = set_angle; } + void setCCW(double set_angle) + { + ccw = ccw; + } void setSteps(size_t set_steps) { steps = set_steps; @@ -90,6 +94,7 @@ public: //in "amount" we store the time or distance used in the satellite double amount; double angle; + bool ccw; size_t steps; }; diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index 60af272e83..9de8e953c4 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -142,6 +142,7 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) satellite.setIsTime(flexible); satellite.setHasMirror(true); satellite.setHidden(hide_knots); + satellite.setCCW(false); subpath_satellites.push_back(satellite); } @@ -421,6 +422,24 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) if (only_selected && isNodePointSelected(curve_in.initialPoint()) ){ satellites[i][j].setSelected(true); } + size_t prev = j - 1; + if (j == 0 && pathvres[i].closed()) { + prev = pathvres[i].size_closed() - 1; + } + if (prev >= 0 && j < pathvres[i].size_closed() - 1) { + bool retracted = false; + if (satellites[i][j].amount == 0) { + satellites[i][j].amount = 3; + retracted = true; + } + Geom::Point end = satellites[i][j].getPosition(pathvres[i][j], false); + Geom::Point start = satellites[i][j].getPosition(pathvres[i][prev], true); + satellites[i][j].ccw = cross(pathvres[i][j].finalPoint() - start, end - start) < 0; + std::cout << satellites[i][j].ccw << "aa" << std::endl; + if (retracted) { + satellites[i][j].amount = 0; + } + } } if (!pathvres[i].closed()) { satellites[i][0].amount = 0; @@ -501,6 +520,10 @@ LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) if (curve == pathv[path].size_closed() - 1 && pathv[path].closed()) { next_index = 0; } + size_t next_next_index = next_index + 1; + if (curve == pathv[path].size_closed() - 2 && pathv[path].closed()) { + next_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 @@ -513,7 +536,9 @@ LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) continue; } Geom::Curve const &curve_it2 = pathv[path][next_index]; + Geom::Curve const &curve_it3 = pathv[path][next_next_index]; Satellite satellite = satellites[path][next_index]; + Satellite nextsatellite = satellites[path][next_next_index]; if (Geom::are_near((*curve_it1).initialPoint(), (*curve_it1).finalPoint())) { _degenerate_hide = true; g_warning("Knots hidden if consecutive nodes has the same position."); @@ -529,9 +554,14 @@ LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) double s = satellite.arcDistance(curve_it2); double time1 = satellite.time(s, true, (*curve_it1)); double time2 = satellite.time(curve_it2); - if (time1 <= time0) { + double s2 = satellite.arcDistance(curve_it3); + double time3 = nextsatellite.time(s2, true, (curve_it2)); + if (time1 < time0) { time1 = time0; } + if (time2 > time3) { + time2 = time3; + } if (time2 > 1) { time2 = 1; } @@ -600,6 +630,7 @@ LPEFilletChamfer::doEffect_path(Geom::PathVector const &path_in) Geom::Line const x_line(Geom::Point(0, 0), Geom::Point(1, 0)); Geom::Line const angled_line(start_arc_point, end_arc_point); double arc_angle = Geom::angle_between(x_line, angled_line); + satellite.setAngle(arc_angle); double radius = Geom::distance(start_arc_point, middle_point(start_arc_point, end_arc_point)) / sin(angle / 2.0); Geom::Coord rx = radius; diff --git a/src/live_effects/parameter/array.cpp b/src/live_effects/parameter/array.cpp index 376252f45c..d8f86332d8 100644 --- a/src/live_effects/parameter/array.cpp +++ b/src/live_effects/parameter/array.cpp @@ -59,7 +59,7 @@ ArrayParam >::readsvg(const gchar * str) gchar ** strarray = g_strsplit(str, "@", 0); gchar ** iter = strarray; while (*iter != nullptr) { - gchar ** strsubarray = g_strsplit(*iter, ",", 8); + gchar ** strsubarray = g_strsplit(*iter, ",", 9); if (*strsubarray[7]) {//steps always > 0 Satellite *satellite = new Satellite(); satellite->setSatelliteType(g_strstrip(strsubarray[0])); @@ -76,6 +76,12 @@ ArrayParam >::readsvg(const gchar * str) satellite->amount = amount; satellite->angle = angle; satellite->steps = steps; + // cww pre 1.0 added keep for comatibility? 4-12-2019 + if (*strsubarray[8]) { + satellite->ccw = strncmp(strsubarray[8],"1",1) == 0; + } else { + satellite->ccw = false; + } subpath_satellites.push_back(*satellite); } g_strfreev (strsubarray); diff --git a/src/live_effects/parameter/array.h b/src/live_effects/parameter/array.h index 1c9ffc4e0e..50f6470543 100644 --- a/src/live_effects/parameter/array.h +++ b/src/live_effects/parameter/array.h @@ -132,6 +132,8 @@ protected: str << ","; str << vector_data[i].angle; str << ","; + str << vector_data[i].ccw; + str << ","; str << static_cast(vector_data[i].steps); } } diff --git a/src/live_effects/parameter/satellitesarray.cpp b/src/live_effects/parameter/satellitesarray.cpp index 4362a4f1ad..85c1751699 100644 --- a/src/live_effects/parameter/satellitesarray.cpp +++ b/src/live_effects/parameter/satellitesarray.cpp @@ -26,6 +26,12 @@ namespace Inkscape { namespace LivePathEffect { +guint32 const CO_KNOT_COLOR_NORMAL = 0xffffff00; +guint32 const CO_KNOT_COLOR_MOUSEOVER = 0xff000000; +guint32 const CO_KNOT_COLOR_SELECTED = 0x0000ff00; +guint32 const CO_KNOT_COLOR_HIGHLIGHT = 0xffffff00; +guint32 const CO_KNOT_COLOR_MESHCORNER = 0xbfbfbf00; + SatellitesArrayParam::SatellitesArrayParam(const Glib::ustring &label, const Glib::ustring &tip, const Glib::ustring &key, @@ -33,7 +39,7 @@ SatellitesArrayParam::SatellitesArrayParam(const Glib::ustring &label, Effect *effect) : ArrayParam >(label, tip, key, wr, effect, 0), _knoth(nullptr) { - _knot_shape = SP_KNOT_SHAPE_DIAMOND; + _knot_shape = SP_KNOT_SHAPE_TRIANGLE; _knot_mode = SP_KNOT_MODE_XOR; _knot_color = 0xAAFF8800; _use_distance = false; @@ -190,6 +196,21 @@ void SatellitesArrayParam::param_transform_multiply(Geom::Affine const &postmul, param_set_and_write_new_value(_vector); } } +// TODO: avoid duplication wtht gradient code +void SatellitesArrayParam::updateControlSizes(SPKnot * knot) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int sizes[] = {4, 6, 8, 10, 12, 14, 16}; + std::vector sizeTable = std::vector(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0]))); + int size = prefs->getIntLimited("/options/grabsize/value", 3, 1, 7); + int knot_size = sizeTable[size - 1]; + knot_size *= 2.2; + knot_size = floor(knot_size); + if ( knot_size % 2 == 0 ){ + knot_size += 1; + } + knot->setSize(knot_size); +} void SatellitesArrayParam::addKnotHolderEntities(KnotHolder *knotholder, SPItem *item, @@ -230,7 +251,7 @@ void SatellitesArrayParam::addKnotHolderEntities(KnotHolder *knotholder, "Ctrl+Alt+Click reset"); } FilletChamferKnotHolderEntity *e = new FilletChamferKnotHolderEntity(this, index); - e->create(nullptr, item, knotholder, Inkscape::CTRL_TYPE_LPE, _(tip), _knot_shape, _knot_mode, + e->create(nullptr, item, knotholder, Inkscape::CTRL_TYPE_LPE, _(tip), SP_KNOT_SHAPE_TRIANGLE, _knot_mode, _knot_color); knotholder->add(e); } @@ -325,10 +346,26 @@ void FilletChamferKnotHolderEntity::knot_set(Geom::Point const &p, if (time_start > mirror_time) { mirror_time = time_start; } +/* size_t next = subsatelite_index + 1; + size_t prev = subsatelite_index - 1; + if (_pparam->_vector[satelite_index].size() -1 == subsatelite_index) { + next = 0; + } + if (0 == subsatelite_index) { + prev = _pparam->_vector[satelite_index].size() -1; + } + Satellite nexts = _pparam->_vector[satelite_index][next]; + Satellite prevs = _pparam->_vector[satelite_index][prev];*/ double size = arcLengthAt(mirror_time, curve_in); - double amount = curve_in.length() - size; + double amount = curve_in.length() - size; if (satellite.is_time) { amount = timeAtArcLength(amount, pathv[satelite_index][subsatelite_index]); +/* if (amount + prevs.ammount >= 1) { + amount = 1 - prevs.ammount; + } + if (amount + next.ammount >= 1) { + amount = 1 - next.ammount; + } */ } satellite.amount = amount; } else { @@ -353,6 +390,11 @@ FilletChamferKnotHolderEntity::knot_ungrabbed(Geom::Point const &p, Geom::Point } } +Geom::Point +sp_tangent_angle(Geom::Point point, Geom::Curve const &curve_in) { + return unitTangentAt(curve_in.toSBasis(), curve_in.nearestTime(point)).cw(); +} + Geom::Point FilletChamferKnotHolderEntity::knot_get() const { if (!_pparam->_last_pathvector_satellites || _pparam->_global_knot_hide) { @@ -381,6 +423,7 @@ Geom::Point FilletChamferKnotHolderEntity::knot_get() const return Geom::Point(Geom::infinity(), Geom::infinity()); } this->knot->show(); + Geom::Point tangent; if (is_mirror) { gint previous_index = subsatelite_index - 1; if (subsatelite_index == 0 && pathv[satelite_index].closed()) { @@ -389,9 +432,9 @@ Geom::Point FilletChamferKnotHolderEntity::knot_get() const if ( previous_index < 0 ) { return Geom::Point(Geom::infinity(), Geom::infinity()); } - Geom::Curve const &curve_in = pathv[satelite_index][previous_index]; + Geom::Curve *curve_in = pathv[satelite_index][previous_index].duplicate(); double s = satellite.arcDistance(pathv[satelite_index][subsatelite_index]); - double t = satellite.time(s, true, curve_in); + double t = satellite.time(s, true, *curve_in); if (t > 1) { t = 1; } @@ -399,16 +442,37 @@ Geom::Point FilletChamferKnotHolderEntity::knot_get() const t = 0; } double time_start = 0; - time_start = _pparam->_last_pathvector_satellites->getSatellites()[satelite_index][previous_index].time(curve_in); + time_start = _pparam->_last_pathvector_satellites->getSatellites()[satelite_index][previous_index].time(*curve_in); if (time_start > t) { t = time_start; } - tmp_point = (curve_in).pointAt(t); + tmp_point = (*curve_in).pointAt(t); + _pparam->updateControlSizes(this->knot); + /* if (satellite.ccw) { + t = 1 - t; + curve_in = curve_in->reverse(); + } */ + tangent = Geom::unitTangentAt(curve_in->toSBasis(),t); } else { - tmp_point = satellite.getPosition(pathv[satelite_index][subsatelite_index]); - } + Geom::Curve *curve_in = pathv[satelite_index][subsatelite_index].duplicate(); + tmp_point = satellite.getPosition(*curve_in); + /* if (satellite.ccw) { + curve_in = curve_in->reverse(); + } */ + tangent = Geom::unitTangentAt(curve_in->toSBasis(), curve_in->nearestTime(tmp_point)); + } + double angle = Geom::atan2(tangent.ccw()); + if (satellite.ccw) { + angle = Geom::atan2(tangent.cw()); + } + _pparam->updateControlSizes(this->knot); + this->knot->setAngle(angle); + this->knot->updateCtrl(); + this->knot->setFill(CO_KNOT_COLOR_HIGHLIGHT, CO_KNOT_COLOR_MOUSEOVER, CO_KNOT_COLOR_MOUSEOVER, CO_KNOT_COLOR_MOUSEOVER); + g_object_set (G_OBJECT (this->knot->item), "shape", SP_KNOT_SHAPE_TRIANGLE, NULL); Geom::Point const canvas_point = tmp_point; - return canvas_point; + Geom::Point res = Geom::Point::polar(this->knot->angle, 8) + canvas_point; + return res; } void FilletChamferKnotHolderEntity::knot_click(guint state) diff --git a/src/live_effects/parameter/satellitesarray.h b/src/live_effects/parameter/satellitesarray.h index c15b7107bb..04f8223cd6 100644 --- a/src/live_effects/parameter/satellitesarray.h +++ b/src/live_effects/parameter/satellitesarray.h @@ -59,6 +59,7 @@ public: void updateAmmount(double amount); void setPathVectorSatellites(PathVectorSatellites *pathVectorSatellites, bool write = true); void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); + void updateControlSizes(SPKnot * knot); friend class FilletChamferKnotHolderEntity; friend class LPEFilletChamfer; diff --git a/src/ui/control-manager.cpp b/src/ui/control-manager.cpp index 0330b5be37..77e3fb250b 100644 --- a/src/ui/control-manager.cpp +++ b/src/ui/control-manager.cpp @@ -250,6 +250,7 @@ SPCanvasItem *ControlManagerImpl::createControl(SPCanvasGroup *parent, ControlTy "stroke_color", 0x000000ff, NULL); break; + case CTRL_TYPE_LPE: case CTRL_TYPE_NODE_AUTO: case CTRL_TYPE_NODE_CUSP: case CTRL_TYPE_NODE_SMOOTH: @@ -269,7 +270,6 @@ SPCanvasItem *ControlManagerImpl::createControl(SPCanvasGroup *parent, ControlTy NULL); break; case CTRL_TYPE_UNKNOWN: - case CTRL_TYPE_LPE: default: item = sp_canvas_item_new(parent, SP_TYPE_CTRL, nullptr); } -- GitLab