summaryrefslogtreecommitdiffstats
path: root/src/live_effects/lpe-fillet-chamfer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/live_effects/lpe-fillet-chamfer.cpp')
-rw-r--r--src/live_effects/lpe-fillet-chamfer.cpp163
1 files changed, 69 insertions, 94 deletions
diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp
index 1dffba1bf..0ad21a284 100644
--- a/src/live_effects/lpe-fillet-chamfer.cpp
+++ b/src/live_effects/lpe-fillet-chamfer.cpp
@@ -22,6 +22,9 @@
#include "desktop.h"
#include "display/curve.h"
#include "helper/geom-nodetype.h"
+#include "helper/geom-curves.h"
+#include "helper/geom.h"
+
#include "live_effects/parameter/filletchamferpointarray.h"
// for programmatically updating knots
@@ -49,6 +52,8 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) :
ignore_radius_0(_("Ignore 0 radius knots"), _("Ignore 0 radius knots"), "ignore_radius_0", &wr, this, false),
only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false),
flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), "flexible", &wr, this, false),
+ force_arcs(_("Use arcs in cubic curves"), _("Use arcs in cubic curves"), "force_arcs", &wr, this, false),
+ use_knot_distance(_("Use knots distance instead radius"), _("Use knots distance instead radius"), "use_knot_distance", &wr, this, false),
unit(_("Unit"), _("Unit"), "unit", &wr, this),
radius(_("Radius (unit or %)"), _("Radius, in unit or %"), "radius", &wr, this, 0.),
helper_size(_("Helper size with direction"), _("Helper size with direction"), "helper_size", &wr, this, 0)
@@ -58,9 +63,11 @@ LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) :
registerParameter(&radius);
registerParameter(&helper_size);
registerParameter(&flexible);
+ registerParameter(&use_knot_distance);
registerParameter(&ignore_radius_0);
registerParameter(&only_selected);
registerParameter(&hide_knots);
+ registerParameter(&force_arcs);
radius.param_set_range(0., infinity());
radius.param_set_increments(1, 1);
@@ -270,10 +277,10 @@ void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pa
}
std::vector<Point> filletChamferData = fillet_chamfer_values.data();
std::vector<Geom::Point> result;
+ std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
int counter = 0;
- for (PathVector::const_iterator path_it = original_pathv.begin();
- path_it != original_pathv.end(); ++path_it) {
- int pathCounter = 0;
+ for (PathVector::const_iterator path_it = original_pathv_processed.begin();
+ path_it != original_pathv_processed.end(); ++path_it) {
if (path_it->empty())
continue;
@@ -289,6 +296,9 @@ void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pa
double powerend = 0;
while (curve_it1 != curve_endit) {
powerend = power;
+ if (power < 0 && !use_knot_distance) {
+ powerend = fillet_chamfer_values.rad_to_len(counter,powerend);
+ }
if (power > 0) {
powerend = counter + (power / 100);
}
@@ -306,7 +316,6 @@ void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pa
++curve_it1;
++curve_it2;
counter++;
- pathCounter++;
}
}
fillet_chamfer_values.param_set_and_write_new_value(result);
@@ -334,8 +343,9 @@ void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_path
}
std::vector<Point> filletChamferData = fillet_chamfer_values.data();
std::vector<Geom::Point> result;
+ std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
int counter = 0;
- for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
+ for (PathVector::const_iterator path_it = original_pathv_processed.begin(); path_it != original_pathv_processed.end(); ++path_it) {
int pathCounter = 0;
if (path_it->empty())
continue;
@@ -378,7 +388,7 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
{
if (SP_IS_SHAPE(lpeItem)) {
std::vector<Point> point;
- PathVector const &original_pathv = SP_SHAPE(lpeItem)->_curve->get_pathvector();
+ PathVector const &original_pathv = pathv_to_linear_and_cubic_beziers(SP_SHAPE(lpeItem)->_curve->get_pathvector());
Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
if (path_it->empty())
@@ -401,10 +411,15 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
}
int counter = 0;
while (curve_it1 != curve_endit) {
+ std::pair<std::size_t, std::size_t> positions = fillet_chamfer_values.get_positions(counter, original_pathv);
Geom::NodeType nodetype;
- if (counter == 0) {
+ if (positions.second == 0) {
if (path_it->closed()) {
- nodetype = get_nodetype(path_it->back_default(), *curve_it1);
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(pwd2_in[fillet_chamfer_values.last_index(counter, original_pathv)], 1);
+ Geom::Curve const * A = path_from_piecewise(u, 0.1)[0][0].duplicate();
+ nodetype = get_nodetype(*A, *curve_it1);
} else {
nodetype = NODE_NONE;
}
@@ -433,12 +448,15 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem)
{
if (SP_IS_SHAPE(lpeItem)) {
fillet_chamfer_values.set_helper_size(helper_size);
+ fillet_chamfer_values.set_use_distance(use_knot_distance);
fillet_chamfer_values.set_unit(unit.get_abbreviation());
- SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem)->get_original_curve() : SP_SHAPE(lpeItem)->getCurve();
+ SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem)
+ ->get_original_curve()
+ : SP_SHAPE(lpeItem)->getCurve();
std::vector<Point> filletChamferData = fillet_chamfer_values.data();
if (!filletChamferData.empty() && getKnotsNumber(c) != (int)
filletChamferData.size()) {
- PathVector const original_pathv = c->get_pathvector();
+ PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pwd2_in);
}
@@ -450,7 +468,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem)
int LPEFilletChamfer::getKnotsNumber(SPCurve const *c)
{
int nKnots = c->nodes_in_path();
- PathVector const pv = c->get_pathvector();
+ PathVector const pv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
for (std::vector<Geom::Path>::const_iterator path_it = pv.begin();
path_it != pv.end(); ++path_it) {
if (!(*path_it).closed()) {
@@ -464,8 +482,7 @@ void
LPEFilletChamfer::adjustForNewPath(std::vector<Geom::Path> const &path_in)
{
if (!path_in.empty()) {
- fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(path_in[0]
- .toPwSb());
+ fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pathv_to_linear_and_cubic_beziers(path_in)[0].toPwSb());
}
}
@@ -473,17 +490,17 @@ std::vector<Geom::Path>
LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
{
std::vector<Geom::Path> pathvector_out;
- Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(path_in);
+ Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(pathv_to_linear_and_cubic_beziers(path_in));
pwd2_in = remove_short_cuts(pwd2_in, .01);
Piecewise<D2<SBasis> > der = derivative(pwd2_in);
Piecewise<D2<SBasis> > n = rot90(unitVector(der));
fillet_chamfer_values.set_pwd2(pwd2_in, n);
std::vector<Point> filletChamferData = fillet_chamfer_values.data();
unsigned int counter = 0;
- //from http://launchpadlibrarian.net/12692602/rcp.svg
const double K = (4.0 / 3.0) * (sqrt(2.0) - 1.0);
- for (PathVector::const_iterator path_it = path_in.begin();
- path_it != path_in.end(); ++path_it) {
+ std::vector<Geom::Path> path_in_processed = pathv_to_linear_and_cubic_beziers(path_in);
+ for (PathVector::const_iterator path_it = path_in_processed.begin();
+ path_it != path_in_processed.end(); ++path_it) {
if (path_it->empty())
continue;
Geom::Path path_out;
@@ -504,81 +521,24 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
}
unsigned int counterCurves = 0;
while (curve_it1 != curve_endit) {
- Coord it1_length = (*curve_it1).length(tolerance);
- double time_it1, time_it2, time_it1_B, intpart;
- time_it1 = modf(
- fillet_chamfer_values.to_time(counter, filletChamferData[counter][X]),
- &intpart);
- if (filletChamferData[counter][Y] == 0) {
- time_it1 = 0;
- }
- if (path_it->closed() && curve_it2 == curve_endit) {
- time_it2 = modf(fillet_chamfer_values.to_time(
- counter - counterCurves,
- filletChamferData[counter - counterCurves][X]),
- &intpart);
- } else if (!path_it->closed() && curve_it2 == curve_endit){
- time_it2 = 0;
- } else {
- time_it2 = modf(fillet_chamfer_values.to_time(
- counter + 1, filletChamferData[counter + 1][X]),
- &intpart);
- }
- double resultLenght = 0;
- time_it1_B = 1;
- if (path_it->closed() && curve_it2 == curve_endit) {
- resultLenght =
- it1_length + fillet_chamfer_values.to_len(
- counter - counterCurves,
- filletChamferData[counter - counterCurves][X]);
- } else if (!path_it->closed() && curve_it2 == curve_endit){
- resultLenght = 0;
- } else {
- resultLenght =
- it1_length + fillet_chamfer_values.to_len(
- counter + 1, filletChamferData[counter + 1][X]);
- }
- if (resultLenght > 0 && time_it2 != 0) {
- time_it1_B = modf(fillet_chamfer_values.to_time(counter, -resultLenght),
- &intpart);
- } else {
- if (time_it2 == 0) {
- time_it1_B = 1;
- } else {
- time_it1_B = gapHelper;
- }
- }
- if (path_it->closed() && curve_it2 == curve_endit &&
- filletChamferData[counter - counterCurves][Y] == 0) {
- time_it1_B = 1;
- time_it2 = 0;
- } else if (path_it->size() > counterCurves + 1 &&
- filletChamferData[counter + 1][Y] == 0) {
- time_it1_B = 1;
- time_it2 = 0;
+ Curve *curve_it2Fixed = (*path_it->begin()).duplicate();
+ if(!path_it->closed() || curve_it2 != curve_endit){
+ curve_it2Fixed = (*curve_it2).duplicate();
}
- if (time_it1_B < time_it1) {
- time_it1_B = time_it1 + gapHelper;
- }
- Curve *knotCurve1 = curve_it1->portion(time_it1, time_it1_B);
+ bool last = curve_it2 == curve_endit;
+ std::vector<double> times = fillet_chamfer_values.get_times(counter, path_in, last);
+ Curve *knotCurve1 = curve_it1->portion(times[0], times[1]);
if (counterCurves > 0) {
knotCurve1->setInitial(path_out.finalPoint());
} else {
- path_out.start((*curve_it1).pointAt(time_it1));
- }
- Curve *knotCurve2 = (*path_it).front().portion(time_it2, 1);
- if (curve_it2 != curve_endit) {
- knotCurve2 = (*curve_it2).portion(time_it2, 1);
+ path_out.start((*curve_it1).pointAt(times[0]));
}
+ Curve *knotCurve2 = curve_it2Fixed->portion(times[2], 1);
Point startArcPoint = knotCurve1->finalPoint();
- Point endArcPoint = (*path_it).front().pointAt(time_it2);
- if (curve_it2 != curve_endit) {
- endArcPoint = (*curve_it2).pointAt(time_it2);
- }
+ Point endArcPoint = curve_it2Fixed->pointAt(times[2]);
double k1 = distance(startArcPoint, curve_it1->finalPoint()) * K;
double k2 = distance(endArcPoint, curve_it1->finalPoint()) * K;
- Geom::CubicBezier const *cubic1 =
- dynamic_cast<Geom::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);
@@ -591,8 +551,7 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
ray2.setPoints(endArcPoint, (*cubic2)[1]);
}
Point handle2 = endArcPoint - Point::polar(ray2.angle(),k2);
- bool ccwToggle = cross(curve_it1->finalPoint() - startArcPoint,
- endArcPoint - startArcPoint) < 0;
+ bool ccwToggle = cross(curve_it1->finalPoint() - startArcPoint, endArcPoint - startArcPoint) < 0;
double angle = angle_between(ray1, ray2, ccwToggle);
double handleAngle = ray1.angle() - angle;
if (ccwToggle) {
@@ -604,14 +563,22 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
handleAngle = ray2.angle() - angle;
}
Point inverseHandle2 = endArcPoint - Point::polar(handleAngle,k2);
- if (time_it1_B != 1) {
- if (time_it1_B != gapHelper && time_it1_B != time_it1 + gapHelper) {
+ //straigth lines arc based
+ Line const x_line(Geom::Point(0,0),Geom::Point(1,0));
+ Line const angled_line(startArcPoint,endArcPoint);
+ 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] != gapHelper && times[1] != times[0] + gapHelper) {
path_out.append(*knotCurve1);
}
int type = 0;
- if(path_it->closed() && curve_it2 == curve_endit){
+ if(path_it->closed() && last){
type = abs(filletChamferData[counter - counterCurves][Y]);
- } else if (!path_it->closed() && curve_it2 == curve_endit){
+ } else if (!path_it->closed() && last){
//0
} else {
type = abs(filletChamferData[counter + 1][Y]);
@@ -624,15 +591,23 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
}
path_out.appendNew<Geom::LineSegment>(endArcPoint);
} else if (type == 2) {
- path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2,
- endArcPoint);
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed)) || force_arcs){
+ ccwToggle = ccwToggle?0:1;
+ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ }else{
+ path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint);
+ }
} else {
- path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
+ if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed)) || force_arcs){
+ path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
+ } else {
+ path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
+ }
}
} else {
path_out.append(*knotCurve1);
}
- if (path_it->closed() && curve_it2 == curve_endit) {
+ if (path_it->closed() && last) {
path_out.close();
}
++curve_it1;