Example #1
0
 def update_ee_image_layers(self):
     layers = QgsProject.instance().mapLayers().values()
     for eelayer in filter(
             lambda layer: layer.customProperty('ee-image') == 'XML',
             layers):
         extent = eelayer.customProperty('ee-image-wkt')
         bb = QgsRectangle.fromWkt(extent)
         eelayer.setExtent(bb)
         xml_file = eelayer.dataProvider().dataSourceUri()
         # ds = gdal.Open(xml_file)
         # if ds.ReadAsArray(xsize=1, ysize=1) is None:
         imageid = eelayer.customProperty('ee-image-id')
         bands = eelayer.customProperty('ee-image-bands')
         qml = eelayer.customProperty('ee-image-qml')
         palette = eelayer.customProperty('ee-image-palette')
         if not qml:
             b_min = list(map(int,
                              eelayer.customProperty('ee-image-b_min')))
             b_max = list(map(int,
                              eelayer.customProperty('ee-image-b_max')))
         else:
             b_min = None
             b_max = None
         if self.ee_uninitialized:
             ee.Initialize()
         new_tms = update_ee_image_layer(imageid, bands, b_min, b_max,
                                         palette)
         replace_tms(xml_file, new_tms)
Example #2
0
    def gee_layer_make_xml(self):
        eelayer = self.iface.activeLayer()
        dest_dir = QgsProject.instance().absolutePath() or os.getcwd()
        dest_name = eelayer.name().replace('/', '_') + '.xml'
        dest_file = os.path.join(dest_dir, dest_name)
        source_xml = eelayer.dataProvider().dataSourceUri()
        dest_xml, _ = QFileDialog.getSaveFileName(self.dlg,
                                                  'Select output file',
                                                  dest_file,
                                                  'XML files (*.xml)')
        if dest_xml:
            shutil.copyfile(source_xml, dest_xml)
            newname = os.path.splitext(os.path.basename(dest_xml))[0]
            newlayer = QgsRasterLayer(dest_xml, newname)

            if newlayer.isValid():
                imageid = eelayer.customProperty('ee-image-id')
                date = eelayer.customProperty('ee-image-date')
                qml = eelayer.customProperty('ee-image-qml')
                extent = eelayer.customProperty('ee-image-wkt')
                # load qml must be first since this clean all custom properties
                if qml is not None:
                    if isfile(qml + '_' +
                              QSettings().value('locale/userLocale') + '.qml'):
                        newlayer.loadNamedStyle(
                            qml + '_' +
                            QSettings().value('locale/userLocale') + '.qml')
                    else:
                        newlayer.loadNamedStyle(qml + '.qml')
                newlayer.setCustomProperty('ee-image', 'XML')
                newlayer.setCustomProperty('ee-image-id', imageid)
                newlayer.setCustomProperty('ee-image-date', date)
                newlayer.setCustomProperty(
                    'ee-image-bands', eelayer.customProperty('ee-image-bands'))
                newlayer.setCustomProperty(
                    'ee-image-scale', eelayer.customProperty('ee-image-scale'))
                newlayer.setCustomProperty(
                    'ee-image-b_min', eelayer.customProperty('ee-image-b_min'))
                newlayer.setCustomProperty(
                    'ee-image-b_max', eelayer.customProperty('ee-image-b_max'))
                newlayer.setCustomProperty(
                    'ee-image-palette',
                    eelayer.customProperty('ee-image-palette'))
                newlayer.setCustomProperty('ee-image-qml', qml)
                newlayer.setCustomProperty('ee-image-wkt', extent)
                if date is not None:
                    newlayer.setAbstract(
                        f"ee.Image('{imageid}') \n\nDate: {date}")
                else:
                    newlayer.setAbstract(f"ee.Image('{imageid}')")
                bb = QgsRectangle.fromWkt(extent)
                newlayer.setExtent(bb)
                QgsProject.instance().addMapLayer(newlayer)
                QgsProject.instance().layerTreeRoot().findLayer(
                    newlayer.id()).setItemVisibilityChecked(False)
Example #3
0
 def update_ee_image_layer(self, eelayer):
     extent = eelayer.customProperty('ee-image-wkt')
     bb = QgsRectangle.fromWkt(extent)
     eelayer.setExtent(bb)
     xml_file = eelayer.dataProvider().dataSourceUri()
     # ds = gdal.Open(xml_file)
     # if ds.ReadAsArray(xsize=1, ysize=1) is None:
     imageid = eelayer.customProperty('ee-image-id')
     bands = eelayer.customProperty('ee-image-bands')
     qml = eelayer.customProperty('ee-image-qml')
     palette = eelayer.customProperty('ee-image-palette')
     if not qml:
         b_min = list(map(int, eelayer.customProperty('ee-image-b_min')))
         b_max = list(map(int, eelayer.customProperty('ee-image-b_max')))
     else:
         b_min = None
         b_max = None
     if self.ee_uninitialized:
         ee.Initialize()
     new_xml = update_ee_image_xml(imageid, bands, b_min, b_max, palette)
     write_xmlfile(new_xml, name=None, dest=xml_file)
     eelayer.dataProvider().reloadData()
     eelayer.triggerRepaint()
     eelayer.reload()
Example #4
0
    def result(self, result):
        # See if OK was pressed
        if result:
            project = QgsProject.instance()
            # First get all the values of the GUI items
            crs_input = self.dlg.crs_input.crs()
            crs_out = QgsCoordinateReferenceSystem(
                'EPSG:4326')  # we need this to be WGS84 for Nominatim
            lineedit_text = self.dlg.lineedit_xy.value()

            # Protect the free text field for coordinates from generic user failure
            try:
                lineedit_yx = [
                    float(coord.strip()) for coord in lineedit_text.split(',')
                ]
            except:
                QMessageBox.critical(
                    self.iface.mainWindow(), 'QuickAPI error',
                    "Did you really specify a coordinate in comma-separated Lat/Long?\nExiting..."
                )
                return

            # Create a Point and transform if necessary
            point = QgsPointXY(*reversed(lineedit_yx))
            if crs_input.authid() != 'EPSG:4326':
                xform = QgsCoordinateTransform(crs_input, crs_out, project)
                point_transform = xform.transform(point)
                point = point_transform

            # Set up the GET Request to Nominatim
            query = QUrlQuery()
            query.addQueryItem('lat', str(point.y()))
            query.addQueryItem('lon', str(point.x()))
            query.addQueryItem('format', 'json')

            url = QUrl('https://nominatim.openstreetmap.org/reverse')
            url.setQuery(query)

            request = QNetworkRequest(url)
            request.setHeader(QNetworkRequest.UserAgentHeader,
                              '*****@*****.**')

            nam = QgsNetworkAccessManager()
            response: QgsNetworkReplyContent = nam.blockingGet(request)

            # Only process if HTTP status code is 200
            status_code = response.attribute(
                QNetworkRequest.HttpStatusCodeAttribute)
            if status_code == 200:
                # Get the content of the response and process it
                response_json = json.loads(bytes(response.content()))
                if response_json.get('error'):
                    QMessageBox.critical(
                        self.iface.mainWindow(), "Quick API error",
                        "The request was not processed succesfully!\n\n"
                        "Message:\n"
                        "{}".format(response_json['error']))
                    return

                x = float(response_json['lon'])
                y = float(response_json['lat'])
                address = response_json['display_name']
                license = response_json['licence']

                # Create the output memory layer
                layer_out = QgsVectorLayer(
                    "Point?crs=EPSG:4326&field=address:string&field=license:string",
                    "Nominatim Reverse Geocoding", "memory")

                # Create the output feature (only one here)
                point_out = QgsPointXY(x, y)
                feature = QgsFeature()
                feature.setGeometry(QgsGeometry.fromPointXY(point_out))
                feature.setAttributes([address, license])

                # Add feature to layer and layer to map
                layer_out.dataProvider().addFeature(feature)
                layer_out.updateExtents()
                project.addMapLayer(layer_out)

                # build bbox for auto-zoom feature
                bbox = [float(coord) for coord in response_json['boundingbox']]
                min_y, max_y, min_x, max_x = bbox
                bbox_geom = QgsGeometry.fromRect(
                    QgsRectangle(min_x, min_y, max_x, max_y))

                # Transform bbox if map canvas has a different CRS
                if project.crs().authid() != 'EPSG:4326':
                    xform = QgsCoordinateTransform(crs_out, project.crs(),
                                                   project)
                    bbox_geom.transform(xform)

                self.iface.mapCanvas().zoomToFeatureExtent(
                    QgsRectangle.fromWkt(bbox_geom.asWkt()))
 def from_dict(dict_data: dict):
     return LocationResult(
         QgsGeometry.fromWkt(dict_data['point']).asPoint(),
         QgsRectangle.fromWkt(dict_data['bbox']), dict_data['layer'],
         dict_data['feature_id'], dict_data['html_label'])
Example #6
0
def add_ee_image_layer(imageid, name, date, bands, scale, b_min=None, b_max=None, palette=None, qml=None, extent=None,
                       shown=False, destination=None):
    nbands = len(bands)
    # if nbands > 3:
    #     rgb = ee.Image(imageid).select(bands[0:3])
    #     pan = ee.Image(imageid).select(bands[3])
    #     huesat = rgb.rgbToHsv().select('hue', 'saturation')
    #     image = ee.Image.cat(huesat, pan).hsvToRgb().select([0, 1, 2], bands[0:3])
    #     nbands = 3
    # else:
    image = ee.Image(imageid)
    if not any([b_min, b_max, palette, qml]):
        image_stats = image.select(bands[0:nbands]).reduceRegion(ee.Reducer.minMax(), None, scale, None, None, False, 1.0E13).getInfo()
        b_min = [image_stats[bands[n] + '_min'] for n in range(nbands)]
        b_max = [image_stats[bands[n] + '_max'] for n in range(nbands)]
        # b_min = [image_stats[bands[0] + '_min'], image_stats[bands[1] + '_min'], image_stats[bands[2] + '_min']]
        # b_max = [image_stats[bands[0] + '_max'], image_stats[bands[1] + '_max'], image_stats[bands[2] + '_max']]
    rgb = image.visualize(bands=bands[0:nbands], min=b_min, max=b_max, palette=palette)
    tms = get_ee_image_tms(rgb)
    if extent is None:
        image_geojson = get_ee_image_bb(rgb)
        extent = geojson_to_wkt(image_geojson)
    bb = QgsRectangle.fromWkt(extent)
    url = tms_to_gdalurl(tms)
    xml = get_gdal_xml(url, nbands=nbands+1)
    # vfn = write_vsimem_xml(xml) # changed to named temporary file
    tmp, fn = write_xmlfile(xml, name, dest=destination)
    layer = QgsRasterLayer(fn, name)
    if layer.isValid():
        if qml is not None:
            if isfile(qml + '_' + QSettings().value('locale/userLocale') + '.qml'):
                layer.loadNamedStyle(qml + '_' + QSettings().value('locale/userLocale') + '.qml')
            else:
                layer.loadNamedStyle(qml + '.qml')
        layer.setExtent(bb)
        if tmp:
            layer.setCustomProperty('ee-image', 'MEM')
        else:
            layer.setCustomProperty('ee-image', 'XML')
        layer.setCustomProperty('ee-image-id', imageid)
        layer.setCustomProperty('ee-image-date', date)
        layer.setCustomProperty('ee-image-bands', bands)
        layer.setCustomProperty('ee-image-scale', scale)
        layer.setCustomProperty('ee-image-b_min', b_min)
        layer.setCustomProperty('ee-image-b_max', b_max)
        layer.setCustomProperty('ee-image-palette', palette)
        layer.setCustomProperty('ee-image-qml', qml)
        layer.setCustomProperty('ee-image-wkt', extent)
        # else:
        #     layer.setAbstract(f"ee.Image('{imageid}')")
        # if len(bands) < 4:
        #     try:
        #         layer.setCustomProperty('ee-image-stats', image_stats)
        #     except NameError:
        #         pass
        if date is not None:
            layer.setAbstract(f"ee.Image('{imageid}') \n\nDate: {date}")
        else:
            layer.setAbstract(f"ee.Image('{imageid}')")
        QgsProject.instance().addMapLayer(layer)
        if not shown:
            QgsProject.instance().layerTreeRoot().findLayer(layer.id()).setItemVisibilityChecked(shown)
Example #7
0
    def result(self, result):
        if result:

            # save a project reference
            project = QgsProject.instance()

            # Save the user input
            lineedit_text = self.dlg.lineedit_xy.value()
            crs_input = self.dlg.crs_input.crs()

            crs_out = QgsCoordinateReferenceSystem(
                4326)  # we need this to be WGS84 for Nominatim

            # Protect the free text field for coordinates from generic user failure:)
            try:
                lineedit_yx = [
                    float(coord.strip()) for coord in lineedit_text.split(',')
                ]
            except:
                QMessageBox.critical(
                    self.iface.mainWindow(), 'QuickAPI error',
                    "Did you really specify a coordinate in comma-separated Lat/Long?\nExiting..."
                )
                return

            # Create a Point and transform if necessary
            point = QgsPointXY(*reversed(lineedit_yx))

            if crs_input.authid() != 'EPSG:4326':
                xform = QgsCoordinateTransform(crs_input, crs_out, project)
                point_transform = xform.transform(point)
                point = point_transform

            # Set up and fire Nominatim GET request
            user_agent = '*****@*****.**'
            base_url = 'https://nominatim.openstreetmap.org/reverse'
            params = {'lat': point.y(), 'lon': point.x(), 'format': 'json'}

            response = requests.get(url=base_url,
                                    params=params,
                                    headers={'User-Agent': user_agent})
            response_json = response.json()

            # Only process response if HTTP 200
            if response.status_code == 200:
                # Unfortunately Nominatim goes against protocol and responds with 200 even if an error occurred
                if response_json.get('error'):
                    QMessageBox.critical(
                        self.iface.mainWindow(), "Quick API error",
                        "The request was not processed succesfully!\n\n"
                        "Message:\n"
                        "{}".format(response.json()))
                    return

                # Capture relevant response fields
                x = float(response_json['lon'])
                y = float(response_json['lat'])
                address = response_json['display_name']
                license = response_json['licence']

                # Create the output memory layer
                layer_out = QgsVectorLayer(
                    "Point?crs=EPSG:4326&field=address:string&field=license:string",
                    "Nominatim Reverse Geocoding", "memory")

                # Create the output feature (only one here)
                point_out = QgsPointXY(x, y)
                feature = QgsFeature()
                feature.setGeometry(QgsGeometry.fromPointXY(point_out))
                feature.setAttributes([address, license])

                # Add feature to layer and layer to map
                layer_out.dataProvider().addFeature(feature)
                layer_out.updateExtents()
                project.addMapLayer(layer_out)

                # build bbox for auto-zoom feature
                bbox = [float(coord) for coord in response_json['boundingbox']]
                min_y, max_y, min_x, max_x = bbox
                bbox_geom = QgsGeometry.fromPolygonXY([[
                    QgsPointXY(min_x, min_y),
                    QgsPointXY(min_x, max_y),
                    QgsPointXY(max_x, max_y),
                    QgsPointXY(max_x, min_y),
                ]])

                # Transform bbox if map canvas has a different CRS
                if project.crs().authid() != 'EPSG:4326':
                    xform = QgsCoordinateTransform(crs_out, project.crs(),
                                                   project)
                    bbox_geom.transform(xform)

                self.iface.mapCanvas().zoomToFeatureExtent(
                    QgsRectangle.fromWkt(bbox_geom.asWkt()))