def stationTimeZone(stationFeature):
    timeZoneId = stationFeature['timeZoneId']
    timeZoneUTC = stationFeature['timeZoneUTC']

    tz = None
    if timeZoneId:
        tz = QTimeZone(QByteArray(timeZoneId.encode()))
        if not tz.isValid():
            tz = None
    if not tz:
        tz = QTimeZone(QByteArray(timeZoneUTC.encode()))

    return tz
    def convert_to_time_zone(values, feature, parent):
        """Converts the given datetime to a time zone.<br>
        <br>
        convert_to_time_zone(datetime, utcId[, ianaId])<br>
        <br>
        datetime -- a datetime to convert<br>
        utcId -- a required string UTC offset, e.g. 'UTC+01:00'
        ianaId -- an optional IANA timezone ID, e.g. 'America/Chicago'
        """
        dt = values[0]
        utcId = values[1]
        tz = None

        if len(values) >= 3:
            ianaId = values[2]
            if ianaId:
                tz = QTimeZone(QByteArray(ianaId.encode()))   # if we have IANA, we'll try it
                if not tz.isValid():
                    tz = None           # wasn't available on our system, we guess
        if not tz:
            tz = QTimeZone(QByteArray(utcId.encode()))   # our fallback position is to use UTC

        return dt.toTimeZone(tz)
示例#3
0
    def testExportToSvg(self):
        md = QgsProject.instance().metadata()
        md.setTitle('proj title')
        md.setAuthor('proj author')
        md.setCreationDateTime(QDateTime(QDate(2011, 5, 3), QTime(9, 4, 5), QTimeZone(36000)))
        md.setIdentifier('proj identifier')
        md.setAbstract('proj abstract')
        md.setKeywords({'kw': ['kw1', 'kw2']})
        QgsProject.instance().setMetadata(md)
        l = QgsLayout(QgsProject.instance())
        l.initializeDefaults()

        # add a second page
        page2 = QgsLayoutItemPage(l)
        page2.setPageSize('A5')
        l.pageCollection().addPage(page2)

        # add some items
        item1 = QgsLayoutItemShape(l)
        item1.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.green)
        fill.setStrokeStyle(Qt.NoPen)
        item1.setSymbol(fill_symbol)
        l.addItem(item1)

        item2 = QgsLayoutItemShape(l)
        item2.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        item2.attemptMove(QgsLayoutPoint(10, 20), page=1)
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.cyan)
        fill.setStrokeStyle(Qt.NoPen)
        item2.setSymbol(fill_symbol)
        l.addItem(item2)

        exporter = QgsLayoutExporter(l)
        # setup settings
        settings = QgsLayoutExporter.SvgExportSettings()
        settings.dpi = 80
        settings.forceVectorOutput = False
        settings.exportMetadata = True

        svg_file_path = os.path.join(self.basetestpath, 'test_exporttosvgdpi.svg')
        svg_file_path_2 = os.path.join(self.basetestpath, 'test_exporttosvgdpi_2.svg')
        self.assertEqual(exporter.exportToSvg(svg_file_path, settings), QgsLayoutExporter.Success)
        self.assertTrue(os.path.exists(svg_file_path))
        self.assertTrue(os.path.exists(svg_file_path_2))

        # metadata
        def checkMetadata(f, expected):
            # ideally we'd check the path too - but that's very complex given that
            # the output from Qt svg generator isn't valid XML, and no Python standard library
            # xml parser handles invalid xml...
            self.assertEqual('proj title' in open(f).read(), expected)
            self.assertEqual('proj author' in open(f).read(), expected)
            self.assertEqual('proj identifier' in open(f).read(), expected)
            self.assertEqual('2011-05-03' in open(f).read(), expected)
            self.assertEqual('proj abstract' in open(f).read(), expected)
            self.assertEqual('kw1' in open(f).read(), expected)
            self.assertEqual('kw2' in open(f).read(), expected)

        for f in [svg_file_path, svg_file_path_2]:
            checkMetadata(f, True)

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exporttosvgdpi.png')
        svgToPng(svg_file_path, rendered_page_1, width=936)
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exporttosvgdpi2.png')
        svgToPng(svg_file_path_2, rendered_page_2, width=467)

        self.assertTrue(self.checkImage('exporttosvgdpi_page1', 'exporttopdfdpi_page1', rendered_page_1, size_tolerance=1))
        self.assertTrue(self.checkImage('exporttosvgdpi_page2', 'exporttopdfdpi_page2', rendered_page_2, size_tolerance=1))

        # no metadata
        settings.exportMetadata = False
        self.assertEqual(exporter.exportToSvg(svg_file_path, settings), QgsLayoutExporter.Success)
        for f in [svg_file_path, svg_file_path_2]:
            checkMetadata(f, False)

        # layered
        settings.exportAsLayers = True
        settings.exportMetadata = True

        svg_file_path = os.path.join(self.basetestpath, 'test_exporttosvglayered.svg')
        svg_file_path_2 = os.path.join(self.basetestpath, 'test_exporttosvglayered_2.svg')
        self.assertEqual(exporter.exportToSvg(svg_file_path, settings), QgsLayoutExporter.Success)
        self.assertTrue(os.path.exists(svg_file_path))
        self.assertTrue(os.path.exists(svg_file_path_2))

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exporttosvglayered.png')
        svgToPng(svg_file_path, rendered_page_1, width=936)
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exporttosvglayered2.png')
        svgToPng(svg_file_path_2, rendered_page_2, width=467)

        self.assertTrue(self.checkImage('exporttosvglayered_page1', 'exporttopdfdpi_page1', rendered_page_1, size_tolerance=1))
        self.assertTrue(self.checkImage('exporttosvglayered_page2', 'exporttopdfdpi_page2', rendered_page_2, size_tolerance=1))

        for f in [svg_file_path, svg_file_path_2]:
            checkMetadata(f, True)

        # layered no metadata
        settings.exportAsLayers = True
        settings.exportMetadata = False
        self.assertEqual(exporter.exportToSvg(svg_file_path, settings), QgsLayoutExporter.Success)
        for f in [svg_file_path, svg_file_path_2]:
            checkMetadata(f, False)
示例#4
0
    def testExportToPdf(self):
        md = QgsProject.instance().metadata()
        md.setTitle('proj title')
        md.setAuthor('proj author')
        md.setCreationDateTime(QDateTime(QDate(2011, 5, 3), QTime(9, 4, 5), QTimeZone(36000)))
        md.setIdentifier('proj identifier')
        md.setAbstract('proj abstract')
        md.setKeywords({'kw': ['kw1', 'kw2'], 'KWx': ['kw3', 'kw4']})
        QgsProject.instance().setMetadata(md)

        l = QgsLayout(QgsProject.instance())
        l.initializeDefaults()

        # add a second page
        page2 = QgsLayoutItemPage(l)
        page2.setPageSize('A5')
        l.pageCollection().addPage(page2)

        # add some items
        item1 = QgsLayoutItemShape(l)
        item1.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.green)
        fill.setStrokeStyle(Qt.NoPen)
        item1.setSymbol(fill_symbol)
        l.addItem(item1)

        item2 = QgsLayoutItemShape(l)
        item2.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        item2.attemptMove(QgsLayoutPoint(10, 20), page=1)
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.cyan)
        fill.setStrokeStyle(Qt.NoPen)
        item2.setSymbol(fill_symbol)
        l.addItem(item2)

        exporter = QgsLayoutExporter(l)
        # setup settings
        settings = QgsLayoutExporter.PdfExportSettings()
        settings.dpi = 80
        settings.rasterizeWholeImage = False
        settings.forceVectorOutput = False
        settings.exportMetadata = True

        pdf_file_path = os.path.join(self.basetestpath, 'test_exporttopdfdpi.pdf')
        self.assertEqual(exporter.exportToPdf(pdf_file_path, settings), QgsLayoutExporter.Success)
        self.assertTrue(os.path.exists(pdf_file_path))

        rendered_page_1 = os.path.join(self.basetestpath, 'test_exporttopdfdpi.png')
        dpi = 80
        pdfToPng(pdf_file_path, rendered_page_1, dpi=dpi, page=1)
        rendered_page_2 = os.path.join(self.basetestpath, 'test_exporttopdfdpi2.png')
        pdfToPng(pdf_file_path, rendered_page_2, dpi=dpi, page=2)

        self.assertTrue(self.checkImage('exporttopdfdpi_page1', 'exporttopdfdpi_page1', rendered_page_1, size_tolerance=1))
        self.assertTrue(self.checkImage('exporttopdfdpi_page2', 'exporttopdfdpi_page2', rendered_page_2, size_tolerance=1))

        d = gdal.Open(pdf_file_path)
        metadata = d.GetMetadata()
        self.assertEqual(metadata['AUTHOR'], 'proj author')
        self.assertEqual(metadata['CREATION_DATE'], "D:20110503090405+10'0'")
        self.assertEqual(metadata['KEYWORDS'], 'KWx: kw3,kw4;kw: kw1,kw2')
        self.assertEqual(metadata['SUBJECT'], 'proj abstract')
        self.assertEqual(metadata['TITLE'], 'proj title')
示例#5
0
    def testExportToImage(self):
        md = QgsProject.instance().metadata()
        md.setTitle('proj title')
        md.setAuthor('proj author')
        md.setCreationDateTime(QDateTime(QDate(2011, 5, 3), QTime(9, 4, 5), QTimeZone(36000)))
        md.setIdentifier('proj identifier')
        md.setAbstract('proj abstract')
        md.setKeywords({'kw': ['kw1', 'kw2'], 'KWx': ['kw3', 'kw4']})
        QgsProject.instance().setMetadata(md)
        l = QgsLayout(QgsProject.instance())
        l.initializeDefaults()

        # add a second page
        page2 = QgsLayoutItemPage(l)
        page2.setPageSize('A5')
        l.pageCollection().addPage(page2)

        # add some items
        item1 = QgsLayoutItemShape(l)
        item1.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.green)
        fill.setStrokeStyle(Qt.NoPen)
        item1.setSymbol(fill_symbol)
        l.addItem(item1)

        item2 = QgsLayoutItemShape(l)
        item2.attemptSetSceneRect(QRectF(10, 20, 100, 150))
        item2.attemptMove(QgsLayoutPoint(10, 20), page=1)
        fill = QgsSimpleFillSymbolLayer()
        fill_symbol = QgsFillSymbol()
        fill_symbol.changeSymbolLayer(0, fill)
        fill.setColor(Qt.cyan)
        fill.setStrokeStyle(Qt.NoPen)
        item2.setSymbol(fill_symbol)
        l.addItem(item2)

        exporter = QgsLayoutExporter(l)
        # setup settings
        settings = QgsLayoutExporter.ImageExportSettings()
        settings.dpi = 80

        rendered_file_path = os.path.join(self.basetestpath, 'test_exporttoimagedpi.png')
        self.assertEqual(exporter.exportToImage(rendered_file_path, settings), QgsLayoutExporter.Success)

        self.assertTrue(self.checkImage('exporttoimagedpi_page1', 'exporttoimagedpi_page1', rendered_file_path))
        page2_path = os.path.join(self.basetestpath, 'test_exporttoimagedpi_2.png')
        self.assertTrue(self.checkImage('exporttoimagedpi_page2', 'exporttoimagedpi_page2', page2_path))

        for f in (rendered_file_path, page2_path):
            d = gdal.Open(f)
            metadata = d.GetMetadata()
            self.assertEqual(metadata['Author'], 'proj author')
            self.assertEqual(metadata['Created'], '2011-05-03T09:04:05+10:00')
            self.assertEqual(metadata['Keywords'], 'KWx: kw3,kw4;kw: kw1,kw2')
            self.assertEqual(metadata['Subject'], 'proj abstract')
            self.assertEqual(metadata['Title'], 'proj title')

        # crop to contents
        settings.cropToContents = True
        settings.cropMargins = QgsMargins(10, 20, 30, 40)

        rendered_file_path = os.path.join(self.basetestpath, 'test_exporttoimagecropped.png')
        self.assertEqual(exporter.exportToImage(rendered_file_path, settings), QgsLayoutExporter.Success)

        self.assertTrue(self.checkImage('exporttoimagecropped_page1', 'exporttoimagecropped_page1', rendered_file_path))
        page2_path = os.path.join(self.basetestpath, 'test_exporttoimagecropped_2.png')
        self.assertTrue(self.checkImage('exporttoimagecropped_page2', 'exporttoimagecropped_page2', page2_path))

        # specific pages
        settings.cropToContents = False
        settings.pages = [1]

        rendered_file_path = os.path.join(self.basetestpath, 'test_exporttoimagepages.png')
        self.assertEqual(exporter.exportToImage(rendered_file_path, settings), QgsLayoutExporter.Success)

        self.assertFalse(os.path.exists(rendered_file_path))
        page2_path = os.path.join(self.basetestpath, 'test_exporttoimagepages_2.png')
        self.assertTrue(self.checkImage('exporttoimagedpi_page2', 'exporttoimagedpi_page2', page2_path))

        # image size
        settings.imageSize = QSize(600, 851)
        rendered_file_path = os.path.join(self.basetestpath, 'test_exporttoimagesize.png')
        self.assertEqual(exporter.exportToImage(rendered_file_path, settings), QgsLayoutExporter.Success)
        self.assertFalse(os.path.exists(rendered_file_path))
        page2_path = os.path.join(self.basetestpath, 'test_exporttoimagesize_2.png')
        self.assertTrue(self.checkImage('exporttoimagesize_page2', 'exporttoimagesize_page2', page2_path))

        # image size with incorrect aspect ratio
        # this can happen as a result of data defined page sizes
        settings.imageSize = QSize(851, 600)
        rendered_file_path = os.path.join(self.basetestpath, 'test_exporttoimagesizebadaspect.png')
        self.assertEqual(exporter.exportToImage(rendered_file_path, settings), QgsLayoutExporter.Success)

        page2_path = os.path.join(self.basetestpath, 'test_exporttoimagesizebadaspect_2.png')
        im = QImage(page2_path)
        self.assertTrue(self.checkImage('exporttoimagesize_badaspect', 'exporttoimagedpi_page2', page2_path), '{}x{}'.format(im.width(), im.height()))
示例#6
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
        }
示例#7
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
            }
        })