Test Read DXF file, display geometry by pivy.coin

A forum dedicated to the Draft, Arch and BIM workbenches development.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Test Read DXF file, display geometry by pivy.coin

Post by chakkree »

The problem to import DXF file to FreeCAD Object, its take a long time.
I write the macro to read dxf file and use pivy.coin for display line, lwpolyline and circle.
Used External Python Module, dxfgrabber for reads data from dxf file.
Next step, I will try to use pivy.coin display texts, blocks from the dxf file.
-------------------------------
OS: Windows 10
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.17.10235 (Git)
Build type: Release
Branch: master
Hash: e5fe3d8e107bc604bc868922d82f5fb3611cdd93
Python version: 2.7.8
Qt version: 4.8.7
Coin version: 4.0.0a
OCC version: 7.0.0

Code: Select all

# -*- coding: utf8 -*-

#
#  chakkree tiyawongsuwan
#

import dxfgrabber

import FreeCADGui
import Draft , Part
import math


from FreeCAD import Vector
from pivy import coin
from math import  radians

path = 'D:\\FreeCAD\\2017\\Python\\ReadDXF\\'
#dxf = dxfgrabber.readfile(path + "Structural_Floor01.dxf")
dxf = dxfgrabber.readfile(path +'A-Plan_Floor1.dxf')



def readDXF2DraftObject():
    all_lines = [entity for entity in dxf.entities if entity.dxftype == 'LINE']
    for iEntry in all_lines:
        points=[FreeCAD.Vector(iEntry.start),FreeCAD.Vector(iEntry.end)]
        line = Draft.makeWire(points,closed=False,face=True,support=None)
    
    
    all_lines = [entity for entity in dxf.entities if entity.dxftype == 'LWPOLYLINE']
    for iEntry in all_lines:
        points =[]
        for iPoint in iEntry.points:
            #Msg("%f , %f \n"%(iPoint[0],iPoint[1]))
            pt1 = FreeCAD.Vector( iPoint[0],iPoint[1] , 0 )
            points.append(pt1)
        line = Draft.makeWire(points,closed=iEntry.is_closed,face=True,support=None)

def readDXF2Coin():
    scale = 1000.0
    sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
    all_lines = [entity for entity in dxf.entities if entity.dxftype == 'LINE']
    for iEntry in all_lines:
        points=[FreeCAD.Vector(iEntry.start),FreeCAD.Vector(iEntry.end)]
        sep = coin.SoSeparator()
        mat = coin.SoMaterial()
        linestyle = coin.SoDrawStyle()
        linecoords = coin.SoCoordinate3()
        lineset = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
        
        linestyle.linePattern = 0xffff
        mat.diffuseColor.setValue([0.494,0.184,0.267])
        
        linecoords.point.setValues([[iEntry.start[0]*scale,iEntry.start[1]*scale,iEntry.start[2]*scale] ,
                                    [iEntry.end[0]*scale,iEntry.end[1]*scale,iEntry.end[2]*scale]])
        lineset.coordIndex.setValues(0,2,[0,1])
        lineset.coordIndex.setNum(2)
        sep.addChild(mat)
        sep.addChild(linestyle)
        sep.addChild(linecoords)
        sep.addChild(lineset)
        sg.addChild(sep)
     
    all_lines = [entity for entity in dxf.entities if entity.dxftype == 'LWPOLYLINE']
    for iEntry in all_lines:
        verts = []
        vset = []
        i=0
        for iPoint in iEntry.points:
            verts.append([iPoint[0]*scale,iPoint[1]*scale , 0 ])
            vset.append(i)
            i += 1
        
        points.append(-1)
        sep = coin.SoSeparator()
        mat = coin.SoMaterial()
        linestyle = coin.SoDrawStyle()
        linecoords = coin.SoCoordinate3()
        lineset = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
        
        linestyle.linePattern = 0xffff
        mat.diffuseColor.setValue([0.0,0.0,0.0])
        
        linecoords.point.setValues(verts)
        lineset.coordIndex.setValues(0,len(vset),vset  )
        lineset.coordIndex.setNum(len(vset))
        sep.addChild(mat)
        sep.addChild(linestyle)
        sep.addChild(linecoords)
        sep.addChild(lineset)
        sg.addChild(sep)
    
    all_circles = [entity for entity in dxf.entities if entity.dxftype == 'CIRCLE']
    for iEntry in all_circles:
        rad = iEntry.radius*scale
        center = Vector(iEntry.center[0]*scale, iEntry.center[1]*scale, 0)
        buf = Part.makeCircle(rad,center).writeInventor()
        try:
            cin = coin.SoInput()
            cin.setBuffer(buf)
            cob = coin.SoDB.readAll(cin)
        except:
            buf = buf.replace("\n","")
            pts = re.findall("point \[(.*?)\]",buf)[0]
            pts = pts.split(",")
            pc = []
            for p in pts:
                v = p.strip().split()
                pc.append([float(v[0]),float(v[1]),float(v[2])])
            coords = coin.SoCoordinate3()
            coords.point.setValues(0,len(pc),pc)
            line = coin.SoLineSet()
            line.numVertices.setValue(-1)
        
        mat.diffuseColor.setValue([0.0,0.463,0.0])
        bubble = coin.SoSeparator()
        
        bubble.addChild(coords)
        bubble.addChild(line)
        bubble.addChild(mat)
        sep.addChild(bubble)

#readDXF2DraftObject()
readDXF2Coin()

Msg('Done!\n')
Result from macro:
Test02.png
Test02.png (421.85 KiB) Viewed 8069 times
Test01.png
Test01.png (298.75 KiB) Viewed 8069 times
User avatar
yorik
Founder
Posts: 13659
Joined: Tue Feb 17, 2009 9:16 pm
Location: Brussels
Contact:

Re: Test Read DXF file, display geometry by pivy.coin

Post by yorik »

Oh that's really nice! Indeed often a dxf file is only needed as a reference background, it doesn't really to "exist" in the document.
But have you tried the built-in (not legacy) importer with the "group layers into blocks" option turned on? That is really fast.
User avatar
Eneen
Posts: 61
Joined: Wed Aug 12, 2015 9:06 pm

Re: Test Read DXF file, display geometry by pivy.coin

Post by Eneen »

I can help testing with bunch of my dxfs (from dwg).
User avatar
chakkree
Posts: 327
Joined: Tue Jun 30, 2015 12:58 am
Location: Bangkok Thailand

Re: Test Read DXF file, display geometry by pivy.coin

Post by chakkree »

yorik wrote:Oh that's really nice! Indeed often a dxf file is only needed as a reference background, it doesn't really to "exist" in the document.
But have you tried the built-in (not legacy) importer with the "group layers into blocks" option turned on? That is really fast.
@Yorik, Thank you so much.
The dxfLibrary is very fast.
I set "group layers into blocks" option turned on, and download dxfLibrary.

Result:
Test_dxfLibrary_01.png
Test_dxfLibrary_01.png (278.44 KiB) Viewed 7940 times
Post Reply