Allow adding spline points.

pull/4/head
EvilSpirit 2016-04-08 14:20:42 +06:00 committed by whitequark
parent 77d8291216
commit 16ea824456
5 changed files with 66 additions and 12 deletions

View File

@ -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) { if(dogd.drawing) {
// Draw lines from active group in front of those from previous // Draw lines from active group in front of those from previous
ssglDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 3); 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); double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), true);
// A little bit easier to select in the active group // A little bit easier to select in the active group
if(group.v == SS.GW.activeGroup.v) d -= 1; 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); dogd.refp = (a.Plus(b)).ScaledBy(0.5);
} }
@ -127,7 +130,7 @@ void Entity::GenerateEdges(SEdgeList *el, bool includingConstruction) {
List<Vector> lv = {}; List<Vector> lv = {};
sb->MakePwlInto(&lv); sb->MakePwlInto(&lv);
for(j = 1; j < lv.n; j++) { 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(); lv.Clear();
} }
@ -707,10 +710,10 @@ void Entity::DrawOrGetDistance(void) {
// And draw the curves; generate the rational polynomial curves for // And draw the curves; generate the rational polynomial curves for
// everything, then piecewise linearize them, and display those. // everything, then piecewise linearize them, and display those.
SEdgeList *sel = GetOrGenerateEdges(); SEdgeList *sel = GetOrGenerateEdges();
int i; dogd.data = -1;
for(i = 0; i < sel->l.n; i++) { for(int i = 0; i < sel->l.n; i++) {
SEdge *se = &(sel->l.elem[i]); SEdge *se = &(sel->l.elem[i]);
LineDrawOrGetDistance(se->a, se->b, true); LineDrawOrGetDistance(se->a, se->b, true, se->auxB);
} }
} }

View File

@ -15,11 +15,8 @@ void GraphicsWindow::ReplacePointInConstraints(hEntity oldpt, hEntity newpt) {
int i; int i;
for(i = 0; i < SK.constraint.n; i++) { for(i = 0; i < SK.constraint.n; i++) {
Constraint *c = &(SK.constraint.elem[i]); Constraint *c = &(SK.constraint.elem[i]);
if(c->ptA.v == oldpt.v) c->ptA = newpt;
if(c->type == Constraint::POINTS_COINCIDENT) { 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;
}
} }
} }

View File

@ -528,6 +528,11 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
return; 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; context.active = true;
if(!hover.IsEmpty()) { if(!hover.IsEmpty()) {
@ -537,6 +542,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
GroupSelection(); GroupSelection();
bool itemsSelected = (gs.n > 0 || gs.constraints > 0); bool itemsSelected = (gs.n > 0 || gs.constraints > 0);
int addAfterPoint = -1;
if(itemsSelected) { if(itemsSelected) {
if(gs.stylables > 0) { 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) { if(gs.points == 1) {
Entity *p = SK.GetEntity(gs.point[0]); Entity *p = SK.GetEntity(gs.point[0]);
Constraint *c; Constraint *c;
@ -717,6 +739,36 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
break; 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: { case CMNU_GROUP_INFO: {
hGroup hg; hGroup hg;
if(gs.entities == 1) { if(gs.entities == 1) {

View File

@ -492,8 +492,9 @@ public:
double lineWidth; double lineWidth;
double stippleScale; double stippleScale;
int stippleType; int stippleType;
int data;
} dogd; // state for drawing or getting distance (for hit testing) } 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); void DrawOrGetDistance(void);
bool IsStylable(); bool IsStylable();

View File

@ -680,6 +680,7 @@ public:
CMNU_DEL_COINCIDENT = 0x132, CMNU_DEL_COINCIDENT = 0x132,
CMNU_SNAP_TO_GRID = 0x140, CMNU_SNAP_TO_GRID = 0x140,
CMNU_REMOVE_SPLINE_PT = 0x141, CMNU_REMOVE_SPLINE_PT = 0x141,
CMNU_ADD_SPLINE_PT = 0x142,
CMNU_FIRST_STYLE = 0x40000000 CMNU_FIRST_STYLE = 0x40000000
}; };
void ContextMenuListStyles(void); void ContextMenuListStyles(void);