diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2015-02-19 20:53:20 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2015-02-19 20:53:20 +0000 |
| commit | a230b9d6684f01ded46fd530ba0cc74ce9696e2d (patch) | |
| tree | 2aa262efa6bf38dde79634efc3f7e5e8f580790e /src | |
| parent | starting fillet/chamfer (diff) | |
| download | inkscape-a230b9d6684f01ded46fd530ba0cc74ce9696e2d.tar.gz inkscape-a230b9d6684f01ded46fd530ba0cc74ce9696e2d.zip | |
Basic filleting using pointwise
(bzr r13645.1.16)
Diffstat (limited to 'src')
| -rw-r--r-- | src/2geom/pointwise.cpp | 7 | ||||
| -rw-r--r-- | src/2geom/pointwise.h | 2 | ||||
| -rw-r--r-- | src/2geom/satellite.cpp | 103 | ||||
| -rw-r--r-- | src/live_effects/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/live_effects/lpe-fillet-chamfer.cpp | 123 | ||||
| -rw-r--r-- | src/live_effects/parameter/Makefile_insert | 2 | ||||
| -rw-r--r-- | src/live_effects/parameter/filletchamferpointarray.cpp | 881 | ||||
| -rw-r--r-- | src/live_effects/parameter/filletchamferpointarray.h | 127 | ||||
| -rw-r--r-- | src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 300 | ||||
| -rw-r--r-- | src/ui/dialog/lpe-fillet-chamfer-properties.h | 115 |
10 files changed, 190 insertions, 1472 deletions
diff --git a/src/2geom/pointwise.cpp b/src/2geom/pointwise.cpp index 5cbccbca9..d7d5afc63 100644 --- a/src/2geom/pointwise.cpp +++ b/src/2geom/pointwise.cpp @@ -41,12 +41,17 @@ Pointwise::Pointwise(Piecewise<D2<SBasis> > pwd2, std::vector<std::pair<int,Sate Pointwise::~Pointwise(){}; std::vector<Satellite> -Pointwise::findSatellites(int A) const +Pointwise::findSatellites(int A, int B) const { std::vector<Satellite> ret; + int counter = 0; for(unsigned i = 0; i < _satellites.size(); i++){ if(_satellites[i].first == A){ + if(counter >= B && B != -1){ + return ret; + } ret.push_back(_satellites[i].second); + counter++; } } return ret; diff --git a/src/2geom/pointwise.h b/src/2geom/pointwise.h index 6e9c8840b..d48321832 100644 --- a/src/2geom/pointwise.h +++ b/src/2geom/pointwise.h @@ -62,7 +62,7 @@ class Pointwise Pointwise(){}; Pointwise(Piecewise<D2<SBasis> > pwd2, std::vector<std::pair<int,Satellite> > satellites); virtual ~Pointwise(); - std::vector<Satellite> findSatellites(int A) const; + std::vector<Satellite> findSatellites(int A, int B = -1) const; Pointwise recalculate_for_new_pwd2(Piecewise<D2<SBasis> > A); Pointwise pwd2_reverse(int index); Pointwise pwd2_append(int index); diff --git a/src/2geom/satellite.cpp b/src/2geom/satellite.cpp new file mode 100644 index 000000000..b8ddd040b --- /dev/null +++ b/src/2geom/satellite.cpp @@ -0,0 +1,103 @@ +/** + * \file + * \brief Satellite + *//* + * Authors: + * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es> + * Copyright 2015 authors + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + */ + +#include <2geom/satellite.h> +#include <2geom/curve.h> +#include <2geom/nearest-point.h> +#include <2geom/sbasis-geometric.h> + + +namespace Geom { + +Satellite::Satellite(){}; + +Satellite::Satellite(SatelliteType satellitetype, bool isTime, bool active, bool hasMirror, bool hidden, double size, double time) + : _satellitetype(satellitetype), _isTime(isTime), _active(active), _hasMirror(hasMirror), _hidden(hidden), _size(size), _time(time){}; + +Satellite::~Satellite() {}; + +void +Satellite::setPosition(Geom::Point p, Geom::D2<Geom::SBasis> d2_in){ + _time = Geom::nearest_point(p, d2_in); + if (d2_in[0].degreesOfFreedom() != 2) { + Geom::Piecewise<Geom::D2<Geom::SBasis> > u; + u.push_cut(0); + u.push(d2_in, 1); + u = Geom::portion(u, 0.0, _time); + _size = Geom::length(u, 0.001); + } else { + double lenghtPart = Geom::length(d2_in, Geom::EPSILON); + _size = (_time * lenghtPart); + } +} + +Geom::Point +Satellite::getPosition(Geom::D2<Geom::SBasis> d2_in){ + return d2_in.valueAt(_time); +} + +double +Satellite::getOpositeTime(Geom::D2<Geom::SBasis> d2_in){ + double t = 0; + if(_size == 0){ + return 1; + } + double lenghtPart = Geom::length(d2_in, Geom::EPSILON); + double size = lenghtPart - _size; + if (d2_in[0].degreesOfFreedom() != 2) { + Geom::Piecewise<Geom::D2<Geom::SBasis> > u; + u.push_cut(0); + u.push(d2_in, 1); + std::vector<double> t_roots = roots(arcLengthSb(u) - size); + if (t_roots.size() > 0) { + t = t_roots[0]; + } + } else { + if (size < lenghtPart && lenghtPart != 0) { + t = size / lenghtPart; + } + } + return t; +} + +} // end namespace Geom + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index 6b004e1df..3af27a220 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -55,7 +55,6 @@ set(live_effects_SRC parameter/array.cpp parameter/bool.cpp - parameter/filletchamferpointarray.cpp parameter/parameter.cpp parameter/path.cpp parameter/originalpath.cpp @@ -131,7 +130,6 @@ set(live_effects_SRC parameter/array.h parameter/bool.h - parameter/filletchamferpointarray.h parameter/enum.h parameter/parameter.h parameter/path-reference.h diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index b34cd87a1..3b1b1697c 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -64,6 +64,7 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv); pwd2_in = remove_short_cuts(pwd2_in, .01); satellitepairarrayparam_values.set_pwd2(pwd2_in); + int counterTotal = 0; for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { if (path_it->empty()){ continue; @@ -98,10 +99,11 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) nodetype = get_nodetype((*path_it)[counter - 1], *curve_it1); } if (nodetype == NODE_CUSP) { - satellites.push_back(std::make_pair(counter, satellite)); + satellites.push_back(std::make_pair(counterTotal, satellite)); } ++curve_it1; counter++; + counterTotal++; } } satellitepairarrayparam_values.param_set_and_write_new_value(satellites); @@ -132,14 +134,17 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) } } + std::vector<Geom::Path> LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) { + const double gapHelper = 0.00001; std::vector<Geom::Path> pathvector_out; Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(pathv_to_linear_and_cubic_beziers(path_in)); pwd2_in = remove_short_cuts(pwd2_in, .01); satellitepairarrayparam_values.set_pwd2(pwd2_in); std::vector<std::pair<int, Satellite> > filletChamferData = satellitepairarrayparam_values.data(); + Pointwise *pointwise = new Pointwise( pwd2_in, filletChamferData); unsigned int counter = 0; const double K = (4.0 / 3.0) * (sqrt(2.0) - 1.0); std::vector<Geom::Path> path_in_processed = pathv_to_linear_and_cubic_beziers(path_in); @@ -152,9 +157,9 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); Geom::Path::const_iterator curve_endit = path_it->end_default(); if (path_it->closed()) { - const Curve &closingline = path_it->back_closed(); + const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type - // LineSegment. + // 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 @@ -164,18 +169,46 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) } } unsigned int counterCurves = 0; + unsigned int first = counter; + double time0 = 0; while (curve_it1 != curve_endit) { + std::vector<Satellite> satVector; + Satellite sat(FILLET, true, true, false, false, 0.0, 0.0); Curve *curve_it2Fixed = (*path_it->begin()).duplicate(); - int indexFix = 0; if(!path_it->closed() || curve_it2 != curve_endit){ curve_it2Fixed = (*curve_it2).duplicate(); - indexFix = counter; + satVector = pointwise->findSatellites(counter+1,1); + if(satVector.size()>0){ + sat = satVector[0]; + } + } else { + satVector = pointwise->findSatellites(first,1); + if(satVector.size()>0){ + sat = satVector[0]; + } + } + if(first == counter){ + satVector = pointwise->findSatellites(first,1); + if(satVector.size()>0){ + time0 = satVector[0].getTime(); + } } bool last = curve_it2 == curve_endit; + double time1 = sat.getOpositeTime((*curve_it1).toSBasis()); + double time2 = sat.getTime(); + if(time1 <= time0){ + time1 = time0 + gapHelper; + } + if(time0 == 1){ + time0 = time0 - gapHelper; + } + if(time2 == 1){ + time2 = time2 - gapHelper; + } std::vector<double> times; - times.push_back(filletChamferData[counter].second.getTime()); - times.push_back(filletChamferData[indexFix].second.getOpositeTime((*curve_it1).toSBasis())); - times.push_back(filletChamferData[indexFix].second.getTime()); + times.push_back(time0); + times.push_back(time1); + times.push_back(time2); Curve *knotCurve1 = curve_it1->portion(times[0], times[1]); if (counterCurves > 0) { knotCurve1->setInitial(path_out.finalPoint()); @@ -187,14 +220,17 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) Point endArcPoint = curve_it2Fixed->pointAt(times[2]); double k1 = distance(startArcPoint, curve_it1->finalPoint()) * K; double k2 = distance(endArcPoint, curve_it1->finalPoint()) * K; - CubicBezier const *cubic1 = dynamic_cast<CubicBezier const *>(&*knotCurve1); + Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1); Ray ray1(startArcPoint, curve_it1->finalPoint()); if (cubic1) { ray1.setPoints((*cubic1)[2], startArcPoint); } Point handle1 = Point::polar(ray1.angle(),k1) + startArcPoint; - CubicBezier const *cubic2 = - dynamic_cast<CubicBezier const *>(&*knotCurve2); + if(time0 == 1){ + handle1 = startArcPoint; + } + Geom::CubicBezier const *cubic2 = + dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2); Ray ray2(curve_it1->finalPoint(), endArcPoint); if (cubic2) { ray2.setPoints(endArcPoint, (*cubic2)[1]); @@ -207,76 +243,76 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) handleAngle = ray1.angle() + angle; } Point inverseHandle1 = Point::polar(handleAngle,k1) + startArcPoint; + if(time0 == 1){ + inverseHandle1 = startArcPoint; + } handleAngle = ray2.angle() + angle; if (ccwToggle) { handleAngle = ray2.angle() - angle; } Point inverseHandle2 = endArcPoint - Point::polar(handleAngle,k2); - //straigth lines arc based - Line const x_line(Point(0,0),Point(1,0)); + Line const x_line(Geom::Point(0,0),Geom::Point(1,0)); Line const angled_line(startArcPoint,endArcPoint); - double angleArc = angle_between( x_line,angled_line); - double radius = distance(startArcPoint,middle_point(startArcPoint,endArcPoint))/sin(angle/2.0); + double angleArc = Geom::angle_between( x_line,angled_line); + double radius = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint))/sin(angle/2.0); Coord rx = radius; Coord ry = rx; - if (times[1] != 1) { - if (times[1] != times[0]) { + if (times[1] != 1 || (times[1] == 1 && times[0] == times[1] - gapHelper )) { + if (times[1] != times[0] + gapHelper) { path_out.append(*knotCurve1); } - SatelliteType satType = FILLET; - if(path_it->closed() && last){ - satType = filletChamferData[counter - counterCurves].second.getSatelliteType(); - } else if (!path_it->closed() && last){ - //0 - } else { - satType = filletChamferData[counter + 1].second.getSatelliteType(); - } + SatelliteType type = FILLET; + type = sat.getSatelliteType(); if(are_near(middle_point(startArcPoint,endArcPoint),curve_it1->finalPoint(), 0.0001)){ - path_out.appendNew<LineSegment>(endArcPoint); - } else if (satType == CHAMFER) { - unsigned int chamferSubs = 0; + //path_out.appendNew<Geom::LineSegment>(endArcPoint); + } else if (type == CHAMFER) { + /* + unsigned int chamferSubs = type-3000; Geom::Path path_chamfer; path_chamfer.start(path_out.finalPoint()); if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); } else { - path_chamfer.appendNew<CubicBezier>(handle1, handle2, endArcPoint); + path_chamfer.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint); } double chamfer_stepsTime = 1.0/chamferSubs; for(unsigned int i = 1; i < chamferSubs; i++){ - Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); - path_out.appendNew<LineSegment>(chamferStep); + Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); + path_out.appendNew<Geom::LineSegment>(chamferStep); } - path_out.appendNew<LineSegment>(endArcPoint); - } else if (satType == INVERSE_CHAMFER) { - unsigned int chamferSubs = 2; + path_out.appendNew<Geom::LineSegment>(endArcPoint); + /*/ + } else if (type == INVERSE_CHAMFER) { + /* + unsigned int chamferSubs = type-4000; Geom::Path path_chamfer; path_chamfer.start(path_out.finalPoint()); if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ ccwToggle = ccwToggle?0:1; path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); }else{ - path_chamfer.appendNew<CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); + path_chamfer.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); } double chamfer_stepsTime = 1.0/chamferSubs; for(unsigned int i = 1; i < chamferSubs; i++){ - Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); - path_out.appendNew<LineSegment>(chamferStep); + Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i); + path_out.appendNew<Geom::LineSegment>(chamferStep); } - path_out.appendNew<LineSegment>(endArcPoint); - } else if (satType == INVERSE_FILLET) { + path_out.appendNew<Geom::LineSegment>(endArcPoint); + */ + } else if (type == INVERSE_FILLET) { if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ ccwToggle = ccwToggle?0:1; path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); }else{ - path_out.appendNew<CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); + path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint); } - } else if (satType == FILLET){ + } else if (type == FILLET){ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint); } else { - path_out.appendNew<CubicBezier>(handle1, handle2, endArcPoint); + path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint); } } } else { @@ -291,6 +327,7 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) } counter++; counterCurves++; + time0 = times[2]; } pathvector_out.push_back(path_out); } @@ -299,7 +336,7 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in) void LPEFilletChamfer::adjustForNewPath(std::vector<Geom::Path> const &path_in) -{ +{ if (!path_in.empty()) { //satellitepairarrayparam_values.recalculate_controlpoints_for_new_pwd2(pathv_to_linear_and_cubic_beziers(path_in)[0].toPwSb()); } diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert index 33c6b0673..c9f40f7d1 100644 --- a/src/live_effects/parameter/Makefile_insert +++ b/src/live_effects/parameter/Makefile_insert @@ -24,8 +24,6 @@ ink_common_sources += \ live_effects/parameter/originalpatharray.h \ live_effects/parameter/powerstrokepointarray.cpp \ live_effects/parameter/powerstrokepointarray.h \ - live_effects/parameter/filletchamferpointarray.cpp \ - live_effects/parameter/filletchamferpointarray.h \ live_effects/parameter/satellitepairarray.cpp \ live_effects/parameter/satellitepairarray.h \ live_effects/parameter/text.cpp \ diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp deleted file mode 100644 index 2ebe11b4b..000000000 --- a/src/live_effects/parameter/filletchamferpointarray.cpp +++ /dev/null @@ -1,881 +0,0 @@ -/* - * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> - * Special thanks to Johan Engelen for the base of the effect -powerstroke- - * Also to ScislaC for point me to the idea - * Also su_v for his construvtive feedback and time - * and finaly to Liam P. White for his big help on coding, that save me a lot of - * hours - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <2geom/piecewise.h> -#include <2geom/sbasis-to-bezier.h> -#include <2geom/sbasis-geometric.h> -#include <2geom/svg-elliptical-arc.h> -#include <2geom/line.h> -#include <2geom/path-intersection.h> - -#include "ui/dialog/lpe-fillet-chamfer-properties.h" -#include "live_effects/parameter/filletchamferpointarray.h" -#include "live_effects/effect.h" -#include "svg/svg.h" -#include "svg/stringstream.h" -#include "knotholder.h" -#include "sp-lpe-item.h" -#include "selection.h" - -// needed for on-canvas editting: -#include "desktop.h" -#include "live_effects/lpeobject.h" -#include "helper/geom-nodetype.h" -#include "helper/geom-curves.h" -#include "ui/tools/node-tool.h" - -// TODO due to internal breakage in glibmm headers, -// this has to be included last. -#include <glibmm/i18n.h> - - -using namespace Geom; - -namespace Inkscape { - -namespace LivePathEffect { - -FilletChamferPointArrayParam::FilletChamferPointArrayParam( - const Glib::ustring &label, const Glib::ustring &tip, - const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr, - Effect *effect) - : ArrayParam<Point>(label, tip, key, wr, effect, 0) -{ - knot_shape = SP_KNOT_SHAPE_DIAMOND; - knot_mode = SP_KNOT_MODE_XOR; - knot_color = 0x00ff0000; -} - -FilletChamferPointArrayParam::~FilletChamferPointArrayParam() {} - -Gtk::Widget *FilletChamferPointArrayParam::param_newWidget() -{ - return NULL; - /* - Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = - Gtk::manage( - new Inkscape::UI::Widget::RegisteredTransformedPoint( - param_label, - param_tooltip, - param_key, - *param_wr, - param_effect->getRepr(), - param_effect->getSPDoc() - ) ); - // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP) - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Affine transf = desktop->doc2dt(); - pointwdg->setTransform(transf); - pointwdg->setValue( *this ); - pointwdg->clearProgrammatically(); - pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, - _("Change point parameter")); - - Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() ); - static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true); - static_cast<Gtk::HBox*>(hbox)->show_all_children(); - - return dynamic_cast<Gtk::Widget *> (hbox); - */ -} - -void -FilletChamferPointArrayParam::param_transform_multiply(Affine const &postmul, - bool /*set*/) -{ - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - if (prefs->getBool("/options/transform/rectcorners", true) && - _vector[1][X] <= 0) { - std::vector<Geom::Point> result; - for (std::vector<Point>::const_iterator point_it = _vector.begin(); - point_it != _vector.end(); ++point_it) { - Coord A = - (*point_it)[X] * ((postmul.expansionX() + postmul.expansionY()) / 2); - result.push_back(Point(A, (*point_it)[Y])); - } - param_set_and_write_new_value(result); - } - - // param_set_and_write_new_value( (*this) * postmul ); -} - -/** call this method to recalculate the controlpoints such that they stay at the - * same location relative to the new path. Useful after adding/deleting nodes to - * the path.*/ -void FilletChamferPointArrayParam::recalculate_controlpoints_for_new_pwd2( - Piecewise<D2<SBasis> > const &pwd2_in) -{ - if (!last_pwd2.empty()) { - PathVector const pathv = - path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001); - PathVector last_pathv = - path_from_piecewise(remove_short_cuts(last_pwd2, 0.1), 0.001); - std::vector<Point> result; - unsigned long counter = 0; - unsigned long counterPaths = 0; - unsigned long counterCurves = 0; - long offset = 0; - long offsetPaths = 0; - Geom::NodeType nodetype; - for (PathVector::const_iterator path_it = pathv.begin(); - path_it != pathv.end(); ++path_it) { - if (path_it->empty()) { - counterPaths++; - counter++; - continue; - } - Geom::Path::const_iterator curve_it1 = path_it->begin(); - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); - Geom::Path::const_iterator curve_endit = path_it->end_default(); - if (path_it->closed() && path_it->back_closed().isDegenerate()) { - const Curve &closingline = path_it->back_closed(); - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - curve_endit = path_it->end_open(); - } - } - counterCurves = 0; - while (curve_it1 != curve_endit) { - //if start a path get node type - if (counterCurves == 0) { - if (path_it->closed()) { - if (path_it->back_closed().isDegenerate()) { - nodetype = get_nodetype(path_it->back_open(), *curve_it1); - } else { - nodetype = get_nodetype(path_it->back_closed(), *curve_it1); - } - } else { - nodetype = NODE_NONE; - } - } else { - //check node type also whith straight lines because get_nodetype - //return non cusp node in a node inserted inside a straight line - //todo: if the path remove some nodes whith the result of a straight - //line but with handles, the node inserted into dont fire the knot - // because is not handle as cusp node by get_nodetype function - bool this_is_line = true; - bool next_is_line = is_straight_curve(*curve_it1); - this_is_line = is_straight_curve((*path_it)[counterCurves - 1]); - nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1); - if (this_is_line || next_is_line) { - nodetype = NODE_CUSP; - } - } - if (last_pathv.size() > pathv.size() || - (last_pathv.size() > counterPaths && - last_pathv[counterPaths].size() > counter - offset && - !are_near(curve_it1->initialPoint(), - last_pathv[counterPaths][counter - offset].initialPoint(), - 0.1))) { - if ( curve_it2 == curve_endit) { - if (last_pathv[counterPaths].size() != pathv[counterPaths].size()) { - offset = (last_pathv[counterPaths].size() - pathv[counterPaths].size()) * -1; - } else { - offset = 0; - } - offsetPaths += offset; - offset = offsetPaths; - } else if (counterCurves == 0 && last_pathv.size() <= pathv.size() && - counter - offset <= last_pathv[counterPaths].size() && - are_near(curve_it1->initialPoint(), - last_pathv[counterPaths].finalPoint(), 0.1) && - !last_pathv[counterPaths].closed()) { - long e = counter - offset + 1; - std::vector<Point> tmp = _vector; - for (unsigned long i = - last_pathv[counterPaths].size() + counter - offset; - i > counterCurves - offset + 1; i--) { - - if (tmp[i - 1][X] > 0) { - double fractpart, intpart; - fractpart = modf(tmp[i - 1][X], &intpart); - _vector[e] = Point(e + fractpart, tmp[i - 1][Y]); - } else { - _vector[e] = Point(tmp[i - 1][X], tmp[i - 1][Y]); - } - e++; - } - //delete temp vector - std::vector<Point>().swap(tmp); - if (last_pathv.size() > counterPaths) { - last_pathv[counterPaths] = last_pathv[counterPaths].reverse(); - } - } else { - if (last_pathv.size() > counterPaths) { - if (last_pathv[counterPaths].size() < - pathv[counterPaths].size()) { - offset++; - } else if (last_pathv[counterPaths].size() > - pathv[counterPaths].size()) { - offset--; - continue; - } - } else { - offset++; - } - } - double xPos = 0; - if (_vector[1][X] > 0) { - xPos = nearest_point(curve_it1->initialPoint(), pwd2_in); - } - if (nodetype == NODE_CUSP) { - result.push_back(Point(xPos, 1)); - } else { - result.push_back(Point(xPos, 0)); - } - } else { - double xPos = _vector[counter - offset][X]; - if (_vector.size() <= (unsigned)(counter - offset)) { - if (_vector[1][X] > 0) { - xPos = nearest_point(curve_it1->initialPoint(), pwd2_in); - } else { - xPos = 0; - } - } - if (nodetype == NODE_CUSP) { - double vectorY = _vector[counter - offset][Y]; - if (_vector.size() <= (unsigned)(counter - offset) || vectorY == 0) { - vectorY = 1; - } - result.push_back(Point(xPos, vectorY)); - } else { - if (_vector[1][X] < 0) { - xPos = 0; - } - result.push_back(Point(floor(xPos), 0)); - } - } - ++curve_it1; - if (curve_it2 != curve_endit) { - ++curve_it2; - } - counter++; - counterCurves++; - } - counterPaths++; - } - _vector = result; - write_to_SVG(); - } -} - -void FilletChamferPointArrayParam::recalculate_knots( - Piecewise<D2<SBasis> > const &pwd2_in) -{ - bool change = false; - PathVector pathv = path_from_piecewise(pwd2_in, 0.001); - if (!pathv.empty()) { - std::vector<Point> result; - int counter = 0; - int counterCurves = 0; - Geom::NodeType nodetype; - for (PathVector::const_iterator path_it = pathv.begin(); - path_it != pathv.end(); ++path_it) { - if (path_it->empty()) { - counter++; - continue; - } - Geom::Path::const_iterator curve_it1 = path_it->begin(); - Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); - Geom::Path::const_iterator curve_endit = path_it->end_default(); - if (path_it->closed() && path_it->back_closed().isDegenerate()) { - const Curve &closingline = path_it->back_closed(); - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - curve_endit = path_it->end_open(); - } - } - counterCurves = 0; - while (curve_it1 != curve_endit) { - //if start a path get node type - if (counterCurves == 0) { - if (path_it->closed()) { - if (path_it->back_closed().isDegenerate()) { - nodetype = get_nodetype(path_it->back_open(), *curve_it1); - } else { - nodetype = get_nodetype(path_it->back_closed(), *curve_it1); - } - } else { - nodetype = NODE_NONE; - } - } else { - bool this_is_line = true; - bool next_is_line = is_straight_curve(*curve_it1); - this_is_line = is_straight_curve((*path_it)[counterCurves - 1]); - nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1); - if (this_is_line || next_is_line) { - nodetype = NODE_CUSP; - } - } - if (nodetype == NODE_CUSP) { - double vectorY = _vector[counter][Y]; - if (vectorY == 0) { - vectorY = 1; - change = true; - } - result.push_back(Point(_vector[counter][X], vectorY)); - } else { - double xPos = floor(_vector[counter][X]); - if (_vector[1][X] < 0) { - xPos = 0; - } - double vectorY = _vector[counter][Y]; - if (vectorY != 0) { - change = true; - } - result.push_back(Point(xPos, 0)); - } - ++curve_it1; - counter++; - if (curve_it2 != curve_endit) { - ++curve_it2; - } - counterCurves++; - } - } - if (change) { - _vector = result; - write_to_SVG(); - } - } -} - -void FilletChamferPointArrayParam::set_pwd2( - Piecewise<D2<SBasis> > const &pwd2_in, - Piecewise<D2<SBasis> > const &pwd2_normal_in) -{ - last_pwd2 = pwd2_in; - last_pwd2_normal = pwd2_normal_in; -} - -void FilletChamferPointArrayParam::set_document_unit(Glib::ustring const * value_document_unit) -{ - documentUnit = value_document_unit; -} - -void FilletChamferPointArrayParam::set_helper_size(int hs) -{ - helper_size = hs; -} - -void FilletChamferPointArrayParam::set_chamfer_steps(int value_chamfer_steps) -{ - chamfer_steps = value_chamfer_steps; -} - -void FilletChamferPointArrayParam::set_use_distance(bool use_knot_distance ) -{ - use_distance = use_knot_distance; -} - -void FilletChamferPointArrayParam::set_unit(const gchar *abbr) -{ - unit = abbr; -} - -void FilletChamferPointArrayParam::updateCanvasIndicators() -{ - std::vector<Point> ts = data(); - hp.clear(); - unsigned int i = 0; - for (std::vector<Point>::const_iterator point_it = ts.begin(); - point_it != ts.end(); ++point_it) { - double Xvalue = to_time(i, (*point_it)[X]) -i; - if (Xvalue == 0) { - i++; - continue; - } - Geom::Point ptA = last_pwd2[i].valueAt(Xvalue); - Geom::Point derivA = unit_vector(derivative(last_pwd2[i]).valueAt(Xvalue)); - Geom::Rotate rot(Geom::Rotate::from_degrees(-90)); - derivA = derivA * rot; - Geom::Point C = ptA - derivA * helper_size; - Geom::Point D = ptA + derivA * helper_size; - Geom::Ray ray1(C, D); - char const * svgd = "M 1,0.25 0.5,0 1,-0.25 M 1,0.5 0,0 1,-0.5"; - Geom::PathVector pathv = sp_svg_read_pathv(svgd); - Geom::Affine aff = Geom::Affine(); - aff *= Geom::Scale(helper_size); - aff *= Geom::Rotate(ray1.angle() - deg_to_rad(270)); - pathv *= aff; - pathv += last_pwd2[i].valueAt(Xvalue); - hp.push_back(pathv[0]); - hp.push_back(pathv[1]); - i++; - } -} - -void FilletChamferPointArrayParam::addCanvasIndicators( - SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) -{ - hp_vec.push_back(hp); -} - -double FilletChamferPointArrayParam::rad_to_len(int index, double rad) -{ - double len = 0; - std::vector<Geom::Path> subpaths = path_from_piecewise(last_pwd2, 0.1); - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); - D2<SBasis> A = last_pwd2[last_index(index, subpaths)]; - if(positions.second != 0){ - A = last_pwd2[index-1]; - }else{ - if(!subpaths[positions.first].closed()){ - return len; - } - } - D2<SBasis> B = last_pwd2[index]; - Piecewise<D2<SBasis> > offset_curve0 = Piecewise<D2<SBasis> >(A)+rot90(unitVector(derivative(A)))*(rad); - Piecewise<D2<SBasis> > offset_curve1 = Piecewise<D2<SBasis> >(B)+rot90(unitVector(derivative(B)))*(rad); - Geom::Path p0 = path_from_piecewise(offset_curve0, 0.1)[0]; - Geom::Path p1 = path_from_piecewise(offset_curve1, 0.1)[0]; - Geom::Crossings cs = Geom::crossings(p0, p1); - if(cs.size() > 0){ - Point cp =p0(cs[0].ta); - double p0pt = nearest_point(cp, B); - len = time_to_len(index,p0pt); - } else { - if(rad < 0){ - len = rad_to_len(index, rad * -1); - } - } - return len; -} - -double FilletChamferPointArrayParam::len_to_rad(int index, double len) -{ - double rad = 0; - double tmp_len = _vector[index][X]; - _vector[index] = Geom::Point(len,_vector[index][Y]); - std::vector<Geom::Path> subpaths = path_from_piecewise(last_pwd2, 0.1); - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); - Piecewise<D2<SBasis> > u; - u.push_cut(0); - u.push(last_pwd2[last_index(index, subpaths)], 1); - Geom::Curve * A = path_from_piecewise(u, 0.1)[0][0].duplicate(); - Geom::Curve * B = subpaths[positions.first][positions.second].duplicate(); - std::vector<double> times; - if(positions.second != 0){ - A = subpaths[positions.first][positions.second-1].duplicate(); - times = get_times(index-1, subpaths, false); - }else{ - if(!subpaths[positions.first].closed()){ - return rad; - } - times = get_times(last_index(index, subpaths), subpaths, true); - } - _vector[index] = Geom::Point(tmp_len,_vector[index][Y]); - Geom::Point startArcPoint = A->toSBasis().valueAt(times[1]); - Geom::Point endArcPoint = B->toSBasis().valueAt(times[2]); - Curve *knotCurve1 = A->portion(times[0], times[1]); - Curve *knotCurve2 = B->portion(times[2], 1); - Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1); - Ray ray1(startArcPoint, A->finalPoint()); - if (cubic1) { - ray1.setPoints((*cubic1)[2], startArcPoint); - } - Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2); - Ray ray2(B->initialPoint(), endArcPoint); - if (cubic2) { - ray2.setPoints(endArcPoint, (*cubic2)[1]); - } - bool ccwToggle = cross(A->finalPoint() - startArcPoint, endArcPoint - startArcPoint) < 0; - double distanceArc = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint)); - double angleBetween = angle_between(ray1, ray2, ccwToggle); - rad = distanceArc/sin(angleBetween/2.0); - return rad * -1; -} - -std::vector<double> FilletChamferPointArrayParam::get_times(int index, std::vector<Geom::Path> subpaths, bool last) -{ - const double tolerance = 0.001; - const double gapHelper = 0.00001; - std::pair<std::size_t, std::size_t> positions = get_positions(index, subpaths); - Curve *curve_it1; - curve_it1 = subpaths[positions.first][positions.second].duplicate(); - Coord it1_length = (*curve_it1).length(tolerance); - double time_it1, time_it2, time_it1_B, intpart; - time_it1 = modf(to_time(index, _vector[index][X]), &intpart); - if (_vector[index][Y] == 0) { - time_it1 = 0; - } - double resultLenght = 0; - time_it1_B = 1; - if (subpaths[positions.first].closed() && last) { - time_it2 = modf(to_time(index - positions.second , _vector[index - positions.second ][X]), &intpart); - resultLenght = it1_length + to_len(index - positions.second, _vector[index - positions.second ][X]); - } else if (!subpaths[positions.first].closed() && last){ - time_it2 = 0; - resultLenght = 0; - } else { - time_it2 = modf(to_time(index + 1, _vector[index + 1][X]), &intpart); - resultLenght = it1_length + to_len( index + 1, _vector[index + 1][X]); - } - if (resultLenght > 0 && time_it2 != 0) { - time_it1_B = modf(to_time(index, -resultLenght), &intpart); - } else { - if (time_it2 == 0) { - time_it1_B = 1; - } else { - time_it1_B = gapHelper; - } - } - - if ((subpaths[positions.first].closed() && last && _vector[index - positions.second][Y] == 0) || (subpaths[positions.first].size() > positions.second + 1 && _vector[index + 1][Y] == 0)) { - time_it1_B = 1; - time_it2 = 0; - } - if (time_it1_B < time_it1) { - time_it1_B = time_it1 + gapHelper; - } - std::vector<double> out; - out.push_back(time_it1); - out.push_back(time_it1_B); - out.push_back(time_it2); - return out; -} - -std::pair<std::size_t, std::size_t> FilletChamferPointArrayParam::get_positions(int index, std::vector<Geom::Path> subpaths) -{ - int counter = -1; - std::size_t first = 0; - std::size_t second = 0; - for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) { - if (path_it->empty()) - continue; - Geom::Path::const_iterator curve_it1 = path_it->begin(); - Geom::Path::const_iterator curve_endit = path_it->end_default(); - if (path_it->closed()) { - const Geom::Curve &closingline = path_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! - curve_endit = path_it->end_open(); - } - } - first++; - second = 0; - while (curve_it1 != curve_endit) { - counter++; - second++; - if(counter == index){ - break; - } - ++curve_it1; - } - if(counter == index){ - break; - } - } - first--; - second--; - std::pair<std::size_t, std::size_t> out(first, second); - return out; -} - -int FilletChamferPointArrayParam::last_index(int index, std::vector<Geom::Path> subpaths) -{ - int counter = -1; - bool inSubpath = false; - for (PathVector::const_iterator path_it = subpaths.begin(); path_it != subpaths.end(); ++path_it) { - if (path_it->empty()) - continue; - Geom::Path::const_iterator curve_it1 = path_it->begin(); - Geom::Path::const_iterator curve_endit = path_it->end_default(); - if (path_it->closed()) { - const Geom::Curve &closingline = path_it->back_closed(); - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - curve_endit = path_it->end_open(); - } - } - while (curve_it1 != curve_endit) { - counter++; - if(counter == index){ - inSubpath = true; - } - ++curve_it1; - } - if(inSubpath){ - break; - } - } - if(!inSubpath){ - counter = -1; - } - return counter; -} - - -double FilletChamferPointArrayParam::len_to_time(int index, double len) -{ - double t = 0; - if (last_pwd2.size() > (unsigned) index) { - if (len != 0) { - if (last_pwd2[index][0].degreesOfFreedom() != 2) { - Piecewise<D2<SBasis> > u; - u.push_cut(0); - u.push(last_pwd2[index], 1); - std::vector<double> t_roots = roots(arcLengthSb(u) - std::abs(len)); - if (t_roots.size() > 0) { - t = t_roots[0]; - } - } else { - double lenghtPart = 0; - if (last_pwd2.size() > (unsigned) index) { - lenghtPart = length(last_pwd2[index], EPSILON); - } - if (std::abs(len) < lenghtPart && lenghtPart != 0) { - t = std::abs(len) / lenghtPart; - } - } - } - t = double(index) + t; - } else { - t = double(last_pwd2.size() - 1); - } - - return t; -} - -double FilletChamferPointArrayParam::time_to_len(int index, double time) -{ - double intpart; - double len = 0; - time = modf(time, &intpart); - double lenghtPart = 0; - if (last_pwd2.size() <= (unsigned) index || time == 0) { - return len; - } - if (last_pwd2[index][0].degreesOfFreedom() != 2) { - Piecewise<D2<SBasis> > u; - u.push_cut(0); - u.push(last_pwd2[index], 1); - u = portion(u, 0, time); - return length(u, 0.001) * -1; - } - lenghtPart = length(last_pwd2[index], EPSILON); - return (time * lenghtPart) * -1; -} - -double FilletChamferPointArrayParam::to_time(int index, double A) -{ - if (A > 0) { - return A; - } else { - return len_to_time(index, A); - } -} - -double FilletChamferPointArrayParam::to_len(int index, double A) -{ - if (A > 0) { - return time_to_len(index, A); - } else { - return A; - } -} - -void FilletChamferPointArrayParam::set_oncanvas_looks(SPKnotShapeType shape, - SPKnotModeType mode, - guint32 color) -{ - knot_shape = shape; - knot_mode = mode; - knot_color = color; -} - -FilletChamferPointArrayParamKnotHolderEntity:: -FilletChamferPointArrayParamKnotHolderEntity( - FilletChamferPointArrayParam *p, unsigned int index) - : _pparam(p), _index(index) {} - -void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p, - Point const &/*origin*/, - guint state) -{ - using namespace Geom; - - if (!valid_index(_index)) { - return; - } - Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2(); - double t = nearest_point(p, pwd2[_index]); - Geom::Point const s = snap_knot_position(pwd2[_index].valueAt(t), state); - t = nearest_point(s, pwd2[_index]); - if (t == 1) { - t = 0.9999; - } - t += _index; - - if (_pparam->_vector.at(_index)[X] <= 0) { - _pparam->_vector.at(_index) = - Point(_pparam->time_to_len(_index, t), _pparam->_vector.at(_index)[Y]); - } else { - _pparam->_vector.at(_index) = Point(t, _pparam->_vector.at(_index)[Y]); - } - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); -} - -Point FilletChamferPointArrayParamKnotHolderEntity::knot_get() const -{ - using namespace Geom; - - if (!valid_index(_index)) { - return Point(infinity(), infinity()); - } - - Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2(); - - double time_it = _pparam->to_time(_index, _pparam->_vector.at(_index)[X]); - Point canvas_point = pwd2.valueAt(time_it); - - _pparam->updateCanvasIndicators(); - return canvas_point; - -} - -void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state) -{ - if (state & GDK_CONTROL_MASK) { - if (state & GDK_MOD1_MASK) { - _pparam->_vector.at(_index) = Point(_index, _pparam->_vector.at(_index)[Y]); - _pparam->param_set_and_write_new_value(_pparam->_vector); - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); - }else{ - using namespace Geom; - int type = (int)_pparam->_vector.at(_index)[Y]; - if (type >=3000 && type < 4000){ - type = 3; - } - if (type >=4000 && type < 5000){ - type = 4; - } - switch(type){ - case 1: - type = 2; - break; - case 2: - type = _pparam->chamfer_steps + 3000; - break; - case 3: - type = _pparam->chamfer_steps + 4000; - break; - default: - type = 1; - break; - } - _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], (double)type); - _pparam->param_set_and_write_new_value(_pparam->_vector); - sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); - const gchar *tip; - if (type >=3000 && type < 4000){ - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else if (type >=4000 && type < 5000) { - tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else if (type == 2) { - tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else { - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } - this->knot->tip = g_strdup(tip); - this->knot->show(); - } - } else if (state & GDK_SHIFT_MASK) { - double xModified = _pparam->_vector.at(_index).x(); - if(xModified < 0 && !_pparam->use_distance){ - xModified = _pparam->len_to_rad(_index, _pparam->_vector.at(_index).x()); - } - std::vector<Geom::Path> subpaths = path_from_piecewise(_pparam->last_pwd2, 0.1); - std::pair<std::size_t, std::size_t> positions = _pparam->get_positions(_index, subpaths); - D2<SBasis> A = _pparam->last_pwd2[_pparam->last_index(_index, subpaths)]; - if(positions.second != 0){ - A = _pparam->last_pwd2[_index-1]; - } - D2<SBasis> B = _pparam->last_pwd2[_index]; - bool aprox = (A[0].degreesOfFreedom() != 2 || B[0].degreesOfFreedom() != 2) && !_pparam->use_distance?true:false; - Geom::Point offset = Geom::Point(xModified, _pparam->_vector.at(_index).y()); - Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog( - this->desktop, offset, this, _pparam->unit, _pparam->use_distance, aprox, _pparam->documentUnit); - } - -} - -void FilletChamferPointArrayParamKnotHolderEntity::knot_set_offset( - Geom::Point offset) -{ - double xModified = offset.x(); - if(xModified < 0 && !_pparam->use_distance){ - xModified = _pparam->rad_to_len(_index, offset.x()); - } - _pparam->_vector.at(_index) = Geom::Point(xModified, offset.y()); - this->parent_holder->knot_ungrabbed_handler(this->knot, 0); -} - -void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder, - SPDesktop *desktop, - SPItem *item) -{ - recalculate_knots(get_pwd2()); - for (unsigned int i = 0; i < _vector.size(); ++i) { - if (_vector[i][Y] <= 0) { - continue; - } - const gchar *tip; - if (_vector[i][Y] >=3000 && _vector[i][Y] < 4000){ - tip = _("<b>Chamfer</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else if (_vector[i][Y] >=4000 && _vector[i][Y] < 5000) { - tip = _("<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else if (_vector[i][Y] == 2) { - tip = _("<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } else { - tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggle type, " - "<b>Shift+Click</b> open dialog, " - "<b>Ctrl+Alt+Click</b> reset"); - } - FilletChamferPointArrayParamKnotHolderEntity *e = - new FilletChamferPointArrayParamKnotHolderEntity(this, i); - e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip), - knot_shape, knot_mode, knot_color); - knotholder->add(e); - } - updateCanvasIndicators(); -} - -} /* namespace LivePathEffect */ - -} /* namespace Inkscape */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h deleted file mode 100644 index 6e5cce353..000000000 --- a/src/live_effects/parameter/filletchamferpointarray.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H -#define INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H - -/* - * Inkscape::LivePathEffectParameters - * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es> - * Special thanks to Johan Engelen for the base of the effect -powerstroke- - * Also to ScislaC for point me to the idea - * Also su_v for his construvtive feedback and time - * and finaly to Liam P. White for his big help on coding, that save me a lot of - * hours - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <glib.h> -#include <2geom/point.h> - -#include "live_effects/parameter/array.h" - -#include "knot-holder-entity.h" - -namespace Inkscape { - -namespace LivePathEffect { - -class FilletChamferPointArrayParamKnotHolderEntity; - -class FilletChamferPointArrayParam : public ArrayParam<Geom::Point> { -public: - FilletChamferPointArrayParam(const Glib::ustring &label, - const Glib::ustring &tip, - const Glib::ustring &key, - Inkscape::UI::Widget::Registry *wr, - Effect *effect); - virtual ~FilletChamferPointArrayParam(); - - virtual Gtk::Widget *param_newWidget(); - - virtual void param_transform_multiply(Geom::Affine const &postmul, - bool /*set*/); - - void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, - guint32 color); - virtual double to_time(int index, double A); - virtual double to_len(int index, double A); - virtual double rad_to_len(int index, double rad); - virtual double len_to_rad(int index, double len); - virtual double len_to_time(int index, double len); - virtual double time_to_len(int index, double time); - virtual std::pair<std::size_t, std::size_t> get_positions(int index, std::vector<Geom::Path> subpaths); - virtual int last_index(int index, std::vector<Geom::Path> subpaths); - std::vector<double> get_times(int index, std::vector<Geom::Path> subpaths, bool last); - virtual void set_helper_size(int hs); - virtual void set_use_distance(bool use_knot_distance); - virtual void set_chamfer_steps(int value_chamfer_steps); - virtual void set_document_unit(Glib::ustring const * value_document_unit); - virtual void set_unit(const gchar *abbr); - virtual void addCanvasIndicators(SPLPEItem const *lpeitem, - std::vector<Geom::PathVector> &hp_vec); - virtual bool providesKnotHolderEntities() const { - return true; - } - virtual void updateCanvasIndicators(); - virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, - SPItem *item); - - void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in, - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_normal_in); - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2() const { - return last_pwd2; - } - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2_normal() const { - return last_pwd2_normal; - } - - void recalculate_controlpoints_for_new_pwd2( - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in); - void recalculate_knots( - Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in); - friend class FilletChamferPointArrayParamKnotHolderEntity; - -private: - FilletChamferPointArrayParam(const FilletChamferPointArrayParam &); - FilletChamferPointArrayParam &operator=(const FilletChamferPointArrayParam &); - - SPKnotShapeType knot_shape; - SPKnotModeType knot_mode; - guint32 knot_color; - int helper_size; - int chamfer_steps; - bool use_distance; - const gchar *unit; - Glib::ustring const * documentUnit; - Geom::PathVector hp; - - Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2; - Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal; -}; - -class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity { -public: - FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam *p, - unsigned int index); - virtual ~FilletChamferPointArrayParamKnotHolderEntity() {} - - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, - guint state); - virtual Geom::Point knot_get() const; - virtual void knot_click(guint state); - virtual void knot_set_offset(Geom::Point offset); - - /*Checks whether the index falls within the size of the parameter's vector*/ - bool valid_index(unsigned int index) const { - return (_pparam->_vector.size() > index); - } - ; - -private: - FilletChamferPointArrayParam *_pparam; - unsigned int _index; -}; - -} //namespace LivePathEffect - -} //namespace Inkscape - -#endif diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index b318933a7..e69de29bb 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -1,300 +0,0 @@ -/** - * From the code of Liam P.White from his Power Stroke Knot dialog - * - * Released under GNU GPL. Read the file 'COPYING' for more information - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if GLIBMM_DISABLE_DEPRECATED &&HAVE_GLIBMM_THREADS_H -#include <glibmm/threads.h> -#endif - -#include <gtkmm.h> -#include "lpe-fillet-chamfer-properties.h" -#include <boost/lexical_cast.hpp> -#include <glibmm/main.h> -#include <glibmm/i18n.h> -#include "inkscape.h" -#include "desktop.h" -#include "document.h" -#include "document-undo.h" -#include "layer-manager.h" -#include "message-stack.h" - -#include "sp-object.h" -#include "sp-item.h" -#include "verbs.h" -#include "selection.h" -#include "selection-chemistry.h" -#include "ui/icon-names.h" -#include "ui/widget/imagetoggler.h" -#include "util/units.h" -#include <cmath> - -//#include "event-context.h" - -namespace Inkscape { -namespace UI { -namespace Dialogs { - -FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() - : _desktop(NULL), _knotpoint(NULL), _position_visible(false) -{ - Gtk::Box *mainVBox = get_vbox(); - mainVBox->set_homogeneous(false); - _layout_table.set_spacings(4); - _layout_table.resize(3, 3); - - // Layer name widgets - _fillet_chamfer_position_numeric.set_digits(4); - _fillet_chamfer_position_numeric.set_increments(1,1); - //todo: get tha max aloable infinity freeze the widget - _fillet_chamfer_position_numeric.set_range(0., 999999999999999999.); - - _fillet_chamfer_position_label.set_label(_("Radius (pixels):")); - _fillet_chamfer_position_label.set_alignment(1.0, 0.5); - - _layout_table.attach(_fillet_chamfer_position_label, 0, 1, 0, 1, Gtk::FILL, - Gtk::FILL); - _layout_table.attach(_fillet_chamfer_position_numeric, 1, 2, 0, 1, - Gtk::FILL | Gtk::EXPAND, Gtk::FILL); - _fillet_chamfer_chamfer_subdivisions.set_digits(0); - _fillet_chamfer_chamfer_subdivisions.set_increments(1,1); - //todo: get tha max aloable infinity freeze the widget - _fillet_chamfer_chamfer_subdivisions.set_range(0, 999999999999999999.0); - - _fillet_chamfer_chamfer_subdivisions_label.set_label(_("Chamfer subdivisions:")); - _fillet_chamfer_chamfer_subdivisions_label.set_alignment(1.0, 0.5); - - _layout_table.attach(_fillet_chamfer_chamfer_subdivisions_label, 0, 1, 1, 2, Gtk::FILL, - Gtk::FILL); - _layout_table.attach(_fillet_chamfer_chamfer_subdivisions, 1, 2, 1, 2, - Gtk::FILL | Gtk::EXPAND, Gtk::FILL); - _fillet_chamfer_type_fillet.set_label(_("Fillet")); - _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group); - _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet")); - _fillet_chamfer_type_inverse_fillet.set_group(_fillet_chamfer_type_group); - _fillet_chamfer_type_chamfer.set_label(_("Chamfer")); - _fillet_chamfer_type_chamfer.set_group(_fillet_chamfer_type_group); - _fillet_chamfer_type_inverse_chamfer.set_label(_("Inverse chamfer")); - _fillet_chamfer_type_inverse_chamfer.set_group(_fillet_chamfer_type_group); - - - mainVBox->pack_start(_layout_table, true, true, 4); - mainVBox->pack_start(_fillet_chamfer_type_fillet, true, true, 4); - mainVBox->pack_start(_fillet_chamfer_type_inverse_fillet, true, true, 4); - mainVBox->pack_start(_fillet_chamfer_type_chamfer, true, true, 4); - mainVBox->pack_start(_fillet_chamfer_type_inverse_chamfer, true, true, 4); - - // Buttons - _close_button.set_use_stock(true); - _close_button.set_label(Gtk::Stock::CANCEL.id); - _close_button.set_can_default(); - - _apply_button.set_use_underline(true); - _apply_button.set_can_default(); - - _close_button.signal_clicked() - .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close)); - _apply_button.signal_clicked() - .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_apply)); - - signal_delete_event().connect(sigc::bind_return( - sigc::hide(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close)), - true)); - - add_action_widget(_close_button, Gtk::RESPONSE_CLOSE); - add_action_widget(_apply_button, Gtk::RESPONSE_APPLY); - - _apply_button.grab_default(); - - show_all_children(); - - set_focus(_fillet_chamfer_position_numeric); -} - -FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog() -{ - - _set_desktop(NULL); -} - -void FilletChamferPropertiesDialog::showDialog( - SPDesktop *desktop, Geom::Point knotpoint, - const Inkscape::LivePathEffect:: - FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit, - bool use_distance, - bool aprox_radius, - Glib::ustring const * documentUnit) -{ - FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); - - dialog->_set_desktop(desktop); - dialog->_set_unit(unit); - dialog->_set_use_distance(use_distance); - dialog->_set_aprox(aprox_radius); - dialog->_set_document_unit(documentUnit); - dialog->_set_knot_point(knotpoint); - dialog->_set_pt(pt); - - dialog->set_title(_("Modify Fillet-Chamfer")); - dialog->_apply_button.set_label(_("_Modify")); - - dialog->set_modal(true); - desktop->setWindowTransient(dialog->gobj()); - dialog->property_destroy_with_parent() = true; - - dialog->show(); - dialog->present(); -} - -void FilletChamferPropertiesDialog::_apply() -{ - double d_width; - double d_pos = _fillet_chamfer_position_numeric.get_value(); - if (d_pos) { - if (_fillet_chamfer_type_fillet.get_active() == true) { - d_width = 1; - } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { - d_width = 2; - } else if (_fillet_chamfer_type_inverse_chamfer.get_active() == true) { - d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 4000; - } else { - d_width = _fillet_chamfer_chamfer_subdivisions.get_value() + 3000; - } - if (_flexible) { - if (d_pos > 99.99999 || d_pos < 0) { - d_pos = 0; - } - d_pos = _index + (d_pos / 100); - } else { - d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, *document_unit); - d_pos = d_pos * -1; - } - _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); - } - _close(); -} - -void FilletChamferPropertiesDialog::_close() -{ - _set_desktop(NULL); - destroy_(); - Glib::signal_idle().connect( - sigc::bind_return( - sigc::bind(sigc::ptr_fun(&::operator delete), this), - false - ) - ); -} - -bool FilletChamferPropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/) -{ - return false; -} - -void FilletChamferPropertiesDialog::_handleButtonEvent(GdkEventButton *event) -{ - if ((event->type == GDK_2BUTTON_PRESS) && (event->button == 1)) { - _apply(); - } -} - -void FilletChamferPropertiesDialog::_set_knot_point(Geom::Point knotpoint) -{ - double position; - std::string distance_or_radius = std::string(_("Radius")); - if(aprox){ - distance_or_radius = std::string(_("Radius approximated")); - } - if(use_distance){ - distance_or_radius = std::string(_("Knot distance")); - } - if (knotpoint.x() > 0) { - double intpart; - position = modf(knotpoint[Geom::X], &intpart) * 100; - _flexible = true; - _index = intpart; - _fillet_chamfer_position_label.set_label(_("Position (%):")); - } else { - _flexible = false; - std::string posConcat = Glib::ustring::compose (_("%1 (%2):"), distance_or_radius, unit); - _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); - position = knotpoint[Geom::X] * -1; - - position = Inkscape::Util::Quantity::convert(position, *document_unit, unit); - } - _fillet_chamfer_position_numeric.set_value(position); - if (knotpoint.y() == 1) { - _fillet_chamfer_type_fillet.set_active(true); - } else if (knotpoint.y() == 2) { - _fillet_chamfer_type_inverse_fillet.set_active(true); - } else if (knotpoint.y() >= 3000 && knotpoint.y() < 4000) { - _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 3000); - _fillet_chamfer_type_chamfer.set_active(true); - } else if (knotpoint.y() >= 4000 && knotpoint.y() < 5000) { - _fillet_chamfer_chamfer_subdivisions.set_value(knotpoint.y() - 4000); - _fillet_chamfer_type_inverse_chamfer.set_active(true); - } -} - -void FilletChamferPropertiesDialog::_set_pt( - const Inkscape::LivePathEffect:: - FilletChamferPointArrayParamKnotHolderEntity *pt) -{ - _knotpoint = const_cast< - Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity *>( - pt); -} - -void FilletChamferPropertiesDialog::_set_unit(const gchar *abbr) -{ - unit = abbr; -} - -void FilletChamferPropertiesDialog::_set_document_unit(Glib::ustring const *abbr) -{ - document_unit = abbr; -} - -void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance) -{ - use_distance = use_knot_distance; -} - -void FilletChamferPropertiesDialog::_set_aprox(bool aprox_radius) -{ - aprox = aprox_radius; -} - -void FilletChamferPropertiesDialog::_set_desktop(SPDesktop *desktop) -{ - if (desktop) { - Inkscape::GC::anchor(desktop); - } - if (_desktop) { - Inkscape::GC::release(_desktop); - } - _desktop = desktop; -} - -} // namespace -} // namespace -} // namespace - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: -// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 -// : diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index 3807e98c8..e69de29bb 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -1,115 +0,0 @@ -/** - * - * From the code of Liam P.White from his Power Stroke Knot dialog - * - * Released under GNU GPL. Read the file 'COPYING' for more information - */ - -#ifndef INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H -#define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H - -#include <2geom/point.h> -#include <gtkmm.h> -#include "live_effects/parameter/filletchamferpointarray.h" - -class SPDesktop; - -namespace Inkscape { -namespace UI { -namespace Dialogs { - -class FilletChamferPropertiesDialog : public Gtk::Dialog { -public: - FilletChamferPropertiesDialog(); - virtual ~FilletChamferPropertiesDialog(); - - Glib::ustring getName() const { - return "LayerPropertiesDialog"; - } - - static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, - const Inkscape::LivePathEffect:: - FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit, - bool use_distance, - bool aprox_radius, - Glib::ustring const * documentUnit); - -protected: - - SPDesktop *_desktop; - Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity * - _knotpoint; - - Gtk::Label _fillet_chamfer_position_label; - Gtk::SpinButton _fillet_chamfer_position_numeric; - Gtk::RadioButton::Group _fillet_chamfer_type_group; - Gtk::RadioButton _fillet_chamfer_type_fillet; - Gtk::RadioButton _fillet_chamfer_type_inverse_fillet; - Gtk::RadioButton _fillet_chamfer_type_chamfer; - Gtk::RadioButton _fillet_chamfer_type_inverse_chamfer; - Gtk::Label _fillet_chamfer_chamfer_subdivisions_label; - Gtk::SpinButton _fillet_chamfer_chamfer_subdivisions; - - Gtk::Table _layout_table; - bool _position_visible; - double _index; - - Gtk::Button _close_button; - Gtk::Button _apply_button; - - sigc::connection _destroy_connection; - - static FilletChamferPropertiesDialog &_instance() { - static FilletChamferPropertiesDialog instance; - return instance; - } - - void _set_desktop(SPDesktop *desktop); - void _set_pt(const Inkscape::LivePathEffect:: - FilletChamferPointArrayParamKnotHolderEntity *pt); - void _set_unit(const gchar *abbr); - void _set_document_unit(Glib::ustring const * abbr); - void _set_use_distance(bool use_knot_distance); - void _set_aprox(bool aprox_radius); - void _apply(); - void _close(); - bool _flexible; - const gchar *unit; - Glib::ustring const * document_unit; - bool use_distance; - bool aprox; - void _set_knot_point(Geom::Point knotpoint); - void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); - - bool _handleKeyEvent(GdkEventKey *event); - void _handleButtonEvent(GdkEventButton *event); - - friend class Inkscape::LivePathEffect:: - FilletChamferPointArrayParamKnotHolderEntity; - -private: - FilletChamferPropertiesDialog( - FilletChamferPropertiesDialog const &); // no copy - FilletChamferPropertiesDialog &operator=( - FilletChamferPropertiesDialog const &); // no assign -}; - -} // namespace -} // namespace -} // namespace - -#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: -// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 -// : |
