1

I'm writing a script with python in QGIS that allows me to convert a dxf file to shp. In the dxf file I have oriented text but after the conversion I lose this information. Is it possible to keep it? this is my script :

import os 
from PyQt4.QtCore import *
import datetime
print datetime.datetime.now().minute
uri="C:/Users/Lenovo/Desktop/stage_brome/restitution.dxf|layername=entities"
vlayer = QgsVectorLayer(uri, 'layer', 'ogr')
##For each sublayer, diferent type of geometry, load a layer to map.
subLayers = vlayer.dataProvider().subLayers()
types=["LineString","Point","Polygon"]
for sublayer in subLayers:
    #Extract the geometry type
    geom_type = sublayer.split(':')[-1]
    #Set the path
    url = str(uri)+"|layername=entities|geometrytype="+str(geom_type)
    #Name for sub layer
    dxf_file_name = os.path.splitext(os.path.basename(url))[0]
    layer_name =str(dxf_file_name)+" - "+str(geom_type)
    #Create layer
    sub_vlayer = QgsVectorLayer(url, layer_name, 'ogr')
    #Add layer to map
    QgsMapLayerRegistry.instance().addMapLayer(sub_vlayer)
    if geom_type in types:
        #list of string that contains the name of each layer 
        layer_types=[]
        #list of vector layers 
        vlayers_by_type=[]
        #list of providers for each vector layer
        vlayers_providers=[]
        geom_types=[]

        for feature in sub_vlayer.getFeatures():
            #fill the lists (vector layer and it's provider and attributes of each layer)
            if (feature.attributes())[0] not in layer_types:
                name=(feature.attributes())[0]
                layer_types.append(name)
                # create vlayer
                vl=QgsVectorLayer(geom_type, "temporary_points", "memory")
                geom_types.append(geom_type)
                pr = vl.dataProvider()
                # add fields
                fields=[field for field in sub_vlayer.pendingFields()]
                pr.addAttributes(fields)
                # tell the vector layer to fetch changes from the provider
                vl.updateFields()
                vlayers_by_type.append(vl)
                vlayers_providers.append(pr)
                error = QgsVectorFileWriter.writeAsVectorFormat(vl, "C:/Users/Lenovo/Desktop/stage_brome/output/layers/"+name+"-"+str(geom_type)+".shp", "CP1250", None, "ESRI Shapefile")
#                if error != QgsVectorFileWriter.NoError:
#                    print "failed  "------------------------------------

        for feature in sub_vlayer.getFeatures():
            name=(feature.attributes())[0] 
            if name in layer_types:
                # add features 
                vl=vlayers_by_type[layer_types.index(name)]
                pr=vlayers_providers[layer_types.index(name)]
                pr.addFeatures([feature])
                # update layer's extent when new features have been added
                # because change of extent in provider is not propagated to the layer
                geom_type=geom_types[layer_types.index(name)]
                vl.updateExtents()
                error = QgsVectorFileWriter.writeAsVectorFormat(vl, "C:/Users/Lenovo/Desktop/stage_brome/output/layers/"+str(name)+"-"+str(geom_type)+".shp", "CP1250", None, "ESRI Shapefile")
                if error != QgsVectorFileWriter.NoError:
                    print "failed  "+str(layer_types[vlayers_by_type.index(vl)])

print datetime.datetime.now().minute
0

Yes it is possible. The plugin "AnotherDXF2Shape" makes that.

[edit] You must use the appropriate SQL code with OGR.

import processing
dxfdat="d:/.../test.dxf"
shpdat="d:/.../dxf2.shp"

opt="-skipfailure  --config DXF_MERGE_BLOCK_GEOMETRIES FALSE --config DXF_INLINE_BLOCKS TRUE  -nlt POINT "
sql= "-sql \"select *, ogr_style from entities where OGR_GEOMETRY LIKE '%POINT%'\""

print processing.runalg('gdalogr:convertformat',dxfdat , 0,opt + sql, shpdat)

Then you find the angle in the DBF column ogr_style Param a:<win>:

LABEL(f:"Arial",t:"mytext",p:1,s:0.603g,c:#000000,a:143.25)

1) In Plugin "AnotherDXF2Shape" there is a Option: "Group layer". enter image description here

2) My Code produce a shape with a DBF. In the DBF exist a field "Layer".

import processing
dxfdat="d:/test.dxf"
shpdat="d:/point.shp"
savedir="d:/output/layers/"

# Step 1: Create a Shape with POINT's
opt="-skipfailure  --config DXF_MERGE_BLOCK_GEOMETRIES FALSE --config DXF_INLINE_BLOCKS TRUE  -nlt POINT "
sql= "-sql \"select *, ogr_style from entities where OGR_GEOMETRY LIKE '%POINT%'\""

print processing.runalg('gdalogr:convertformat',dxfdat , 0,opt + sql, shpdat)
DBFedit (shpdat) ###!!!!!!!!!!!!!###
# Step 2: Group the Shape by Layer
Layer = QgsVectorLayer(shpdat, "points","ogr") 

fni = Layer.fieldNameIndex('Layer')
unique_values = Layer.dataProvider().uniqueValues(fni)
for AktLayerNam in unique_values:
        Layer = QgsVectorLayer(shpdat, AktLayerNam,"ogr")
        Layer.setSubsetString( "Layer = '" + AktLayerNam + "'" )
        QgsMapLayerRegistry.instance().addMapLayer(Layer, True) 
        # Step 3:  save Shape by Layer
        QgsVectorFileWriter.writeAsVectorFormat(Layer, savedir+ AktLayerNam+ ".shp", "CP1250", None, "ESRI Shapefile")

This function edits the point shape. Quick&dirty:

# -*- coding: utf-8 -*-
import ogr
def DBFedit (shpdat):
    def trennArtDaten(ArtDaten):
        #BRUSH(fc:#dcdcdc)
        #LABEL(f:"Arial",t:"{\fArial|b1|i0|c0|p34;VZOG}",s:3.5g,p:8,c:#ff7f7f)
        sDaten = ""
        sArt = ""
        inDaten = False
        for c in ArtDaten[:-1]:
            if c == '(' and not inDaten:
                inDaten = True
                c = ''
            if inDaten:
                sDaten = sDaten + c
            else:
                sArt = sArt + c
        return sArt, sDaten

    def csvSplit(csvZeile, trenn=',', tKenn='"', tKennDel = True):
        inString = False
        mask = ""
        s = ''
        sb = False
        for c in csvZeile: 

            if c == tKenn and not sb:
                inString = not inString
            if c == trenn and inString  and not sb:
                if mask == "":
                    mask = "$$"
                    while mask in csvZeile:
                        mask = mask + '$'
                s=s+mask
            else:
                if not (tKennDel and (not sb) and c == tKenn): 
                    s=s+c
            if c == "\\":
                sb = True
            else:
                sb = False

        arr = s.split(trenn)
        if mask != "":
            for i in range(0,len(arr)):
                arr[i] = arr[i].replace(mask,trenn)

        return arr

    source = ogr.Open(shpdat, update=True)
    if source is None:
        print('ogr: can not open: ' + shpdat)
        return

    layer = source.GetLayer()
    laydef = layer.GetLayerDefn()

    Found = False
    for i in range(laydef.GetFieldCount()):
        if laydef.GetFieldDefn(i).GetName() == 'ogr_style':
            Found = True

    if not Found:
        print("missing field 'ogr_style': " + shpdat)
        return
    # add a new field for angle
    layer.CreateField(ogr.FieldDefn('angle', ogr.OFTReal))    

    feature = layer.GetNextFeature()
    while feature:
            att=feature.GetField('ogr_style') 
            if att is None:
                print("missing field 'ogr_style' in: "  + shpdat)
            else:
                sArt,sDaten = trennArtDaten(att)
                params = csvSplit (sDaten)
                for param in params:
                    arr=csvSplit(param,":")
                    if len(arr) == 2:
                        f = arr[0]
                        w = arr[1]
                        if f == "a":
                            dWin = float(w)
                            if dWin >=360:
                                dWin = dWin - 360                             
                            feature.SetField('angle', dWin)
                    else:
                        print ("incomplete field 'ogr_style': " + param)

            layer.SetFeature(feature)
            feature = layer.GetNextFeature()
    source.Destroy()
16
  • I'm writing my own script because of some other specific needs – ayar anasse Mar 1 '18 at 12:48
  • Then please show what you have tried - the relevant code. – Mike Mar 1 '18 at 13:28
  • I edit my answer. – Mike Mar 1 '18 at 14:15
  • is it possible to combine this with my code ? – ayar anasse Mar 1 '18 at 14:49
  • I do not think so. My way is different (processing-modul). What should your code do, what AnotherDXF2Shape can not do? – Mike Mar 1 '18 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.