[Import]Flatten sketch before dxf export.

This commit is contained in:
wandererfan
2023-12-03 17:27:35 -05:00
committed by WandererFan
parent 67508fdc9b
commit e3d42e82a6
5 changed files with 199 additions and 13 deletions

View File

@@ -51,6 +51,7 @@
#endif
#include "dxf/ImpExpDxf.h"
#include "SketchExportHelper.h"
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
@@ -427,8 +428,10 @@ private:
return Py::None();
}
Py::Object writeDXFShape(const Py::Tuple& args)
{
Base::Console().Message("Imp:writeDXFShape()\n");
PyObject* shapeObj = nullptr;
char* fname = nullptr;
std::string filePath;
@@ -592,11 +595,19 @@ private:
PyObject* item = (*it).ptr();
App::DocumentObject* obj =
static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
Part::Feature* part = static_cast<Part::Feature*>(obj);
layerName = part->getNameInDocument();
layerName = obj->getNameInDocument();
writer.setLayerName(layerName);
const TopoDS_Shape& shape = part->Shape.getValue();
writer.exportShape(shape);
TopoDS_Shape shapeToExport;
if (SketchExportHelper::isSketch(obj)) {
// project sketch along sketch Z via hlrProjector to get geometry on XY plane
shapeToExport = SketchExportHelper::getFlatSketchXY(obj);
} else {
// do we know that obj is a Part::Feature? is this checked somewhere before this?
// this should be a located shape??
Part::Feature* part = static_cast<Part::Feature*>(obj);
shapeToExport = part->Shape.getValue();
}
writer.exportShape(shapeToExport);
}
}
writer.endRun();
@@ -620,6 +631,8 @@ private:
filePath = std::string(fname);
layerName = "none";
PyMem_Free(fname);
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(docObj)->getDocumentObjectPtr();
Base::Console().Message("Imp:writeDXFObject - docObj: %s\n", obj->getNameInDocument());
if ((versionParm == 12) || (versionParm == 14)) {
versionOverride = true;
@@ -644,11 +657,19 @@ private:
writer.init();
App::DocumentObject* obj =
static_cast<App::DocumentObjectPy*>(docObj)->getDocumentObjectPtr();
Part::Feature* part = static_cast<Part::Feature*>(obj);
layerName = part->getNameInDocument();
layerName = obj->getNameInDocument();
writer.setLayerName(layerName);
const TopoDS_Shape& shape = part->Shape.getValue();
writer.exportShape(shape);
TopoDS_Shape shapeToExport;
if (SketchExportHelper::isSketch(obj)) {
// project sketch along sketch Z via hlrProjector to get geometry on XY plane
shapeToExport = SketchExportHelper::getFlatSketchXY(obj);
} else {
// TODO: do we know that obj is a Part::Feature? is this checked somewhere before this?
// TODO: this should be a located shape??
Part::Feature* part = static_cast<Part::Feature*>(obj);
shapeToExport = part->Shape.getValue();
}
writer.exportShape(shapeToExport);
writer.endRun();
return Py::None();
}

View File

@@ -50,6 +50,8 @@ SET(Import_SRCS
WriterIges.h
WriterStep.cpp
WriterStep.h
SketchExportHelper.cpp
SketchExportHelper.h
dxf/ImpExpDxf.cpp
dxf/ImpExpDxf.h
dxf/dxf.cpp

View File

@@ -0,0 +1,115 @@
/***************************************************************************
* Copyright (c) 2024 WandererFan <wandererfan@gmail.com> *
* *
* 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 *
* *
***************************************************************************/
//! a class to assist with exporting sketches to dxf
#include "PreCompiled.h"
#ifndef _PreComp_
#include <HLRBRep_Algo.hxx>
#include <HLRAlgo_Projector.hxx>
#include <HLRBRep_HLRToShape.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#endif
#include <App/DocumentObject.h>
#include <Base/Placement.h>
#include <Base/Vector3D.h>
#include <Mod/Part/App/PartFeature.h>
#include "SketchExportHelper.h"
using namespace Import;
//! project a shape so that it is represented as a flat shape on the XY plane. Z coordinate information
//! is lost in this process, so it should only be used for flat objects like sketches.
//! Note: this only returns hard and outline edges. Seam, smooth, isoparametric and hidden lines are not returned.
TopoDS_Shape SketchExportHelper::projectShape(const TopoDS_Shape& inShape, const gp_Ax2& projectionCS)
{
Handle(HLRBRep_Algo) brep_hlr = new HLRBRep_Algo();
brep_hlr->Add(inShape);
HLRAlgo_Projector projector(projectionCS);
brep_hlr->Projector(projector);
brep_hlr->Update();
brep_hlr->Hide();
HLRBRep_HLRToShape hlrToShape(brep_hlr);
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
if (!hlrToShape.VCompound().IsNull()) {
builder.Add(comp, hlrToShape.VCompound());
}
if (!hlrToShape.OutLineVCompound().IsNull()) {
builder.Add(comp, hlrToShape.OutLineVCompound());
}
return comp;
}
//! true if obj is a sketch
bool SketchExportHelper::isSketch(App::DocumentObject* obj)
{
// TODO:: the check for an object being a sketch should be done as in the commented
// if statement below. To do this, we need to include Mod/Sketcher/SketchObject.h,
// but that makes Import dependent on Eigen libraries which we don't use. As a
// workaround we will inspect the object's class name.
// if (obj->isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
std::string objTypeName = obj->getTypeId().getName();
std::string sketcherToken("Sketcher");
return objTypeName.find(sketcherToken) != std::string::npos;
}
//! return a version of a sketch's geometry mapped to the OXYZ coordinate system
//! preferred by dxf
TopoDS_Shape SketchExportHelper::getFlatSketchXY(App::DocumentObject* obj)
{
// since we can't reference Sketcher module here, we will cast obj to
// a Part::Feature instead
auto sketch = dynamic_cast<Part::Feature*>(obj);
if ( !sketch || !isSketch(obj)){
return {};
}
auto plm = sketch->Placement.getValue();
Base::Rotation rot = plm.getRotation();
//get the sketch normal
Base::Vector3d stdZ{0.0, 0.0, 1.0};
Base::Vector3d sketchNormal;
rot.multVec(stdZ, sketchNormal);
Base::Vector3d stdX{1.0, 0.0, 0.0};
Base::Vector3d sketchX;
rot.multVec(stdX, sketchX);
//get the sketch origin
Base::Vector3d position = plm.getPosition();
gp_Ax2 projectionCS(gp_Pnt(position.x, position.y, position.z),
gp_Dir(sketchNormal.x, sketchNormal.y, sketchNormal.z),
gp_Dir(sketchX.x, sketchX.y, sketchX.z));
const TopoDS_Shape& shape = sketch->Shape.getValue();
return projectShape(shape, projectionCS);
}

View File

@@ -0,0 +1,46 @@
/***************************************************************************
* Copyright (c) 2024 WandererFan <wandererfan@gmail.com> *
* *
* 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 *
* *
***************************************************************************/
//! a class to assist with exporting sketches to dxf
#include <Mod/Import/ImportGlobal.h>
#include <TopoDS_Shape.hxx>
#include <gp_Ax2.hxx>
namespace App
{
class DocumentObject;
}
namespace Import
{
class ImportExport SketchExportHelper
{
public:
static TopoDS_Shape projectShape(const TopoDS_Shape& inShape, const gp_Ax2& projectionCS);
static bool isSketch(App::DocumentObject* obj);
static TopoDS_Shape getFlatSketchXY(App::DocumentObject* obj);
};
}

View File

@@ -656,7 +656,7 @@ void CDxfWrite::writePolyline(const LWPolyDataOut& pd)
(*m_ssEntity) << " 20" << endl;
(*m_ssEntity) << p.y << endl;
(*m_ssEntity) << " 30" << endl;
(*m_ssEntity) << "0.0" << endl;
(*m_ssEntity) << p.z << endl;
}
(*m_ssEntity) << " 0" << endl;
(*m_ssEntity) << "SEQEND" << endl;
@@ -692,7 +692,10 @@ void CDxfWrite::writePoint(const double* point)
(*m_ssEntity) << point[2] << endl; // Z in WCS coordinates
}
//! arc from 3 points - start, end, center. dir true if arc is AntiClockwise. unspecified assumption is that
//! points are on XY plane in coord system OXYZ.
void CDxfWrite::writeArc(const double* start, const double* end, const double* center, bool dir)
{
double ax = start[0] - center[0];
double ay = start[1] - center[1];
@@ -766,8 +769,8 @@ void CDxfWrite::writeCircle(const double* center, double radius)
(*m_ssEntity) << center[0] << endl; // X in WCS coordinates
(*m_ssEntity) << " 20" << endl;
(*m_ssEntity) << center[1] << endl; // Y in WCS coordinates
// (*m_ssEntity) << " 30" << endl;
// (*m_ssEntity) << center[2] << endl; // Z in WCS coordinates
(*m_ssEntity) << " 30" << endl;
(*m_ssEntity) << center[2] << endl; // Z in WCS coordinates
(*m_ssEntity) << " 40" << endl; //
(*m_ssEntity) << radius << endl; // Radius
}
@@ -817,8 +820,7 @@ void CDxfWrite::writeEllipse(const double* center,
(*m_ssEntity) << " 31" << endl;
(*m_ssEntity) << m.z << endl; // Major Z
(*m_ssEntity) << " 40" << endl; //
(*m_ssEntity) << ratio
<< endl; // Ratio
(*m_ssEntity) << ratio << endl; // Ratio
// (*m_ssEntity) << "210" << endl; //extrusion dir??
// (*m_ssEntity) << "0" << endl;
// (*m_ssEntity) << "220" << endl;