Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 46 additions & 12 deletions src/constrainteq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,13 +271,47 @@ void ConstraintBase::Generate(ParamList *l) {
}

void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
bool forReference) const {
if(reference && !forReference) return;
bool forReference) const {
if(reference && !forReference) {
return;
}

Expr *exA = Expr::From(valA);
// comments don't create equations
if(type == Type::COMMENT) return;

Expr *exA = {};
Expr *exLen = {};

// Need to pull the group from this constraint and get its valid names list
// then delete the above code
Group *g = SK.GetGroup(group);

// a numeric dimension is stored in valA. When a complex expression is used
// it is stored in the comment string and the unit scale is in valA.
if(comment != "") {
int usedParams = 0;
// exA = Expr::From(comment.c_str(), false, &usedParams, &vars);
exA = Expr::From(comment.c_str(), false, &usedParams, &(g->dict));

// the expression may have become invalid if a name has been deleted.
// return will prevent a crash but silently make the constraint fail.
// creating a 1=0 equation will cause a solve fail and (awkward) constraint deletion.
if(!exA)
{
exA = Expr::From(1.0);
AddEq(l, exA, 0);
return;
}

exLen = exA->Times(Expr::From(valA));
} else {
exA = Expr::From(valA);
exLen = Expr::From(valA);
}

switch(type) {
case Type::PT_PT_DISTANCE:
AddEq(l, Distance(workplane, ptA, ptB)->Minus(exA), 0);
AddEq(l, Distance(workplane, ptA, ptB)->Minus(exLen), 0);
return;

case Type::PROJ_PT_DISTANCE: {
Expand All @@ -288,18 +322,18 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
ExprVector pp = SK.GetEntity(entityA)->VectorGetExprs();
pp = pp.WithMagnitude(Expr::From(1.0));

AddEq(l, (dp.Dot(pp))->Minus(exA), 0);
AddEq(l, (dp.Dot(pp))->Minus(exLen), 0);
return;
}

case Type::PT_LINE_DISTANCE:
AddEq(l,
PointLineDistance(workplane, ptA, entityA)->Minus(exA), 0);
PointLineDistance(workplane, ptA, entityA)->Minus(exLen), 0);
return;

case Type::PT_PLANE_DISTANCE: {
ExprVector pt = SK.GetEntity(ptA)->PointGetExprs();
AddEq(l, (PointPlaneDistance(pt, entityA))->Minus(exA), 0);
AddEq(l, (PointPlaneDistance(pt, entityA))->Minus(exLen), 0);
return;
}

Expand All @@ -308,7 +342,7 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
EntityBase *f = SK.GetEntity(entityA);
ExprVector p0 = f->FaceGetPointExprs();
ExprVector n = f->FaceGetNormalExprs();
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exA), 0);
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exLen), 0);
return;
}

Expand Down Expand Up @@ -454,7 +488,7 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
EntityBase *b = SK.GetEntity(entityB);
Expr *la = Distance(workplane, a->point[0], a->point[1]);
Expr *lb = Distance(workplane, b->point[0], b->point[1]);
AddEq(l, (la->Minus(lb))->Minus(exA), 0);
AddEq(l, (la->Minus(lb))->Minus(exLen), 0);
return;
}

Expand Down Expand Up @@ -520,7 +554,7 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
theta2 = (Expr::From(2*PI))->Minus(costheta2->ACos());
}
// And write the equation; (r1*theta1) - ( r2*theta2) = some difference
AddEq(l, (r1->Times(theta1))->Minus(r2->Times(theta2))->Minus(exA), 0);
AddEq(l, (r1->Times(theta1))->Minus(r2->Times(theta2))->Minus(exLen), 0);
return;
}

Expand Down Expand Up @@ -558,14 +592,14 @@ void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
theta1 = (Expr::From(2*PI))->Minus(costheta1->ACos());
}
// And write the equation; (r1*theta1) - ( length) = some difference
AddEq(l, (r1->Times(theta1))->Minus(ll)->Minus(exA), 0);
AddEq(l, (r1->Times(theta1))->Minus(ll)->Minus(exLen), 0);
return;
}

case Type::DIAMETER: {
EntityBase *circle = SK.GetEntity(entityA);
Expr *r = circle->CircleGetRadiusExpr();
AddEq(l, (r->Times(Expr::From(2)))->Minus(exA), 0);
AddEq(l, (r->Times(Expr::From(2)))->Minus(exLen), 0);
return;
}

Expand Down
18 changes: 14 additions & 4 deletions src/drawconstraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,30 @@ namespace SolveSpace {
std::string Constraint::Label() const {
std::string result;
if(type == Type::ANGLE) {
result = SS.DegreeToString(valA) + "°";
if(comment != "") {
result = comment;
} else {
result = SS.DegreeToString(valA) + "°";
}
} else if(type == Type::LENGTH_RATIO || type == Type::ARC_ARC_LEN_RATIO || type == Type::ARC_LINE_LEN_RATIO) {
result = ssprintf("%.3f:1", valA);
} else if(type == Type::COMMENT) {
result = comment;
} else if(type == Type::DIAMETER) {
if(!other) {
if(comment != "") {
result = comment;
} else if(!other) {
result = "⌀" + SS.MmToStringSI(valA);
} else {
result = "R" + SS.MmToStringSI(valA / 2);
}
} else {
// valA has units of distance
result = SS.MmToStringSI(fabs(valA));
if(comment != "") {
result = comment;
} else {
// valA has units of distance
result = SS.MmToStringSI(fabs(valA));
}
}
if(reference) {
result += " REF";
Expand Down
40 changes: 32 additions & 8 deletions src/expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// Copyright 2008-2013 Jonathan Westhues.
//-----------------------------------------------------------------------------
#include "solvespace.h"
#include "sketch.h"

namespace SolveSpace {

Expand Down Expand Up @@ -648,6 +649,9 @@ class ExprParser {
std::string::const_iterator it, end;
std::vector<Token> stack;

int *varCnt;
std::unordered_map<std::string, hParam> *vars;

char ReadChar();
char PeekChar();

Expand All @@ -659,11 +663,12 @@ class ExprParser {

int Precedence(Token token);
Token LexNumber(std::string *error);
// Token Lex(std::string *error);
Token Lex(std::string *error);
bool Reduce(std::string *error);
bool Parse(std::string *error, size_t reduceUntil = 0);

static Expr *Parse(const std::string &input, std::string *error);
static Expr* Parse(const std::string &input, std::string *error, int *cntNames = 0,
std::unordered_map<std::string, hParam> *paramNames = NULL);
};

ExprParser::Token ExprParser::Token::From(TokenType type, Expr *expr) {
Expand Down Expand Up @@ -761,8 +766,21 @@ ExprParser::Token ExprParser::Lex(std::string *error) {
} else if(s == "pi") {
t = Token::From(TokenType::OPERAND, Expr::Op::CONSTANT);
t.expr->v = PI;
} else {
*error = "'" + s + "' is not a valid variable, function or constant";
} else { // check the named parameters
bool found = false;
if(vars) {
if(vars->find(s) != vars->end()) {
t = Token::From(TokenType::OPERAND, Expr::Op::PARAM);
hParam hp = (*vars)[s];
t.expr->parh = hp;
found = true;
if(varCnt) *varCnt += 1;
}
}
if(!found)
{
*error = "'" + s + "' is not a valid variable, function or constant";
}
}
} else if(isdigit(c) || c == '.') {
return LexNumber(error);
Expand Down Expand Up @@ -932,8 +950,13 @@ bool ExprParser::Parse(std::string *error, size_t reduceUntil) {
return true;
}

Expr *ExprParser::Parse(const std::string &input, std::string *error) {
Expr* ExprParser::Parse(const std::string &input, std::string *error, int *cntNames,
std::unordered_map<std::string, hParam> *paramNames) {

ExprParser parser;
parser.vars = paramNames;
parser.varCnt = cntNames;

parser.it = input.cbegin();
parser.end = input.cend();
if(!parser.Parse(error)) return NULL;
Expand All @@ -943,13 +966,14 @@ Expr *ExprParser::Parse(const std::string &input, std::string *error) {
return r.expr;
}

Expr *Expr::Parse(const std::string &input, std::string *error) {
Expr* Expr::Parse(const std::string &input, std::string *error) {
return ExprParser::Parse(input, error);
}

Expr *Expr::From(const std::string &input, bool popUpError) {
Expr* Expr::From(const std::string &input, bool popUpError, int* paramCount,
std::unordered_map<std::string, hParam> *paramNames) {
std::string error;
Expr *e = ExprParser::Parse(input, &error);
Expr *e = ExprParser::Parse(input, &error, paramCount, paramNames);
if(!e) {
dbp("Parse/lex error: %s", error.c_str());
if(popUpError) {
Expand Down
6 changes: 4 additions & 2 deletions src/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ class Expr {
ParamList *thenTry,
bool foldConstants = false) const;

static Expr *Parse(const std::string &input, std::string *error);
static Expr *From(const std::string &input, bool popUpError);
static Expr* Parse(const std::string &input, std::string *error);
// static Expr* From(const std::string &input, bool popUpError);
static Expr* From(const std::string &input, bool popUpError, int* paramCount = 0,
std::unordered_map<std::string, hParam> *paramNames = NULL);
};

class ExprVector {
Expand Down
15 changes: 15 additions & 0 deletions src/generate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
SK.entity.Clear();
SK.entity.ReserveMore(oldEntityCount);

// For seeding the name dictionary of each group start with references
hGroup hprev = SK.groupOrder[0];
// Not using range-for because we're using the index inside the loop.
for(i = 0; i < SK.groupOrder.n; i++) {
hGroup hg = SK.groupOrder[i];
Expand All @@ -244,14 +246,27 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
if(PruneGroups(hg))
goto pruned;

Group *pg = SK.GetGroup(hg);
// import the named_parameter dictionary from the previous group
pg->dict.clear();
pg->dict = SK.GetGroup(hprev)->dict;
hprev = hg;
// pg->dict = SK.GetGroup(Group::HGROUP_REFERENCES)->dict;

int groupRequestIndex = 0;
for(auto &req : SK.request) {
Request *r = &req;
if(r->group != hg) continue;
r->groupRequestIndex = groupRequestIndex++;

r->Generate(&(SK.entity), &(SK.param));
// we only add parameters from this group or overwrite handles
if ((r->type == Request::Type::NAMED_PARAMETER)
||(r->type == Request::Type::NAMED_CONST_PARAM)) {
pg->dict[r->str] = r->h.param(64);
}
}

for(auto &con : SK.constraint) {
Constraint *c = &con;
if(c->group != hg) continue;
Expand Down
38 changes: 31 additions & 7 deletions src/mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,8 +1385,12 @@ void GraphicsWindow::EditConstraint(hConstraint constraint) {
if(c->type == Constraint::Type::DIAMETER && c->other)
value /= 2;

if(c->comment != "") {
editValue = c->comment;
editPlaceholder = "aaaaaaaaaa";
break;
} else if(c->type == Constraint::Type::LENGTH_RATIO || c->type == Constraint::Type::ARC_ARC_LEN_RATIO || c->type == Constraint::Type::ARC_LINE_LEN_RATIO) {
// Try showing value with default number of digits after decimal first.
if(c->type == Constraint::Type::LENGTH_RATIO || c->type == Constraint::Type::ARC_ARC_LEN_RATIO || c->type == Constraint::Type::ARC_LINE_LEN_RATIO) {
editValue = ssprintf("%.3f", value);
} else if(c->type == Constraint::Type::ANGLE) {
editValue = SS.DegreeToString(value);
Expand Down Expand Up @@ -1439,9 +1443,27 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
return;
}

if(Expr *e = Expr::From(s, true)) {
// we will need to reference the group dictionary.
Group *gp = SK.GetGroup(c->group);

int usedParams = 0;

// if(Expr *e = Expr::From(s, true)) {
Expr *e = Expr::From(s, true, &usedParams, &gp->dict);
if(e) {
SS.UndoRemember();

double distance = 1.0;
if(usedParams != 0)
{
c->comment = s;
distance = SS.MmPerUnit();
}
else
{
c->comment = "";
distance = SS.ExprToMm(e);
}

switch(c->type) {
case Constraint::Type::PROJ_PT_DISTANCE:
case Constraint::Type::PT_LINE_DISTANCE:
Expand All @@ -1455,9 +1477,11 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
// negative distance.
bool wasNeg = (c->valA < 0);
if(wasNeg) {
c->valA = -SS.ExprToMm(e);
// c->valA = -SS.ExprToMm(e);
c->valA = -distance;
} else {
c->valA = SS.ExprToMm(e);
// c->valA = SS.ExprToMm(e);
c->valA = distance;
}
break;
}
Expand All @@ -1471,7 +1495,7 @@ void GraphicsWindow::EditControlDone(const std::string &s) {
break;

case Constraint::Type::DIAMETER:
c->valA = fabs(SS.ExprToMm(e));
c->valA = fabs(distance);

// If displayed and edited as radius, convert back
// to diameter
Expand All @@ -1481,7 +1505,7 @@ void GraphicsWindow::EditControlDone(const std::string &s) {

default:
// These are always positive, and they get the units conversion.
c->valA = fabs(SS.ExprToMm(e));
c->valA = fabs(distance);
break;
}
SS.MarkGroupDirty(c->group);
Expand Down
Loading