diff options
| author | jtx <javier.arraiza@marker.es> | 2013-03-01 11:09:45 +0000 |
|---|---|---|
| committer | jtx <javier.arraiza@marker.es> | 2013-03-01 11:09:45 +0000 |
| commit | bea047adffe8c71c5d2eddef0b570470741da74a (patch) | |
| tree | 8080fb9016c6aaf932d6dc1f48c5dc663dd4d8d4 /src | |
| parent | Refactor problem cusp nodes (diff) | |
| parent | BSpline refactor (diff) | |
| download | inkscape-bea047adffe8c71c5d2eddef0b570470741da74a.tar.gz inkscape-bea047adffe8c71c5d2eddef0b570470741da74a.zip | |
Update from branch
(bzr r11950.3.3)
Diffstat (limited to 'src')
| -rw-r--r-- | src/draw-context.cpp | 22 | ||||
| -rw-r--r-- | src/live_effects/lpe-bspline.cpp | 143 | ||||
| -rw-r--r-- | src/pen-context.cpp | 650 | ||||
| -rw-r--r-- | src/ui/tool/curve-drag-point.cpp | 20 | ||||
| -rw-r--r-- | src/ui/tool/node.cpp | 45 | ||||
| -rw-r--r-- | src/ui/tool/path-manipulator.cpp | 65 |
6 files changed, 610 insertions, 335 deletions
diff --git a/src/draw-context.cpp b/src/draw-context.cpp index 8da39b027..dcd0fc7ec 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -561,7 +561,15 @@ void spdc_concat_colors_and_flush(SPDrawContext *dc, gboolean forceclosed) dc->sa->curve->append_continuous(c, 0.0625); c->unref(); dc->sa->curve->closepath_current(); - spdc_flush_white(dc, NULL); + //BSpline + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 || + prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){ + dc->white_curves = g_slist_remove(dc->white_curves, dc->sa->curve); + spdc_flush_white(dc, dc->sa->curve); + }else + //BSpline End + spdc_flush_white(dc, NULL); return; } @@ -687,6 +695,18 @@ SPDrawAnchor *spdc_test_inside(SPDrawContext *dc, Geom::Point p) } } + //BSpline + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if((prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 || + prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) && + dc->sa && !dc->red_curve->is_empty() && !dc->green_anchor){ + if(active){ + active->curve = dc->sa->curve; + active->curve->ref(); + } + } + //BSpline End + return active; } diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index 8147ae014..d046ad683 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -32,40 +32,12 @@ LPEBSpline::~LPEBSpline() void LPEBSpline::doEffect(SPCurve * curve) { - using Geom::X; - using Geom::Y; - if(curve->get_segment_count() < 2) - return; + 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 > SBasisHelper; - //curves - SPCurve * in = new SPCurve(); - SPCurve * out = new SPCurve(); - SPCurve * end = new SPCurve(); - //Curvas temporales - SPCurve *lineHelper = new SPCurve(); - SPCurve *curveHelper = new SPCurve(); - SPCurve *nCurve = new SPCurve(); - //Puntos a usar. Ponemos todos los posibles para hacer más inteligible el código - Geom::Point startNode(0,0); - Geom::Point previousNode(0,0); - Geom::Point node(0,0); - //Geom::Point previousPointAt3(0,0); - Geom::Point pointAt0(0,0); - 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::CubicBezier const *cubicIn; - Geom::CubicBezier const *cubicOut; - Geom::CubicBezier const *cubicEnd; + //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... @@ -75,31 +47,60 @@ LPEBSpline::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_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 + SPCurve * in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); + SPCurve * out = new SPCurve(); out->moveto(curve_it2->initialPoint()); out->lineto(curve_it2->finalPoint()); - //este no cambia. - end->moveto(curve_end->initialPoint()); - end->lineto(curve_end->finalPoint()); + SPCurve *nCurve = new SPCurve(); + Geom::Point startNode(0,0); + 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::CubicBezier const *cubic = NULL; //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) { + + if (path_it->closed()) { //Calculamos el nodo de inicio BSpline - lineHelper->moveto((*cubicIn)[1]); - lineHelper->lineto((*cubicEnd)[2]); - SBasisHelper = lineHelper->first_segment()->toSBasis(); + const Geom::Curve &closingline = path_it->back_closed(); + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + curve_endit = path_it->end_open(); + } + SPCurve * end = new SPCurve(); + end->moveto(curve_endit->initialPoint()); + end->lineto(curve_endit->finalPoint()); + Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis(); + Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); + end->reset(); + delete end; + SPCurve *lineHelper = new SPCurve(); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + lineHelper->moveto(SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()))); + }else{ + lineHelper->moveto(in->first_segment()->initialPoint()); + } + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit); + if(cubic){ + lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); + }else{ + lineHelper->lineto(end->first_segment()->finalPoint()); + } + Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis(); lineHelper->reset(); + delete lineHelper; //Guardamos el principio de la curva startNode = SBasisHelper.valueAt(0.5); //Definimos el punto de inicio original de la curva resultante @@ -110,68 +111,73 @@ LPEBSpline::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){ + Geom::D2< Geom::SBasis > 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{ - pointAt0 = in->first_segment()->initialPoint(); pointAt1 = in->first_segment()->initialPoint(); pointAt2 = in->first_segment()->finalPoint(); - pointAt3 = in->first_segment()->finalPoint(); } //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){ + Geom::D2< Geom::SBasis > 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 //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(); + Geom::D2< Geom::SBasis > 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); + SPCurve *curveHelper = new SPCurve(); curveHelper->moveto(previousNode); curveHelper->curveto(pointAt1, pointAt2, node); //añadimos la curva generada a la curva pricipal nCurve->append_continuous(curveHelper, 0.0625); curveHelper->reset(); + delete curveHelper; //aumentamos los valores para el siguiente paso en el bucle ++curve_it1; ++curve_it2; - //Damos valor a el objeto para el path de entrada y el de salida in->reset(); + delete in; + SPCurve * in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); out->reset(); - if(curve_it1 != curve_end){ + delete out; + if(curve_it1 != curve_endit){ + SPCurve * out = new SPCurve(); out->moveto(curve_it2->initialPoint()); out->lineto(curve_it2->finalPoint()); } } //Aberiguamos la ultima parte de la curva correspondiente al último segmento + SPCurve *curveHelper = new SPCurve(); curveHelper->moveto(node); //Si está cerrada la curva, la cerramos sobre el valor guardado previamente //Si no finalizamos en el punto final @@ -182,26 +188,21 @@ LPEBSpline::doEffect(SPCurve * curve) } //añadimos este último segmento nCurve->append_continuous(curveHelper, 0.0625); + curveHelper->reset(); + delete curveHelper; //y cerramos la curva if (path_it->closed()) { nCurve->closepath_current(); } curve->append(nCurve,false); nCurve->reset(); + delete nCurve; //Limpiamos in->reset(); out->reset(); - end->reset(); - lineHelper->reset(); - curveHelper->reset(); + delete in; + delete out; } - delete in; - delete out; - delete end; - delete lineHelper; - delete curveHelper; - //Todo: remove? - //delete SBasisHelper; } }; //namespace LivePathEffect diff --git a/src/pen-context.cpp b/src/pen-context.cpp index e393a706b..a505f8de7 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -97,6 +97,7 @@ static void sp_pen_context_set_mode(SPPenContext *const pc, guint mode); static void spiro_color(SPPenContext *const pc); //Guarda el valor si se ha pulsado la tecla SHIFT al continuar una curva static bool saShift = false; + //Preparamos la curva roja para que se muestre según esté pulsada la tecla SHIFT static void spiro(SPPenContext *const pc, bool Shift); //Unimos todas las curvas en juego y llamamos a la función doEffect. @@ -104,7 +105,15 @@ static void spiro_build(SPPenContext *const pc); //function spiro cloned from lpe-spiro.cpp static void spiro_doEffect(SPCurve * curve); //Preparamos la curva roja para que se muestre según esté pulsada la tecla SHIFT -static void bspline(SPPenContext *const pc,bool Shift); +static void bspline(SPPenContext *const pc,bool shift); +static void bsplineOn(SPPenContext *const pc); +static void bsplineOff(SPPenContext *const pc); +static void bsplineStartAnchor(SPPenContext *const pc,bool shift); +static void bsplineStartAnchorOn(SPPenContext *const pc); +static void bsplineStartAnchorOff(SPPenContext *const pc); +static void bsplineMotion(SPPenContext *const pc,bool shift); +static void bsplineEndAnchorOn(SPPenContext *const pc); +static void bsplineEndAnchorOff(SPPenContext *const pc); //Unimos todas las curvas en juego y llamamos a la función doEffect. static void bspline_build(SPPenContext *const pc); //function bspline cloned from lpe-bspline.cpp @@ -458,7 +467,8 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const Geom::Point event_dt(desktop->w2d(event_w)); SPEventContext *event_context = SP_EVENT_CONTEXT(pc); //Test whether we hit any anchor. - SPDrawAnchor * const anchor = spdc_test_inside(pc, event_w); + //Anchor changed from Const because need to update pc->ea for BSpline. + SPDrawAnchor * anchor = spdc_test_inside(pc, event_w); //BSpline //with this we avoid creating a new point over the existing one if((pc->spiro || pc->bspline) && pc->npoints > 0 && pc->p[0] == pc->p[3]){ @@ -528,6 +538,16 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const // Set start anchor pc->sa = anchor; + //BSpline + if(anchor){ + if(pc->spiro){ + spiro(pc,(bevent.state & GDK_SHIFT_MASK)); + } + if(pc->bspline){ + bsplineStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK)); + } + } + //BSpline End if (anchor && !sp_pen_context_has_waiting_LPE(pc)) { // Adjust point to anchor if needed; if we have a waiting LPE, we need // a fresh path to be created so don't continue an existing one @@ -578,12 +598,10 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const spdc_pen_set_subsequent_point(pc, p, true); } } - - pc->state = pc->polylines_only ? SP_PEN_CONTEXT_POINT : SP_PEN_CONTEXT_CONTROL; //BSpline //Esto evita arrastrar los manejadores ya que el punto se crea //al soltar el botón del ratón. - if((pc->spiro || pc->bspline) && pc->state != SP_PEN_CONTEXT_CLOSE) pc->state = SP_PEN_CONTEXT_POINT; + pc->state = (pc->spiro || pc->bspline || pc->polylines_only) ? SP_PEN_CONTEXT_POINT : SP_PEN_CONTEXT_CONTROL; //BSpline End ret = TRUE; break; @@ -665,7 +683,6 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons // Find desktop coordinates Geom::Point p = dt->w2d(event_w); - // Test, whether we hit any anchor SPDrawAnchor *anchor = spdc_test_inside(pc, event_w); switch (pc->mode) { @@ -747,16 +764,14 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons case SP_PEN_CONTEXT_CONTROL: case SP_PEN_CONTEXT_CLOSE: // Placing controls is last operation in CLOSE state - // snap the handle spdc_endpoint_snap_handle(pc, p, mevent.state); - //BSpline - if (!pc->polylines_only && !pc->spiro && !pc->bspline) { - //BSpline End + if (!pc->polylines_only) { spdc_pen_set_ctrl(pc, p, mevent.state); } else { spdc_pen_set_ctrl(pc, pc->p[1], mevent.state); } + gobble_motion_events(GDK_BUTTON1_MASK); ret = TRUE; break; @@ -782,7 +797,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons spiro(pc,(mevent.state & GDK_SHIFT_MASK)); } if(pc->bspline){ - bspline(pc,(mevent.state & GDK_SHIFT_MASK)); + bsplineMotion(pc,(mevent.state & GDK_SHIFT_MASK)); } pen_drag_origin_w = event_w; } @@ -830,6 +845,16 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con p = anchor->dp; } pc->sa = anchor; + //BSpline + if (anchor) { + if(pc->spiro){ + spiro(pc,(revent.state & GDK_SHIFT_MASK)); + } + if(pc->bspline){ + bsplineStartAnchor(pc,(revent.state & GDK_SHIFT_MASK)); + } + } + //BSpline End spdc_pen_set_initial_point(pc, p); } else { // Set end anchor here @@ -838,14 +863,6 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con p = anchor->dp; } } - //BSpline - if(pc->spiro){ - spiro(pc,(revent.state & GDK_SHIFT_MASK)); - } - if(pc->bspline){ - bspline(pc,(revent.state & GDK_SHIFT_MASK)); - } - //BSpline End pc->state = SP_PEN_CONTEXT_CONTROL; ret = TRUE; break; @@ -889,7 +906,10 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con spdc_pen_finish_segment(pc, p, revent.state); break; case SP_PEN_CONTEXT_CLOSE: - spdc_endpoint_snap(pc, p, revent.state); + // End current segment + if (!anchor) { // Snap node only if not hitting anchor + spdc_endpoint_snap(pc, p, revent.state); + } spdc_pen_finish_segment(pc, p, revent.state); //BSpline //Ocultamos la guia del penultimo nodo al cerrar la curva @@ -908,7 +928,7 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con case SP_PEN_CONTEXT_STOP: // This is allowed, if we just cancelled curve break; - default: + default: break; } pc->state = SP_PEN_CONTEXT_POINT; @@ -984,20 +1004,8 @@ static void pen_redraw_all (SPPenContext *const pc) // handles //BSpline - SPCurve * WPower = new SPCurve(); - Geom::D2< Geom::SBasis > SBasisWPower; - float WP = 0; - if (pc->p[0] != pc->p[1] && !pc->spiro /*&& !pc->bspline*/) { + if (pc->p[0] != pc->p[1] && !pc->spiro && !pc->bspline) { //BSpline End - if(pc->bspline){ - WPower->moveto(pc->red_curve->first_segment()->initialPoint()); - WPower->lineto(pc->red_curve->first_segment()->finalPoint()); - SBasisWPower = WPower->first_segment()->toSBasis(); - - WPower->reset(); - pc->p[1] = SBasisWPower.valueAt(WP); - } - SP_CTRL(pc->c1)->moveto(pc->p[1]); pc->cl1->setCoords(pc->p[0], pc->p[1]); sp_canvas_item_show(pc->c1); @@ -1006,23 +1014,16 @@ static void pen_redraw_all (SPPenContext *const pc) sp_canvas_item_hide(pc->c1); sp_canvas_item_hide(pc->cl1); } - Geom::Point p2; + Geom::Curve const * last_seg = pc->green_curve->last_segment(); if (last_seg) { Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>( last_seg ); //BSpline if ( cubic && - (*cubic)[2] != pc->p[0]&& !pc->spiro /*&& !pc->bspline*/ ) + (*cubic)[2] != pc->p[0] && !pc->spiro && !pc->bspline ) { //BSpline End - if(pc->bspline){ - WPower->moveto(last_seg->finalPoint()); - WPower->lineto(last_seg->initialPoint()); - SBasisWPower = WPower->first_segment()->toSBasis(); - p2 = SBasisWPower.valueAt(WP); - }else{ - p2 = (*cubic)[2]; - } + Geom::Point p2 = (*cubic)[2]; SP_CTRL(pc->c0)->moveto(p2); pc->cl0->setCoords(p2, pc->p[0]); sp_canvas_item_show(pc->c0); @@ -1378,12 +1379,6 @@ static gint pen_handle_key_press(SPPenContext *const pc, GdkEvent *event) } } else { // Reset red curve - //BSpline - if ((pc->spiro || pc->bspline) && pc->green_curve->get_segment_count()==1) { - pen_cancel (pc); - ret = TRUE; - } - //BSpline End pc->red_curve->reset(); // Destroy topmost green bpath if (pc->green_bpaths) { @@ -1401,27 +1396,38 @@ static gint pen_handle_key_press(SPPenContext *const pc, GdkEvent *event) pc->p[0] = crv->initialPoint(); if ( Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>(crv)) { pc->p[1] = (*cubic)[1]; + //BSpline + if(pc->spiro || pc->bspline)pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]); + //BSpline End } else { pc->p[1] = pc->p[0]; } - Geom::Point const pt(( pc->npoints < 4 + + Geom::Point const pt((pc->npoints < 4 ? (Geom::Point)(crv->finalPoint()) - : pc->p[3] )); + : pc->p[3])); + pc->npoints = 2; - pc->green_curve->backspace(); + //BSpline + if( pc->green_curve->get_segment_count() == 1){ + pc->npoints = 5; + if (pc->green_bpaths) { + if (pc->green_bpaths->data) + sp_canvas_item_destroy(SP_CANVAS_ITEM(pc->green_bpaths->data)); + pc->green_bpaths = g_slist_remove(pc->green_bpaths, pc->green_bpaths->data); + } + pc->green_curve->reset(); + }else{ + pc->green_curve->backspace(); + } + //BSpline End sp_canvas_item_hide(pc->cl0); sp_canvas_item_hide(pc->cl1); pc->state = SP_PEN_CONTEXT_POINT; spdc_pen_set_subsequent_point(pc, pt, true); pen_last_paraxial_dir = !pen_last_paraxial_dir; //BSpline - if(pc->spiro || pc->bspline){ - SPCanvasItem *cshape = sp_canvas_bpath_new(sp_desktop_sketch(pc->desktop), pc->green_curve); - sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), pc->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(cshape), 0, SP_WIND_RULE_NONZERO); - pc->green_bpaths = g_slist_prepend(pc->green_bpaths, cshape); - pen_redraw_all(pc); - } + if(pc->spiro || pc->bspline) bspline_build(pc); //BSpline End ret = TRUE; } @@ -1783,54 +1789,283 @@ static void spiro_doEffect(SPCurve * curve) } //Unimos todas las curvas en juego y llamamos a la función doEffect. -static void bspline(SPPenContext *const pc, bool Shift) + +static void bspline(SPPenContext *const pc, bool shift) +{ + if(!pc->anchor_statusbar) + shift?bsplineOff(pc):bsplineOn(pc); + + bspline_build(pc); +} + +static void bsplineOn(SPPenContext *const pc){ + if(!pc->red_curve->is_empty()){ + using Geom::X; + using Geom::Y; + pc->npoints = 5; + pc->p[0] = pc->red_curve->first_segment()->initialPoint(); + pc->p[3] = pc->red_curve->first_segment()->finalPoint(); + pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); + pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); + } +} + +static void bsplineOff(SPPenContext *const pc) +{ + 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(); + pc->p[2] = pc->p[3]; + } +} + +static void bsplineStartAnchor(SPPenContext *const pc, bool shift) +{ + if(pc->sa->curve->is_empty()) + return; + + if(shift) + bsplineStartAnchorOff(pc); + else + bsplineStartAnchorOn(pc); +} + +static void bsplineStartAnchorOn(SPPenContext *const pc) { 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); + SPCurve *tmpCurve = new SPCurve(); + tmpCurve = pc->sa->curve->copy(); + if(pc->sa->start) + tmpCurve = tmpCurve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + SPCurve *lastSeg = new SPCurve(); + Geom::Point A = tmpCurve->last_segment()->initialPoint(); + Geom::Point D = tmpCurve->last_segment()->finalPoint(); + Geom::Point C = D + (1./3)*(A - D); + C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + if(cubic){ + lastSeg->moveto(A); + lastSeg->curveto((*cubic)[1],C,D); + }else{ + lastSeg->moveto(A); + lastSeg->curveto(A,C,D); + } + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; + }else{ + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); + } + if (pc->sa->start) { + tmpCurve = tmpCurve->create_reverse(); + } + pc->sa->curve->reset(); + pc->sa->curve = tmpCurve; +} + +static void bsplineStartAnchorOff(SPPenContext *const pc) +{ + SPCurve *tmpCurve = new SPCurve(); + tmpCurve = pc->sa->curve->copy(); + if(pc->sa->start) + tmpCurve = tmpCurve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + if(cubic){ + SPCurve *lastSeg = new SPCurve(); + lastSeg->moveto((*cubic)[0]); + lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; + }else{ + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); + } + if (pc->sa->start) { + tmpCurve = tmpCurve->create_reverse(); + } + pc->sa->curve->reset(); + pc->sa->curve = tmpCurve; + } + +} + +static void bsplineMotion(SPPenContext *const pc, bool shift){ + using Geom::X; + using Geom::Y; + SPCurve *tmpCurve = new SPCurve(); + if(shift) + pc->p[2] = pc->p[3]; + else + pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); + pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); + + if(pc->green_curve->is_empty() && !pc->sa){ + pc->p[1] = pc->p[0] + (1./3)*(pc->p[3] - pc->p[0]); + }else if(!pc->green_curve->is_empty()){ + tmpCurve = pc->green_curve->copy(); + }else{ + tmpCurve = pc->sa->curve->copy(); + if(pc->sa->start) + tmpCurve = tmpCurve->create_reverse(); + } + if(!tmpCurve->is_empty() && !pc->red_curve->is_empty()){ + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + if(cubic){ + SPCurve * WPower = new SPCurve(); + Geom::D2< Geom::SBasis > SBasisWPower; + WPower->moveto(tmpCurve->last_segment()->finalPoint()); + WPower->lineto(tmpCurve->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] + 0.0625,pc->p[1][Y] + 0.0625); + }else{ + pc->p[1] = pc->p[0]; + } + } + + if(pc->anchor_statusbar && !pc->red_curve->is_empty()){ + if(shift) + bsplineEndAnchorOff(pc); + else + bsplineEndAnchorOn(pc); + } + + bspline_build(pc); +} + +static void bsplineEndAnchorOn(SPPenContext *const pc) +{ + using Geom::X; + using Geom::Y; + pc->p[2] = pc->p[3] + (1./3)*(pc->p[0] - pc->p[3]); + pc->p[2] = Geom::Point(pc->p[2][X] + 0.0625,pc->p[2][Y] + 0.0625); + SPCurve *tmpCurve = new SPCurve(); + SPCurve *lastSeg = new SPCurve(); + Geom::Point C(0,0); + if(!pc->sa || pc->sa->curve->is_empty()){ + tmpCurve = pc->green_curve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); + C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + if(cubic){ + lastSeg->moveto((*cubic)[0]); + lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); + }else{ + lastSeg->moveto(tmpCurve->last_segment()->initialPoint()); + lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint()); + } + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; + }else{ + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); + } + tmpCurve = tmpCurve->create_reverse(); + pc->green_curve->reset(); + pc->green_curve = tmpCurve; + }else{ + tmpCurve = pc->sa->curve->copy(); + if(!pc->sa->start) + tmpCurve = tmpCurve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint()); + C = Geom::Point(C[X] + 0.0625,C[Y] + 0.0625); + if(cubic){ + lastSeg->moveto((*cubic)[0]); + lastSeg->curveto((*cubic)[1],C,(*cubic)[3]); + }else{ + lastSeg->moveto(tmpCurve->last_segment()->initialPoint()); + lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint()); + } + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; + }else{ + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); + } + if (!pc->sa->start) { + tmpCurve = tmpCurve->create_reverse(); + } + pc->sa->curve->reset(); + pc->sa->curve = tmpCurve; + } +} + +static void bsplineEndAnchorOff(SPPenContext *const pc) +{ + pc->p[2] = pc->p[3]; + SPCurve *tmpCurve = new SPCurve(); + SPCurve *lastSeg = new SPCurve(); + if(!pc->sa || pc->sa->curve->is_empty()){ + tmpCurve = pc->green_curve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + if(cubic){ + lastSeg->moveto((*cubic)[0]); + lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; }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); - } + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); } - 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); + tmpCurve = tmpCurve->create_reverse(); + pc->green_curve->reset(); + pc->green_curve = tmpCurve; } - 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{ + tmpCurve = pc->sa->curve->copy(); + if(!pc->sa->start) + tmpCurve = tmpCurve->create_reverse(); + Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment()); + if(cubic){ + lastSeg->moveto((*cubic)[0]); + lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]); + if( tmpCurve->get_segment_count() == 1){ + tmpCurve = lastSeg; + }else{ + //we eliminate the last segment + tmpCurve->backspace(); + //and we add it again with the recreation + tmpCurve->append_continuous(lastSeg, 0.0625); + } + if (!pc->sa->start) { + tmpCurve = tmpCurve->create_reverse(); + } + pc->sa->curve->reset(); + pc->sa->curve = tmpCurve; + } + } +} + +/* +//Unimos todas las curvas en juego y llamamos a la función doEffect. +static void bspline(SPPenContext *const pc, bool Shift) +{ + using Geom::X; + using Geom::Y; + Geom::CubicBezier const *cubic; + 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 +2079,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 +2106,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 +2125,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,11 +2150,47 @@ 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); } - +/*/ //preparates the curves for its trasformation into BSline curves. static void bspline_build(SPPenContext *const pc) @@ -1929,7 +2204,7 @@ static void bspline_build(SPPenContext *const pc) curve = curve->create_reverse(); } } - //We add also the green curve + if (!pc->green_curve->is_empty()) curve->append_continuous(pc->green_curve, 0.0625); @@ -1937,16 +2212,12 @@ static void bspline_build(SPPenContext *const pc) if (!pc->red_curve->is_empty()){ pc->red_curve->reset(); pc->red_curve->moveto(pc->p[0]); - if(pc->npoints == 2){ - pc->red_curve->lineto(pc->p[1]); - }else{ - pc->red_curve->curveto(pc->p[1],pc->p[2],pc->p[3]); - } + pc->red_curve->curveto(pc->p[1],pc->p[2],pc->p[3]); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), pc->red_curve); curve->append_continuous(pc->red_curve, 0.0625); } - if(curve->get_segment_count() > 1 ){ + if(!curve->is_empty()){ //cerramos la curva si estan cerca los puntos finales de la curva spiro if(Geom::are_near(curve->first_path()->initialPoint(), curve->last_path()->finalPoint())){ curve->closepath_current(); @@ -1974,42 +2245,14 @@ 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; + 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 > SBasisHelper; - //curves - SPCurve * in = new SPCurve(); - SPCurve * out = new SPCurve(); - SPCurve * end = new SPCurve(); - //Curvas temporales - SPCurve *lineHelper = new SPCurve(); - SPCurve *curveHelper = new SPCurve(); - SPCurve *nCurve = new SPCurve(); - //Puntos a usar. Ponemos todos los posibles para hacer más inteligible el código - Geom::Point startNode(0,0); - Geom::Point previousNode(0,0); - Geom::Point node(0,0); - //Geom::Point previousPointAt3(0,0); - Geom::Point pointAt0(0,0); - 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::CubicBezier const *cubicIn; - Geom::CubicBezier const *cubicOut; - Geom::CubicBezier const *cubicEnd; + //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,31 +2262,60 @@ 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_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 + SPCurve * in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); + SPCurve * out = new SPCurve(); out->moveto(curve_it2->initialPoint()); out->lineto(curve_it2->finalPoint()); - //este no cambia. - end->moveto(curve_end->initialPoint()); - end->lineto(curve_end->finalPoint()); + SPCurve *nCurve = new SPCurve(); + Geom::Point startNode(0,0); + 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::CubicBezier const *cubic = NULL; //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) { + + if (path_it->closed()) { //Calculamos el nodo de inicio BSpline - lineHelper->moveto((*cubicIn)[1]); - lineHelper->lineto((*cubicEnd)[2]); - SBasisHelper = lineHelper->first_segment()->toSBasis(); + const Geom::Curve &closingline = path_it->back_closed(); + if (are_near(closingline.initialPoint(), closingline.finalPoint())) { + curve_endit = path_it->end_open(); + } + SPCurve * end = new SPCurve(); + end->moveto(curve_endit->initialPoint()); + end->lineto(curve_endit->finalPoint()); + Geom::D2< Geom::SBasis > SBasisIn = in->first_segment()->toSBasis(); + Geom::D2< Geom::SBasis > SBasisEnd = end->first_segment()->toSBasis(); + end->reset(); + delete end; + SPCurve *lineHelper = new SPCurve(); + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_it1); + if(cubic){ + lineHelper->moveto(SBasisIn.valueAt(Geom::nearest_point((*cubic)[1],*in->first_segment()))); + }else{ + lineHelper->moveto(in->first_segment()->initialPoint()); + } + cubic = dynamic_cast<Geom::CubicBezier const*>(&*curve_endit); + if(cubic){ + lineHelper->lineto(SBasisEnd.valueAt(Geom::nearest_point((*cubic)[2],*end->first_segment()))); + }else{ + lineHelper->lineto(end->first_segment()->finalPoint()); + } + Geom::D2< Geom::SBasis > SBasisHelper = lineHelper->first_segment()->toSBasis(); lineHelper->reset(); + delete lineHelper; //Guardamos el principio de la curva startNode = SBasisHelper.valueAt(0.5); //Definimos el punto de inicio original de la curva resultante @@ -2054,68 +2326,73 @@ 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){ + Geom::D2< Geom::SBasis > 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{ - pointAt0 = in->first_segment()->initialPoint(); pointAt1 = in->first_segment()->initialPoint(); pointAt2 = in->first_segment()->finalPoint(); - pointAt3 = in->first_segment()->finalPoint(); } //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){ + Geom::D2< Geom::SBasis > 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 //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(); + Geom::D2< Geom::SBasis > 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); + SPCurve *curveHelper = new SPCurve(); curveHelper->moveto(previousNode); curveHelper->curveto(pointAt1, pointAt2, node); //añadimos la curva generada a la curva pricipal nCurve->append_continuous(curveHelper, 0.0625); curveHelper->reset(); + delete curveHelper; //aumentamos los valores para el siguiente paso en el bucle ++curve_it1; ++curve_it2; - //Damos valor a el objeto para el path de entrada y el de salida in->reset(); + delete in; + SPCurve * in = new SPCurve(); in->moveto(curve_it1->initialPoint()); in->lineto(curve_it1->finalPoint()); out->reset(); - if(curve_it1 != curve_end){ + delete out; + if(curve_it1 != curve_endit){ + SPCurve * out = new SPCurve(); out->moveto(curve_it2->initialPoint()); out->lineto(curve_it2->finalPoint()); } } //Aberiguamos la ultima parte de la curva correspondiente al último segmento + SPCurve *curveHelper = new SPCurve(); curveHelper->moveto(node); //Si está cerrada la curva, la cerramos sobre el valor guardado previamente //Si no finalizamos en el punto final @@ -2126,28 +2403,22 @@ static void __attribute__((optimize(0))) bspline_doEffect(SPCurve * curve) } //añadimos este último segmento nCurve->append_continuous(curveHelper, 0.0625); + curveHelper->reset(); + delete curveHelper; //y cerramos la curva if (path_it->closed()) { nCurve->closepath_current(); } curve->append(nCurve,false); nCurve->reset(); + delete nCurve; //Limpiamos in->reset(); out->reset(); - end->reset(); - lineHelper->reset(); - curveHelper->reset(); + delete in; + delete out; } - delete in; - delete out; - delete end; - delete lineHelper; - delete curveHelper; - //Todo: remove? - //delete SBasisHelper; } - //BSpline end static void spdc_pen_set_subsequent_point(SPPenContext *const pc, Geom::Point const p, bool statusbar, guint status) @@ -2251,14 +2522,12 @@ static void spdc_pen_finish_segment(SPPenContext *const pc, Geom::Point const p, ++pc->num_clicks; if (!pc->red_curve->is_empty()) { - //BSpline if(pc->spiro){ - spiro(pc, (state & GDK_SHIFT_MASK)); + spiro(pc,(state & GDK_SHIFT_MASK)); } if(pc->bspline){ - bspline(pc, (state & GDK_SHIFT_MASK)); + bspline(pc,(state & GDK_SHIFT_MASK)); } - //BSpline End pc->green_curve->append_continuous(pc->red_curve, 0.0625); SPCurve *curve = pc->red_curve->copy(); /// \todo fixme: @@ -2284,9 +2553,6 @@ static void spdc_pen_finish(SPPenContext *const pc, gboolean const closed) } pc->num_clicks = 0; - if(pc->spiro || pc->bspline){ - saShift = false; - } pen_disable_events(pc); SPDesktop *const desktop = pc->desktop; diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp index b83ce1b3c..40dcb5058 100644 --- a/src/ui/tool/curve-drag-point.cpp +++ b/src/ui/tool/curve-drag-point.cpp @@ -53,9 +53,12 @@ bool CurveDragPoint::grabbed(GdkEventMotion */*event*/) // delta is a vector equal 1/3 of distance from first to second Geom::Point delta = (second->position() - first->position()) / 3.0; - first->front()->move(first->front()->position() + delta); - second->back()->move(second->back()->position() - delta); - + //BSpline + if(!_pm.isBSpline()){ + first->front()->move(first->front()->position() + delta); + second->back()->move(second->back()->position() - delta); + } + //BSpline End _pm.update(); } else { _segment_was_degenerate = false; @@ -87,10 +90,13 @@ void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event) Geom::Point delta = new_pos - position(); Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta; Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta; - - first->front()->move(first->front()->position() + offset0); - second->back()->move(second->back()->position() + offset1); - + //BSpline + if(!_pm.isBSpline()){ + first->front()->move(first->front()->position() + offset0); + second->back()->move(second->back()->position() + offset1); + }else if(weight>=0.8)second->back()->move(new_pos); + else if(weight<=0.2)first->front()->move(new_pos); + //BSpline End _pm.update(); } diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 447133b7c..4cac0e543 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -138,11 +138,14 @@ void Handle::move(Geom::Point const &new_pos) //BSpline bool isBSpline = false; double pos = 0; - Handle *h = this; + Handle *h = NULL; + Handle *h2 = NULL; if(_pm().isBSpline()){ isBSpline = true; - //BSpline End + if(!_parent->selected()) + _parent->_selection.insert(_parent); } + //BSpline End if (Geom::are_near(new_pos, _parent->position())) { // The handle becomes degenerate. @@ -176,12 +179,11 @@ void Handle::move(Geom::Point const &new_pos) setPosition(new_pos); //BSpline if(isBSpline){ + h = this; setPosition(_pm().BSplineHandleReposition(h)); pos = _pm().BSplineHandlePosition(h); - other->setPosition(_pm().BSplineHandleReposition(other,pos)); - if(pos == 0){ - _parent->setPosition(h->position()); - } + h2 = this->other(); + this->other()->setPosition(_pm().BSplineHandleReposition(h2,pos)); } //BSpline End return; @@ -216,12 +218,11 @@ void Handle::move(Geom::Point const &new_pos) setPosition(new_pos); //BSpline if(isBSpline){ + h = this; setPosition(_pm().BSplineHandleReposition(h)); pos = _pm().BSplineHandlePosition(h); - other->setPosition(_pm().BSplineHandleReposition(other,pos)); - if(pos == 0){ - _parent->setPosition(h->position()); - } + h2 = this->other(); + this->other()->setPosition(_pm().BSplineHandleReposition(h2,pos)); } //BSpline End } @@ -577,17 +578,35 @@ void Node::move(Geom::Point const &new_pos) Geom::Point old_pos = position(); Geom::Point delta = new_pos - position(); //BSpline + double prevPos = 0; double pos = 0; + double nextPos = 0; + Node *n = this; + Node * nextNode = n->nodeToward(n->front()); + Node * prevNode = n->nodeToward(n->back()); if(_pm().isBSpline()){ - Node *n = this; + if(prevNode) + prevPos = _pm().BSplineHandlePosition(prevNode->front()); pos = _pm().BSplineHandlePosition(n->front()); if(pos == 0) pos = _pm().BSplineHandlePosition(n->back()); + if(nextNode) + nextPos = _pm().BSplineHandlePosition(nextNode->back()); } //BSpline End setPosition(new_pos); + //BSpline + if(prevNode) + prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevPos)); + if(nextNode) + nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextPos)); + //BSpline End _front.setPosition(_front.position() + delta); _back.setPosition(_back.position() + delta); + //BSpline End + // if the node has a smooth handle after a line segment, it should be kept colinear + // with the segment + _fixNeighbors(old_pos, new_pos); //BSpline if(_pm().isBSpline()){ Handle* front = &_front; @@ -595,10 +614,6 @@ void Node::move(Geom::Point const &new_pos) _front.setPosition(_pm().BSplineHandleReposition(front,pos)); _back.setPosition(_pm().BSplineHandleReposition(back,pos)); } - //BSpline End - // if the node has a smooth handle after a line segment, it should be kept colinear - // with the segment - _fixNeighbors(old_pos, new_pos); } void Node::transform(Geom::Affine const &m) diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 03e25dfa3..7c23ee153 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -1182,28 +1182,33 @@ bool PathManipulator::isBSpline(){ } return false; } + double PathManipulator::BSplineHandlePosition(Handle *h){ + using Geom::X; + using Geom::Y; double pos = 0; Node *n = h->parent(); - Geom::D2< Geom::SBasis > SBasisInsideNodes; SPCurve *lineInsideNodes = new SPCurve(); Node * nextNode = n->nodeToward(h); - if(nextNode){ + Geom::Point positionH = h->position(); + positionH = Geom::Point(positionH[X] - 0.0625,positionH[Y] - 0.0625); + if(nextNode && n->position() != h->position()){ lineInsideNodes->moveto(n->position()); lineInsideNodes->lineto(nextNode->position()); - SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis(); - pos = Geom::nearest_point(h->position(),*lineInsideNodes->first_segment()); + pos = Geom::nearest_point(positionH,*lineInsideNodes->first_segment()); } return pos; } Geom::Point PathManipulator::BSplineHandleReposition(Handle *h){ - double pos = 0; - pos = this->BSplineHandlePosition(h); + double pos = this->BSplineHandlePosition(h); return BSplineHandleReposition(h,pos); } Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){ + using Geom::X; + using Geom::Y; + Geom::Point ret(0,0); Node *n = h->parent(); Geom::D2< Geom::SBasis > SBasisInsideNodes; SPCurve *lineInsideNodes = new SPCurve(); @@ -1212,10 +1217,12 @@ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){ lineInsideNodes->moveto(n->position()); lineInsideNodes->lineto(nextNode->position()); SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis(); + ret = SBasisInsideNodes.valueAt(pos); + ret = Geom::Point(ret[X] + 0.0625,ret[Y] + 0.0625); }else{ - return n->position(); + ret = n->position(); } - return SBasisInsideNodes.valueAt(pos); + return ret; } /** Construct the geometric representation of nodes and handles, update the outline @@ -1232,55 +1239,15 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE) continue; } NodeList::iterator prev = subpath->begin(); - //BSpline - double pos = 0; - bool isBSpline = false; - if(this->isBSpline()) - isBSpline = true; - if(isBSpline){ - pos = BSplineHandlePosition(prev.ptr()->front()); - prev.ptr()->front()->setPosition(BSplineHandleReposition(prev.ptr()->front(),pos)); - if(pos == 0){ - prev.ptr()->setPosition(prev.ptr()->front()->position()); - } - } - //BSpline End builder.moveTo(prev->position()); for (NodeList::iterator i = ++subpath->begin(); i != subpath->end(); ++i) { - //BSpline - if (isBSpline) { - pos = BSplineHandlePosition(i.ptr()->front()); - if(pos == 0) - pos = BSplineHandlePosition(i.ptr()->back()); - i.ptr()->front()->setPosition(BSplineHandleReposition(i.ptr()->front(),pos)); - i.ptr()->back()->setPosition(BSplineHandleReposition(i.ptr()->back(),pos)); - if(pos == 0){ - i.ptr()->setPosition(i.ptr()->front()->position()); - } - } - - //BSpline End build_segment(builder, prev.ptr(), i.ptr()); prev = i; } + if (subpath->closed()) { // Here we link the last and first node if the path is closed. // If the last segment is Bezier, we add it. - /* - //BSpline - if (isBSpline) { - pos = BSplineHandlePosition(prev.ptr()->front()); - if(pos == 0) - pos = BSplineHandlePosition(subpath->begin().ptr()->back()); - subpath->begin().ptr()->front()->setPosition(BSplineHandleReposition(subpath->begin().ptr()->front(),pos)); - prev.ptr()->back()->setPosition(BSplineHandleReposition(prev.ptr()->back(),pos)); - if(pos == 0){ - subpath->begin().ptr()->setPosition(subpath->begin().ptr()->front()->position()); - prev.ptr()->setPosition(prev.ptr()->back()->position()); - } - } - //BSpline End - /*/ if (!prev->front()->isDegenerate() || !subpath->begin()->back()->isDegenerate()) { build_segment(builder, prev.ptr(), subpath->begin().ptr()); } |
