summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2013-02-28 03:43:21 +0000
committerJabiertxo Arraiza Zenotz <jtx@jtx.marker.es>2013-02-28 03:43:21 +0000
commitecc57932f1e7d157950ada2901f6ea6f3acc8aad (patch)
treea709f96bc323c5e7b69d09ece12aefebfb0e14d8 /src
parentBSpline refactor (diff)
downloadinkscape-ecc57932f1e7d157950ada2901f6ea6f3acc8aad.tar.gz
inkscape-ecc57932f1e7d157950ada2901f6ea6f3acc8aad.zip
Fixed closed pc->ea
(bzr r11950.1.40)
Diffstat (limited to 'src')
-rw-r--r--src/draw-context.cpp22
-rw-r--r--src/live_effects/lpe-bspline.cpp10
-rw-r--r--src/pen-context.cpp420
-rw-r--r--src/ui/tool/node.cpp38
-rw-r--r--src/ui/tool/path-manipulator.cpp45
5 files changed, 293 insertions, 242 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 8dc840556..36caf73c5 100644
--- a/src/live_effects/lpe-bspline.cpp
+++ b/src/live_effects/lpe-bspline.cpp
@@ -34,6 +34,8 @@ LPEBSpline::doEffect(SPCurve * curve)
{
if(curve->get_segment_count() < 2)
return;
+ using Geom::X;
+ using Geom::Y;
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
curve->reset();
@@ -94,13 +96,6 @@ LPEBSpline::doEffect(SPCurve * curve)
//en posible caso de que se cierre con una linea recta creando un nodo BSPline
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);
@@ -223,6 +218,7 @@ LPEBSpline::doEffect(SPCurve * curve)
//Todo: remove?
//delete SBasisHelper;
}
+
}; //namespace LivePathEffect
}; /* namespace Inkscape */
diff --git a/src/pen-context.cpp b/src/pen-context.cpp
index 4270aecea..6910e903b 100644
--- a/src/pen-context.cpp
+++ b/src/pen-context.cpp
@@ -106,12 +106,13 @@ static void spiro_build(SPPenContext *const pc);
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 bsplineInMotion(SPPenContext *const pc,bool shift);
static void bsplineOn(SPPenContext *const pc);
-static void bsplineStartAnchorOn(SPPenContext *const pc);
-static void bsplineEndAnchorOn(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);
@@ -466,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]){
@@ -542,7 +544,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
spiro(pc,(bevent.state & GDK_SHIFT_MASK));
}
if(pc->bspline){
- bspline(pc,(bevent.state & GDK_SHIFT_MASK));
+ bsplineStartAnchor(pc,(bevent.state & GDK_SHIFT_MASK));
}
}
//BSpline End
@@ -596,8 +598,10 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const
spdc_pen_set_subsequent_point(pc, p, true);
}
}
- //BSpline;
- pc->state = (pc->polylines_only || pc->spiro || pc->bspline )? 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.
+ pc->state = (pc->spiro || pc->bspline || pc->polylines_only) ? SP_PEN_CONTEXT_POINT : SP_PEN_CONTEXT_CONTROL;
//BSpline End
ret = TRUE;
break;
@@ -760,7 +764,6 @@ 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);
if (!pc->polylines_only) {
@@ -768,6 +771,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons
} else {
spdc_pen_set_ctrl(pc, pc->p[1], mevent.state);
}
+
gobble_motion_events(GDK_BUTTON1_MASK);
ret = TRUE;
break;
@@ -793,7 +797,7 @@ static gint pen_handle_motion_notify(SPPenContext *const pc, GdkEventMotion cons
spiro(pc,(mevent.state & GDK_SHIFT_MASK));
}
if(pc->bspline){
- bsplineInMotion(pc,(mevent.state & GDK_SHIFT_MASK));
+ bsplineMotion(pc,(mevent.state & GDK_SHIFT_MASK));
}
pen_drag_origin_w = event_w;
}
@@ -842,11 +846,13 @@ static gint pen_handle_button_release(SPPenContext *const pc, GdkEventButton con
}
pc->sa = anchor;
//BSpline
- if(pc->spiro){
- spiro(pc,(revent.state & GDK_SHIFT_MASK));
- }
- if(pc->bspline){
- bspline(pc,(revent.state & GDK_SHIFT_MASK));
+ 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);
@@ -900,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
@@ -919,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;
@@ -1011,7 +1020,7 @@ static void pen_redraw_all (SPPenContext *const pc)
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
Geom::Point p2 = (*cubic)[2];
@@ -1387,24 +1396,37 @@ 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) && ( pc->green_curve->is_empty() || pc->green_curve->last_segment() == NULL )){
- pen_cancel (pc);
- ret = TRUE;
- } pc->blue_curve->reset();
if(pc->spiro || pc->bspline) bspline_build(pc);
//BSpline End
ret = TRUE;
@@ -1770,48 +1792,22 @@ static void spiro_doEffect(SPCurve * curve)
static void bspline(SPPenContext *const pc, bool shift)
{
- shift?bsplineOff(pc):bsplineOn(pc);
+ if(!pc->anchor_statusbar)
+ shift?bsplineOff(pc):bsplineOn(pc);
+
bspline_build(pc);
}
-static void bsplineInMotion(SPPenContext *const pc, bool shift){
- SPCurve *tmpCurve = new SPCurve();
- 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);
- }else{
- pc->p[1] = pc->p[0];
- }
- }
-
- if(pc->anchor_statusbar && !pc->red_curve->is_empty()){
- if(shift)
- bsplineEndAnchorOff(pc);
- else
- bsplineEndAnchorOn(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);
}
-
- bspline_build(pc);
}
static void bsplineOff(SPPenContext *const pc)
@@ -1821,10 +1817,54 @@ static void bsplineOff(SPPenContext *const pc)
pc->p[0] = pc->red_curve->first_segment()->initialPoint();
pc->p[3] = pc->red_curve->first_segment()->finalPoint();
pc->p[2] = pc->p[3];
- pc->p[4] = pc->p[3];
}
- if(pc->anchor_statusbar && pc->sa && !pc->sa->curve->is_empty() && pc->red_curve->is_empty())
+}
+
+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;
+ 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)
@@ -1838,8 +1878,14 @@ static void bsplineStartAnchorOff(SPPenContext *const pc)
SPCurve *lastSeg = new SPCurve();
lastSeg->moveto((*cubic)[0]);
lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ 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();
}
@@ -1849,84 +1895,61 @@ static void bsplineStartAnchorOff(SPPenContext *const pc)
}
-static void bsplineEndAnchorOff(SPPenContext *const pc)
-{
- pc->p[2] = pc->p[3];
+static void bsplineMotion(SPPenContext *const pc, bool shift){
+ using Geom::X;
+ using Geom::Y;
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]);
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
- tmpCurve = tmpCurve->create_reverse();
- pc->green_curve->reset();
- pc->green_curve = tmpCurve;
- }
+ 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)
+ 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){
- lastSeg->moveto((*cubic)[0]);
- lastSeg->curveto((*cubic)[1],(*cubic)[3],(*cubic)[3]);
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
- if (!pc->sa->start) {
- tmpCurve = tmpCurve->create_reverse();
- }
- pc->sa->curve->reset();
- pc->sa->curve = tmpCurve;
+ 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];
}
}
-}
-static void bsplineOn(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] + (1./3)*(pc->p[0] - pc->p[3]);
+ if(pc->anchor_statusbar && !pc->red_curve->is_empty()){
+ if(shift)
+ bsplineEndAnchorOff(pc);
+ else
+ bsplineEndAnchorOn(pc);
}
- if(pc->anchor_statusbar && pc->sa && !pc->sa->curve->is_empty() && pc->red_curve->is_empty())
- bsplineStartAnchorOn(pc);
-}
-static void bsplineStartAnchorOn(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());
- SPCurve *lastSeg = new SPCurve();
- Geom::Point A = tmpCurve->last_segment()->initialPoint();
- Geom::Point D = tmpCurve->last_segment()->finalPoint();
- Geom::Point C(0,0);
- if(cubic){
- C = D + (1./3)*(A - D);
- lastSeg->moveto(A);
- lastSeg->curveto((*cubic)[1],C,D);
- }else{
- lastSeg->moveto(A);
- lastSeg->curveto(A,C,D);
- }
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
- if (pc->sa->start) {
- tmpCurve = tmpCurve->create_reverse();
- }
- pc->sa->curve->reset();
- pc->sa->curve = tmpCurve;
+ 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);
@@ -1934,6 +1957,7 @@ static void bsplineEndAnchorOn(SPPenContext *const pc)
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]);
@@ -1941,8 +1965,14 @@ static void bsplineEndAnchorOn(SPPenContext *const pc)
lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint());
}
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ 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;
@@ -1952,6 +1982,7 @@ static void bsplineEndAnchorOn(SPPenContext *const pc)
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]);
@@ -1959,8 +1990,14 @@ static void bsplineEndAnchorOn(SPPenContext *const pc)
lastSeg->moveto(tmpCurve->last_segment()->initialPoint());
lastSeg->curveto(tmpCurve->last_segment()->initialPoint(),C,tmpCurve->last_segment()->finalPoint());
}
- tmpCurve->backspace();
- tmpCurve->append_continuous(lastSeg, 0.0625);
+ 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();
}
@@ -1968,6 +2005,55 @@ static void bsplineEndAnchorOn(SPPenContext *const pc)
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{
+ //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());
+ 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)
@@ -2118,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);
@@ -2126,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();
@@ -2167,6 +2249,8 @@ static void bspline_doEffect(SPCurve * curve)
{
if(curve->get_segment_count() < 2)
return;
+ using Geom::X;
+ using Geom::Y;
// Make copy of old path as it is changed during processing
Geom::PathVector const original_pathv = curve->get_pathvector();
curve->reset();
@@ -2227,29 +2311,11 @@ static void bspline_doEffect(SPCurve * curve)
//en posible caso de que se cierre con una linea recta creando un nodo BSPline
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();
- }
+ //Calculamos el nodo de inicio BSpline
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);
+ lineHelper->moveto(SBasisIn.valueAt(0.3334));
+ lineHelper->lineto(SBasisEnd.valueAt(0.6667));
SBasisHelper = lineHelper->first_segment()->toSBasis();
lineHelper->reset();
//Guardamos el principio de la curva
@@ -2267,32 +2333,17 @@ static void bspline_doEffect(SPCurve * curve)
{
//previousPointAt3 = pointAt3;
//Calculamos los puntos que dividirían en tres segmentos iguales el path recto de entrada y de salida
- 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();
- pointAt2 = in->first_segment()->finalPoint();
- pointAt3 = in->first_segment()->finalPoint();
- }
+ SBasisIn = in->first_segment()->toSBasis();
+ SBasisOut = out->first_segment()->toSBasis();
+ pointAt0 = SBasisIn.valueAt(0);
+ pointAt1 = SBasisIn.valueAt(0.3334);
+ pointAt2 = SBasisIn.valueAt(0.6667);
+ pointAt3 = SBasisIn.valueAt(1);
//Y hacemos lo propio con el path de salida
//nextPointAt0 = curveOut.valueAt(0);
- 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();
- }
+ nextPointAt1 = SBasisOut.valueAt(0.3334);
+ nextPointAt2 = SBasisOut.valueAt(0.6667);;
+ nextPointAt3 = SBasisOut.valueAt(1);
//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
@@ -2356,7 +2407,6 @@ static void bspline_doEffect(SPCurve * curve)
//Todo: remove?
//delete SBasisHelper;
}
-
//BSpline end
static void spdc_pen_set_subsequent_point(SPPenContext *const pc, Geom::Point const p, bool statusbar, guint status)
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index fef904006..4cac0e543 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -138,12 +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;
- _parent->_selection.insert(_parent);
- //BSpline End
+ if(!_parent->selected())
+ _parent->_selection.insert(_parent);
}
+ //BSpline End
if (Geom::are_near(new_pos, _parent->position())) {
// The handle becomes degenerate.
@@ -177,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;
@@ -217,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
}
@@ -588,21 +588,25 @@ void Node::move(Geom::Point const &new_pos)
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){
+ if(prevNode)
prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevPos));
- }
- if(nextNode){
+ 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;
@@ -610,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 ecb8abcf4..7c23ee153 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -1182,15 +1182,20 @@ bool PathManipulator::isBSpline(){
}
return false;
}
+
double PathManipulator::BSplineHandlePosition(Handle *h){
+ using Geom::X;
+ using Geom::Y;
double pos = 0;
Node *n = h->parent();
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());
- pos = Geom::nearest_point(h->position(),*lineInsideNodes->first_segment());
+ pos = Geom::nearest_point(positionH,*lineInsideNodes->first_segment());
}
return pos;
}
@@ -1201,18 +1206,23 @@ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h){
}
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();
Node * nextNode = n->nodeToward(h);
- if(nextNode){
+ if(nextNode && pos != 0){
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
@@ -1229,26 +1239,8 @@ 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->front()->setPosition(BSplineHandleReposition(prev->front(),pos));
- }
- //BSpline End
builder.moveTo(prev->position());
for (NodeList::iterator i = ++subpath->begin(); i != subpath->end(); ++i) {
- //BSpline
- if (isBSpline) {
- pos = BSplineHandlePosition(i->back());
- i->front()->setPosition(BSplineHandleReposition(i->front(),pos));
- i->back()->setPosition(BSplineHandleReposition(i->back(),pos));
- }
-
- //BSpline End
build_segment(builder, prev.ptr(), i.ptr());
prev = i;
}
@@ -1256,13 +1248,6 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
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.next()->back());
- subpath->begin()->front()->setPosition(BSplineHandleReposition(subpath->begin()->front(),pos));
- prev.next()->back()->setPosition(BSplineHandleReposition(prev.next()->back(),pos));
- }
- //BSpline End
if (!prev->front()->isDegenerate() || !subpath->begin()->back()->isDegenerate()) {
build_segment(builder, prev.ptr(), subpath->begin().ptr());
}