예제 #1
0
    def processAlgorithm(self, parameters, context, feedback):
        self.parameters = parameters
        self.context = context
        filename = self.parameterAsFile(parameters, self.PrmInput, context)
        f, extension = os.path.splitext(filename)
        extension = extension.lower()
        try:
            if extension == '.kmz':
                kmz = ZipFile(filename, 'r')
                kml = kmz.open('doc.kml', 'r')
            elif extension == '.kml':
                kml = open(filename,
                           encoding="utf-8",
                           errors="backslashreplace")
            else:
                msg = "Invalid extension: Should be kml or kmz"
                feedback.reportError(msg)
                raise QgsProcessingException(msg)
        except:
            msg = "Failed to open file"
            feedback.reportError(msg)
            raise QgsProcessingException(msg)

        skipPt = True if self.PrmPointOutputLayer not in parameters or parameters[
            self.PrmPointOutputLayer] is None else False
        skipline = True if self.PrmLineOutputLayer not in parameters or parameters[
            self.PrmLineOutputLayer] is None else False
        skipPoly = True if self.PrmPolygonOutputLayer not in parameters or parameters[
            self.PrmPolygonOutputLayer] is None else False
        self.cntPt = 0
        self.cntLine = 0
        self.cntPoly = 0
        parser = xml.sax.make_parser()
        # Do a pre-pass through the KML to see if there are any extended data fields
        preprocess = PreProcessHandler()
        parser.setContentHandler(preprocess)
        try:
            input_source = xml.sax.xmlreader.InputSource()
            input_source.setByteStream(kml)
            input_source.setEncoding('utf-8')
            parser.parse(input_source)
        except:
            preprocess.endDocument()
        # Reset the KML/KMZ file to the beginning. The handler seems to automatically close the file
        # which is why we are reopening it.
        if extension == '.kmz':
            kmz.close()
        else:
            kml.close()
        if extension == '.kmz':
            kmz = ZipFile(filename, 'r')
            kml = kmz.open('doc.kml', 'r')
        else:
            kml = open(filename, encoding="utf-8", errors="backslashreplace")

        # Set up the handler for doing the main processing
        self.extData = preprocess.getExtendedDataFields()
        self.extData.sort()
        self.extDataMap = {}
        index = 0
        for item in self.extData:
            self.extDataMap[item] = index
            index += 1
        handler = PlacemarkHandler(skipPt, skipline, skipPoly, self.extDataMap,
                                   feedback)
        handler.addpoint.connect(self.addpoint)
        handler.addline.connect(self.addline)
        handler.addpolygon.connect(self.addpolygon)
        parser.setContentHandler(handler)
        try:
            input_source = xml.sax.xmlreader.InputSource()
            input_source.setByteStream(kml)
            input_source.setEncoding('utf-8')
            parser.parse(input_source)
        except:
            '''s = traceback.format_exc()
            feedback.pushInfo(s)'''
            feedback.pushInfo(
                tr('Failure in kml extraction - May return partial results.'))
            handler.endDocument()

        if extension == '.kmz':
            kmz.close()
        else:
            kml.close()

        feedback.pushInfo('{} points extracted'.format(self.cntPt))
        feedback.pushInfo('{} lines extracted'.format(self.cntLine))
        feedback.pushInfo('{} polygons extracted'.format(self.cntPoly))

        r = {}
        if self.cntPt > 0:
            r[self.PrmPointOutputLayer] = self.dest_id_pt
        if self.cntLine > 0:
            r[self.PrmLineOutputLayer] = self.dest_id_line
        if self.cntPoly > 0:
            r[self.PrmPolygonOutputLayer] = self.dest_id_poly

        return (r)
예제 #2
0
 def close(self):
     handler = self.getContentHandler()
     if handler:
         handler.endDocument()
     self._buffer = ""
예제 #3
0
 def close(self):
     handler = self.getContentHandler()
     if handler:
         handler.endDocument()
     self._buffer = ""
예제 #4
0
    def processAlgorithm(self, parameters, context, feedback):
        self.parameters = parameters
        self.context = context
        self.feedback = feedback
        load_geotiffs = self.parameterAsInt(parameters, self.PrmLoadGeoTiffs,
                                            context)
        out_folder = self.parameterAsFile(parameters,
                                          self.PrmGroundOverlayFolder, context)
        input_file = self.parameterAsFile(parameters, self.PrmInput, context)
        f, extension = os.path.splitext(input_file)
        dirname = os.path.dirname(input_file)
        extension = extension.lower()
        try:
            if extension == '.kmz':
                kmz = ZipFile(input_file, 'r')
                kml = kmz.open('doc.kml', 'r')
            elif extension == '.kml':
                kml = open(input_file,
                           encoding="utf-8",
                           errors="backslashreplace")
            else:
                msg = "Invalid extension: Should be kml or kmz"
                raise QgsProcessingException(msg)
        except Exception:
            msg = "Failed to open file"
            raise QgsProcessingException(msg)

        parser = xml.sax.make_parser()

        self.overlays = []
        # Set up the handler for doing the main processing
        handler = GroundOverlayHandler(feedback)
        handler.groundoverlay.connect(self.groundoverlay)
        parser.setContentHandler(handler)
        try:
            input_source = xml.sax.xmlreader.InputSource()
            input_source.setByteStream(kml)
            input_source.setEncoding('utf-8')
            parser.parse(input_source)
        except Exception:
            '''s = traceback.format_exc()
            feedback.pushInfo(s)'''
            feedback.reportError(
                tr('Failure in kml extraction - May return partial results.'))
            handler.endDocument()

        # Iterate through each found overlay images
        for overlay in self.overlays:
            north = overlay[0]
            south = overlay[1]
            east = overlay[2]
            west = overlay[3]
            rotation = overlay[4]
            href = overlay[5]
            if href.startswith('http:') or href.startswith('https:'):
                feedback.reportError(
                    'Cannot process network images: {}'.format(href))
                continue
            if extension == '.kmz':
                try:
                    image = kmz.read(href)
                    output_file = os.path.basename(href)
                    file_name, ext = os.path.splitext(output_file)
                    # Write out a temporary image
                    temp_file_name = os.path.join(
                        out_folder, '{}_temp{}'.format(file_name, ext))
                    fp = open(temp_file_name, "wb")
                    fp.write(image)
                    fp.close()
                    raster = QgsRasterLayer(temp_file_name, "temp")
                except Exception:
                    feedback.reportError(
                        'Image does not exist: {}'.format(href))
                    continue
            else:
                # Check to see if it is a valid file name
                in_path = os.path.join(dirname, href)
                if not os.path.isfile(in_path):
                    # The path was not valid
                    feedback.reportError(
                        'Image file does not exist: {}'.format(in_path))
                    continue
                raster = QgsRasterLayer(in_path, "temp")
                output_file = os.path.basename(in_path)
                file_name, ext = os.path.splitext(output_file)
            if not raster.isValid():
                feedback.reportError('Invalid raster image: {}'.format(href))
                continue
            out_path = os.path.join(out_folder, file_name + ".tif")
            if rotation == 0:
                status = processing.run(
                    "gdal:translate", {
                        'INPUT':
                        raster,
                        'EXTRA':
                        '-a_srs EPSG:4326 -a_ullr {} {} {} {}'.format(
                            west, north, east, south),
                        'DATA_TYPE':
                        0,
                        'OUTPUT':
                        out_path
                    })
            else:
                rwidth = raster.width()
                rheight = raster.height()
                center_x = (east + west) / 2.0
                center_y = (north + south) / 2.0
                center_pt = QgsPointXY(center_x, center_y)
                ul_pt = QgsPointXY(west, north)
                ur_pt = QgsPointXY(east, north)
                lr_pt = QgsPointXY(east, south)
                ll_pt = QgsPointXY(west, south)
                distance = center_pt.distance(ul_pt)
                az = center_pt.azimuth(ul_pt) - rotation
                pt1 = center_pt.project(distance, az)
                az = center_pt.azimuth(ur_pt) - rotation
                pt2 = center_pt.project(distance, az)
                az = center_pt.azimuth(lr_pt) - rotation
                pt3 = center_pt.project(distance, az)
                az = center_pt.azimuth(ll_pt) - rotation
                pt4 = center_pt.project(distance, az)
                gcp1 = '-gcp {} {} {} {}'.format(0, 0, pt1.x(), pt1.y())
                gcp2 = '-gcp {} {} {} {}'.format(rwidth, 0, pt2.x(), pt2.y())
                gcp3 = '-gcp {} {} {} {}'.format(rwidth, rheight, pt3.x(),
                                                 pt3.y())
                gcp4 = '-gcp {} {} {} {}'.format(0, rheight, pt4.x(), pt4.y())

                status = processing.run(
                    "gdal:translate", {
                        'INPUT':
                        raster,
                        'EXTRA':
                        '-a_srs EPSG:4326 -a_nodata 0,0,0 {} {} {} {}'.format(
                            gcp1, gcp2, gcp3, gcp4),
                        'DATA_TYPE':
                        0,
                        'OUTPUT':
                        out_path
                    })
            if load_geotiffs:
                context.addLayerToLoadOnCompletion(
                    out_path,
                    context.LayerDetails(file_name, project=context.project()))

            del raster
            if extension == '.kmz':
                try:
                    os.remove(temp_file_name)
                    os.remove(temp_file_name + '.aux.xml')
                except Exception:
                    pass

        if extension == '.kmz':
            kmz.close()
        else:
            kml.close()

        # self.feedback.pushInfo('Number of overlays: {}'.format(len(self.overlays)))

        return ({})