diff --git a/src/Mod/Import/App/AppImportPy.cpp b/src/Mod/Import/App/AppImportPy.cpp index da6bc79b26..197d705a2b 100644 --- a/src/Mod/Import/App/AppImportPy.cpp +++ b/src/Mod/Import/App/AppImportPy.cpp @@ -439,7 +439,7 @@ private: std::string filePath; std::string layerName; const char* optionSource = nullptr; - std::string defaultOptions = "User parameter:BaseApp/Preferences/Mod/Import"; + std::string defaultOptions = "User parameter:BaseApp/Preferences/Mod/Draft"; int versionParm = -1; bool versionOverride = false; bool polyOverride = false; @@ -551,7 +551,7 @@ private: std::string filePath; std::string layerName; const char* optionSource = nullptr; - std::string defaultOptions = "User parameter:BaseApp/Preferences/Mod/Import"; + std::string defaultOptions = "User parameter:BaseApp/Preferences/Mod/Draft"; int versionParm = -1; bool versionOverride = false; bool polyOverride = false; diff --git a/src/Mod/Import/App/dxf/ImpExpDxf.cpp b/src/Mod/Import/App/dxf/ImpExpDxf.cpp index 0cbb575308..8fbf5c9c06 100644 --- a/src/Mod/Import/App/dxf/ImpExpDxf.cpp +++ b/src/Mod/Import/App/dxf/ImpExpDxf.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -293,38 +294,43 @@ TopoDS_Wire ImpExpDxfRead::BuildWireFromPolyline(std::list& vertices if (is_closed && vertices.size() > 1) { const VertexInfo& start_vertex = vertices.back(); const VertexInfo& end_vertex = vertices.front(); - TopoDS_Edge edge; - if (start_vertex.bulge == 0.0) { - edge = BRepBuilderAPI_MakeEdge(makePoint(start_vertex.location), - makePoint(end_vertex.location)) - .Edge(); - } - else { - double cot = ((1.0 / start_vertex.bulge) - start_vertex.bulge) / 2.0; - double center_x = ((start_vertex.location.x + end_vertex.location.x) - - (end_vertex.location.y - start_vertex.location.y) * cot) - / 2.0; - double center_y = ((start_vertex.location.y + end_vertex.location.y) - + (end_vertex.location.x - start_vertex.location.x) * cot) - / 2.0; - double center_z = (start_vertex.location.z + end_vertex.location.z) / 2.0; - Base::Vector3d center(center_x, center_y, center_z); + // check if the vertices are coincident (distance < tolerance) + // if they are, the polyline is already closed and we don't need a closing edge + gp_Pnt p0 = makePoint(start_vertex.location); + gp_Pnt p1 = makePoint(end_vertex.location); + double distance = p0.Distance(p1); - gp_Pnt p0 = makePoint(start_vertex.location); - gp_Pnt p1 = makePoint(end_vertex.location); - gp_Dir up(0, 0, 1); - if (start_vertex.bulge < 0) { - up.Reverse(); + if (distance > Precision::Confusion()) { + TopoDS_Edge edge; + + if (start_vertex.bulge == 0.0) { + edge = BRepBuilderAPI_MakeEdge(p0, p1).Edge(); } - gp_Pnt pc = makePoint(center); - gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc)); - if (circle.Radius() > 1e-9) { - edge = BRepBuilderAPI_MakeEdge(circle, p0, p1).Edge(); + else { + double cot = ((1.0 / start_vertex.bulge) - start_vertex.bulge) / 2.0; + double center_x = ((start_vertex.location.x + end_vertex.location.x) + - (end_vertex.location.y - start_vertex.location.y) * cot) + / 2.0; + double center_y = ((start_vertex.location.y + end_vertex.location.y) + + (end_vertex.location.x - start_vertex.location.x) * cot) + / 2.0; + double center_z = (start_vertex.location.z + end_vertex.location.z) / 2.0; + Base::Vector3d center(center_x, center_y, center_z); + + gp_Dir up(0, 0, 1); + if (start_vertex.bulge < 0) { + up.Reverse(); + } + gp_Pnt pc = makePoint(center); + gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc)); + if (circle.Radius() > 1e-9) { + edge = BRepBuilderAPI_MakeEdge(circle, p0, p1).Edge(); + } + } + if (!edge.IsNull()) { + wireBuilder.Add(edge); } - } - if (!edge.IsNull()) { - wireBuilder.Add(edge); } } @@ -1648,7 +1654,7 @@ point3D gPntTopoint3D(gp_Pnt& p) ImpExpDxfWrite::ImpExpDxfWrite(std::string filepath) : CDxfWrite(filepath.c_str()) { - setOptionSource("User parameter:BaseApp/Preferences/Mod/Import"); + setOptionSource("User parameter:BaseApp/Preferences/Mod/Draft"); setOptions(); } @@ -2028,9 +2034,10 @@ void ImpExpDxfWrite::exportLine(BRepAdaptor_Curve& c) writeLine(start, end); } -void ImpExpDxfWrite::exportLWPoly(BRepAdaptor_Curve& c) +// Helper function to discretize a curve into polyline vertices +// Returns true if discretization was successful and pd was populated +bool ImpExpDxfWrite::discretizeCurveToPolyline(BRepAdaptor_Curve& c, LWPolyDataOut& pd) const { - LWPolyDataOut pd; pd.Flag = c.IsClosed(); pd.Elev = 0.0; pd.Thick = 0.0; @@ -2041,14 +2048,35 @@ void ImpExpDxfWrite::exportLWPoly(BRepAdaptor_Curve& c) GCPnts_UniformAbscissa discretizer; discretizer.Initialize(c, optionMaxLength); - std::vector points; - if (discretizer.IsDone() && discretizer.NbPoints() > 0) { - int nbPoints = discretizer.NbPoints(); - for (int i = 1; i <= nbPoints; i++) { - gp_Pnt p = c.Value(discretizer.Parameter(i)); - pd.Verts.push_back(gPntTopoint3D(p)); + + if (!discretizer.IsDone() || discretizer.NbPoints() <= 0) { + return false; + } + + int nbPoints = discretizer.NbPoints(); + // for closed curves, don't include the last point if it duplicates the first + int endIndex = nbPoints; + if (pd.Flag && nbPoints > 1) { + gp_Pnt pFirst = c.Value(discretizer.Parameter(1)); + gp_Pnt pLast = c.Value(discretizer.Parameter(nbPoints)); + if (pFirst.Distance(pLast) < Precision::Confusion()) { + endIndex = nbPoints - 1; } - pd.nVert = discretizer.NbPoints(); + } + + for (int i = 1; i <= endIndex; i++) { + gp_Pnt p = c.Value(discretizer.Parameter(i)); + pd.Verts.push_back(gPntTopoint3D(p)); + } + pd.nVert = static_cast(pd.Verts.size()); + + return true; +} + +void ImpExpDxfWrite::exportLWPoly(BRepAdaptor_Curve& c) +{ + LWPolyDataOut pd; + if (discretizeCurveToPolyline(c, pd)) { writeLWPolyLine(pd); } } @@ -2056,24 +2084,7 @@ void ImpExpDxfWrite::exportLWPoly(BRepAdaptor_Curve& c) void ImpExpDxfWrite::exportPolyline(BRepAdaptor_Curve& c) { LWPolyDataOut pd; - pd.Flag = c.IsClosed(); - pd.Elev = 0.0; - pd.Thick = 0.0; - pd.Extr.x = 0.0; - pd.Extr.y = 0.0; - pd.Extr.z = 1.0; - pd.nVert = 0; - - GCPnts_UniformAbscissa discretizer; - discretizer.Initialize(c, optionMaxLength); - std::vector points; - if (discretizer.IsDone() && discretizer.NbPoints() > 0) { - int nbPoints = discretizer.NbPoints(); - for (int i = 1; i <= nbPoints; i++) { - gp_Pnt p = c.Value(discretizer.Parameter(i)); - pd.Verts.push_back(gPntTopoint3D(p)); - } - pd.nVert = discretizer.NbPoints(); + if (discretizeCurveToPolyline(c, pd)) { writePolyline(pd); } } diff --git a/src/Mod/Import/App/dxf/ImpExpDxf.h b/src/Mod/Import/App/dxf/ImpExpDxf.h index 9054b253a7..c8eb1e3ee3 100644 --- a/src/Mod/Import/App/dxf/ImpExpDxf.h +++ b/src/Mod/Import/App/dxf/ImpExpDxf.h @@ -542,6 +542,9 @@ protected: void exportLWPoly(BRepAdaptor_Curve& c); // LWPolyline not supported in R12? void exportPolyline(BRepAdaptor_Curve& c); + // helper function to discretize a curve into polyline vertices + bool discretizeCurveToPolyline(BRepAdaptor_Curve& c, LWPolyDataOut& pd) const; + // std::string m_optionSource; double optionMaxLength; bool optionPolyLine; diff --git a/src/Mod/Import/App/dxf/dxf.h b/src/Mod/Import/App/dxf/dxf.h index 4f6a1f778a..19e43ea209 100644 --- a/src/Mod/Import/App/dxf/dxf.h +++ b/src/Mod/Import/App/dxf/dxf.h @@ -164,7 +164,7 @@ struct SplineDataOut struct LWPolyDataOut { - double nVert; + int nVert; int Flag; double Width; double Elev;