diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/live_effects/lpe-bspline.cpp | 360 | ||||
| -rw-r--r-- | src/ui/tools/freehand-base.cpp | 8 | ||||
| -rw-r--r-- | src/ui/tools/pen-tool.cpp | 232 |
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; } |
