1
/***************************************************************************
2
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
25
#include <boost/regex.hpp>
28
#include <Base/Console.h>
29
#include <Base/Interpreter.h>
30
#include <Base/PyWrapParseTupleAndKeywords.h>
31
#include <Base/VectorPy.h>
32
#include <Mod/Part/App/OCCError.h>
33
#include <Mod/Part/App/TopoShapePy.h>
35
#include "ProjectionAlgos.h"
40
using Part::TopoShapePy;
45
/** Copies a Python dictionary of Python strings to a C++ container.
47
* After the function call, the key-value pairs of the Python
48
* dictionary are copied into the target buffer as C++ pairs
49
* (pair<string, string>).
51
* @param sourceRange is a Python dictionary (Py::Dict). Both, the
52
* keys and the values must be Python strings.
54
* @param targetIt refers to where the data should be inserted. Must
55
* be of concept output iterator.
57
template<typename OutputIt>
58
void copy(Py::Dict sourceRange, OutputIt targetIt)
63
for (const auto& keyPy : sourceRange.keys()) {
64
key = Py::String(keyPy);
65
value = Py::String(sourceRange[keyPy]);
66
*targetIt = {key, value};
72
class Module: public Py::ExtensionModule<Module>
76
: Py::ExtensionModule<Module>("Drawing")
78
add_varargs_method("project",
80
"[visiblyG0,visiblyG1,hiddenG0,hiddenG1] = "
81
"project(TopoShape[,App.Vector Direction, string type])\n"
82
" -- Project a shape and return the visible/invisible parts of it.");
83
add_varargs_method("projectEx",
85
"[V,V1,VN,VO,VI,H,H1,HN,HO,HI] = projectEx(TopoShape[,App.Vector "
86
"Direction, string type])\n"
87
" -- Project a shape and return the all parts of it.");
90
&Module::projectToSVG,
91
"string = projectToSVG(TopoShape[, App.Vector direction, string type, float tolerance, "
92
"dict vStyle, dict v0Style, dict v1Style, dict hStyle, dict h0Style, dict h1Style])\n"
93
" -- Project a shape and return the SVG representation as string.");
94
add_varargs_method("projectToDXF",
95
&Module::projectToDXF,
96
"string = projectToDXF(TopoShape[,App.Vector Direction, string type])\n"
97
" -- Project a shape and return the DXF representation as string.");
100
&Module::removeSvgTags,
101
"string = removeSvgTags(string) -- Removes the opening and closing svg tags\n"
102
"and other metatags from a svg code, making it embeddable");
103
initialize("This module is the Drawing module."); // register with Python
110
virtual Py::Object invoke_method_varargs(void* method_def, const Py::Tuple& args)
113
return Py::ExtensionModule<Module>::invoke_method_varargs(method_def, args);
115
catch (const Standard_Failure& e) {
117
Standard_CString msg = e.GetMessageString();
118
str += typeid(e).name();
124
str += "No OCCT Exception Message";
126
Base::Console().Error("%s\n", str.c_str());
127
throw Py::Exception(Part::PartExceptionOCCError, str);
129
catch (const Base::Exception& e) {
131
str += "FreeCAD exception thrown (";
135
throw Py::RuntimeError(str);
137
catch (const std::exception& e) {
139
str += "C++ exception thrown (";
142
Base::Console().Error("%s\n", str.c_str());
143
throw Py::RuntimeError(str);
146
Py::Object project(const Py::Tuple& args)
148
PyObject* pcObjShape;
149
PyObject* pcObjDir = nullptr;
151
if (!PyArg_ParseTuple(args.ptr(),
153
&(Part::TopoShapePy::Type),
155
&(Base::VectorPy::Type),
157
throw Py::Exception();
160
Part::TopoShapePy* pShape = static_cast<Part::TopoShapePy*>(pcObjShape);
161
Base::Vector3d Vector(0, 0, 1);
163
Vector = *static_cast<Base::VectorPy*>(pcObjDir)->getVectorPtr();
166
ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(), Vector);
169
list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V)), true));
170
list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.V1)), true));
171
list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H)), true));
172
list.append(Py::Object(new Part::TopoShapePy(new Part::TopoShape(Alg.H1)), true));
176
Py::Object projectEx(const Py::Tuple& args)
178
PyObject* pcObjShape;
179
PyObject* pcObjDir = nullptr;
181
if (!PyArg_ParseTuple(args.ptr(),
183
&(TopoShapePy::Type),
185
&(Base::VectorPy::Type),
187
throw Py::Exception();
190
TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObjShape);
191
Base::Vector3d Vector(0, 0, 1);
193
Vector = *static_cast<Base::VectorPy*>(pcObjDir)->getVectorPtr();
196
ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(), Vector);
199
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V)), true));
200
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.V1)), true));
201
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VN)), true));
202
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VO)), true));
203
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.VI)), true));
204
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H)), true));
205
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.H1)), true));
206
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HN)), true));
207
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HO)), true));
208
list.append(Py::Object(new TopoShapePy(new TopoShape(Alg.HI)), true));
213
Py::Object projectToSVG(const Py::Tuple& args, const Py::Dict& keys)
215
static const std::array<const char*, 11> argNames {"topoShape",
226
PyObject* pcObjShape = nullptr;
227
PyObject* pcObjDir = nullptr;
228
const char* extractionTypePy = nullptr;
229
ProjectionAlgos::ExtractionType extractionType = ProjectionAlgos::Plain;
230
const float tol = 0.1f;
231
PyObject* vStylePy = nullptr;
232
ProjectionAlgos::XmlAttributes vStyle;
233
PyObject* v0StylePy = nullptr;
234
ProjectionAlgos::XmlAttributes v0Style;
235
PyObject* v1StylePy = nullptr;
236
ProjectionAlgos::XmlAttributes v1Style;
237
PyObject* hStylePy = nullptr;
238
ProjectionAlgos::XmlAttributes hStyle;
239
PyObject* h0StylePy = nullptr;
240
ProjectionAlgos::XmlAttributes h0Style;
241
PyObject* h1StylePy = nullptr;
242
ProjectionAlgos::XmlAttributes h1Style;
246
if (!Base::Wrapped_ParseTupleAndKeywords(args.ptr(),
250
&(TopoShapePy::Type),
252
&(Base::VectorPy::Type),
263
throw Py::Exception();
266
// Convert all arguments into the right format
268
TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObjShape);
270
Base::Vector3d directionVector(0, 0, 1);
272
directionVector = static_cast<Base::VectorPy*>(pcObjDir)->value();
275
if (extractionTypePy && string(extractionTypePy) == "ShowHiddenLines") {
276
extractionType = ProjectionAlgos::WithHidden;
280
copy(Py::Dict(vStylePy), inserter(vStyle, vStyle.begin()));
283
copy(Py::Dict(v0StylePy), inserter(v0Style, v0Style.begin()));
286
copy(Py::Dict(v1StylePy), inserter(v1Style, v1Style.begin()));
289
copy(Py::Dict(hStylePy), inserter(hStyle, hStyle.begin()));
292
copy(Py::Dict(h0StylePy), inserter(h0Style, h0Style.begin()));
295
copy(Py::Dict(h1StylePy), inserter(h1Style, h1Style.begin()));
298
// Execute the SVG generation
300
ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(), directionVector);
302
Alg.getSVG(extractionType, tol, vStyle, v0Style, v1Style, hStyle, h0Style, h1Style));
306
Py::Object projectToDXF(const Py::Tuple& args)
308
PyObject* pcObjShape;
309
PyObject* pcObjDir = nullptr;
310
const char* type = nullptr;
314
if (!PyArg_ParseTuple(args.ptr(),
316
&(TopoShapePy::Type),
318
&(Base::VectorPy::Type),
323
throw Py::Exception();
326
TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObjShape);
327
Base::Vector3d Vector(0, 0, 1);
329
Vector = static_cast<Base::VectorPy*>(pcObjDir)->value();
331
ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(), Vector);
334
if (type && std::string(type) == "ShowHiddenLines") {
339
Alg.getDXF(hidden ? ProjectionAlgos::WithHidden : ProjectionAlgos::Plain, scale, tol));
342
Py::Object removeSvgTags(const Py::Tuple& args)
345
if (!PyArg_ParseTuple(args.ptr(), "s", &svgcode)) {
346
throw Py::Exception();
349
std::string svg(svgcode);
350
std::string empty = "";
351
std::string endline = "--endOfLine--";
352
std::string linebreak = "\\n";
353
// removing linebreaks for regex to work
354
boost::regex e1("\\n");
355
svg = boost::regex_replace(svg, e1, endline);
356
// removing starting xml definition
357
boost::regex e2("<\\?xml.*?\\?>");
358
svg = boost::regex_replace(svg, e2, empty);
359
// removing starting svg tag
360
boost::regex e3("<svg.*?>");
361
svg = boost::regex_replace(svg, e3, empty);
362
// removing sodipodi tags -- DANGEROUS, some sodipodi tags are single, better leave it
363
// boost::regex e4 ("<sodipodi.*?>");
364
// svg = boost::regex_replace(svg, e4, empty);
365
// removing metadata tags
366
boost::regex e5("<metadata.*?</metadata>");
367
svg = boost::regex_replace(svg, e5, empty);
368
// removing closing svg tags
369
boost::regex e6("</svg>");
370
svg = boost::regex_replace(svg, e6, empty);
371
// restoring linebreaks
372
boost::regex e7("--endOfLine--");
373
svg = boost::regex_replace(svg, e7, linebreak);
374
Py::String result(svg);
379
PyObject* initModule()
381
return Base::Interpreter().addModule(new Module);
384
} // namespace Drawing