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)
def close(self): handler = self.getContentHandler() if handler: handler.endDocument() self._buffer = ""
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 ({})