1

I have written a python script which has two input vector layers (one point-layer and one line-layer). The outpout is another line-layer. But when I try too set the geometry for the new edge, the python script stopps and I get the error "minidump written to C".

Here is my python script code:

# name :  MergeEdges_script
# date   : 22.10.2018
# description: merges edges with the same edgeid
#           and adds two attributes for speed limits on each lane 

from qgis.core import *
from PyQt4.QtCore import *
from math import degrees

#***********Constants*************#
EDGEID = 'edgeid'
FROM = 'from'
TO = 'to'
PRIORITY = 'priority'
LENGTH = 'length'
TIME = 'time'

ID = 'id'
VTO = 'vto'
VFROM = 'vfrom'
NODE1 = 'node1'
NODE2 = 'node2'
#*******************************#

# input parameters 
##Edges=vector
##Nodes=vector

inLayerEdges = processing.getObject(Edges)
inNodes = processing.getObject(Nodes)

crs = inLayerEdges.crs().toWkt()

# get field indices for inputlayer
idxEdgeId = inLayerEdges.fieldNameIndex(ID)
idxPriority = inLayerEdges.fieldNameIndex(PRIORITY)
idxLength  = inLayerEdges.fieldNameIndex(LENGTH)
idxTime    = inLayerEdges.fieldNameIndex(TIME)
idxFrom  = inLayerEdges.fieldNameIndex(FROM)
idxTo  = inLayerEdges.fieldNameIndex(TO)

idx_id = inNodes.fieldNameIndex(NODEID)
idx_x = inNodes.fieldNameIndex(COORD_X)
idx_y = inNodes.fieldNameIndex(COORD_Y)

# Create output layer and specify geometry type
outLayer = QgsVectorLayer('Linestring?crs=' + crs, 'merged_edges', 'memory')
# Set the provider to accept the data source
outdp = outLayer.dataProvider()

# define attributes and add them to the vector layer
outdp.addAttributes([QgsField(EDGEID, QVariant.String),
                        QgsField(NODE1, QVariant.String),
                        QgsField(NODE2, QVariant.String),
                        QgsField(PRIORITY, QVariant.Int),
                        QgsField(VTO, QVariant.Double),
                        QgsField(VFROM, QVariant.Double)])
outLayer.updateFields()

# get field indices for outputlayer
outEdgeId = outdp.fieldNameIndex(EDGEID)
outNode1 = outdp.fieldNameIndex(NODE1)
outNode2 = outdp.fieldNameIndex(NODE2)
outPriority = outdp.fieldNameIndex(PRIORITY)
outVTo = outdp.fieldNameIndex(VTO)
outVFrom = outdp.fieldNameIndex(VFROM)

listOfEdgeIds = []
count = 0
flag = 0

# loop through edges of inLayerEdges and merge 
for feat in inLayerEdges.getFeatures():

  # create new edge (line) for outputLayer
  newEdge = QgsFeature(outLayer.pendingFields())

  currentPriority = feat.attributes()[idxPriority]
  currentEdgeId = feat.attributes()[idxEdgeId]

  if currentEdgeId.find('From') == -1:
      edgeIdTrimmed = currentEdgeId.replace('To', '')
  else:
      edgeIdTrimmed = currentEdgeId.replace('From', '')

  if edgeIdTrimmed in listOfEdgeIds:
      # if current edge id already processed -> skip it.
      #print "current edgeid already in list. Continue ..."
      continue

  else:      
      # if not, find all entries in the graph which share the same current edge id
      # and merge them
      listOfEdgeIds.append(edgeIdTrimmed)

      newEdge.setAttribute(EDGEID, edgeIdTrimmed)
      newEdge.setAttribute(PRIORITY, currentPriority)

      node1 = feat.attributes()[idxFrom]
      node2 = feat.attributes()[idxTo]
      newEdge.setAttribute(NODE1, node1)
      newEdge.setAttribute(NODE2, node2)

      # search for specific from_node by nodeID
      exp = QgsExpression('nodeID ILIKE \'' + node1 +'\' ')
      request = QgsFeatureRequest(exp)
      request.setLimit(1)

      for feat2 in inNodes.getFeatures(request):
          geomFrom = feat2.geometry()
          print geomFrom

      # search for specific to_node by nodeID
      exp = QgsExpression('nodeID ILIKE \'' + node2 +'\' ')
      request = QgsFeatureRequest(exp)
      request.setLimit(1)

      for feat2 in inNodes.getFeatures(request):
          geomTo = feat2.geometry()
          print geomTo

      # find all entries in the graph with current edge id
      exp = QgsExpression('id ILIKE \'' + edgeIdTrimmed + '%\' ')
      request = QgsFeatureRequest(exp)

      # loop through all egdes with the same current edgeids
      for feat1 in inLayerEdges.getFeatures(request):

          tempEdgeId = feat1.attributes()[idxEdgeId]

          length = feat1.attributes()[idxLength]
          time    = feat1.attributes()[idxTime]
          velocity = (length / time) * 3.6

          if tempEdgeId.find("From") is not -1:
              #print("Python found the string From!")
              newEdge.setAttribute(VFROM, velocity)
          elif tempEdgeId.find("To") is not -1:
              #print("Python found the string To!")
              newEdge.setAttribute(VTO, velocity)
          else:
              print("Python did NOT find the substring!")


    newEdge.setGeometry(QgsGeometry.fromPolyline
      ([geomFrom.asPoint(),geomTo.asPoint()]))
    # add the feature to the layer
    (res, outFeats) = outdp.addFeatures([newEdge])


# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)
print "Done ... "

With the help of printf-Debugging, I have figured out that the crash is caused by this line:

        newEdge.setGeometry(QgsGeometry.fromPolyline([geomFrom.asPoint(),geomTo.asPoint()]))

I have already deleted the .qgis2-folder and started qgis 2.18 anew. But without success.

Any suggestions?

2

You are most likely hitting the famous issue 777

There are 2 possibilities to get around this:

  1. Upgrade to QGIS 3
  2. Make sure the geometry is saved to a variable and not passed as temporary to keep the python garbage collector happy

geom = QgsGeometry.fromPolyline([geomFrom.asPoint(),geomTo.asPoint()])
newEdge.setGeometry(geom)
  • Thank you for your answer, your 2. suggestions hasn't solved the problem, so I will try it by upgrading to QGIS3. I will let you know if I was able to solve the issue. – applebrown Oct 31 '18 at 10:52

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.