diff --git a/src/Mod/TechDraw/App/AppTechDraw.cpp b/src/Mod/TechDraw/App/AppTechDraw.cpp index 5814f252dc..5a4362137e 100644 --- a/src/Mod/TechDraw/App/AppTechDraw.cpp +++ b/src/Mod/TechDraw/App/AppTechDraw.cpp @@ -65,6 +65,8 @@ #include "CosmeticExtension.h" +#include "FeatureProjection.h" + namespace TechDraw { extern PyObject* initModule(); } @@ -130,6 +132,8 @@ PyMOD_INIT_FUNC(TechDraw) TechDraw::CosmeticExtension ::init(); TechDraw::CosmeticExtensionPython::init(); + TechDraw::FeatureProjection::init(); + // are these python init calls required? some modules don't have them // Python Types TechDraw::DrawPagePython ::init(); diff --git a/src/Mod/TechDraw/App/AppTechDrawPy.cpp b/src/Mod/TechDraw/App/AppTechDrawPy.cpp index 23e64468a1..e95b0a8e50 100644 --- a/src/Mod/TechDraw/App/AppTechDrawPy.cpp +++ b/src/Mod/TechDraw/App/AppTechDrawPy.cpp @@ -34,9 +34,12 @@ #include #include #include - #endif +#include + +#include + #include #include @@ -58,7 +61,6 @@ #include #include -#include #include #include "DrawProjectSplit.h" @@ -78,6 +80,10 @@ #include "HatchLine.h" #include "DrawGeomHatch.h" +#include "TechDrawExport.h" +#include "ProjectionAlgos.h" + + namespace TechDraw { //module level static C++ functions go here } @@ -90,8 +96,39 @@ using Part::TopoShapeWirePy; using Part::TopoShapeCompoundPy; using Import::ImpExpDxfWrite; +using TechDraw::ProjectionAlgos; + +using namespace std; + namespace TechDraw { +/** Copies a Python dictionary of Python strings to a C++ container. + * + * After the function call, the key-value pairs of the Python + * dictionary are copied into the target buffer as C++ pairs + * (pair). + * + * @param sourceRange is a Python dictionary (Py::Dict). Both, the + * keys and the values must be Python strings. + * + * @param targetIt refers to where the data should be inserted. Must + * be of concept output iterator. + */ +template +void copy(Py::Dict sourceRange, OutputIt targetIt) +{ + string key; + string value; + + for (auto keyPy : sourceRange.keys()) { + key = Py::String(keyPy); + value = Py::String(sourceRange[keyPy]); + *targetIt = {key, value}; + ++targetIt; + } +} + + class Module : public Py::ExtensionModule { public: @@ -133,6 +170,26 @@ public: add_varargs_method("makeGeomHatch",&Module::makeGeomHatch, "makeGeomHatch(face, [patScale], [patName], [patFile]) -- draw a geom hatch on a given face, using optionally the given scale (default 1) and a given pattern name (ex. Diamond) and .pat file (the default pattern name and/or .pat files set in preferences are used if none are given). Returns a Part compound shape." ); + add_varargs_method("project",&Module::project, + "[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = project(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the visible/invisible parts of it." + ); + add_varargs_method("projectEx",&Module::projectEx, + "[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the all parts of it." + ); + add_keyword_method("projectToSVG",&Module::projectToSVG, + "string = projectToSVG(TopoShape[, App.Vector direction, string type, float tolerance, dict vStyle, dict v0Style, dict v1Style, dict hStyle, dict h0Style, dict h1Style])\n" + " -- Project a shape and return the SVG representation as string." + ); + add_varargs_method("projectToDXF",&Module::projectToDXF, + "string = projectToDXF(TopoShape[,App.Vector Direction, string type])\n" + " -- Project a shape and return the DXF representation as string." + ); + add_varargs_method("removeSvgTags",&Module::removeSvgTags, + "string = removeSvgTags(string) -- Removes the opening and closing svg tags\n" + "and other metatags from a svg code, making it embeddable" + ); initialize("This is a module for making drawings"); // register with Python } virtual ~Module() {} @@ -362,7 +419,7 @@ private: try { App::DocumentObject* obj = 0; TechDraw::DrawViewPart* dvp = 0; - Drawing::DXFOutput dxfOut; + TechDraw::DXFOutput dxfOut; std::string dxfText; std::stringstream ss; if (PyObject_TypeCheck(viewObj, &(TechDraw::DrawViewPartPy::Type))) { @@ -419,7 +476,7 @@ private: try { App::DocumentObject* obj = 0; TechDraw::DrawViewPart* dvp = 0; - Drawing::SVGOutput svgOut; + TechDraw::SVGOutput svgOut; std::string svgText; std::stringstream ss; if (PyObject_TypeCheck(viewObj, &(TechDraw::DrawViewPartPy::Type))) { @@ -965,6 +1022,192 @@ private: return Py::None(); } + Py::Object project(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(Part::TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); + + Part::TopoShapePy* pShape = static_cast(pcObjShape); + Base::Vector3d Vector(0,0,1); + if (pcObjDir) + Vector = *static_cast(pcObjDir)->getVectorPtr(); + + ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(),Vector); + + Py::List list; + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V1)), true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H)) , true)); + list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H1)), true)); + + return list; + } + Py::Object projectEx(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + + if (!PyArg_ParseTuple(args.ptr(), "O!|O!", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir)) + throw Py::Exception(); + + TopoShapePy* pShape = static_cast(pcObjShape); + Base::Vector3d Vector(0,0,1); + if (pcObjDir) + Vector = *static_cast(pcObjDir)->getVectorPtr(); + + ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(),Vector); + + Py::List list; + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V)) , true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V1)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VN)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VO)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VI)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H)) , true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H1)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HN)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HO)), true)); + list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HI)), true)); + + return list; + } + + Py::Object projectToSVG(const Py::Tuple& args, const Py::Dict& keys) + { + static char* argNames[] = {"topoShape", "direction", "type", "tolerance", "vStyle", "v0Style", "v1Style", "hStyle", "h0Style", "h1Style", NULL}; + PyObject *pcObjShape = 0; + PyObject *pcObjDir = 0; + const char *extractionTypePy = 0; + ProjectionAlgos::ExtractionType extractionType = ProjectionAlgos::Plain; + const float tol = 0.1f; + PyObject* vStylePy = 0; + ProjectionAlgos::XmlAttributes vStyle; + PyObject* v0StylePy = 0; + ProjectionAlgos::XmlAttributes v0Style; + PyObject* v1StylePy = 0; + ProjectionAlgos::XmlAttributes v1Style; + PyObject* hStylePy = 0; + ProjectionAlgos::XmlAttributes hStyle; + PyObject* h0StylePy = 0; + ProjectionAlgos::XmlAttributes h0Style; + PyObject* h1StylePy = 0; + ProjectionAlgos::XmlAttributes h1Style; + + // Get the arguments + + if (!PyArg_ParseTupleAndKeywords( + args.ptr(), keys.ptr(), + "O!|O!sfOOOOOO", + argNames, + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, + &extractionTypePy, &tol, + &vStylePy, &v0StylePy, &v1StylePy, + &hStylePy, &h0StylePy, &h1StylePy)) + + throw Py::Exception(); + + // Convert all arguments into the right format + + TopoShapePy* pShape = static_cast(pcObjShape); + + Base::Vector3d directionVector(0,0,1); + if (pcObjDir) + directionVector = static_cast(pcObjDir)->value(); + + if (extractionTypePy && std::string(extractionTypePy) == "ShowHiddenLines") + extractionType = ProjectionAlgos::WithHidden; + + if (vStylePy) + copy(Py::Dict(vStylePy), inserter(vStyle, vStyle.begin())); + if (v0StylePy) + copy(Py::Dict(v0StylePy), inserter(v0Style, v0Style.begin())); + if (v1StylePy) + copy(Py::Dict(v1StylePy), inserter(v1Style, v1Style.begin())); + if (hStylePy) + copy(Py::Dict(hStylePy), inserter(hStyle, hStyle.begin())); + if (h0StylePy) + copy(Py::Dict(h0StylePy), inserter(h0Style, h0Style.begin())); + if (h1StylePy) + copy(Py::Dict(h1StylePy), inserter(h1Style, h1Style.begin())); + + // Execute the SVG generation + + ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(), + directionVector); + Py::String result(Alg.getSVG(extractionType, tol, + vStyle, v0Style, v1Style, + hStyle, h0Style, h1Style)); + return result; + } + + Py::Object projectToDXF(const Py::Tuple& args) + { + PyObject *pcObjShape; + PyObject *pcObjDir=0; + const char *type=0; + float scale=1.0f; + float tol=0.1f; + + if (!PyArg_ParseTuple(args.ptr(), "O!|O!sff", + &(TopoShapePy::Type), &pcObjShape, + &(Base::VectorPy::Type), &pcObjDir, &type, &scale, &tol)) + throw Py::Exception(); + + TopoShapePy* pShape = static_cast(pcObjShape); + Base::Vector3d Vector(0,0,1); + if (pcObjDir) + Vector = static_cast(pcObjDir)->value(); + ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(),Vector); + + bool hidden = false; + if (type && std::string(type) == "ShowHiddenLines") + hidden = true; + + Py::String result(Alg.getDXF(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol)); + return result; + } + Py::Object removeSvgTags(const Py::Tuple& args) + { + const char* svgcode; + if (!PyArg_ParseTuple(args.ptr(), "s",&svgcode)) + throw Py::Exception(); + + std::string svg(svgcode); + std::string empty = ""; + std::string endline = "--endOfLine--"; + std::string linebreak = "\\n"; + // removing linebreaks for regex to work + boost::regex e1 ("\\n"); + svg = boost::regex_replace(svg, e1, endline); + // removing starting xml definition + boost::regex e2 ("<\\?xml.*?\\?>"); + svg = boost::regex_replace(svg, e2, empty); + // removing starting svg tag + boost::regex e3 (""); + svg = boost::regex_replace(svg, e3, empty); + // removing sodipodi tags -- DANGEROUS, some sodipodi tags are single, better leave it + //boost::regex e4 (""); + //svg = boost::regex_replace(svg, e4, empty); + // removing metadata tags + boost::regex e5 (""); + svg = boost::regex_replace(svg, e5, empty); + // removing closing svg tags + boost::regex e6 (""); + svg = boost::regex_replace(svg, e6, empty); + // restoring linebreaks + boost::regex e7 ("--endOfLine--"); + svg = boost::regex_replace(svg, e7, linebreak); + Py::String result(svg); + return result; + } }; diff --git a/src/Mod/TechDraw/App/CMakeLists.txt b/src/Mod/TechDraw/App/CMakeLists.txt index 5df6d59b72..7d8b63e4d2 100644 --- a/src/Mod/TechDraw/App/CMakeLists.txt +++ b/src/Mod/TechDraw/App/CMakeLists.txt @@ -132,6 +132,8 @@ SET(Draw_SRCS DrawTileWeld.h DrawWeldSymbol.cpp DrawWeldSymbol.h + FeatureProjection.cpp + FeatureProjection.h ) SET(TechDraw_SRCS @@ -157,6 +159,10 @@ SET(TechDraw_SRCS ArrowPropEnum.h Preferences.cpp Preferences.h + TechDrawExport.cpp + TechDrawExport.h + ProjectionAlgos.cpp + ProjectionAlgos.h ) SET(Geometry_SRCS diff --git a/src/Mod/TechDraw/App/FeatureProjection.cpp b/src/Mod/TechDraw/App/FeatureProjection.cpp new file mode 100644 index 0000000000..3acf63af0c --- /dev/null +++ b/src/Mod/TechDraw/App/FeatureProjection.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (c) 2009 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +#endif + + +#include +#include +#include +#include + +#include "FeatureProjection.h" +#include "ProjectionAlgos.h" + +using namespace TechDraw; + + +PROPERTY_SOURCE(TechDraw::FeatureProjection, Part::Feature) + + +FeatureProjection::FeatureProjection() +{ + static const char *group = "Projection"; + ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"Shape to project"); + ADD_PROPERTY_TYPE(Direction ,(Base::Vector3d(0,0,1)),group,App::Prop_None,"Projection direction"); + ADD_PROPERTY_TYPE(VCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(Rg1LineVCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(RgNLineVCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(OutLineVCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(IsoLineVCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(HCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(Rg1LineHCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(RgNLineHCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(OutLineHCompound ,(true),group,App::Prop_None,"Projection parameter"); + ADD_PROPERTY_TYPE(IsoLineHCompound ,(true),group,App::Prop_None,"Projection parameter"); +} + +FeatureProjection::~FeatureProjection() +{ +} + +App::DocumentObjectExecReturn *FeatureProjection::execute(void) +{ + App::DocumentObject* link = Source.getValue(); + if (!link) + return new App::DocumentObjectExecReturn("No object linked"); + if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Linked object is not a Part object"); + const TopoDS_Shape& shape = static_cast(link)->Shape.getShape().getShape(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Linked shape object is empty"); + + try { + const Base::Vector3d& dir = Direction.getValue(); + TechDraw::ProjectionAlgos alg(shape, dir); + + TopoDS_Compound comp; + BRep_Builder builder; + builder.MakeCompound(comp); + if (!alg.V.IsNull() && VCompound.getValue()) + builder.Add(comp, alg.V); + if (!alg.V1.IsNull() && Rg1LineVCompound.getValue()) + builder.Add(comp, alg.V1); + if (!alg.VN.IsNull() && RgNLineVCompound.getValue()) + builder.Add(comp, alg.VN); + if (!alg.VO.IsNull() && OutLineVCompound.getValue()) + builder.Add(comp, alg.VO); + if (!alg.VI.IsNull() && IsoLineVCompound.getValue()) + builder.Add(comp, alg.VI); + if (!alg.H.IsNull() && HCompound.getValue()) + builder.Add(comp, alg.H); + if (!alg.H1.IsNull() && Rg1LineHCompound.getValue()) + builder.Add(comp, alg.H1); + if (!alg.HN.IsNull() && RgNLineHCompound.getValue()) + builder.Add(comp, alg.HN); + if (!alg.HO.IsNull() && OutLineHCompound.getValue()) + builder.Add(comp, alg.HO); + if (!alg.HI.IsNull() && IsoLineHCompound.getValue()) + builder.Add(comp, alg.HI); + + Shape.setValue(comp); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure& e) { + return new App::DocumentObjectExecReturn(e.GetMessageString()); + } +} diff --git a/src/Mod/TechDraw/App/FeatureProjection.h b/src/Mod/TechDraw/App/FeatureProjection.h new file mode 100644 index 0000000000..a6b309a8ef --- /dev/null +++ b/src/Mod/TechDraw/App/FeatureProjection.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2009 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#ifndef TECHDRAW_FEATUREPROJECTION +#define TECHDRAW_FEATUREPROJECTION + + +#include +#include +#include +#include + + +namespace TechDraw +{ + + +/** Base class of all View Features in the drawing module + */ +class TechDrawExport FeatureProjection : public Part::Feature +{ + PROPERTY_HEADER(TechDraw::FeatureProjection); + +public: + /// Constructor + FeatureProjection(); + virtual ~FeatureProjection(); + + App::PropertyLink Source; + App::PropertyVector Direction; + App::PropertyBool VCompound; + App::PropertyBool Rg1LineVCompound; + App::PropertyBool RgNLineVCompound; + App::PropertyBool OutLineVCompound; + App::PropertyBool IsoLineVCompound; + App::PropertyBool HCompound; + App::PropertyBool Rg1LineHCompound; + App::PropertyBool RgNLineHCompound; + App::PropertyBool OutLineHCompound; + App::PropertyBool IsoLineHCompound; + + /** @name methods override feature */ + //@{ + /// recalculate the Feature + virtual App::DocumentObjectExecReturn *execute(void); + //@} +}; + +} //namespace TechDraw + + + +#endif // TECHDRAW_FEATUREPROJECTION diff --git a/src/Mod/TechDraw/App/ProjectionAlgos.cpp b/src/Mod/TechDraw/App/ProjectionAlgos.cpp new file mode 100644 index 0000000000..c9a07a59c8 --- /dev/null +++ b/src/Mod/TechDraw/App/ProjectionAlgos.cpp @@ -0,0 +1,290 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ProjectionAlgos.h" +#include "TechDrawExport.h" + +using namespace TechDraw; +using namespace std; + +//=========================================================================== +// ProjectionAlgos +//=========================================================================== + + + +ProjectionAlgos::ProjectionAlgos(const TopoDS_Shape &Input, const Base::Vector3d &Dir) + : Input(Input), Direction(Dir) +{ + execute(); +} + +ProjectionAlgos::~ProjectionAlgos() +{ +} + +//added by tanderson. aka blobfish. +//projection algorithms build a 2d curve(pcurve) but no 3d curve. +//this causes problems with meshing algorithms after save and load. +static const TopoDS_Shape& build3dCurves(const TopoDS_Shape &shape) +{ + TopExp_Explorer it; + for (it.Init(shape, TopAbs_EDGE); it.More(); it.Next()) + BRepLib::BuildCurve3d(TopoDS::Edge(it.Current())); + return shape; +} + +void ProjectionAlgos::execute(void) +{ + Handle( HLRBRep_Algo ) brep_hlr = new HLRBRep_Algo; + brep_hlr->Add(Input); + + gp_Ax2 transform(gp_Pnt(0,0,0),gp_Dir(Direction.x,Direction.y,Direction.z)); + HLRAlgo_Projector projector( transform ); + brep_hlr->Projector(projector); + brep_hlr->Update(); + brep_hlr->Hide(); + + // extracting the result sets: + HLRBRep_HLRToShape shapes( brep_hlr ); + + V = build3dCurves(shapes.VCompound ());// hard edge visibly + V1 = build3dCurves(shapes.Rg1LineVCompound());// Smoth edges visibly + VN = build3dCurves(shapes.RgNLineVCompound());// contour edges visibly + VO = build3dCurves(shapes.OutLineVCompound());// contours apparents visibly + VI = build3dCurves(shapes.IsoLineVCompound());// isoparamtriques visibly + H = build3dCurves(shapes.HCompound ());// hard edge invisibly + H1 = build3dCurves(shapes.Rg1LineHCompound());// Smoth edges invisibly + HN = build3dCurves(shapes.RgNLineHCompound());// contour edges invisibly + HO = build3dCurves(shapes.OutLineHCompound());// contours apparents invisibly + HI = build3dCurves(shapes.IsoLineHCompound());// isoparamtriques invisibly +} + +string ProjectionAlgos::getSVG(ExtractionType type, + double tolerance, + XmlAttributes V_style, + XmlAttributes V0_style, + XmlAttributes V1_style, + XmlAttributes H_style, + XmlAttributes H0_style, + XmlAttributes H1_style) +{ + stringstream result; + SVGOutput output; + + if (!H.IsNull() && (type & WithHidden)) { + H_style.insert({"stroke", "rgb(0, 0, 0)"}); + H_style.insert({"stroke-width", "0.15"}); + H_style.insert({"stroke-linecap", "butt"}); + H_style.insert({"stroke-linejoin", "miter"}); + H_style.insert({"stroke-dasharray", "0.2,0.1)"}); + H_style.insert({"fill", "none"}); + H_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(H,tolerance); + result << "" << endl + << output.exportEdges(H) + << "" << endl; + } + if (!HO.IsNull() && (type & WithHidden)) { + H0_style.insert({"stroke", "rgb(0, 0, 0)"}); + H0_style.insert({"stroke-width", "0.15"}); + H0_style.insert({"stroke-linecap", "butt"}); + H0_style.insert({"stroke-linejoin", "miter"}); + H0_style.insert({"stroke-dasharray", "0.02,0.1)"}); + H0_style.insert({"fill", "none"}); + H0_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(HO,tolerance); + result << "" << endl + << output.exportEdges(HO) + << "" << endl; + } + if (!VO.IsNull()) { + V0_style.insert({"stroke", "rgb(0, 0, 0)"}); + V0_style.insert({"stroke-width", "1.0"}); + V0_style.insert({"stroke-linecap", "butt"}); + V0_style.insert({"stroke-linejoin", "miter"}); + V0_style.insert({"fill", "none"}); + V0_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(VO,tolerance); + result << "" << endl + << output.exportEdges(VO) + << "" << endl; + } + if (!V.IsNull()) { + V_style.insert({"stroke", "rgb(0, 0, 0)"}); + V_style.insert({"stroke-width", "1.0"}); + V_style.insert({"stroke-linecap", "butt"}); + V_style.insert({"stroke-linejoin", "miter"}); + V_style.insert({"fill", "none"}); + V_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(V,tolerance); + result << "" << endl + << output.exportEdges(V) + << "" << endl; + } + if (!V1.IsNull() && (type & WithSmooth)) { + V1_style.insert({"stroke", "rgb(0, 0, 0)"}); + V1_style.insert({"stroke-width", "1.0"}); + V1_style.insert({"stroke-linecap", "butt"}); + V1_style.insert({"stroke-linejoin", "miter"}); + V1_style.insert({"fill", "none"}); + V1_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(V1,tolerance); + result << "" << endl + << output.exportEdges(V1) + << "" << endl; + } + if (!H1.IsNull() && (type & WithSmooth) && (type & WithHidden)) { + H1_style.insert({"stroke", "rgb(0, 0, 0)"}); + H1_style.insert({"stroke-width", "0.15"}); + H1_style.insert({"stroke-linecap", "butt"}); + H1_style.insert({"stroke-linejoin", "miter"}); + H1_style.insert({"stroke-dasharray", "0.09,0.05)"}); + H1_style.insert({"fill", "none"}); + H1_style.insert({"transform", "scale(1,-1)"}); + BRepMesh_IncrementalMesh(H1,tolerance); + result << "" << endl + << output.exportEdges(H1) + << "" << endl; + } + return result.str(); +} + +/* dxf output section - Dan Falck 2011/09/25 */ + +string ProjectionAlgos::getDXF(ExtractionType type, double /*scale*/, double tolerance) +{ + stringstream result; + DXFOutput output; + + if (!H.IsNull() && (type & WithHidden)) { + //float width = 0.15f/scale; + BRepMesh_IncrementalMesh(H,tolerance); + result << output.exportEdges(H); + } + if (!HO.IsNull() && (type & WithHidden)) { + //float width = 0.15f/scale; + BRepMesh_IncrementalMesh(HO,tolerance); + result << output.exportEdges(HO); + } + if (!VO.IsNull()) { + //float width = 0.35f/scale; + BRepMesh_IncrementalMesh(VO,tolerance); + result << output.exportEdges(VO); + } + if (!V.IsNull()) { + //float width = 0.35f/scale; + BRepMesh_IncrementalMesh(V,tolerance); + result << output.exportEdges(V); + } + if (!V1.IsNull() && (type & WithSmooth)) { + //float width = 0.35f/scale; + BRepMesh_IncrementalMesh(V1,tolerance); + result << output.exportEdges(V1); + } + if (!H1.IsNull() && (type & WithSmooth) && (type & WithHidden)) { + //float width = 0.15f/scale; + BRepMesh_IncrementalMesh(H1,tolerance); + result << output.exportEdges(H1); + } + + return result.str(); +} diff --git a/src/Mod/TechDraw/App/ProjectionAlgos.h b/src/Mod/TechDraw/App/ProjectionAlgos.h new file mode 100644 index 0000000000..dd60216c99 --- /dev/null +++ b/src/Mod/TechDraw/App/ProjectionAlgos.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2009 * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#ifndef _TechDrawProjectionAlgos_h_ +#define _TechDrawProjectionAlgos_h_ + +#include + +#include +#include +#include + +class BRepAdaptor_Curve; + +namespace TechDraw +{ + +/** Algo class for projecting shapes and creating SVG output of it + */ +class TechDrawExport ProjectionAlgos +{ +public: + /// Constructor + ProjectionAlgos(const TopoDS_Shape &Input,const Base::Vector3d &Dir); + virtual ~ProjectionAlgos(); + + void execute(void); + + enum ExtractionType { + Plain = 0, + WithHidden = 1, + WithSmooth = 2 + }; + typedef std::map XmlAttributes; + + std::string getSVG(ExtractionType type, double tolerance=0.05, + XmlAttributes V_style=XmlAttributes(), + XmlAttributes V0_style=XmlAttributes(), + XmlAttributes V1_style=XmlAttributes(), + XmlAttributes H_style=XmlAttributes(), + XmlAttributes H0_style=XmlAttributes(), + XmlAttributes H1_style=XmlAttributes()); + std::string getDXF(ExtractionType type, double scale, double tolerance);//added by Dan Falck 2011/09/25 + + + const TopoDS_Shape &Input; + const Base::Vector3d &Direction; + + TopoDS_Shape V ;// hard edge visibly + TopoDS_Shape V1;// Smoth edges visibly + TopoDS_Shape VN;// contour edges visibly + TopoDS_Shape VO;// contours apparents visibly + TopoDS_Shape VI;// isoparamtriques visibly + TopoDS_Shape H ;// hard edge invisibly + TopoDS_Shape H1;// Smoth edges invisibly + TopoDS_Shape HN;// contour edges invisibly + TopoDS_Shape HO;// contours apparents invisibly + TopoDS_Shape HI;// isoparamtriques invisibly +}; + +} //namespace TechDraw + + +#endif diff --git a/src/Mod/TechDraw/App/TechDrawExport.cpp b/src/Mod/TechDraw/App/TechDrawExport.cpp new file mode 100644 index 0000000000..f447343c82 --- /dev/null +++ b/src/Mod/TechDraw/App/TechDrawExport.cpp @@ -0,0 +1,771 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if OCC_VERSION_HEX < 0x070600 +#include +#endif + +#include "TechDrawExport.h" +#include +#include + +#if OCC_VERSION_HEX >= 0x070600 +using BRepAdaptor_HCurve = BRepAdaptor_Curve; +#endif + +using namespace TechDraw; +using namespace std; + +TopoDS_Edge TechDrawOutput::asCircle(const BRepAdaptor_Curve& c) const +{ + double curv=0; + gp_Pnt pnt, center; + + try { + // approximate the circle center from three positions + BRepLProp_CLProps prop(c,c.FirstParameter(),2,Precision::Confusion()); + curv += prop.Curvature(); + prop.CentreOfCurvature(pnt); + center.ChangeCoord().Add(pnt.Coord()); + + prop.SetParameter(0.5*(c.FirstParameter()+c.LastParameter())); + curv += prop.Curvature(); + prop.CentreOfCurvature(pnt); + center.ChangeCoord().Add(pnt.Coord()); + + prop.SetParameter(c.LastParameter()); + curv += prop.Curvature(); + prop.CentreOfCurvature(pnt); + center.ChangeCoord().Add(pnt.Coord()); + + center.ChangeCoord().Divide(3); + curv /= 3; + } + catch (Standard_Failure&) { + // if getting center of curvature fails, e.g. + // for straight lines it raises LProp_NotDefined + return TopoDS_Edge(); + } + + // get circle from curvature information + double radius = 1 / curv; + + TopLoc_Location location; + Handle(Poly_Polygon3D) polygon = BRep_Tool::Polygon3D(c.Edge(), location); + if (!polygon.IsNull()) { + const TColgp_Array1OfPnt& nodes = polygon->Nodes(); + for (int i = nodes.Lower(); i <= nodes.Upper(); i++) { + gp_Pnt p = nodes(i); + double dist = p.Distance(center); + if (std::abs(dist - radius) > 0.001) + return TopoDS_Edge(); + } + + gp_Circ circ; + circ.SetLocation(center); + circ.SetRadius(radius); + gp_Pnt p1 = nodes(nodes.Lower()); + gp_Pnt p2 = nodes(nodes.Upper()); + double dist = p1.Distance(p2); + + if (dist < Precision::Confusion()) { + BRepBuilderAPI_MakeEdge mkEdge(circ); + return mkEdge.Edge(); + } + else { + gp_Vec dir1(center, p1); + dir1.Normalize(); + gp_Vec dir2(center, p2); + dir2.Normalize(); + p1 = gp_Pnt(center.XYZ() + radius * dir1.XYZ()); + p2 = gp_Pnt(center.XYZ() + radius * dir2.XYZ()); + BRepBuilderAPI_MakeEdge mkEdge(circ, p1, p2); + return mkEdge.Edge(); + } + } + + return TopoDS_Edge(); +} + +TopoDS_Edge TechDrawOutput::asBSpline(const BRepAdaptor_Curve& c, int maxDegree) const +{ + Standard_Real tol3D = 0.001; + Standard_Integer maxSegment = 50; + Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c); + // approximate the curve using a tolerance + Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree); + if (approx.IsDone() && approx.HasResult()) { + // have the result + Handle(Geom_BSplineCurve) spline = approx.Curve(); + BRepBuilderAPI_MakeEdge mkEdge(spline, spline->FirstParameter(), spline->LastParameter()); + return mkEdge.Edge(); + } + + return TopoDS_Edge(); +} + +SVGOutput::SVGOutput() +{ +} + +std::string SVGOutput::exportEdges(const TopoDS_Shape& input) +{ + std::stringstream result; + + 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) { + printCircle(adapt, result); + } + else if (adapt.GetType() == GeomAbs_Ellipse) { + printEllipse(adapt, i, result); + } + else if (adapt.GetType() == GeomAbs_BSplineCurve) { +// TopoDS_Edge circle = asCircle(adapt); +// if (circle.IsNull()) { + printBSpline(adapt, i, result); +// } +// else { +// BRepAdaptor_Curve adapt_circle(circle); +// printCircle(adapt_circle, result); +// } + } + else if (adapt.GetType() == GeomAbs_BezierCurve) { + printBezier(adapt, i, result); + } + // fallback + else { + printGeneric(adapt, i, result); + } + } + + return result.str(); +} + +void SVGOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) +{ + gp_Circ circ = c.Circle(); + const gp_Pnt& p= circ.Location(); + double r = circ.Radius(); + 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); + + // a full circle + if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { + out << ""; + } + // arc of circle + else { + // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths + char xar = '0'; // x-axis-rotation + char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag + char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) + out << ""; + } +} + +void SVGOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& out) +{ + gp_Elips ellp = c.Ellipse(); + const gp_Pnt& p= ellp.Location(); + double r1 = ellp.MajorRadius(); + double r2 = ellp.MinorRadius(); + 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); + + // If the minor radius is very small compared to the major radius + // the geometry actually degenerates to a line + double ratio = std::min(r1,r2)/std::max(r1,r2); + if (ratio < 0.001) { + printGeneric(c, id, out); + return; + } + + gp_Vec v1(m,s); + gp_Vec v2(m,e); + gp_Vec v3(0,0,1); + double a = v3.DotCross(v1,v2); + + // a full ellipse + // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths + gp_Dir xaxis = ellp.XAxis().Direction(); + Standard_Real angle = xaxis.AngleWithRef(gp_Dir(1,0,0),gp_Dir(0,0,-1)); + angle = Base::toDegrees(angle); + if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { + out << "" << std::endl; + out << "" << std::endl; + out << "" << std::endl; + } + // arc of ellipse + else { + char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag + char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) + out << "" << std::endl; + } +} + +void SVGOutput::printBezier(const BRepAdaptor_Curve& c, int id, std::ostream& out) +{ + try { + std::stringstream str; + str << "NbPoles(); + + // if it's a bezier with degree higher than 3 convert it into a B-spline + if (bezier->Degree() > 3 || bezier->IsRational()) { + TopoDS_Edge edge = asBSpline(c, 3); + if (!edge.IsNull()) { + BRepAdaptor_Curve spline(edge); + printBSpline(spline, id, out); + } + else { + Standard_Failure::Raise("do it the generic way"); + } + + return; + } + + + gp_Pnt p1 = bezier->Pole(1); + str << p1.X() << "," << p1.Y(); + if (bezier->Degree() == 3) { + if (poles != 4) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + gp_Pnt p4 = bezier->Pole(4); + str << " C" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " " + << p4.X() << "," << p4.Y() << " "; + } + else if (bezier->Degree() == 2) { + if (poles != 3) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + str << " Q" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " "; + } + else if (bezier->Degree() == 1) { + if (poles != 2) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + str << " L" << p2.X() << "," << p2.Y() << " "; + } + else { + Standard_Failure::Raise("do it the generic way"); + } + + str << "\" />"; + out << str.str(); + } + catch (Standard_Failure&) { + printGeneric(c, id, out); + } +} + +void SVGOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) +{ + try { + std::stringstream str; + Handle(Geom_BSplineCurve) spline; + Standard_Real tol3D = 0.001; + Standard_Integer maxDegree = 3, maxSegment = 100; + Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c); + // approximate the curve using a tolerance + Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree); + if (approx.IsDone() && approx.HasResult()) { + // have the result + spline = approx.Curve(); + } else { + printGeneric(c, id, out); + return; + } + + GeomConvert_BSplineCurveToBezierCurve crt(spline); + Standard_Integer arcs = crt.NbArcs(); + str << "NbPoles(); + if (i == 1) { + gp_Pnt p1 = bezier->Pole(1); + str << p1.X() << "," << p1.Y(); + } + if (bezier->Degree() == 3) { + if (poles != 4) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + gp_Pnt p4 = bezier->Pole(4); + str << " C" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " " + << p4.X() << "," << p4.Y() << " "; + } + else if (bezier->Degree() == 2) { + if (poles != 3) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + gp_Pnt p3 = bezier->Pole(3); + str << " Q" + << p2.X() << "," << p2.Y() << " " + << p3.X() << "," << p3.Y() << " "; + } + else if (bezier->Degree() == 1) { + if (poles != 2) + Standard_Failure::Raise("do it the generic way"); + gp_Pnt p2 = bezier->Pole(2); + str << " L" << p2.X() << "," << p2.Y() << " "; + } + else { + Standard_Failure::Raise("do it the generic way"); + } + } + + str << "\" />"; + out << str.str(); + } + catch (Standard_Failure&) { + printGeneric(c, id, out); + } +} + +void SVGOutput::printGeneric(const BRepAdaptor_Curve& bac, int id, std::ostream& out) +{ + TopLoc_Location location; + Handle(Poly_Polygon3D) polygon = BRep_Tool::Polygon3D(bac.Edge(), location); + if (!polygon.IsNull()) { + const TColgp_Array1OfPnt& nodes = polygon->Nodes(); + char c = 'M'; + out << "" << endl; + } else if (bac.GetType() == GeomAbs_Line) { + //BRep_Tool::Polygon3D assumes the edge has polygon representation - ie already been "tessellated" + //this is not true for all edges, especially "floating edges" + double f = bac.FirstParameter(); + double l = bac.LastParameter(); + gp_Pnt s = bac.Value(f); + gp_Pnt e = bac.Value(l); + char c = 'M'; + out << "" << endl; + } +} + +// ---------------------------------------------------------------------------- + +DXFOutput::DXFOutput() +{ +} + +std::string DXFOutput::exportEdges(const TopoDS_Shape& input) +{ + std::stringstream result; + + 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) { + printCircle(adapt, result); + } + else if (adapt.GetType() == GeomAbs_Ellipse) { + printEllipse(adapt, i, result); + } + else if (adapt.GetType() == GeomAbs_BSplineCurve) { + printBSpline(adapt, i, result); + } + // fallback + else { + printGeneric(adapt, i, result); + } + } + + return result.str(); +} + +void DXFOutput::printHeader( std::ostream& out) +{ + out << 0 << endl; + out << "SECTION" << endl; + out << 2 << endl; + out << "ENTITIES" << endl; +} + +void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out) +{ + gp_Circ circ = c.Circle(); + //const gp_Ax1& axis = c->Axis(); + const gp_Pnt& p= circ.Location(); + double r = circ.Radius(); + 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); + + // a full circle + if (s.SquareDistance(e) < 0.001) { + //out << ""; + out << 0 << endl; + out << "CIRCLE" << endl; + out << 8 << endl; // Group code for layer name + out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbCircle" << endl; + out << 10 << endl; // Centre X + out << p.X() << endl; // X in WCS coordinates + out << 20 << endl; + out << p.Y() << endl; // Y in WCS coordinates + out << 30 << endl; + out << 0 << endl; // Z in WCS coordinates-leaving flat + out << 40 << endl; // + out << r << endl; // Radius + } + + + + // arc of circle + else { + // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths + /*char xar = '0'; // x-axis-rotation + char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag + char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) + out << "";*/ + double ax = s.X() - p.X(); + double ay = s.Y() - p.Y(); + double bx = e.X() - p.X(); + double by = e.Y() - p.Y(); + + double start_angle = atan2(ay, ax) * 180/D_PI; + double end_angle = atan2(by, bx) * 180/D_PI; + + + if(a > 0){ + double temp = start_angle; + start_angle = end_angle; + end_angle = temp;} + out << 0 << endl; + out << "ARC" << endl; + out << 8 << endl; // Group code for layer name + out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbCircle" << endl; + out << 10 << endl; // Centre X + out << p.X() << endl; // X in WCS coordinates + out << 20 << endl; + out << p.Y() << endl; // Y in WCS coordinates + out << 30 << endl; + out << 0 << endl; // Z in WCS coordinates + out << 40 << endl; // + out << r << endl; // Radius + out << "100" << endl; + out << "AcDbArc" << endl; + out << 50 << endl; + out << start_angle << endl; // Start angle + out << 51 << endl; + out << end_angle << endl; // End angle + + + + } +} + +void DXFOutput::printEllipse(const BRepAdaptor_Curve& c, int /*id*/, std::ostream& out) +{ + gp_Elips ellp = c.Ellipse(); + const gp_Pnt& p= ellp.Location(); + double r1 = ellp.MajorRadius(); + double r2 = ellp.MinorRadius(); + double dp = ellp.Axis().Direction().Dot(gp_Vec(0,0,1)); + + // a full ellipse + /* if (s.SquareDistance(e) < 0.001) { + out << ""; + } + // arc of ellipse + else { + // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths + gp_Dir xaxis = ellp.XAxis().Direction(); + Standard_Real angle = xaxis.Angle(gp_Dir(1,0,0)); + angle = Base::toDegrees(angle); + char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag + char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) + out << ""; + }*/ + gp_Dir xaxis = ellp.XAxis().Direction(); + double angle = xaxis.AngleWithRef(gp_Dir(1,0,0),gp_Dir(0,0,-1)); + //double rotation = Base::toDegrees(angle); + + double start_angle = c.FirstParameter(); + double end_angle = c.LastParameter(); + + double major_x;double major_y; + + major_x = r1 * cos(angle); + major_y = r1 * sin(angle); + + double ratio = r2/r1; + + if(dp < 0){ + double temp = start_angle; + start_angle = end_angle; + end_angle = temp; + } + out << 0 << endl; + out << "ELLIPSE" << endl; + out << 8 << endl; // Group code for layer name + out << "sheet_layer" << endl; // Layer number + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbEllipse" << endl; + out << 10 << endl; // Centre X + out << p.X() << endl; // X in WCS coordinates + out << 20 << endl; + out << p.Y() << endl; // Y in WCS coordinates + out << 30 << endl; + out << 0 << endl; // Z in WCS coordinates + out << 11 << endl; // + out << major_x << endl; // Major X + out << 21 << endl; + out << major_y << endl; // Major Y + out << 31 << endl; + out << 0 << endl; // Major Z + out << 40 << endl; // + out << ratio << endl; // Ratio + out << 41 << endl; + out << start_angle << endl; // Start angle + out << 42 << endl; + out << end_angle << endl; // End angle +} + +void DXFOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) //Not even close yet- DF +{ + try { + std::stringstream str; + Handle(Geom_BSplineCurve) spline; + Standard_Real tol3D = 0.001; + Standard_Integer maxDegree = 3, maxSegment = 50; + Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c); + // approximate the curve using a tolerance + Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C0,maxSegment,maxDegree); + if (approx.IsDone() && approx.HasResult()) { + // have the result + spline = approx.Curve(); + } else { + printGeneric(c, id, out); + return; + } + + //GeomConvert_BSplineCurveToBezierCurve crt(spline); + //GeomConvert_BSplineCurveKnotSplitting crt(spline,0); + //Standard_Integer arcs = crt.NbArcs(); + //Standard_Integer arcs = crt.NbSplits()-1; + Standard_Integer m = 0; + if (spline->IsPeriodic()) { + m = spline->NbPoles() + 2*spline->Degree() - spline->Multiplicity(1) + 2; + } + else { + for (int i=1; i<= spline->NbKnots(); i++) + m += spline->Multiplicity(i); + } + TColStd_Array1OfReal knotsequence(1,m); + spline->KnotSequence(knotsequence); + TColgp_Array1OfPnt poles(1,spline->NbPoles()); + spline->Poles(poles); + + + str << 0 << endl + << "SPLINE" << endl + << 8 << endl // Group code for layer name + << "sheet_layer" << endl // Layer name + << "100" << endl + << "AcDbEntity" << endl + << "100" << endl + << "AcDbSpline" << endl + << 70 << endl + << spline->IsRational()*4 << endl //flags + << 71 << endl << spline->Degree() << endl + << 72 << endl << knotsequence.Length() << endl + << 73 << endl << poles.Length() << endl + << 74 << endl << 0 << endl; //fitpoints + + for (int i = knotsequence.Lower() ; i <= knotsequence.Upper(); i++) { + str << 40 << endl << knotsequence(i) << endl; + } + for (int i = poles.Lower(); i <= poles.Upper(); i++) { + gp_Pnt pole = poles(i); + str << 10 << endl << pole.X() << endl + << 20 << endl << pole.Y() << endl + << 30 << endl << pole.Z() << endl; + if (spline->IsRational()) { + str << 41 << endl << spline->Weight(i) << endl; + } + } + + //str << "\" />"; + out << str.str(); + } + catch (Standard_Failure&) { + printGeneric(c, id, out); + } +} + +void DXFOutput::printGeneric(const BRepAdaptor_Curve& c, int /*id*/, std::ostream& out) +{ + double uStart = c.FirstParameter(); + gp_Pnt PS; + gp_Vec VS; + c.D1(uStart, PS, VS); + + double uEnd = c.LastParameter(); + gp_Pnt PE; + gp_Vec VE; + c.D1(uEnd, PE, VE); + + out << "0" << endl; + out << "LINE" << endl; + out << "8" << endl; // Group code for layer name + out << "sheet_layer" << endl; // Layer name + out << "100" << endl; + out << "AcDbEntity" << endl; + out << "100" << endl; + out << "AcDbLine" << endl; + out << "10" << endl; // Start point of line + out << PS.X() << endl; // X in WCS coordinates + out << "20" << endl; + out << PS.Y() << endl; // Y in WCS coordinates + out << "30" << endl; + out << "0" << endl; // Z in WCS coordinates + out << "11" << endl; // End point of line + out << PE.X() << endl; // X in WCS coordinates + out << "21" << endl; + out << PE.Y() << endl; // Y in WCS coordinates + out << "31" << endl; + out << "0" << endl; // Z in WCS coordinates +} diff --git a/src/Mod/TechDraw/App/TechDrawExport.h b/src/Mod/TechDraw/App/TechDrawExport.h new file mode 100644 index 0000000000..286690d85f --- /dev/null +++ b/src/Mod/TechDraw/App/TechDrawExport.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#ifndef TECHDRAW_EXPORT_H +#define TECHDRAW_EXPORT_H + +#include + +#include +#include + +class TopoDS_Shape; +class BRepAdaptor_Curve; + +namespace TechDraw +{ + +class TechDrawExport TechDrawOutput +{ +public: + // If the curve is approximately a circle it will be returned, + // otherwise a null edge is returned. + TopoDS_Edge asCircle(const BRepAdaptor_Curve&) const; + TopoDS_Edge asBSpline(const BRepAdaptor_Curve&, int maxDegree) const; +}; + +class TechDrawExport SVGOutput : public TechDrawOutput +{ +public: + SVGOutput(); + std::string exportEdges(const TopoDS_Shape&); + +private: + void printCircle(const BRepAdaptor_Curve&, std::ostream&); + void printEllipse(const BRepAdaptor_Curve&, int id, std::ostream&); + void printBSpline(const BRepAdaptor_Curve&, int id, std::ostream&); + void printBezier(const BRepAdaptor_Curve&, int id, std::ostream&); + void printGeneric(const BRepAdaptor_Curve&, int id, std::ostream&); +}; + +/* dxf output section - Dan Falck 2011/09/25 */ +class TechDrawExport DXFOutput : public TechDrawOutput +{ +public: + DXFOutput(); + std::string exportEdges(const TopoDS_Shape&); + +private: + void printHeader(std::ostream& out); + void printCircle(const BRepAdaptor_Curve&, std::ostream&); + void printEllipse(const BRepAdaptor_Curve&, int id, std::ostream&); + void printBSpline(const BRepAdaptor_Curve&, int id, std::ostream&); + void printGeneric(const BRepAdaptor_Curve&, int id, std::ostream&); +}; + +} //namespace TechDraw + +#endif // TECHDRAW_EXPORT_H diff --git a/src/Mod/TechDraw/Gui/CMakeLists.txt b/src/Mod/TechDraw/Gui/CMakeLists.txt index 418720d2b9..06d751d661 100644 --- a/src/Mod/TechDraw/Gui/CMakeLists.txt +++ b/src/Mod/TechDraw/Gui/CMakeLists.txt @@ -84,7 +84,7 @@ set(TechDrawGui_UIC_SRCS TaskWeldingSymbol.ui SymbolChooser.ui TaskMoveView.ui - + TaskProjection.ui ) if(BUILD_QT5) @@ -210,6 +210,9 @@ SET(TechDrawGui_SRCS TaskCosmeticLine.cpp TaskCosmeticLine.h TaskMoveView.ui + TaskProjection.cpp + TaskProjection.h + TaskProjection.ui ) SET(TechDrawGuiView_SRCS @@ -381,6 +384,7 @@ SET(TechDrawGuiTaskDlgs_SRCS TaskCosmeticLine.ui TaskSelectLineAttributes.ui TaskMoveView.ui + TaskProjection.ui ) SOURCE_GROUP("TaskDialogs" FILES ${TechDrawGuiTaskDlgs_SRCS}) diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index 357bf93793..6c25453e9d 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -95,6 +95,7 @@ #include "TaskSectionView.h" #include "TaskActiveView.h" #include "TaskDetail.h" +#include "TaskProjection.h" #include "ViewProviderPage.h" #include "ViewProviderViewPart.h" @@ -1462,6 +1463,38 @@ bool CmdTechDrawExportPageDXF::isActive(void) return DrawGuiUtil::needPage(this); } +//=========================================================================== +// TechDraw_ProjectShape +//=========================================================================== + +DEF_STD_CMD_A(CmdTechDrawProjectShape) + +CmdTechDrawProjectShape::CmdTechDrawProjectShape() + : Command("TechDraw_ProjectShape") +{ + sAppModule = "TechDraw"; + sGroup = QT_TR_NOOP("TechDraw"); + sMenuText = QT_TR_NOOP("Project shape..."); + sToolTipText = sMenuText; + sWhatsThis = "TechDraw_ProjectShape"; + sStatusTip = sToolTipText; + sPixmap = "actions/TechDraw_ProjectShape"; +} + +void CmdTechDrawProjectShape::activated(int iMsg) +{ + Q_UNUSED(iMsg); + Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); + if (!dlg) { + Gui::Control().showDialog(new TaskDlgProjection()); + } +} + +bool CmdTechDrawProjectShape::isActive(void) +{ + return true; +} + void CreateTechDrawCommands(void) { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -1484,4 +1517,5 @@ void CreateTechDrawCommands(void) rcCmdMgr.addCommand(new CmdTechDrawArchView()); rcCmdMgr.addCommand(new CmdTechDrawSpreadsheetView()); rcCmdMgr.addCommand(new CmdTechDrawBalloon()); + rcCmdMgr.addCommand(new CmdTechDrawProjectShape()); } diff --git a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc index 1a77d4259b..58a0df1051 100644 --- a/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc +++ b/src/Mod/TechDraw/Gui/Resources/TechDraw.qrc @@ -111,6 +111,7 @@ icons/actions/TechDraw_WeldSymbol.svg icons/actions/TechDraw_MoveView.svg icons/actions/TechDraw_CopyView.svg + icons/actions/TechDraw_ProjectShape.svg icons/actions/section-up.svg icons/actions/section-down.svg icons/actions/section-left.svg diff --git a/src/Mod/TechDraw/Gui/Resources/icons/actions/TechDraw_ProjectShape.svg b/src/Mod/TechDraw/Gui/Resources/icons/actions/TechDraw_ProjectShape.svg new file mode 100644 index 0000000000..604a2516c6 --- /dev/null +++ b/src/Mod/TechDraw/Gui/Resources/icons/actions/TechDraw_ProjectShape.svg @@ -0,0 +1,631 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + [agryson] Alexander Gryson + + + http://agryson.net + + techdraw-view + 2016-01-14 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/TechDraw/Gui/Resources/icons/actions/techdraw-view.svg + + + FreeCAD LGPL2+ + + + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/TechDraw/Gui/TaskProjection.cpp b/src/Mod/TechDraw/Gui/TaskProjection.cpp new file mode 100644 index 0000000000..0991e4964b --- /dev/null +++ b/src/Mod/TechDraw/Gui/TaskProjection.cpp @@ -0,0 +1,171 @@ +/*************************************************************************** + * Copyright (c) 2009 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +#endif + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "TaskProjection.h" +#include "ui_TaskProjection.h" + +using namespace TechDrawGui; + +/* TRANSLATOR TechDrawGui::TaskProjection */ + +TaskProjection::TaskProjection() : + ui(new Ui_TaskProjection) +{ + + ui->setupUi(this); +} + +TaskProjection::~TaskProjection() +{ + // automatically deleted in the sub-class +} + +bool TaskProjection::accept() +{ + Gui::Document* document = Gui::Application::Instance->activeDocument(); + if (!document) { + QMessageBox::warning(Gui::getMainWindow(), tr("No active document"), + tr("There is currently no active document to complete the operation")); + return true; + } + std::list mdis = document->getMDIViewsOfType(Gui::View3DInventor::getClassTypeId()); + if (mdis.empty()) { + QMessageBox::warning(Gui::getMainWindow(), tr("No active view"), + tr("There is currently no active view to complete the operation")); + return false; + } + + Gui::View3DInventorViewer* viewer = static_cast(mdis.front())->getViewer(); + SbVec3f pnt, dir; + viewer->getNearPlane(pnt, dir); + float x=0, y=1,z=1; + dir.getValue(x,y,z); + + std::vector shapes = Gui::Selection().getObjectsOfType(); + Gui::Command::openCommand("Project shape"); + Gui::Command::addModule(Gui::Command::Doc,"TechDraw"); + for (std::vector::iterator it = shapes.begin(); it != shapes.end(); ++it) { + const char* object = (*it)->getNameInDocument(); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.addObject('TechDraw::FeatureProjection','%s_proj')", object); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.Direction=FreeCAD.Vector(%f,%f,%f)", x,y,z); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.Source=FreeCAD.ActiveDocument.%s", object); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.VCompound=%s", (ui->cbVisSharp->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.Rg1LineVCompound=%s", (ui->cbVisSmooth->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.RgNLineVCompound=%s", (ui->cbVisSewn->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.OutLineVCompound=%s", (ui->cbVisOutline->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.IsoLineVCompound=%s", (ui->cbVisIso->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.HCompound=%s", (ui->cbHidSharp->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.Rg1LineHCompound=%s", (ui->cbHidSmooth->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.RgNLineHCompound=%s", (ui->cbHidSewn->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.OutLineHCompound=%s", (ui->cbHidOutline->isChecked() ? "True" : "False")); + Gui::Command::doCommand(Gui::Command::Doc, + "FreeCAD.ActiveDocument.ActiveObject.IsoLineHCompound=%s", (ui->cbHidIso->isChecked() ? "True" : "False")); + } + Gui::Command::updateActive(); + Gui::Command::commitCommand(); + return true; +} + +bool TaskProjection::reject() +{ + return true; +} + + +/////////////////////////////////////////////////////////////////////////// + +TaskDlgProjection::TaskDlgProjection() : + TaskDialog() +{ + widget = new TaskProjection(); + taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_ProjectShape"), widget->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); + setAutoCloseOnTransactionChange(true); +} + +TaskDlgProjection::~TaskDlgProjection() +{ +} + +void TaskDlgProjection::update() +{ +} + +//==== calls from the TaskView =============================================================== +void TaskDlgProjection::open() +{ +} + +void TaskDlgProjection::clicked(int i) +{ + Q_UNUSED(i); +} + +bool TaskDlgProjection::accept() +{ + widget->accept(); + return true; +} + +bool TaskDlgProjection::reject() +{ + widget->reject(); + return true; +} + +#include "moc_TaskProjection.cpp" diff --git a/src/Mod/TechDraw/Gui/TaskProjection.h b/src/Mod/TechDraw/Gui/TaskProjection.h new file mode 100644 index 0000000000..1fa6392600 --- /dev/null +++ b/src/Mod/TechDraw/Gui/TaskProjection.h @@ -0,0 +1,96 @@ +/*************************************************************************** + * Copyright (c) 2009 Werner Mayer * + * * + * 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 * + * * + ***************************************************************************/ +//this file originally part of TechDraw workbench +//migrated to TechDraw workbench 2022-01-26 by Wandererfan + + +#ifndef TECHDRAWGUI_TASKDIALOG +#define TECHDRAWGUI_TASKDIALOG + +#include +#include +#include + +class QCheckBox; + +namespace TechDrawGui +{ + +/** + * Embed the panel into a task dialog. + */ +class Ui_TaskProjection; +class TaskProjection : public QWidget +{ + Q_OBJECT + +public: + TaskProjection(); + ~TaskProjection(); + +public: + bool accept(); + bool reject(); + + virtual bool isAllowedAlterDocument(void) const + { return true; } + +private: + std::unique_ptr ui; + +}; + + +class TaskDlgProjection : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgProjection(); + ~TaskDlgProjection(); + +public: + /// is called the TaskView when the dialog is opened + virtual void open(); + /// is called by the framework if an button is clicked which has no accept or reject role + virtual void clicked(int); + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user presses the help button + virtual void helpRequested() { return;} + + void update(); + +protected: + +private: + TaskProjection* widget; + Gui::TaskView::TaskBox* taskbox; +}; + +} //namespace TechDrawGui + + + +#endif // TECHDRAWGUI_TASKDIALOG diff --git a/src/Mod/TechDraw/Gui/TaskProjection.ui b/src/Mod/TechDraw/Gui/TaskProjection.ui new file mode 100644 index 0000000000..0000c8ad57 --- /dev/null +++ b/src/Mod/TechDraw/Gui/TaskProjection.ui @@ -0,0 +1,110 @@ + + + TechDrawGui::TaskProjection + + + + 0 + 0 + 353 + 300 + + + + Project shapes + + + + + + + + Visible sharp edges + + + true + + + + + + + Visible smooth edges + + + true + + + + + + + Visible sewn edges + + + true + + + + + + + Visible outline edges + + + true + + + + + + + Visible isoparameters + + + true + + + + + + + Hidden sharp edges + + + + + + + Hidden smooth edges + + + + + + + Hidden sewn edges + + + + + + + Hidden outline edges + + + + + + + Hidden isoparameters + + + + + + + + + + diff --git a/src/Mod/TechDraw/Gui/Workbench.cpp b/src/Mod/TechDraw/Gui/Workbench.cpp index 3094405a84..438a0a4885 100644 --- a/src/Mod/TechDraw/Gui/Workbench.cpp +++ b/src/Mod/TechDraw/Gui/Workbench.cpp @@ -207,6 +207,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const *draw << "TechDraw_DecorateLine"; *draw << "TechDraw_ShowAll"; *draw << "TechDraw_WeldSymbol"; + *draw << "Separator"; + *draw << "TechDraw_ProjectShape"; return root; } @@ -231,6 +233,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const *views << "TechDraw_SpreadsheetView"; *views << "TechDraw_MoveView"; *views << "TechDraw_CopyView"; + *views << "TechDraw_ProjectShape"; Gui::ToolBarItem *clips = new Gui::ToolBarItem(root); clips->setCommand("TechDraw Clips"); @@ -364,6 +367,8 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const *views << "TechDraw_SpreadsheetView"; *views << "TechDraw_MoveView"; *views << "TechDraw_CopyView"; + *views << "TechDraw_ProjectShape"; + Gui::ToolBarItem *clips = new Gui::ToolBarItem(root); clips->setCommand("TechDraw Clips"); diff --git a/src/Mod/TechDraw/TDTest/TDPyTest.py b/src/Mod/TechDraw/TDTest/TDPyTest.py new file mode 100644 index 0000000000..f9b8170e11 --- /dev/null +++ b/src/Mod/TechDraw/TDTest/TDPyTest.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# basic test script for TechDraw Py functions migrated from Drawing + +from __future__ import print_function + +import FreeCAD +import Part +import Measure +import TechDraw +import os + +def TDPyTest(): + path = os.path.dirname(os.path.abspath(__file__)) + print ('TDPy path: ' + path) + + FreeCAD.newDocument("TDPy") + FreeCAD.setActiveDocument("TDPy") + FreeCAD.ActiveDocument=FreeCAD.getDocument("TDPy") + + direction = FreeCAD.Vector(0.0, 1.0, 0.0) + box = FreeCAD.ActiveDocument.addObject("Part::Box","Box") + + result = TechDraw.project(box.Shape, direction) #visible hard & smooth, hidden hard & smooth + print("project result: {0}".format(result)) +# Part.show(result[0]) + + result = TechDraw.projectEx(box.Shape, direction) #visible & hidden hard, smooth, seam, outline, iso + print("projectEx result: {0}".format(result)) +# Part.show(result[0]) + + SVGResult = TechDraw.projectToSVG(box.Shape, direction, "ShowHiddenLines", 0.10) #SVG string + print("SVG result: {0}".format(SVGResult)) + + result = TechDraw.projectToDXF(box.Shape, direction) #DXF string + print("DXF result: {0}".format(result)) + + result = TechDraw.removeSvgTags(SVGResult) + print("remove tags result: {0}".format(result)) + +if __name__ == '__main__': + TDPyTest()