summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/lpe-bspline.cpp360
-rw-r--r--src/ui/tools/freehand-base.cpp8
-rw-r--r--src/ui/tools/pen-tool.cpp232
3 files changed, 216 insertions, 384 deletions
diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp
index 433696aab..1141e87ef 100644
--- a/src/live_effects/lpe-bspline.cpp
+++ b/src/live_effects/lpe-bspline.cpp
@@ -52,6 +52,7 @@ using Inkscape::DocumentUndo;
namespace Inkscape {
namespace LivePathEffect {
+const double handleCubicGap = 0.01;
LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
steps(_("Steps whith CTRL:"), _("Change number of steps whith CTRL pressed"), "steps", &wr, this, 2),
@@ -97,192 +98,136 @@ void LPEBSpline::createAndApply(const char *name, SPDocument *doc, SPItem *item)
void LPEBSpline::doEffect(SPCurve *curve)
{
- if (curve->get_segment_count() < 1)
+ if (curve->get_segment_count() < 1){
return;
- // Make copy of old path as it is changed during processing
+ }
+
Geom::PathVector const original_pathv = curve->get_pathvector();
curve->reset();
- //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el
- //penúltimo
for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
path_it != original_pathv.end(); ++path_it) {
- //Si está vacío...
if (path_it->empty())
continue;
- //Itreadores
- Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
- Geom::Path::const_iterator curve_it2 =
- ++(path_it->begin()); // outgoing curve
- Geom::Path::const_iterator curve_endit =
- path_it->end_default(); // this determines when the loop has to stop
- //Creamos las lineas rectas que unen todos los puntos del trazado y donde se
- //calcularán
- //los puntos clave para los manejadores.
- //Esto hace que la curva BSpline no pierda su condición aunque se trasladen
- //dichos manejadores
+ 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();
SPCurve *nCurve = new SPCurve();
Geom::Point previousNode(0, 0);
Geom::Point node(0, 0);
Geom::Point pointAt1(0, 0);
Geom::Point pointAt2(0, 0);
Geom::Point nextPointAt1(0, 0);
- Geom::Point nextPointAt2(0, 0);
- Geom::Point nextPointAt3(0, 0);
Geom::D2<Geom::SBasis> SBasisIn;
Geom::D2<Geom::SBasis> SBasisOut;
Geom::D2<Geom::SBasis> SBasisHelper;
Geom::CubicBezier const *cubic = NULL;
if (path_it->closed()) {
- // if the path is closed, maybe we have to stop a bit earlier because the
- // closing line segment has zerolength.
- const Geom::Curve &closingline =
- path_it->back_closed(); // the closing line segment is always of type
- // Geom::LineSegment.
+ const Geom::Curve &closingline = path_it->back_closed();
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();
}
}
- //Si la curva está cerrada calculamos el punto donde
- //deveria estar el nodo BSpline de cierre/inicio de la curva
- //en posible caso de que se cierre con una linea recta creando un nodo
- //BSPline
nCurve->moveto(curve_it1->initialPoint());
- //Recorremos todos los segmentos menos el último
- while (curve_it2 != curve_endit) {
- //previousPointAt3 = pointAt3;
- //Calculamos los puntos que dividirían en tres segmentos iguales el path
- //recto de entrada y de salida
+ while (curve_it1 != curve_endit) {
SPCurve *in = new SPCurve();
in->moveto(curve_it1->initialPoint());
in->lineto(curve_it1->finalPoint());
cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
if (cubic) {
SBasisIn = in->first_segment()->toSBasis();
- pointAt1 = SBasisIn.valueAt(
- Geom::nearest_point((*cubic)[1], *in->first_segment()));
- pointAt2 = SBasisIn.valueAt(
- Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ pointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ }
+ if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
+ pointAt2 = SBasisIn.valueAt(0.6667);
+ } else {
+ pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ }
} else {
pointAt1 = in->first_segment()->initialPoint();
pointAt2 = in->first_segment()->finalPoint();
}
in->reset();
delete in;
- //Y hacemos lo propio con el path de salida
- //nextPointAt0 = curveOut.valueAt(0);
- SPCurve *out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
- if (cubic) {
- SBasisOut = out->first_segment()->toSBasis();
- nextPointAt1 = SBasisOut.valueAt(
- Geom::nearest_point((*cubic)[1], *out->first_segment()));
- nextPointAt2 = SBasisOut.valueAt(
- Geom::nearest_point((*cubic)[2], *out->first_segment()));
- ;
- nextPointAt3 = out->first_segment()->finalPoint();
+ if ( curve_it2 != curve_endit ) {
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ nextPointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ }
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ }
+ out->reset();
+ delete out;
+ }
+ Geom::Point startNode = path_it->begin()->initialPoint();
+ if (path_it->closed() && curve_it2 == curve_endit) {
+ SPCurve *start = new SPCurve();
+ start->moveto(path_it->begin()->initialPoint());
+ start->lineto(path_it->begin()->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
+ SPCurve *lineHelper = new SPCurve();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
+ if (cubic) {
+ lineHelper->moveto(SBasisStart.valueAt(
+ Geom::nearest_point((*cubic)[1], *start->first_segment())));
+ } else {
+ lineHelper->moveto(start->first_segment()->initialPoint());
+ }
+ start->reset();
+ delete start;
+
+ SPCurve *end = new SPCurve();
+ end->moveto(curve_it1->initialPoint());
+ end->lineto(curve_it1->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ lineHelper->lineto(SBasisEnd.valueAt(
+ Geom::nearest_point((*cubic)[2], *end->first_segment())));
+ } else {
+ lineHelper->lineto(end->first_segment()->finalPoint());
+ }
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ startNode = SBasisHelper.valueAt(0.5);
+ nCurve->curveto(pointAt1, pointAt2, startNode);
+ nCurve->move_endpoints(startNode, startNode);
+ } else if ( curve_it2 == curve_endit) {
+ nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
} else {
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- nextPointAt3 = out->first_segment()->finalPoint();
+ SPCurve *lineHelper = new SPCurve();
+ lineHelper->moveto(pointAt2);
+ lineHelper->lineto(nextPointAt1);
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ previousNode = node;
+ node = SBasisHelper.valueAt(0.5);
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
+ node = curve_it1->finalPoint();
+ }
+ nCurve->curveto(pointAt1, pointAt2, node);
}
- out->reset();
- delete out;
- //La curva BSpline se forma calculando el centro del segmanto de unión
- //de el punto situado en las 2/3 partes de el segmento de entrada
- //con el punto situado en la posición 1/3 del segmento de salida
- //Estos dos puntos ademas estan posicionados en el lugas correspondiente
- //de
- //los manejadores de la curva
- SPCurve *lineHelper = new SPCurve();
- lineHelper->moveto(pointAt2);
- lineHelper->lineto(nextPointAt1);
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- //almacenamos el punto del anterior bucle -o el de cierre- que nos hara de
- //principio de curva
- previousNode = node;
- //Y este hará de final de curva
- node = SBasisHelper.valueAt(0.5);
- nCurve->curveto(pointAt1, pointAt2, node);
- //aumentamos los valores para el siguiente paso en el bucle
++curve_it1;
++curve_it2;
}
- SPCurve *out = new SPCurve();
- out->moveto(curve_it1->initialPoint());
- out->lineto(curve_it1->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- SBasisOut = out->first_segment()->toSBasis();
- nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
- nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2], *out->first_segment()));
- nextPointAt3 = out->first_segment()->finalPoint();
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- nextPointAt3 = out->first_segment()->finalPoint();
- }
- out->reset();
- delete out;
- //Si está cerrada la curva, la cerramos sobre el valor guardado
- //previamente
- //Si no finalizamos en el punto final
- Geom::Point startNode = path_it->begin()->initialPoint();
- if (path_it->closed()) {
- SPCurve *start = new SPCurve();
- start->moveto(path_it->begin()->initialPoint());
- start->lineto(path_it->begin()->finalPoint());
- Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
- SPCurve *lineHelper = new SPCurve();
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
- if (cubic) {
- lineHelper->moveto(SBasisStart.valueAt(
- Geom::nearest_point((*cubic)[1], *start->first_segment())));
- } else {
- lineHelper->moveto(start->first_segment()->initialPoint());
- }
- start->reset();
- delete start;
-
- SPCurve *end = new SPCurve();
- end->moveto(curve_it1->initialPoint());
- end->lineto(curve_it1->finalPoint());
- Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
-
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- lineHelper->lineto(SBasisEnd.valueAt(
- Geom::nearest_point((*cubic)[2], *end->first_segment())));
- } else {
- lineHelper->lineto(end->first_segment()->finalPoint());
- }
- end->reset();
- delete end;
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- startNode = SBasisHelper.valueAt(0.5);
- nCurve->curveto(nextPointAt1, nextPointAt2, startNode);
- nCurve->move_endpoints(startNode, startNode);
- } else {
- SPCurve *start = new SPCurve();
- start->moveto(path_it->begin()->initialPoint());
- start->lineto(path_it->begin()->finalPoint());
- startNode = start->first_segment()->initialPoint();
- start->reset();
- delete start;
- nCurve->curveto(nextPointAt1, nextPointAt2, nextPointAt3);
- nCurve->move_endpoints(startNode, nextPointAt3);
- }
//y cerramos la curva
if (path_it->closed()) {
nCurve->closepath_current();
@@ -402,7 +347,7 @@ bool LPEBSpline::nodeIsSelected(Geom::Point nodePoint)
for (std::vector<Geom::Point>::iterator i = points.begin();
i != points.end(); ++i) {
Geom::Point p = *i;
- if (Geom::are_near(p, nodePoint, 0.0001)) {
+ if (Geom::are_near(p, nodePoint, handleCubicGap)) {
return true;
} else {
}
@@ -463,10 +408,6 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
Geom::Point pointAt1(0, 0);
Geom::Point pointAt2(0, 0);
Geom::Point pointAt3(0, 0);
- Geom::Point nextPointAt0(0, 0);
- Geom::Point nextPointAt1(0, 0);
- Geom::Point nextPointAt2(0, 0);
- Geom::Point nextPointAt3(0, 0);
Geom::D2<Geom::SBasis> SBasisIn;
Geom::D2<Geom::SBasis> SBasisOut;
Geom::CubicBezier const *cubic = NULL;
@@ -490,7 +431,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
//BSPline
nCurve->moveto(curve_it1->initialPoint());
//Recorremos todos los segmentos menos el último
- while (curve_it2 != curve_endit) {
+ while (curve_it1 != curve_endit) {
//previousPointAt3 = pointAt3;
//Calculamos los puntos que dividirían en tres segmentos iguales el path
//recto de entrada y de salida
@@ -507,7 +448,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt1 = SBasisIn.valueAt(weightValue);
if (weightValue != 0.0000) {
pointAt1 =
- Geom::Point(pointAt1[X] + 0.0001, pointAt1[Y] + 0.0001);
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
}
} else {
pointAt1 = in->first_segment()->initialPoint();
@@ -516,7 +457,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt2 = SBasisIn.valueAt(1 - weightValue);
if (weightValue != 0.0000) {
pointAt2 =
- Geom::Point(pointAt2[X] + 0.0001, pointAt2[Y] + 0.0001);
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
}
} else {
pointAt2 = in->first_segment()->finalPoint();
@@ -526,12 +467,12 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt1 = SBasisIn.valueAt(weightValue);
if (weightValue != 0.0000) {
pointAt1 =
- Geom::Point(pointAt1[X] + 0.0001, pointAt1[Y] + 0.0001);
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
}
pointAt2 = SBasisIn.valueAt(1 - weightValue);
if (weightValue != 0.0000) {
pointAt2 =
- Geom::Point(pointAt2[X] + 0.0001, pointAt2[Y] + 0.0001);
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
}
} else {
pointAt1 = in->first_segment()->initialPoint();
@@ -545,7 +486,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt1 = SBasisIn.valueAt(weightValue);
if (weightValue != 0.0000) {
pointAt1 =
- Geom::Point(pointAt1[X] + 0.0001, pointAt1[Y] + 0.0001);
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
}
} else {
pointAt1 = (*cubic)[1];
@@ -558,7 +499,7 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt2 = SBasisIn.valueAt(1 - weightValue);
if (weightValue != 0.0000) {
pointAt2 =
- Geom::Point(pointAt2[X] + 0.0001, pointAt2[Y] + 0.0001);
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
}
} else {
pointAt2 = (*cubic)[2];
@@ -567,18 +508,18 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
pointAt2 = in->first_segment()->finalPoint();
}
} else {
- if (!ignoreCusp && weightValue != 0.000) {
+ if (!ignoreCusp && weightValue != 0.0000) {
if (nodeIsSelected(pointAt0)) {
pointAt1 = SBasisIn.valueAt(weightValue);
pointAt1 =
- Geom::Point(pointAt1[X] + 0.0001, pointAt1[Y] + 0.0001);
+ Geom::Point(pointAt1[X] + handleCubicGap, pointAt1[Y] + handleCubicGap);
} else {
pointAt1 = in->first_segment()->initialPoint();
}
if (nodeIsSelected(pointAt3)) {
pointAt2 = SBasisIn.valueAt(weightValue);
pointAt2 =
- Geom::Point(pointAt2[X] + 0.0001, pointAt2[Y] + 0.0001);
+ Geom::Point(pointAt2[X] + handleCubicGap, pointAt2[Y] + handleCubicGap);
} else {
pointAt2 = in->first_segment()->finalPoint();
}
@@ -601,110 +542,11 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weightValue)
++curve_it1;
++curve_it2;
}
- SPCurve *out = new SPCurve();
- out->moveto(curve_it1->initialPoint());
- out->lineto(curve_it1->finalPoint());
- SBasisOut = out->first_segment()->toSBasis();
- nextPointAt0 = out->first_segment()->initialPoint();
- nextPointAt3 = out->first_segment()->finalPoint();
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (!onlySelected) {
- if (cubic) {
- if (!ignoreCusp || !Geom::are_near((*cubic)[1], nextPointAt0)) {
- nextPointAt1 = SBasisOut.valueAt(weightValue);
- if (weightValue != 0.0000) {
- nextPointAt1 =
- Geom::Point(nextPointAt1[X] + 0.0001, nextPointAt1[Y] + 0.0001);
- }
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- }
- if (!ignoreCusp || !Geom::are_near((*cubic)[2], nextPointAt3)) {
- nextPointAt2 = SBasisOut.valueAt(1 - weightValue);
- if (weightValue != 0.0000) {
- nextPointAt2 =
- Geom::Point(nextPointAt2[X] + 0.0001, nextPointAt2[Y] + 0.0001);
- }
- } else {
- nextPointAt2 = out->first_segment()->finalPoint();
- }
- } else {
- if (!ignoreCusp && weightValue != 0.0000) {
- nextPointAt1 = SBasisOut.valueAt(weightValue);
- nextPointAt1 =
- Geom::Point(nextPointAt1[X] + 0.0001, nextPointAt1[Y] + 0.0001);
- nextPointAt2 = SBasisOut.valueAt(1 - weightValue);
- nextPointAt2 =
- Geom::Point(nextPointAt2[X] + 0.0001, nextPointAt2[Y] + 0.0001);
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- }
- }
- } else {
- if (cubic) {
- if (!ignoreCusp || !Geom::are_near((*cubic)[1], nextPointAt0)) {
- if (nodeIsSelected(nextPointAt0)) {
- nextPointAt1 = SBasisOut.valueAt(weightValue);
- if (weightValue != 0.0000) {
- nextPointAt1 = Geom::Point(nextPointAt1[X] + 0.0001,
- nextPointAt1[Y] + 0.0001);
- }
- } else {
- nextPointAt1 = (*cubic)[1];
- }
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- }
- if (!ignoreCusp || !Geom::are_near((*cubic)[2], nextPointAt3)) {
- if (nodeIsSelected(nextPointAt3)) {
- nextPointAt2 = SBasisOut.valueAt(1 - weightValue);
- if (weightValue != 0.0000) {
- nextPointAt2 = Geom::Point(nextPointAt2[X] + 0.0001,
- nextPointAt2[Y] + 0.0001);
- }
- } else {
- nextPointAt2 = (*cubic)[2];
- }
- } else {
- nextPointAt2 = out->first_segment()->finalPoint();
- }
- } else {
- if (!ignoreCusp && weightValue != 0.0000) {
- if (nodeIsSelected(nextPointAt0)) {
- nextPointAt1 = SBasisOut.valueAt(weightValue);
- nextPointAt1 =
- Geom::Point(nextPointAt1[X] + 0.0001, nextPointAt1[Y] + 0.0001);
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- }
- if (nodeIsSelected(nextPointAt3)) {
- nextPointAt2 = SBasisOut.valueAt(weightValue);
- nextPointAt2 =
- Geom::Point(nextPointAt2[X] + 0.0001, nextPointAt2[Y] + 0.0001);
- } else {
- nextPointAt2 = out->first_segment()->finalPoint();
- }
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- }
- }
- }
- out->reset();
- delete out;
- //Aberiguamos la ultima parte de la curva correspondiente al último
- //segmento
- //Y hacemos lo propio con el path de salida
- //nextPointAt0 = curveOut.valueAt(0);
if (path_it->closed()) {
- nCurve->curveto(nextPointAt1, nextPointAt2,
- path_it->begin()->initialPoint());
nCurve->move_endpoints(path_it->begin()->initialPoint(),
path_it->begin()->initialPoint());
} else {
- nCurve->curveto(nextPointAt1, nextPointAt2, nextPointAt3);
- nCurve->move_endpoints(path_it->begin()->initialPoint(), nextPointAt3);
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), pointAt3);
}
//y cerramos la curva
if (path_it->closed()) {
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index bab6bc7e3..17f173e47 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -609,12 +609,12 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
if (dc->sa) {
SPCurve *s = dc->sa->curve;
dc->white_curves = g_slist_remove(dc->white_curves, s);
- if (dc->sa->start) {
- s = reverse_then_unref(s);
- }
if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 ||
prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){
- dc->overwriteCurve = s;
+ s = dc->overwriteCurve;
+ }
+ if (dc->sa->start) {
+ s = reverse_then_unref(s);
}
s->append_continuous(c, 0.0625);
c->unref();
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index b68231e10..a72934ae3 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -1827,155 +1827,145 @@ void PenTool::_bspline_spiro_build()
void PenTool::_bspline_doEffect(SPCurve * curve)
{
// commenting the function doEffect in src/live_effects/lpe-bspline.cpp
- Geom::PathVector const original_pathv = curve->get_pathvector();
- if (curve->get_segment_count() < 1)
+ if (curve->get_segment_count() < 1){
return;
+ }
+ // Make copy of old path as it is changed during processing
+ Geom::PathVector const original_pathv = curve->get_pathvector();
curve->reset();
- for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
+ //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el
+ //penúltimo
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+ //Si está vacío...
if (path_it->empty())
continue;
+ //Itreadores
- Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve
- Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop
+ 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();
SPCurve *nCurve = new SPCurve();
- Geom::Point previousNode(0,0);
- Geom::Point node(0,0);
- Geom::Point pointAt1(0,0);
- Geom::Point pointAt2(0,0);
- Geom::Point nextPointAt1(0,0);
- Geom::Point nextPointAt2(0,0);
- Geom::Point nextPointAt3(0,0);
- Geom::D2< Geom::SBasis > SBasisIn;
- Geom::D2< Geom::SBasis > SBasisOut;
- Geom::D2< Geom::SBasis > SBasisHelper;
+ Geom::Point previousNode(0, 0);
+ Geom::Point node(0, 0);
+ Geom::Point pointAt1(0, 0);
+ Geom::Point pointAt2(0, 0);
+ Geom::Point nextPointAt1(0, 0);
+ Geom::D2<Geom::SBasis> SBasisIn;
+ Geom::D2<Geom::SBasis> SBasisOut;
+ Geom::D2<Geom::SBasis> SBasisHelper;
Geom::CubicBezier const *cubic = NULL;
if (path_it->closed()) {
- const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
curve_endit = path_it->end_open();
}
}
- while ( curve_it2 != curve_endit )
- {
- SPCurve * in = new SPCurve();
+ nCurve->moveto(curve_it1->initialPoint());
+ while (curve_it1 != curve_endit) {
+ SPCurve *in = new SPCurve();
in->moveto(curve_it1->initialPoint());
in->lineto(curve_it1->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
- if(cubic){
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
SBasisIn = in->first_segment()->toSBasis();
- pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()));
- pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2],*in->first_segment()));
- }else{
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ pointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1], *in->first_segment()));
+ }
+ if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
+ pointAt2 = SBasisIn.valueAt(0.6667);
+ } else {
+ pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2], *in->first_segment()));
+ }
+ } else {
pointAt1 = in->first_segment()->initialPoint();
pointAt2 = in->first_segment()->finalPoint();
}
in->reset();
delete in;
- SPCurve * out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it2);
- if(cubic){
- SBasisOut = out->first_segment()->toSBasis();
- nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1],*out->first_segment()));
- nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2],*out->first_segment()));;
- nextPointAt3 = (*cubic)[3];
- }else{
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- nextPointAt3 = out->first_segment()->finalPoint();
+ if ( curve_it2 != curve_endit ) {
+ SPCurve *out = new SPCurve();
+ out->moveto(curve_it2->initialPoint());
+ out->lineto(curve_it2->finalPoint());
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
+ if (cubic) {
+ SBasisOut = out->first_segment()->toSBasis();
+ if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
+ nextPointAt1 = SBasisIn.valueAt(0.3334);
+ } else {
+ nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
+ }
+ } else {
+ nextPointAt1 = out->first_segment()->initialPoint();
+ }
+ out->reset();
+ delete out;
+ }
+ Geom::Point startNode = path_it->begin()->initialPoint();
+ if (path_it->closed() && curve_it2 == curve_endit) {
+ SPCurve *start = new SPCurve();
+ start->moveto(path_it->begin()->initialPoint());
+ start->lineto(path_it->begin()->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisStart = start->first_segment()->toSBasis();
+ SPCurve *lineHelper = new SPCurve();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
+ if (cubic) {
+ lineHelper->moveto(SBasisStart.valueAt(
+ Geom::nearest_point((*cubic)[1], *start->first_segment())));
+ } else {
+ lineHelper->moveto(start->first_segment()->initialPoint());
+ }
+ start->reset();
+ delete start;
+
+ SPCurve *end = new SPCurve();
+ end->moveto(curve_it1->initialPoint());
+ end->lineto(curve_it1->finalPoint());
+ Geom::D2<Geom::SBasis> SBasisEnd = end->first_segment()->toSBasis();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ lineHelper->lineto(SBasisEnd.valueAt(
+ Geom::nearest_point((*cubic)[2], *end->first_segment())));
+ } else {
+ lineHelper->lineto(end->first_segment()->finalPoint());
+ }
+ end->reset();
+ delete end;
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ startNode = SBasisHelper.valueAt(0.5);
+ nCurve->curveto(pointAt1, pointAt2, startNode);
+ nCurve->move_endpoints(startNode, startNode);
+ } else if ( curve_it2 == curve_endit) {
+ nCurve->curveto(pointAt1, pointAt2, curve_it1->finalPoint());
+ nCurve->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
+ } else {
+ SPCurve *lineHelper = new SPCurve();
+ lineHelper->moveto(pointAt2);
+ lineHelper->lineto(nextPointAt1);
+ SBasisHelper = lineHelper->first_segment()->toSBasis();
+ lineHelper->reset();
+ delete lineHelper;
+ previousNode = node;
+ node = SBasisHelper.valueAt(0.5);
+ Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
+ node = curve_it1->finalPoint();
+ }
+ nCurve->curveto(pointAt1, pointAt2, node);
}
- out->reset();
- delete out;
- SPCurve *lineHelper = new SPCurve();
- lineHelper->moveto(pointAt2);
- lineHelper->lineto(nextPointAt1);
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- previousNode = node;
- node = SBasisHelper.valueAt(0.5);
- SPCurve *curveHelper = new SPCurve();
- curveHelper->moveto(previousNode);
- curveHelper->curveto(pointAt1, pointAt2, node);
- nCurve->append_continuous(curveHelper, 0.0625);
- curveHelper->reset();
- delete curveHelper;
++curve_it1;
++curve_it2;
}
- SPCurve *out = new SPCurve();
- out->moveto(curve_it1->initialPoint());
- out->lineto(curve_it1->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- SBasisOut = out->first_segment()->toSBasis();
- nextPointAt1 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[1], *out->first_segment()));
- nextPointAt2 = SBasisOut.valueAt(Geom::nearest_point((*cubic)[2], *out->first_segment()));
- nextPointAt3 = out->first_segment()->finalPoint();
- } else {
- nextPointAt1 = out->first_segment()->initialPoint();
- nextPointAt2 = out->first_segment()->finalPoint();
- nextPointAt3 = out->first_segment()->finalPoint();
- }
- out->reset();
- delete out;
- SPCurve *curveHelper = new SPCurve();
- curveHelper->moveto(node);
- Geom::Point startNode = path_it->begin()->initialPoint();
- if (path_it->closed()) {
- SPCurve * start = new SPCurve();
- start->moveto(path_it->begin()->initialPoint());
- start->lineto(path_it->begin()->finalPoint());
- Geom::D2< Geom::SBasis > SBasisStart = start->first_segment()->toSBasis();
- SPCurve *lineHelper = new SPCurve();
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*path_it->begin());
- if(cubic){
- lineHelper->moveto(SBasisStart.valueAt(Geom::nearest_point((*cubic)[1],*start->first_segment())));
- }else{
- lineHelper->moveto(start->first_segment()->initialPoint());
- }
- start->reset();
- delete start;
-
- SPCurve * end = new SPCurve();
- end->moveto(curve_it1->initialPoint());
- end->lineto(curve_it1->finalPoint());
- Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis();
- cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1);
- if(cubic){
- lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment())));
- }else{
- lineHelper->lineto(end->first_segment()->finalPoint());
- }
- end->reset();
- delete end;
- SBasisHelper = lineHelper->first_segment()->toSBasis();
- lineHelper->reset();
- delete lineHelper;
- startNode = SBasisHelper.valueAt(0.5);
- curveHelper->curveto(nextPointAt1, nextPointAt2, startNode);
- nCurve->append_continuous(curveHelper, 0.0625);
- nCurve->move_endpoints(startNode,startNode);
- }else{
- SPCurve * start = new SPCurve();
- start->moveto(path_it->begin()->initialPoint());
- start->lineto(path_it->begin()->finalPoint());
- startNode = start->first_segment()->initialPoint();
- start->reset();
- delete start;
- curveHelper->curveto(nextPointAt1, nextPointAt2, nextPointAt3);
- nCurve->append_continuous(curveHelper, 0.0625);
- nCurve->move_endpoints(startNode,nextPointAt3);
- }
- curveHelper->reset();
- delete curveHelper;
if (path_it->closed()) {
nCurve->closepath_current();
}
- curve->append(nCurve,false);
+ curve->append(nCurve, false);
nCurve->reset();
delete nCurve;
}