Skip to content

Commit

Permalink
ProjectionAlgos: Make the style of the lines in the SVG file configur…
Browse files Browse the repository at this point in the history
…able.

* getSVG provides new style parameters for every kind of line:
  V, V0, V1, H, H0, H1.
* Old line width parameters are removed. The style parameters
  can be used instead.
* A style is a map container for svg attribute keys and values
  (string, string).
* The Python interface is updated to offer the new style parameters
  accordingly as a dict.
* Because there are many parameters on the function call now,
  the Python interface supports keyword parameters.
* Update ArchSectionPlane to take advantage of the new style parameters.
  This simplifies the code. String replacements could be removed
  (done in a later commit).
* FeatureViewPy.cpp is – to my knowledge – the only function that used the
  old line width parameters. I rewrote it to use the new style parameters.
  • Loading branch information
simsiem authored and yorikvanhavre committed Apr 23, 2017
1 parent 2bda3a3 commit 9633c94
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 151 deletions.
40 changes: 19 additions & 21 deletions src/Mod/Arch/ArchSectionPlane.py
Expand Up @@ -196,21 +196,21 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume = getCutShapes(objs,section,showHidden)
if shapes:
baseshape = Part.makeCompound(shapes)
svgf = Drawing.projectToSVG(baseshape,direction)
if svgf:
svgf = svgf.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
svgf = svgf.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
svgf = svgf.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
svg += svgf
style = {'stroke-width': 'LWPlaceholder'}
svgf = Drawing.projectToSVG(
baseshape, direction,
hStyle=style, h0Style=style, h1Style=style,
vStyle=style, v0Style=style, v1Style=style)
svg += svgf
if hshapes:
hshapes = Part.makeCompound(hshapes)
svgh = Drawing.projectToSVG(hshapes,direction)
if svgh:
svgh = svgh.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
svgh = svgh.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
svgh = svgh.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
svgh = svgh.replace('fill="none"','fill="none"\nstroke-dasharray="DAPlaceholder"')
svg += svgh
style = {'stroke-width': 'LWPlaceholder',
'stroke-dasharray': 'DAPlaceholder'}
svgh = Drawing.projectToSVG(
hshapes, direction,
hStyle=style, h0Style=style, h1Style=style,
vStyle=style, v0Style=style, v1Style=style)
svg += svgh
if sshapes:
svgs = ""
if showFill:
Expand All @@ -224,14 +224,12 @@ def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=
svgs += f
svgs += "</g>\n"
sshapes = Part.makeCompound(sshapes)
svgs += Drawing.projectToSVG(sshapes,direction)
if svgs:
svgs = svgs.replace('stroke-width="0.35"','stroke-width="SWPlaceholder"')
svgs = svgs.replace('stroke-width="1"','stroke-width="SWPlaceholder"')
svgs = svgs.replace('stroke-width:0.01','stroke-width:SWPlaceholder')
svgs = svgs.replace('stroke-width="0.35 px"','stroke-width="SWPlaceholder"')
svgs = svgs.replace('stroke-width:0.35','stroke-width:SWPlaceholder')
svg += svgs
style = {'stroke-width': 'SWPlaceholder'}
svgs += Drawing.projectToSVG(
sshapes, direction,
hStyle=style, h0Style=style, h1Style=style,
vStyle=style, v0Style=style, v1Style=style)
svg += svgs
scaledlinewidth = linewidth/scale
st = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("CutLineThickness",2)
yt = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("SymbolLineThickness",0.6)
Expand Down
121 changes: 97 additions & 24 deletions src/Mod/Drawing/App/AppDrawingPy.cpp
Expand Up @@ -37,10 +37,39 @@

#include <Mod/Part/App/OCCError.h>

using namespace std;
using Part::TopoShapePy;
using Part::TopoShape;

namespace Drawing {

/** 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<string, string>).
*
* @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<typename OutputIt>
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<Module>
{
public:
Expand All @@ -54,8 +83,8 @@ class Module : public Py::ExtensionModule<Module>
"[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_varargs_method("projectToSVG",&Module::projectToSVG,
"string = projectToSVG(TopoShape[,App.Vector Direction, string type])\n"
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,
Expand Down Expand Up @@ -160,32 +189,76 @@ class Module : public Py::ExtensionModule<Module>

return list;
}
Py::Object projectToSVG(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();
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

TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObjShape);
Base::Vector3d Vector(0,0,1);
if (pcObjDir)
Vector = static_cast<Base::VectorPy*>(pcObjDir)->value();
ProjectionAlgos Alg(pShape->getTopoShapePtr()->getShape(),Vector);
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();

bool hidden = false;
if (type && std::string(type) == "ShowHiddenLines")
hidden = true;
// Convert all arguments into the right format

TopoShapePy* pShape = static_cast<TopoShapePy*>(pcObjShape);

Base::Vector3d directionVector(0,0,1);
if (pcObjDir)
directionVector = static_cast<Base::VectorPy*>(pcObjDir)->value();

if (extractionTypePy && 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::String result(Alg.getSVG(hidden?ProjectionAlgos::WithHidden:ProjectionAlgos::Plain, scale, tol));
return result;
}
Py::Object projectToDXF(const Py::Tuple& args)
{
PyObject *pcObjShape;
Expand Down
8 changes: 7 additions & 1 deletion src/Mod/Drawing/App/FeatureViewPart.cpp
Expand Up @@ -120,7 +120,13 @@ App::DocumentObjectExecReturn *FeatureViewPart::execute(void)
ProjectionAlgos::ExtractionType type = ProjectionAlgos::Plain;
if (hidden) type = (ProjectionAlgos::ExtractionType)(type|ProjectionAlgos::WithHidden);
if (smooth) type = (ProjectionAlgos::ExtractionType)(type|ProjectionAlgos::WithSmooth);
result << Alg.getSVG(type, this->LineWidth.getValue() / this->Scale.getValue(), this->Tolerance.getValue(), this->HiddenWidth.getValue() / this->Scale.getValue());
ProjectionAlgos::XmlAttributes visible_style = {
{"stroke_width", to_string(this->LineWidth.getValue() / this->Scale.getValue())}
};
ProjectionAlgos::XmlAttributes hidden_style = {
{"stroke_width", to_string(this->HiddenWidth.getValue() / this->Scale.getValue()) }
};
result << Alg.getSVG(type, this->Tolerance.getValue(), visible_style, visible_style, visible_style, hidden_style, hidden_style, hidden_style);

result << "</g>" << endl;

Expand Down

0 comments on commit 9633c94

Please sign in to comment.