2013-07-28 22:08:34 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Given a constraint, generate one or more equations in our symbolic algebra
|
|
|
|
// system to represent that constraint; also various geometric helper
|
|
|
|
// functions for that.
|
|
|
|
//
|
|
|
|
// Copyright 2008-2013 Jonathan Westhues.
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-01-03 12:31:19 +00:00
|
|
|
#include "solvespace.h"
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
const hConstraint ConstraintBase::NO_CONSTRAINT = { 0 };
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
bool ConstraintBase::HasLabel() const {
|
2010-05-10 01:06:09 +00:00
|
|
|
switch(type) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_LINE_DISTANCE:
|
|
|
|
case Type::PT_PLANE_DISTANCE:
|
|
|
|
case Type::PT_FACE_DISTANCE:
|
|
|
|
case Type::PT_PT_DISTANCE:
|
|
|
|
case Type::PROJ_PT_DISTANCE:
|
|
|
|
case Type::DIAMETER:
|
|
|
|
case Type::LENGTH_RATIO:
|
|
|
|
case Type::LENGTH_DIFFERENCE:
|
|
|
|
case Type::ANGLE:
|
|
|
|
case Type::COMMENT:
|
2010-05-10 01:06:09 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:15:15 +00:00
|
|
|
ExprVector ConstraintBase::VectorsParallel3d(ExprVector a, ExprVector b, hParam p) {
|
|
|
|
return a.Minus(b.ScaledBy(Expr::From(p)));
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *ConstraintBase::PointLineDistance(hEntity wrkpl, hEntity hpt, hEntity hln)
|
|
|
|
{
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ln = SK.GetEntity(hln);
|
|
|
|
EntityBase *a = SK.GetEntity(ln->point[0]);
|
|
|
|
EntityBase *b = SK.GetEntity(ln->point[1]);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *p = SK.GetEntity(hpt);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
2019-07-09 14:44:57 +00:00
|
|
|
if(wrkpl == EntityBase::FREE_IN_3D) {
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector ep = p->PointGetExprs();
|
|
|
|
|
|
|
|
ExprVector ea = a->PointGetExprs();
|
|
|
|
ExprVector eb = b->PointGetExprs();
|
|
|
|
ExprVector eab = ea.Minus(eb);
|
|
|
|
Expr *m = eab.Magnitude();
|
|
|
|
|
|
|
|
return ((eab.Cross(ea.Minus(ep))).Magnitude())->Div(m);
|
|
|
|
} else {
|
|
|
|
Expr *ua, *va, *ub, *vb;
|
|
|
|
a->PointGetExprsInWorkplane(wrkpl, &ua, &va);
|
|
|
|
b->PointGetExprsInWorkplane(wrkpl, &ub, &vb);
|
|
|
|
|
|
|
|
Expr *du = ua->Minus(ub);
|
|
|
|
Expr *dv = va->Minus(vb);
|
|
|
|
|
|
|
|
Expr *u, *v;
|
|
|
|
p->PointGetExprsInWorkplane(wrkpl, &u, &v);
|
|
|
|
|
|
|
|
Expr *m = ((du->Square())->Plus(dv->Square()))->Sqrt();
|
|
|
|
|
|
|
|
Expr *proj = (dv->Times(ua->Minus(u)))->Minus(
|
|
|
|
(du->Times(va->Minus(v))));
|
|
|
|
|
|
|
|
return proj->Div(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *ConstraintBase::PointPlaneDistance(ExprVector p, hEntity hpl) {
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector n;
|
|
|
|
Expr *d;
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetEntity(hpl)->WorkplaneGetPlaneExprs(&n, &d);
|
2009-01-03 12:31:19 +00:00
|
|
|
return (p.Dot(n))->Minus(d);
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *ConstraintBase::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *pa = SK.GetEntity(hpa);
|
|
|
|
EntityBase *pb = SK.GetEntity(hpb);
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(pa->IsPoint() && pb->IsPoint(),
|
|
|
|
"Expected two points to measure projected distance between");
|
2009-01-03 12:31:19 +00:00
|
|
|
|
2019-07-09 14:44:57 +00:00
|
|
|
if(wrkpl == EntityBase::FREE_IN_3D) {
|
2009-01-03 12:31:19 +00:00
|
|
|
// This is true distance
|
|
|
|
ExprVector ea, eb, eab;
|
|
|
|
ea = pa->PointGetExprs();
|
|
|
|
eb = pb->PointGetExprs();
|
|
|
|
eab = ea.Minus(eb);
|
|
|
|
|
|
|
|
return eab.Magnitude();
|
|
|
|
} else {
|
|
|
|
// This is projected distance, in the given workplane.
|
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
|
|
|
|
pa->PointGetExprsInWorkplane(wrkpl, &au, &av);
|
|
|
|
pb->PointGetExprsInWorkplane(wrkpl, &bu, &bv);
|
|
|
|
|
|
|
|
Expr *du = au->Minus(bu);
|
|
|
|
Expr *dv = av->Minus(bv);
|
|
|
|
|
|
|
|
return ((du->Square())->Plus(dv->Square()))->Sqrt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Return the cosine of the angle between two vectors. If a workplane is
|
|
|
|
// specified, then it's the cosine of their projections into that workplane.
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *ConstraintBase::DirectionCosine(hEntity wrkpl,
|
|
|
|
ExprVector ae, ExprVector be)
|
|
|
|
{
|
2019-07-09 14:44:57 +00:00
|
|
|
if(wrkpl == EntityBase::FREE_IN_3D) {
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *mags = (ae.Magnitude())->Times(be.Magnitude());
|
|
|
|
return (ae.Dot(be))->Div(mags);
|
|
|
|
} else {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *w = SK.GetEntity(wrkpl);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector u = w->Normal()->NormalExprsU();
|
|
|
|
ExprVector v = w->Normal()->NormalExprsV();
|
|
|
|
Expr *ua = u.Dot(ae);
|
|
|
|
Expr *va = v.Dot(ae);
|
|
|
|
Expr *ub = u.Dot(be);
|
|
|
|
Expr *vb = v.Dot(be);
|
|
|
|
Expr *maga = (ua->Square()->Plus(va->Square()))->Sqrt();
|
|
|
|
Expr *magb = (ub->Square()->Plus(vb->Square()))->Sqrt();
|
|
|
|
Expr *dot = (ua->Times(ub))->Plus(va->Times(vb));
|
|
|
|
return dot->Div(maga->Times(magb));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector ConstraintBase::PointInThreeSpace(hEntity workplane,
|
|
|
|
Expr *u, Expr *v)
|
|
|
|
{
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *w = SK.GetEntity(workplane);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
ExprVector ub = w->Normal()->NormalExprsU();
|
|
|
|
ExprVector vb = w->Normal()->NormalExprsV();
|
|
|
|
ExprVector ob = w->WorkplaneGetOffsetExprs();
|
|
|
|
|
|
|
|
return (ub.ScaledBy(u)).Plus(vb.ScaledBy(v)).Plus(ob);
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void ConstraintBase::ModifyToSatisfy() {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(type == Type::ANGLE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector a = SK.GetEntity(entityA)->VectorGetNum();
|
|
|
|
Vector b = SK.GetEntity(entityB)->VectorGetNum();
|
2009-01-03 12:31:19 +00:00
|
|
|
if(other) a = a.ScaledBy(-1);
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane != EntityBase::FREE_IN_3D) {
|
2009-01-03 12:31:19 +00:00
|
|
|
a = a.ProjectVectorInto(workplane);
|
|
|
|
b = b.ProjectVectorInto(workplane);
|
|
|
|
}
|
|
|
|
double c = (a.Dot(b))/(a.Magnitude() * b.Magnitude());
|
|
|
|
valA = acos(c)*180/PI;
|
2017-01-25 16:39:26 +00:00
|
|
|
} else if(type == Type::PT_ON_LINE) {
|
|
|
|
EntityBase *eln = SK.GetEntity(entityA);
|
|
|
|
EntityBase *ea = SK.GetEntity(eln->point[0]);
|
|
|
|
EntityBase *eb = SK.GetEntity(eln->point[1]);
|
|
|
|
EntityBase *ep = SK.GetEntity(ptA);
|
|
|
|
ExprVector exp = ep->PointGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector exa = ea->PointGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector exb = eb->PointGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector exba = exb.Minus(exa);
|
|
|
|
SK.GetParam(valP)->val = exba.Dot(exp.Minus(exa))->Eval() / exba.Dot(exba)->Eval();
|
2009-01-03 12:31:19 +00:00
|
|
|
} else {
|
|
|
|
// We'll fix these ones up by looking at their symbolic equation;
|
|
|
|
// that means no extra work.
|
2015-03-27 15:31:23 +00:00
|
|
|
IdList<Equation,hEquation> l = {};
|
2009-01-03 12:31:19 +00:00
|
|
|
// Generate the equations even if this is a reference dimension
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
GenerateEquations(&l, /*forReference=*/true);
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(l.n == 1, "Expected constraint to generate a single equation");
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
// These equations are written in the form f(...) - d = 0, where
|
|
|
|
// d is the value of the valA.
|
|
|
|
valA += (l.elem[0].e)->Eval();
|
|
|
|
|
|
|
|
l.Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
void ConstraintBase::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) const
|
2009-04-19 04:28:21 +00:00
|
|
|
{
|
2009-01-03 12:31:19 +00:00
|
|
|
Equation eq;
|
|
|
|
eq.e = expr;
|
|
|
|
eq.h = h.equation(index);
|
|
|
|
l->Add(&eq);
|
|
|
|
}
|
|
|
|
|
2016-11-01 17:15:15 +00:00
|
|
|
void ConstraintBase::AddEq(IdList<Equation,hEquation> *l, const ExprVector &v,
|
|
|
|
int baseIndex) const {
|
|
|
|
AddEq(l, v.x, baseIndex);
|
|
|
|
AddEq(l, v.y, baseIndex + 1);
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2016-11-01 17:15:15 +00:00
|
|
|
AddEq(l, v.z, baseIndex + 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-25 16:39:26 +00:00
|
|
|
void ConstraintBase::Generate(IdList<Param,hParam> *l) {
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
switch(type) {
|
2016-11-01 17:15:15 +00:00
|
|
|
case Type::PARALLEL:
|
2016-11-27 07:59:47 +00:00
|
|
|
case Type::CUBIC_LINE_TANGENT:
|
|
|
|
// Add new parameter only when we operate in 3d space
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane != EntityBase::FREE_IN_3D) break;
|
2016-11-01 17:15:15 +00:00
|
|
|
// fallthrough
|
2016-11-27 08:43:21 +00:00
|
|
|
case Type::SAME_ORIENTATION:
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
case Type::PT_ON_LINE: {
|
|
|
|
Param p = {};
|
2017-01-25 16:39:26 +00:00
|
|
|
valP = h.param(0);
|
|
|
|
p.h = valP;
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
l->Add(&p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
void ConstraintBase::GenerateEquations(IdList<Equation,hEquation> *l,
|
|
|
|
bool forReference) const {
|
|
|
|
if(reference && !forReference) return;
|
|
|
|
|
|
|
|
Expr *exA = Expr::From(valA);
|
2009-01-03 12:31:19 +00:00
|
|
|
switch(type) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_PT_DISTANCE:
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, Distance(workplane, ptA, ptB)->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PROJ_PT_DISTANCE: {
|
2010-01-27 18:15:06 +00:00
|
|
|
ExprVector pA = SK.GetEntity(ptA)->PointGetExprs(),
|
|
|
|
pB = SK.GetEntity(ptB)->PointGetExprs(),
|
|
|
|
dp = pB.Minus(pA);
|
|
|
|
|
|
|
|
ExprVector pp = SK.GetEntity(entityA)->VectorGetExprs();
|
|
|
|
pp = pp.WithMagnitude(Expr::From(1.0));
|
|
|
|
|
|
|
|
AddEq(l, (dp.Dot(pp))->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2010-01-27 18:15:06 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_LINE_DISTANCE:
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l,
|
|
|
|
PointLineDistance(workplane, ptA, entityA)->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_PLANE_DISTANCE: {
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector pt = SK.GetEntity(ptA)->PointGetExprs();
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, (PointPlaneDistance(pt, entityA))->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_FACE_DISTANCE: {
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector pt = SK.GetEntity(ptA)->PointGetExprs();
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *f = SK.GetEntity(entityA);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector p0 = f->FaceGetPointExprs();
|
|
|
|
ExprVector n = f->FaceGetNormalExprs();
|
|
|
|
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQUAL_LENGTH_LINES: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
EntityBase *b = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, Distance(workplane, a->point[0], a->point[1])->Minus(
|
|
|
|
Distance(workplane, b->point[0], b->point[1])), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// These work on distance squared, since the pt-line distances are
|
|
|
|
// signed, and we want the absolute value.
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQ_LEN_PT_LINE_D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *forLen = SK.GetEntity(entityA);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *d1 = Distance(workplane, forLen->point[0], forLen->point[1]);
|
|
|
|
Expr *d2 = PointLineDistance(workplane, ptA, entityB);
|
|
|
|
AddEq(l, (d1->Square())->Minus(d2->Square()), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQ_PT_LN_DISTANCES: {
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *d1 = PointLineDistance(workplane, ptA, entityA);
|
|
|
|
Expr *d2 = PointLineDistance(workplane, ptB, entityB);
|
|
|
|
AddEq(l, (d1->Square())->Minus(d2->Square()), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::LENGTH_RATIO: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
EntityBase *b = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *la = Distance(workplane, a->point[0], a->point[1]);
|
|
|
|
Expr *lb = Distance(workplane, b->point[0], b->point[1]);
|
|
|
|
AddEq(l, (la->Div(lb))->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::LENGTH_DIFFERENCE: {
|
2015-10-27 10:28:33 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
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);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2015-10-27 10:28:33 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::DIAMETER: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *circle = SK.GetEntity(entityA);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *r = circle->CircleGetRadiusExpr();
|
|
|
|
AddEq(l, (r->Times(Expr::From(2)))->Minus(exA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQUAL_RADIUS: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *c1 = SK.GetEntity(entityA);
|
|
|
|
EntityBase *c2 = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, (c1->CircleGetRadiusExpr())->Minus(
|
|
|
|
c2->CircleGetRadiusExpr()), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQUAL_LINE_ARC_LEN: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *line = SK.GetEntity(entityA),
|
|
|
|
*arc = SK.GetEntity(entityB);
|
2009-01-08 17:22:59 +00:00
|
|
|
|
|
|
|
// Get the line length
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector l0 = SK.GetEntity(line->point[0])->PointGetExprs(),
|
|
|
|
l1 = SK.GetEntity(line->point[1])->PointGetExprs();
|
2009-01-08 17:22:59 +00:00
|
|
|
Expr *ll = (l1.Minus(l0)).Magnitude();
|
|
|
|
|
|
|
|
// And get the arc radius, and the cosine of its angle
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ao = SK.GetEntity(arc->point[0]),
|
|
|
|
*as = SK.GetEntity(arc->point[1]),
|
|
|
|
*af = SK.GetEntity(arc->point[2]);
|
2009-01-08 17:22:59 +00:00
|
|
|
|
|
|
|
ExprVector aos = (as->PointGetExprs()).Minus(ao->PointGetExprs()),
|
|
|
|
aof = (af->PointGetExprs()).Minus(ao->PointGetExprs());
|
|
|
|
Expr *r = aof.Magnitude();
|
|
|
|
|
|
|
|
ExprVector n = arc->Normal()->NormalExprsN();
|
|
|
|
ExprVector u = aos.WithMagnitude(Expr::From(1.0));
|
|
|
|
ExprVector v = n.Cross(u);
|
|
|
|
// so in our new csys, we start at (1, 0, 0)
|
|
|
|
Expr *costheta = aof.Dot(u)->Div(r);
|
|
|
|
Expr *sintheta = aof.Dot(v)->Div(r);
|
|
|
|
|
|
|
|
double thetas, thetaf, dtheta;
|
|
|
|
arc->ArcGetAngles(&thetas, &thetaf, &dtheta);
|
|
|
|
Expr *theta;
|
|
|
|
if(dtheta < 3*PI/4) {
|
|
|
|
theta = costheta->ACos();
|
|
|
|
} else if(dtheta < 5*PI/4) {
|
|
|
|
// As the angle crosses pi, cos theta is not invertible;
|
|
|
|
// so use the sine to stop blowing up
|
|
|
|
theta = Expr::From(PI)->Minus(sintheta->ASin());
|
|
|
|
} else {
|
|
|
|
theta = (Expr::From(2*PI))->Minus(costheta->ACos());
|
|
|
|
}
|
|
|
|
|
|
|
|
// And write the equation; r*theta = L
|
|
|
|
AddEq(l, (r->Times(theta))->Minus(ll), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-08 17:22:59 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::POINTS_COINCIDENT: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(ptA);
|
|
|
|
EntityBase *b = SK.GetEntity(ptB);
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector pa = a->PointGetExprs();
|
|
|
|
ExprVector pb = b->PointGetExprs();
|
|
|
|
AddEq(l, pa.x->Minus(pb.x), 0);
|
|
|
|
AddEq(l, pa.y->Minus(pb.y), 1);
|
|
|
|
AddEq(l, pa.z->Minus(pb.z), 2);
|
|
|
|
} else {
|
|
|
|
Expr *au, *av;
|
|
|
|
Expr *bu, *bv;
|
|
|
|
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
|
|
|
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
|
|
|
AddEq(l, au->Minus(bu), 0);
|
|
|
|
AddEq(l, av->Minus(bv), 1);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_IN_PLANE:
|
2009-01-03 12:31:19 +00:00
|
|
|
// This one works the same, whether projected or not.
|
|
|
|
AddEq(l, PointPlaneDistance(
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetEntity(ptA)->PointGetExprs(), entityA), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_ON_FACE: {
|
2009-01-03 12:31:19 +00:00
|
|
|
// a plane, n dot (p - p0) = 0
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector p = SK.GetEntity(ptA)->PointGetExprs();
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *f = SK.GetEntity(entityA);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector p0 = f->FaceGetPointExprs();
|
|
|
|
ExprVector n = f->FaceGetNormalExprs();
|
|
|
|
AddEq(l, (p.Minus(p0)).Dot(n), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
case Type::PT_ON_LINE: {
|
|
|
|
EntityBase *ln = SK.GetEntity(entityA);
|
|
|
|
EntityBase *a = SK.GetEntity(ln->point[0]);
|
|
|
|
EntityBase *b = SK.GetEntity(ln->point[1]);
|
|
|
|
EntityBase *p = SK.GetEntity(ptA);
|
|
|
|
|
|
|
|
ExprVector ep = p->PointGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector ea = a->PointGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector eb = b->PointGetExprsInWorkplane(workplane);
|
|
|
|
|
2017-01-25 16:39:26 +00:00
|
|
|
ExprVector ptOnLine = ea.Plus(eb.Minus(ea).ScaledBy(Expr::From(valP)));
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
ExprVector eq = ptOnLine.Minus(ep);
|
|
|
|
|
2016-11-01 17:15:15 +00:00
|
|
|
AddEq(l, eq);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
Rewrite equations generated for pt-on-line constraints.
Before this commit, pt-on-line constraints are buggy. To reproduce,
extrude a circle, then add a datum point and constrain it to the
axis of the circle, then move it. The cylinder will collapse.
To quote Jonathan:
> On investigation, I (a) confirm that the problem is
> the unconstrained extrusion depth going to zero, and (b) retract
> my earlier statement blaming extrude and other similar non-entity
> parameter treatment for this problem; you can easily reproduce it
> with a point in 3d constrained to lie on any line whose length
> is free.
>
> PT_ON_LINE is written using VectorsParallel, for no obvious reason.
> Rewriting that constraint to work on two projected distances (using
> any two basis vectors perpendicular to the line) should fix that
> problem, since replacing the "point on line in 3d" constraint with
> two "point on line in 2d" constraints works. That still has
> the hairy ball problem of choosing the basis vectors, which you
> can't do with a continuous function; you'd need Vector::Normal()
> or equivalent.
>
> You could write three equations and make the constraint itself
> introduce one new parameter for t. I don't know how well that
> would work numerically, but it would avoid the hairy ball problem,
> perhaps elegant at the cost of speed.
Indeed, this commit implements the latter solution: it introduces
an additional free parameter. The point being coincident with
the start of the line corresponds to the parameter being zero, and
point being coincident with the end corresponds to one).
In effect, instead of constraining two of three degrees of freedom
(for which the equations do not exist because of the hairy ball
theorem), it constrains three and adds one more.
2016-11-01 16:06:57 +00:00
|
|
|
}
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PT_ON_CIRCLE: {
|
2009-01-03 12:31:19 +00:00
|
|
|
// This actually constrains the point to lie on the cylinder.
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *circle = SK.GetEntity(entityA);
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector center = SK.GetEntity(circle->point[0])->PointGetExprs();
|
|
|
|
ExprVector pt = SK.GetEntity(ptA)->PointGetExprs();
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *normal = SK.GetEntity(circle->normal);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector u = normal->NormalExprsU(),
|
|
|
|
v = normal->NormalExprsV();
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *du = (center.Minus(pt)).Dot(u),
|
|
|
|
*dv = (center.Minus(pt)).Dot(v);
|
|
|
|
|
|
|
|
Expr *r = circle->CircleGetRadiusExpr();
|
|
|
|
|
2017-04-08 14:38:07 +00:00
|
|
|
AddEq(l, du->Square()->Plus(dv->Square())->Sqrt()->Minus(r), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::AT_MIDPOINT:
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ln = SK.GetEntity(entityA);
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector a = SK.GetEntity(ln->point[0])->PointGetExprs();
|
|
|
|
ExprVector b = SK.GetEntity(ln->point[1])->PointGetExprs();
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector m = (a.Plus(b)).ScaledBy(Expr::From(0.5));
|
|
|
|
|
|
|
|
if(ptA.v) {
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector p = SK.GetEntity(ptA)->PointGetExprs();
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, (m.x)->Minus(p.x), 0);
|
|
|
|
AddEq(l, (m.y)->Minus(p.y), 1);
|
|
|
|
AddEq(l, (m.z)->Minus(p.z), 2);
|
|
|
|
} else {
|
|
|
|
AddEq(l, PointPlaneDistance(m, entityB), 0);
|
|
|
|
}
|
|
|
|
} else {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ln = SK.GetEntity(entityA);
|
|
|
|
EntityBase *a = SK.GetEntity(ln->point[0]);
|
|
|
|
EntityBase *b = SK.GetEntity(ln->point[1]);
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
|
|
|
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
|
|
|
Expr *mu = Expr::From(0.5)->Times(au->Plus(bu));
|
|
|
|
Expr *mv = Expr::From(0.5)->Times(av->Plus(bv));
|
|
|
|
|
|
|
|
if(ptA.v) {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *p = SK.GetEntity(ptA);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *pu, *pv;
|
|
|
|
p->PointGetExprsInWorkplane(workplane, &pu, &pv);
|
|
|
|
AddEq(l, pu->Minus(mu), 0);
|
|
|
|
AddEq(l, pv->Minus(mv), 1);
|
|
|
|
} else {
|
|
|
|
ExprVector m = PointInThreeSpace(workplane, mu, mv);
|
|
|
|
AddEq(l, PointPlaneDistance(m, entityB), 0);
|
|
|
|
}
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::SYMMETRIC:
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *plane = SK.GetEntity(entityA);
|
|
|
|
EntityBase *ea = SK.GetEntity(ptA);
|
|
|
|
EntityBase *eb = SK.GetEntity(ptB);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector a = ea->PointGetExprs();
|
|
|
|
ExprVector b = eb->PointGetExprs();
|
|
|
|
|
|
|
|
// The midpoint of the line connecting the symmetric points
|
|
|
|
// lies on the plane of the symmetry.
|
|
|
|
ExprVector m = (a.Plus(b)).ScaledBy(Expr::From(0.5));
|
|
|
|
AddEq(l, PointPlaneDistance(m, plane->h), 0);
|
|
|
|
|
|
|
|
// And projected into the plane of symmetry, the points are
|
|
|
|
// coincident.
|
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
ea->PointGetExprsInWorkplane(plane->h, &au, &av);
|
|
|
|
eb->PointGetExprsInWorkplane(plane->h, &bu, &bv);
|
|
|
|
AddEq(l, au->Minus(bu), 1);
|
|
|
|
AddEq(l, av->Minus(bv), 2);
|
|
|
|
} else {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *plane = SK.GetEntity(entityA);
|
|
|
|
EntityBase *a = SK.GetEntity(ptA);
|
|
|
|
EntityBase *b = SK.GetEntity(ptB);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
|
|
|
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
|
|
|
Expr *mu = Expr::From(0.5)->Times(au->Plus(bu));
|
|
|
|
Expr *mv = Expr::From(0.5)->Times(av->Plus(bv));
|
|
|
|
|
|
|
|
ExprVector m = PointInThreeSpace(workplane, mu, mv);
|
|
|
|
AddEq(l, PointPlaneDistance(m, plane->h), 0);
|
|
|
|
|
|
|
|
// Construct a vector within the workplane that is normal
|
|
|
|
// to the symmetry pane's normal (i.e., that lies in the
|
|
|
|
// plane of symmetry). The line connecting the points is
|
|
|
|
// perpendicular to that constructed vector.
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *w = SK.GetEntity(workplane);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector u = w->Normal()->NormalExprsU();
|
|
|
|
ExprVector v = w->Normal()->NormalExprsV();
|
|
|
|
|
|
|
|
ExprVector pa = a->PointGetExprs();
|
|
|
|
ExprVector pb = b->PointGetExprs();
|
|
|
|
ExprVector n;
|
|
|
|
Expr *d;
|
|
|
|
plane->WorkplaneGetPlaneExprs(&n, &d);
|
|
|
|
AddEq(l, (n.Cross(u.Cross(v))).Dot(pa.Minus(pb)), 1);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::SYMMETRIC_HORIZ:
|
|
|
|
case Type::SYMMETRIC_VERT: {
|
2019-07-09 14:44:57 +00:00
|
|
|
ssassert(workplane != Entity::FREE_IN_3D,
|
2016-11-19 10:19:08 +00:00
|
|
|
"Unexpected horizontal/vertical symmetric constraint in 3d");
|
|
|
|
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(ptA);
|
|
|
|
EntityBase *b = SK.GetEntity(ptB);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
|
|
|
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(type == Type::SYMMETRIC_HORIZ) {
|
2009-01-03 12:31:19 +00:00
|
|
|
AddEq(l, av->Minus(bv), 0);
|
|
|
|
AddEq(l, au->Plus(bu), 1);
|
|
|
|
} else {
|
|
|
|
AddEq(l, au->Minus(bu), 0);
|
|
|
|
AddEq(l, av->Plus(bv), 1);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::SYMMETRIC_LINE: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *pa = SK.GetEntity(ptA);
|
|
|
|
EntityBase *pb = SK.GetEntity(ptB);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
Expr *pau, *pav, *pbu, *pbv;
|
|
|
|
pa->PointGetExprsInWorkplane(workplane, &pau, &pav);
|
|
|
|
pb->PointGetExprsInWorkplane(workplane, &pbu, &pbv);
|
|
|
|
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ln = SK.GetEntity(entityA);
|
|
|
|
EntityBase *la = SK.GetEntity(ln->point[0]);
|
|
|
|
EntityBase *lb = SK.GetEntity(ln->point[1]);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *lau, *lav, *lbu, *lbv;
|
|
|
|
la->PointGetExprsInWorkplane(workplane, &lau, &lav);
|
|
|
|
lb->PointGetExprsInWorkplane(workplane, &lbu, &lbv);
|
|
|
|
|
|
|
|
Expr *dpu = pbu->Minus(pau), *dpv = pbv->Minus(pav);
|
|
|
|
Expr *dlu = lbu->Minus(lau), *dlv = lbv->Minus(lav);
|
|
|
|
|
|
|
|
// The line through the points is perpendicular to the line
|
|
|
|
// of symmetry.
|
|
|
|
AddEq(l, (dlu->Times(dpu))->Plus(dlv->Times(dpv)), 0);
|
|
|
|
|
|
|
|
// And the signed distances of the points to the line are
|
|
|
|
// equal in magnitude and opposite in sign, so sum to zero
|
|
|
|
Expr *dista = (dlv->Times(lau->Minus(pau)))->Minus(
|
|
|
|
(dlu->Times(lav->Minus(pav))));
|
|
|
|
Expr *distb = (dlv->Times(lau->Minus(pbu)))->Minus(
|
|
|
|
(dlu->Times(lav->Minus(pbv))));
|
|
|
|
AddEq(l, dista->Plus(distb), 1);
|
|
|
|
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::HORIZONTAL:
|
|
|
|
case Type::VERTICAL: {
|
2019-07-09 14:44:57 +00:00
|
|
|
ssassert(workplane != Entity::FREE_IN_3D,
|
2016-11-19 10:19:08 +00:00
|
|
|
"Unexpected horizontal/vertical constraint in 3d");
|
|
|
|
|
2009-01-03 12:31:19 +00:00
|
|
|
hEntity ha, hb;
|
|
|
|
if(entityA.v) {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *e = SK.GetEntity(entityA);
|
2009-01-03 12:31:19 +00:00
|
|
|
ha = e->point[0];
|
|
|
|
hb = e->point[1];
|
|
|
|
} else {
|
|
|
|
ha = ptA;
|
|
|
|
hb = ptB;
|
|
|
|
}
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(ha);
|
|
|
|
EntityBase *b = SK.GetEntity(hb);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
Expr *au, *av, *bu, *bv;
|
|
|
|
a->PointGetExprsInWorkplane(workplane, &au, &av);
|
|
|
|
b->PointGetExprsInWorkplane(workplane, &bu, &bv);
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
AddEq(l, (type == Type::HORIZONTAL) ? av->Minus(bv) : au->Minus(bu), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::SAME_ORIENTATION: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
EntityBase *b = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
ExprVector au = a->NormalExprsU(),
|
|
|
|
an = a->NormalExprsN();
|
|
|
|
ExprVector bu = b->NormalExprsU(),
|
|
|
|
bv = b->NormalExprsV(),
|
|
|
|
bn = b->NormalExprsN();
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2017-01-25 16:39:26 +00:00
|
|
|
ExprVector eq = VectorsParallel3d(an, bn, valP);
|
2017-02-13 17:08:06 +00:00
|
|
|
AddEq(l, eq.x, 0);
|
|
|
|
AddEq(l, eq.y, 1);
|
|
|
|
AddEq(l, eq.z, 2);
|
2009-01-03 12:31:19 +00:00
|
|
|
Expr *d1 = au.Dot(bv);
|
|
|
|
Expr *d2 = au.Dot(bu);
|
|
|
|
// Allow either orientation for the coordinate system, depending
|
|
|
|
// on how it was drawn.
|
|
|
|
if(fabs(d1->Eval()) < fabs(d2->Eval())) {
|
2016-11-27 08:43:21 +00:00
|
|
|
AddEq(l, d1, 3);
|
2009-01-03 12:31:19 +00:00
|
|
|
} else {
|
2016-11-27 08:43:21 +00:00
|
|
|
AddEq(l, d2, 3);
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PERPENDICULAR:
|
|
|
|
case Type::ANGLE: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
EntityBase *b = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector ae = a->VectorGetExprs();
|
|
|
|
ExprVector be = b->VectorGetExprs();
|
|
|
|
if(other) ae = ae.ScaledBy(Expr::From(-1));
|
|
|
|
Expr *c = DirectionCosine(workplane, ae, be);
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(type == Type::ANGLE) {
|
2009-01-03 12:31:19 +00:00
|
|
|
// The direction cosine is equal to the cosine of the
|
|
|
|
// specified angle
|
2015-06-08 18:19:29 +00:00
|
|
|
Expr *rads = exA->Times(Expr::From(PI/180)),
|
|
|
|
*rc = rads->Cos();
|
|
|
|
double arc = fabs(rc->Eval());
|
|
|
|
// avoid false detection of inconsistent systems by gaining
|
|
|
|
// up as the difference in dot products gets small at small
|
|
|
|
// angles; doubles still have plenty of precision, only
|
|
|
|
// problem is that rank test
|
|
|
|
Expr *mult = Expr::From(arc > 0.99 ? 0.01/(1.00001 - arc) : 1);
|
|
|
|
AddEq(l, (c->Minus(rc))->Times(mult), 0);
|
2009-01-03 12:31:19 +00:00
|
|
|
} else {
|
|
|
|
// The dot product (and therefore the direction cosine)
|
|
|
|
// is equal to zero, perpendicular.
|
|
|
|
AddEq(l, c, 0);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::EQUAL_ANGLE: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *a = SK.GetEntity(entityA);
|
|
|
|
EntityBase *b = SK.GetEntity(entityB);
|
|
|
|
EntityBase *c = SK.GetEntity(entityC);
|
|
|
|
EntityBase *d = SK.GetEntity(entityD);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector ae = a->VectorGetExprs();
|
|
|
|
ExprVector be = b->VectorGetExprs();
|
|
|
|
ExprVector ce = c->VectorGetExprs();
|
|
|
|
ExprVector de = d->VectorGetExprs();
|
|
|
|
|
|
|
|
if(other) ae = ae.ScaledBy(Expr::From(-1));
|
|
|
|
|
|
|
|
Expr *cab = DirectionCosine(workplane, ae, be);
|
|
|
|
Expr *ccd = DirectionCosine(workplane, ce, de);
|
|
|
|
|
|
|
|
AddEq(l, cab->Minus(ccd), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::ARC_LINE_TANGENT: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *arc = SK.GetEntity(entityA);
|
|
|
|
EntityBase *line = SK.GetEntity(entityB);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector ac = SK.GetEntity(arc->point[0])->PointGetExprs();
|
2015-03-29 00:30:52 +00:00
|
|
|
ExprVector ap =
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetEntity(arc->point[other ? 2 : 1])->PointGetExprs();
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
ExprVector ld = line->VectorGetExprs();
|
|
|
|
|
|
|
|
// The line is perpendicular to the radius
|
|
|
|
AddEq(l, ld.Dot(ac.Minus(ap)), 0);
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::CUBIC_LINE_TANGENT: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *cubic = SK.GetEntity(entityA);
|
|
|
|
EntityBase *line = SK.GetEntity(entityB);
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2009-10-21 04:46:01 +00:00
|
|
|
ExprVector a;
|
|
|
|
if(other) {
|
|
|
|
a = cubic->CubicGetFinishTangentExprs();
|
|
|
|
} else {
|
|
|
|
a = cubic->CubicGetStartTangentExprs();
|
|
|
|
}
|
2009-01-03 12:31:19 +00:00
|
|
|
|
|
|
|
ExprVector b = line->VectorGetExprs();
|
|
|
|
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2017-01-25 16:39:26 +00:00
|
|
|
ExprVector eq = VectorsParallel3d(a, b, valP);
|
2016-11-27 07:59:47 +00:00
|
|
|
AddEq(l, eq);
|
2009-01-03 12:31:19 +00:00
|
|
|
} else {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *w = SK.GetEntity(workplane);
|
2009-01-03 12:31:19 +00:00
|
|
|
ExprVector wn = w->Normal()->NormalExprsN();
|
|
|
|
AddEq(l, (a.Cross(b)).Dot(wn), 0);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::CURVE_CURVE_TANGENT: {
|
2010-05-10 04:14:06 +00:00
|
|
|
bool parallel = true;
|
|
|
|
int i;
|
|
|
|
ExprVector dir[2];
|
|
|
|
for(i = 0; i < 2; i++) {
|
|
|
|
EntityBase *e = SK.GetEntity((i == 0) ? entityA : entityB);
|
|
|
|
bool oth = (i == 0) ? other : other2;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
if(e->type == Entity::Type::ARC_OF_CIRCLE) {
|
2010-05-10 04:14:06 +00:00
|
|
|
ExprVector center, endpoint;
|
|
|
|
center = SK.GetEntity(e->point[0])->PointGetExprs();
|
|
|
|
endpoint =
|
|
|
|
SK.GetEntity(e->point[oth ? 2 : 1])->PointGetExprs();
|
|
|
|
dir[i] = endpoint.Minus(center);
|
|
|
|
// We're using the vector from the center of the arc to
|
|
|
|
// an endpoint; so that's normal to the tangent, not
|
|
|
|
// parallel.
|
|
|
|
parallel = !parallel;
|
2016-08-02 17:38:42 +00:00
|
|
|
} else if(e->type == Entity::Type::CUBIC) { // BRANCH_ALWAYS_TAKEN
|
2010-05-10 04:14:06 +00:00
|
|
|
if(oth) {
|
|
|
|
dir[i] = e->CubicGetFinishTangentExprs();
|
|
|
|
} else {
|
|
|
|
dir[i] = e->CubicGetStartTangentExprs();
|
|
|
|
}
|
|
|
|
} else {
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(false, "Unexpected entity types for CURVE_CURVE_TANGENT");
|
2010-05-10 04:14:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(parallel) {
|
|
|
|
EntityBase *w = SK.GetEntity(workplane);
|
|
|
|
ExprVector wn = w->Normal()->NormalExprsN();
|
|
|
|
AddEq(l, ((dir[0]).Cross(dir[1])).Dot(wn), 0);
|
|
|
|
} else {
|
|
|
|
AddEq(l, (dir[0]).Dot(dir[1]), 0);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2010-05-10 04:14:06 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::PARALLEL: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *ea = SK.GetEntity(entityA), *eb = SK.GetEntity(entityB);
|
2016-11-01 17:15:15 +00:00
|
|
|
ExprVector a = ea->VectorGetExprsInWorkplane(workplane);
|
|
|
|
ExprVector b = eb->VectorGetExprsInWorkplane(workplane);
|
2009-01-03 12:31:19 +00:00
|
|
|
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2017-01-25 16:39:26 +00:00
|
|
|
ExprVector eq = VectorsParallel3d(a, b, valP);
|
2016-11-01 17:15:15 +00:00
|
|
|
AddEq(l, eq);
|
2009-01-03 12:31:19 +00:00
|
|
|
} else {
|
2016-11-01 17:15:15 +00:00
|
|
|
// We use expressions written in workplane csys, so we can assume the workplane
|
|
|
|
// normal is (0, 0, 1). We can write the equation as:
|
|
|
|
// Expr *eq = a.Cross(b).Dot(ExprVector::From(0.0, 0.0, 1.0));
|
|
|
|
// but this will just result in elimination of x and y terms after dot product.
|
|
|
|
// We can only use the z expression:
|
|
|
|
// Expr *eq = a.Cross(b).z;
|
|
|
|
// but it's more efficient to write it in the terms of pseudo-scalar product:
|
|
|
|
Expr *eq = (a.x->Times(b.y))->Minus(a.y->Times(b.x));
|
|
|
|
AddEq(l, eq, 0);
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
2016-11-01 17:15:15 +00:00
|
|
|
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::WHERE_DRAGGED: {
|
2010-05-04 05:11:52 +00:00
|
|
|
EntityBase *ep = SK.GetEntity(ptA);
|
2019-07-09 14:44:57 +00:00
|
|
|
if(workplane == EntityBase::FREE_IN_3D) {
|
2010-05-04 05:11:52 +00:00
|
|
|
ExprVector ev = ep->PointGetExprs();
|
|
|
|
Vector v = ep->PointGetNum();
|
|
|
|
|
|
|
|
AddEq(l, ev.x->Minus(Expr::From(v.x)), 0);
|
|
|
|
AddEq(l, ev.y->Minus(Expr::From(v.y)), 1);
|
|
|
|
AddEq(l, ev.z->Minus(Expr::From(v.z)), 2);
|
|
|
|
} else {
|
|
|
|
Expr *u, *v;
|
|
|
|
ep->PointGetExprsInWorkplane(workplane, &u, &v);
|
|
|
|
AddEq(l, u->Minus(Expr::From(u->Eval())), 0);
|
|
|
|
AddEq(l, v->Minus(Expr::From(v->Eval())), 1);
|
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2010-05-04 05:11:52 +00:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 08:31:20 +00:00
|
|
|
case Type::COMMENT:
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
return;
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
Enable exhaustive switch coverage warnings as an error, and use them.
Specifically, this enables -Wswitch=error on GCC/Clang and its MSVC
equivalent; the exact way it is handled varies slightly, but what
they all have in common is that in a switch statement over an
enumeration, any enumerand that is not explicitly (via case:) or
implicitly (via default:) handled in the switch triggers an error.
Moreover, we also change the switch statements in three ways:
* Switch statements that ought to be extended every time a new
enumerand is added (e.g. Entity::DrawOrGetDistance(), are changed
to explicitly list every single enumerand, and not have a
default: branch.
Note that the assertions are kept because it is legal for
a enumeration to have a value unlike any of its defined
enumerands, and we can e.g. read garbage from a file, or
an uninitialized variable. This requires some rearranging if
a default: branch is undesired.
* Switch statements that ought to only ever see a few select
enumerands, are changed to always assert in the default: branch.
* Switch statements that do something meaningful for a few
enumerands, and ignore everything else, are changed to do nothing
in a default: branch, under the assumption that changing them
every time an enumerand is added or removed would just result
in noise and catch no bugs.
This commit also removes the {Request,Entity,Constraint}::UNKNOWN and
Entity::DATUM_POINT enumerands, as those were just fancy names for
zeroes. They mess up switch exhaustiveness checks and most of the time
were not the best way to implement what they did anyway.
2016-05-25 06:55:50 +00:00
|
|
|
ssassert(false, "Unexpected constraint ID");
|
2009-01-03 12:31:19 +00:00
|
|
|
}
|
|
|
|
|