def _vertex_id(part, ring, vertex): vertex_id = QgsVertexId(part, ring, vertex, QgsVertexId.SegmentVertex) if not vertex_id.isValid(): vertex_id = QgsVertexId(part, ring, vertex, QgsVertexId.CurveVertex) if not vertex_id.isValid(): raise ValueError("Invalid vertex addressing.") return vertex_id
def transformFeatures(self): inQueue = multiprocessing.Queue() outQueue = multiprocessing.Queue() threads = [] numThreads = multiprocessing.cpu_count() + 1 for _ in range(numThreads): p = multiprocessing.Process(target=transformPoint, args=(self.metaFeatures, self.reductionFactor, inQueue, outQueue)) p.start() threads.append(p) features = \ {feature.id(): feature.geometry() for feature in self.layer.getFeatures()} for featureId in features: abstractGeometry = features[featureId].constGet() for p in range(abstractGeometry.partCount()): for r in range(abstractGeometry.ringCount(p)): for v in range(abstractGeometry.vertexCount(p, r) - 1): # -1 because the last one is the first one again vertexId = \ QgsVertexId(p, r, v, QgsVertexId.SegmentVertex) if not vertexId.isValid(): vertexId = QgsVertexId(p, r, v, QgsVertexId.CurveVertex) if not vertexId.isValid(): continue point = abstractGeometry.vertexAt(vertexId) inQueue.put( ((featureId, p, r, v), (point.x(), point.y()))) self.progress.emit(1) for _ in range(numThreads): inQueue.put((None, (None, None))) while True: if self.stopped: # clean inQueue while True: (f, g) = inQueue.get() if f is None: break # put some more death pills so everybody gets one for i in range(numThreads): inQueue.put((None, (None, None))) # wait for the children to die for p in threads: p.join() # give up ourselves (main thread) break ((featureId, p, r, v), (x, y)) = outQueue.get() if featureId is None: numThreads -= 1 if numThreads == 0: break else: continue abstractGeometry = features[featureId].constGet().clone() abstractGeometry.moveVertex( QgsVertexId(p, r, v, QgsVertexId.SegmentVertex), QgsPoint(x, y)) features[featureId] = QgsGeometry(abstractGeometry) self.layer.dataProvider().changeGeometryValues(features) self.layer.reload()