solvespace/src/importdxf.cpp

934 lines
30 KiB
C++
Raw Normal View History

2016-04-13 08:43:06 +00:00
#include "solvespace.h"
#include "libdxfrw.h"
#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);
}
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);
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(&center, &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);
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;
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;
}
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;
}
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);
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);
SK.GetEntity(hr.entity(1))->PointForceTo(p0);
SK.GetEntity(hr.entity(2))->PointForceTo(p1);
processPoint(hr.entity(1));
processPoint(hr.entity(2));
if(constrainHV) {
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 cType = Constraint::Type::UNKNOWN;
if(fabs(p0.x - p1.x) < LENGTH_EPS) {
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;
}
else if(fabs(p0.y - p1.y) < LENGTH_EPS) {
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;
}
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(cType != Constraint::Type::UNKNOWN) {
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);
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);
}
void addLayer(const DRW_Layer &data) override {
2016-04-13 08:43:06 +00:00
layers.emplace(data.name, data);
}
void addBlock(const DRW_Block &data) override {
2016-04-13 08:43:06 +00:00
readBlock = &blocks[data.name];
readBlock->data = data;
}
void endBlock() override {
2016-04-13 08:43:06 +00:00
readBlock = NULL;
}
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));
processPoint(hr.entity(0));
2016-04-13 08:43:06 +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;
createLine(toVector(data.basePoint), toVector(data.secPoint), styleFor(&data).v, true);
2016-04-13 08:43:06 +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);
processPoint(hr.entity(1));
processPoint(hr.entity(2));
processPoint(hr.entity(3));
2016-04-13 08:43:06 +00:00
setStyle(hr, styleFor(&data));
}
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;
createCircle(toVector(data.basePoint), data.radious, styleFor(&data).v);
2016-04-13 08:43:06 +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)) {
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);
}
}
}
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)) {
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);
}
}
}
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]));
processPoint(hr.entity(i + 1));
2016-04-13 08:43:06 +00:00
}
setStyle(hr, styleFor(data));
}
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);
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;
}
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);
}
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);
}
void addDimAlign(const DRW_DimAligned *data) override {
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,
createOrGetPoint(p0),
createOrGetPoint(p1),
Entity::NO_ENTITY
);
Constraint *c = SK.GetConstraint(hc);
if(data->hasActualMeasurement()) {
c->valA = data->getActualMeasurement();
} else {
c->ModifyToSatisfy();
}
c->disp.offset = p2.Minus(p0.Plus(p1).ScaledBy(0.5));
}
void addDimLinear(const DRW_DimLinear *data) override {
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,
createOrGetPoint(p0),
Entity::NO_ENTITY,
createLine(p1, p3, invisibleStyle().v)
);
Constraint *c = SK.GetConstraint(hc);
if(data->hasActualMeasurement()) {
c->valA = data->getActualMeasurement();
} else {
c->ModifyToSatisfy();
}
c->disp.offset = p2.Minus(p4);
}
void addDimAngular(const DRW_DimAngular *data) override {
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,
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();
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;
}
bool skew = false;
Vector pi = Vector::AtIntersectionOfLines(l0p0, l0p1, l1p0, l1p1, &skew);
if(!skew) {
c->disp.offset = toVector(data->getTextPoint()).Minus(pi);
}
}
hConstraint createDiametric(Vector cp, double r, Vector tp, double actual, bool asRadius = false) {
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,
Entity::NO_ENTITY,
Entity::NO_ENTITY,
he
);
Constraint *c = SK.GetConstraint(hc);
if(actual > 0.0) {
c->valA = asRadius ? actual * 2.0 : actual;
} else {
c->ModifyToSatisfy();
}
c->disp.offset = tp.Minus(cp);
if(asRadius) c->other = true;
return hc;
}
void addDimRadial(const DRW_DimRadial *data) override {
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());
double actual = -1.0;
if(data->hasActualMeasurement()) {
actual = data->getActualMeasurement();
}
createDiametric(cp, cp.Minus(dp).Magnitude(), tp, actual, /*asRadius=*/true);
}
void addDimDiametric(const DRW_DimDiametric *data) override {
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());
double actual = -1.0;
if(data->hasActualMeasurement()) {
actual = data->getActualMeasurement();
}
createDiametric(cp, cp.Minus(dp1).Magnitude(), tp, actual, /*asRadius=*/false);
}
void addDimAngular3P(const DRW_DimAngular3p *data) override {
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();
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());
}
}
void ImportDwg(const std::string &filename) {
2016-05-20 05:53:00 +00:00
SS.UndoRemember();
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
}