From 16ea824456e9d44df59fe6021dc9a9563c5d2559 Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Fri, 8 Apr 2016 14:20:42 +0600 Subject: [PATCH] Allow adding spline points. --- src/drawentity.cpp | 15 +++++++------ src/modify.cpp | 7 ++----- src/mouse.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ src/sketch.h | 3 ++- src/ui.h | 1 + 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/drawentity.cpp b/src/drawentity.cpp index 45834a01..6aab2b93 100644 --- a/src/drawentity.cpp +++ b/src/drawentity.cpp @@ -17,7 +17,7 @@ std::string Entity::DescriptionString(void) { } } -void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) { +void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat, int data) { if(dogd.drawing) { // Draw lines from active group in front of those from previous ssglDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 3); @@ -32,7 +32,10 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat) { double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true); // A little bit easier to select in the active group if(group.v == SS.GW.activeGroup.v) d -= 1; - dogd.dmin = min(dogd.dmin, d); + if(d < dogd.dmin) { + dogd.dmin = d; + dogd.data = data; + } } dogd.refp = (a.Plus(b)).ScaledBy(0.5); } @@ -127,7 +130,7 @@ void Entity::GenerateEdges(SEdgeList *el, bool includingConstruction) { List lv = {}; sb->MakePwlInto(&lv); for(j = 1; j < lv.n; j++) { - el->AddEdge(lv.elem[j-1], lv.elem[j], style.v); + el->AddEdge(lv.elem[j-1], lv.elem[j], style.v, i); } lv.Clear(); } @@ -707,10 +710,10 @@ void Entity::DrawOrGetDistance(void) { // And draw the curves; generate the rational polynomial curves for // everything, then piecewise linearize them, and display those. SEdgeList *sel = GetOrGenerateEdges(); - int i; - for(i = 0; i < sel->l.n; i++) { + dogd.data = -1; + for(int i = 0; i < sel->l.n; i++) { SEdge *se = &(sel->l.elem[i]); - LineDrawOrGetDistance(se->a, se->b, true); + LineDrawOrGetDistance(se->a, se->b, true, se->auxB); } } diff --git a/src/modify.cpp b/src/modify.cpp index 63e97381..47eee368 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -15,11 +15,8 @@ void GraphicsWindow::ReplacePointInConstraints(hEntity oldpt, hEntity newpt) { int i; for(i = 0; i < SK.constraint.n; i++) { Constraint *c = &(SK.constraint.elem[i]); - - if(c->type == Constraint::POINTS_COINCIDENT) { - if(c->ptA.v == oldpt.v) c->ptA = newpt; - if(c->ptB.v == oldpt.v) c->ptB = newpt; - } + if(c->ptA.v == oldpt.v) c->ptA = newpt; + if(c->ptB.v == oldpt.v) c->ptB = newpt; } } diff --git a/src/mouse.cpp b/src/mouse.cpp index 65265888..ee727c90 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -528,6 +528,11 @@ void GraphicsWindow::MouseRightUp(double x, double y) { return; } + // The current mouse location + Vector v = offset.ScaledBy(-1); + v = v.Plus(projRight.ScaledBy(x/scale)); + v = v.Plus(projUp.ScaledBy(y/scale)); + context.active = true; if(!hover.IsEmpty()) { @@ -537,6 +542,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) { GroupSelection(); bool itemsSelected = (gs.n > 0 || gs.constraints > 0); + int addAfterPoint = -1; if(itemsSelected) { if(gs.stylables > 0) { @@ -581,6 +587,22 @@ void GraphicsWindow::MouseRightUp(double x, double y) { } } + if(gs.entities == 1) { + hRequest hr = gs.entity[0].request(); + if(hr.v != 0) { + Request *r = SK.GetRequest(hr); + if(r->type == Request::CUBIC || r->type == Request::CUBIC_PERIODIC) { + Entity *e = SK.GetEntity(gs.entity[0]); + e->GetDistance(Point2d::From(x, y)); + addAfterPoint = e->dogd.data; + if(addAfterPoint == -1) oops(); + // Skip derivative point. + if(r->type == Request::CUBIC) addAfterPoint++; + AddContextMenuItem("Add Spline Point", CMNU_ADD_SPLINE_PT); + } + } + } + if(gs.points == 1) { Entity *p = SK.GetEntity(gs.point[0]); Constraint *c; @@ -717,6 +739,36 @@ void GraphicsWindow::MouseRightUp(double x, double y) { break; } + case CMNU_ADD_SPLINE_PT: { + hRequest hr = gs.entity[0].request(); + Request *r = SK.GetRequest(hr); + + int pointCount = r->extraPoints + ((r->type == Request::CUBIC_PERIODIC) ? 3 : 4); + if(pointCount < MAX_POINTS_IN_ENTITY) { + SS.UndoRemember(); + r->extraPoints++; + SS.MarkGroupDirtyByEntity(gs.entity[0]); + SS.GenerateAll(SolveSpaceUI::GENERATE_REGEN); + + Entity *e = SK.GetEntity(r->h.entity(0)); + for(int i = MAX_POINTS_IN_ENTITY; i > addAfterPoint + 1; i--) { + Entity *p0 = SK.entity.FindByIdNoOops(e->point[i]); + if(p0 == NULL) continue; + Entity *p1 = SK.GetEntity(e->point[i - 1]); + ReplacePointInConstraints(p1->h, p0->h); + p0->PointForceTo(p1->PointGetNum()); + } + Entity *p = SK.GetEntity(e->point[addAfterPoint + 1]); + p->PointForceTo(v); + SS.MarkGroupDirtyByEntity(gs.entity[0]); + SS.ScheduleGenerateAll(); + ClearSelection(); + } else { + Error("Cannot add spline point: maximum number of points reached."); + } + break; + } + case CMNU_GROUP_INFO: { hGroup hg; if(gs.entities == 1) { diff --git a/src/sketch.h b/src/sketch.h index 7b340700..371bb38c 100644 --- a/src/sketch.h +++ b/src/sketch.h @@ -492,8 +492,9 @@ public: double lineWidth; double stippleScale; int stippleType; + int data; } dogd; // state for drawing or getting distance (for hit testing) - void LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat=false); + void LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat=false, int userData = -1); void DrawOrGetDistance(void); bool IsStylable(); diff --git a/src/ui.h b/src/ui.h index e1c56378..cdf26623 100644 --- a/src/ui.h +++ b/src/ui.h @@ -680,6 +680,7 @@ public: CMNU_DEL_COINCIDENT = 0x132, CMNU_SNAP_TO_GRID = 0x140, CMNU_REMOVE_SPLINE_PT = 0x141, + CMNU_ADD_SPLINE_PT = 0x142, CMNU_FIRST_STYLE = 0x40000000 }; void ContextMenuListStyles(void);