diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2013-02-23 22:34:58 +0000 |
|---|---|---|
| committer | Jabiertxo Arraiza Zenotz <jtx@jtx.marker.es> | 2013-02-23 22:34:58 +0000 |
| commit | 9af17a6572db964acebd2b7eeea29c8b722c8221 (patch) | |
| tree | 20fef1b2c5a2f9d49a841be10238919be7acf72e /src/pen-context.cpp | |
| parent | Mayor refactor (diff) | |
| download | inkscape-9af17a6572db964acebd2b7eeea29c8b722c8221.tar.gz inkscape-9af17a6572db964acebd2b7eeea29c8b722c8221.zip | |
Saved for next refactor
(bzr r11950.1.37)
Diffstat (limited to 'src/pen-context.cpp')
| -rw-r--r-- | src/pen-context.cpp | 171 |
1 files changed, 96 insertions, 75 deletions
diff --git a/src/pen-context.cpp b/src/pen-context.cpp index e393a706b..350924adb 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -1788,49 +1788,10 @@ static void bspline(SPPenContext *const pc, bool Shift) using Geom::X; using Geom::Y; Geom::CubicBezier const *cubic; - if(!Shift){ - //NODO CUSP formado por nodo SMOOTH - //solo mobemos el manejador del nodo final de cada segmento - //Es suficiente para mostrar el nodo como CUSP - //Usamos 5 puntos - if(!pc->red_curve->is_empty()){ - pc->npoints = 5; - pc->p[0] = pc->red_curve->first_segment()->initialPoint(); - pc->p[3] = pc->red_curve->first_segment()->finalPoint(); - if(pc->green_curve->is_empty()){ - pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]); - pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1); - }else{ - cubic = dynamic_cast<Geom::CubicBezier const*>(&*pc->green_curve->last_segment()); - if(!cubic || ((*cubic)[2] == (*cubic)[3])) - pc->p[1] = pc->p[0]; - else{ - SPCurve * WPower = new SPCurve(); - Geom::D2< Geom::SBasis > SBasisWPower; - WPower->moveto(pc->green_curve->last_segment()->finalPoint()); - WPower->lineto(pc->green_curve->last_segment()->initialPoint()); - float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment()); - WPower->reset(); - WPower->moveto(pc->red_curve->last_segment()->initialPoint()); - WPower->lineto(pc->red_curve->last_segment()->finalPoint()); - SBasisWPower = WPower->first_segment()->toSBasis(); - WPower->reset(); - pc->p[1] = SBasisWPower.valueAt(WP); - pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1); - } - } - pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); - pc->p[2] = Geom::Point(pc->p[2][X]+1,pc->p[2][Y]+1); - } - if(pc->green_curve->is_empty() && saShift) - pc->p[1] = pc->p[0]; - if(pc->anchor_statusbar && pc->red_curve->is_empty()) - saShift = false; - }else{ + if(Shift){ //Continuamos la curva en modo CUSP //Guardamos el valor de inicio en cusp para que no se redibuje como SYMM if(pc->anchor_statusbar && pc->red_curve->is_empty()){ - saShift = true; SPCurve *previousCurve = new SPCurve(); if(pc->sa && !pc->sa->curve->is_empty()){ previousCurve = pc->sa->curve->copy(); @@ -1844,10 +1805,15 @@ static void bspline(SPPenContext *const pc, bool Shift) lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); previousCurve->backspace(); previousCurve->append_continuous(lastSeg, 0.0625); + if (pc->sa->start) { + previousCurve = previousCurve->create_reverse(); + } + pc->sa->curve->reset(); pc->sa->curve = previousCurve; } } } + if(pc->anchor_statusbar && !pc->red_curve->is_empty()){ // Step B - both start and end anchored to same curve if ( pc->sa && pc->ea @@ -1866,7 +1832,10 @@ static void bspline(SPPenContext *const pc, bool Shift) lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); same->backspace(); same->append_continuous(lastSeg, 0.0625); - same = same->create_reverse(); + if (pc->sa->start) { + same = same->create_reverse(); + } + pc->sa->curve->reset(); pc->sa->curve = same; } } @@ -1882,16 +1851,12 @@ static void bspline(SPPenContext *const pc, bool Shift) green->backspace(); green->append_continuous(lastSeg, 0.0625); green = green->create_reverse(); + pc->green_curve->reset(); pc->green_curve = green; } } } - if(!pc->green_curve->is_empty()){ - //Damos valor original a la variable por si se necesita de nuevo - saShift = false; - } - if (!pc->red_curve->is_empty()){ pc->npoints = 5; pc->p[0] = pc->red_curve->first_segment()->initialPoint(); @@ -1911,6 +1876,42 @@ static void bspline(SPPenContext *const pc, bool Shift) } } + }else{ + //NODO CUSP formado por nodo SMOOTH + //solo mobemos el manejador del nodo final de cada segmento + //Es suficiente para mostrar el nodo como CUSP + //Usamos 5 puntos + if(!pc->red_curve->is_empty()){ + pc->npoints = 5; + pc->p[0] = pc->red_curve->first_segment()->initialPoint(); + pc->p[3] = pc->red_curve->first_segment()->finalPoint(); + if(pc->green_curve->is_empty()){ + if(!pc->sa || (pc->sa && pc->p[0] != pc->p[1])){ + pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]); + pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1); + } + }else{ + cubic = dynamic_cast<Geom::CubicBezier const*>(&*pc->green_curve->last_segment()); + if(!cubic || ((*cubic)[2] == (*cubic)[3])) + pc->p[1] = pc->p[0]; + else{ + SPCurve * WPower = new SPCurve(); + Geom::D2< Geom::SBasis > SBasisWPower; + WPower->moveto(pc->green_curve->last_segment()->finalPoint()); + WPower->lineto(pc->green_curve->last_segment()->initialPoint()); + float WP = Geom::nearest_point((*cubic)[2],*WPower->first_segment()); + WPower->reset(); + WPower->moveto(pc->red_curve->last_segment()->initialPoint()); + WPower->lineto(pc->red_curve->last_segment()->finalPoint()); + SBasisWPower = WPower->first_segment()->toSBasis(); + WPower->reset(); + pc->p[1] = SBasisWPower.valueAt(WP); + pc->p[1] = Geom::Point(pc->p[1][X]+1,pc->p[1][Y]+1); + } + } + pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); + pc->p[2] = Geom::Point(pc->p[2][X]+1,pc->p[2][Y]+1); + } } bspline_build(pc); } @@ -1974,17 +1975,17 @@ static void bspline_build(SPPenContext *const pc) } } -static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) +static void bspline_doEffect(SPCurve * curve) { - using Geom::X; - using Geom::Y; - if(curve->get_segment_count() < 2) return; // Make copy of old path as it is changed during processing Geom::PathVector const original_pathv = curve->get_pathvector(); curve->reset(); //Sbasis + Geom::D2< Geom::SBasis > SBasisIn; + Geom::D2< Geom::SBasis > SBasisOut; + Geom::D2< Geom::SBasis > SBasisEnd; Geom::D2< Geom::SBasis > SBasisHelper; //curves SPCurve * in = new SPCurve(); @@ -2007,9 +2008,9 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) Geom::Point nextPointAt1(0,0); Geom::Point nextPointAt2(0,0); Geom::Point nextPointAt3(0,0); - Geom::CubicBezier const *cubicIn; - Geom::CubicBezier const *cubicOut; - Geom::CubicBezier const *cubicEnd; + + Geom::Point endPointAt2(0,0); + Geom::CubicBezier const *cubic; //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... @@ -2019,7 +2020,7 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) 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_end = path_it->end(); // end curve + Geom::Path::const_iterator curve_end = path_it->end_open(); // end 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 @@ -2036,12 +2037,31 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) //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 - cubicEnd = dynamic_cast<Geom::CubicBezier const*>(&*curve_end); - cubicIn = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); - if (path_it->closed() && cubicEnd && cubicIn) { - //Calculamos el nodo de inicio BSpline - lineHelper->moveto((*cubicIn)[1]); - lineHelper->lineto((*cubicEnd)[2]); + + 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. + 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(); + } + SBasisIn = in->first_segment()->toSBasis(); + SBasisEnd = end->first_segment()->toSBasis(); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment())); + }else{ + pointAt1 = in->first_segment()->initialPoint(); + } + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_end); + if(cubic){ + endPointAt2 = SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment())); + }else{ + endPointAt2 = end->first_segment()->finalPoint(); + } + lineHelper->moveto(pointAt1); + lineHelper->lineto(endPointAt2); SBasisHelper = lineHelper->first_segment()->toSBasis(); lineHelper->reset(); //Guardamos el principio de la curva @@ -2054,18 +2074,18 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) //Definimos el punto de inicio original de la curva resultante node = startNode; } - //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 - cubicIn = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); - if(cubicIn){ - pointAt0 = (*cubicIn)[0]; - pointAt1 = (*cubicIn)[1]; - pointAt2 = (*cubicIn)[2]; - pointAt3 = (*cubicIn)[3]; + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + SBasisIn = in->first_segment()->toSBasis(); + pointAt0 = (*cubic)[0]; + pointAt1 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment())); + pointAt2 = SBasisIn.valueAt(Geom::nearest_point((*cubic)[2],*in->first_segment())); + pointAt3 = (*cubic)[3]; }else{ pointAt0 = in->first_segment()->initialPoint(); pointAt1 = in->first_segment()->initialPoint(); @@ -2074,15 +2094,16 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) } //Y hacemos lo propio con el path de salida //nextPointAt0 = curveOut.valueAt(0); - cubicOut = dynamic_cast<Geom::CubicBezier const*>(&*curve_it2); - if(cubicOut){ - nextPointAt1 = (*cubicOut)[1]; - nextPointAt2 = (*cubicOut)[2]; - nextPointAt3 = (*cubicOut)[3]; + 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 = in->first_segment()->initialPoint(); - nextPointAt2 = in->first_segment()->finalPoint(); - nextPointAt3 = in->first_segment()->finalPoint(); + nextPointAt1 = out->first_segment()->initialPoint(); + nextPointAt2 = out->first_segment()->finalPoint(); + nextPointAt3 = out->first_segment()->finalPoint(); } //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 |
