From 279d156d30b51bc849c4818894d6f63bb4ef84fb Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 10 Aug 2015 19:55:59 -0300 Subject: [PATCH] Draft: Starting a C++ DXF importer - issue #2205 --- src/Mod/Draft/App/AppDraftUtils.cpp | 53 + src/Mod/Draft/App/AppDraftUtilsPy.cpp | 81 ++ src/Mod/Draft/App/CMakeLists.txt | 42 + src/Mod/Draft/App/DraftDxf.cpp | 175 +++ src/Mod/Draft/App/DraftDxf.h | 57 + src/Mod/Draft/App/PreCompiled.cpp | 24 + src/Mod/Draft/App/PreCompiled.h | 58 + src/Mod/Draft/App/dxf.cpp | 1597 +++++++++++++++++++++++++ src/Mod/Draft/App/dxf.h | 157 +++ src/Mod/Draft/CMakeLists.txt | 2 + 10 files changed, 2246 insertions(+) create mode 100644 src/Mod/Draft/App/AppDraftUtils.cpp create mode 100644 src/Mod/Draft/App/AppDraftUtilsPy.cpp create mode 100644 src/Mod/Draft/App/CMakeLists.txt create mode 100644 src/Mod/Draft/App/DraftDxf.cpp create mode 100644 src/Mod/Draft/App/DraftDxf.h create mode 100644 src/Mod/Draft/App/PreCompiled.cpp create mode 100644 src/Mod/Draft/App/PreCompiled.h create mode 100644 src/Mod/Draft/App/dxf.cpp create mode 100644 src/Mod/Draft/App/dxf.h diff --git a/src/Mod/Draft/App/AppDraftUtils.cpp b/src/Mod/Draft/App/AppDraftUtils.cpp new file mode 100644 index 0000000000..0528f44203 --- /dev/null +++ b/src/Mod/Draft/App/AppDraftUtils.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include + +extern struct PyMethodDef DraftUtils_methods[]; + +PyDoc_STRVAR(module_DraftUtils_doc, "The DraftUtils module contains utility functions for the Draft module."); + +/* Python entry */ +extern "C" { + + void DraftUtilsExport initDraftUtils() + { + // load dependent module + try { + Base::Interpreter().loadModule("Part"); + } + catch(const Base::Exception& e) { + PyErr_SetString(PyExc_ImportError, e.what()); + return; + } + PyObject* DraftUtilsModule = Py_InitModule3("DraftUtils", DraftUtils_methods, module_DraftUtils_doc); /* mod name, table ptr */ + Base::Console().Log("Loading DraftUtils module... done\n"); + } + +} // extern "C" diff --git a/src/Mod/Draft/App/AppDraftUtilsPy.cpp b/src/Mod/Draft/App/AppDraftUtilsPy.cpp new file mode 100644 index 0000000000..33d08a3d7f --- /dev/null +++ b/src/Mod/Draft/App/AppDraftUtilsPy.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "DraftDxf.h" + +using namespace DraftUtils; + +static PyObject * readDXF (PyObject *self, PyObject *args) +{ + char* Name; + const char* DocName=0; + bool IgnoreErrors=true; + if (!PyArg_ParseTuple(args, "et|sb","utf-8",&Name,&DocName,&IgnoreErrors)) + return NULL; + std::string EncodedName = std::string(Name); + PyMem_Free(Name); + + Base::FileInfo file(EncodedName.c_str()); + if (!file.exists()) + Py_Error(Base::BaseExceptionFreeCADError, "File doesn't exist"); + App::Document *pcDoc; + if (DocName) + pcDoc = App::GetApplication().getDocument(DocName); + else + pcDoc = App::GetApplication().getActiveDocument(); + if (!pcDoc) + pcDoc = App::GetApplication().newDocument(DocName); + + PY_TRY { + // read the DXF file + DraftDxfRead dxf_file(EncodedName,pcDoc); + dxf_file.DoRead(IgnoreErrors); + pcDoc->recompute(); + } PY_CATCH; + Py_Return; +} + + + + +/* registration table */ +struct PyMethodDef DraftUtils_methods[] = { + + {"readDXF" ,readDXF ,METH_VARARGS, + "readDXF(filename,[document,ignore_errors]): Imports a DXF file into the given document. ignore_errors is True by default."}, + + {NULL, NULL} /* end of table marker */ +}; diff --git a/src/Mod/Draft/App/CMakeLists.txt b/src/Mod/Draft/App/CMakeLists.txt new file mode 100644 index 0000000000..8a4916201d --- /dev/null +++ b/src/Mod/Draft/App/CMakeLists.txt @@ -0,0 +1,42 @@ +if(MSVC) + add_definitions(-DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH) +else(MSVC) + add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H) +endif(MSVC) + + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_BINARY_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} + ${Boost_INCLUDE_DIRS} + ${OCC_INCLUDE_DIR} + ${PYTHON_INCLUDE_DIRS} +) +link_directories(${OCC_LIBRARY_DIR}) + +set(DraftUtils_LIBS + Part + FreeCADApp +) + +SET(DraftUtils_SRCS + AppDraftUtils.cpp + AppDraftUtilsPy.cpp + PreCompiled.cpp + PreCompiled.h + dxf.cpp + dxf.h + DraftDxf.cpp + DraftDxf.h +) + +add_library(DraftUtils SHARED ${DraftUtils_SRCS}) +target_link_libraries(DraftUtils ${DraftUtils_LIBS}) + + +SET_BIN_DIR(DraftUtils DraftUtils /Mod/Draft) +SET_PYTHON_PREFIX_SUFFIX(DraftUtils) + +INSTALL(TARGETS DraftUtils DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/Mod/Draft/App/DraftDxf.cpp b/src/Mod/Draft/App/DraftDxf.cpp new file mode 100644 index 0000000000..f7fd15c937 --- /dev/null +++ b/src/Mod/Draft/App/DraftDxf.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +#endif + +#include "DraftDxf.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace DraftUtils; + +DraftDxfRead::DraftDxfRead(std::string filepath, App::Document *pcDoc) : CDxfRead(filepath.c_str()) +{ + document = pcDoc; + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Draft"); + optionGroupLayers = hGrp->GetBool("groupLayers",false); +} + + +void DraftDxfRead::OnReadLine(const double* s, const double* e, bool hidden) +{ + gp_Pnt p0(s[0], s[1], s[2]); + gp_Pnt p1(e[0], e[1], e[2]); + if (p0.IsEqual(p1,0.00000001)) + return; + BRepBuilderAPI_MakeEdge makeEdge(p0, p1); + TopoDS_Edge edge = makeEdge.Edge(); + AddObject(new Part::TopoShape(edge)); +} + + +void DraftDxfRead::OnReadPoint(const double* s) +{ + BRepBuilderAPI_MakeVertex makeVertex(gp_Pnt(s[0], s[1], s[2])); + TopoDS_Vertex vertex = makeVertex.Vertex(); + AddObject(new Part::TopoShape(vertex)); +} + + +void DraftDxfRead::OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden) +{ + gp_Pnt p0(s[0], s[1], s[2]); + gp_Pnt p1(e[0], e[1], e[2]); + gp_Dir up(0, 0, 1); + if (!dir) + up = -up; + gp_Pnt pc(c[0], c[1], c[2]); + gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc)); + BRepBuilderAPI_MakeEdge makeEdge(circle, p0, p1); + TopoDS_Edge edge = makeEdge.Edge(); + AddObject(new Part::TopoShape(edge)); +} + + +void DraftDxfRead::OnReadCircle(const double* s, const double* c, bool dir, bool hidden) +{ + gp_Pnt p0(s[0], s[1], s[2]); + gp_Dir up(0, 0, 1); + if (!dir) + up = -up; + gp_Pnt pc(c[0], c[1], c[2]); + gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc)); + BRepBuilderAPI_MakeEdge makeEdge(circle); + TopoDS_Edge edge = makeEdge.Edge(); + AddObject(new Part::TopoShape(edge)); +} + + +void DraftDxfRead::OnReadSpline(struct SplineData& sd) +{ + // not yet implemented +} + + +void DraftDxfRead::OnReadEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir) +{ + gp_Dir up(0, 0, 1); + if(!dir) + up = -up; + gp_Pnt pc(c[0], c[1], c[2]); + gp_Elips ellipse(gp_Ax2(pc, up), major_radius, minor_radius); + ellipse.Rotate(gp_Ax1(pc,up),rotation); + BRepBuilderAPI_MakeEdge makeEdge(ellipse); + TopoDS_Edge edge = makeEdge.Edge(); + AddObject(new Part::TopoShape(edge)); +} + + +void DraftDxfRead::OnReadText(const double *point, const double height, const std::string text) +{ + // not yet implemented +} + + +void DraftDxfRead::AddObject(Part::TopoShape *shape) +{ + if (optionGroupLayers) { + std::cout << "layer:" << LayerName() << std::endl; + std::vector vec; + if (layers.count(LayerName())) + vec = layers[LayerName()]; + vec.push_back(shape); + layers[LayerName()] = vec; + } else { + Part::Feature *pcFeature = (Part::Feature *)document->addObject("Part::Feature", "Shape"); + pcFeature->Shape.setValue(*shape); + } +} + + +void DraftDxfRead::AddGraphics() const +{ + std::cout << "end of file" << std::endl; + if (optionGroupLayers) { + for(std::map > ::const_iterator i = layers.begin(); i != layers.end(); ++i) { + BRep_Builder builder; + TopoDS_Compound comp; + builder.MakeCompound(comp); + std::string k = i->first; + std::vector v = i->second; + std::cout << "joining:" << k << " size " << v.size() << std::endl; + for(std::vector::const_iterator j = v.begin(); j != v.end(); ++j) { + const TopoDS_Shape& sh = (*j)->_Shape; + if (!sh.IsNull()) + builder.Add(comp, sh); + } + if (!comp.IsNull()) { + std::cout << "valid shape" << std::endl; + Part::Feature *pcFeature = (Part::Feature *)document->addObject("Part::Feature", k.c_str()); + pcFeature->Shape.setValue(comp); + } + else std::cout << "invalid shape" << std::endl; + } + } +} + + diff --git a/src/Mod/Draft/App/DraftDxf.h b/src/Mod/Draft/App/DraftDxf.h new file mode 100644 index 0000000000..63375a8ff7 --- /dev/null +++ b/src/Mod/Draft/App/DraftDxf.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef DRAFTDXF_H +#define DRAFTDXF_H + +#include "dxf.h" +#include +#include + +namespace DraftUtils +{ + class DraftUtilsExport DraftDxfRead : public CDxfRead + { + public: + DraftDxfRead(std::string filepath, App::Document *pcDoc); + + // CDxfRead's virtual functions + void OnReadLine(const double* s, const double* e, bool hidden); + void OnReadPoint(const double* s); + void OnReadText(const double* point, const double height, const std::string text); + void OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden); + void OnReadCircle(const double* s, const double* c, bool dir, bool hidden); + void OnReadEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir); + void OnReadSpline(struct SplineData& sd); + void AddGraphics() const; + + // FreeCAD-specific functions + void AddObject(Part::TopoShape *shape); + + protected: + App::Document *document; + bool optionGroupLayers; + std::map > layers; + }; +} + +#endif // DRAFTDXF_H diff --git a/src/Mod/Draft/App/PreCompiled.cpp b/src/Mod/Draft/App/PreCompiled.cpp new file mode 100644 index 0000000000..0e8374b910 --- /dev/null +++ b/src/Mod/Draft/App/PreCompiled.cpp @@ -0,0 +1,24 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" diff --git a/src/Mod/Draft/App/PreCompiled.h b/src/Mod/Draft/App/PreCompiled.h new file mode 100644 index 0000000000..73e7bb7e93 --- /dev/null +++ b/src/Mod/Draft/App/PreCompiled.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef DRAFTUTILS_PRECOMPILED_H +#define DRAFTUTILS_PRECOMPILED_H + +#include + +// Exporting of App classes +#ifdef FC_OS_WIN32 +# define DraftUtilsExport __declspec(dllexport) +# define PartExport __declspec(dllexport) +# define BaseExport __declspec(dllimport) +#else // for Linux +# define DraftUtilsExport +# define PartExport +# define BaseExport +#endif + +#ifdef _PreComp_ + +// standard +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif // _PreComp_ +#endif + diff --git a/src/Mod/Draft/App/dxf.cpp b/src/Mod/Draft/App/dxf.cpp new file mode 100644 index 0000000000..febda59e71 --- /dev/null +++ b/src/Mod/Draft/App/dxf.cpp @@ -0,0 +1,1597 @@ +// dxf.cpp +// Copyright (c) 2009, Dan Heeks +// This program is released under the BSD license. See the file COPYING for details. + +#include "dxf.h" + +using namespace std; +static const double Pi = 3.14159265358979323846264338327950288419716939937511; + +CDxfWrite::CDxfWrite(const char* filepath) +{ + // start the file + m_fail = false; +#ifdef __WXMSW__ + m_ofs = new ofstream(filepath, ios::out); +#else + m_ofs = new ofstream(filepath, ios::out); +#endif + if(!(*m_ofs)){ + m_fail = true; + return; + } + m_ofs->imbue(std::locale("C")); + + // start + (*m_ofs) << 0 << endl; + (*m_ofs) << "SECTION" << endl; + (*m_ofs) << 2 << endl; + (*m_ofs) << "ENTITIES" << endl; +} + +CDxfWrite::~CDxfWrite() +{ + // end + (*m_ofs) << 0 << endl; + (*m_ofs) << "ENDSEC" << endl; + (*m_ofs) << 0 << endl; + (*m_ofs) << "EOF"; + + delete m_ofs; +} + +void CDxfWrite::WriteLine(const double* s, const double* e, const char* layer_name) +{ + (*m_ofs) << 0 << endl; + (*m_ofs) << "LINE" << endl; + (*m_ofs) << 8 << endl; // Group code for layer name + (*m_ofs) << layer_name << endl; // Layer number + (*m_ofs) << 10 << endl; // Start point of line + (*m_ofs) << s[0] << endl; // X in WCS coordinates + (*m_ofs) << 20 << endl; + (*m_ofs) << s[1] << endl; // Y in WCS coordinates + (*m_ofs) << 30 << endl; + (*m_ofs) << s[2] << endl; // Z in WCS coordinates + (*m_ofs) << 11 << endl; // End point of line + (*m_ofs) << e[0] << endl; // X in WCS coordinates + (*m_ofs) << 21 << endl; + (*m_ofs) << e[1] << endl; // Y in WCS coordinates + (*m_ofs) << 31 << endl; + (*m_ofs) << e[2] << endl; // Z in WCS coordinates +} + +void CDxfWrite::WritePoint(const double* s, const char* layer_name) +{ + (*m_ofs) << 0 << endl; + (*m_ofs) << "POINT" << endl; + (*m_ofs) << 8 << endl; // Group code for layer name + (*m_ofs) << layer_name << endl; // Layer number + (*m_ofs) << 10 << endl; // Start point of line + (*m_ofs) << s[0] << endl; // X in WCS coordinates + (*m_ofs) << 20 << endl; + (*m_ofs) << s[1] << endl; // Y in WCS coordinates + (*m_ofs) << 30 << endl; + (*m_ofs) << s[2] << endl; // Z in WCS coordinates +} + +void CDxfWrite::WriteArc(const double* s, const double* e, const double* c, bool dir, const char* layer_name) +{ + double ax = s[0] - c[0]; + double ay = s[1] - c[1]; + double bx = e[0] - c[0]; + double by = e[1] - c[1]; + + double start_angle = atan2(ay, ax) * 180/Pi; + double end_angle = atan2(by, bx) * 180/Pi; + double radius = sqrt(ax*ax + ay*ay); + if(!dir){ + double temp = start_angle; + start_angle = end_angle; + end_angle = temp; + } + (*m_ofs) << 0 << endl; + (*m_ofs) << "ARC" << endl; + (*m_ofs) << 8 << endl; // Group code for layer name + (*m_ofs) << layer_name << endl; // Layer number + (*m_ofs) << 10 << endl; // Centre X + (*m_ofs) << c[0] << endl; // X in WCS coordinates + (*m_ofs) << 20 << endl; + (*m_ofs) << c[1] << endl; // Y in WCS coordinates + (*m_ofs) << 30 << endl; + (*m_ofs) << c[2] << endl; // Z in WCS coordinates + (*m_ofs) << 40 << endl; // + (*m_ofs) << radius << endl; // Radius + (*m_ofs) << 50 << endl; + (*m_ofs) << start_angle << endl; // Start angle + (*m_ofs) << 51 << endl; + (*m_ofs) << end_angle << endl; // End angle +} + +void CDxfWrite::WriteCircle(const double* c, double radius, const char* layer_name) +{ + (*m_ofs) << 0 << endl; + (*m_ofs) << "CIRCLE" << endl; + (*m_ofs) << 8 << endl; // Group code for layer name + (*m_ofs) << layer_name << endl; // Layer number + (*m_ofs) << 10 << endl; // Centre X + (*m_ofs) << c[0] << endl; // X in WCS coordinates + (*m_ofs) << 20 << endl; + (*m_ofs) << c[1] << endl; // Y in WCS coordinates + (*m_ofs) << 30 << endl; + (*m_ofs) << c[2] << endl; // Z in WCS coordinates + (*m_ofs) << 40 << endl; // + (*m_ofs) << radius << endl; // Radius +} + +void CDxfWrite::WriteEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir, const char* layer_name ) +{ + double m[3]; + m[2]=0; + m[0] = major_radius * sin(rotation); + m[1] = major_radius * cos(rotation); + + double ratio = minor_radius/major_radius; + + if(!dir){ + double temp = start_angle; + start_angle = end_angle; + end_angle = temp; + } + (*m_ofs) << 0 << endl; + (*m_ofs) << "ELLIPSE" << endl; + (*m_ofs) << 8 << endl; // Group code for layer name + (*m_ofs) << layer_name << endl; // Layer number + (*m_ofs) << 10 << endl; // Centre X + (*m_ofs) << c[0] << endl; // X in WCS coordinates + (*m_ofs) << 20 << endl; + (*m_ofs) << c[1] << endl; // Y in WCS coordinates + (*m_ofs) << 30 << endl; + (*m_ofs) << c[2] << endl; // Z in WCS coordinates + (*m_ofs) << 40 << endl; // + (*m_ofs) << ratio << endl; // Ratio + (*m_ofs) << 11 << endl; // + (*m_ofs) << m[0] << endl; // Major X + (*m_ofs) << 21 << endl; + (*m_ofs) << m[1] << endl; // Major Y + (*m_ofs) << 31 << endl; + (*m_ofs) << m[2] << endl; // Major Z + (*m_ofs) << 41 << endl; + (*m_ofs) << start_angle << endl; // Start angle + (*m_ofs) << 42 << endl; + (*m_ofs) << end_angle << endl; // End angle +} + +CDxfRead::CDxfRead(const char* filepath) +{ + // start the file + memset( m_unused_line, '\0', sizeof(m_unused_line) ); + m_fail = false; + m_aci = 0; + m_eUnits = eMillimeters; + m_measurement_inch = false; + strcpy(m_layer_name, "0"); // Default layer name + m_ignore_errors = true; + + m_ifs = new ifstream(filepath); + if(!(*m_ifs)){ + m_fail = true; + printf("DXF file didn't load\n"); + return; + } + m_ifs->imbue(std::locale("C")); + +} + +CDxfRead::~CDxfRead() +{ + delete m_ifs; +} + +double CDxfRead::mm( double value ) const +{ + if(m_measurement_inch) + { + value *= 0.0393700787401575; + } + + switch(m_eUnits) + { + case eUnspecified: return(value * 1.0); // We don't know any better. + case eInches: return(value * 25.4); + case eFeet: return(value * 25.4 * 12); + case eMiles: return(value * 1609344.0); + case eMillimeters: return(value * 1.0); + case eCentimeters: return(value * 10.0); + case eMeters: return(value * 1000.0); + case eKilometers: return(value * 1000000.0); + case eMicroinches: return(value * 25.4 / 1000.0); + case eMils: return(value * 25.4 / 1000.0); + case eYards: return(value * 3 * 12 * 25.4); + case eAngstroms: return(value * 0.0000001); + case eNanometers: return(value * 0.000001); + case eMicrons: return(value * 0.001); + case eDecimeters: return(value * 100.0); + case eDekameters: return(value * 10000.0); + case eHectometers: return(value * 100000.0); + case eGigameters: return(value * 1000000000000.0); + case eAstronomicalUnits: return(value * 149597870690000.0); + case eLightYears: return(value * 9454254955500000000.0); + case eParsecs: return(value * 30856774879000000000.0); + default: return(value * 1.0); // We don't know any better. + } // End switch +} // End mm() method + + +bool CDxfRead::ReadLine() +{ + double s[3] = {0, 0, 0}; + double e[3] = {0, 0, 0}; + bool hidden = false; + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadLine() Failed to read integer from '%s'\n", m_str ); + return false; + } + + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with line + DerefACI(); + OnReadLine(s, e, hidden); + hidden = false; + return true; + + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 6: // line style name follows + get_line(); + if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; + break; + + case 10: + // start x + get_line(); + ss.str(m_str); ss >> s[0]; s[0] = mm(s[0]); if(ss.fail()) return false; + break; + case 20: + // start y + get_line(); + ss.str(m_str); ss >> s[1]; s[1] = mm(s[1]); if(ss.fail()) return false; + break; + case 30: + // start z + get_line(); + ss.str(m_str); ss >> s[2]; s[2] = mm(s[2]); if(ss.fail()) return false; + break; + case 11: + // end x + get_line(); + ss.str(m_str); ss >> e[0]; e[0] = mm(e[0]); if(ss.fail()) return false; + break; + case 21: + // end y + get_line(); + ss.str(m_str); ss >> e[1]; e[1] = mm(e[1]); if(ss.fail()) return false; + break; + case 31: + // end z + get_line(); + ss.str(m_str); ss >> e[2]; e[2] = mm(e[2]); if(ss.fail()) return false; + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + + try { + DerefACI(); + OnReadLine(s, e, false); + } + catch(...) + { + if (! IgnoreErrors()) throw; // Re-throw the exception. + } + + return false; +} + +bool CDxfRead::ReadPoint() +{ + double s[3] = {0, 0, 0}; + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadPoint() Failed to read integer from '%s'\n", m_str ); + return false; + } + + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with line + DerefACI(); + OnReadPoint(s); + return true; + + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // start x + get_line(); + ss.str(m_str); ss >> s[0]; s[0] = mm(s[0]); if(ss.fail()) return false; + break; + case 20: + // start y + get_line(); + ss.str(m_str); ss >> s[1]; s[1] = mm(s[1]); if(ss.fail()) return false; + break; + case 30: + // start z + get_line(); + ss.str(m_str); ss >> s[2]; s[2] = mm(s[2]); if(ss.fail()) return false; + break; + + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + + } + + try { + DerefACI(); + OnReadPoint(s); + } + catch(...) + { + if (! IgnoreErrors()) throw; // Re-throw the exception. + } + + return false; +} + +bool CDxfRead::ReadArc() +{ + double start_angle = 0.0;// in degrees + double end_angle = 0.0; + double radius = 0.0; + double c[3]; // centre + double z_extrusion_dir = 1.0; + bool hidden = false; + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadArc() Failed to read integer from '%s'\n", m_str); + return false; + } + + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with arc + DerefACI(); + OnReadArc(start_angle, end_angle, radius, c,z_extrusion_dir, hidden); + hidden = false; + return true; + + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 6: // line style name follows + get_line(); + if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; + break; + + case 10: + // centre x + get_line(); + ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; + break; + case 20: + // centre y + get_line(); + ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; + break; + case 30: + // centre z + get_line(); + ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; + break; + case 40: + // radius + get_line(); + ss.str(m_str); ss >> radius; radius = mm(radius); if(ss.fail()) return false; + break; + case 50: + // start angle + get_line(); + ss.str(m_str); ss >> start_angle; if(ss.fail()) return false; + break; + case 51: + // end angle + get_line(); + ss.str(m_str); ss >> end_angle; if(ss.fail()) return false; + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + + + case 100: + case 39: + case 210: + case 220: + // skip the next line + get_line(); + break; + case 230: + //Z extrusion direction for arc + get_line(); + ss.str(m_str); ss >> z_extrusion_dir; if(ss.fail()) return false; + break; + + default: + // skip the next line + get_line(); + break; + } + } + DerefACI(); + OnReadArc(start_angle, end_angle, radius, c, z_extrusion_dir, false); + return false; +} + +bool CDxfRead::ReadSpline() +{ + struct SplineData sd; + sd.norm[0] = 0; + sd.norm[1] = 0; + sd.norm[2] = 1; + sd.degree = 0; + sd.knots = 0; + sd.flag = 0; + sd.control_points = 0; + sd.fit_points = 0; + + double temp_double; + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadSpline() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with Spline + DerefACI(); + OnReadSpline(sd); + return true; + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + case 210: + // normal x + get_line(); + ss.str(m_str); ss >> sd.norm[0]; if(ss.fail()) return false; + break; + case 220: + // normal y + get_line(); + ss.str(m_str); ss >> sd.norm[1]; if(ss.fail()) return false; + break; + case 230: + // normal z + get_line(); + ss.str(m_str); ss >> sd.norm[2]; if(ss.fail()) return false; + break; + case 70: + // flag + get_line(); + ss.str(m_str); ss >> sd.flag; if(ss.fail()) return false; + break; + case 71: + // degree + get_line(); + ss.str(m_str); ss >> sd.degree; if(ss.fail()) return false; + break; + case 72: + // knots + get_line(); + ss.str(m_str); ss >> sd.knots; if(ss.fail()) return false; + break; + case 73: + // control points + get_line(); + ss.str(m_str); ss >> sd.control_points; if(ss.fail()) return false; + break; + case 74: + // fit points + get_line(); + ss.str(m_str); ss >> sd.fit_points; if(ss.fail()) return false; + break; + case 12: + // starttan x + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.starttanx.push_back(temp_double); + break; + case 22: + // starttan y + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.starttany.push_back(temp_double); + break; + case 32: + // starttan z + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.starttanz.push_back(temp_double); + break; + case 13: + // endtan x + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.endtanx.push_back(temp_double); + break; + case 23: + // endtan y + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.endtany.push_back(temp_double); + break; + case 33: + // endtan z + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.endtanz.push_back(temp_double); + break; + case 40: + // knot + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.knot.push_back(temp_double); + break; + case 41: + // weight + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.weight.push_back(temp_double); + break; + case 10: + // control x + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.controlx.push_back(temp_double); + break; + case 20: + // control y + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.controly.push_back(temp_double); + break; + case 30: + // control z + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.controlz.push_back(temp_double); + break; + case 11: + // fit x + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.fitx.push_back(temp_double); + break; + case 21: + // fit y + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.fity.push_back(temp_double); + break; + case 31: + // fit z + get_line(); + ss.str(m_str); ss >> temp_double; temp_double = mm(temp_double); if(ss.fail()) return false; + sd.fitz.push_back(temp_double); + break; + case 42: + case 43: + case 44: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + DerefACI(); + OnReadSpline(sd); + return false; +} + + +bool CDxfRead::ReadCircle() +{ + double radius = 0.0; + double c[3]; // centre + bool hidden = false; + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadCircle() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with Circle + DerefACI(); + OnReadCircle(c, radius, hidden); + hidden = false; + return true; + + case 6: // line style name follows + get_line(); + if(m_str[0] == 'h' || m_str[0] == 'H')hidden = true; + break; + + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // centre x + get_line(); + ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; + break; + case 20: + // centre y + get_line(); + ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; + break; + case 30: + // centre z + get_line(); + ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; + break; + case 40: + // radius + get_line(); + ss.str(m_str); ss >> radius; radius = mm(radius); if(ss.fail()) return false; + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + DerefACI(); + OnReadCircle(c, radius, false); + return false; +} + + +bool CDxfRead::ReadText() +{ + double c[3]; // coordinate + double height = 0.03082; + + memset( c, 0, sizeof(c) ); + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadText() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + return false; + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // centre x + get_line(); + ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; + break; + case 20: + // centre y + get_line(); + ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; + break; + case 30: + // centre z + get_line(); + ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; + break; + case 40: + // text height + get_line(); + ss.str(m_str); ss >> height; height = mm(height); if(ss.fail()) return false; + break; + case 1: + // text + get_line(); + DerefACI(); + OnReadText(c, height * 25.4 / 72.0, m_str); + return(true); + + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + case 100: + case 39: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + + return false; +} + + +bool CDxfRead::ReadEllipse() +{ + double c[3]; // centre + double m[3]; //major axis point + double ratio=0; //ratio of major to minor axis + double start=0; //start of arc + double end=0; // end of arc + + while(!((*m_ifs).eof())) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadEllipse() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found, so finish with Ellipse + DerefACI(); + OnReadEllipse(c, m, ratio, start, end); + return true; + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // centre x + get_line(); + ss.str(m_str); ss >> c[0]; c[0] = mm(c[0]); if(ss.fail()) return false; + break; + case 20: + // centre y + get_line(); + ss.str(m_str); ss >> c[1]; c[1] = mm(c[1]); if(ss.fail()) return false; + break; + case 30: + // centre z + get_line(); + ss.str(m_str); ss >> c[2]; c[2] = mm(c[2]); if(ss.fail()) return false; + break; + case 11: + // major x + get_line(); + ss.str(m_str); ss >> m[0]; m[0] = mm(m[0]); if(ss.fail()) return false; + break; + case 21: + // major y + get_line(); + ss.str(m_str); ss >> m[1]; m[1] = mm(m[1]); if(ss.fail()) return false; + break; + case 31: + // major z + get_line(); + ss.str(m_str); ss >> m[2]; m[2] = mm(m[2]); if(ss.fail()) return false; + break; + case 40: + // ratio + get_line(); + ss.str(m_str); ss >> ratio; if(ss.fail()) return false; + break; + case 41: + // start + get_line(); + ss.str(m_str); ss >> start; if(ss.fail()) return false; + break; + case 42: + // end + get_line(); + ss.str(m_str); ss >> end; if(ss.fail()) return false; + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + case 100: + case 210: + case 220: + case 230: + // skip the next line + get_line(); + break; + default: + // skip the next line + get_line(); + break; + } + } + DerefACI(); + OnReadEllipse(c, m, ratio, start, end); + return false; +} + + +static bool poly_prev_found = false; +static double poly_prev_x; +static double poly_prev_y; +static double poly_prev_z; +static double poly_prev_bulge_found; +static double poly_prev_bulge; +static bool poly_first_found = false; +static double poly_first_x; +static double poly_first_y; +static double poly_first_z; + +static void AddPolyLinePoint(CDxfRead* dxf_read, double x, double y, double z, bool bulge_found, double bulge) +{ + + try { + if(poly_prev_found) + { + bool arc_done = false; + if(poly_prev_bulge_found) + { + double cot = 0.5 * ((1.0 / poly_prev_bulge) - poly_prev_bulge); + double cx = ((poly_prev_x + x) - ((y - poly_prev_y) * cot)) / 2.0; + double cy = ((poly_prev_y + y) + ((x - poly_prev_x) * cot)) / 2.0; + double ps[3] = {poly_prev_x, poly_prev_y, poly_prev_z}; + double pe[3] = {x, y, z}; + double pc[3] = {cx, cy, (poly_prev_z + z)/2.0}; + dxf_read->OnReadArc(ps, pe, pc, poly_prev_bulge >= 0, false); + arc_done = true; + } + + if(!arc_done) + { + double s[3] = {poly_prev_x, poly_prev_y, poly_prev_z}; + double e[3] = {x, y, z}; + dxf_read->OnReadLine(s, e, false); + } + } + + poly_prev_found = true; + poly_prev_x = x; + poly_prev_y = y; + poly_prev_z = z; + if(!poly_first_found) + { + poly_first_x = x; + poly_first_y = y; + poly_first_z = z; + poly_first_found = true; + } + poly_prev_bulge_found = bulge_found; + poly_prev_bulge = bulge; + } + catch(...) + { + if (! dxf_read->IgnoreErrors()) throw; // Re-throw it. + } +} + +static void PolyLineStart() +{ + poly_prev_found = false; + poly_first_found = false; +} + +bool CDxfRead::ReadLwPolyLine() +{ + PolyLineStart(); + + bool x_found = false; + bool y_found = false; + double x = 0.0; + double y = 0.0; + double z = 0.0; + bool bulge_found = false; + double bulge = 0.0; + bool closed = false; + int flags; + bool next_item_found = false; + + while(!((*m_ifs).eof()) && !next_item_found) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadLwPolyLine() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found + + DerefACI(); + if(x_found && y_found){ + // add point + AddPolyLinePoint(this, x, y, z, bulge_found, bulge); + bulge_found = false; + x_found = false; + y_found = false; + } + next_item_found = true; + break; + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // x + get_line(); + if(x_found && y_found){ + // add point + AddPolyLinePoint(this, x, y, z, bulge_found, bulge); + bulge_found = false; + x_found = false; + y_found = false; + } + ss.str(m_str); ss >> x; x = mm(x); if(ss.fail()) return false; + x_found = true; + break; + case 20: + // y + get_line(); + ss.str(m_str); ss >> y; y = mm(y); if(ss.fail()) return false; + y_found = true; + break; + case 42: + // bulge + get_line(); + ss.str(m_str); ss >> bulge; if(ss.fail()) return false; + bulge_found = true; + break; + case 70: + // flags + get_line(); + if(sscanf(m_str, "%d", &flags) != 1)return false; + closed = ((flags & 1) != 0); + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + default: + // skip the next line + get_line(); + break; + } + } + + if(next_item_found) + { + if(closed && poly_first_found) + { + // repeat the first point + DerefACI(); + AddPolyLinePoint(this, poly_first_x, poly_first_y, poly_first_z, false, 0.0); + } + return true; + } + + return false; +} + + +bool CDxfRead::ReadVertex(double *pVertex, bool *bulge_found, double *bulge) +{ + bool x_found = false; + bool y_found = false; + + double x = 0.0; + double y = 0.0; + double z = 0.0; + *bulge = 0.0; + *bulge_found = false; + + pVertex[0] = 0.0; + pVertex[1] = 0.0; + pVertex[2] = 0.0; + + while(!(*m_ifs).eof()) { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) { + printf("CDxfRead::ReadVertex() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + DerefACI(); + put_line(m_str); // read one line too many. put it back. + return(x_found && y_found); + break; + + case 8: // Layer name follows + get_line(); + strcpy(m_layer_name, m_str); + break; + + case 10: + // x + get_line(); + ss.str(m_str); ss >> x; pVertex[0] = mm(x); if(ss.fail()) return false; + x_found = true; + break; + case 20: + // y + get_line(); + ss.str(m_str); ss >> y; pVertex[1] = mm(y); if(ss.fail()) return false; + y_found = true; + break; + case 30: + // z + get_line(); + ss.str(m_str); ss >> z; pVertex[2] = mm(z); if(ss.fail()) return false; + break; + + case 42: + get_line(); + *bulge_found = true; + ss.str(m_str); ss >> *bulge; if(ss.fail()) return false; + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + + default: + // skip the next line + get_line(); + break; + } + } + + return false; +} + + + +bool CDxfRead::ReadPolyLine() +{ + PolyLineStart(); + + bool closed = false; + int flags; + bool first_vertex_section_found = false; + double first_vertex[3]; + bool bulge_found; + double bulge; + + while(!(*m_ifs).eof()) + { + get_line(); + int n; + if(sscanf(m_str, "%d", &n) != 1) + { + printf("CDxfRead::ReadPolyLine() Failed to read integer from '%s'\n", m_str); + return false; + } + std::istringstream ss; + ss.imbue(std::locale("C")); + switch(n){ + case 0: + // next item found + DerefACI(); + get_line(); + if (! strcmp(m_str,"VERTEX")) + { + double vertex[3]; + if (CDxfRead::ReadVertex(vertex, &bulge_found, &bulge)) + { + if(!first_vertex_section_found) { + first_vertex_section_found = true; + memcpy(first_vertex, vertex, 3*sizeof(double)); + } + AddPolyLinePoint(this, vertex[0], vertex[1], vertex[2], bulge_found, bulge); + break; + } + } + if (! strcmp(m_str,"SEQEND")) + { + if(closed && first_vertex_section_found) { + AddPolyLinePoint(this, first_vertex[0], first_vertex[1], first_vertex[2], 0, 0); + } + first_vertex_section_found = false; + PolyLineStart(); + return(true); + } + break; + case 70: + // flags + get_line(); + if(sscanf(m_str, "%d", &flags) != 1)return false; + closed = ((flags & 1) != 0); + break; + case 62: + // color index + get_line(); + ss.str(m_str); ss >> m_aci; if(ss.fail()) return false; + break; + default: + // skip the next line + get_line(); + break; + } + } + + return false; +} + +void CDxfRead::OnReadArc(double start_angle, double end_angle, double radius, const double* c, double z_extrusion_dir, bool hidden){ + double s[3], e[3], temp[3] ; + if (z_extrusion_dir==1.0) + { + temp[0] =c[0]; + temp[1] =c[1]; + temp[2] =c[2]; + s[0] = c[0] + radius * cos(start_angle * Pi/180); + s[1] = c[1] + radius * sin(start_angle * Pi/180); + s[2] = c[2]; + e[0] = c[0] + radius * cos(end_angle * Pi/180); + e[1] = c[1] + radius * sin(end_angle * Pi/180); + e[2] = c[2]; + } + else + { + temp[0] =-c[0]; + temp[1] =c[1]; + temp[2] =c[2]; + + e[0] = -(c[0] + radius * cos(start_angle * Pi/180)); + e[1] = (c[1] + radius * sin(start_angle * Pi/180)); + e[2] = c[2]; + s[0] = -(c[0] + radius * cos(end_angle * Pi/180)); + s[1] = (c[1] + radius * sin(end_angle * Pi/180)); + s[2] = c[2]; + + } + OnReadArc(s, e, temp, true, hidden); +} + +void CDxfRead::OnReadCircle(const double* c, double radius, bool hidden){ + double s[3]; + double start_angle = 0; + s[0] = c[0] + radius * cos(start_angle * Pi/180); + s[1] = c[1] + radius * sin(start_angle * Pi/180); + s[2] = c[2]; + + OnReadCircle(s, c, false, hidden); //false to change direction because otherwise the arc length is zero +} + +void CDxfRead::OnReadEllipse(const double* c, const double* m, double ratio, double start_angle, double end_angle){ + double major_radius = sqrt(m[0]*m[0] + m[1]*m[1] + m[2]*m[2]); + double minor_radius = major_radius * ratio; + + //Since we only support 2d stuff, we can calculate the rotation from the major axis x and y value only, + //since z is zero, major_radius is the vector length + + double rotation = atan2(m[1]/major_radius,m[0]/major_radius); + + + OnReadEllipse(c, major_radius, minor_radius, rotation, start_angle, end_angle, true); +} + +void CDxfRead::get_line() +{ + if (m_unused_line[0] != '\0') + { + strcpy(m_str, m_unused_line); + memset( m_unused_line, '\0', sizeof(m_unused_line)); + return; + } + + m_ifs->getline(m_str, 1024); + + char str[1024]; + int len = strlen(m_str); + int j = 0; + bool non_white_found = false; + for(int i = 0; i 0) + { + result.append(m_section_name); + } + + if (strlen(m_block_name) > 0) + { + result.append(" "); + result.append(m_block_name); + } + + if (strlen(m_layer_name) > 0) + { + result.append(" "); + result.append(m_layer_name); + } + + return(result); +} diff --git a/src/Mod/Draft/App/dxf.h b/src/Mod/Draft/App/dxf.h new file mode 100644 index 0000000000..bb895f6d3b --- /dev/null +++ b/src/Mod/Draft/App/dxf.h @@ -0,0 +1,157 @@ +// dxf.h +// Copyright (c) 2009, Dan Heeks +// This program is released under the BSD license. See the file COPYING for details. +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//Following is required to be defined on Ubuntu with OCC 6.3.1 +#ifndef HAVE_IOSTREAM +#define HAVE_IOSTREAM +#endif + +typedef int Aci_t; // AutoCAD color index + +typedef 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 +} eDxfUnits_t; + + +struct SplineData +{ + double norm[3]; + int degree; + int knots; + int control_points; + int fit_points; + int flag; + std::list starttanx; + std::list starttany; + std::list starttanz; + std::list endtanx; + std::list endtany; + std::list endtanz; + std::list knot; + std::list weight; + std::list controlx; + std::list controly; + std::list controlz; + std::list fitx; + std::list fity; + std::list fitz; +}; + +class CDxfWrite{ +private: + std::ofstream* m_ofs; + bool m_fail; + +public: + CDxfWrite(const char* filepath); + ~CDxfWrite(); + + bool Failed(){return m_fail;} + + void WriteLine(const double* s, const double* e, const char* layer_name ); + void WritePoint(const double*, const char*); + void WriteArc(const double* s, const double* e, const double* c, bool dir, const char* layer_name ); + void WriteEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir, const char* layer_name ); + void WriteCircle(const double* c, double radius, const char* layer_name ); +}; + +// derive a class from this and implement it's virtual functions +class CDxfRead{ +private: + std::ifstream* m_ifs; + + bool m_fail; + char m_str[1024]; + char m_unused_line[1024]; + eDxfUnits_t m_eUnits; + bool m_measurement_inch; + char m_layer_name[1024]; + char m_section_name[1024]; + char m_block_name[1024]; + bool m_ignore_errors; + + + typedef std::map< std::string,Aci_t > LayerAciMap_t; + LayerAciMap_t m_layer_aci; // layer names -> layer color aci map + + bool ReadUnits(); + bool ReadLayer(); + bool ReadLine(); + bool ReadText(); + bool ReadArc(); + bool ReadCircle(); + bool ReadEllipse(); + bool ReadPoint(); + bool ReadSpline(); + bool ReadLwPolyLine(); + bool ReadPolyLine(); + bool ReadVertex(double *pVertex, bool *bulge_found, double *bulge); + void OnReadArc(double start_angle, double end_angle, double radius, const double* c, double z_extrusion_dir, bool hidden); + void OnReadCircle(const double* c, double radius, bool hidden); + void OnReadEllipse(const double* c, const double* m, double ratio, double start_angle, double end_angle); + + void get_line(); + void put_line(const char *value); + void DerefACI(); + +protected: + Aci_t m_aci; // manifest color name or 256 for layer color + +public: + CDxfRead(const char* filepath); // this opens the file + ~CDxfRead(); // this closes the file + + bool Failed(){return m_fail;} + void DoRead(const bool ignore_errors = false); // this reads the file and calls the following functions + + double mm( double value ) const; + + bool IgnoreErrors() const { return(m_ignore_errors); } + + virtual void OnReadLine(const double* s, const double* e, bool hidden){} + virtual void OnReadPoint(const double* s){} + virtual void OnReadText(const double* point, const double height, const char* text){} + virtual void OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden){} + virtual void OnReadCircle(const double* s, const double* c, bool dir, bool hidden){} + virtual void OnReadEllipse(const double* c, double major_radius, double minor_radius, double rotation, double start_angle, double end_angle, bool dir){} + virtual void OnReadSpline(struct SplineData& sd){} + virtual void AddGraphics() const { } + + std::string LayerName() const; + +}; diff --git a/src/Mod/Draft/CMakeLists.txt b/src/Mod/Draft/CMakeLists.txt index 96b9fba35c..f4bf239b63 100644 --- a/src/Mod/Draft/CMakeLists.txt +++ b/src/Mod/Draft/CMakeLists.txt @@ -1,3 +1,5 @@ +add_subdirectory(App) + PYSIDE_WRAP_RC(Draft_QRC_SRCS Resources/Draft.qrc) SET(Draft_SRCS