TechDraw: export View to DXF

Discussions about the development of the TechDraw workbench
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

TechDraw: export View to DXF

Post by easyw-fc »

Hi,
I'm trying to export a page View to DXF...
following this
https://www.freecadweb.org/tracker/view.php?id=2882
I tried to use the API as following:

Code: Select all

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# test script for TechDraw module
# creates a page and 2 views
# adds 1 length dimension to view1
# adds 1 radius dimension to view2
from __future__ import print_function

import FreeCAD
import Part
import Measure
import TechDraw
import os

def DVDimensionTest():
    path = os.path.dirname(os.path.abspath(__file__))
    print ('TDDim path: ' + path)
    templateFileSpec = path + '/A4_LandscapeTD.svg'

    FreeCAD.newDocument("TDDim")
    FreeCAD.setActiveDocument("TDDim")
    FreeCAD.ActiveDocument=FreeCAD.getDocument("TDDim")

    #make source feature
    box = FreeCAD.ActiveDocument.addObject("Part::Box","Box")
    sphere = FreeCAD.ActiveDocument.addObject("Part::Sphere","Sphere")

    #make a page
    page = FreeCAD.ActiveDocument.addObject('TechDraw::DrawPage','Page')
    FreeCAD.ActiveDocument.addObject('TechDraw::DrawSVGTemplate','Template')
    FreeCAD.ActiveDocument.Template.Template = templateFileSpec
    FreeCAD.ActiveDocument.Page.Template = FreeCAD.ActiveDocument.Template
    page.Scale = 5.0
#    page.ViewObject.show()   # unit tests run in console mode 

    #make Views
    view1 = FreeCAD.ActiveDocument.addObject('TechDraw::DrawViewPart','View')
    FreeCAD.ActiveDocument.View.Source = [FreeCAD.ActiveDocument.Box]
    rc = page.addView(view1)

    FreeCAD.ActiveDocument.recompute()
    rc = True
        
    fileSpecDxf = "C:/Temp/fcOut.dxf"
    v = App.ActiveDocument.View
    #v = view1
    s = TechDraw.viewPartAsDxf(v)
    dxfEnd = "0\nEOF\n"
    dxfFile = open(fileSpecDxf, "w")
    dxfFile.write(s)
    dxfFile.write(dxfEnd)
    dxfFile.close() 
    
    return rc

if __name__ == '__main__':
    DVDimensionTest()
I can generate a Page and a View, but the fcOut.dxf file doesn't contain nothing more than the dxf header

I'm attaching the dxf out file
fcOut.dxf
(428 Bytes) Downloaded 78 times
and my FC details
OS: Windows 10
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.17.13387 (Git)
Build type: Release
Branch: master
Hash: c5f4079252b11e3c54cd603be7d3697fa9f9d922
Python version: 2.7.14
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.1.0
Locale: English/UnitedStates (en_US)
Thx for support
Maurice

PS if I do the same using the svg option, it works

Code: Select all

    fileSpecSvg = "c:/Temp/fcOut.svg"
    v = App.ActiveDocument.View
    s = TechDraw.viewPartAsSvg(v)
    head = '<svg\n' + \
        '	xmlns="http://www.w3.org/2000/svg" version="1.1" \n' + \
        '	xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace">\n'
    tail = '\n</svg>'
    svgFile = open(fileSpecSvg, "w")
    svgFile.write(head)
    svgFile.write(s)
    svgFile.write(tail)
    svgFile.close() 
Last edited by easyw-fc on Sat Mar 17, 2018 5:22 pm, edited 1 time in total.
reox
Posts: 929
Joined: Sat Aug 13, 2016 10:06 am
Contact:

Re: TD: export View to DXF

Post by reox »

On my machine I get at least some output:

Code: Select all

>>> App.ActiveDocument.View
<DrawViewPart object>
>>> TechDraw.viewPartAsDxf(App.ActiveDocument.View)
'0\nLINE\n8\nsheet_layer\n100\nAcDbEntity\n100\nAcDbLine\n10\n-5\n20\n-5\n30\n0\n11\n-5\n21\n5\n31\n0\n0\nLINE\n8\nsheet_layer\n100\nAcDbEntity\n100\nAcDbLine\n10\n5\n20\n-5\n30\n0\n11\n5\n21\n5\n31\n0\n0\nLINE\n8\nsheet_layer\n100\nAcDbEntity\n100\nAcDbLine\n10\n-5\n20\n-5\n30\n0\n11\n5\n21\n-5\n31\n0\n0\nLINE\n8\nsheet_layer\n100\nAcDbEntity\n100\nAcDbLine\n10\n-5\n20\n5\n30\n0\n11\n5\n21\n5\n31\n0\n'
>>> TechDraw.viewPartAsSvg(App.ActiveDocument.View)
'<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="0.5" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="4">\n<path id= "1" d=" M -5 5 L -5 -5 " />\n<path id= "2" d=" M 5 5 L 5 -5 " />\n<path id= "3" d=" M -5 5 L 5 5 " />\n<path id= "4" d=" M -5 -5 L 5 -5 " />\n</g>\n'
I tested also your code and can produce some dxf... But it is empty when I open it with librecad.

Code: Select all

OS: Debian GNU/Linux testing (buster)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.17.13424 (Git)
Build type: None
Branch: master
Hash: 597dbf60947067852268033c32d6b78ac9ef280c
Python version: 2.7.14
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.1.0
Locale: German/Austria (de_AT)
Attachments
fcOut.dxf
(346 Bytes) Downloaded 56 times
dxfexport.fcstd
(7.65 KiB) Downloaded 65 times
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TD: export View to DXF

Post by easyw-fc »

Ok, I made some progress...
the following code is exporting all Views of the Active Document to a DXF file

Code: Select all

import FreeCAD, FreeCADGui
import TechDraw

fileSpecDxf = "d:/Temp/fcOutDxf.dxf"

s=""
for o in FreeCAD.ActiveDocument.Objects:
    print (o.Label)
    if o.TypeId == "TechDraw::DrawViewPart":
        s += TechDraw.viewPartAsDxf(o)        

# print (s)
dxfStart= "0\nSECTION\n2\nENTITIES\n"
dxfEnd = "0\nEOF\n"
dxfFile = open(fileSpecDxf, "w")
dxfFile.write(dxfStart)
dxfFile.write(s)
dxfFile.write(dxfEnd)
dxfFile.close() 
What was missing was the
dxfStart= "0\nSECTION\n2\nENTITIES\n"
syntax at the beginning of dxf file

I still have an issue...
All Views are generated without the relative placement...
so all the entities will be placed to the origin of the DXF file...
TDtoDXF.gif
TDtoDXF.gif (529.85 KiB) Viewed 21679 times
The nice thing is that the dxf generated is giving single entities each object.

Is there a way to get the View Position/Rotation, to be applied to DXF entities befor the exporting, so to replicate the layout?

Thx
Maurice
User avatar
wandererfan
Veteran
Posts: 6317
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: TD: export View to DXF

Post by wandererfan »

easyw-fc wrote: Sat Mar 17, 2018 4:54 pm Ok, I made some progress...
the following code is exporting all Views of the Active Document ot a DXF file

good! This is how viewPartAsDxf was meant to be used - in a loop to get whichever views were interesting, then combined into 1 output file.
easyw-fc wrote: What was missing was the
dxfStart= "0\nSECTION\n2\nENTITIES\n"
syntax at the beginning of dxf file

I may have known this at one time. :oops: There are other Headers and Trailers in a DXF. I made some notes at the time, but they are on a semi-retired computer. I will see what I can find.
easyw-fc wrote: Is there a way to get the View Position/Rotation, to be applied to DXF entities before the exporting, so to replicate the layout?
That information is definitely available in TechDraw, but I don't know how to specify it in DXF. Might take a while do decipher the DXF spec.
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TD: export View to DXF

Post by easyw-fc »

wandererfan wrote: Sat Mar 17, 2018 5:41 pm
easyw-fc wrote: Is there a way to get the View Position/Rotation, to be applied to DXF entities before the exporting, so to replicate the layout?
That information is definitely available in TechDraw, but I don't know how to specify it in DXF. Might take a while do decipher the DXF spec.
I'm investigating and it seems I could apply the X,Y position of the View to the Entities...
ATM what it could be done is:
1) shift ELLIPSE, CIRCLE and ARC by applying X,Y View position to 'AcDbEllipse' 'AcDbCircle' 'AcDbArc' entity in p.X(), p.Y()
2) shift LINE adding X,Y View position to 'AcDbLine' entity in PS.X(), PS.Y(), PE.X(), PE.Y()
for BSPLines I don't know how to do it ATM...

Is there a way to apply this shifting before doing the call 'TechDraw.viewPartAsDxf(v)'?

Thanx
Maurice
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TechDraw: export View to DXF

Post by easyw-fc »

wandererfan wrote: Sat Mar 17, 2018 5:41 pm That information is definitely available in TechDraw, but I don't know how to specify it in DXF. Might take a while do decipher the DXF spec.
I'm going a bit forward...
EDIT improved code/examples

Code: Select all

import FreeCAD, FreeCADGui
import TechDraw, StringIO



s=""
sout=""
simpleout=""
structure=[]
for o in FreeCAD.ActiveDocument.Objects:
    # print (o.Label)
    if o.TypeId == "TechDraw::DrawViewPart":
        x = o.X
        y = o.Y
        print ('view x,y ' + str(x)+', '+str(y))
        s = TechDraw.viewPartAsDxf(o)
        simpleout=s+simpleout
        #applying offset
        # i=0
        # for line in StringIO.StringIO(s):
        #     i+=1
        # #    print (line)
        # print (i)
        structure=s.splitlines(True)
        i=0
        for entity in structure:
            if 'AcDbCircle' in entity:
                structure [i+2] = str(x)+'\n'
                structure [i+4] = str(y)+'\n'
            if 'AcDbEllipse' in entity:
                print ('Ellipse')
                structure [i+2] = str(float(structure [i+2])+x)+'\n'
                structure [i+4] = str(float(structure [i+4])+y)+'\n'
            if 'AcDbLine' in entity:
                structure [i+2] = str(float(structure [i+2])+x)+'\n'
                structure [i+4] = str(float(structure [i+4])+y)+'\n'
                structure [i+8] = str(float(structure [i+8])+x)+'\n'
                structure [i+10] = str(float(structure [i+10])+y)+'\n'
            i+=1   
        print structure
        sout = sout + ''.join(structure)
    # print (s)
    # if o.TypeId == "TechDraw::DrawViewDimension":
    #     s = s+TechDraw.viewPartAsDxf(o)
        
#v = view1
#s = TechDraw.viewPartAsDxf(v)
# print (s)
fileSpecDxf = "d:/Temp/fcOutDxf.dxf"
dxfStart= "0\nSECTION\n2\nENTITIES\n"
dxfEnd = "0\nEOF\n"
dxfFile = open(fileSpecDxf, "w")
dxfFile.write(dxfStart)
dxfFile.write(sout)
dxfFile.write(dxfEnd)
dxfFile.close() 

fileSpecDxf = "d:/Temp/fcOutDxfSimple.dxf"
dxfStart= "0\nSECTION\n2\nENTITIES\n"
dxfEnd = "0\nEOF\n"
dxfFile = open(fileSpecDxf, "w")
dxfFile.write(dxfStart)
dxfFile.write(simpleout)
dxfFile.write(dxfEnd)
dxfFile.close() 

if 1:

    fileSpecSvg = "d:/Temp/fcOutSvg.svg"
    s=""
    for o in FreeCAD.ActiveDocument.Objects:
        print (o.Label)
        if o.TypeId == "TechDraw::DrawViewPart":
            s += TechDraw.viewPartAsSvg(o)
        # if o.TypeId == "TechDraw::DrawViewDimension":
        #     s = s+TechDraw.viewPartAsDxf(o)
    head = '<svg\n' + \
        '	xmlns="http://www.w3.org/2000/svg" version="1.1" \n' + \
        '	xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace">\n'
    tail = '\n</svg>'
    svgFile = open(fileSpecSvg, "w")
    svgFile.write(head)
    svgFile.write(s)
    svgFile.write(tail)
    svgFile.close() 
 
It seems that with circles, lines and ellipses the routine is working fine if a View Direction is the standard one (0,0,1), but not when the direction is i.e. (-1,-1,-1)
I don't know if this may depends on an internal error on TechDraw dxf routines
TD-dxf-2.FCStd
(20.54 KiB) Downloaded 71 times
TDtoDXF-3.gif
TDtoDXF-3.gif (309.7 KiB) Viewed 21591 times
It seems also I have found a bug in TechDraw.viewPartAsDxf() ... if I have a simple Ellipse, this function doesn't work
I'm attaching a test file...
TD-Ellipse.FCStd
(21.49 KiB) Downloaded 54 times
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TechDraw: export View to DXF

Post by easyw-fc »

Ok,
I think I'm very close...
here the code:

Code: Select all

import FreeCAD, FreeCADGui
import TechDraw, StringIO



s=""
sout=""
simpleout=""
structure=[]
for o in FreeCAD.ActiveDocument.Objects:
    # print (o.Label)
    if o.TypeId == "TechDraw::DrawViewPart":
        x = o.X
        y = o.Y
        print ('view x,y ' + str(x)+', '+str(y))
        s = TechDraw.viewPartAsDxf(o)
        simpleout=s+simpleout
        #applying offset
        # i=0
        # for line in StringIO.StringIO(s):
        #     i+=1
        # #    print (line)
        # print (i)
        structure=s.splitlines(True)
        i=0
        for entity in structure:
            if 'AcDbCircle' in entity:
                structure [i+2] = str(float(structure [i+2])+x)+'\n'
                structure [i+4] = str(float(structure [i+4])+y)+'\n'
            if 'AcDbEllipse' in entity:
                print ('Ellipse')
                structure [i+2] = str(float(structure [i+2])+x)+'\n'
                structure [i+4] = str(float(structure [i+4])+y)+'\n'
            if 'AcDbLine' in entity:
                structure [i+2] = str(float(structure [i+2])+x)+'\n'
                structure [i+4] = str(float(structure [i+4])+y)+'\n'
                structure [i+8] = str(float(structure [i+8])+x)+'\n'
                structure [i+10] = str(float(structure [i+10])+y)+'\n'
            i+=1   
        print structure
        sout = sout + ''.join(structure)
    # print (s)
    # if o.TypeId == "TechDraw::DrawViewDimension":
    #     s = s+TechDraw.viewPartAsDxf(o)
        
#v = view1
#s = TechDraw.viewPartAsDxf(v)
# print (s)
fileSpecDxf = "d:/Temp/fcOutDxf.dxf"
dxfStart= "0\nSECTION\n2\nENTITIES\n"
dxfEnd = "0\nEOF\n"
dxfFile = open(fileSpecDxf, "w")
dxfFile.write(dxfStart)
dxfFile.write(sout)
dxfFile.write(dxfEnd)
dxfFile.close() 

fileSpecDxf = "d:/Temp/fcOutDxfSimple.dxf"
dxfStart= "0\nSECTION\n2\nENTITIES\n"
dxfEnd = "0\nEOF\n"
dxfFile = open(fileSpecDxf, "w")
dxfFile.write(dxfStart)
dxfFile.write(simpleout)
dxfFile.write(dxfEnd)
dxfFile.close() 

if 1:

    fileSpecSvg = "d:/Temp/fcOutSvg.svg"
    s=""
    for o in FreeCAD.ActiveDocument.Objects:
        print (o.Label)
        if o.TypeId == "TechDraw::DrawViewPart":
            s += TechDraw.viewPartAsSvg(o)
        # if o.TypeId == "TechDraw::DrawViewDimension":
        #     s = s+TechDraw.viewPartAsDxf(o)
    head = '<svg\n' + \
        '	xmlns="http://www.w3.org/2000/svg" version="1.1" \n' + \
        '	xmlns:freecad="http://www.freecadweb.org/wiki/index.php?title=Svg_Namespace">\n'
    tail = '\n</svg>'
    svgFile = open(fileSpecSvg, "w")
    svgFile.write(head)
    svgFile.write(s)
    svgFile.write(tail)
    svgFile.close() 
    
TDtoDXF-4.gif
TDtoDXF-4.gif (164.82 KiB) Viewed 21577 times
I can confirm the following bug:
TechDraw.viewPartAsDxf if invoked for the simple ellipse I'm attaching, will produce a wrong output, instead the TechDraw.viewPartAsSvg() is working as expected
TD-Ellipse-simple.FCStd
(19.46 KiB) Downloaded 51 times
TDtoDXF-5.gif
TDtoDXF-5.gif (134.11 KiB) Viewed 21575 times
Thx for looking into this,
Maurice
User avatar
wandererfan
Veteran
Posts: 6317
Joined: Tue Nov 06, 2012 5:42 pm
Contact:

Re: TD: export View to DXF

Post by wandererfan »

reox wrote: Sat Mar 17, 2018 10:34 am On my machine I get at least some output:
LibreCAD will read your file with some modifications at each end.
reoxDxfInLC.png
reoxDxfInLC.png (22.19 KiB) Viewed 21540 times
easyw-fc wrote: Is there a way to apply this shifting before doing the call 'TechDraw.viewPartAsDxf(v)'?
yes, I can apply a translation based on the view position to each edge before passing it to the Dxf converter. That should save you from having to figure out how to do BSPLINE.

I don't understand the projection direction issue yet. The edges are already projected onto the page before being passed to the converter, so the direction shouldn't matter.
Attachments
reox_fcOut_mod.dxf
(375 Bytes) Downloaded 51 times
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TD: export View to DXF

Post by easyw-fc »

wandererfan wrote: Sat Mar 17, 2018 10:36 pm
easyw-fc wrote: Is there a way to apply this shifting before doing the call 'TechDraw.viewPartAsDxf(v)'?
yes, I can apply a translation based on the view position to each edge before passing it to the Dxf converter. That should save you from having to figure out how to do BSPLINE.
great, thx :D

wandererfan wrote: Sat Mar 17, 2018 10:36 pm I don't understand the projection direction issue yet. The edges are already projected onto the page before being passed to the converter, so the direction shouldn't matter.
Don't worry, I forgot to add the position in the shift for the circle/ellipse :oops: :D

But the issue with the 'TD-Ellipse-simple.FCStd' is present...

Moreover I found some issue with some arcs both in TechDraw.viewPartAsDxf() and TechDraw.viewPartAsSvg()... (the internal TechDraw export to svg is instead working fine)
I will post a file for reference...

Thx again
Maurice
User avatar
easyw-fc
Veteran
Posts: 3633
Joined: Thu Jul 09, 2015 9:34 am

Re: TechDraw: export View to DXF

Post by easyw-fc »

wandererfan wrote: Sat Mar 17, 2018 10:36 pm yes, I can apply a translation based on the view position to each edge before passing it to the Dxf converter. That should save you from having to figure out how to do BSPLINE.
it seems the issues I have with TechDraw.viewPartAsDxf are BSpline related...
Here two files where the dxf export is failing with bsplines (the dxf is the result of a direct export without the shifting)
pallier-front.FCStd
(34.52 KiB) Downloaded 52 times
pallier-front-top.FCStd
(34.81 KiB) Downloaded 52 times
TDtoDXF-6.gif
TDtoDXF-6.gif (182.55 KiB) Viewed 21037 times
thx again
Maurice
Post Reply