2016-04-13 08:43:06 +00:00
|
|
|
#include "solvespace.h"
|
|
|
|
#include "libdxfrw.h"
|
2016-05-07 05:17:23 +00:00
|
|
|
#include "libdwgr.h"
|
2016-04-13 08:43:06 +00:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
// Conflicts with DRW::TEXT.
|
|
|
|
# undef TEXT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace SolveSpace {
|
|
|
|
|
|
|
|
static std::string ToUpper(std::string str) {
|
|
|
|
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
class DxfReadInterface : public DRW_Interface {
|
|
|
|
public:
|
|
|
|
Vector blockX;
|
|
|
|
Vector blockY;
|
|
|
|
Vector blockT;
|
|
|
|
|
|
|
|
void invertXTransform() {
|
|
|
|
blockX.x = -blockX.x;
|
|
|
|
blockY.x = -blockY.x;
|
|
|
|
blockT.x = -blockT.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
void multBlockTransform(double x, double y, double sx, double sy, double angle) {
|
|
|
|
Vector oldX = blockX;
|
|
|
|
Vector oldY = blockY;
|
|
|
|
Vector oldT = blockT;
|
|
|
|
|
|
|
|
Vector newX = Vector::From(sx, 0.0, 0.0).RotatedAbout(Vector::From(0.0, 0.0, 1.0), angle);
|
|
|
|
Vector newY = Vector::From(0.0, sy, 0.0).RotatedAbout(Vector::From(0.0, 0.0, 1.0), angle);
|
|
|
|
Vector newT = Vector::From(x, y, 0.0);
|
|
|
|
|
|
|
|
blockX = oldX.ScaledBy(newX.x).Plus(
|
|
|
|
oldY.ScaledBy(newX.y));
|
|
|
|
|
|
|
|
blockY = oldX.ScaledBy(newY.x).Plus(
|
|
|
|
oldY.ScaledBy(newY.y));
|
|
|
|
|
|
|
|
blockT = oldX.ScaledBy(newT.x).Plus(
|
|
|
|
oldY.ScaledBy(newT.y)).Plus(oldT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clearBlockTransform() {
|
|
|
|
blockX = Vector::From(1.0, 0.0, 0.0);
|
|
|
|
blockY = Vector::From(0.0, 1.0, 0.0);
|
|
|
|
blockT = Vector::From(0.0, 0.0, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector blockTransform(Vector v) {
|
|
|
|
Vector r = blockT;
|
|
|
|
r = r.Plus(blockX.ScaledBy(v.x));
|
|
|
|
r = r.Plus(blockY.ScaledBy(v.y));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void blockTransformArc(Vector *c, Vector *p0, Vector *p1) {
|
|
|
|
bool oldSign = p0->Minus(*c).Cross(p1->Minus(*c)).z > 0.0;
|
|
|
|
|
|
|
|
*c = blockTransform(*c);
|
|
|
|
*p0 = blockTransform(*p0);
|
|
|
|
*p1 = blockTransform(*p1);
|
|
|
|
|
|
|
|
bool newSign = p0->Minus(*c).Cross(p1->Minus(*c)).z > 0.0;
|
|
|
|
if(oldSign != newSign) std::swap(*p0, *p1);
|
|
|
|
}
|
|
|
|
|
2016-04-26 00:47:02 +00:00
|
|
|
Vector toVector(const DRW_Coord &c, bool transform = true) {
|
2016-04-13 08:43:06 +00:00
|
|
|
Vector result = Vector::From(c.x, c.y, 0.0);
|
2016-04-26 00:47:02 +00:00
|
|
|
if(transform) return blockTransform(result);
|
|
|
|
return result;
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Vector toVector(const DRW_Vertex2D &c) {
|
|
|
|
Vector result = Vector::From(c.x, c.y, 0.0);
|
|
|
|
return blockTransform(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector toVector(const DRW_Vertex &c) {
|
|
|
|
Vector result = Vector::From(c.basePoint.x, c.basePoint.y, 0.0);
|
|
|
|
return blockTransform(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
double angleTo(Vector v0, Vector v1) {
|
|
|
|
Vector d = v1.Minus(v0);
|
|
|
|
double a = atan2(d.y, d.x);
|
|
|
|
return M_PI + remainder(a - M_PI, 2 * M_PI);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector polar(double radius, double angle) {
|
|
|
|
return Vector::From(radius * cos(angle), radius * sin(angle), 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
hRequest createBulge(Vector p0, Vector p1, double bulge) {
|
|
|
|
bool reversed = bulge < 0.0;
|
|
|
|
double alpha = atan(bulge) * 4.0;
|
|
|
|
|
|
|
|
Vector middle = p1.Plus(p0).ScaledBy(0.5);
|
|
|
|
double dist = p1.Minus(p0).Magnitude() / 2.0;
|
|
|
|
double angle = angleTo(p0, p1);
|
|
|
|
|
|
|
|
// alpha can't be 0.0 at this point
|
|
|
|
double radius = fabs(dist / sin(alpha / 2.0));
|
|
|
|
double wu = fabs(radius * radius - dist * dist);
|
|
|
|
double h = sqrt(wu);
|
|
|
|
|
|
|
|
if(bulge > 0.0) {
|
|
|
|
angle += M_PI_2;
|
|
|
|
} else {
|
|
|
|
angle -= M_PI_2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fabs(alpha) > M_PI) {
|
|
|
|
h *= -1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector center = polar(h, angle);
|
|
|
|
center = center.Plus(middle);
|
|
|
|
|
|
|
|
if(reversed) std::swap(p0, p1);
|
|
|
|
blockTransformArc(¢er, &p0, &p1);
|
|
|
|
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, false);
|
2016-04-13 08:43:06 +00:00
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(center);
|
|
|
|
SK.GetEntity(hr.entity(2))->PointForceTo(p0);
|
|
|
|
SK.GetEntity(hr.entity(3))->PointForceTo(p1);
|
2016-04-26 00:47:02 +00:00
|
|
|
processPoint(hr.entity(1));
|
|
|
|
processPoint(hr.entity(2));
|
|
|
|
processPoint(hr.entity(3));
|
2016-04-13 08:43:06 +00:00
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Block {
|
|
|
|
std::vector<std::unique_ptr<DRW_Entity>> entities;
|
|
|
|
DRW_Block data;
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned unknownEntities = 0;
|
|
|
|
std::map<std::string, hStyle> styles;
|
|
|
|
std::map<std::string, Block> blocks;
|
|
|
|
std::map<std::string, DRW_Layer> layers;
|
|
|
|
Block *readBlock = NULL;
|
|
|
|
const DRW_Insert *insertInsert = NULL;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
bool addPendingBlockEntity(const T &e) {
|
|
|
|
if(readBlock == NULL) return false;
|
|
|
|
readBlock->entities.emplace_back(new T(e));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void addEntity(DRW_Entity *e) {
|
|
|
|
switch(e->eType) {
|
|
|
|
case DRW::POINT:
|
|
|
|
addPoint(*static_cast<DRW_Point *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::LINE:
|
|
|
|
addLine(*static_cast<DRW_Line *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::ARC:
|
|
|
|
addArc(*static_cast<DRW_Arc *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::CIRCLE:
|
|
|
|
addCircle(*static_cast<DRW_Circle *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::POLYLINE:
|
|
|
|
addPolyline(*static_cast<DRW_Polyline *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::LWPOLYLINE:
|
|
|
|
addLWPolyline(*static_cast<DRW_LWPolyline *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::SPLINE:
|
|
|
|
addSpline(static_cast<DRW_Spline *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::INSERT:
|
|
|
|
addInsert(*static_cast<DRW_Insert *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::TEXT:
|
|
|
|
addText(*static_cast<DRW_Text *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::MTEXT:
|
|
|
|
addMText(*static_cast<DRW_MText *>(e));
|
|
|
|
break;
|
2016-04-26 00:47:02 +00:00
|
|
|
case DRW::DIMALIGNED:
|
|
|
|
addDimAlign(static_cast<DRW_DimAligned *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::DIMLINEAR:
|
|
|
|
addDimLinear(static_cast<DRW_DimLinear *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::DIMRADIAL:
|
|
|
|
addDimRadial(static_cast<DRW_DimRadial *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::DIMDIAMETRIC:
|
|
|
|
addDimDiametric(static_cast<DRW_DimDiametric *>(e));
|
|
|
|
break;
|
|
|
|
case DRW::DIMANGULAR:
|
|
|
|
addDimAngular(static_cast<DRW_DimAngular *>(e));
|
|
|
|
break;
|
2016-04-13 08:43:06 +00:00
|
|
|
default:
|
|
|
|
unknownEntities++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
Style::TextOrigin dxfAlignToOrigin(DRW_Text::HAlign alignH, DRW_Text::VAlign alignV) {
|
|
|
|
uint32_t origin = 0;
|
2016-04-13 08:43:06 +00:00
|
|
|
switch(alignH) {
|
|
|
|
case DRW_Text::HLeft:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::LEFT;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DRW_Text::HMiddle:
|
|
|
|
case DRW_Text::HCenter:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRW_Text::HRight:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::RIGHT;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DRW_Text::HAligned:
|
|
|
|
case DRW_Text::HFit:
|
|
|
|
default:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::LEFT;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(alignV) {
|
|
|
|
case DRW_Text::VBaseLine:
|
|
|
|
case DRW_Text::VBottom:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::BOT;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DRW_Text::VMiddle:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRW_Text::VTop:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::TOP;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
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
|
|
|
origin |= (uint32_t)Style::TextOrigin::BOT;
|
2016-04-13 08:43:06 +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
|
|
|
return (Style::TextOrigin)origin;
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DRW_Layer *getSourceLayer(const DRW_Entity *e) {
|
|
|
|
DRW_Layer *layer = NULL;
|
|
|
|
if(insertInsert != NULL) {
|
|
|
|
std::string l = insertInsert->layer;
|
|
|
|
auto bi = layers.find(l);
|
|
|
|
if(bi != layers.end()) layer = &bi->second;
|
|
|
|
} else {
|
|
|
|
std::string l = e->layer;
|
|
|
|
auto bi = layers.find(l);
|
|
|
|
if(bi != layers.end()) layer = &bi->second;
|
|
|
|
}
|
|
|
|
return layer;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getColor(const DRW_Entity *e) {
|
|
|
|
int col = e->color;
|
|
|
|
if(col == DRW::ColorByBlock) {
|
|
|
|
if(insertInsert != NULL) {
|
|
|
|
col = insertInsert->color;
|
|
|
|
} else {
|
|
|
|
col = 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(col == DRW::ColorByLayer) {
|
|
|
|
DRW_Layer *layer = getSourceLayer(e);
|
|
|
|
if(layer != NULL) {
|
|
|
|
col = layer->color;
|
|
|
|
} else {
|
|
|
|
col = 7;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
|
|
|
|
DRW_LW_Conv::lineWidth getLineWidth(const DRW_Entity *e) {
|
|
|
|
DRW_LW_Conv::lineWidth result = e->lWeight;
|
|
|
|
if(result == DRW_LW_Conv::widthByBlock) {
|
|
|
|
if(insertInsert != NULL) {
|
|
|
|
result = insertInsert->lWeight;
|
|
|
|
} else {
|
|
|
|
result = DRW_LW_Conv::widthDefault;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(result == DRW_LW_Conv::widthByLayer) {
|
|
|
|
DRW_Layer *layer = getSourceLayer(e);
|
|
|
|
if(layer != NULL) {
|
|
|
|
result = layer->lWeight;
|
|
|
|
} else {
|
|
|
|
result = DRW_LW_Conv::widthDefault;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string getLineType(const DRW_Entity *e) {
|
|
|
|
std::string result = e->lineType;
|
|
|
|
if(result == "BYBLOCK") {
|
|
|
|
if(insertInsert != NULL) {
|
|
|
|
result = ToUpper(insertInsert->lineType);
|
|
|
|
} else {
|
|
|
|
result = "CONTINUOUS";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(result == "BYLAYER") {
|
|
|
|
DRW_Layer *layer = getSourceLayer(e);
|
|
|
|
if(layer != NULL) {
|
|
|
|
result = ToUpper(layer->lineType);
|
|
|
|
} else {
|
|
|
|
result = "CONTINUOUS";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-04-26 00:47:02 +00:00
|
|
|
hStyle invisibleStyle() {
|
|
|
|
std::string id = "@dxf-invisible";
|
|
|
|
|
|
|
|
auto si = styles.find(id);
|
|
|
|
if(si != styles.end()) {
|
|
|
|
return si->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
hStyle hs = { Style::CreateCustomStyle(/*rememberForUndo=*/false) };
|
|
|
|
Style *s = Style::Get(hs);
|
|
|
|
s->name = id;
|
|
|
|
s->visible = false;
|
|
|
|
|
|
|
|
styles.emplace(id, hs);
|
|
|
|
return hs;
|
|
|
|
}
|
|
|
|
|
2016-04-13 08:43:06 +00:00
|
|
|
hStyle styleFor(const DRW_Entity *e) {
|
|
|
|
// Color.
|
|
|
|
// TODO: which color to choose: index or RGB one?
|
|
|
|
int col = getColor(e);
|
|
|
|
RgbaColor c = RgbaColor::From(DRW::dxfColors[col][0],
|
|
|
|
DRW::dxfColors[col][1],
|
|
|
|
DRW::dxfColors[col][2]);
|
|
|
|
|
|
|
|
// Line width.
|
|
|
|
DRW_LW_Conv::lineWidth lw = getLineWidth(e);
|
|
|
|
double width = DRW_LW_Conv::lineWidth2dxfInt(e->lWeight) / 100.0;
|
|
|
|
if(width < 0.0) width = 1.0;
|
|
|
|
|
|
|
|
// Line stipple.
|
|
|
|
// TODO: Probably, we can load default autocad patterns and match it with ours.
|
|
|
|
std::string lineType = getLineType(e);
|
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
|
|
|
StipplePattern stipple = StipplePattern::CONTINUOUS;
|
|
|
|
for(uint32_t i = 0; i <= (uint32_t)StipplePattern::LAST; i++) {
|
|
|
|
StipplePattern st = (StipplePattern)i;
|
|
|
|
if(lineType == DxfFileWriter::lineTypeName(st)) {
|
|
|
|
stipple = st;
|
2016-04-13 08:43:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Text properties.
|
|
|
|
DRW_Text::HAlign alignH = DRW_Text::HLeft;
|
|
|
|
DRW_Text::VAlign alignV = DRW_Text::VBaseLine;
|
|
|
|
double textAngle = 0.0;
|
|
|
|
double textHeight = Style::DefaultTextHeight();
|
|
|
|
|
|
|
|
if(e->eType == DRW::TEXT || e->eType == DRW::MTEXT) {
|
|
|
|
const DRW_Text *text = static_cast<const DRW_Text *>(e);
|
|
|
|
alignH = text->alignH;
|
|
|
|
alignV = text->alignV;
|
|
|
|
textHeight = text->height;
|
|
|
|
textAngle = text->angle;
|
|
|
|
// I have no idea why, but works
|
|
|
|
if(alignH == DRW_Text::HMiddle) {
|
|
|
|
alignV = DRW_Text::VMiddle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unique identifier based on style properties.
|
|
|
|
std::string id = "@dxf";
|
|
|
|
if(lw != DRW_LW_Conv::widthDefault)
|
|
|
|
id += ssprintf("-w%.4g", width);
|
|
|
|
if(lineType != "CONTINUOUS")
|
|
|
|
id += ssprintf("-%s", lineType.c_str());
|
|
|
|
if(c.red != 0 || c.green != 0 || c.blue != 0)
|
|
|
|
id += ssprintf("-#%02x%02x%02x", c.red, c.green, c.blue);
|
|
|
|
if(textHeight != Style::DefaultTextHeight())
|
|
|
|
id += ssprintf("-h%.4g", textHeight);
|
|
|
|
if(textAngle != 0.0)
|
|
|
|
id += ssprintf("-a%.5g", textAngle);
|
|
|
|
if(alignH != DRW_Text::HLeft)
|
|
|
|
id += ssprintf("-oh%d", alignH);
|
|
|
|
if(alignV != DRW_Text::VBaseLine)
|
|
|
|
id += ssprintf("-ov%d", alignV);
|
|
|
|
|
|
|
|
auto si = styles.find(id);
|
|
|
|
if(si != styles.end()) {
|
|
|
|
return si->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
hStyle hs = { Style::CreateCustomStyle(/*rememberForUndo=*/false) };
|
|
|
|
Style *s = Style::Get(hs);
|
|
|
|
if(lw != DRW_LW_Conv::widthDefault) {
|
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
|
|
|
s->widthAs = Style::UnitsAs::MM;
|
2016-04-13 08:43:06 +00:00
|
|
|
s->width = width;
|
|
|
|
s->stippleScale = 1.0 + width * 2.0;
|
|
|
|
}
|
|
|
|
s->name = id;
|
|
|
|
s->stippleType = stipple;
|
|
|
|
if(c.red != 0 || c.green != 0 || c.blue != 0) s->color = c;
|
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
|
|
|
s->textHeightAs = Style::UnitsAs::MM;
|
2016-04-13 08:43:06 +00:00
|
|
|
s->textHeight = textHeight;
|
|
|
|
s->textAngle = textAngle;
|
|
|
|
s->textOrigin = dxfAlignToOrigin(alignH, alignV);
|
|
|
|
|
|
|
|
styles.emplace(id, hs);
|
|
|
|
return hs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setStyle(hRequest hr, hStyle hs) {
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
r->style = hs;
|
|
|
|
}
|
|
|
|
|
2016-04-26 00:47:02 +00:00
|
|
|
struct VectorHash {
|
|
|
|
size_t operator()(const Vector &v) const {
|
|
|
|
static const size_t size = std::numeric_limits<size_t>::max() / 2 - 1;
|
|
|
|
static const double eps = (4.0 * LENGTH_EPS);
|
|
|
|
|
|
|
|
double x = fabs(v.x) / eps;
|
|
|
|
double y = fabs(v.y) / eps;
|
|
|
|
|
|
|
|
size_t xs = size_t(fmod(x, double(size)));
|
|
|
|
size_t ys = size_t(fmod(y, double(size)));
|
|
|
|
|
|
|
|
return ys * size + xs;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VectorPred {
|
|
|
|
bool operator()(Vector a, Vector b) const {
|
|
|
|
return a.Equals(b, LENGTH_EPS);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::unordered_map<Vector, hEntity, VectorHash, VectorPred> points;
|
|
|
|
|
|
|
|
void processPoint(hEntity he, bool constrain = true) {
|
|
|
|
Entity *e = SK.GetEntity(he);
|
|
|
|
Vector pos = e->PointGetNum();
|
|
|
|
hEntity p = findPoint(pos);
|
|
|
|
if(p.v == he.v) return;
|
|
|
|
if(p.v != Entity::NO_ENTITY.v) {
|
|
|
|
if(constrain) {
|
|
|
|
Constraint::ConstrainCoincident(he, p);
|
|
|
|
}
|
|
|
|
// We don't add point because we already
|
|
|
|
// have point in this position
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
points.emplace(pos, he);
|
|
|
|
}
|
|
|
|
|
|
|
|
hEntity findPoint(const Vector &p) {
|
|
|
|
auto it = points.find(p);
|
|
|
|
if(it == points.end()) return Entity::NO_ENTITY;
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
hEntity createOrGetPoint(const Vector &p) {
|
|
|
|
hEntity he = findPoint(p);
|
|
|
|
if(he.v != Entity::NO_ENTITY.v) return he;
|
|
|
|
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::DATUM_POINT, false);
|
2016-04-26 00:47:02 +00:00
|
|
|
he = hr.entity(0);
|
|
|
|
SK.GetEntity(he)->PointForceTo(p);
|
|
|
|
points.emplace(p, he);
|
|
|
|
return he;
|
|
|
|
}
|
|
|
|
|
|
|
|
hEntity createLine(Vector p0, Vector p1, uint32_t style, bool constrainHV = false) {
|
|
|
|
if(p0.Equals(p1)) return Entity::NO_ENTITY;
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::LINE_SEGMENT, false);
|
2016-04-26 00:47:02 +00:00
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(p0);
|
|
|
|
SK.GetEntity(hr.entity(2))->PointForceTo(p1);
|
|
|
|
processPoint(hr.entity(1));
|
|
|
|
processPoint(hr.entity(2));
|
|
|
|
|
|
|
|
if(constrainHV) {
|
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
|
|
|
bool hasConstraint = false;
|
|
|
|
Constraint::Type cType;
|
2016-04-26 00:47:02 +00:00
|
|
|
if(fabs(p0.x - p1.x) < LENGTH_EPS) {
|
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
|
|
|
hasConstraint = true;
|
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
|
|
|
cType = Constraint::Type::VERTICAL;
|
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
|
|
|
} else if(fabs(p0.y - p1.y) < LENGTH_EPS) {
|
|
|
|
hasConstraint = true;
|
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
|
|
|
cType = Constraint::Type::HORIZONTAL;
|
2016-04-26 00:47:02 +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
|
|
|
if(hasConstraint) {
|
2016-04-26 00:47:02 +00:00
|
|
|
Constraint::Constrain(
|
|
|
|
cType,
|
|
|
|
Entity::NO_ENTITY,
|
|
|
|
Entity::NO_ENTITY,
|
|
|
|
hr.entity(0)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(style != 0) {
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
r->style = hStyle{ style };
|
|
|
|
}
|
|
|
|
return hr.entity(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
hEntity createCircle(const Vector &c, double r, uint32_t style) {
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::CIRCLE, false);
|
2016-04-26 00:47:02 +00:00
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(c);
|
|
|
|
processPoint(hr.entity(1));
|
|
|
|
SK.GetEntity(hr.entity(64))->DistanceForceTo(r);
|
|
|
|
if(style != 0) {
|
|
|
|
Request *r = SK.GetRequest(hr);
|
|
|
|
r->style = hStyle{ style };
|
|
|
|
}
|
|
|
|
return hr.entity(0);
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addLayer(const DRW_Layer &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
layers.emplace(data.name, data);
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addBlock(const DRW_Block &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
readBlock = &blocks[data.name];
|
|
|
|
readBlock->data = data;
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void endBlock() override {
|
2016-04-13 08:43:06 +00:00
|
|
|
readBlock = NULL;
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addPoint(const DRW_Point &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Point>(data)) return;
|
|
|
|
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::DATUM_POINT, false);
|
2016-04-13 08:43:06 +00:00
|
|
|
SK.GetEntity(hr.entity(0))->PointForceTo(toVector(data.basePoint));
|
2016-04-26 00:47:02 +00:00
|
|
|
processPoint(hr.entity(0));
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addLine(const DRW_Line &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Line>(data)) return;
|
|
|
|
|
2016-04-26 00:47:02 +00:00
|
|
|
createLine(toVector(data.basePoint), toVector(data.secPoint), styleFor(&data).v, true);
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addArc(const DRW_Arc &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Arc>(data)) return;
|
|
|
|
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::ARC_OF_CIRCLE, false);
|
2016-04-13 08:43:06 +00:00
|
|
|
double r = data.radious;
|
|
|
|
double sa = data.staangle;
|
|
|
|
double ea = data.endangle;
|
|
|
|
Vector c = Vector::From(data.basePoint.x, data.basePoint.y, 0.0);
|
|
|
|
Vector rvs = Vector::From(r * cos(sa), r * sin(sa), data.basePoint.z).Plus(c);
|
|
|
|
Vector rve = Vector::From(r * cos(ea), r * sin(ea), data.basePoint.z).Plus(c);
|
|
|
|
|
|
|
|
if(data.extPoint.z == -1.0) {
|
|
|
|
c.x = -c.x;
|
|
|
|
rvs.x = - rvs.x;
|
|
|
|
rve.x = - rve.x;
|
|
|
|
std::swap(rvs, rve);
|
|
|
|
}
|
|
|
|
|
|
|
|
blockTransformArc(&c, &rvs, &rve);
|
|
|
|
|
|
|
|
SK.GetEntity(hr.entity(1))->PointForceTo(c);
|
|
|
|
SK.GetEntity(hr.entity(2))->PointForceTo(rvs);
|
|
|
|
SK.GetEntity(hr.entity(3))->PointForceTo(rve);
|
2016-04-26 00:47:02 +00:00
|
|
|
processPoint(hr.entity(1));
|
|
|
|
processPoint(hr.entity(2));
|
|
|
|
processPoint(hr.entity(3));
|
2016-04-13 08:43:06 +00:00
|
|
|
setStyle(hr, styleFor(&data));
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addCircle(const DRW_Circle &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Circle>(data)) return;
|
|
|
|
|
2016-04-26 00:47:02 +00:00
|
|
|
createCircle(toVector(data.basePoint), data.radious, styleFor(&data).v);
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addLWPolyline(const DRW_LWPolyline &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_LWPolyline>(data)) return;
|
|
|
|
|
|
|
|
size_t vNum = data.vertlist.size();
|
|
|
|
|
|
|
|
// Check for closed polyline.
|
|
|
|
if((data.flags & 1) != 1) vNum--;
|
|
|
|
|
|
|
|
// Correct coordinate system for the case where z=-1, as described in
|
|
|
|
// http://paulbourke.net/dataformats/dxf/dxf10.html.
|
|
|
|
bool needSwapX = data.extPoint.z == -1.0;
|
|
|
|
|
|
|
|
for(size_t i = 0; i < vNum; i++) {
|
|
|
|
DRW_Vertex2D c0 = *data.vertlist[i];
|
|
|
|
DRW_Vertex2D c1 = *data.vertlist[(i + 1) % data.vertlist.size()];
|
|
|
|
|
|
|
|
if(needSwapX) {
|
|
|
|
c0.x = -c0.x;
|
|
|
|
c1.x = -c1.x;
|
|
|
|
c0.bulge = -c0.bulge;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector p0 = Vector::From(c0.x, c0.y, 0.0);
|
|
|
|
Vector p1 = Vector::From(c1.x, c1.y, 0.0);
|
|
|
|
hStyle hs = styleFor(&data);
|
|
|
|
|
|
|
|
if(EXACT(data.vertlist[i]->bulge == 0.0)) {
|
2016-04-26 00:47:02 +00:00
|
|
|
createLine(blockTransform(p0), blockTransform(p1), hs.v, true);
|
2016-04-13 08:43:06 +00:00
|
|
|
} else {
|
|
|
|
hRequest hr = createBulge(p0, p1, c0.bulge);
|
|
|
|
setStyle(hr, hs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addPolyline(const DRW_Polyline &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Polyline>(data)) return;
|
|
|
|
|
|
|
|
int vNum = data.vertlist.size();
|
|
|
|
|
|
|
|
// Check for closed polyline.
|
|
|
|
if((data.flags & 1) != 1) vNum--;
|
|
|
|
|
|
|
|
// Correct coordinate system for the case where z=-1, as described in
|
|
|
|
// http://paulbourke.net/dataformats/dxf/dxf10.html.
|
|
|
|
bool needSwapX = data.extPoint.z == -1.0;
|
|
|
|
|
|
|
|
for(int i = 0; i < vNum; i++) {
|
|
|
|
DRW_Coord c0 = data.vertlist[i]->basePoint;
|
|
|
|
DRW_Coord c1 = data.vertlist[(i + 1) % data.vertlist.size()]->basePoint;
|
|
|
|
|
|
|
|
double bulge = data.vertlist[i]->bulge;
|
|
|
|
if(needSwapX) {
|
|
|
|
c0.x = -c0.x;
|
|
|
|
c1.x = -c1.x;
|
|
|
|
bulge = -bulge;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector p0 = Vector::From(c0.x, c0.y, 0.0);
|
|
|
|
Vector p1 = Vector::From(c1.x, c1.y, 0.0);
|
|
|
|
hStyle hs = styleFor(&data);
|
|
|
|
|
|
|
|
if(EXACT(bulge == 0.0)) {
|
2016-04-26 00:47:02 +00:00
|
|
|
createLine(blockTransform(p0), blockTransform(p1), hs.v, true);
|
2016-04-13 08:43:06 +00:00
|
|
|
} else {
|
|
|
|
hRequest hr = createBulge(p0, p1, bulge);
|
|
|
|
setStyle(hr, hs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addSpline(const DRW_Spline *data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(data->degree != 3) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Spline>(*data)) return;
|
|
|
|
|
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
|
|
|
hRequest hr = SS.GW.AddRequest(Request::Type::CUBIC, false);
|
2016-04-13 08:43:06 +00:00
|
|
|
for(int i = 0; i < 4; i++) {
|
|
|
|
SK.GetEntity(hr.entity(i + 1))->PointForceTo(toVector(*data->controllist[i]));
|
2016-04-26 00:47:02 +00:00
|
|
|
processPoint(hr.entity(i + 1));
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|
|
|
|
setStyle(hr, styleFor(data));
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addInsert(const DRW_Insert &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Insert>(data)) return;
|
|
|
|
|
|
|
|
auto bi = blocks.find(data.name);
|
2016-05-18 22:51:36 +00:00
|
|
|
ssassert(bi != blocks.end(), "Inserted block does not exist");
|
2016-04-13 08:43:06 +00:00
|
|
|
Block *block = &bi->second;
|
|
|
|
|
|
|
|
// Push transform.
|
|
|
|
Vector x = blockX;
|
|
|
|
Vector y = blockY;
|
|
|
|
Vector t = blockT;
|
|
|
|
|
|
|
|
const DRW_Insert *oldInsert = insertInsert;
|
|
|
|
insertInsert = &data;
|
|
|
|
|
|
|
|
if(data.extPoint.z == -1.0) invertXTransform();
|
|
|
|
multBlockTransform(data.basePoint.x, data.basePoint.y, data.xscale, data.yscale, data.angle);
|
|
|
|
for(auto &e : block->entities) {
|
|
|
|
addEntity(&*e);
|
|
|
|
}
|
|
|
|
|
|
|
|
insertInsert = oldInsert;
|
|
|
|
|
|
|
|
// Pop transform.
|
|
|
|
blockX = x;
|
|
|
|
blockY = y;
|
|
|
|
blockT = t;
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addMText(const DRW_MText &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_MText>(data)) return;
|
|
|
|
|
|
|
|
DRW_MText text = data;
|
|
|
|
text.secPoint = text.basePoint;
|
|
|
|
addText(text);
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addText(const DRW_Text &data) override {
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_Text>(data)) return;
|
|
|
|
|
|
|
|
Constraint c = {};
|
|
|
|
c.group = SS.GW.activeGroup;
|
|
|
|
c.workplane = SS.GW.ActiveWorkplane();
|
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
|
|
|
c.type = Constraint::Type::COMMENT;
|
2016-04-13 08:43:06 +00:00
|
|
|
if(data.alignH == DRW_Text::HLeft && data.alignV == DRW_Text::VBaseLine) {
|
|
|
|
c.disp.offset = toVector(data.basePoint);
|
|
|
|
} else {
|
|
|
|
c.disp.offset = toVector(data.secPoint);
|
|
|
|
}
|
|
|
|
c.comment = data.text;
|
|
|
|
c.disp.style = styleFor(&data);
|
|
|
|
Constraint::AddConstraint(&c, false);
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimAlign(const DRW_DimAligned *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimAligned>(*data)) return;
|
|
|
|
|
|
|
|
Vector p0 = toVector(data->getDef1Point());
|
|
|
|
Vector p1 = toVector(data->getDef2Point());
|
|
|
|
Vector p2 = toVector(data->getTextPoint());
|
|
|
|
hConstraint hc = Constraint::Constrain(
|
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
|
|
|
Constraint::Type::PT_PT_DISTANCE,
|
2016-04-26 00:47:02 +00:00
|
|
|
createOrGetPoint(p0),
|
|
|
|
createOrGetPoint(p1),
|
|
|
|
Entity::NO_ENTITY
|
|
|
|
);
|
|
|
|
|
|
|
|
Constraint *c = SK.GetConstraint(hc);
|
2016-05-17 06:49:37 +00:00
|
|
|
if(data->hasActualMeasurement()) {
|
|
|
|
c->valA = data->getActualMeasurement();
|
|
|
|
} else {
|
|
|
|
c->ModifyToSatisfy();
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
c->disp.offset = p2.Minus(p0.Plus(p1).ScaledBy(0.5));
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimLinear(const DRW_DimLinear *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimLinear>(*data)) return;
|
|
|
|
|
|
|
|
Vector p0 = toVector(data->getDef1Point(), false);
|
|
|
|
Vector p1 = toVector(data->getDef2Point(), false);
|
|
|
|
Vector p2 = toVector(data->getTextPoint(), false);
|
|
|
|
|
|
|
|
double angle = data->getAngle() * PI / 180.0;
|
|
|
|
Vector dir = Vector::From(cos(angle), sin(angle), 0.0);
|
|
|
|
Vector p3 = p1.Minus(p1.ClosestPointOnLine(p2, dir)).Plus(p1);
|
|
|
|
if(p1.Minus(p3).Magnitude() < LENGTH_EPS) {
|
|
|
|
p3 = p0.Minus(p0.ClosestPointOnLine(p2, dir)).Plus(p1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector p4 = p0.ClosestPointOnLine(p1, p3.Minus(p1)).Plus(p0).ScaledBy(0.5);
|
|
|
|
|
|
|
|
p0 = blockTransform(p0);
|
|
|
|
p1 = blockTransform(p1);
|
|
|
|
p2 = blockTransform(p2);
|
|
|
|
p3 = blockTransform(p3);
|
|
|
|
p4 = blockTransform(p4);
|
|
|
|
|
|
|
|
hConstraint hc = Constraint::Constrain(
|
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
|
|
|
Constraint::Type::PT_LINE_DISTANCE,
|
2016-04-26 00:47:02 +00:00
|
|
|
createOrGetPoint(p0),
|
|
|
|
Entity::NO_ENTITY,
|
|
|
|
createLine(p1, p3, invisibleStyle().v)
|
|
|
|
);
|
|
|
|
|
|
|
|
Constraint *c = SK.GetConstraint(hc);
|
2016-05-17 06:49:37 +00:00
|
|
|
if(data->hasActualMeasurement()) {
|
|
|
|
c->valA = data->getActualMeasurement();
|
|
|
|
} else {
|
|
|
|
c->ModifyToSatisfy();
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
c->disp.offset = p2.Minus(p4);
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimAngular(const DRW_DimAngular *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimAngular>(*data)) return;
|
|
|
|
|
|
|
|
Vector l0p0 = toVector(data->getFirstLine1());
|
|
|
|
Vector l0p1 = toVector(data->getFirstLine2());
|
|
|
|
Vector l1p0 = toVector(data->getSecondLine1());
|
|
|
|
Vector l1p1 = toVector(data->getSecondLine2());
|
|
|
|
|
|
|
|
hConstraint hc = Constraint::Constrain(
|
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
|
|
|
Constraint::Type::ANGLE,
|
2016-04-26 00:47:02 +00:00
|
|
|
Entity::NO_ENTITY,
|
|
|
|
Entity::NO_ENTITY,
|
|
|
|
createLine(l0p0, l0p1, invisibleStyle().v),
|
|
|
|
createLine(l1p1, l1p0, invisibleStyle().v),
|
|
|
|
/*other=*/false,
|
|
|
|
/*other2=*/false
|
|
|
|
);
|
|
|
|
|
|
|
|
Constraint *c = SK.GetConstraint(hc);
|
|
|
|
c->ModifyToSatisfy();
|
2016-05-17 06:49:37 +00:00
|
|
|
if(data->hasActualMeasurement()) {
|
|
|
|
double actual = data->getActualMeasurement() / PI * 180.0;
|
|
|
|
if(fabs(180.0 - actual - c->valA) < fabs(actual - c->valA)) {
|
|
|
|
c->other = true;
|
|
|
|
}
|
|
|
|
c->valA = actual;
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
|
|
|
|
bool skew = false;
|
|
|
|
Vector pi = Vector::AtIntersectionOfLines(l0p0, l0p1, l1p0, l1p1, &skew);
|
|
|
|
if(!skew) {
|
|
|
|
c->disp.offset = toVector(data->getTextPoint()).Minus(pi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 06:49:37 +00:00
|
|
|
hConstraint createDiametric(Vector cp, double r, Vector tp, double actual, bool asRadius = false) {
|
2016-04-26 00:47:02 +00:00
|
|
|
hEntity he = createCircle(cp, r, invisibleStyle().v);
|
|
|
|
|
|
|
|
hConstraint hc = Constraint::Constrain(
|
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
|
|
|
Constraint::Type::DIAMETER,
|
2016-04-26 00:47:02 +00:00
|
|
|
Entity::NO_ENTITY,
|
|
|
|
Entity::NO_ENTITY,
|
|
|
|
he
|
|
|
|
);
|
|
|
|
|
|
|
|
Constraint *c = SK.GetConstraint(hc);
|
2016-05-17 06:49:37 +00:00
|
|
|
if(actual > 0.0) {
|
|
|
|
c->valA = asRadius ? actual * 2.0 : actual;
|
|
|
|
} else {
|
|
|
|
c->ModifyToSatisfy();
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
c->disp.offset = tp.Minus(cp);
|
|
|
|
if(asRadius) c->other = true;
|
|
|
|
return hc;
|
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimRadial(const DRW_DimRadial *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimRadial>(*data)) return;
|
|
|
|
|
|
|
|
Vector cp = toVector(data->getCenterPoint());
|
|
|
|
Vector dp = toVector(data->getDiameterPoint());
|
|
|
|
Vector tp = toVector(data->getTextPoint());
|
2016-05-17 06:49:37 +00:00
|
|
|
double actual = -1.0;
|
|
|
|
if(data->hasActualMeasurement()) {
|
|
|
|
actual = data->getActualMeasurement();
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
|
2016-05-17 06:49:37 +00:00
|
|
|
createDiametric(cp, cp.Minus(dp).Magnitude(), tp, actual, /*asRadius=*/true);
|
2016-04-26 00:47:02 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimDiametric(const DRW_DimDiametric *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimRadial>(*data)) return;
|
|
|
|
|
|
|
|
Vector dp1 = toVector(data->getDiameter1Point());
|
|
|
|
Vector dp2 = toVector(data->getDiameter2Point());
|
|
|
|
|
|
|
|
Vector cp = dp1.Plus(dp2).ScaledBy(0.5);
|
|
|
|
Vector tp = toVector(data->getTextPoint());
|
2016-05-17 06:49:37 +00:00
|
|
|
double actual = -1.0;
|
|
|
|
if(data->hasActualMeasurement()) {
|
|
|
|
actual = data->getActualMeasurement();
|
|
|
|
}
|
2016-04-26 00:47:02 +00:00
|
|
|
|
2016-05-17 06:49:37 +00:00
|
|
|
createDiametric(cp, cp.Minus(dp1).Magnitude(), tp, actual, /*asRadius=*/false);
|
2016-04-26 00:47:02 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 18:42:33 +00:00
|
|
|
void addDimAngular3P(const DRW_DimAngular3p *data) override {
|
2016-04-26 00:47:02 +00:00
|
|
|
if(data->space != DRW::ModelSpace) return;
|
|
|
|
if(addPendingBlockEntity<DRW_DimAngular3p>(*data)) return;
|
|
|
|
|
|
|
|
DRW_DimAngular dim = *static_cast<const DRW_Dimension *>(data);
|
|
|
|
dim.setFirstLine1(data->getVertexPoint());
|
|
|
|
dim.setFirstLine2(data->getFirstLine());
|
|
|
|
dim.setSecondLine1(data->getVertexPoint());
|
|
|
|
dim.setSecondLine2(data->getSecondLine());
|
|
|
|
addDimAngular(&dim);
|
|
|
|
}
|
2016-04-13 08:43:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void ImportDxf(const std::string &filename) {
|
2016-05-20 05:53:00 +00:00
|
|
|
SS.UndoRemember();
|
2016-04-13 08:43:06 +00:00
|
|
|
dxfRW dxf(filename.c_str());
|
|
|
|
DxfReadInterface interface;
|
|
|
|
interface.clearBlockTransform();
|
2016-05-07 05:17:23 +00:00
|
|
|
if(!dxf.read(&interface, false)) {
|
|
|
|
Error("Corrupted DXF file!");
|
|
|
|
}
|
2016-04-13 08:43:06 +00:00
|
|
|
if(interface.unknownEntities > 0) {
|
|
|
|
Message(ssprintf("%u DXF entities of unknown type were ignored.",
|
|
|
|
interface.unknownEntities).c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-07 05:17:23 +00:00
|
|
|
void ImportDwg(const std::string &filename) {
|
2016-05-20 05:53:00 +00:00
|
|
|
SS.UndoRemember();
|
2016-05-07 05:17:23 +00:00
|
|
|
dwgR dwg(filename.c_str());
|
|
|
|
DxfReadInterface interface;
|
|
|
|
interface.clearBlockTransform();
|
|
|
|
if(!dwg.read(&interface, false)) {
|
|
|
|
Error("Corrupted DWG file!");
|
|
|
|
}
|
|
|
|
if(interface.unknownEntities > 0) {
|
|
|
|
Message(ssprintf("%u DWG entities of unknown type were ignored.",
|
|
|
|
interface.unknownEntities).c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-13 08:43:06 +00:00
|
|
|
}
|