Move Dxf function to Mod/Import Ph1
- move HeeksCAD dxf import/export code from Draft to Mod/Import. This first phase moves dxf.cpp and DraftDxf.cpp to Mod/Import and adds dxfWrite functionality to DraftDxf.cpp.
This commit is contained in:
@@ -66,6 +66,10 @@
|
||||
#include <Mod/Part/App/ImportIges.h>
|
||||
#include <Mod/Part/App/ImportStep.h>
|
||||
#include <Mod/Part/App/encodeFilename.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <Mod/Part/App/TopoShapePy.h>
|
||||
|
||||
#include "ImpExpDxf.h"
|
||||
|
||||
namespace Import {
|
||||
class Module : public Py::ExtensionModule<Module>
|
||||
@@ -85,7 +89,13 @@ public:
|
||||
add_varargs_method("export",&Module::exporter,
|
||||
"export(list,string) -- Export a list of objects into a single file."
|
||||
);
|
||||
initialize("This module is the Import module."); // register with Python
|
||||
add_varargs_method("readDXF",&Module::readDXF,
|
||||
"readDXF(filename,[document,ignore_errors]): Imports a DXF file into the given document. ignore_errors is True by default."
|
||||
);
|
||||
add_varargs_method("writeDXFShape",&Module::writeDXFShape,
|
||||
"writeDXFShape(shape,filename): Exports a Shape to a DXF file."
|
||||
);
|
||||
initialize("This module is the Import module."); // register with Python
|
||||
}
|
||||
|
||||
virtual ~Module() {}
|
||||
@@ -313,6 +323,74 @@ private:
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object readDXF(const Py::Tuple& args)
|
||||
{
|
||||
char* Name;
|
||||
const char* DocName=0;
|
||||
bool IgnoreErrors=true;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et|sb","utf-8",&Name,&DocName,&IgnoreErrors))
|
||||
throw Py::Exception();
|
||||
|
||||
std::string EncodedName = std::string(Name);
|
||||
PyMem_Free(Name);
|
||||
|
||||
Base::FileInfo file(EncodedName.c_str());
|
||||
if (!file.exists())
|
||||
throw Py::RuntimeError("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);
|
||||
|
||||
try {
|
||||
// read the DXF file
|
||||
ImpExpDxfRead dxf_file(EncodedName,pcDoc);
|
||||
//dxf_file.setOptionSource("myoptionpath");
|
||||
//dxf_file.setOptions();
|
||||
dxf_file.DoRead(IgnoreErrors);
|
||||
pcDoc->recompute();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object writeDXFShape(const Py::Tuple& args)
|
||||
{
|
||||
PyObject *shapeObj;
|
||||
char* name;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "Oet", &shapeObj, "utf-8",&name)) {
|
||||
throw Py::Exception("expected (Page,path");
|
||||
}
|
||||
|
||||
std::string filePath = std::string(name);
|
||||
std::string layerName = "none";
|
||||
PyMem_Free(name);
|
||||
try {
|
||||
ImpExpDxfWrite writer(filePath);
|
||||
//writer.setOptionSource("myoptionpath");
|
||||
//writer.setOptions();
|
||||
writer.setLayerName(layerName);
|
||||
if (PyObject_TypeCheck(shapeObj, &(Part::TopoShapePy::Type))) {
|
||||
Part::TopoShape* obj = static_cast<Part::TopoShapePy*>(shapeObj)->getTopoShapePtr();
|
||||
TopoDS_Shape shape = obj->getShape();
|
||||
writer.exportShape(shape);
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
/*
|
||||
static PyObject * importAssembly(PyObject *self, PyObject *args)
|
||||
|
||||
@@ -37,6 +37,10 @@ SET(Import_SRCS
|
||||
StepShapePyImp.cpp
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
ImpExpDxf.cpp
|
||||
ImpExpDxf.h
|
||||
dxf.cpp
|
||||
dxf.h
|
||||
)
|
||||
|
||||
SET(SCL_Resources
|
||||
|
||||
593
src/Mod/Import/App/ImpExpDxf.cpp
Normal file
593
src/Mod/Import/App/ImpExpDxf.cpp
Normal file
@@ -0,0 +1,593 @@
|
||||
/***************************************************************************
|
||||
* 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 "ImpExpDxf.h"
|
||||
|
||||
#include <Approx_Curve3d.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_HCurve.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeVertex.hxx>
|
||||
#include <GCPnts_UniformAbscissa.hxx>
|
||||
#include <GeomAPI_PointsToBSpline.hxx>
|
||||
#include <GeomAdaptor_Curve.hxx>
|
||||
#include <Geom_BSplineCurve.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Elips.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Matrix.h>
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/Annotation.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
using namespace Import;
|
||||
|
||||
|
||||
//******************************************************************************
|
||||
// reading
|
||||
ImpExpDxfRead::ImpExpDxfRead(std::string filepath, App::Document *pcDoc) : CDxfRead(filepath.c_str())
|
||||
{
|
||||
document = pcDoc;
|
||||
setOptionSource("User parameter:BaseApp/Preferences/Mod/Draft");
|
||||
setOptions();
|
||||
// ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Draft");
|
||||
// optionGroupLayers = hGrp->GetBool("groupLayers",false);
|
||||
// optionImportAnnotations = hGrp->GetBool("dxftext",false);
|
||||
// optionScaling = hGrp->GetFloat("dxfScaling",1.0);
|
||||
}
|
||||
|
||||
void ImpExpDxfRead::setOptions(void)
|
||||
{
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(getOptionSource().c_str());
|
||||
optionGroupLayers = hGrp->GetBool("groupLayers",false);
|
||||
optionImportAnnotations = hGrp->GetBool("dxftext",false);
|
||||
optionScaling = hGrp->GetFloat("dxfScaling",1.0);
|
||||
}
|
||||
|
||||
gp_Pnt ImpExpDxfRead::makePoint(const double* p)
|
||||
{
|
||||
double sp1(p[0]);
|
||||
double sp2(p[1]);
|
||||
double sp3(p[2]);
|
||||
if (optionScaling != 1.0) {
|
||||
sp1 = sp1 * optionScaling;
|
||||
sp2 = sp2 * optionScaling;
|
||||
sp3 = sp3 * optionScaling;
|
||||
}
|
||||
return gp_Pnt(sp1,sp2,sp3);
|
||||
}
|
||||
|
||||
void ImpExpDxfRead::OnReadLine(const double* s, const double* e, bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Pnt p1 = makePoint(e);
|
||||
if (p0.IsEqual(p1,0.00000001))
|
||||
return;
|
||||
BRepBuilderAPI_MakeEdge makeEdge(p0, p1);
|
||||
TopoDS_Edge edge = makeEdge.Edge();
|
||||
AddObject(new Part::TopoShape(edge));
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadPoint(const double* s)
|
||||
{
|
||||
BRepBuilderAPI_MakeVertex makeVertex(makePoint(s));
|
||||
TopoDS_Vertex vertex = makeVertex.Vertex();
|
||||
AddObject(new Part::TopoShape(vertex));
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadArc(const double* s, const double* e, const double* c, bool dir, bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Pnt p1 = makePoint(e);
|
||||
gp_Dir up(0, 0, 1);
|
||||
if (!dir)
|
||||
up = -up;
|
||||
gp_Pnt pc = makePoint(c);
|
||||
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 ImpExpDxfRead::OnReadCircle(const double* s, const double* c, bool dir, bool /*hidden*/)
|
||||
{
|
||||
gp_Pnt p0 = makePoint(s);
|
||||
gp_Dir up(0, 0, 1);
|
||||
if (!dir)
|
||||
up = -up;
|
||||
gp_Pnt pc = makePoint(c);
|
||||
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 ImpExpDxfRead::OnReadSpline(struct SplineData& /*sd*/)
|
||||
{
|
||||
// not yet implemented
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::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 = makePoint(c);
|
||||
gp_Elips ellipse(gp_Ax2(pc, up), major_radius * optionScaling, minor_radius * optionScaling);
|
||||
ellipse.Rotate(gp_Ax1(pc,up),rotation);
|
||||
BRepBuilderAPI_MakeEdge makeEdge(ellipse);
|
||||
TopoDS_Edge edge = makeEdge.Edge();
|
||||
AddObject(new Part::TopoShape(edge));
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadText(const double *point, const double /*height*/, const char* text)
|
||||
{
|
||||
if (optionImportAnnotations) {
|
||||
Base::Vector3d pt(point[0] * optionScaling, point[1] * optionScaling, point[2] * optionScaling);
|
||||
if(LayerName().substr(0, 6) != "BLOCKS") {
|
||||
App::Annotation *pcFeature = (App::Annotation *)document->addObject("App::Annotation", "Text");
|
||||
pcFeature->LabelText.setValue(Deformat(text));
|
||||
pcFeature->Position.setValue(pt);
|
||||
}
|
||||
//else std::cout << "skipped text in block: " << LayerName() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadInsert(const double* point, const double* scale, const char* name, double rotation)
|
||||
{
|
||||
//std::cout << "Inserting block " << name << " rotation " << rotation << " pos " << point[0] << "," << point[1] << "," << point[2] << " scale " << scale[0] << "," << scale[1] << "," << scale[2] << std::endl;
|
||||
std::string prefix = "BLOCKS ";
|
||||
prefix += name;
|
||||
prefix += " ";
|
||||
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) {
|
||||
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();
|
||||
if (!sh.IsNull())
|
||||
builder.Add(comp, sh);
|
||||
}
|
||||
if (!comp.IsNull()) {
|
||||
Part::TopoShape* pcomp = new Part::TopoShape(comp);
|
||||
Base::Matrix4D mat;
|
||||
mat.scale(scale[0],scale[1],scale[2]);
|
||||
mat.rotZ(rotation);
|
||||
mat.move(point[0]*optionScaling,point[1]*optionScaling,point[2]*optionScaling);
|
||||
pcomp->transformShape(mat,true);
|
||||
AddObject(pcomp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::OnReadDimension(const double* s, const double* e, const double* point, double /*rotation*/)
|
||||
{
|
||||
if (optionImportAnnotations) {
|
||||
Base::Interpreter().runString("import Draft");
|
||||
Base::Interpreter().runStringArg("p1=FreeCAD.Vector(%f,%f,%f)",s[0]*optionScaling,s[1]*optionScaling,s[2]*optionScaling);
|
||||
Base::Interpreter().runStringArg("p2=FreeCAD.Vector(%f,%f,%f)",e[0]*optionScaling,e[1]*optionScaling,e[2]*optionScaling);
|
||||
Base::Interpreter().runStringArg("p3=FreeCAD.Vector(%f,%f,%f)",point[0]*optionScaling,point[1]*optionScaling,point[2]*optionScaling);
|
||||
Base::Interpreter().runString("Draft.makeDimension(p1,p2,p3)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::AddObject(Part::TopoShape *shape)
|
||||
{
|
||||
//std::cout << "layer:" << LayerName() << std::endl;
|
||||
std::vector <Part::TopoShape*> vec;
|
||||
if (layers.count(LayerName()))
|
||||
vec = layers[LayerName()];
|
||||
vec.push_back(shape);
|
||||
layers[LayerName()] = vec;
|
||||
if (!optionGroupLayers) {
|
||||
if(LayerName().substr(0, 6) != "BLOCKS") {
|
||||
Part::Feature *pcFeature = (Part::Feature *)document->addObject("Part::Feature", "Shape");
|
||||
pcFeature->Shape.setValue(shape->getShape());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ImpExpDxfRead::Deformat(const char* text)
|
||||
{
|
||||
// this function removes DXF formatting from texts
|
||||
std::stringstream ss;
|
||||
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] == '\\')
|
||||
escape = true;
|
||||
else if (escape) {
|
||||
if (longescape) {
|
||||
if (text[i] == ';') {
|
||||
escape = false;
|
||||
longescape = false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( (text[i] != '{') && (text[i] != '}') ) {
|
||||
ss << text[i];
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
void ImpExpDxfRead::AddGraphics() const
|
||||
{
|
||||
if (optionGroupLayers) {
|
||||
for(std::map<std::string,std::vector<Part::TopoShape*> > ::const_iterator i = layers.begin(); i != layers.end(); ++i) {
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound comp;
|
||||
builder.MakeCompound(comp);
|
||||
std::string k = i->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 (!sh.IsNull())
|
||||
builder.Add(comp, sh);
|
||||
}
|
||||
if (!comp.IsNull()) {
|
||||
Part::Feature *pcFeature = (Part::Feature *)document->addObject("Part::Feature", k.c_str());
|
||||
pcFeature->Shape.setValue(comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// writing
|
||||
|
||||
void gPntToTuple(double* result, gp_Pnt& p)
|
||||
{
|
||||
result[0] = p.X();
|
||||
result[1] = p.Y();
|
||||
result[2] = p.Z();
|
||||
}
|
||||
|
||||
point3D gPntTopoint3D(gp_Pnt& p)
|
||||
{
|
||||
point3D result;
|
||||
result.x = p.X();
|
||||
result.y = p.Y();
|
||||
result.z = p.Z();
|
||||
return result;
|
||||
}
|
||||
|
||||
ImpExpDxfWrite::ImpExpDxfWrite(std::string filepath) :
|
||||
CDxfWrite(filepath.c_str()),
|
||||
m_layerName("none")
|
||||
{
|
||||
setOptionSource("User parameter:BaseApp/Preferences/Mod/Draft");
|
||||
setOptions();
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::setOptions(void)
|
||||
{
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Draft");
|
||||
optionMaxLength = hGrp->GetFloat("maxsegmentlength",5.0);
|
||||
optionPolyLine = hGrp->GetBool("DiscretizeEllipses",true);
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportShape(const TopoDS_Shape input)
|
||||
{
|
||||
//export Edges
|
||||
TopExp_Explorer edges(input, TopAbs_EDGE);
|
||||
for (int i = 1 ; edges.More(); edges.Next(),i++) {
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(edges.Current());
|
||||
BRepAdaptor_Curve adapt(edge);
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
double f = adapt.FirstParameter();
|
||||
double l = adapt.LastParameter();
|
||||
gp_Pnt s = adapt.Value(f);
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
exportCircle(adapt);
|
||||
} else {
|
||||
exportArc(adapt);
|
||||
}
|
||||
} else if (adapt.GetType() == GeomAbs_Ellipse) {
|
||||
double f = adapt.FirstParameter();
|
||||
double l = adapt.LastParameter();
|
||||
gp_Pnt s = adapt.Value(f);
|
||||
gp_Pnt e = adapt.Value(l);
|
||||
if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
|
||||
exportEllipse(adapt);
|
||||
} else {
|
||||
exportEllipseArc(adapt);
|
||||
}
|
||||
|
||||
} else if (adapt.GetType() == GeomAbs_BSplineCurve) {
|
||||
if (optionPolyLine) {
|
||||
exportLWPoly(adapt);
|
||||
} else {
|
||||
exportBSpline(adapt);
|
||||
}
|
||||
} else if (adapt.GetType() == GeomAbs_BezierCurve) {
|
||||
exportBCurve(adapt);
|
||||
} else if (adapt.GetType() == GeomAbs_Line) {
|
||||
exportLine(adapt);
|
||||
} else {
|
||||
Base::Console().Warning("ImpExpDxf - unknown curve type: %d\n",adapt.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
//export Vertices
|
||||
// TopExp_Explorer verts(input, TopAbs_VERTEX);
|
||||
// for (int i = 1 ; verts.More(); verts.Next(),i++) {
|
||||
// const TopoDS_Vertex& v = TopoDS::Vertex(verts.Current());
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportCircle(BRepAdaptor_Curve c)
|
||||
{
|
||||
gp_Circ circ = c.Circle();
|
||||
gp_Pnt p = circ.Location();
|
||||
double center[3] = {0,0,0};
|
||||
gPntToTuple(center, p);
|
||||
|
||||
double radius = circ.Radius();
|
||||
|
||||
WriteCircle(center, radius, getLayerName().c_str());
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportEllipse(BRepAdaptor_Curve c)
|
||||
{
|
||||
gp_Elips ellp = c.Ellipse();
|
||||
gp_Pnt p = ellp.Location();
|
||||
double center[3] = {0,0,0};
|
||||
gPntToTuple(center, p);
|
||||
|
||||
double major = ellp.MajorRadius();
|
||||
double minor = ellp.MinorRadius();
|
||||
|
||||
gp_Dir xaxis = ellp.XAxis().Direction(); //direction of major axis
|
||||
//rotation appears to be the clockwise(?) angle between major & +Y??
|
||||
double rotation = xaxis.AngleWithRef(gp_Dir(0, 1, 0), gp_Dir(0, 0, 1));
|
||||
|
||||
//2*M_PI = 6.28319 is invalid(doesn't display in LibreCAD), but 2PI = 6.28318 is valid!
|
||||
//WriteEllipse(center, major, minor, rotation, 0.0, 2 * M_PI, true, getLayerName().c_str() );
|
||||
WriteEllipse(center, major, minor, rotation, 0.0, 6.28318, true, getLayerName().c_str() );
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportArc(BRepAdaptor_Curve c)
|
||||
{
|
||||
gp_Circ circ = c.Circle();
|
||||
gp_Pnt p = circ.Location();
|
||||
double center[3] = {0,0,0};
|
||||
gPntToTuple(center, p);
|
||||
|
||||
double f = c.FirstParameter();
|
||||
double l = c.LastParameter();
|
||||
gp_Pnt s = c.Value(f);
|
||||
double start[3];
|
||||
gPntToTuple(start, s);
|
||||
gp_Pnt m = c.Value((l+f)/2.0);
|
||||
gp_Pnt e = c.Value(l);
|
||||
double end[3] = {0,0,0};
|
||||
gPntToTuple(end, e);
|
||||
|
||||
gp_Vec v1(m,s);
|
||||
gp_Vec v2(m,e);
|
||||
gp_Vec v3(0,0,1);
|
||||
double a = v3.DotCross(v1,v2);
|
||||
|
||||
bool dir = (a < 0) ? true: false;
|
||||
WriteArc(start, end, center, dir, getLayerName().c_str() );
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportEllipseArc(BRepAdaptor_Curve c)
|
||||
{
|
||||
gp_Elips ellp = c.Ellipse();
|
||||
gp_Pnt p = ellp.Location();
|
||||
double center[3] = {0,0,0};
|
||||
gPntToTuple(center, p);
|
||||
|
||||
double major = ellp.MajorRadius();
|
||||
double minor = ellp.MinorRadius();
|
||||
|
||||
gp_Dir xaxis = ellp.XAxis().Direction(); //direction of major axis
|
||||
//rotation appears to be the clockwise angle between major & +Y??
|
||||
double rotation = xaxis.AngleWithRef(gp_Dir(0, 1, 0), gp_Dir(0, 0, 1));
|
||||
|
||||
double f = c.FirstParameter();
|
||||
double l = c.LastParameter();
|
||||
gp_Pnt s = c.Value(f);
|
||||
gp_Pnt m = c.Value((l+f)/2.0);
|
||||
gp_Pnt e = c.Value(l);
|
||||
|
||||
gp_Vec v1(m,s);
|
||||
gp_Vec v2(m,e);
|
||||
gp_Vec v3(0,0,1);
|
||||
double a = v3.DotCross(v1,v2);
|
||||
|
||||
double startAngle = fmod(f,2.0*M_PI);
|
||||
double endAngle = fmod(l,2.0*M_PI);
|
||||
bool dir = (a < 0) ? true: false;
|
||||
|
||||
WriteEllipse(center, major, minor, rotation, startAngle, endAngle, dir, getLayerName().c_str() );
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportBSpline(BRepAdaptor_Curve c)
|
||||
{
|
||||
SplineDataOut sd;
|
||||
Handle(Geom_BSplineCurve) spline;
|
||||
double f,l;
|
||||
gp_Pnt s,ePt;
|
||||
|
||||
Standard_Real tol3D = 0.001;
|
||||
Standard_Integer maxDegree = 3, maxSegment = 100;
|
||||
Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
|
||||
Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree);
|
||||
if (approx.IsDone() && approx.HasResult()) {
|
||||
spline = approx.Curve();
|
||||
} else {
|
||||
if (approx.HasResult()) { //result, but not within tolerance
|
||||
spline = approx.Curve();
|
||||
Base::Console().Message("DxfWrite::exportBSpline - result not within tolerance\n");
|
||||
} else {
|
||||
f = c.FirstParameter();
|
||||
l = c.LastParameter();
|
||||
s = c.Value(f);
|
||||
ePt = c.Value(l);
|
||||
Base::Console().Message("DxfWrite::exportBSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
|
||||
s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles());
|
||||
TColgp_Array1OfPnt controlPoints(0,1);
|
||||
controlPoints.SetValue(0,s);
|
||||
controlPoints.SetValue(1,ePt);
|
||||
spline = GeomAPI_PointsToBSpline(controlPoints,1).Curve();
|
||||
}
|
||||
}
|
||||
//WF? norm of surface containing curve??
|
||||
sd.norm.x = 0.0;
|
||||
sd.norm.y = 0.0;
|
||||
sd.norm.z = 1.0;
|
||||
|
||||
sd.flag = spline->IsClosed();
|
||||
sd.flag += spline->IsPeriodic()*2;
|
||||
sd.flag += spline->IsRational()*4;
|
||||
|
||||
sd.degree = spline->Degree();
|
||||
sd.control_points = spline->NbPoles();
|
||||
sd.knots = spline->NbKnots();
|
||||
gp_Pnt p;
|
||||
spline->D0(spline->FirstParameter(),p);
|
||||
sd.starttan = gPntTopoint3D(p);
|
||||
spline->D0(spline->LastParameter(),p);
|
||||
sd.endtan = gPntTopoint3D(p);
|
||||
|
||||
TColStd_Array1OfReal knotsequence(1,sd.knots);
|
||||
spline->KnotSequence(knotsequence);
|
||||
for (int i = knotsequence.Lower() ; i <= knotsequence.Upper(); i++) {
|
||||
sd.knot.push_back(knotsequence(i));
|
||||
}
|
||||
TColgp_Array1OfPnt poles(1,spline->NbPoles());
|
||||
spline->Poles(poles);
|
||||
for (int i = poles.Lower(); i <= poles.Upper(); i++) {
|
||||
sd.control.push_back(gPntTopoint3D(poles(i)));
|
||||
}
|
||||
//OCC doesn't have separate lists for control points and fit points.
|
||||
|
||||
WriteSpline(sd,getLayerName().c_str());
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportBCurve(BRepAdaptor_Curve c)
|
||||
{
|
||||
(void) c;
|
||||
Base::Console().Message("BCurve dxf export not yet supported\n");
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportLine(BRepAdaptor_Curve c)
|
||||
{
|
||||
double f = c.FirstParameter();
|
||||
double l = c.LastParameter();
|
||||
gp_Pnt s = c.Value(f);
|
||||
double start[3] = {0,0,0};
|
||||
gPntToTuple(start, s);
|
||||
gp_Pnt e = c.Value(l);
|
||||
double end[3] = {0,0,0};
|
||||
gPntToTuple(end, e);
|
||||
WriteLine(start, end, getLayerName().c_str());
|
||||
}
|
||||
|
||||
void ImpExpDxfWrite::exportLWPoly(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;
|
||||
|
||||
GCPnts_UniformAbscissa discretizer;
|
||||
discretizer.Initialize (c, optionMaxLength);
|
||||
std::vector<point3D> 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));
|
||||
}
|
||||
WriteLWPolyLine(pd,getLayerName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
101
src/Mod/Import/App/ImpExpDxf.h
Normal file
101
src/Mod/Import/App/ImpExpDxf.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/***************************************************************************
|
||||
* 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 IMPEXPDXF_H
|
||||
#define IMPEXPDXF_H
|
||||
|
||||
#include "dxf.h"
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
#include <App/Document.h>
|
||||
#include <gp_Pnt.hxx>
|
||||
|
||||
class BRepAdaptor_Curve;
|
||||
|
||||
namespace Import
|
||||
{
|
||||
class ImportExport ImpExpDxfRead : public CDxfRead
|
||||
{
|
||||
public:
|
||||
ImpExpDxfRead(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 char* 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 OnReadInsert(const double* point, const double* scale, const char* name, double rotation);
|
||||
void OnReadDimension(const double* s, const double* e, const double* point, double rotation);
|
||||
void AddGraphics() const;
|
||||
|
||||
// FreeCAD-specific functions
|
||||
void AddObject(Part::TopoShape *shape); //Called by OnRead functions to add Part objects
|
||||
std::string Deformat(const char* text); // Removes DXF formatting from texts
|
||||
|
||||
std::string getOptionSource() { return m_optionSource; }
|
||||
void setOptionSource(std::string s) { m_optionSource = s; }
|
||||
void setOptions(void);
|
||||
|
||||
private:
|
||||
gp_Pnt makePoint(const double* p);
|
||||
|
||||
protected:
|
||||
App::Document *document;
|
||||
bool optionGroupLayers;
|
||||
bool optionImportAnnotations;
|
||||
double optionScaling;
|
||||
std::map <std::string, std::vector <Part::TopoShape*> > layers;
|
||||
std::string m_optionSource;
|
||||
};
|
||||
|
||||
class ImportExport ImpExpDxfWrite : public CDxfWrite
|
||||
{
|
||||
public:
|
||||
ImpExpDxfWrite(std::string filepath);
|
||||
|
||||
void exportShape(const TopoDS_Shape input);
|
||||
std::string getLayerName() { return m_layerName; }
|
||||
void setLayerName(std::string s) { m_layerName = s; }
|
||||
std::string getOptionSource() { return m_optionSource; }
|
||||
void setOptionSource(std::string s) { m_optionSource = s; }
|
||||
void setOptions(void);
|
||||
|
||||
protected:
|
||||
void exportCircle(BRepAdaptor_Curve c);
|
||||
void exportEllipse(BRepAdaptor_Curve c);
|
||||
void exportArc(BRepAdaptor_Curve c);
|
||||
void exportEllipseArc(BRepAdaptor_Curve c);
|
||||
void exportBSpline(BRepAdaptor_Curve c);
|
||||
void exportBCurve(BRepAdaptor_Curve c);
|
||||
void exportLine(BRepAdaptor_Curve c);
|
||||
void exportLWPoly(BRepAdaptor_Curve c);
|
||||
std::string m_layerName;
|
||||
std::string m_optionSource;
|
||||
double optionMaxLength;
|
||||
bool optionPolyLine;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // IMPEXPDXF_H
|
||||
1973
src/Mod/Import/App/dxf.cpp
Normal file
1973
src/Mod/Import/App/dxf.cpp
Normal file
File diff suppressed because it is too large
Load Diff
209
src/Mod/Import/App/dxf.h
Normal file
209
src/Mod/Import/App/dxf.h
Normal file
@@ -0,0 +1,209 @@
|
||||
// dxf.h
|
||||
// Copyright (c) 2009, Dan Heeks
|
||||
// This program is released under the BSD license. See the file COPYING for details.
|
||||
// modified 2018 wandererfan
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
//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;
|
||||
|
||||
|
||||
//spline data for reading
|
||||
struct SplineData
|
||||
{
|
||||
double norm[3];
|
||||
int degree;
|
||||
int knots;
|
||||
int control_points;
|
||||
int fit_points;
|
||||
int flag;
|
||||
std::list<double> starttanx;
|
||||
std::list<double> starttany;
|
||||
std::list<double> starttanz;
|
||||
std::list<double> endtanx;
|
||||
std::list<double> endtany;
|
||||
std::list<double> endtanz;
|
||||
std::list<double> knot;
|
||||
std::list<double> weight;
|
||||
std::list<double> controlx;
|
||||
std::list<double> controly;
|
||||
std::list<double> controlz;
|
||||
std::list<double> fitx;
|
||||
std::list<double> fity;
|
||||
std::list<double> fitz;
|
||||
};
|
||||
|
||||
//***************************
|
||||
//data structures for writing
|
||||
//added by Wandererfan 2018 (wandererfan@gmail.com) for FreeCAD project
|
||||
struct point3D
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct SplineDataOut
|
||||
{
|
||||
point3D norm;
|
||||
int degree;
|
||||
int knots;
|
||||
int control_points;
|
||||
int fit_points;
|
||||
int flag;
|
||||
point3D starttan;
|
||||
point3D endtan;
|
||||
std::vector<double> knot;
|
||||
std::vector<double> weight;
|
||||
std::vector<point3D> control;
|
||||
std::vector<point3D> fit;
|
||||
};
|
||||
|
||||
struct LWPolyDataOut
|
||||
{
|
||||
double nVert;
|
||||
int Flag;
|
||||
double Width;
|
||||
double Elev;
|
||||
double Thick;
|
||||
std::vector<point3D> Verts;
|
||||
std::vector<double> StartWidth;
|
||||
std::vector<double> EndWidth;
|
||||
std::vector<double> Bulge;
|
||||
point3D Extr;
|
||||
};
|
||||
//********************
|
||||
|
||||
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 );
|
||||
void WriteSpline(SplineDataOut sd, const char* layer_name);
|
||||
void WriteLWPolyLine(LWPolyDataOut pd, 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);
|
||||
bool ReadInsert();
|
||||
bool ReadDimension();
|
||||
bool ReadBlockInfo();
|
||||
|
||||
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 OnReadInsert(const double* /*point*/, const double* /*scale*/, const char* /*name*/, double /*rotation*/){}
|
||||
virtual void OnReadDimension(const double* /*s*/, const double* /*e*/, const double* /*point*/, double /*rotation*/){}
|
||||
virtual void AddGraphics() const { }
|
||||
|
||||
std::string LayerName() const;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user