示例#1
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        track_id = self.parameterAsInt(parameters, self.TRACK_ID, context)
        track_tags = self.parameterAsString(parameters, self.TRACK_TAGS,
                                            context)
        timestamp_field = self.parameterAsString(parameters,
                                                 self.TIMESTAMP_FIELD, context)
        add_track_point_motion_attributes = self.parameterAsBoolean(
            parameters, self.ADD_MOTION_ATTRIBUTES, context)
        fields_for_tags = self.parameterAsFields(parameters,
                                                 self.FIELDS_AS_TAGS, context)
        json_file = self.parameterAsFileOutput(parameters, self.OUTPUT,
                                               context)

        json_track = {
            'id': track_id,
            'metadata': dict(),
            'trackPoints': list()
        }

        meta_number_of_points = 0
        meta_start_date = None
        meta_end_date = None
        meta_length = 0
        meta_tags = None
        if track_tags != '':
            meta_tags = json.loads(track_tags)

        base_timestamp = QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0),
                                   QTimeZone.utc())
        base_timestamp_ms = base_timestamp.toMSecsSinceEpoch()

        previous_feature = None
        previous_track_point = None

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, feature in enumerate(source.getFeatures()):

            if not feature[timestamp_field]:
                # Skip feature
                # feedback.pushInfo("Timestamp not available. Point skipped.")
                continue
            if not feature.geometry():
                # Skip feature
                # feedback.pushInfo("Geometry not available. Point skipped.")
                continue

            feature_timestamp_ms = feature[timestamp_field].toMSecsSinceEpoch()
            timestamp = int((feature_timestamp_ms - base_timestamp_ms))

            meta_start_date = timestamp if meta_start_date is None else meta_start_date
            meta_end_date = timestamp
            meta_number_of_points += 1

            track_point = {
                'id': meta_number_of_points,
                'timestamp': timestamp,
                'x': feature.geometry().constGet().x(),
                'y': feature.geometry().constGet().y()
            }

            if feature.geometry().constGet().is3D():
                track_point['z'] = feature.geometry().constGet().z()

            length = 0.0
            if previous_feature:
                length = GeomTools.distance(
                    previous_feature.geometry().constGet(),
                    feature.geometry().constGet(), source.sourceCrs())
                if length is not None:
                    meta_length += length

            if add_track_point_motion_attributes:
                if previous_feature:
                    track_point['h'] = GeomTools.calculate_angle(
                        previous_feature.geometry().constGet(),
                        feature.geometry().constGet()) / math.pi * 180
                    track_point['distCalc'] = length
                    track_point['vCalc'] = GeomTools.calculate_speed(
                        previous_feature[timestamp_field],
                        feature[timestamp_field],
                        previous_feature.geometry().constGet(),
                        feature.geometry().constGet(), source.sourceCrs())
                    track_point[
                        'durationCalc'] = timestamp - previous_track_point[
                            'timestamp']
                    if track_point['vCalc'] and previous_track_point['vCalc']:
                        track_point['aCalc'] = (track_point['vCalc'] / 3.6 - previous_track_point['vCalc'] / 3.6) /\
                                               (track_point['durationCalc'] / 1000)
                    else:
                        track_point['aCalc'] = None
                else:
                    # first feature
                    track_point['h'] = None
                    track_point['distCalc'] = None
                    track_point['vCalc'] = None
                    track_point['durationCalc'] = None
                    track_point['aCalc'] = None

            if len(fields_for_tags) > 0:
                track_point_tags = dict()
                for field in fields_for_tags:
                    if feature[field]:
                        track_point_tags[field] = feature[field]

                if len(track_point_tags) > 0:
                    track_point['tags'] = track_point_tags

            json_track['trackPoints'].append(track_point)
            feedback.setProgress(int(current * total))

            previous_feature = feature
            previous_track_point = track_point

        if meta_start_date and meta_end_date:
            json_track['metadata'][
                'duration'] = meta_end_date - meta_start_date
        else:
            json_track['metadata']['duration'] = None
        json_track['metadata']['startDate'] = meta_start_date
        json_track['metadata']['endDate'] = meta_end_date
        json_track['metadata']['length'] = meta_length
        json_track['metadata']['numberOfPoints'] = meta_number_of_points
        if meta_tags:
            json_track['metadata']['tags'] = meta_tags

        with open(json_file, 'w') as output_file:
            output_file.write(json.dumps(json_track))

        return {
            self.OUTPUT: json_file,
            self.NUMBER_TRACK_POINTS: meta_number_of_points
        }
示例#2
0
    def test_feature_to_json(self):
        test_fields = QgsFields()

        attributes = []

        test_fields.append(QgsField('a_string_field', QVariant.String))
        attributes.append('my string value')

        test_fields.append(QgsField('a_int_field', QVariant.Int))
        attributes.append(5)

        test_fields.append(QgsField('a_double_field', QVariant.Double))
        attributes.append(5.5)

        test_fields.append(QgsField('a_boolean_field', QVariant.Bool))
        attributes.append(True)

        test_fields.append(QgsField('a_datetime_field', QVariant.DateTime))
        attributes.append(
            QDateTime(QDate(2022, 3, 4), QTime(12, 13, 14), Qt.UTC))

        test_fields.append(QgsField('a_date_field', QVariant.Date))
        attributes.append(QDate(2022, 3, 4))

        test_fields.append(QgsField('a_null_value', QVariant.String))
        attributes.append(NULL)

        test_feature = QgsFeature(test_fields)
        test_feature.setAttributes(attributes)
        test_feature.setGeometry(QgsGeometry.fromWkt('Point(1 2)'))

        context = QgsArcGisRestContext()
        context.setTimeZone(QTimeZone.utc())
        res = QgsArcGisRestUtils.featureToJson(test_feature, context)
        self.assertEqual(
            res, {
                'attributes': {
                    'a_boolean_field': True,
                    'a_datetime_field': 1646395994000,
                    'a_date_field': 1646352000000,
                    'a_double_field': 5.5,
                    'a_int_field': 5,
                    'a_string_field': 'my string value',
                    'a_null_value': None
                },
                'geometry': {
                    'x': 1.0,
                    'y': 2.0
                }
            })
        # without geometry
        res = QgsArcGisRestUtils.featureToJson(
            test_feature,
            context,
            flags=QgsArcGisRestUtils.FeatureToJsonFlags(
                QgsArcGisRestUtils.FeatureToJsonFlag.
                IncludeNonObjectIdAttributes))
        self.assertEqual(
            res, {
                'attributes': {
                    'a_boolean_field': True,
                    'a_datetime_field': 1646395994000,
                    'a_date_field': 1646352000000,
                    'a_double_field': 5.5,
                    'a_int_field': 5,
                    'a_string_field': 'my string value',
                    'a_null_value': None
                }
            })
        # without attributes
        context.setObjectIdFieldName('a_int_field')
        res = QgsArcGisRestUtils.featureToJson(
            test_feature,
            context,
            flags=QgsArcGisRestUtils.FeatureToJsonFlags(
                QgsArcGisRestUtils.FeatureToJsonFlag.IncludeGeometry))
        self.assertEqual(res, {
            'attributes': {
                'a_int_field': 5
            },
            'geometry': {
                'x': 1.0,
                'y': 2.0
            }
        })