Streamline scaling for DXF import
Eliminate m_measurement_inch to clean up logic for priority of MEASUREMENT and INSUNITS. Save the actual scaling factor rather than the scaling enum so a switch statement is not executed for each call to mm() Add to CDxfRead the work to handle dxfScaling option, ImpExpDxfRead just has to set it up now. Get the scaling factor from a lookup table rather than a switch statement Display a message explaining what the scaling factor is and where it comes from Remove large amount of Lint.
This commit is contained in:
committed by
Yorik van Havre
parent
51e4561fd7
commit
c2fb684ff7
@@ -78,10 +78,12 @@ using BRepAdaptor_HCurve = BRepAdaptor_Curve;
|
||||
|
||||
//******************************************************************************
|
||||
// reading
|
||||
ImpExpDxfRead::ImpExpDxfRead(std::string filepath, App::Document* pcDoc)
|
||||
: CDxfRead(filepath.c_str())
|
||||
ImpExpDxfRead::ImpExpDxfRead(const std::string& filepath, App::Document* pcDoc)
|
||||
: CDxfRead(filepath)
|
||||
, document(pcDoc)
|
||||
, optionGroupLayers(false)
|
||||
, optionImportAnnotations(true)
|
||||
{
|
||||
document = pcDoc;
|
||||
setOptionSource("User parameter:BaseApp/Preferences/Mod/Draft");
|
||||
setOptions();
|
||||
}
|
||||
@@ -92,22 +94,17 @@ void ImpExpDxfRead::setOptions()
|
||||
App::GetApplication().GetParameterGroupByPath(getOptionSource().c_str());
|
||||
optionGroupLayers = hGrp->GetBool("groupLayers", false);
|
||||
optionImportAnnotations = hGrp->GetBool("dxftext", false);
|
||||
optionScaling = hGrp->GetFloat("dxfScaling", 1.0);
|
||||
SetAdditionalScaling(hGrp->GetFloat("dxfScaling", 1.0));
|
||||
}
|
||||
|
||||
gp_Pnt ImpExpDxfRead::makePoint(const double point3d[3]) const
|
||||
void ImpExpDxfRead::OnReadLine(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
bool /*hidden*/)
|
||||
{
|
||||
if (optionScaling != 1.0) {
|
||||
return {point3d[0] * optionScaling, point3d[1] * optionScaling, point3d[2] * optionScaling};
|
||||
}
|
||||
return {point3d[0], point3d[1], point3d[2]};
|
||||
}
|
||||
|
||||
void ImpExpDxfRead::OnReadLine(const double* s, const double* e, bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Pnt p1 = makePoint(e);
|
||||
gp_Pnt p0 = makePoint(start);
|
||||
gp_Pnt p1 = makePoint(end);
|
||||
if (p0.IsEqual(p1, 0.00000001)) {
|
||||
// TODO: Really?? What about the people designing integrated circuits?
|
||||
return;
|
||||
}
|
||||
BRepBuilderAPI_MakeEdge makeEdge(p0, p1);
|
||||
@@ -116,27 +113,27 @@ void ImpExpDxfRead::OnReadLine(const double* s, const double* e, bool /*hidden*/
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadPoint(const double* s)
|
||||
void ImpExpDxfRead::OnReadPoint(const Base::Vector3d& start)
|
||||
{
|
||||
BRepBuilderAPI_MakeVertex makeVertex(makePoint(s));
|
||||
BRepBuilderAPI_MakeVertex makeVertex(makePoint(start));
|
||||
TopoDS_Vertex vertex = makeVertex.Vertex();
|
||||
AddObject(new Part::TopoShape(vertex));
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadArc(const double* s,
|
||||
const double* e,
|
||||
const double* c,
|
||||
void ImpExpDxfRead::OnReadArc(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
const Base::Vector3d& center,
|
||||
bool dir,
|
||||
bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Pnt p1 = makePoint(e);
|
||||
gp_Pnt p0 = makePoint(start);
|
||||
gp_Pnt p1 = makePoint(end);
|
||||
gp_Dir up(0, 0, 1);
|
||||
if (!dir) {
|
||||
up = -up;
|
||||
}
|
||||
gp_Pnt pc = makePoint(c);
|
||||
gp_Pnt pc = makePoint(center);
|
||||
gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc));
|
||||
if (circle.Radius() > 0) {
|
||||
BRepBuilderAPI_MakeEdge makeEdge(circle, p0, p1);
|
||||
@@ -149,14 +146,17 @@ void ImpExpDxfRead::OnReadArc(const double* s,
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadCircle(const double* s, const double* c, bool dir, bool /*hidden*/)
|
||||
void ImpExpDxfRead::OnReadCircle(const Base::Vector3d& start,
|
||||
const Base::Vector3d& center,
|
||||
bool dir,
|
||||
bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Pnt p0 = makePoint(start);
|
||||
gp_Dir up(0, 0, 1);
|
||||
if (!dir) {
|
||||
up = -up;
|
||||
}
|
||||
gp_Pnt pc = makePoint(c);
|
||||
gp_Pnt pc = makePoint(center);
|
||||
gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc));
|
||||
if (circle.Radius() > 0) {
|
||||
BRepBuilderAPI_MakeEdge makeEdge(circle);
|
||||
@@ -180,18 +180,18 @@ Handle(Geom_BSplineCurve) getSplineFromPolesAndKnots(struct SplineData& sd)
|
||||
// handle the poles
|
||||
TColgp_Array1OfPnt occpoles(1, sd.control_points);
|
||||
int index = 1;
|
||||
for (auto x : sd.controlx) {
|
||||
occpoles(index++).SetX(x);
|
||||
for (auto coordinate : sd.controlx) {
|
||||
occpoles(index++).SetX(coordinate);
|
||||
}
|
||||
|
||||
index = 1;
|
||||
for (auto y : sd.controly) {
|
||||
occpoles(index++).SetY(y);
|
||||
for (auto coordinate : sd.controly) {
|
||||
occpoles(index++).SetY(coordinate);
|
||||
}
|
||||
|
||||
index = 1;
|
||||
for (auto z : sd.controlz) {
|
||||
occpoles(index++).SetZ(z);
|
||||
for (auto coordinate : sd.controlz) {
|
||||
occpoles(index++).SetZ(coordinate);
|
||||
}
|
||||
|
||||
// handle knots and mults
|
||||
@@ -202,10 +202,9 @@ Handle(Geom_BSplineCurve) getSplineFromPolesAndKnots(struct SplineData& sd)
|
||||
TColStd_Array1OfInteger occmults(1, numKnots);
|
||||
TColStd_Array1OfReal occknots(1, numKnots);
|
||||
index = 1;
|
||||
for (auto k : unique) {
|
||||
size_t m = std::count(sd.knot.begin(), sd.knot.end(), k);
|
||||
occknots(index) = k;
|
||||
occmults(index) = m;
|
||||
for (auto knot : unique) {
|
||||
occknots(index) = knot;
|
||||
occmults(index) = (int)std::count(sd.knot.begin(), sd.knot.end(), knot);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -213,8 +212,8 @@ Handle(Geom_BSplineCurve) getSplineFromPolesAndKnots(struct SplineData& sd)
|
||||
TColStd_Array1OfReal occweights(1, sd.control_points);
|
||||
if (sd.weight.size() == std::size_t(sd.control_points)) {
|
||||
index = 1;
|
||||
for (auto w : sd.weight) {
|
||||
occweights(index++) = w;
|
||||
for (auto weight : sd.weight) {
|
||||
occweights(index++) = weight;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -240,18 +239,18 @@ Handle(Geom_BSplineCurve) getInterpolationSpline(struct SplineData& sd)
|
||||
// handle the poles
|
||||
Handle(TColgp_HArray1OfPnt) fitpoints = new TColgp_HArray1OfPnt(1, sd.fit_points);
|
||||
int index = 1;
|
||||
for (auto x : sd.fitx) {
|
||||
fitpoints->ChangeValue(index++).SetX(x);
|
||||
for (auto coordinate : sd.fitx) {
|
||||
fitpoints->ChangeValue(index++).SetX(coordinate);
|
||||
}
|
||||
|
||||
index = 1;
|
||||
for (auto y : sd.fity) {
|
||||
fitpoints->ChangeValue(index++).SetY(y);
|
||||
for (auto coordinate : sd.fity) {
|
||||
fitpoints->ChangeValue(index++).SetY(coordinate);
|
||||
}
|
||||
|
||||
index = 1;
|
||||
for (auto z : sd.fitz) {
|
||||
fitpoints->ChangeValue(index++).SetZ(z);
|
||||
for (auto coordinate : sd.fitz) {
|
||||
fitpoints->ChangeValue(index++).SetZ(coordinate);
|
||||
}
|
||||
|
||||
Standard_Boolean periodic = sd.flag == 2;
|
||||
@@ -288,21 +287,22 @@ void ImpExpDxfRead::OnReadSpline(struct SplineData& sd)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadEllipse(const double* c,
|
||||
// NOLINTBEGIN(bugprone-easily-swappable-parameters)
|
||||
void ImpExpDxfRead::OnReadEllipse(const Base::Vector3d& center,
|
||||
double major_radius,
|
||||
double minor_radius,
|
||||
double rotation,
|
||||
double /*start_angle*/,
|
||||
double /*end_angle*/,
|
||||
bool dir)
|
||||
// NOLINTEND(bugprone-easily-swappable-parameters)
|
||||
{
|
||||
gp_Dir up(0, 0, 1);
|
||||
if (!dir) {
|
||||
up = -up;
|
||||
}
|
||||
gp_Pnt pc = makePoint(c);
|
||||
gp_Elips ellipse(gp_Ax2(pc, up), major_radius * optionScaling, minor_radius * optionScaling);
|
||||
gp_Pnt pc = makePoint(center);
|
||||
gp_Elips ellipse(gp_Ax2(pc, up), major_radius, minor_radius);
|
||||
ellipse.Rotate(gp_Ax1(pc, up), rotation);
|
||||
if (ellipse.MinorRadius() > 0) {
|
||||
BRepBuilderAPI_MakeEdge makeEdge(ellipse);
|
||||
@@ -315,34 +315,34 @@ void ImpExpDxfRead::OnReadEllipse(const double* c,
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadText(const double* point,
|
||||
void ImpExpDxfRead::OnReadText(const Base::Vector3d& point,
|
||||
const double height,
|
||||
const char* text,
|
||||
const std::string& text,
|
||||
const double rotation)
|
||||
{
|
||||
// Note that our parameters do not contain all the information needed to properly orient the
|
||||
// text. As a result the text will always appear on the XY plane
|
||||
if (optionImportAnnotations) {
|
||||
if (LayerName().substr(0, 6) != "BLOCKS") {
|
||||
if (LayerName().rfind("BLOCKS", 0) != 0) {
|
||||
PyObject* draftModule = nullptr;
|
||||
Base::Vector3d insertionPoint(point[0], point[1], point[2]);
|
||||
insertionPoint *= optionScaling;
|
||||
Base::Rotation rot(Base::Vector3d(0, 0, 1), rotation);
|
||||
PyObject* placement = new Base::PlacementPy(Base::Placement(insertionPoint, rot));
|
||||
PyObject* placement = new Base::PlacementPy(Base::Placement(point, rot));
|
||||
draftModule = PyImport_ImportModule("Draft");
|
||||
if (draftModule != nullptr) {
|
||||
// returns a wrapped App::FeaturePython
|
||||
auto builtText = static_cast<App::FeaturePythonPyT<App::DocumentObjectPy>*>(
|
||||
PyObject_CallMethod(draftModule,
|
||||
"make_text",
|
||||
"sOif",
|
||||
text,
|
||||
placement,
|
||||
0,
|
||||
height));
|
||||
auto builtText = dynamic_cast<App::FeaturePythonPyT<App::DocumentObjectPy>*>(
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
(Base::PyObjectBase*)PyObject_CallMethod(draftModule,
|
||||
"make_text",
|
||||
"sOif",
|
||||
text.c_str(),
|
||||
placement,
|
||||
0,
|
||||
height));
|
||||
if (builtText != nullptr) {
|
||||
ApplyGuiStyles(
|
||||
static_cast<App::FeaturePython*>(builtText->getDocumentObjectPtr()));
|
||||
dynamic_cast<App::FeaturePython*>(builtText->getDocumentObjectPtr()));
|
||||
}
|
||||
}
|
||||
// We own all the return values so we must release them.
|
||||
@@ -356,9 +356,9 @@ void ImpExpDxfRead::OnReadText(const double* point,
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadInsert(const double* point,
|
||||
const double* scale,
|
||||
const char* name,
|
||||
void ImpExpDxfRead::OnReadInsert(const Base::Vector3d& point,
|
||||
const Base::Vector3d& scale,
|
||||
const std::string& name,
|
||||
double rotation)
|
||||
{
|
||||
// std::cout << "Inserting block " << name << " rotation " << rotation << " pos " << point[0] <<
|
||||
@@ -367,32 +367,26 @@ void ImpExpDxfRead::OnReadInsert(const double* point,
|
||||
std::string prefix = "BLOCKS ";
|
||||
prefix += name;
|
||||
prefix += " ";
|
||||
auto checkScale = [=](double v) {
|
||||
return v != 0.0 ? v : 1.0;
|
||||
auto checkScale = [=](double scale) {
|
||||
return scale != 0.0 ? scale : 1.0;
|
||||
};
|
||||
for (std::map<std::string, std::vector<Part::TopoShape*>>::const_iterator i = layers.begin();
|
||||
i != layers.end();
|
||||
++i) {
|
||||
std::string k = i->first;
|
||||
if (k.substr(0, prefix.size()) == prefix) {
|
||||
for (const auto& layer : layers) {
|
||||
if (layer.first.substr(0, prefix.size()) == prefix) {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
std::vector<Part::TopoShape*> v = i->second;
|
||||
for (std::vector<Part::TopoShape*>::const_iterator j = v.begin(); j != v.end(); ++j) {
|
||||
const TopoDS_Shape& sh = (*j)->getShape();
|
||||
for (const auto& shape : layer.second) {
|
||||
const TopoDS_Shape& sh = shape->getShape();
|
||||
if (!sh.IsNull()) {
|
||||
builder.Add(comp, sh);
|
||||
}
|
||||
}
|
||||
if (!comp.IsNull()) {
|
||||
Part::TopoShape* pcomp = new Part::TopoShape(comp);
|
||||
auto pcomp = new Part::TopoShape(comp);
|
||||
Base::Matrix4D mat;
|
||||
mat.scale(checkScale(scale[0]), checkScale(scale[1]), checkScale(scale[2]));
|
||||
mat.rotZ(rotation);
|
||||
mat.move(point[0] * optionScaling,
|
||||
point[1] * optionScaling,
|
||||
point[2] * optionScaling);
|
||||
mat.move(point[0], point[1], point[2]);
|
||||
pcomp->transformShape(mat, true);
|
||||
AddObject(pcomp);
|
||||
}
|
||||
@@ -401,35 +395,36 @@ void ImpExpDxfRead::OnReadInsert(const double* point,
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadDimension(const double* s,
|
||||
const double* e,
|
||||
const double* point,
|
||||
void ImpExpDxfRead::OnReadDimension(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
const Base::Vector3d& point,
|
||||
double /*rotation*/)
|
||||
{
|
||||
if (optionImportAnnotations) {
|
||||
PyObject* draftModule = nullptr;
|
||||
PyObject* start = new Base::VectorPy(Base::Vector3d(s[0], s[1], s[2]) * optionScaling);
|
||||
PyObject* end = new Base::VectorPy(Base::Vector3d(e[0], e[1], e[2]) * optionScaling);
|
||||
PyObject* lineLocation =
|
||||
new Base::VectorPy(Base::Vector3d(point[0], point[1], point[2]) * optionScaling);
|
||||
PyObject* startPy = new Base::VectorPy(start);
|
||||
PyObject* endPy = new Base::VectorPy(end);
|
||||
PyObject* lineLocationPy = new Base::VectorPy(point);
|
||||
draftModule = PyImport_ImportModule("Draft");
|
||||
if (draftModule != nullptr) {
|
||||
// returns a wrapped App::FeaturePython
|
||||
auto builtDim = static_cast<App::FeaturePythonPyT<App::DocumentObjectPy>*>(
|
||||
PyObject_CallMethod(draftModule,
|
||||
"make_linear_dimension",
|
||||
"OOO",
|
||||
start,
|
||||
end,
|
||||
lineLocation));
|
||||
auto builtDim = dynamic_cast<App::FeaturePythonPyT<App::DocumentObjectPy>*>(
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
(Base::PyObjectBase*)PyObject_CallMethod(draftModule,
|
||||
"make_linear_dimension",
|
||||
"OOO",
|
||||
startPy,
|
||||
endPy,
|
||||
lineLocationPy));
|
||||
if (builtDim != nullptr) {
|
||||
ApplyGuiStyles(static_cast<App::FeaturePython*>(builtDim->getDocumentObjectPtr()));
|
||||
ApplyGuiStyles(dynamic_cast<App::FeaturePython*>(builtDim->getDocumentObjectPtr()));
|
||||
}
|
||||
}
|
||||
// We own all the return values so we must release them.
|
||||
Py_DECREF(start);
|
||||
Py_DECREF(end);
|
||||
Py_DECREF(lineLocation);
|
||||
Py_DECREF(startPy);
|
||||
Py_DECREF(endPy);
|
||||
Py_DECREF(lineLocationPy);
|
||||
Py_XDECREF(draftModule);
|
||||
}
|
||||
}
|
||||
@@ -438,15 +433,16 @@ void ImpExpDxfRead::OnReadDimension(const double* s,
|
||||
void ImpExpDxfRead::AddObject(Part::TopoShape* shape)
|
||||
{
|
||||
std::vector<Part::TopoShape*> vec;
|
||||
if (layers.count(LayerName())) {
|
||||
vec = layers[LayerName()];
|
||||
std::string destinationLayerName(LayerName());
|
||||
if (layers.count(destinationLayerName) != 0) {
|
||||
vec = layers[destinationLayerName];
|
||||
}
|
||||
vec.push_back(shape);
|
||||
layers[LayerName()] = vec;
|
||||
layers[destinationLayerName] = vec;
|
||||
if (!optionGroupLayers) {
|
||||
if (LayerName().substr(0, 6) != "BLOCKS") {
|
||||
Part::Feature* pcFeature =
|
||||
static_cast<Part::Feature*>(document->addObject("Part::Feature", "Shape"));
|
||||
if (destinationLayerName.rfind("BLOCKS", 0) != 0) {
|
||||
auto pcFeature =
|
||||
dynamic_cast<Part::Feature*>(document->addObject("Part::Feature", "Shape"));
|
||||
pcFeature->Shape.setValue(shape->getShape());
|
||||
ApplyGuiStyles(pcFeature);
|
||||
}
|
||||
@@ -461,33 +457,31 @@ std::string ImpExpDxfRead::Deformat(const char* text)
|
||||
bool escape = false; // turned on when finding an escape character
|
||||
bool longescape = false; // turned on for certain escape codes that expect additional chars
|
||||
for (unsigned int i = 0; i < strlen(text); i++) {
|
||||
if (text[i] == '\\') {
|
||||
char ch = text[i];
|
||||
if (ch == '\\') {
|
||||
escape = true;
|
||||
}
|
||||
else if (escape) {
|
||||
if (longescape) {
|
||||
if (text[i] == ';') {
|
||||
if (ch == ';') {
|
||||
escape = false;
|
||||
longescape = false;
|
||||
}
|
||||
}
|
||||
else if ((ch == 'H') || (ch == 'h') || (ch == 'Q') || (ch == 'q') || (ch == 'W')
|
||||
|| (ch == 'w') || (ch == 'F') || (ch == 'f') || (ch == 'A') || (ch == 'a')
|
||||
|| (ch == 'C') || (ch == 'c') || (ch == 'T') || (ch == 't')) {
|
||||
longescape = true;
|
||||
}
|
||||
else {
|
||||
if ((text[i] == 'H') || (text[i] == 'h') || (text[i] == 'Q') || (text[i] == 'q')
|
||||
|| (text[i] == 'W') || (text[i] == 'w') || (text[i] == 'F') || (text[i] == 'f')
|
||||
|| (text[i] == 'A') || (text[i] == 'a') || (text[i] == 'C') || (text[i] == 'c')
|
||||
|| (text[i] == 'T') || (text[i] == 't')) {
|
||||
longescape = true;
|
||||
}
|
||||
else {
|
||||
if ((text[i] == 'P') || (text[i] == 'p')) {
|
||||
ss << "\n";
|
||||
}
|
||||
escape = false;
|
||||
if ((ch == 'P') || (ch == 'p')) {
|
||||
ss << "\n";
|
||||
}
|
||||
escape = false;
|
||||
}
|
||||
}
|
||||
else if ((text[i] != '{') && (text[i] != '}')) {
|
||||
ss << text[i];
|
||||
else if ((ch != '{') && (ch != '}')) {
|
||||
ss << ch;
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
@@ -497,28 +491,23 @@ std::string ImpExpDxfRead::Deformat(const char* text)
|
||||
void ImpExpDxfRead::AddGraphics() const
|
||||
{
|
||||
if (optionGroupLayers) {
|
||||
for (std::map<std::string, std::vector<Part::TopoShape*>>::const_iterator i =
|
||||
layers.begin();
|
||||
i != layers.end();
|
||||
++i) {
|
||||
for (const auto& layer : layers) {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
std::string k = i->first;
|
||||
std::string k = layer.first;
|
||||
if (k == "0") { // FreeCAD doesn't like an object name being '0'...
|
||||
k = "LAYER_0";
|
||||
}
|
||||
std::vector<Part::TopoShape*> v = i->second;
|
||||
if (k.substr(0, 6) != "BLOCKS") {
|
||||
for (std::vector<Part::TopoShape*>::const_iterator j = v.begin(); j != v.end();
|
||||
++j) {
|
||||
const TopoDS_Shape& sh = (*j)->getShape();
|
||||
if (k.rfind("BLOCKS", 0) != 0) {
|
||||
for (const auto& shape : layer.second) {
|
||||
const TopoDS_Shape& sh = shape->getShape();
|
||||
if (!sh.IsNull()) {
|
||||
builder.Add(comp, sh);
|
||||
}
|
||||
}
|
||||
if (!comp.IsNull()) {
|
||||
Part::Feature* pcFeature = static_cast<Part::Feature*>(
|
||||
auto pcFeature = dynamic_cast<Part::Feature*>(
|
||||
document->addObject("Part::Feature", k.c_str()));
|
||||
pcFeature->Shape.setValue(comp);
|
||||
}
|
||||
@@ -530,7 +519,7 @@ void ImpExpDxfRead::AddGraphics() const
|
||||
//******************************************************************************
|
||||
// writing
|
||||
|
||||
void gPntToTuple(double* result, gp_Pnt& p)
|
||||
void gPntToTuple(double result[3], gp_Pnt& p)
|
||||
{
|
||||
result[0] = p.X();
|
||||
result[1] = p.Y();
|
||||
@@ -574,9 +563,9 @@ void ImpExpDxfWrite::exportShape(const TopoDS_Shape input)
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
double f = adapt.FirstParameter();
|
||||
double l = adapt.LastParameter();
|
||||
gp_Pnt s = adapt.Value(f);
|
||||
gp_Pnt start = adapt.Value(f);
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
if (fabs(l - f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
if (fabs(l - f) > 1.0 && start.SquareDistance(e) < 0.001) {
|
||||
exportCircle(adapt);
|
||||
}
|
||||
else {
|
||||
@@ -586,9 +575,9 @@ void ImpExpDxfWrite::exportShape(const TopoDS_Shape input)
|
||||
else if (adapt.GetType() == GeomAbs_Ellipse) {
|
||||
double f = adapt.FirstParameter();
|
||||
double l = adapt.LastParameter();
|
||||
gp_Pnt s = adapt.Value(f);
|
||||
gp_Pnt start = adapt.Value(f);
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
if (fabs(l - f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
if (fabs(l - f) > 1.0 && start.SquareDistance(e) < 0.001) {
|
||||
if (m_polyOverride) {
|
||||
if (m_version >= 14) {
|
||||
exportLWPoly(adapt);
|
||||
|
||||
@@ -39,19 +39,25 @@ namespace Import
|
||||
class ImportExport ImpExpDxfRead: public CDxfRead
|
||||
{
|
||||
public:
|
||||
ImpExpDxfRead(std::string filepath, App::Document* pcDoc);
|
||||
ImpExpDxfRead(const std::string& filepath, App::Document* pcDoc);
|
||||
|
||||
// CDxfRead's virtual functions
|
||||
void OnReadLine(const double* s, const double* e, bool hidden) override;
|
||||
void OnReadPoint(const double* s) override;
|
||||
void OnReadText(const double* point,
|
||||
const double height,
|
||||
const char* text,
|
||||
const double rotation) override;
|
||||
void
|
||||
OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden) override;
|
||||
void OnReadCircle(const double* s, const double* c, bool dir, bool hidden) override;
|
||||
void OnReadEllipse(const double* c,
|
||||
void OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool hidden) override;
|
||||
void OnReadPoint(const Base::Vector3d& start) override;
|
||||
void OnReadText(const Base::Vector3d& point,
|
||||
double height,
|
||||
const std::string& text,
|
||||
double rotation) override;
|
||||
void OnReadArc(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
const Base::Vector3d& center,
|
||||
bool dir,
|
||||
bool hidden) override;
|
||||
void OnReadCircle(const Base::Vector3d& start,
|
||||
const Base::Vector3d& center,
|
||||
bool dir,
|
||||
bool hidden) override;
|
||||
void OnReadEllipse(const Base::Vector3d& center,
|
||||
double major_radius,
|
||||
double minor_radius,
|
||||
double rotation,
|
||||
@@ -59,13 +65,13 @@ public:
|
||||
double end_angle,
|
||||
bool dir) override;
|
||||
void OnReadSpline(struct SplineData& sd) override;
|
||||
void OnReadInsert(const double* point,
|
||||
const double* scale,
|
||||
const char* name,
|
||||
void OnReadInsert(const Base::Vector3d& point,
|
||||
const Base::Vector3d& scale,
|
||||
const std::string& name,
|
||||
double rotation) override;
|
||||
void OnReadDimension(const double* s,
|
||||
const double* e,
|
||||
const double* point,
|
||||
void OnReadDimension(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
const Base::Vector3d& point,
|
||||
double rotation) override;
|
||||
void AddGraphics() const override;
|
||||
|
||||
@@ -77,24 +83,26 @@ public:
|
||||
{
|
||||
return m_optionSource;
|
||||
}
|
||||
void setOptionSource(std::string s)
|
||||
void setOptionSource(const std::string& sourceName)
|
||||
{
|
||||
m_optionSource = s;
|
||||
m_optionSource = sourceName;
|
||||
}
|
||||
void setOptions();
|
||||
|
||||
private:
|
||||
gp_Pnt makePoint(const double point3d[3]) const;
|
||||
static gp_Pnt makePoint(const Base::Vector3d& point3d)
|
||||
{
|
||||
return {point3d.x, point3d.y, point3d.z};
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void ApplyGuiStyles(Part::Feature*)
|
||||
virtual void ApplyGuiStyles(Part::Feature* /*object*/)
|
||||
{}
|
||||
virtual void ApplyGuiStyles(App::FeaturePython*)
|
||||
virtual void ApplyGuiStyles(App::FeaturePython* /*object*/)
|
||||
{}
|
||||
App::Document* document;
|
||||
bool optionGroupLayers;
|
||||
bool optionImportAnnotations;
|
||||
double optionScaling;
|
||||
std::map<std::string, std::vector<Part::TopoShape*>> layers;
|
||||
std::string m_optionSource;
|
||||
};
|
||||
@@ -103,9 +111,13 @@ class ImportExport ImpExpDxfWrite: public CDxfWrite
|
||||
{
|
||||
public:
|
||||
explicit ImpExpDxfWrite(std::string filepath);
|
||||
ImpExpDxfWrite(const ImpExpDxfWrite&) = delete;
|
||||
ImpExpDxfWrite(const ImpExpDxfWrite&&) = delete;
|
||||
ImpExpDxfWrite& operator=(const ImpExpDxfWrite&) = delete;
|
||||
ImpExpDxfWrite& operator=(const ImpExpDxfWrite&&) = delete;
|
||||
~ImpExpDxfWrite();
|
||||
|
||||
void exportShape(const TopoDS_Shape input);
|
||||
void exportShape(TopoDS_Shape input);
|
||||
std::string getOptionSource()
|
||||
{
|
||||
return m_optionSource;
|
||||
@@ -129,8 +141,8 @@ public:
|
||||
int type);
|
||||
void exportAngularDim(Base::Vector3d textLocn,
|
||||
Base::Vector3d lineLocn,
|
||||
Base::Vector3d extLine1Start,
|
||||
Base::Vector3d extLine2Start,
|
||||
Base::Vector3d extLine1End,
|
||||
Base::Vector3d extLine2End,
|
||||
Base::Vector3d apexPoint,
|
||||
char* dimText);
|
||||
void exportRadialDim(Base::Vector3d centerPoint,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@
|
||||
// This program is released under the BSD license. See the file COPYING for details.
|
||||
// modified 2018 wandererfan
|
||||
|
||||
#ifndef _dxf_h_
|
||||
#define _dxf_h_
|
||||
#ifndef Included_dxf_h_
|
||||
#define Included_dxf_h_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4251)
|
||||
@@ -26,39 +26,93 @@
|
||||
#include <App/Color.h>
|
||||
#include <Mod/Import/ImportGlobal.h>
|
||||
|
||||
// For some reason Cpplint complains about some of the categories used by Clang-tidy
|
||||
// However, cpplint also does not seem to use NOLINTE BEGIN and NOLINT END so we must use
|
||||
// NOLINT NEXT LINE on each occurrence. [spaces added to avoid being seen by lint]
|
||||
using ColorIndex_t = int; // DXF color index
|
||||
|
||||
typedef int ColorIndex_t; // DXF color index
|
||||
|
||||
typedef enum
|
||||
// The C++ version we use does not support designated initiailzers, so we have a class to set this
|
||||
// up
|
||||
class DxfUnits
|
||||
{
|
||||
eUnspecified = 0, // Unspecified (No units)
|
||||
eInches,
|
||||
eFeet,
|
||||
eMiles,
|
||||
eMillimeters,
|
||||
eCentimeters,
|
||||
eMeters,
|
||||
eKilometers,
|
||||
eMicroinches,
|
||||
eMils,
|
||||
eYards,
|
||||
eAngstroms,
|
||||
eNanometers,
|
||||
eMicrons,
|
||||
eDecimeters,
|
||||
eDekameters,
|
||||
eHectometers,
|
||||
eGigameters,
|
||||
eAstronomicalUnits,
|
||||
eLightYears,
|
||||
eParsecs
|
||||
} eDxfUnits_t;
|
||||
public:
|
||||
using eDxfUnits_t = enum {
|
||||
eUnspecified = 0, // Unspecified (No units)
|
||||
eInches,
|
||||
eFeet,
|
||||
eMiles,
|
||||
eMillimeters,
|
||||
eCentimeters,
|
||||
eMeters,
|
||||
eKilometers,
|
||||
eMicroinches,
|
||||
eMils,
|
||||
eYards,
|
||||
eAngstroms,
|
||||
eNanometers,
|
||||
eMicrons,
|
||||
eDecimeters,
|
||||
eDekameters,
|
||||
eHectometers,
|
||||
eGigameters,
|
||||
eAstronomicalUnits,
|
||||
eLightYears,
|
||||
eParsecs,
|
||||
kMaxUnit
|
||||
};
|
||||
|
||||
private:
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
|
||||
DxfUnits()
|
||||
{
|
||||
// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
|
||||
m_factors[eInches] = 25.4;
|
||||
m_factors[eFeet] = 25.4 * 12;
|
||||
m_factors[eMiles] = 1609344.0;
|
||||
m_factors[eMillimeters] = 1.0;
|
||||
m_factors[eCentimeters] = 10.0;
|
||||
m_factors[eMeters] = 1000.0;
|
||||
m_factors[eKilometers] = 1000000.0;
|
||||
m_factors[eMicroinches] = 25.4 / 1000.0;
|
||||
m_factors[eMils] = 25.4 / 1000.0;
|
||||
m_factors[eYards] = 3 * 12 * 25.4;
|
||||
m_factors[eAngstroms] = 0.0000001;
|
||||
m_factors[eNanometers] = 0.000001;
|
||||
m_factors[eMicrons] = 0.001;
|
||||
m_factors[eDecimeters] = 100.0;
|
||||
m_factors[eDekameters] = 10000.0;
|
||||
m_factors[eHectometers] = 100000.0;
|
||||
m_factors[eGigameters] = 1000000000000.0;
|
||||
m_factors[eAstronomicalUnits] = 149597870690000.0;
|
||||
m_factors[eLightYears] = 9454254955500000000.0;
|
||||
m_factors[eParsecs] = 30856774879000000000.0;
|
||||
// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
|
||||
}
|
||||
|
||||
public:
|
||||
static double Factor(eDxfUnits_t enumValue)
|
||||
{
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index)
|
||||
return Instance.m_factors[enumValue];
|
||||
}
|
||||
static bool IsValid(eDxfUnits_t enumValue)
|
||||
{
|
||||
return enumValue > eUnspecified && enumValue <= eParsecs;
|
||||
}
|
||||
|
||||
private:
|
||||
static const DxfUnits Instance;
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
|
||||
double m_factors[kMaxUnit];
|
||||
};
|
||||
|
||||
// spline data for reading
|
||||
struct SplineData
|
||||
{
|
||||
double norm[3] = {0, 0, 0};
|
||||
Base::Vector3d norm;
|
||||
int degree = 0;
|
||||
int knots = 0;
|
||||
int control_points = 0;
|
||||
@@ -119,8 +173,45 @@ struct LWPolyDataOut
|
||||
std::vector<double> Bulge;
|
||||
point3D Extr;
|
||||
};
|
||||
typedef enum
|
||||
{
|
||||
using eDXFGroupCode_t = enum {
|
||||
eObjectType = 0,
|
||||
ePrimaryText = 1,
|
||||
eName = 2,
|
||||
eExtraText = 3,
|
||||
eLinetypeName = 6,
|
||||
eTextStyleName = 7,
|
||||
eLayerName = 8,
|
||||
eVariableName = 9,
|
||||
ePrimaryPoint = 10,
|
||||
ePoint2 = 11,
|
||||
ePoint3 = 12,
|
||||
ePoint4 = 13,
|
||||
ePoint5 = 14,
|
||||
eFloat1 = 40,
|
||||
eFloat2 = 41,
|
||||
eFloat3 = 42,
|
||||
eFloat4 = 43,
|
||||
eAngleDegrees1 = 50,
|
||||
eAngleDegrees2 = 51,
|
||||
eColor = 62,
|
||||
eCoordinateSpace = 67,
|
||||
eInteger1 = 70,
|
||||
eInteger2 = 71,
|
||||
eInteger3 = 72,
|
||||
eInteger4 = 73,
|
||||
eInteger5 = 74,
|
||||
eUCSOrigin = 110,
|
||||
eUCSXDirection = 111,
|
||||
eUCSYDirection = 112,
|
||||
eExtrusionDirection = 210,
|
||||
|
||||
// The following apply to points and directions in text DXF files to identify the three
|
||||
// coordinates
|
||||
eXOffset = 0,
|
||||
eYOffset = 10,
|
||||
eZOffset = 20
|
||||
};
|
||||
using eDXFVersion_t = enum {
|
||||
RUnknown,
|
||||
ROlder,
|
||||
R10,
|
||||
@@ -134,7 +225,20 @@ typedef enum
|
||||
R2013,
|
||||
R2018,
|
||||
RNewer,
|
||||
} eDXFVersion_t;
|
||||
};
|
||||
using eDimensionType_t = enum {
|
||||
eLinear = 0, // Rotated, Horizontal, or Vertical
|
||||
eAligned = 1,
|
||||
eAngular = 2,
|
||||
eDiameter = 3,
|
||||
eRadius = 4,
|
||||
eAngular3Point = 5,
|
||||
eOrdinate = 6,
|
||||
eTypeMask = 0xF,
|
||||
eOnlyBlockReference = 32,
|
||||
eOrdianetIsXType = 64,
|
||||
eUserTextLocation = 128
|
||||
};
|
||||
//********************
|
||||
|
||||
class ImportExport CDxfWrite
|
||||
@@ -148,38 +252,45 @@ private:
|
||||
std::ostringstream* m_ssLayer;
|
||||
|
||||
protected:
|
||||
void putLine(const Base::Vector3d s,
|
||||
const Base::Vector3d e,
|
||||
static Base::Vector3d toVector3d(const double* coordinatesXYZ)
|
||||
{
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
return Base::Vector3d(coordinatesXYZ[0], coordinatesXYZ[1], coordinatesXYZ[2]);
|
||||
}
|
||||
|
||||
void putLine(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
std::ostringstream* outStream,
|
||||
const std::string handle,
|
||||
const std::string ownerHandle);
|
||||
const std::string& handle,
|
||||
const std::string& ownerHandle);
|
||||
void putText(const char* text,
|
||||
const Base::Vector3d location1,
|
||||
const Base::Vector3d location2,
|
||||
const double height,
|
||||
const int horizJust,
|
||||
const Base::Vector3d& location1,
|
||||
const Base::Vector3d& location2,
|
||||
double height,
|
||||
int horizJust,
|
||||
std::ostringstream* outStream,
|
||||
const std::string handle,
|
||||
const std::string ownerHandle);
|
||||
void putArrow(Base::Vector3d arrowPos,
|
||||
Base::Vector3d barb1Pos,
|
||||
Base::Vector3d barb2Pos,
|
||||
const std::string& handle,
|
||||
const std::string& ownerHandle);
|
||||
void putArrow(Base::Vector3d& arrowPos,
|
||||
Base::Vector3d& barb1Pos,
|
||||
Base::Vector3d& barb2Pos,
|
||||
std::ostringstream* outStream,
|
||||
const std::string handle,
|
||||
const std::string ownerHandle);
|
||||
const std::string& handle,
|
||||
const std::string& ownerHandle);
|
||||
|
||||
//! copy boiler plate file
|
||||
std::string getPlateFile(std::string fileSpec);
|
||||
void setDataDir(std::string s)
|
||||
void setDataDir(const std::string& dirName)
|
||||
{
|
||||
m_dataDir = s;
|
||||
m_dataDir = dirName;
|
||||
}
|
||||
std::string getHandle();
|
||||
std::string getEntityHandle();
|
||||
std::string getLayerHandle();
|
||||
std::string getBlockHandle();
|
||||
std::string getBlkRecordHandle();
|
||||
|
||||
// NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||
std::string m_optionSource;
|
||||
int m_version;
|
||||
int m_handle;
|
||||
@@ -199,15 +310,20 @@ protected:
|
||||
std::vector<std::string> m_layerList;
|
||||
std::vector<std::string> m_blockList;
|
||||
std::vector<std::string> m_blkRecordList;
|
||||
// NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||
|
||||
public:
|
||||
explicit CDxfWrite(const char* filepath);
|
||||
CDxfWrite(const CDxfWrite&) = delete;
|
||||
CDxfWrite(const CDxfWrite&&) = delete;
|
||||
CDxfWrite& operator=(const CDxfWrite&) = delete;
|
||||
CDxfWrite& operator=(const CDxfWrite&&) = delete;
|
||||
~CDxfWrite();
|
||||
|
||||
void init();
|
||||
void endRun();
|
||||
|
||||
bool Failed()
|
||||
bool Failed() const
|
||||
{
|
||||
return m_fail;
|
||||
}
|
||||
@@ -217,37 +333,39 @@ public:
|
||||
{
|
||||
return m_layerName;
|
||||
}
|
||||
void setLayerName(std::string s);
|
||||
void setVersion(int v)
|
||||
void setLayerName(std::string name);
|
||||
void setVersion(int version)
|
||||
{
|
||||
m_version = v;
|
||||
m_version = version;
|
||||
}
|
||||
void setPolyOverride(bool b)
|
||||
void setPolyOverride(bool setting)
|
||||
{
|
||||
m_polyOverride = b;
|
||||
m_polyOverride = setting;
|
||||
}
|
||||
void addBlockName(std::string s, std::string blkRecordHandle);
|
||||
void addBlockName(const std::string& name, const std::string& blkRecordHandle);
|
||||
|
||||
void writeLine(const double* s, const double* e);
|
||||
void writeLine(const double* start, const double* end);
|
||||
void writePoint(const double*);
|
||||
void writeArc(const double* s, const double* e, const double* c, bool dir);
|
||||
void writeEllipse(const double* c,
|
||||
void writeArc(const double* start, const double* end, const double* center, bool dir);
|
||||
void writeEllipse(const double* center,
|
||||
double major_radius,
|
||||
double minor_radius,
|
||||
double rotation,
|
||||
double start_angle,
|
||||
double end_angle,
|
||||
bool endIsCW);
|
||||
void writeCircle(const double* c, double radius);
|
||||
void writeCircle(const double* center, double radius);
|
||||
void writeSpline(const SplineDataOut& sd);
|
||||
void writeLWPolyLine(const LWPolyDataOut& pd);
|
||||
void writePolyline(const LWPolyDataOut& pd);
|
||||
// NOLINTNEXTLINE(readability/nolint)
|
||||
// NOLINTNEXTLINE(readability-identifier-length)
|
||||
void writeVertex(double x, double y, double z);
|
||||
void writeText(const char* text,
|
||||
const double* location1,
|
||||
const double* location2,
|
||||
const double height,
|
||||
const int horizJust);
|
||||
double height,
|
||||
int horizJust);
|
||||
void writeLinearDim(const double* textMidPoint,
|
||||
const double* lineDefPoint,
|
||||
const double* extLine1,
|
||||
@@ -312,36 +430,50 @@ class ImportExport CDxfRead
|
||||
{
|
||||
private:
|
||||
// Low-level reader members
|
||||
std::ifstream* m_ifs;
|
||||
int m_record_type = 0;
|
||||
char m_record_data[1024] = "";
|
||||
std::ifstream* m_ifs; // TODO: gsl::owner<ifstream>
|
||||
eDXFGroupCode_t m_record_type = eObjectType;
|
||||
std::string m_record_data;
|
||||
bool m_not_eof = true;
|
||||
int m_line = 0;
|
||||
bool m_repeat_last_record = false;
|
||||
|
||||
// file-level options/properties
|
||||
eDxfUnits_t m_eUnits = eMillimeters;
|
||||
bool m_measurement_inch = false;
|
||||
// The scaling from DXF units to millimetres.
|
||||
// This does not include the dxfScaling option
|
||||
// This has the value 0.0 if no units have been specified.
|
||||
// If it is still 0 after reading the HEADER section, it iw set to comething sensible.
|
||||
double m_unitScalingFactor = 0.0;
|
||||
|
||||
protected:
|
||||
// An additional scaling factor which can be modified before readDXF is called, and will be
|
||||
// incorporated into m_unitScalingFactor.
|
||||
void SetAdditionalScaling(double scaling)
|
||||
{
|
||||
m_additionalScaling = scaling <= 0.0 ? 1.0 : scaling;
|
||||
}
|
||||
|
||||
private:
|
||||
double m_additionalScaling = 1.0;
|
||||
|
||||
// The following provide a state when reading any entity: If m_block_name is not empty the
|
||||
// entity is in a BLOCK being defined, and LayerName() will return "BLOCKS xxxx" where xxxx is
|
||||
// the block name. Otherwise m_layer_name will be the layer name from the entity records
|
||||
// (default to "0") and LayerName() will return "ENTITIES xxxx" where xxxx is the layer name.
|
||||
// This is clunky but it is a non-private interface and so difficult to change.
|
||||
char m_layer_name[1024] = "0";
|
||||
char m_block_name[1024] = "";
|
||||
std::string m_layer_name;
|
||||
std::string m_block_name;
|
||||
|
||||
|
||||
// Error-handling control
|
||||
bool m_ignore_errors = true;
|
||||
bool m_fail = false;
|
||||
|
||||
std::map<std::string, ColorIndex_t>
|
||||
m_layer_ColorIndex_map; // Mapping from layer name -> layer color index
|
||||
// Mapping from layer name -> layer color index
|
||||
std::map<std::string, ColorIndex_t> m_layer_ColorIndex_map;
|
||||
const ColorIndex_t ColorBylayer = 256;
|
||||
const ColorIndex_t ColorByBlock = 0;
|
||||
|
||||
// Readers for various parts of the DXF file.
|
||||
bool ReadSection();
|
||||
// Section readers (sections are identified by the type-2 (name) record they start with and each
|
||||
// has its own reader function
|
||||
bool ReadHeaderSection();
|
||||
@@ -351,6 +483,12 @@ private:
|
||||
|
||||
bool ReadIgnoredSection();
|
||||
|
||||
// The Header section consists of multipel variables, only a few of which we give special
|
||||
// handling.
|
||||
bool ReadVariable();
|
||||
bool ReadVersion();
|
||||
bool ReadDWGCodePage();
|
||||
|
||||
// The Tables section consists of several tables (again identified by their type-2 record asfter
|
||||
// th 0-TABLE record) each with its own reader
|
||||
bool ReadLayerTable();
|
||||
@@ -359,7 +497,6 @@ private:
|
||||
// inline-defined to.
|
||||
bool ReadIgnoredTable();
|
||||
|
||||
bool ReadUnits();
|
||||
bool ReadLayer();
|
||||
|
||||
bool ReadEntity(); // Identify entity type and read it
|
||||
@@ -373,134 +510,181 @@ private:
|
||||
bool ReadSpline();
|
||||
bool ReadLwPolyLine();
|
||||
bool ReadPolyLine();
|
||||
typedef struct
|
||||
struct VertexInfo
|
||||
{
|
||||
double location[3];
|
||||
double bulge;
|
||||
} VertexInfo;
|
||||
Base::Vector3d location;
|
||||
double bulge = 0;
|
||||
};
|
||||
|
||||
bool OnReadPolyline(std::list<VertexInfo>&, int flags);
|
||||
void OnReadArc(double start_angle,
|
||||
double end_angle,
|
||||
double radius,
|
||||
const double* c,
|
||||
const Base::Vector3d& center,
|
||||
double z_extrusion_dir,
|
||||
bool hidden);
|
||||
void OnReadCircle(const double* c, double radius, bool hidden);
|
||||
void OnReadEllipse(const double* c,
|
||||
const double* m,
|
||||
void OnReadCircle(const Base::Vector3d& center, double radius, bool hidden);
|
||||
void OnReadEllipse(const Base::Vector3d& center,
|
||||
const Base::Vector3d& majorAxisEnd,
|
||||
double ratio,
|
||||
double start_angle,
|
||||
double end_angle);
|
||||
bool ReadInsert();
|
||||
bool ReadDimension();
|
||||
bool ReadUnknownEntity();
|
||||
|
||||
// Helper for reading common attributes for entities
|
||||
void InitializeAttributes();
|
||||
void InitializeCommonEntityAttributes();
|
||||
void Setup3DVectorAttribute(int x_record_type, double destination[3]);
|
||||
void SetupScaledDoubleAttribute(int record_type, double& destination);
|
||||
void SetupScaledDoubleIntoList(int record_type, std::list<double>& destination);
|
||||
void Setup3DCoordinatesIntoLists(int x_record_type,
|
||||
void Setup3DVectorAttribute(eDXFGroupCode_t x_record_type, Base::Vector3d& destination);
|
||||
void SetupScaledDoubleAttribute(eDXFGroupCode_t record_type, double& destination);
|
||||
void SetupScaledDoubleIntoList(eDXFGroupCode_t record_type, std::list<double>& destination);
|
||||
void Setup3DCoordinatesIntoLists(eDXFGroupCode_t x_record_type,
|
||||
std::list<double>& x_destination,
|
||||
std::list<double>& y_destination,
|
||||
std::list<double>& z_destination);
|
||||
void SetupStringAttribute(int record_type, char* destination);
|
||||
void SetupStringAttribute(int record_type, std::string& destination);
|
||||
void SetupStringAttribute(eDXFGroupCode_t record_type, std::string& destination);
|
||||
std::map<int, std::pair<void (*)(CDxfRead*, void*), void*>> m_coordinate_attributes;
|
||||
static void ProcessScaledDouble(CDxfRead* object, void* target);
|
||||
static void ProcessScaledDoubleIntoList(CDxfRead* object, void* target);
|
||||
static void ProcessString(CDxfRead* object, void* target);
|
||||
static void ProcessStdString(CDxfRead* object, void* target);
|
||||
// For all types T where strean >> x and x = 0 works
|
||||
template<typename T>
|
||||
void SetupValueAttribute(int record_type, T& target);
|
||||
void SetupValueAttribute(eDXFGroupCode_t record_type, T& destination);
|
||||
// TODO: Once all compilers used for FreeCAD support class-level template specializations,
|
||||
// SetupValueAttribute could have specializations and replace SetupStringAttribute etc.
|
||||
// The template specialization is required to handle the (char *) case, which would
|
||||
// otherwise try to read the actual pointer from the stream, or... what?
|
||||
// The specialization would also handle the default value when it cannot be zero.
|
||||
template<typename T>
|
||||
static void ProcessValue(CDxfRead* object, void* target);
|
||||
static void ProcessValue(CDxfRead* object, void* target)
|
||||
{
|
||||
ParseValue<T>(object, target);
|
||||
}
|
||||
template<typename T>
|
||||
static bool ParseValue(CDxfRead* object, void* target);
|
||||
|
||||
bool ProcessAttribute();
|
||||
void ProcessAllAttributes();
|
||||
|
||||
bool ReadBlockInfo();
|
||||
bool ReadVersion();
|
||||
bool ReadDWGCodePage();
|
||||
bool ResolveEncoding();
|
||||
|
||||
bool get_next_record();
|
||||
void repeat_last_record();
|
||||
|
||||
bool (CDxfRead::*stringToUTF8)(std::string&) const = &CDxfRead::UTF8ToUTF8;
|
||||
|
||||
protected:
|
||||
// common entity properties. Some properties are accumulated local to the reader method and
|
||||
// passed to the ReadXxxx virtual method. Others are collected here as private values and also
|
||||
// passed to ReadXxxx. Finally some of the attributes are accessed using references to
|
||||
// public/protected fields or methods (such as LayerName()). Altogether a bit of a mishmash.
|
||||
// NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||
ColorIndex_t m_ColorIndex = 0;
|
||||
char m_LineType[1024] = "";
|
||||
std::string m_LineType;
|
||||
eDXFVersion_t m_version = RUnknown; // Version from $ACADVER variable in DXF
|
||||
const char* (CDxfRead::*stringToUTF8)(const char*) const = &CDxfRead::UTF8ToUTF8;
|
||||
// Although this is called "ImportWarning" it is just a wrapper to write a warning eithout any
|
||||
// NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||
|
||||
// Although this is called "ImportError" it is just a wrapper to write a warning eithout any
|
||||
// additional information such as a line number and as such, may be split into a basic
|
||||
// message-writer and something that adds a line number.
|
||||
//
|
||||
// The "Developer" methods stick a line break into the output window.
|
||||
// The "User" methods show up in the notification popup window.
|
||||
// "Critical" causes a popup messagebox
|
||||
// "Warnings" show up in yellow in the output window and with a warning icon in the notification
|
||||
// popup "Error" show up in red in the output window and with an error icon in the notification
|
||||
// popup "Notification" show up in black in the output window and an information icon in the
|
||||
// notification popup "Log" goes to a log somewhere and not to the screen/user at all
|
||||
|
||||
template<typename... args>
|
||||
void ImportError(const char* format, args... argValues) const
|
||||
void ImportError(const char* format, args&&... argValues) const
|
||||
{
|
||||
Base::ConsoleSingleton::Instance().Warning(format, argValues...);
|
||||
Base::ConsoleSingleton::Instance().Warning(format, std::forward<args>(argValues)...);
|
||||
}
|
||||
void UnsupportedFeature(const char* format, ...);
|
||||
template<typename... args>
|
||||
void ImportObservation(const char* format, args&&... argValues) const
|
||||
{
|
||||
Base::ConsoleSingleton::Instance().Message(format, std::forward<args>(argValues)...);
|
||||
}
|
||||
template<typename... args>
|
||||
void UnsupportedFeature(const char* format, args&&... argValues);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::pair<int, int>> m_unsupportedFeaturesNoted;
|
||||
const std::string* m_CodePage =
|
||||
nullptr; // Code Page name from $DWGCODEPAGE or null if none/not read yet
|
||||
std::string m_CodePage; // Code Page name from $DWGCODEPAGE or null if none/not read yet
|
||||
// The following was going to be python's canonical name for the encoding, but this is (a) not
|
||||
// easily found and (b) does not speed up finding the encoding object.
|
||||
const std::string* m_encoding =
|
||||
nullptr; // A name for the encoding implied by m_version and m_CodePage
|
||||
const char* UTF8ToUTF8(const char* encoded) const;
|
||||
const char* GeneralToUTF8(const char* encoded) const;
|
||||
std::string m_encoding; // A name for the encoding implied by m_version and m_CodePage
|
||||
bool UTF8ToUTF8(std::string& encoded) const;
|
||||
bool GeneralToUTF8(std::string& encoded) const;
|
||||
|
||||
// Compare with specific object name for eObjectType records
|
||||
bool IsObjectName(const char* testName) const
|
||||
{
|
||||
return m_record_data == testName;
|
||||
}
|
||||
// Compare with specific variable name for eVariableName records
|
||||
bool IsVariableName(const char* testName) const
|
||||
{
|
||||
return m_record_data == testName;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit CDxfRead(const char* filepath); // this opens the file
|
||||
virtual ~CDxfRead(); // this closes the file
|
||||
explicit CDxfRead(const std::string& filepath); // this opens the file
|
||||
CDxfRead(const CDxfRead&) = delete;
|
||||
CDxfRead(const CDxfRead&&) = delete;
|
||||
CDxfRead& operator=(const CDxfRead&) = delete;
|
||||
CDxfRead& operator=(const CDxfRead&&) = delete;
|
||||
virtual ~CDxfRead(); // this closes the file
|
||||
|
||||
bool Failed()
|
||||
bool Failed() const
|
||||
{
|
||||
return m_fail;
|
||||
}
|
||||
void DoRead(
|
||||
const bool ignore_errors = false); // this reads the file and calls the following functions
|
||||
void
|
||||
DoRead(bool ignore_errors = false); // this reads the file and calls the following functions
|
||||
|
||||
double mm(double value) const;
|
||||
private:
|
||||
double mm(double value) const
|
||||
{
|
||||
if (m_unitScalingFactor == 0.0) {
|
||||
// No scaling factor has been specified.
|
||||
// TODO: Resolve this once we know the HEADER is complete
|
||||
return value;
|
||||
}
|
||||
return m_unitScalingFactor * value;
|
||||
}
|
||||
|
||||
public:
|
||||
bool IgnoreErrors() const
|
||||
{
|
||||
return (m_ignore_errors);
|
||||
}
|
||||
|
||||
virtual void OnReadLine(const double* /*s*/, const double* /*e*/, bool /*hidden*/)
|
||||
virtual void
|
||||
OnReadLine(const Base::Vector3d& /*start*/, const Base::Vector3d& /*end*/, bool /*hidden*/)
|
||||
{}
|
||||
virtual void OnReadPoint(const double* /*s*/)
|
||||
virtual void OnReadPoint(const Base::Vector3d& /*start*/)
|
||||
{}
|
||||
virtual void OnReadText(const double* /*point*/,
|
||||
virtual void OnReadText(const Base::Vector3d& /*point*/,
|
||||
const double /*height*/,
|
||||
const char* /*text*/,
|
||||
const std::string& /*text*/,
|
||||
const double /*rotation*/)
|
||||
{}
|
||||
virtual void OnReadArc(const double* /*s*/,
|
||||
const double* /*e*/,
|
||||
const double* /*c*/,
|
||||
virtual void OnReadArc(const Base::Vector3d& /*start*/,
|
||||
const Base::Vector3d& /*end*/,
|
||||
const Base::Vector3d& /*center*/,
|
||||
bool /*dir*/,
|
||||
bool /*hidden*/)
|
||||
{}
|
||||
virtual void
|
||||
OnReadCircle(const double* /*s*/, const double* /*c*/, bool /*dir*/, bool /*hidden*/)
|
||||
virtual void OnReadCircle(const Base::Vector3d& /*start*/,
|
||||
const Base::Vector3d& /*center*/,
|
||||
bool /*dir*/,
|
||||
bool /*hidden*/)
|
||||
{}
|
||||
virtual void OnReadEllipse(const double* /*c*/,
|
||||
virtual void OnReadEllipse(const Base::Vector3d& /*center*/,
|
||||
double /*major_radius*/,
|
||||
double /*minor_radius*/,
|
||||
double /*rotation*/,
|
||||
@@ -510,14 +694,14 @@ public:
|
||||
{}
|
||||
virtual void OnReadSpline(struct SplineData& /*sd*/)
|
||||
{}
|
||||
virtual void OnReadInsert(const double* /*point*/,
|
||||
const double* /*scale*/,
|
||||
const char* /*name*/,
|
||||
virtual void OnReadInsert(const Base::Vector3d& /*point*/,
|
||||
const Base::Vector3d& /*scale*/,
|
||||
const std::string& /*name*/,
|
||||
double /*rotation*/)
|
||||
{}
|
||||
virtual void OnReadDimension(const double* /*s*/,
|
||||
const double* /*e*/,
|
||||
const double* /*point*/,
|
||||
virtual void OnReadDimension(const Base::Vector3d& /*start*/,
|
||||
const Base::Vector3d& /*end*/,
|
||||
const Base::Vector3d& /*point*/,
|
||||
double /*rotation*/)
|
||||
{}
|
||||
virtual void AddGraphics() const
|
||||
|
||||
@@ -40,8 +40,10 @@ public:
|
||||
ImpExpDxfReadGui(std::string filepath, App::Document* pcDoc);
|
||||
|
||||
protected:
|
||||
void ApplyGuiStyles(Part::Feature*);
|
||||
void ApplyGuiStyles(App::FeaturePython*);
|
||||
void ApplyGuiStyles(Part::Feature* object) override;
|
||||
void ApplyGuiStyles(App::FeaturePython* object) override;
|
||||
|
||||
private:
|
||||
Gui::Document* GuiDocument;
|
||||
};
|
||||
} // namespace ImportGui
|
||||
|
||||
@@ -7,25 +7,31 @@
|
||||
|
||||
AreaDxfRead::AreaDxfRead(CArea* area, const char* filepath):CDxfRead(filepath), m_area(area){}
|
||||
|
||||
void AreaDxfRead::StartCurveIfNecessary(const double* s)
|
||||
void AreaDxfRead::StartCurveIfNecessary(const Base::Vector3d& startPoint) const
|
||||
{
|
||||
Point ps(s);
|
||||
if((m_area->m_curves.size() == 0) || (m_area->m_curves.back().m_vertices.size() == 0) || (m_area->m_curves.back().m_vertices.back().m_p != ps))
|
||||
Point ps(startPoint.x, startPoint.y);
|
||||
if(m_area->m_curves.empty() || m_area->m_curves.back().m_vertices.empty() || m_area->m_curves.back().m_vertices.back().m_p != ps)
|
||||
{
|
||||
// start a new curve
|
||||
m_area->m_curves.emplace_back();
|
||||
m_area->m_curves.back().m_vertices.push_back(ps);
|
||||
m_area->m_curves.back().m_vertices.emplace_back(ps);
|
||||
}
|
||||
}
|
||||
|
||||
void AreaDxfRead::OnReadLine(const double* s, const double* e, bool /*hidden*/)
|
||||
void AreaDxfRead::OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool /*hidden*/)
|
||||
{
|
||||
StartCurveIfNecessary(s);
|
||||
m_area->m_curves.back().m_vertices.push_back(Point(e));
|
||||
StartCurveIfNecessary(start);
|
||||
m_area->m_curves.back().m_vertices.emplace_back(Point(end.x, end.y));
|
||||
}
|
||||
|
||||
void AreaDxfRead::OnReadArc(const double* s, const double* e, const double* c, bool dir, bool /*hidden*/)
|
||||
void AreaDxfRead::OnReadArc(const Base::Vector3d& start,
|
||||
const Base::Vector3d& end,
|
||||
const Base::Vector3d& center,
|
||||
bool dir,
|
||||
bool /*hidden*/)
|
||||
{
|
||||
StartCurveIfNecessary(s);
|
||||
m_area->m_curves.back().m_vertices.emplace_back(dir?1:0, Point(e), Point(c));
|
||||
StartCurveIfNecessary(start);
|
||||
m_area->m_curves.back().m_vertices.emplace_back(dir ? 1 : 0,
|
||||
Point(end.x, end.y),
|
||||
Point(center.x, center.y));
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ class CArea;
|
||||
class CCurve;
|
||||
|
||||
class AreaDxfRead : public CDxfRead{
|
||||
void StartCurveIfNecessary(const double* s);
|
||||
void StartCurveIfNecessary(const Base::Vector3d& startPoint) const;
|
||||
|
||||
public:
|
||||
CArea* m_area;
|
||||
AreaDxfRead(CArea* area, const char* filepath);
|
||||
|
||||
// AreaDxfRead's virtual functions
|
||||
void OnReadLine(const double* s, const double* e, bool /*hidden*/) override;
|
||||
void OnReadArc(const double* s, const double* e, const double* c, bool dir, bool /*hidden*/) override;
|
||||
void OnReadLine(const Base::Vector3d& start, const Base::Vector3d& end, bool /*hidden*/) override;
|
||||
void OnReadArc(const Base::Vector3d& start, const Base::Vector3d& end, const Base::Vector3d& center, bool dir, bool /*hidden*/) override;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user