Draft: Allow to scale imported DXF files - fixes #2557

This commit is contained in:
Yorik van Havre 2016-05-18 14:32:33 -03:00
parent 7a99b34a9d
commit 21ba33df01
4 changed files with 122 additions and 43 deletions

View File

@ -26,8 +26,7 @@
#endif
#include "DraftDxf.h"
#include <gp_Pnt.hxx>
#include <gp_Circ.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
@ -51,19 +50,34 @@
using namespace DraftUtils;
DraftDxfRead::DraftDxfRead(std::string filepath, App::Document *pcDoc) : CDxfRead(filepath.c_str())
{
document = pcDoc;
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Draft");
optionGroupLayers = hGrp->GetBool("groupLayers",false);
optionImportAnnotations = hGrp->GetBool("dxftext",false);
optionScaling = hGrp->GetFloat("dxfScaling",1.0);
}
gp_Pnt DraftDxfRead::makePoint(const double* p)
{
double sp1(p[0]);
double sp2(p[1]);
double sp3(p[2]);
if (optionScaling != 1.0) {
sp1 = sp1 * optionScaling;
sp2 = sp2 * optionScaling;
sp3 = sp3 * optionScaling;
}
return gp_Pnt(sp1,sp2,sp3);
}
void DraftDxfRead::OnReadLine(const double* s, const double* e, bool hidden)
{
gp_Pnt p0(s[0], s[1], s[2]);
gp_Pnt p1(e[0], e[1], e[2]);
gp_Pnt p0 = makePoint(s);
gp_Pnt p1 = makePoint(e);
if (p0.IsEqual(p1,0.00000001))
return;
BRepBuilderAPI_MakeEdge makeEdge(p0, p1);
@ -74,7 +88,7 @@ void DraftDxfRead::OnReadLine(const double* s, const double* e, bool hidden)
void DraftDxfRead::OnReadPoint(const double* s)
{
BRepBuilderAPI_MakeVertex makeVertex(gp_Pnt(s[0], s[1], s[2]));
BRepBuilderAPI_MakeVertex makeVertex(makePoint(s));
TopoDS_Vertex vertex = makeVertex.Vertex();
AddObject(new Part::TopoShape(vertex));
}
@ -82,12 +96,12 @@ void DraftDxfRead::OnReadPoint(const double* s)
void DraftDxfRead::OnReadArc(const double* s, const double* e, const double* c, bool dir, bool hidden)
{
gp_Pnt p0(s[0], s[1], s[2]);
gp_Pnt p1(e[0], e[1], e[2]);
gp_Pnt p0 = makePoint(s);
gp_Pnt p1 = makePoint(e);
gp_Dir up(0, 0, 1);
if (!dir)
up = -up;
gp_Pnt pc(c[0], c[1], c[2]);
gp_Pnt pc = makePoint(c);
gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc));
BRepBuilderAPI_MakeEdge makeEdge(circle, p0, p1);
TopoDS_Edge edge = makeEdge.Edge();
@ -97,11 +111,11 @@ void DraftDxfRead::OnReadArc(const double* s, const double* e, const double* c,
void DraftDxfRead::OnReadCircle(const double* s, const double* c, bool dir, bool hidden)
{
gp_Pnt p0(s[0], s[1], s[2]);
gp_Pnt p0 = makePoint(s);
gp_Dir up(0, 0, 1);
if (!dir)
up = -up;
gp_Pnt pc(c[0], c[1], c[2]);
gp_Pnt pc = makePoint(c);
gp_Circ circle(gp_Ax2(pc, up), p0.Distance(pc));
BRepBuilderAPI_MakeEdge makeEdge(circle);
TopoDS_Edge edge = makeEdge.Edge();
@ -120,8 +134,8 @@ void DraftDxfRead::OnReadEllipse(const double* c, double major_radius, double mi
gp_Dir up(0, 0, 1);
if(!dir)
up = -up;
gp_Pnt pc(c[0], c[1], c[2]);
gp_Elips ellipse(gp_Ax2(pc, up), major_radius, minor_radius);
gp_Pnt pc = makePoint(c);
gp_Elips ellipse(gp_Ax2(pc, up), major_radius * optionScaling, minor_radius * optionScaling);
ellipse.Rotate(gp_Ax1(pc,up),rotation);
BRepBuilderAPI_MakeEdge makeEdge(ellipse);
TopoDS_Edge edge = makeEdge.Edge();
@ -132,7 +146,7 @@ void DraftDxfRead::OnReadEllipse(const double* c, double major_radius, double mi
void DraftDxfRead::OnReadText(const double *point, const double height, const char* text)
{
if (optionImportAnnotations) {
Base::Vector3d pt(point[0],point[1],point[2]);
Base::Vector3d pt(point[0] * optionScaling, point[1] * optionScaling, point[2] * optionScaling);
if(LayerName().substr(0, 6) != "BLOCKS") {
App::Annotation *pcFeature = (App::Annotation *)document->addObject("App::Annotation", "Text");
pcFeature->LabelText.setValue(Deformat(text));
@ -166,7 +180,7 @@ void DraftDxfRead::OnReadInsert(const double* point, const double* scale, const
Base::Matrix4D mat;
mat.scale(scale[0],scale[1],scale[2]);
mat.rotZ(rotation);
mat.move(point[0],point[1],point[2]);
mat.move(point[0]*optionScaling,point[1]*optionScaling,point[2]*optionScaling);
pcomp->transformShape(mat,true);
AddObject(pcomp);
}
@ -179,9 +193,9 @@ void DraftDxfRead::OnReadDimension(const double* s, const double* e, const doubl
{
if (optionImportAnnotations) {
Base::Interpreter().runString("import Draft");
Base::Interpreter().runStringArg("p1=FreeCAD.Vector(%f,%f,%f)",s[0],s[1],s[2]);
Base::Interpreter().runStringArg("p2=FreeCAD.Vector(%f,%f,%f)",e[0],e[1],e[2]);
Base::Interpreter().runStringArg("p3=FreeCAD.Vector(%f,%f,%f)",point[0],point[1],point[2]);
Base::Interpreter().runStringArg("p1=FreeCAD.Vector(%f,%f,%f)",s[0]*optionScaling,s[1]*optionScaling,s[2]*optionScaling);
Base::Interpreter().runStringArg("p2=FreeCAD.Vector(%f,%f,%f)",e[0]*optionScaling,e[1]*optionScaling,e[2]*optionScaling);
Base::Interpreter().runStringArg("p3=FreeCAD.Vector(%f,%f,%f)",point[0]*optionScaling,point[1]*optionScaling,point[2]*optionScaling);
Base::Interpreter().runString("Draft.makeDimension(p1,p2,p3)");
}
}

View File

@ -25,7 +25,8 @@
#include "dxf.h"
#include <Mod/Part/App/TopoShape.h>
#include <App/Document.h>
#include <App/Document.h>
#include <gp_Pnt.hxx>
namespace DraftUtils
{
@ -50,10 +51,14 @@ namespace DraftUtils
void AddObject(Part::TopoShape *shape); //Called by OnRead functions to add Part objects
std::string Deformat(const char* text); // Removes DXF formating from texts
private:
gp_Pnt makePoint(const double* p);
protected:
App::Document *document;
bool optionGroupLayers;
bool optionImportAnnotations;
double optionScaling;
std::map <std::string, std::vector <Part::TopoShape*> > layers;
};
}

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>506</width>
<height>611</height>
<height>647</height>
</rect>
</property>
<property name="windowTitle">
@ -234,6 +234,57 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_4">
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>Scale factor to apply to imported files</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Gui::PrefDoubleSpinBox" name="doubleSpinBox_2">
<property name="toolTip">
<string>Scale factor to apply to DXF files on import.
The factor is the conversion between the unit of your DXF file and millimeters.
Ex: for files in millimeters: 1, in centimeters: 10, in meters: 1000, in inches: 25.4, in feet: 304.8</string>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>99999.990000000005239</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="prefEntry" stdset="0">
<cstring>dxfScaling</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Draft</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>

View File

@ -364,8 +364,16 @@ def formatObject(obj,dxfobj=None):
obj.ViewObject.LineColor = dxfDefaultColor
def vec(pt):
"returns a rounded Vector from a dxf point"
return FreeCAD.Vector(round(pt[0],prec()),round(pt[1],prec()),round(pt[2],prec()))
"returns a rounded and scaled Vector from a dxf point, or rounded and scaled value"
if isinstance(pt,float) or isinstance(pt,int):
v = round(pt,prec())
if dxfScaling != 1:
v = v * dxfScaling
else:
v = FreeCAD.Vector(round(pt[0],prec()),round(pt[1],prec()),round(pt[2],prec()))
if dxfScaling != 1:
v.multiply(dxfScaling)
return v
def drawLine(line,forceShape=False):
"returns a Part shape from a dxf line"
@ -462,7 +470,7 @@ def drawArc(arc,forceShape=False):
lastangle=round(arc.end_angle,prec())
circle=Part.Circle()
circle.Center=v
circle.Radius=round(arc.radius,prec())
circle.Radius=vec(arc.radius)
try:
if (dxfCreateDraft or dxfCreateSketch) and (not forceShape):
pl = FreeCAD.Placement()
@ -478,7 +486,7 @@ def drawCircle(circle,forceShape=False):
"returns a Part shape from a dxf circle"
v = vec(circle.loc)
curve = Part.Circle()
curve.Radius = round(circle.radius,prec())
curve.Radius = vec(circle.radius)
curve.Center = v
try:
if (dxfCreateDraft or dxfCreateSketch) and (not forceShape):
@ -643,7 +651,7 @@ def drawSplineOld(spline,forceShape=False):
cp.append(dline[1])
elif dline[0] == 30:
cp.append(dline[1])
pt = Vector(cp[0],cp[1],cp[2])
pt = vec(cp)
if verts:
if pt != verts[-1]:
verts.append(pt)
@ -698,11 +706,11 @@ non-parametric curve"""
else:
y=0.0
dataremain = dataremain[1:]
vec = FreeCAD.Vector(x,y,z)
v = vec([x,y,z])
if groupnumber == 10:
controlpoints.append(vec)
controlpoints.append(v)
elif groupnumber == 11:
fitpoints.append(vec)
fitpoints.append(v)
else:
dataremain = dataremain[1:]
#print groupnumber #debug
@ -843,7 +851,7 @@ def drawInsert(insert,num=None,clone=False):
tsf.move(pos)
tsf.rotateZ(rot)
sc = insert.scale
sc = FreeCAD.Vector(sc[0],sc[1],0)
sc = vec([sc[0],sc[1],0])
newob.Placement = FreeCAD.Placement(tsf)
newob.Scale = sc
return newob
@ -921,13 +929,13 @@ def addText(text,attrib=False):
if attrib:
lay = locateLayer(rawValue(text,8))
val = rawValue(text,1)
pos = FreeCAD.Vector(rawValue(text,10),rawValue(text,20),rawValue(text,30))
hgt = rawValue(text,40)
pos = vec([rawValue(text,10),rawValue(text,20),rawValue(text,30)])
hgt = vec(rawValue(text,40))
else:
lay = locateLayer(text.layer)
val = text.value
pos = FreeCAD.Vector(text.loc[0],text.loc[1],text.loc[2])
hgt = text.height
pos = vec(text.loc)
hgt = vec(text.height)
if val:
if attrib:
newob = doc.addObject("App::Annotation","Attribute")
@ -951,7 +959,7 @@ def addText(text,attrib=False):
xv = Vector(1,0,0)
ax = Vector(0,0,1)
if rx or ry or rz:
xv = Vector(rx,ry,rz)
xv = vec([rx,ry,rz])
if not DraftVecUtils.isNull(xv):
ax = (xv.cross(Vector(1,0,0))).negative()
if DraftVecUtils.isNull(ax):
@ -1317,9 +1325,9 @@ def processdxf(document,filename,getShapes=False):
warn(dim)
else:
lay=locateLayer(layer)
pt = FreeCAD.Vector(x1,y1,z1)
p1 = FreeCAD.Vector(x2,y2,z2)
p2 = FreeCAD.Vector(x3,y3,z3)
pt = vec([x1,y1,z1])
p1 = vec([x2,y2,z2])
p2 = vec([x3,y3,z3])
if align >= 128:
align -= 128
elif align >= 64:
@ -1328,9 +1336,9 @@ def processdxf(document,filename,getShapes=False):
align -= 32
if align == 0:
if angle in [0,180]:
p2 = FreeCAD.Vector(x3,y2,z2)
p2 = vec([x3,y2,z2])
elif angle in [90,270]:
p2 = FreeCAD.Vector(x2,y3,z2)
p2 = vec([x2,y3,z2])
newob = doc.addObject("App::FeaturePython","Dimension")
lay.addObject(newob)
_Dimension(newob)
@ -1345,7 +1353,7 @@ def processdxf(document,filename,getShapes=False):
if dxfUseStandardSize and draftui:
newob.ViewObject.FontSize = draftui.fontsize
else:
st = rawValue(dim,3)
st = vec(rawValue(dim,3))
size = getdimheight(st) or 1
newob.ViewObject.FontSize = float(size)*TEXTSCALING
else:
@ -1357,9 +1365,9 @@ def processdxf(document,filename,getShapes=False):
points = drawing.entities.get_type("point")
if points: FreeCAD.Console.PrintMessage("drawing "+str(len(points))+" points...\n")
for point in points:
x = rawValue(point,10)
y = rawValue(point,20)
z = rawValue(point,30)
x = vec(rawValue(point,10))
y = vec(rawValue(point,20))
z = vec(rawValue(point,30))
lay = rawValue(point,8)
if dxfImportLayouts or (not rawValue(point,67)):
if dxfMakeBlocks:
@ -2016,7 +2024,7 @@ def readPreferences():
global dxfCreatePart, dxfCreateDraft, dxfCreateSketch, dxfDiscretizeCurves, dxfStarBlocks
global dxfMakeBlocks, dxfJoin, dxfRenderPolylineWidth, dxfImportTexts, dxfImportLayouts
global dxfImportPoints, dxfImportHatches, dxfUseStandardSize, dxfGetColors, dxfUseDraftVisGroups
global dxfFillMode, dxfBrightBackground, dxfDefaultColor, dxfUseLegacyImporter, dxfExportBlocks
global dxfFillMode, dxfBrightBackground, dxfDefaultColor, dxfUseLegacyImporter, dxfExportBlocks, dxfScaling
dxfCreatePart = p.GetBool("dxfCreatePart",True)
dxfCreateDraft = p.GetBool("dxfCreateDraft",False)
dxfCreateSketch = p.GetBool("dxfCreateSketch",False)
@ -2037,3 +2045,4 @@ def readPreferences():
dxfBrightBackground = isBrightBackground()
dxfDefaultColor = getColor()
dxfExportBlocks = p.GetBool("dxfExportBlocks",True)
dxfScaling = p.GetFloat("dxfScaling",1.0)