2013-07-28 22:08:34 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Draw a representation of an entity on-screen, in the case of curves up
|
|
|
|
// to our chord tolerance, or return the distance from the user's mouse pointer
|
|
|
|
// to the entity for selection.
|
|
|
|
//
|
|
|
|
// Copyright 2008-2013 Jonathan Westhues.
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-06-06 08:14:37 +00:00
|
|
|
#include "solvespace.h"
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
std::string Entity::DescriptionString() const {
|
2009-04-19 04:28:21 +00:00
|
|
|
if(h.isFromRequest()) {
|
2009-04-19 05:53:16 +00:00
|
|
|
Request *r = SK.GetRequest(h.request());
|
2009-04-19 04:28:21 +00:00
|
|
|
return r->DescriptionString();
|
|
|
|
} else {
|
2009-04-19 05:53:16 +00:00
|
|
|
Group *g = SK.GetGroup(h.group());
|
2009-04-19 04:28:21 +00:00
|
|
|
return g->DescriptionString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 08:20:42 +00:00
|
|
|
void Entity::LineDrawOrGetDistance(Vector a, Vector b, bool maybeFat, int data) {
|
2008-06-06 08:14:37 +00:00
|
|
|
if(dogd.drawing) {
|
2008-06-11 04:22:52 +00:00
|
|
|
// Draw lines from active group in front of those from previous
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglDepthRangeOffset((group.v == SS.GW.activeGroup.v) ? 4 : 3);
|
2009-09-18 08:14:15 +00:00
|
|
|
// Narrow lines are drawn as lines, but fat lines must be drawn as
|
|
|
|
// filled polygons, to get the line join style right.
|
2016-03-25 08:05:50 +00:00
|
|
|
ssglStippledLine(a, b, dogd.lineWidth, dogd.stippleType, dogd.stippleScale, maybeFat);
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglDepthRangeOffset(0);
|
2008-06-06 08:14:37 +00:00
|
|
|
} else {
|
|
|
|
Point2d ap = SS.GW.ProjectPoint(a);
|
|
|
|
Point2d bp = SS.GW.ProjectPoint(b);
|
|
|
|
|
2016-05-25 12:08:19 +00:00
|
|
|
double d = dogd.mp.DistanceToLine(ap, bp.Minus(ap), /*asSegment=*/true);
|
2008-06-11 04:22:52 +00:00
|
|
|
// A little bit easier to select in the active group
|
|
|
|
if(group.v == SS.GW.activeGroup.v) d -= 1;
|
2016-04-08 08:20:42 +00:00
|
|
|
if(d < dogd.dmin) {
|
|
|
|
dogd.dmin = d;
|
|
|
|
dogd.data = data;
|
|
|
|
}
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 04:53:46 +00:00
|
|
|
void Entity::DrawAll(bool drawAsHidden) {
|
|
|
|
// This handles points as a special case, because I seem to be able
|
|
|
|
// to get a huge speedup that way, by consolidating stuff to gl.
|
2008-06-06 08:14:37 +00:00
|
|
|
int i;
|
|
|
|
if(SS.GW.showPoints) {
|
|
|
|
double s = 3.5/SS.GW.scale;
|
|
|
|
Vector r = SS.GW.projRight.ScaledBy(s);
|
|
|
|
Vector d = SS.GW.projUp.ScaledBy(s);
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglColorRGB(Style::Color(Style::DATUM));
|
|
|
|
ssglDepthRangeOffset(6);
|
2008-06-06 08:14:37 +00:00
|
|
|
glBegin(GL_QUADS);
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.entity.n; i++) {
|
|
|
|
Entity *e = &(SK.entity.elem[i]);
|
2008-06-06 08:14:37 +00:00
|
|
|
if(!e->IsPoint()) continue;
|
2009-10-29 07:16:28 +00:00
|
|
|
if(!(SK.GetGroup(e->group)->IsVisible())) continue;
|
2008-06-13 04:41:27 +00:00
|
|
|
if(e->forceHidden) continue;
|
2008-06-06 08:14:37 +00:00
|
|
|
|
|
|
|
Vector v = e->PointGetNum();
|
2009-01-04 12:01:46 +00:00
|
|
|
|
2009-09-17 07:32:36 +00:00
|
|
|
// If we're analyzing the sketch to show the degrees of freedom,
|
|
|
|
// then we draw big colored squares over the points that are
|
|
|
|
// free to move.
|
2009-01-04 12:01:46 +00:00
|
|
|
bool free = false;
|
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 == Type::POINT_IN_3D) {
|
2009-04-19 05:53:16 +00:00
|
|
|
Param *px = SK.GetParam(e->param[0]),
|
|
|
|
*py = SK.GetParam(e->param[1]),
|
|
|
|
*pz = SK.GetParam(e->param[2]);
|
2009-01-04 12:01:46 +00:00
|
|
|
|
|
|
|
free = (px->free) || (py->free) || (pz->free);
|
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
|
|
|
} else if(e->type == Type::POINT_IN_2D) {
|
2009-04-19 05:53:16 +00:00
|
|
|
Param *pu = SK.GetParam(e->param[0]),
|
|
|
|
*pv = SK.GetParam(e->param[1]);
|
2009-01-04 12:01:46 +00:00
|
|
|
|
|
|
|
free = (pu->free) || (pv->free);
|
|
|
|
}
|
|
|
|
if(free) {
|
|
|
|
Vector re = r.ScaledBy(2.5), de = d.ScaledBy(2.5);
|
|
|
|
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglColorRGB(Style::Color(Style::ANALYZE));
|
|
|
|
ssglVertex3v(v.Plus (re).Plus (de));
|
|
|
|
ssglVertex3v(v.Plus (re).Minus(de));
|
|
|
|
ssglVertex3v(v.Minus(re).Minus(de));
|
|
|
|
ssglVertex3v(v.Minus(re).Plus (de));
|
|
|
|
ssglColorRGB(Style::Color(Style::DATUM));
|
2009-01-04 12:01:46 +00:00
|
|
|
}
|
|
|
|
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglVertex3v(v.Plus (r).Plus (d));
|
|
|
|
ssglVertex3v(v.Plus (r).Minus(d));
|
|
|
|
ssglVertex3v(v.Minus(r).Minus(d));
|
|
|
|
ssglVertex3v(v.Minus(r).Plus (d));
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
glEnd();
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglDepthRangeOffset(0);
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
for(i = 0; i < SK.entity.n; i++) {
|
|
|
|
Entity *e = &(SK.entity.elem[i]);
|
2016-03-09 04:53:46 +00:00
|
|
|
if(e->IsPoint()) {
|
2008-06-06 08:14:37 +00:00
|
|
|
continue; // already handled
|
|
|
|
}
|
2016-03-09 04:53:46 +00:00
|
|
|
e->Draw(drawAsHidden);
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 04:53:46 +00:00
|
|
|
void Entity::Draw(bool drawAsHidden) {
|
2009-09-17 07:32:36 +00:00
|
|
|
hStyle hs = Style::ForEntity(h);
|
2009-09-18 08:14:15 +00:00
|
|
|
dogd.lineWidth = Style::Width(hs);
|
2016-03-09 04:53:46 +00:00
|
|
|
if(drawAsHidden) {
|
|
|
|
dogd.stippleType = Style::PatternType({ Style::HIDDEN_EDGE });
|
|
|
|
dogd.stippleScale = Style::StippleScaleMm({ Style::HIDDEN_EDGE });
|
|
|
|
} else {
|
|
|
|
dogd.stippleType = Style::PatternType(hs);
|
|
|
|
dogd.stippleScale = Style::StippleScaleMm(hs);
|
|
|
|
}
|
2015-03-22 13:39:12 +00:00
|
|
|
ssglLineWidth((float)dogd.lineWidth);
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglColorRGB(Style::Color(hs));
|
2009-09-17 07:32:36 +00:00
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
dogd.drawing = true;
|
|
|
|
DrawOrGetDistance();
|
|
|
|
}
|
|
|
|
|
2016-05-24 03:47:08 +00:00
|
|
|
void Entity::GenerateEdges(SEdgeList *el) {
|
2016-02-04 09:46:24 +00:00
|
|
|
SBezierList *sbl = GetOrGenerateBezierCurves();
|
2009-01-15 03:55:42 +00:00
|
|
|
|
|
|
|
int i, j;
|
2016-02-04 09:46:24 +00:00
|
|
|
for(i = 0; i < sbl->l.n; i++) {
|
|
|
|
SBezier *sb = &(sbl->l.elem[i]);
|
2009-01-15 03:55:42 +00:00
|
|
|
|
2015-03-27 15:31:23 +00:00
|
|
|
List<Vector> lv = {};
|
2009-01-19 03:51:00 +00:00
|
|
|
sb->MakePwlInto(&lv);
|
2009-01-15 03:55:42 +00:00
|
|
|
for(j = 1; j < lv.n; j++) {
|
2016-04-08 08:20:42 +00:00
|
|
|
el->AddEdge(lv.elem[j-1], lv.elem[j], style.v, i);
|
2009-01-15 03:55:42 +00:00
|
|
|
}
|
|
|
|
lv.Clear();
|
|
|
|
}
|
2016-02-04 09:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SBezierList *Entity::GetOrGenerateBezierCurves() {
|
|
|
|
if(beziers.l.n == 0)
|
|
|
|
GenerateBezierCurves(&beziers);
|
|
|
|
return &beziers;
|
|
|
|
}
|
|
|
|
|
|
|
|
SEdgeList *Entity::GetOrGenerateEdges() {
|
|
|
|
if(edges.l.n != 0) {
|
|
|
|
if(EXACT(edgesChordTol == SS.ChordTolMm()))
|
|
|
|
return &edges;
|
|
|
|
edges.l.Clear();
|
|
|
|
}
|
|
|
|
if(edges.l.n == 0)
|
2016-05-24 03:47:08 +00:00
|
|
|
GenerateEdges(&edges);
|
2016-02-04 09:46:24 +00:00
|
|
|
edgesChordTol = SS.ChordTolMm();
|
|
|
|
return &edges;
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
|
2016-03-05 15:09:11 +00:00
|
|
|
BBox Entity::GetOrGenerateScreenBBox(bool *hasBBox) {
|
2016-02-28 17:08:23 +00:00
|
|
|
SBezierList *sbl = GetOrGenerateBezierCurves();
|
|
|
|
|
2016-05-24 03:44:38 +00:00
|
|
|
// We don't bother with bounding boxes for workplanes, etc.
|
|
|
|
*hasBBox = (IsPoint() || IsNormal() || sbl->l.n > 0);
|
2016-02-28 17:08:23 +00:00
|
|
|
if(!*hasBBox) return {};
|
|
|
|
|
2016-03-05 15:09:11 +00:00
|
|
|
if(screenBBoxValid)
|
|
|
|
return screenBBox;
|
|
|
|
|
2016-02-28 17:08:23 +00:00
|
|
|
if(IsPoint()) {
|
|
|
|
Vector proj = SS.GW.ProjectPoint3(PointGetNum());
|
2016-03-05 15:09:11 +00:00
|
|
|
screenBBox = BBox::From(proj, proj);
|
2016-05-24 03:44:38 +00:00
|
|
|
} else if(IsNormal()) {
|
|
|
|
Vector proj = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
screenBBox = BBox::From(proj, proj);
|
2016-02-28 17:08:23 +00:00
|
|
|
} else if(sbl->l.n > 0) {
|
|
|
|
Vector first = SS.GW.ProjectPoint3(sbl->l.elem[0].ctrl[0]);
|
2016-03-05 15:09:11 +00:00
|
|
|
screenBBox = BBox::From(first, first);
|
2016-02-28 17:08:23 +00:00
|
|
|
for(int i = 0; i < sbl->l.n; i++) {
|
|
|
|
SBezier *sb = &sbl->l.elem[i];
|
|
|
|
for(int i = 0; i <= sb->deg; i++) {
|
2016-03-05 15:09:11 +00:00
|
|
|
screenBBox.Include(SS.GW.ProjectPoint3(sb->ctrl[i]));
|
2016-02-28 17:08:23 +00:00
|
|
|
}
|
|
|
|
}
|
2016-05-18 22:51:36 +00:00
|
|
|
} else ssassert(false, "Expected entity to be a point or have beziers");
|
2016-02-28 17:08:23 +00:00
|
|
|
|
2016-03-05 15:09:11 +00:00
|
|
|
screenBBoxValid = true;
|
|
|
|
return screenBBox;
|
2016-02-28 17:08:23 +00:00
|
|
|
}
|
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
double Entity::GetDistance(Point2d mp) {
|
|
|
|
dogd.drawing = false;
|
|
|
|
dogd.mp = mp;
|
|
|
|
dogd.dmin = 1e12;
|
|
|
|
|
|
|
|
DrawOrGetDistance();
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
return dogd.dmin;
|
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
Vector Entity::GetReferencePos() {
|
2016-05-24 04:14:18 +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::POINT_N_COPY:
|
|
|
|
case Type::POINT_N_TRANS:
|
|
|
|
case Type::POINT_N_ROT_TRANS:
|
|
|
|
case Type::POINT_N_ROT_AA:
|
|
|
|
case Type::POINT_IN_3D:
|
|
|
|
case Type::POINT_IN_2D:
|
2016-05-24 04:14:18 +00:00
|
|
|
return PointGetNum();
|
|
|
|
|
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::NORMAL_N_COPY:
|
|
|
|
case Type::NORMAL_N_ROT:
|
|
|
|
case Type::NORMAL_N_ROT_AA:
|
|
|
|
case Type::NORMAL_IN_3D:
|
|
|
|
case Type::NORMAL_IN_2D:
|
|
|
|
case Type::CIRCLE:
|
|
|
|
case Type::ARC_OF_CIRCLE:
|
|
|
|
case Type::CUBIC:
|
|
|
|
case Type::CUBIC_PERIODIC:
|
|
|
|
case Type::TTF_TEXT:
|
2016-05-24 04:14:18 +00:00
|
|
|
return SK.GetEntity(point[0])->PointGetNum();
|
2008-06-06 08:14:37 +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::LINE_SEGMENT: {
|
2016-05-24 04:14:18 +00:00
|
|
|
Vector a = SK.GetEntity(point[0])->PointGetNum(),
|
|
|
|
b = SK.GetEntity(point[1])->PointGetNum();
|
|
|
|
return b.Plus(a.Minus(b).ScaledBy(0.5));
|
|
|
|
}
|
2008-06-06 08:14:37 +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
|
|
|
case Type::DISTANCE:
|
|
|
|
case Type::DISTANCE_N_COPY:
|
|
|
|
case Type::FACE_NORMAL_PT:
|
|
|
|
case Type::FACE_XPROD:
|
|
|
|
case Type::FACE_N_ROT_TRANS:
|
|
|
|
case Type::FACE_N_TRANS:
|
|
|
|
case Type::FACE_N_ROT_AA:
|
|
|
|
case Type::WORKPLANE:
|
|
|
|
break;
|
2016-05-24 04:14:18 +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 entity type");
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
bool Entity::IsStylable() const {
|
2016-03-25 08:45:49 +00:00
|
|
|
if(IsPoint()) return false;
|
|
|
|
if(IsWorkplane()) return false;
|
|
|
|
if(IsNormal()) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
bool Entity::IsVisible() const {
|
2009-04-19 05:53:16 +00:00
|
|
|
Group *g = SK.GetGroup(group);
|
2008-06-06 08:14:37 +00:00
|
|
|
|
|
|
|
if(g->h.v == Group::HGROUP_REFERENCES.v && IsNormal()) {
|
|
|
|
// The reference normals are always shown
|
|
|
|
return true;
|
|
|
|
}
|
2009-10-29 07:16:28 +00:00
|
|
|
if(!(g->IsVisible())) return false;
|
2008-06-06 08:14:37 +00:00
|
|
|
|
2008-06-12 08:58:58 +00:00
|
|
|
// Don't check if points are hidden; this gets called only for
|
|
|
|
// selected or hovered points, and those should always be shown.
|
2008-06-06 08:14:37 +00:00
|
|
|
if(IsNormal() && !SS.GW.showNormals) return false;
|
|
|
|
|
2008-06-14 09:51:25 +00:00
|
|
|
if(!SS.GW.showWorkplanes) {
|
|
|
|
if(IsWorkplane() && !h.isFromRequest()) {
|
|
|
|
if(g->h.v != SS.GW.activeGroup.v) {
|
|
|
|
// The group-associated workplanes are hidden outside
|
|
|
|
// their group.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
2008-06-13 04:41:27 +00:00
|
|
|
|
2009-09-22 05:46:30 +00:00
|
|
|
if(style.v) {
|
|
|
|
Style *s = Style::Get(style);
|
|
|
|
if(!s->visible) return false;
|
|
|
|
}
|
|
|
|
|
2008-06-13 04:41:27 +00:00
|
|
|
if(forceHidden) return false;
|
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-04-20 07:30:09 +00:00
|
|
|
void Entity::CalculateNumerical(bool forExport) {
|
|
|
|
if(IsPoint()) actPoint = PointGetNum();
|
|
|
|
if(IsNormal()) actNormal = NormalGetNum();
|
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::DISTANCE || type == Type::DISTANCE_N_COPY) {
|
2009-04-20 07:30:09 +00:00
|
|
|
actDistance = DistanceGetNum();
|
|
|
|
}
|
|
|
|
if(IsFace()) {
|
|
|
|
actPoint = FaceGetPointNum();
|
|
|
|
Vector n = FaceGetNormalNum();
|
|
|
|
actNormal = Quaternion::From(0, n.x, n.y, n.z);
|
|
|
|
}
|
|
|
|
if(forExport) {
|
2016-05-07 05:27:54 +00:00
|
|
|
// Visibility in copied linked entities follows source file
|
2009-04-20 07:30:09 +00:00
|
|
|
actVisible = IsVisible();
|
|
|
|
} else {
|
|
|
|
// Copied entities within a file are always visible
|
|
|
|
actVisible = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
bool Entity::PointIsFromReferences() const {
|
2009-04-20 07:30:09 +00:00
|
|
|
return h.request().IsFromReferences();
|
|
|
|
}
|
|
|
|
|
2009-10-21 04:46:01 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Compute a cubic, second derivative continuous, interpolating spline. Same
|
|
|
|
// routine for periodic splines (in a loop) or open splines (with specified
|
|
|
|
// end tangents).
|
|
|
|
//-----------------------------------------------------------------------------
|
2016-05-21 05:18:00 +00:00
|
|
|
void Entity::ComputeInterpolatingSpline(SBezierList *sbl, bool periodic) const {
|
2009-10-21 04:46:01 +00:00
|
|
|
static const int MAX_N = BandedMatrix::MAX_UNKNOWNS;
|
|
|
|
int ep = extraPoints;
|
|
|
|
|
|
|
|
// The number of unknowns to solve for.
|
|
|
|
int n = periodic ? 3 + ep : ep;
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(n < MAX_N, "Too many unknowns");
|
2009-10-21 04:46:01 +00:00
|
|
|
// The number of on-curve points, one more than the number of segments.
|
|
|
|
int pts = periodic ? 4 + ep : 2 + ep;
|
|
|
|
|
|
|
|
int i, j, a;
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2009-10-21 04:46:01 +00:00
|
|
|
// The starting and finishing control points that define our end tangents
|
|
|
|
// (if the spline isn't periodic), and the on-curve points.
|
2013-08-26 19:36:00 +00:00
|
|
|
Vector ctrl_s = Vector::From(0, 0, 0);
|
|
|
|
Vector ctrl_f = Vector::From(0, 0, 0);
|
|
|
|
Vector pt[MAX_N+4];
|
2009-10-21 04:46:01 +00:00
|
|
|
if(periodic) {
|
|
|
|
for(i = 0; i < ep + 3; i++) {
|
|
|
|
pt[i] = SK.GetEntity(point[i])->PointGetNum();
|
|
|
|
}
|
|
|
|
pt[i++] = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
} else {
|
|
|
|
ctrl_s = SK.GetEntity(point[1])->PointGetNum();
|
|
|
|
ctrl_f = SK.GetEntity(point[ep+2])->PointGetNum();
|
|
|
|
j = 0;
|
|
|
|
pt[j++] = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
for(i = 2; i <= ep + 1; i++) {
|
|
|
|
pt[j++] = SK.GetEntity(point[i])->PointGetNum();
|
|
|
|
}
|
|
|
|
pt[j++] = SK.GetEntity(point[ep+3])->PointGetNum();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The unknowns that we will be solving for, a set for each coordinate.
|
|
|
|
double Xx[MAX_N], Xy[MAX_N], Xz[MAX_N];
|
|
|
|
// For a cubic Bezier section f(t) as t goes from 0 to 1,
|
|
|
|
// f' (0) = 3*(P1 - P0)
|
|
|
|
// f' (1) = 3*(P3 - P2)
|
|
|
|
// f''(0) = 6*(P0 - 2*P1 + P2)
|
|
|
|
// f''(1) = 6*(P3 - 2*P2 + P1)
|
|
|
|
for(a = 0; a < 3; a++) {
|
2015-03-27 15:31:23 +00:00
|
|
|
BandedMatrix bm = {};
|
2009-10-21 04:46:01 +00:00
|
|
|
bm.n = n;
|
2015-03-29 00:30:52 +00:00
|
|
|
|
2009-10-21 04:46:01 +00:00
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
int im, it, ip;
|
|
|
|
if(periodic) {
|
|
|
|
im = WRAP(i - 1, n);
|
|
|
|
it = i;
|
|
|
|
ip = WRAP(i + 1, n);
|
|
|
|
} else {
|
|
|
|
im = i;
|
|
|
|
it = i + 1;
|
|
|
|
ip = i + 2;
|
|
|
|
}
|
|
|
|
// All of these are expressed in terms of a constant part, and
|
|
|
|
// of X[i-1], X[i], and X[i+1]; so let these be the four
|
|
|
|
// components of that vector;
|
|
|
|
Vector4 A, B, C, D, E;
|
|
|
|
// The on-curve interpolated point
|
|
|
|
C = Vector4::From((pt[it]).Element(a), 0, 0, 0);
|
|
|
|
// control point one back, C - X[i]
|
|
|
|
B = C.Plus(Vector4::From(0, 0, -1, 0));
|
|
|
|
// control point one forward, C + X[i]
|
|
|
|
D = C.Plus(Vector4::From(0, 0, 1, 0));
|
|
|
|
// control point two back
|
|
|
|
if(i == 0 && !periodic) {
|
|
|
|
A = Vector4::From(ctrl_s.Element(a), 0, 0, 0);
|
|
|
|
} else {
|
|
|
|
// pt[im] + X[i-1]
|
|
|
|
A = Vector4::From(pt[im].Element(a), 1, 0, 0);
|
|
|
|
}
|
|
|
|
// control point two forward
|
|
|
|
if(i == (n - 1) && !periodic) {
|
|
|
|
E = Vector4::From(ctrl_f.Element(a), 0, 0, 0);
|
|
|
|
} else {
|
|
|
|
// pt[ip] - X[i+1]
|
|
|
|
E = Vector4::From((pt[ip]).Element(a), 0, 0, -1);
|
|
|
|
}
|
|
|
|
// Write the second derivatives of each segment, dropping constant
|
|
|
|
Vector4 fprev_pp = (C.Minus(B.ScaledBy(2))).Plus(A),
|
|
|
|
fnext_pp = (C.Minus(D.ScaledBy(2))).Plus(E),
|
|
|
|
eq = fprev_pp.Minus(fnext_pp);
|
|
|
|
|
|
|
|
bm.B[i] = -eq.w;
|
|
|
|
if(periodic) {
|
|
|
|
bm.A[i][WRAP(i-2, n)] = eq.x;
|
|
|
|
bm.A[i][WRAP(i-1, n)] = eq.y;
|
|
|
|
bm.A[i][i] = eq.z;
|
|
|
|
} else {
|
|
|
|
// The wrapping would work, except when n = 1 and everything
|
|
|
|
// wraps to zero...
|
2015-03-29 00:30:52 +00:00
|
|
|
if(i > 0) bm.A[i][i - 1] = eq.x;
|
2009-10-21 04:46:01 +00:00
|
|
|
bm.A[i][i] = eq.y;
|
|
|
|
if(i < (n-1)) bm.A[i][i + 1] = eq.z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bm.Solve();
|
|
|
|
double *X = (a == 0) ? Xx :
|
|
|
|
(a == 1) ? Xy :
|
|
|
|
Xz;
|
|
|
|
memcpy(X, bm.X, n*sizeof(double));
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i = 0; i < pts - 1; i++) {
|
|
|
|
Vector p0, p1, p2, p3;
|
|
|
|
if(periodic) {
|
|
|
|
p0 = pt[i];
|
|
|
|
int iw = WRAP(i - 1, n);
|
|
|
|
p1 = p0.Plus(Vector::From(Xx[iw], Xy[iw], Xz[iw]));
|
|
|
|
} else if(i == 0) {
|
|
|
|
p0 = pt[0];
|
|
|
|
p1 = ctrl_s;
|
|
|
|
} else {
|
|
|
|
p0 = pt[i];
|
|
|
|
p1 = p0.Plus(Vector::From(Xx[i-1], Xy[i-1], Xz[i-1]));
|
|
|
|
}
|
|
|
|
if(periodic) {
|
|
|
|
p3 = pt[i+1];
|
|
|
|
int iw = WRAP(i, n);
|
|
|
|
p2 = p3.Minus(Vector::From(Xx[iw], Xy[iw], Xz[iw]));
|
|
|
|
} else if(i == (pts - 2)) {
|
|
|
|
p3 = pt[pts-1];
|
|
|
|
p2 = ctrl_f;
|
|
|
|
} else {
|
|
|
|
p3 = pt[i+1];
|
|
|
|
p2 = p3.Minus(Vector::From(Xx[i], Xy[i], Xz[i]));
|
|
|
|
}
|
|
|
|
SBezier sb = SBezier::From(p0, p1, p2, p3);
|
|
|
|
sbl->l.Add(&sb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 05:18:00 +00:00
|
|
|
void Entity::GenerateBezierCurves(SBezierList *sbl) const {
|
2009-01-19 03:51:00 +00:00
|
|
|
SBezier sb;
|
2008-07-10 05:26:08 +00:00
|
|
|
|
2009-09-22 05:46:30 +00:00
|
|
|
int i = sbl->l.n;
|
|
|
|
|
2009-01-15 03:55:42 +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::LINE_SEGMENT: {
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector a = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
Vector b = SK.GetEntity(point[1])->PointGetNum();
|
2009-01-19 03:51:00 +00:00
|
|
|
sb = SBezier::From(a, b);
|
2015-10-31 08:22:26 +00:00
|
|
|
sb.entity = h.v;
|
2009-01-19 03:51:00 +00:00
|
|
|
sbl->l.Add(&sb);
|
2009-01-15 03:55:42 +00:00
|
|
|
break;
|
|
|
|
}
|
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:
|
2016-05-25 12:08:19 +00:00
|
|
|
ComputeInterpolatingSpline(sbl, /*periodic=*/false);
|
2009-10-21 04:46:01 +00:00
|
|
|
break;
|
|
|
|
|
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_PERIODIC:
|
2016-05-25 12:08:19 +00:00
|
|
|
ComputeInterpolatingSpline(sbl, /*periodic=*/true);
|
2009-01-15 03:55:42 +00:00
|
|
|
break;
|
2008-07-10 05:26:08 +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::CIRCLE:
|
|
|
|
case Type::ARC_OF_CIRCLE: {
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector center = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
Quaternion q = SK.GetEntity(normal)->NormalGetNum();
|
2009-01-15 03:55:42 +00:00
|
|
|
Vector u = q.RotationU(), v = q.RotationV();
|
|
|
|
double r = CircleGetRadiusNum();
|
|
|
|
double thetaa, thetab, dtheta;
|
|
|
|
|
2009-01-19 03:33:15 +00:00
|
|
|
if(r < LENGTH_EPS) {
|
|
|
|
// If a circle or an arc gets dragged through zero radius,
|
|
|
|
// then we just don't generate anything.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
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::CIRCLE) {
|
2009-01-15 03:55:42 +00:00
|
|
|
thetaa = 0;
|
|
|
|
thetab = 2*PI;
|
|
|
|
dtheta = 2*PI;
|
|
|
|
} else {
|
|
|
|
ArcGetAngles(&thetaa, &thetab, &dtheta);
|
|
|
|
}
|
|
|
|
int i, n;
|
2009-06-21 09:02:36 +00:00
|
|
|
if(dtheta > (3*PI/2 + 0.01)) {
|
2009-01-15 03:55:42 +00:00
|
|
|
n = 4;
|
2009-06-21 09:02:36 +00:00
|
|
|
} else if(dtheta > (PI + 0.01)) {
|
2009-01-15 03:55:42 +00:00
|
|
|
n = 3;
|
2009-06-21 09:02:36 +00:00
|
|
|
} else if(dtheta > (PI/2 + 0.01)) {
|
2009-01-15 03:55:42 +00:00
|
|
|
n = 2;
|
|
|
|
} else {
|
|
|
|
n = 1;
|
|
|
|
}
|
|
|
|
dtheta /= n;
|
2008-07-10 05:26:08 +00:00
|
|
|
|
2009-01-15 03:55:42 +00:00
|
|
|
for(i = 0; i < n; i++) {
|
|
|
|
double s, c;
|
2008-07-10 05:26:08 +00:00
|
|
|
|
2009-01-15 03:55:42 +00:00
|
|
|
c = cos(thetaa);
|
|
|
|
s = sin(thetaa);
|
|
|
|
// The start point of the curve, and the tangent vector at
|
|
|
|
// that start point.
|
|
|
|
Vector p0 = center.Plus(u.ScaledBy( r*c)).Plus(v.ScaledBy(r*s)),
|
|
|
|
t0 = u.ScaledBy(-r*s). Plus(v.ScaledBy(r*c));
|
2008-07-10 05:26:08 +00:00
|
|
|
|
2009-01-15 03:55:42 +00:00
|
|
|
thetaa += dtheta;
|
2008-07-10 05:26:08 +00:00
|
|
|
|
2009-01-15 03:55:42 +00:00
|
|
|
c = cos(thetaa);
|
|
|
|
s = sin(thetaa);
|
|
|
|
Vector p2 = center.Plus(u.ScaledBy( r*c)).Plus(v.ScaledBy(r*s)),
|
|
|
|
t2 = u.ScaledBy(-r*s). Plus(v.ScaledBy(r*c));
|
|
|
|
|
|
|
|
// The control point must lie on both tangents.
|
|
|
|
Vector p1 = Vector::AtIntersectionOfLines(p0, p0.Plus(t0),
|
|
|
|
p2, p2.Plus(t2),
|
|
|
|
NULL);
|
|
|
|
|
2009-01-19 03:51:00 +00:00
|
|
|
SBezier sb = SBezier::From(p0, p1, p2);
|
|
|
|
sb.weight[1] = cos(dtheta/2);
|
|
|
|
sbl->l.Add(&sb);
|
2009-01-15 03:55:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2015-03-29 00:30: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::TTF_TEXT: {
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector topLeft = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
Vector botLeft = SK.GetEntity(point[1])->PointGetNum();
|
2009-01-15 03:55:42 +00:00
|
|
|
Vector n = Normal()->NormalN();
|
|
|
|
Vector v = topLeft.Minus(botLeft);
|
|
|
|
Vector u = (v.Cross(n)).WithMagnitude(v.Magnitude());
|
|
|
|
|
2016-02-14 20:13:40 +00:00
|
|
|
SS.fonts.PlotString(font, str, sbl, botLeft, u, v);
|
2009-01-15 03:55:42 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Not a problem, points and normals and such don't generate curves
|
|
|
|
break;
|
2008-07-10 05:26:08 +00:00
|
|
|
}
|
2009-09-22 05:46:30 +00:00
|
|
|
|
|
|
|
// Record our style for all of the Beziers that we just created.
|
|
|
|
for(; i < sbl->l.n; i++) {
|
|
|
|
sbl->l.elem[i].auxA = style.v;
|
|
|
|
}
|
2008-07-10 05:26:08 +00:00
|
|
|
}
|
|
|
|
|
2016-05-05 05:54:05 +00:00
|
|
|
void Entity::DrawOrGetDistance() {
|
2016-02-28 17:08:23 +00:00
|
|
|
// If we're about to perform hit testing on an entity, consider
|
|
|
|
// whether the pointer is inside its bounding box first.
|
2016-05-24 03:44:38 +00:00
|
|
|
if(!dogd.drawing && !IsNormal()) {
|
2016-02-28 17:08:23 +00:00
|
|
|
bool hasBBox;
|
2016-03-05 15:09:11 +00:00
|
|
|
BBox box = GetOrGenerateScreenBBox(&hasBBox);
|
2016-05-24 03:44:38 +00:00
|
|
|
if(hasBBox && !box.Contains(dogd.mp, SELECTION_RADIUS))
|
2016-02-28 17:08:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-15 03:55:42 +00:00
|
|
|
if(!IsVisible()) return;
|
2008-06-06 08:14:37 +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::POINT_N_COPY:
|
|
|
|
case Type::POINT_N_TRANS:
|
|
|
|
case Type::POINT_N_ROT_TRANS:
|
|
|
|
case Type::POINT_N_ROT_AA:
|
|
|
|
case Type::POINT_IN_3D:
|
|
|
|
case Type::POINT_IN_2D: {
|
2008-06-06 08:14:37 +00:00
|
|
|
Vector v = PointGetNum();
|
|
|
|
|
|
|
|
if(dogd.drawing) {
|
|
|
|
double s = 3.5;
|
|
|
|
Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale);
|
|
|
|
Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale);
|
|
|
|
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglColorRGB(Style::Color(Style::DATUM));
|
|
|
|
ssglDepthRangeOffset(6);
|
2008-06-06 08:14:37 +00:00
|
|
|
glBegin(GL_QUADS);
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglVertex3v(v.Plus (r).Plus (d));
|
|
|
|
ssglVertex3v(v.Plus (r).Minus(d));
|
|
|
|
ssglVertex3v(v.Minus(r).Minus(d));
|
|
|
|
ssglVertex3v(v.Minus(r).Plus (d));
|
2008-06-06 08:14:37 +00:00
|
|
|
glEnd();
|
2013-10-22 04:45:06 +00:00
|
|
|
ssglDepthRangeOffset(0);
|
2008-06-06 08:14:37 +00:00
|
|
|
} else {
|
|
|
|
Point2d pp = SS.GW.ProjectPoint(v);
|
2008-06-11 04:22:52 +00:00
|
|
|
dogd.dmin = pp.DistanceTo(dogd.mp) - 6;
|
2008-06-06 08:14:37 +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;
|
2008-06-06 08:14:37 +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::NORMAL_N_COPY:
|
|
|
|
case Type::NORMAL_N_ROT:
|
|
|
|
case Type::NORMAL_N_ROT_AA:
|
|
|
|
case Type::NORMAL_IN_3D:
|
|
|
|
case Type::NORMAL_IN_2D: {
|
2008-06-06 08:14:37 +00:00
|
|
|
int i;
|
|
|
|
for(i = 0; i < 2; i++) {
|
2009-06-07 23:00:57 +00:00
|
|
|
if(i == 0 && !SS.GW.showNormals) {
|
|
|
|
// When the normals are hidden, we will continue to show
|
|
|
|
// the coordinate axes at the bottom left corner, but
|
|
|
|
// not at the origin.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
hRequest hr = h.request();
|
2009-09-17 07:32:36 +00:00
|
|
|
// Always draw the x, y, and z axes in red, green, and blue;
|
|
|
|
// brighter for the ones at the bottom left of the screen,
|
|
|
|
// dimmer for the ones at the model origin.
|
|
|
|
int f = (i == 0 ? 100 : 255);
|
2008-06-06 08:14:37 +00:00
|
|
|
if(hr.v == Request::HREQUEST_REFERENCE_XY.v) {
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglColorRGB(RGBi(0, 0, f));
|
2008-06-06 08:14:37 +00:00
|
|
|
} else if(hr.v == Request::HREQUEST_REFERENCE_YZ.v) {
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglColorRGB(RGBi(f, 0, 0));
|
2008-06-06 08:14:37 +00:00
|
|
|
} else if(hr.v == Request::HREQUEST_REFERENCE_ZX.v) {
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglColorRGB(RGBi(0, f, 0));
|
2008-06-06 08:14:37 +00:00
|
|
|
} else {
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglColorRGB(Style::Color(Style::NORMALS));
|
2008-06-06 08:14:37 +00:00
|
|
|
if(i > 0) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Quaternion q = NormalGetNum();
|
|
|
|
Vector tail;
|
|
|
|
if(i == 0) {
|
2009-04-19 05:53:16 +00:00
|
|
|
tail = SK.GetEntity(point[0])->PointGetNum();
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglLineWidth(1);
|
2008-06-06 08:14:37 +00:00
|
|
|
} else {
|
|
|
|
// Draw an extra copy of the x, y, and z axes, that's
|
|
|
|
// always in the corner of the view and at the front.
|
|
|
|
// So those are always available, perhaps useful.
|
|
|
|
double s = SS.GW.scale;
|
|
|
|
double h = 60 - SS.GW.height/2;
|
|
|
|
double w = 60 - SS.GW.width/2;
|
|
|
|
tail = SS.GW.projRight.ScaledBy(w/s).Plus(
|
2008-06-17 19:12:25 +00:00
|
|
|
SS.GW.projUp. ScaledBy(h/s)).Minus(SS.GW.offset);
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing) {
|
|
|
|
ssglDepthRangeLockToFront(true);
|
|
|
|
ssglLineWidth(2);
|
|
|
|
}
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Vector v = (q.RotationN()).WithMagnitude(50/SS.GW.scale);
|
|
|
|
Vector tip = tail.Plus(v);
|
|
|
|
LineDrawOrGetDistance(tail, tip);
|
|
|
|
|
|
|
|
v = v.WithMagnitude(12/SS.GW.scale);
|
|
|
|
Vector axis = q.RotationV();
|
|
|
|
LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis, 0.6)));
|
|
|
|
LineDrawOrGetDistance(tip,tip.Minus(v.RotatedAbout(axis,-0.6)));
|
|
|
|
}
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing)
|
|
|
|
ssglDepthRangeLockToFront(false);
|
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;
|
2008-06-06 08:14:37 +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::DISTANCE:
|
|
|
|
case Type::DISTANCE_N_COPY:
|
2008-06-06 08:14:37 +00:00
|
|
|
// These are used only as data structures, nothing to display.
|
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;
|
2008-06-06 08:14:37 +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::WORKPLANE: {
|
2008-06-06 08:14:37 +00:00
|
|
|
Vector p;
|
2009-04-19 05:53:16 +00:00
|
|
|
p = SK.GetEntity(point[0])->PointGetNum();
|
2008-06-06 08:14:37 +00:00
|
|
|
|
|
|
|
Vector u = Normal()->NormalU();
|
|
|
|
Vector v = Normal()->NormalV();
|
|
|
|
|
|
|
|
double s = (min(SS.GW.width, SS.GW.height))*0.45/SS.GW.scale;
|
|
|
|
|
|
|
|
Vector us = u.ScaledBy(s);
|
|
|
|
Vector vs = v.ScaledBy(s);
|
|
|
|
|
|
|
|
Vector pp = p.Plus (us).Plus (vs);
|
|
|
|
Vector pm = p.Plus (us).Minus(vs);
|
|
|
|
Vector mm = p.Minus(us).Minus(vs), mm2 = mm;
|
|
|
|
Vector mp = p.Minus(us).Plus (vs);
|
|
|
|
|
2015-03-26 00:34:28 +00:00
|
|
|
if(dogd.drawing) {
|
|
|
|
ssglLineWidth(1);
|
|
|
|
ssglColorRGB(Style::Color(Style::NORMALS));
|
|
|
|
glEnable(GL_LINE_STIPPLE);
|
|
|
|
glLineStipple(3, 0x1111);
|
|
|
|
}
|
|
|
|
|
2008-06-06 08:14:37 +00:00
|
|
|
if(!h.isFromRequest()) {
|
2016-04-24 22:38:02 +00:00
|
|
|
mm = mm.Plus(v.ScaledBy(70/SS.GW.scale));
|
|
|
|
mm2 = mm2.Plus(u.ScaledBy(70/SS.GW.scale));
|
2008-06-06 08:14:37 +00:00
|
|
|
LineDrawOrGetDistance(mm2, mm);
|
|
|
|
}
|
|
|
|
LineDrawOrGetDistance(pp, pm);
|
|
|
|
LineDrawOrGetDistance(pm, mm2);
|
2016-03-25 08:13:01 +00:00
|
|
|
LineDrawOrGetDistance(mp, mm);
|
|
|
|
LineDrawOrGetDistance(pp, mp);
|
2015-03-26 00:34:28 +00:00
|
|
|
|
|
|
|
if(dogd.drawing)
|
|
|
|
glDisable(GL_LINE_STIPPLE);
|
2008-06-06 08:14:37 +00:00
|
|
|
|
2015-11-06 08:40:12 +00:00
|
|
|
std::string str = DescriptionString().substr(5);
|
2016-03-02 17:15:28 +00:00
|
|
|
double th = Style::DefaultTextHeight();
|
2008-06-06 08:14:37 +00:00
|
|
|
if(dogd.drawing) {
|
2016-04-24 22:38:02 +00:00
|
|
|
Vector o = mm2.Plus(u.ScaledBy(3/SS.GW.scale)).Plus(
|
|
|
|
v.ScaledBy(3/SS.GW.scale));
|
|
|
|
ssglWriteText(str, th, o, u, v, NULL, NULL);
|
2008-06-06 08:14:37 +00:00
|
|
|
} else {
|
2016-02-05 09:28:29 +00:00
|
|
|
Vector pos = mm2.Plus(u.ScaledBy(ssglStrWidth(str, th)/2)).Plus(
|
2016-04-12 13:38:09 +00:00
|
|
|
v.ScaledBy(ssglStrCapHeight(th)/2));
|
2008-06-06 08:14:37 +00:00
|
|
|
Point2d pp = SS.GW.ProjectPoint(pos);
|
|
|
|
dogd.dmin = min(dogd.dmin, pp.DistanceTo(dogd.mp) - 10);
|
|
|
|
// If a line lies in a plane, then select the line, not
|
|
|
|
// the plane.
|
|
|
|
dogd.dmin += 3;
|
|
|
|
}
|
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;
|
2008-06-06 08:14:37 +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::LINE_SEGMENT:
|
|
|
|
case Type::CIRCLE:
|
|
|
|
case Type::ARC_OF_CIRCLE:
|
|
|
|
case Type::CUBIC:
|
|
|
|
case Type::CUBIC_PERIODIC:
|
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
|
|
|
case Type::TTF_TEXT: {
|
|
|
|
// Nothing but the curves; generate the rational polynomial curves for
|
|
|
|
// everything, then piecewise linearize them, and display those.
|
|
|
|
SEdgeList *sel = GetOrGenerateEdges();
|
|
|
|
dogd.data = -1;
|
|
|
|
for(int i = 0; i < sel->l.n; i++) {
|
|
|
|
SEdge *se = &(sel->l.elem[i]);
|
2016-05-25 12:08:19 +00:00
|
|
|
LineDrawOrGetDistance(se->a, se->b, /*maybeFat=*/true, se->auxB);
|
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;
|
|
|
|
}
|
2008-06-30 09:09:17 +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::FACE_NORMAL_PT:
|
|
|
|
case Type::FACE_XPROD:
|
|
|
|
case Type::FACE_N_ROT_TRANS:
|
|
|
|
case Type::FACE_N_TRANS:
|
|
|
|
case Type::FACE_N_ROT_AA:
|
2008-06-06 08:14:37 +00:00
|
|
|
// Do nothing; these are drawn with the triangle mesh
|
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-15 03:55:42 +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 entity type");
|
2008-06-06 08:14:37 +00:00
|
|
|
}
|
|
|
|
|