From 1279c0927cc11030f5f6f7ed76f1797489abab35 Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Mon, 13 Feb 2012 14:03:30 +0100 Subject: [PATCH 1/4] Drawing templates: changed default inkscape unit to mm --- src/Mod/Drawing/Templates/A3_Landscape.svg | 1 + src/Mod/Drawing/Templates/A4_Landscape.svg | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Mod/Drawing/Templates/A3_Landscape.svg b/src/Mod/Drawing/Templates/A3_Landscape.svg index 408973dbc..8b4431912 100644 --- a/src/Mod/Drawing/Templates/A3_Landscape.svg +++ b/src/Mod/Drawing/Templates/A3_Landscape.svg @@ -580,6 +580,7 @@ inkscape:window-x="0" inkscape:window-y="20" inkscape:current-layer="svg2" + inkscape:document-units="mm" showgrid="false" inkscape:window-maximized="1" /> From 96e167edc74b16f6141f97259b686fcb74a956a6 Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Mon, 13 Feb 2012 14:04:51 +0100 Subject: [PATCH 2/4] handling of viewBox and units in importSVG The absolute values in the svg element are used in combination with the viewBox Attribute to scale the svg to milimeter units. If there is no viewbox attribute. 90dpi input is assumed. --- src/Mod/Draft/importSVG.py | 159 ++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 48 deletions(-) diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index 067c734d5..d33307c3e 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -36,7 +36,7 @@ currently unsupported: use, image # debug Problem with 'Sans' font from Inkscape # debug Problem with fill color # implement inherting fill style from group -# handle viewbox and units +# handle relative units import xml.sax, string, FreeCAD, os, math, re, Draft from draftlibs import fcvec @@ -216,10 +216,50 @@ def getcolor(color): b = float(v[2]/255.0) return (r,g,b,0.0) -def getsize(length): - """extracts a number from the given string (removes unit suffixes)""" +def getsize(length,mode='discard',base=None): + """parses length values containing number and unit + with mode 'discard': extracts a number from the given string (removes unit suffixes) + with mode 'tuple': return number and unit as a tuple + with mode 'css': convert the unit to px assuming 90dpi + with mode 'mm': convert the unit to millimeter assuming 90dpi""" + tomm={ + '' : 25.4/90, #default + 'px' : 25.4/90, + 'pt' : 1.25*25.4/90, + 'pc' : 15*25.4/90, + 'mm' : 1.0, + 'cm' : 10.0, + 'in' : 25.4, + 'em': 15*2.54/90, #arbitrarily chosen; has to depend on font size + 'ex': 10*2.54/90, #arbitrarily chosen; has to depend on font size + + '%': 100 #arbitrarily chosen; has to depend on vieport size or (for filling patterns) on bounding box + } + topx={ + '' : 1.0, #default + 'px' : 1.0, + 'pt' : 1.25, + 'pc' : 15, + 'mm' : 90.0/25.4, + 'cm' : 90.0/254.0, + 'in' : 90, + 'em': 15, #arbitrarily chosen; has to depend on font size + 'ex': 10, #arbitrarily chosen; has to depend on font size + + '%': 100 #arbitrarily chosen; has to depend on vieport size or (for filling patterns) on bounding box + } number, exponent, unit=re.findall('([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)(px|pt|pc|mm|cm|in|em|ex|%)?',length)[0] - return float(number) + if mode =='discard': + return float(number) + elif mode == 'tuple': + return float(number),unit + elif mode == 'mm': + return float(number)*tomm[unit] + elif mode == 'css': + if unit != '%': + return float(number)*topx[unit] + else: + return float(number)*(base or 1) def makewire(path,checkclosed=False,donttry=False): '''try to make a wire out of the list of edges. If the 'Wire' functions fails or the wire is not @@ -281,7 +321,7 @@ def arcend2center(lastvec,currentvec,rx,ry,xrotation=0.0,correction=False): try: scalefacpos = math.sqrt(numer/denom) except ValueError: - print 'sqrt(%f/%f)' % (numer,denom) + FreeCAD.Console.PrintMessage('sqrt(%f/%f)\n' % (numer,denom)) scalefacpos = 0 for scalefacsign in (1,-1): scalefac = scalefacpos * scalefacsign @@ -318,6 +358,7 @@ class svgHandler(xml.sax.ContentHandler): self.transform = None self.grouptransform = [] self.lastdim = None + self.viewbox = None global Part import Part @@ -349,8 +390,8 @@ class svgHandler(xml.sax.ContentHandler): self.count += 1 - print "processing element ",self.count,": ",name - print "existing group transform: ", self.grouptransform + FreeCAD.Console.PrintMessage('processing element %d: %s\n'%(self.count,name)) + FreeCAD.Console.PrintMessage('existing group transform: %s\n'%(str(self.grouptransform))) data = {} for (keyword,content) in attrs.items(): @@ -370,7 +411,7 @@ class svgHandler(xml.sax.ContentHandler): for k in ['x','y','x1','y1','x2','y2','r','rx','ry','cx','cy','width','height']: if k in data: - data[k] = getsize(data[k][0]) + data[k] = getsize(data[k][0],'css') for k in ['fill','stroke','stroke-width','font-size']: if k in data: @@ -384,6 +425,29 @@ class svgHandler(xml.sax.ContentHandler): self.width = None self.text = None + if name == 'svg': + m=FreeCAD.Matrix() + if 'width' in data and 'height' in data and \ + 'viewBox' in data: + x0,y0,x1,y1=[float(n) for n in data['viewBox']] + vbw = x1-x0 + vbh = y1-y0 + self.viewbox=(vbw,vbh) + abw = getsize(attrs.getValue('width'),'mm') + abh = getsize(attrs.getValue('height'),'mm') + sx=abw/vbw + sy=abh/vbh + m.scale(Vector(sx,sy,1)) + if round(sx/sy,5) != 1: + FreeCAD.Console.PrintWarning('Scaling Factors do not match!!!\n') + + #FreeCAD.Console.PrintMessage('attrs: %s %s\n'%(attrs.getValue('width'),attrs.getValue('height'))) + #FreeCAD.Console.PrintMessage('vb: %f %f %f %f\n'%(x0,y0,x1,y1)) + #FreeCAD.Console.PrintMessage('absolute: %f %f\n'%(abw,abh)) + else: + #fallback to 90 dpi + m.scale(Vector(25.4/90.0,25.4/90.0,1)) + self.grouptransform.append(m) if 'fill' in data: if data['fill'][0] != 'none': self.fill = getcolor(data['fill']) @@ -392,7 +456,7 @@ class svgHandler(xml.sax.ContentHandler): self.color = getcolor(data['stroke']) if 'stroke-width' in data: if data['stroke-width'] != 'none': - self.width = getsize(data['stroke-width']) + self.width = getsize(data['stroke-width'],'css') if 'transform' in data: m = self.getMatrix(attrs.getValue('transform')) if name == "g": @@ -410,12 +474,12 @@ class svgHandler(xml.sax.ContentHandler): pathname = None if 'id' in data: pathname = data['id'][0] - print "name: ",pathname + FreeCAD.Console.PrintMessage('name: %s\n'%pathname) # processing paths if name == "path": - print data + FreeCAD.Console.PrintMessage('data: %s\n'%str(data)) if not pathname: pathname = 'Path' @@ -462,7 +526,7 @@ class svgHandler(xml.sax.ContentHandler): else: lastvec = Vector(x,-y,0) firstvec = lastvec - print "move ",lastvec + FreeCAD.Console.PrintMessage('move %s\n'%str(lastvec)) lastpole = None if (d == "L" or d == "l") or \ ((d == 'm' or d == 'M') and pointlist) : @@ -473,7 +537,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = Vector(x,-y,0) if not fcvec.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() - print "line ",lastvec,currentvec + FreeCAD.Console.PrintMessage("line %s %s\n" %(lastvec,currentvec)) lastvec = currentvec path.append(seg) lastpole = None @@ -482,8 +546,7 @@ class svgHandler(xml.sax.ContentHandler): if relative: currentvec = lastvec.add(Vector(x,0,0)) else: - lasty = path[-1].y - currentvec = Vector(x,lasty,0) + currentvec = Vector(x,lastvec.y,0) seg = Part.Line(lastvec,currentvec).toShape() lastvec = currentvec lastpole = None @@ -493,8 +556,7 @@ class svgHandler(xml.sax.ContentHandler): if relative: currentvec = lastvec.add(Vector(0,-y,0)) else: - lastx = path[-1].x - currentvec = Vector(lastx,-y,0) + currentvec = Vector(lastvec.x,-y,0) seg = Part.Line(lastvec,currentvec).toShape() lastvec = currentvec lastpole = None @@ -529,14 +591,14 @@ class svgHandler(xml.sax.ContentHandler): solution,(rx,ry) = arcend2center(lastvec,currentvec,rx,ry,math.radians(-xrotation),True) negsol = (largeflag != sweepflag) vcenter,angle1,angledelta = solution[negsol] - print angle1 - print angledelta + #print angle1 + #print angledelta if ry > rx: rx,ry=ry,rx swapaxis = True else: swapaxis = False - print 'Elliptical arc %s rx=%f ry=%f' % (vcenter,rx,ry) + #print 'Elliptical arc %s rx=%f ry=%f' % (vcenter,rx,ry) e1 = Part.Ellipse(vcenter,rx,ry) if sweepflag: #angledelta=-(-angledelta % (math.pi *2)) # Step4 @@ -595,18 +657,18 @@ class svgHandler(xml.sax.ContentHandler): mainv = currentvec.sub(lastvec) pole1v = lastvec.add(pole1) pole2v = currentvec.add(pole2) - print "cubic curve data:",mainv.normalize(),pole1v.normalize(),pole2v.normalize() + #print "cubic curve data:",mainv.normalize(),pole1v.normalize(),pole2v.normalize() if True and \ pole1.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())) and \ pole2.distanceToLine(lastvec,currentvec) < 10**(-1*(2+Draft.precision())): - print "straight segment" + #print "straight segment" seg = Part.Line(lastvec,currentvec).toShape() else: - print "cubic bezier segment" + #print "cubic bezier segment" b = Part.BezierCurve() b.setPoles([lastvec,pole1,pole2,currentvec]) seg = b.toShape() - print "connect ",lastvec,currentvec + #print "connect ",lastvec,currentvec lastvec = currentvec lastpole = ('cubic',pole2) path.append(seg) @@ -636,14 +698,14 @@ class svgHandler(xml.sax.ContentHandler): if not fcvec.equals(currentvec,lastvec): if True and \ pole.distanceToLine(lastvec,currentvec) < 20**(-1*(2+Draft.precision())): - print "straight segment" + #print "straight segment" seg = Part.Line(lastvec,currentvec).toShape() else: - print "quadratic bezier segment" + #print "quadratic bezier segment" b = Part.BezierCurve() b.setPoles([lastvec,pole,currentvec]) seg = b.toShape() - print "connect ",lastvec,currentvec + #print "connect ",lastvec,currentvec lastvec = currentvec lastpole = ('quadratic',pole) path.append(seg) @@ -765,7 +827,7 @@ class svgHandler(xml.sax.ContentHandler): but there would be more difficlult to search for duplicate points beforehand.''' if not pathname: pathname = 'Polyline' points=[float(d) for d in data['points']] - print points + FreeCAD.Console.PrintMessage('points %s\n'%str(points)) lenpoints=len(points) if lenpoints>=4 and lenpoints % 2 == 0: lastvec = Vector(points[0],-points[1],0) @@ -776,7 +838,7 @@ class svgHandler(xml.sax.ContentHandler): currentvec = Vector(svgx,-svgy,0) if not fcvec.equals(lastvec,currentvec): seg = Part.Line(lastvec,currentvec).toShape() - print "polyline seg ",lastvec,currentvec + #print "polyline seg ",lastvec,currentvec lastvec = currentvec path.append(seg) if path: @@ -824,7 +886,7 @@ class svgHandler(xml.sax.ContentHandler): if name in ["text","tspan"]: if not("freecad:skip" in data): - print "processing a text" + FreeCAD.Console.PrintMessage("processing a text\n") if 'x' in data: self.x = data['x'] else: @@ -835,28 +897,28 @@ class svgHandler(xml.sax.ContentHandler): self.y = 0 if 'font-size' in data: if data['font-size'] != 'none': - self.text = getsize(data['font-size']) + self.text = getsize(data['font-size'],'css') else: self.text = 1 else: if self.lastdim: self.lastdim.ViewObject.FontSize = int(getsize(data['font-size'])) - print "done processing element ",self.count + FreeCAD.Console.PrintMessage("done processing element %d\n"%self.count) def characters(self,content): if self.text: - print "reading characters", str(content) + FreeCAD.Console.PrintMessage("reading characters %s\n" % str(content)) obj=self.doc.addObject("App::Annotation",'Text') obj.LabelText = content.encode('latin1') vec = Vector(self.x,-self.y,0) if self.transform: vec = self.translateVec(vec,self.transform) - print "own transform: ",self.transform, vec + #print "own transform: ",self.transform, vec for transform in self.grouptransform[::-1]: #vec = self.translateVec(vec,transform) vec = transform.multiply(vec) - print "applying vector: ",vec + #print "applying vector: ",vec obj.Position = vec if gui: obj.ViewObject.FontSize = int(self.text) @@ -867,17 +929,17 @@ class svgHandler(xml.sax.ContentHandler): if not name in ["tspan"]: self.transform = None self.text = None - if name == "g": - print "closing group" + if name == "g" or name == "svg": + FreeCAD.Console.PrintMessage("closing group\n") self.grouptransform.pop() def applyTrans(self,sh): if isinstance(sh,Part.Shape): if self.transform: - print "applying object transform: ",self.transform + FreeCAD.Console.PrintMessage("applying object transform: %s\n" % self.transform) sh = sh.transformGeometry(self.transform) for transform in self.grouptransform[::-1]: - print "applying group transform: ", transform + FreeCAD.Console.PrintMessage("applying group transform: %s\n" % transform) sh = sh.transformGeometry(transform) return sh elif Draft.getType(sh) == "Dimension": @@ -885,10 +947,10 @@ class svgHandler(xml.sax.ContentHandler): for p in [sh.Start,sh.End,sh.Dimline]: cp = Vector(p) if self.transform: - print "applying object transform: ",self.transform + FreeCAD.Console.PrintMessage("applying object transform: %s\n" % self.transform) cp = self.transform.multiply(cp) for transform in self.grouptransform[::-1]: - print "applying group transform: ",transform + FreeCAD.Console.PrintMessage("applying group transform: %s\n" % transform) cp = transform.multiply(cp) pts.append(cp) sh.Start = pts[0] @@ -906,7 +968,7 @@ class svgHandler(xml.sax.ContentHandler): for transformation, arguments in transformre.findall(tr): argsplit=[float(arg) for arg in arguments.replace(',',' ').split()] #m.multiply(FreeCAD.Matrix (1,0,0,0,0,-1)) - print '%s:%s %s %d' % (transformation, arguments,argsplit,len(argsplit)) + #print '%s:%s %s %d' % (transformation, arguments,argsplit,len(argsplit)) if transformation == 'translate': tx = argsplit[0] ty = argsplit[1] if len(argsplit) > 1 else 0.0 @@ -936,10 +998,10 @@ class svgHandler(xml.sax.ContentHandler): # (+0 -0 +1 +0) (0 0 1 0) # (+0 -0 +0 +1) (0 0 0 1)''' m=m.multiply(FreeCAD.Matrix(argsplit[0],-argsplit[2],0,argsplit[4],-argsplit[1],argsplit[3],0,-argsplit[5])) - else: - print 'SKIPPED %s' % transformation - print "m= ",m - print "generating transformation: ",m + #else: + #print 'SKIPPED %s' % transformation + #print "m= ",m + #print "generating transformation: ",m return m def decodeName(name): @@ -950,7 +1012,8 @@ def decodeName(name): try: decodedName = (name.decode("latin1")) except UnicodeDecodeError: - print "svg: error: couldn't determine character encoding" + FreeCAD.Console.PrintError("svg: error: couldn't determine character encoding\n") + decodedName = name return decodedName @@ -1005,7 +1068,7 @@ def export(exportList,filename): svg_export_style = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft").GetInt("svg_export_style") if svg_export_style != 0 and svg_export_style != 1: - print "unknown svg export style, switching to Translated" + FreeCAD.Console.PrintMessage("unknown svg export style, switching to Translated\n") svg_export_style = 0 # finding sheet size From 5b14931873be137acc96fdee0a06f1b01ce1d712 Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Sat, 18 Feb 2012 12:06:31 +0100 Subject: [PATCH 3/4] importSVG fixed handling of Ellipses --- src/Mod/Draft/importSVG.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index d33307c3e..b2f737710 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -855,11 +855,19 @@ class svgHandler(xml.sax.ContentHandler): c = Vector(data.get('cx',0),-data.get('cy',0),0) rx = data['rx'] ry = data['ry'] - sh = Part.Ellipse(c,rx,ry).toShape() #needs a proxy object + if rx > ry: + sh = Part.Ellipse(c,rx,ry).toShape() + else: + sh = Part.Ellipse(c,ry,rx).toShape() + m3=FreeCAD.Matrix() + m3.move(c) + rot90=FreeCAD.Matrix(0,-1,0,0,1,0) #90 + m3=m3.multiply(rot90) + m3.move(c.multiply(-1)) + sh.transform(m3) if self.fill: sh = Part.Wire([sh]) sh = Part.Face(sh) - sh.translate(c) sh = self.applyTrans(sh) obj = self.doc.addObject("Part::Feature",pathname) obj.Shape = sh From 4ece6a3a674fef135b6e061be7d8c7aee7b2bb1a Mon Sep 17 00:00:00 2001 From: Sebastian Hoogen Date: Tue, 14 Feb 2012 22:14:51 +0100 Subject: [PATCH 4/4] new ISO 7200 compliant drawing template --- .../Templates/A3_Landscape_ISO7200.svg | 154 ++++++++++++++++++ .../Drawing/Templates/A4_Portrait_ISO7200.svg | 154 ++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100755 src/Mod/Drawing/Templates/A3_Landscape_ISO7200.svg create mode 100755 src/Mod/Drawing/Templates/A4_Portrait_ISO7200.svg diff --git a/src/Mod/Drawing/Templates/A3_Landscape_ISO7200.svg b/src/Mod/Drawing/Templates/A3_Landscape_ISO7200.svg new file mode 100755 index 000000000..dbce79194 --- /dev/null +++ b/src/Mod/Drawing/Templates/A3_Landscape_ISO7200.svg @@ -0,0 +1,154 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + Responsible departmentTechnical referenceCreated byApproved byClassification/key wordsLegal ownerDocument typeDocument statusTitle, Supplementary titleIdentification numberRev.Date of issueLanguageSeg./Sh. + + + + me + + myself + + my company + + type + + title + + 0001 + + 2000-00-00 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Drawing/Templates/A4_Portrait_ISO7200.svg b/src/Mod/Drawing/Templates/A4_Portrait_ISO7200.svg new file mode 100755 index 000000000..d6ecc6c4d --- /dev/null +++ b/src/Mod/Drawing/Templates/A4_Portrait_ISO7200.svg @@ -0,0 +1,154 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + Responsible departmentTechnical referenceCreated byApproved byClassification/key wordsLegal ownerDocument typeDocument statusTitle, Supplementary titleIdentification numberRev.Date of issueLanguageSeg./Sh. + + + + me + + myself + + my company + + type + + title + + 0001 + + 2000-00-00 + + + + + + + + + + + + + + + + + + + + + + + +