def testReferencedAttributeIndexesNonExistingField(self): e = QgsExpression() e.setExpression("foo = 1") self.assertTrue(e.isValid()) self.assertEqual(len(e.referencedAttributeIndexes(QgsFields())), 0)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context) order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context) date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context) mvalue_exp = self.parameterAsExpression(parameters, self.MVALUE_EXPRESSION, context) text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context) QgsMessageLog.logMessage("-"*80) QgsMessageLog.logMessage(str(mvalue_exp)) QgsMessageLog.logMessage(mvalue_exp.__class__.__name__) # instantiate the expression if mvalue is set if mvalue_exp: expression = QgsExpression(mvalue_exp) expression_ctx = self.createExpressionContext(parameters, context) expression.prepare(expression_ctx) else: expression = None group_field_index = source.fields().lookupField(group_field_name) order_field_index = source.fields().lookupField(order_field_name) if group_field_index >= 0: group_field_def = source.fields().at(group_field_index) else: group_field_def = None order_field_def = source.fields().at(order_field_index) fields = QgsFields() if group_field_def is not None: fields.append(group_field_def) begin_field = QgsField(order_field_def) begin_field.setName('begin') fields.append(begin_field) end_field = QgsField(order_field_def) end_field.setName('end') fields.append(end_field) output_wkb = QgsWkbTypes.LineString if QgsWkbTypes.hasM(source.wkbType()) or mvalue_exp: output_wkb = QgsWkbTypes.addM(output_wkb) if QgsWkbTypes.hasZ(source.wkbType()): output_wkb = QgsWkbTypes.addZ(output_wkb) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, output_wkb, source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) points = dict() referencedColumns = expression.referencedAttributeIndexes(source.fields()) if expression else [group_field_index, order_field_index] features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(referencedColumns), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue point = f.geometry().constGet().clone() if group_field_index >= 0: group = f.attributes()[group_field_index] else: group = 1 order = f.attributes()[order_field_index] if date_format != '': order = datetime.strptime(str(order), date_format) if group in points: points[group].append((order, point, f)) else: points[group] = [(order, point, f)] feedback.setProgress(int(current * total)) feedback.setProgress(0) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) current = 0 total = 100.0 / len(points) if points else 1 for group, vertices in list(points.items()): if feedback.isCanceled(): break vertices.sort(key=lambda x: (x[0] is None, x[0])) f = QgsFeature() attributes = [] if group_field_index >= 0: attributes.append(group) attributes.extend([vertices[0][0], vertices[-1][0]]) f.setAttributes(attributes) line = [node[1] for node in vertices] if text_dir: fileName = os.path.join(text_dir, '%s.txt' % group) with open(fileName, 'w') as fl: fl.write('angle=Azimuth\n') fl.write('heading=Coordinate_System\n') fl.write('dist_units=Default\n') for i in range(len(line)): if i == 0: fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y())) fl.write('survey=Polygonal\n') fl.write('[data]\n') else: angle = line[i - 1].azimuth(line[i]) distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i])) fl.write('%f;%f;90\n' % (angle, distance)) linestring = QgsLineString(line) if mvalue_exp: linestring.addMValue(0) for i, node in enumerate(vertices): QgsMessageLog.logMessage(node[2].__class__.__name__) expression_ctx.setFeature(node[2]) mvalue = expression.evaluate(expression_ctx) if expression.hasEvalError(): raise QgsProcessingException( self.tr('Evaluation error: {0}').format(expression.evalErrorString())) QgsMessageLog.logMessage("evaluating mvalue at {} to {} {}".format(i, mvalue, mvalue.__class__)) # mvalue = 12 # TODO : remove QgsMessageLog.logMessage("setting mvalue at {} to {} {}".format(i, mvalue, mvalue.__class__)) linestring.setMAt(i, mvalue) # test = linestring.mAt(i) # TODO : remove # QgsMessageLog.logMessage("mvalue at {} is {} {}".format(i, test, test.__class__)) # TODO : remove f.setGeometry(QgsGeometry(linestring)) sink.addFeature(f, QgsFeatureSink.FastInsert) current += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}