def processAlgorithm(self, parameters, context, feedback): raster = self.parameterAsRasterLayer(parameters, self.PrmInput, context) out_path = self.parameterAsOutputLayer(parameters, self.PrmOutputRaster, context) north = self.parameterAsDouble(parameters, self.PrmNorthLatitude, context) south = self.parameterAsDouble(parameters, self.PrmSouthLatitude, context) east = self.parameterAsDouble(parameters, self.PrmEastLongitude, context) west = self.parameterAsDouble(parameters, self.PrmWestLongitude, context) rotation = self.parameterAsDouble(parameters, self.PrmRotation, context) 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}) feedback.pushInfo('{}'.format(status)) results = {} results[self.PrmOutputRaster] = out_path return (results)
def theMaker(self, aDict, alayer): feats = [] for i in range(0, len(aDict) - 1): frwrd = QgsPointXY(aDict[i][1]) # start point rvrs = QgsPointXY(aDict[i + 1][1]) # second point az = frwrd.azimuth(rvrs) distance = math.sqrt(frwrd.sqrDist(rvrs)) c = Calculus.getSemiMajorAndSemiMinorAxis(self, alayer) a = Calculus.getGeographicCoordinates(self, alayer, rvrs.x(), rvrs.y()) conv = Calculus.calculateConvergence(self, a.x(), a.y(), c[0], c[1]) if az < 0: az += 360 azm = az + conv longitude = Calculus.dd2dms( self, Calculus.getGeographicCoordinates(self, alayer, aDict[i][1].x(), aDict[i][1].y()).x()) latitude = Calculus.dd2dms( self, Calculus.getGeographicCoordinates(self, alayer, aDict[i][1].x(), aDict[i][1].y()).y()) fet = QgsFeature() geom = QgsGeometry().fromPointXY(aDict[0][1]) fet.setGeometry(geom) feats.append(fet) fet.setAttributes([ list(aDict.keys())[i], aDict[i][0], aDict[i][1].x(), aDict[i][1].y(), longitude, latitude, aDict[i + 1][0], Calculus.dd2dms(self, azm), distance ]) return feats
def testMeasureLineProjected(self): # +-+ # | | # +-+ + # test setting/getting the source CRS da_3068 = QgsDistanceArea() da_wsg84 = QgsDistanceArea() da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'), QgsProject.instance().transformContext()) if (da_3068.sourceCrs().isGeographic()): da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym()) print(("setting [{}] srid [{}] description [{}]".format(u'Soldner Berlin', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description()))) self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068') da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'), QgsProject.instance().transformContext()) if (da_wsg84.sourceCrs().isGeographic()): da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326') print(("setting [{}] srid [{}] description [{}] isGeographic[{}]".format(u'Wsg84', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic()))) # print(("-- projectionAcronym[{}] ellipsoidAcronym[{}] toWkt[{}] mapUnits[{}] toProj4[{}]".format(da_wsg84.sourceCrs().projectionAcronym(),da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.sourceCrs().toWkt(),da_wsg84.sourceCrs().mapUnits(),da_wsg84.sourceCrs().toProj4()))) print(("Testing Position change for[{}] years[{}]".format(u'Ampelanlage - Potsdamer Platz, Verkehrsinsel', u'1924 and 1998'))) # 1924-10-24 SRID=3068;POINT(23099.49 20296.69) # 1924-10-24 SRID=4326;POINT(13.37650707988041 52.50952361017194) # 1998-10-02 SRID=3068;POINT(23082.30 20267.80) # 1998-10-02 SRID=4326;POINT(13.37625537334001 52.50926345498337) # values returned by SpatiaLite point_soldner_1924 = QgsPointXY(23099.49, 20296.69) point_soldner_1998 = QgsPointXY(23082.30, 20267.80) distance_soldner_meters = 33.617379 azimuth_soldner_1924 = 3.678339 # ST_Transform(point_soldner_1924,point_soldner_1998,4326) point_wsg84_1924 = QgsPointXY(13.37650707988041, 52.50952361017194) point_wsg84_1998 = QgsPointXY(13.37625537334001, 52.50926345498337) # ST_Distance(point_wsg84_1924,point_wsg84_1998,1) distance_wsg84_meters = 33.617302 # ST_Distance(point_wsg84_1924,point_wsg84_1998) # distance_wsg84_mapunits=0.000362 distance_wsg84_mapunits_format = QgsDistanceArea.formatDistance(0.000362, 7, QgsUnitTypes.DistanceDegrees, True) # ST_Azimuth(point_wsg84_1924,point_wsg84_1998) azimuth_wsg84_1924 = 3.674878 # ST_Azimuth(point_wsg84_1998,point_wsg84_1998) azimuth_wsg84_1998 = 0.533282 # ST_Project(point_wsg84_1924,33.617302,3.674878) # SRID=4326;POINT(13.37625537318728 52.50926345503591) point_soldner_1998_project = QgsPointXY(13.37625537318728, 52.50926345503591) # ST_Project(point_wsg84_1998,33.617302,0.533282) # SRID=4326;POINT(13.37650708009255 52.50952361009799) point_soldner_1924_project = QgsPointXY(13.37650708009255, 52.50952361009799) distance_qpoint = point_soldner_1924.distance(point_soldner_1998) azimuth_qpoint = point_soldner_1924.azimuth(point_soldner_1998) point_soldner_1998_result = point_soldner_1924.project(distance_qpoint, azimuth_qpoint) point_soldner_1924_result = QgsPointXY(0, 0) point_soldner_1998_result = QgsPointXY(0, 0) # Test meter based projected point from point_1924 to point_1998 length_1998_mapunits, point_soldner_1998_result = da_3068.measureLineProjected(point_soldner_1924, distance_soldner_meters, azimuth_qpoint) self.assertEqual(point_soldner_1998_result.toString(6), point_soldner_1998.toString(6)) # Test degree based projected point from point_1924 1 meter due East point_wsg84_meter_result = QgsPointXY(0, 0) point_wsg84_1927_meter = QgsPointXY(13.37652180838435, 52.50952361017102) length_meter_mapunits, point_wsg84_meter_result = da_wsg84.measureLineProjected(point_wsg84_1924, 1.0, (math.pi / 2)) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, QgsUnitTypes.DistanceDegrees, True), '0.0000147 deg') self.assertEqual(point_wsg84_meter_result.toString(7), point_wsg84_1927_meter.toString(7)) point_wsg84_1998_result = QgsPointXY(0, 0) length_1928_mapunits, point_wsg84_1998_result = da_wsg84.measureLineProjected(point_wsg84_1924, distance_wsg84_meters, azimuth_wsg84_1924) self.assertEqual(QgsDistanceArea.formatDistance(length_1928_mapunits, 7, QgsUnitTypes.DistanceDegrees, True), distance_wsg84_mapunits_format) self.assertEqual(point_wsg84_1998_result.toString(7), point_wsg84_1998.toString(7))
class GPSMarker(QgsMapCanvasItem): def __init__(self, canvas): super(GPSMarker, self).__init__(canvas) self.canvas = canvas self._quaility = 0 self._heading = 0 self.size = roam.config.settings.get('gps', {}).get('marker_size', 24) self.red = Qt.darkRed self.blue = QColor(129, 173, 210) self.green = Qt.darkGreen self._gpsinfo = QgsGpsInformation() self.pointbrush = QBrush(self.red) self.pointpen = QPen(Qt.black) self.pointpen.setWidth(1) self.map_pos = QgsPoint(0.0, 0.0) self.gps = None def setgps(self, gps): self.gps = gps def setSize(self, size): self.size = size def paint(self, painter, xxx, xxx2): self.setPos(self.toCanvasCoordinates(self.map_pos)) halfSize = self.size / 2.0 rect = QRectF(0 - halfSize, 0 - halfSize, self.size, self.size) painter.setRenderHint(QPainter.Antialiasing) if self.quality == 0: color = self.red elif self.quality == 1: color = self.green elif self.quality >= 2: color = self.blue else: color = self.red self.pointpen.setColor(Qt.gray) self.pointpen.setWidth(2) self.pointbrush.setColor(color) painter.setBrush(self.pointbrush) painter.setPen(self.pointpen) y = 0 - halfSize x = rect.width() / 2 - halfSize line = QLine(x, y, x, rect.height() - halfSize) y = rect.height() / 2 - halfSize x = 0 - halfSize line2 = QLine(x, y, rect.width() - halfSize, y) # Arrow p = QPolygonF() p.append(QPoint(0 - halfSize, 0)) p.append(QPoint(0, -self.size)) x = rect.width() - halfSize p.append(QPoint(x, 0)) p.append(QPoint(0, 0)) offsetp = QPolygonF() offsetp.append(QPoint(0 - halfSize, 0)) offsetp.append(QPoint(0, -self.size)) x = rect.width() - halfSize offsetp.append(QPoint(x, 0)) offsetp.append(QPoint(0, 0)) waypoint = self.gps.waypoint if waypoint: az = self.map_pos.azimuth(waypoint) painter.save() painter.rotate(az) self.pointbrush.setColor(Qt.red) painter.setBrush(self.pointbrush) path = QPainterPath() path.addPolygon(offsetp) painter.drawPath(path) painter.restore() painter.save() painter.rotate(self._heading) path = QPainterPath() path.addPolygon(p) painter.drawPath(path) painter.restore() painter.drawEllipse(rect) painter.drawLine(line) painter.drawLine(line2) def boundingRect(self): halfSize = self.size / 2.0 size = self.size * 2 return QRectF(-size, -size, 2.0 * size, 2.0 * size) @property def quality(self): return self._gpsinfo.quality @quality.setter def quality(self, value): self._quaility = value self.update() def setCenter(self, map_pos, gpsinfo): self._heading = gpsinfo.direction self._gpsinfo = gpsinfo self.map_pos = QgsPointXY(map_pos) self.setPos(self.toCanvasCoordinates(self.map_pos)) def updatePosition(self): self.setCenter(self.map_pos, self._gpsinfo)
class MapTool(QgsMapTool): MODE_NONE = 0 MODE_PAN = 1 MODE_ROTATE = 2 MODE_SCALE = 3 MODE_SCALE_X = 4 MODE_SCALE_Y = 5 MODE_PAN_RESULT = 6 MODE_NODE = 7 NODE_NAMES = ['A', 'B', 'C', 'D'] def __init__(self, widget): QgsMapTool.__init__(self, widget.canvas) self.widget = widget self.canvas = widget.canvas self.mode = self.MODE_NONE self.selected_node = None # clicked point self.p0 = None # centre rectangle self.pX = None # rectangle vertices (handles) self.pA = None # hg self.pB = None # hd self.pC = None # bd self.pD = None # bg self.zoneWidth = None self.zoneDepth = None # eye (rotation) self.pY = None # rectangle self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setStrokeColor(Qt.blue) self.rb.setWidth(3) self.rbFoc = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rbFoc.setStrokeColor(Qt.blue) self.rbFoc.setWidth(1) # SCALE nodes self.rbPA = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPA.setColor(Qt.red) self.rbPA.setWidth(8) self.rbPB = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPB.setColor(Qt.red) self.rbPB.setWidth(8) self.rbPC = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPC.setColor(Qt.red) self.rbPC.setWidth(8) self.rbPD = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPD.setColor(QColor(255, 50, 150, 255)) self.rbPD.setWidth(8) # scale Y node self.rbPH = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPH.setColor(Qt.red) self.rbPH.setWidth(8) # scale X node self.rbPL = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPL.setColor(Qt.red) self.rbPL.setWidth(8) # final pan self.rbPan = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPan.setColor(QColor(0, 200, 50, 255)) self.rbPan.setWidth(8) # ROTATE node self.rbPY = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.rbPY.setColor(Qt.blue) self.rbPY.setWidth(6) self.rotation = 0.0 # cutting lines self.rbLines = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rbLines.setColor(QColor(40, 180, 30, 255)) self.rbLines.setWidth(1.5) # plots self.rbPlots = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rbPlots.setStrokeColor(QColor(200, 120, 70, 150)) self.rbPlots.setWidth(0.8) self.rubbers = [ self.rb, self.rbPA, self.rbPB, self.rbPC, self.rbPD, self.rbPY, self.rbPH, self.rbPL, self.rbPan, self.rbLines, self.rbPlots, self.rbFoc, ] self.rowLines = None self.columnLines = None self.allLines = None def hide(self): for rb in self.rubbers: rb.reset() def updateRubberGeom(self): if self.pA is None: return self.zoneWidth = self.pA.distance(self.pB) self.zoneDepth = self.pA.distance(self.pD) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.d0 = self.pM.distance(self.pY) # self.widget.updateZ(self.pY) self.rb.setToGeometry( QgsGeometry.fromPolygonXY( [[self.pD, self.pA, self.pB, self.pC, self.pD]])) self.rbFoc.setToGeometry( QgsGeometry.fromPolylineXY([self.pD, self.pY, self.pC])) for p, rb in [ [self.pA, self.rbPA], [self.pB, self.rbPB], [self.pC, self.rbPC], [self.pD, self.rbPD], [self.pY, self.rbPY], [self.pH, self.rbPH], [self.pL, self.rbPL], ]: rb.setToGeometry(QgsGeometry.fromPointXY(p)) leftEdge = (QgsGeometry.fromPolylineXY([ self.pA, self.pD ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.pB, self.pC ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) # Plot edges lines polyline = list(zip(leftEdge, rightEdge)) backSide = (QgsGeometry.fromPolylineXY([ self.pA, self.pB ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.pD, self.pC ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) polylineX = list(zip(frontSide[:], backSide[:])) self.finalWidth = self.zoneWidth self.rowLines = polyline self.columnLines = polylineX self.allLines = polyline + polylineX self.rbLines.setToGeometry( QgsGeometry.fromMultiPolylineXY( polylineX + polyline + polyline[::max(1, 1 + len(polyline))])) if self.widget.cbReverseRows.isChecked(): if self.widget.cbReverseColumns.isChecked(): self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPA.setColor(Qt.red) self.rbPB.setColor(QColor(0, 200, 150, 255)) else: self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPA.setColor(QColor(0, 200, 150, 255)) else: if self.widget.cbReverseColumns.isChecked(): self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPC.setColor(QColor(0, 200, 150, 255)) else: self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPC.setColor(Qt.red) self.rbPD.setColor(QColor(0, 200, 150, 255)) self.widget.alert.setText("Total plots: {}".format( self.widget.columnCount.value() * self.widget.rowCount.value())) def getLines(self): return QgsGeometry.fromMultiPolylineXY(self.rowLines) def getSampleLines(self): return ( [self.rowLines[0], self.rowLines[1]] + self.rowLines[2:-1][::max(1, 1 + int((len(self.rowLines) - 3) / 9))] + [self.rowLines[-1]]) def newRubber(self): if self.pX is not None: self.updateRubberGeom() return # default parameters h = 2 * self.widget.canvas.extent().height() / 3 / 20 # first bbox, according to current view h = self.canvas.extent().height() / 6 c = self.canvas.extent().center() rubberExtent = QgsRectangle(QgsPointXY(c.x() - h, c.y() - h), QgsPointXY(c.x() + h, c.y() + h)) self.rotation = 0.0 width = rubberExtent.xMaximum() - rubberExtent.xMinimum() height = rubberExtent.yMaximum() - rubberExtent.yMinimum() # centre rectangle self.pX = QgsPointXY(rubberExtent.xMinimum() + width / 2, rubberExtent.yMinimum() + height / 2) self.pA = QgsPointXY(rubberExtent.xMinimum(), rubberExtent.yMaximum()) self.pB = QgsPointXY(rubberExtent.xMaximum(), rubberExtent.yMaximum()) self.pC = QgsPointXY(rubberExtent.xMaximum(), rubberExtent.yMinimum()) self.pD = QgsPointXY(rubberExtent.xMinimum(), rubberExtent.yMinimum()) # handles H / L self.pH = QgsPointXY((self.pA.x() + self.pB.x()) / 2, (self.pA.y() + self.pB.y()) / 2) self.pL = QgsPointXY((self.pB.x() + self.pC.x()) / 2, (self.pB.y() + self.pC.y()) / 2) # eye (rotation) self.pY = QgsPointXY(self.pX.x(), self.pX.y() - 2 * height / 3) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.rotation_init = self.rotation self.pA_init = QgsPointXY(self.pA) self.pB_init = QgsPointXY(self.pB) self.pC_init = QgsPointXY(self.pC) self.pD_init = QgsPointXY(self.pD) self.pX_init = QgsPointXY(self.pX) self.pY_init = QgsPointXY(self.pY) self.pH_init = QgsPointXY(self.pH) self.pL_init = QgsPointXY(self.pL) self.updateRubberGeom() def canvasPressEvent(self, event): x = event.pos().x() y = event.pos().y() self.p0 = self.canvas.getCoordinateTransform().toMapCoordinates(x, y) distPA = self.p0.distance(self.pA) / self.canvas.mapUnitsPerPixel() distPB = self.p0.distance(self.pB) / self.canvas.mapUnitsPerPixel() distPC = self.p0.distance(self.pC) / self.canvas.mapUnitsPerPixel() distPD = self.p0.distance(self.pD) / self.canvas.mapUnitsPerPixel() distPY = self.p0.distance(self.pY) / self.canvas.mapUnitsPerPixel() distPH = self.p0.distance(self.pH) / self.canvas.mapUnitsPerPixel() distPL = self.p0.distance(self.pL) / self.canvas.mapUnitsPerPixel() edit_individual_node = self.widget.cbIndividualNode.isChecked() if distPA < 6 or distPB < 6 or distPC < 6 or distPD < 6: if edit_individual_node: self.mode = self.MODE_NODE val, idx = min( (val, idx) for (idx, val) in enumerate([distPA, distPB, distPC, distPD])) self.selected_node = self.NODE_NAMES[idx] else: self.mode = self.MODE_SCALE return if distPH < 6: self.mode = self.MODE_SCALE_Y return if distPL < 6: self.mode = self.MODE_SCALE_X return if distPY < 6: self.mode = self.MODE_ROTATE return if self.rb.asGeometry().contains(self.p0): self.mode = self.MODE_PAN return def canvasMoveEvent(self, event): if self.mode == self.MODE_NONE: return x = event.pos().x() y = event.pos().y() pt = self.canvas.getCoordinateTransform().toMapCoordinates(x, y) dx = pt.x() - self.p0.x() dy = pt.y() - self.p0.y() # node name if self.mode == self.MODE_NODE: if self.selected_node == 'A': self.pA.setX(self.pA_init.x() + dx) self.pA.setY(self.pA_init.y() + dy) elif self.selected_node == 'B': self.pB.setX(self.pB_init.x() + dx) self.pB.setY(self.pB_init.y() + dy) elif self.selected_node == 'C': self.pC.setX(self.pC_init.x() + dx) self.pC.setY(self.pC_init.y() + dy) elif self.selected_node == 'D': self.pD.setX(self.pD_init.x() + dx) self.pD.setY(self.pD_init.y() + dy) # pan mode if self.mode == self.MODE_PAN: for p, p_ini in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pX, self.pX_init], [self.pY, self.pY_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: p.setX(p_ini.x() + dx) p.setY(p_ini.y() + dy) # horizontal + vertical sizing if self.mode == self.MODE_SCALE: d_old = self.pA_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old for p, p_ini in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pY, self.pY_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: dx = dd * (p_ini.x() - self.pX.x()) dy = dd * (p_ini.y() - self.pX.y()) p.setX(self.pX.x() + dx) p.setY(self.pX.y() + dy) # horizontal sizing if self.mode == self.MODE_SCALE_X: d_old = self.pL_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old if dd < 0.001: dd = 0.001 dx = dd * (self.pL_init.x() - self.pX.x()) dy = dd * (self.pL_init.y() - self.pX.y()) self.pL.setX(self.pX.x() + dx) self.pL.setY(self.pX.y() + dy) centre = self.pH for p, p_ini in [[self.pA, self.pA_init], [self.pB, self.pB_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) centre = self.pM for p, p_ini in [[self.pC, self.pC_init], [self.pD, self.pD_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) # vertical sizing if self.mode == self.MODE_SCALE_Y: d_old = self.pH_init.distance(self.pX_init) d_new = pt.distance(self.pX_init) dd = d_new / d_old if dd < 0.001: dd = 0.001 dx = dd * (self.pH_init.x() - self.pX.x()) dy = dd * (self.pH_init.y() - self.pX.y()) self.pH.setX(self.pX.x() + dx) self.pH.setY(self.pX.y() + dy) centre = self.pL for p, p_ini in [[self.pB, self.pB_init], [self.pC, self.pC_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) centre = QgsPointXY((self.pA.x() + self.pD.x()) / 2, (self.pA.y() + self.pD.y()) / 2) for p, p_ini in [[self.pA, self.pA_init], [self.pD, self.pD_init]]: dx = dd * (p_ini.x() - centre.x()) dy = dd * (p_ini.y() - centre.y()) p.setX(centre.x() + dx) p.setY(centre.y() + dy) if self.mode == self.MODE_ROTATE: self.pY.setX(self.pY_init.x() + dx) self.pY.setY(self.pY_init.y() + dy) azimuth = self.pX.azimuth(pt) theta = azimuth - self.rotation_init + 180 self.rotation = self.rotation_init + theta for a, i in [ [self.pA, self.pA_init], [self.pB, self.pB_init], [self.pC, self.pC_init], [self.pD, self.pD_init], [self.pH, self.pH_init], [self.pL, self.pL_init], ]: A = QgsGeometry.fromPointXY(i) A.rotate(theta, self.pX) a.setX(A.asPoint().x()) a.setY(A.asPoint().y()) self.updateRubberGeom() def canvasReleaseEvent(self, event): self.pA_init = QgsPointXY(self.pA) self.pB_init = QgsPointXY(self.pB) self.pC_init = QgsPointXY(self.pC) self.pD_init = QgsPointXY(self.pD) self.pX_init = QgsPointXY(self.pX) self.pY_init = QgsPointXY(self.pY) self.pH_init = QgsPointXY(self.pH) self.pL_init = QgsPointXY(self.pL) self.rotation_init = self.rotation self.mode = self.MODE_NONE def activate(self): pass def deactivate(self): self.hide() def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return True
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 ({})
def physiocap_filtrer(self, src, csv_sans_0, csv_avec_0, csv_0_seul, nom_dir_segment, nom_session, chemin_session, diametre_filtre, nom_fichier_synthese, err, mindiam, maxdiam, max_sarments_metre, segment_mini_vitesse, segment_maxi_vitesse, segment_mini_point, segment_max_pdop, segment_max_derive, segment_pas_de_derive, details, eer, eec, d, hv, laProjectionCRS, laProjectionTXT, version_3="NO"): """Fonction de traitement. Filtre ligne brute par ligne brute les données de source (src) pour les valeurs comprises entre mindiam et maxdiam et verifie si on n'a pas atteint le max_sarments_metre. Le résultat est écrit au fur et à mesure dans les fichiers csv_sans_0, csv_avec_0 et depuis v3 dans csv_0_seul mais aussi diametre_filtre La synthese est allongé "details" pilote l'ecriture de 5 parametres ou de la totalité des 10 parametres """ leModeDeTrace = self.fieldComboModeTrace.currentText() # S'il n'existe pas de données parcellaire, le script travaille avec les données brutes titre = "" titre_partie_details = " ; NBSARMM2 ; NBSARCEP ; BIOMMM2 ; BIOMGM2 ; BIOMGCEP " if version_3 == "NO": titre_sans_detail = "X ; Y ; XL93 ; YL93 ; NBSARM ; DIAM ; BIOM ; DATE ; VITESSE" else: # Ajout en version 3 de l'altitude titre_sans_detail = "ID;X ; Y ; XL93 ; YL93 ; ALTITUDE; PDOP ; DISTANCE; DERIVE; AZIMUTH; NBSART; NBSARM ; DIAM ; BIOM ; DATE ; VITESSE" if details == "NO": titre = titre_sans_detail else: #S'il existe des données parcellaire, le script travaille avec les données brutes et les données calculées titre = titre_sans_detail + titre_partie_details # Ecriture de l'entete pour tous les cas csv_sans_0.write("{0}\n".format(titre)) csv_avec_0.write("{0}\n".format(titre)) csv_0_seul.write("{0}\n".format(titre)) # Pour progress bar entre 15 et 40 lignes_brutes = src.readlines() max_lignes = len(lignes_brutes) progress_step = int(max_lignes / 25) #physiocap_log("Bar step: " + str( progress_step), leModeDeTrace) progress_bar = 15 barre = 1 precedent = [] on_coupe = "PREMIER" segment_en_cours = [] gid_en_cours = [] gid_sans_mesure = [] manquant_en_cours = [] info_en_cours = {} derive_en_cours = [] mes_lignes_sans_coupure = [] info_lignes_sans_coupure = [] nombre_segments_sans_coupure = 0 # Récuperer le CRS choisi, les extensions et le calculateur de distance distancearea, EXT_CRS_SHP, EXT_CRS_PRJ, EXT_CRS_RASTER, \ laProjectionCRS, laProjectionTXT, EPSG_NUMBER = \ physiocap_quelle_projection_et_lib_demandee( self) for numero_point, ligne_brute in enumerate(lignes_brutes): if not ligne_brute: break # Progress BAR de 15 à 40 % if (numero_point > barre * progress_step): progress_bar = progress_bar + 1 barre = barre + 1 self.progressBar.setValue(progress_bar) comptage = ligne_brute.count(",") # compte le nombre de virgules result = ligne_brute.split(",") # split en fonction des virgules try: # Transform GPS en L93 # on extrait les Colonnnes 1 à 8 (XY, puis GPS jusqu'à vitesse) # en on les transforme en float ### On utilise XY[0 et 1] puis Altitude XY[2] Pdop XY[5] et vitesse XY[7] XY = [float(x) for x in result[1:9]] # Puis on transforme les WGS84 (du capteur) en L93 (probablement utile) # TODO: ?V3.x autres EPSG ? et eviter cet appel dans la boucle crsDest = QgsCoordinateReferenceSystem.fromEpsgId( EPSG_NUMBER_L93) # Lambert 93 crsSrc = QgsCoordinateReferenceSystem.fromEpsgId( EPSG_NUMBER_GPS) # WGS 84 transformer = QgsCoordinateTransform() transformer.setSourceCrs(crsSrc) transformer.setDestinationCrs(crsDest) if not transformer.isValid(): raise physiocap_exception_no_transform(numero_point) # On assure la tranformation par compatibilité du CVS en GPS et L93 point_L93 = transformer.transform(QgsPointXY(XY[0], XY[1])) XY_L93 = [point_L93.x(), point_L93.y()] # aMsg = "Transformation faite X {0} et Y {1}". \ # format( XY_L93[0], XY_L93[1]) # physiocap_log( aMsg , leModeDeTrace) # physiocap_log( "La projection {0}". format( laProjectionTXT), leModeDeTrace) if (laProjectionTXT == "GPS"): le_point_projete = QgsPointXY(XY[0], XY[1]) else: # Pour le moment seulement L93 le_point_projete = QgsPointXY(XY_L93[0], XY_L93[1]) XY_projete = [le_point_projete.x(), le_point_projete.y()] except: aMsg = "{0} Erreur bloquante durant tranformation SCR : pour la ligne brute numéro {1}". \ format ( PHYSIOCAP_STOP, numero_point) physiocap_error(self, aMsg) err.write(aMsg) # on écrit la ligne dans le fichier ERREUR # monter directemenr exception raise # TODO: ?V3.x marquer les points à conserver (non filtré et dans un segment) # pour creer un 4eme csv POINTS_VALIDES # ce qui reste compliqué pour les segments courts que je ne connais pas encore try: # SEGMENT si V3 # On regarde les points sans mesure avant SEGMENT diams = [float(x) for x in result[9:NB_VIRGULES + 1] ] # on extrait les diams et on les transforme en float diamsF = [ i for i in diams if i > mindiam and i < maxdiam ] # on filtre les diams avec les paramètres entrés ci-dessus derive = 0.0 ma_distance = 0.0 mon_azimuth = 0.0 # SEGMENT si V3 if version_3 == "NO": pass elif precedent == [] or on_coupe == "PREMIER": #physiocap_log( "SEGMENT ==>> point {0} PREMIER".format( numero_point), TRACE_SEGMENT + "_DEBUG") # Stocker le premier point pour comparer au prochain tour # et la Date début precedent = XY_projete # TODO: ?V3.y passage en 3D mettre en Z la dérive info_en_cours[DATE_DEBUT] = result[0] if len(diamsF) == 0: # On ne STOCKE pas les points sans MESURE gid_sans_mesure.append(numero_point) else: gid_en_cours.append(numero_point) derive_en_cours.append(0) segment_en_cours.append(QgsPointXY(le_point_projete)) on_coupe = "NON" else: # On vérifie qualité de mesure # ################################################ # Filtre des points pour découpage en SEGMENT ou # pour montrer les limites de la capture # On cherche si le point est dans la zone attendue # calcul basé sur la vitesse annoncé par GPS sur # le point en cours et PDOP # ################################################# # Quand vitesse plus de 2.5 et moins de 8 et pdop reste cohérent segment_max_pdop if XY[7] >= segment_mini_vitesse and XY[ 7] < segment_maxi_vitesse and XY[5] < segment_max_pdop: # on est en vitesse de croisière # Calcul de la distance théorique par rapport au precedent # Introduire un calcul de distance length et l'azimuth le_point_precedent = QgsPointXY(precedent[0], precedent[1]) ma_distance = distancearea.measureLine( le_point_projete, le_point_precedent) mon_azimuth = le_point_projete.azimuth(le_point_precedent) # TODO: ?V3.y Traiter l'azimuth depuis le début du segment distance_theorique = XY[ 7] * 1000 / 3600 # On suppose une seconde d'avancement derive = (ma_distance - distance_theorique) / distance_theorique * 100 # physiocap_log( "Vitesse {3} Distance théorique {1:.2f} et ma distance {0:.2f} \ # sont distantes de \n {2:.1f} soit une derive de {4:.1f}".\ # format(ma_distance, distance_theorique, \ # ( ma_distance - distance_theorique), XY[7], derive ), \ # TRACE_SEGMENT) #remplacer le precedent par l'actuel precedent = XY_projete # Vérification de dérive if abs(derive) > (segment_max_derive + (2 * segment_pas_de_derive)): physiocap_log( "{0} DECOUPAGE point {1} : l'avancée dérive GRAVE ===> {2:.1f} ! ".\ format(PHYSIOCAP_WARNING, numero_point, derive ), \ TRACE_SEGMENT_DECOUPES) on_coupe = "OUI" elif abs(derive) > (segment_max_derive + segment_pas_de_derive): physiocap_log( "{0} DECOUPAGE point {1} : l'avancée dérive de PLUS d'un PAS ==> {2:.1f} ! ".\ format(PHYSIOCAP_WARNING, numero_point, derive ), \ TRACE_SEGMENT_DECOUPES) on_coupe = "OUI" elif abs(derive) > segment_max_derive: physiocap_log("{0} DECOUPAGE point {1} : l'avancée dérive => {2:.1f} ! ".\ format(PHYSIOCAP_WARNING, numero_point, derive ), \ TRACE_SEGMENT_DECOUPES) on_coupe = "OUI" else: # La derive < segment_max_derive en % : # Stocker ligne "droite" = orientation et sens d'avancement # Créer un flux des avancement stables pour identifier l'écartement problable # Ajouter un point à la ligne segment_en_cours.append(QgsPointXY(le_point_projete)) info_en_cours[DATE_FIN] = result[0] if len(diamsF) == 0: # On ne STOCKE pas les points sans MESURE gid_sans_mesure.append(numero_point) else: gid_en_cours.append(numero_point) derive_en_cours.append(derive) on_coupe = "NON" else: # Cas d'arret (fin de rang) ou pdop on_coupe = "OUI" # Tracer cas decoupe vitessse if XY[7] < segment_mini_vitesse: if len(segment_en_cours) > 0: physiocap_log("{0} DECOUPAGE point {1} : vitesse {2:.1f} alors que min est {3:.1f}! ".\ format(PHYSIOCAP_WARNING, numero_point, XY[7], segment_mini_vitesse), \ TRACE_SEGMENT_DECOUPES) if XY[7] > segment_maxi_vitesse: if len(segment_en_cours) > 0: physiocap_log("{0} DECOUPAGE point {1} : vitesse {2:.1f} que max est {3:.1f}! ".\ format(PHYSIOCAP_WARNING, numero_point, XY[7], segment_maxi_vitesse), \ TRACE_SEGMENT_DECOUPES) # Tracer cas decoupe pdop if XY[5] >= segment_max_pdop: physiocap_log("{0} DECOUPAGE point {1} : pdop {2:.1f} max est {3:.1f}! ".\ format(PHYSIOCAP_WARNING, numero_point, XY[5], segment_max_pdop ), \ TRACE_SEGMENT_DECOUPES) if on_coupe == "OUI": # Cas de fin de ligne if len(segment_en_cours) > segment_mini_point: # Le segment est à garder manquant_en_cours.append(numero_point) # Mémoriser la ligne des points cohérents mes_lignes_sans_coupure.append(segment_en_cours) info_en_cours[NUM_SEG] = nombre_segments_sans_coupure info_en_cours[DATE_FIN] = result[0] info_en_cours[NOMBRE] = len(segment_en_cours) info_en_cours[GID_GARDE] = gid_en_cours info_en_cours[GID_SANS_MESURE] = gid_sans_mesure info_en_cours[GID_TROU] = manquant_en_cours info_en_cours[DERIVE] = np.mean(derive_en_cours) # stocker jour_heure début et fin et derive moyenne ... info_lignes_sans_coupure.append(info_en_cours) nombre_segments_sans_coupure = nombre_segments_sans_coupure + 1 manquant_en_cours = [] else: # Vérifier les gid_sans_mesure # On ne perd pas les points manquants qui seront ajouter dans GID_TROU pour le segment suivant # On aditionne des gid en cours avec les manquants... for gid_perdu in gid_en_cours: manquant_en_cours.append(gid_perdu) manquant_en_cours.append(numero_point) if len(segment_en_cours) > 0: physiocap_log("{0} SEGMENT {1} IGNORE : trop cours == {2} points, le mini est {3} ".\ format(PHYSIOCAP_WARNING, nombre_segments_sans_coupure, len(segment_en_cours), segment_mini_point ), TRACE_SEGMENT_DECOUPES) info_en_cours = {} gid_en_cours = [] gid_sans_mesure = [] precedent = [] on_coupe = "PREMIER" segment_en_cours = [] except: aMsg = "{0} Erreur bloquante durant extraction des segments : pour la ligne brute numéro {1}". \ format ( PHYSIOCAP_STOP, numero_point) physiocap_error(self, aMsg) err.write(aMsg) # on écrit la ligne dans le fichier ERREUR # monter directemenr exception raise try: # On filtre vraiement if details == "NO": if len( diamsF ) == 0: # si le nombre de diamètre après filtrage = 0 alors pas de mesures nbsarm = 0 nbsart = 0 diam = 0 biom = 0 # Ecrire les seuls_0 et aussi les points avec 0 if version_3 == "NO": csv_0_seul.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le csv avec ZERO SEUL csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le fcsv avec ZERO else: # V3 on ajoute altitude, pdop, distance au point precedent et la dérive # puis AZIMUTH et NBSART = 0 a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \ {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};0;0;0;0;{10};{11:.7f}\n" . \ format(numero_point, XY[0],XY[1],XY_L93[0],XY_L93[1], \ XY[2],XY[5],ma_distance,derive,mon_azimuth, result[0],XY[7]) csv_0_seul.write(a_ecrire) csv_avec_0.write(a_ecrire) elif comptage == NB_VIRGULES and len( diamsF ) > 0: # si le nombre de diamètre après filtrage != 0 alors mesures # Nombre sarment total nbsart = len(diamsF) if XY[7] != 0: # Si vitesse non nulle nbsarm = len(diamsF) / (XY[7] * 1000 / 3600) else: nbsarm = 0 if nbsarm > 1 and nbsarm < max_sarments_metre: diam = sum(diamsF) / len(diamsF) biom = 3.1416 * (diam / 2) * (diam / 2) * nbsarm if version_3 == "NO": csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%0.2f%s%.2f%s%.2f%s%s%s%0.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le csv avec ZERO csv_sans_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%0.2f%s%.2f%s%.2f%s%s%s%0.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le csv sans ZERO else: # V3 on ajoute altitude, pdop,distance au point precedent et risque de dérive # puis AZIMUTH et NBSART a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \ {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};{10}; \ {11:.2f}; {12:.2f};{13:.2f};{14};{15:.7f}\n" . \ format( numero_point, XY[0], XY[1], XY_L93[0] ,XY_L93[1], \ XY[2],XY[5],ma_distance,derive,mon_azimuth,nbsart, \ nbsarm,diam,biom,result[0],XY[7]) csv_avec_0.write(a_ecrire) csv_sans_0.write(a_ecrire) for n in range(len(diamsF)): diametre_filtre.write("%f%s" % (diamsF[n], ";")) elif details == "YES": if len( diamsF ) == 0: # si le nombre de diamètre après filtrage = 0 alors pas de mesures nbsart = 0 nbsarm = 0 diam = 0 biom = 0 nbsarmm2 = 0 nbsarcep = 0 biommm2 = 0 biomgm2 = 0 biomgcep = 0 if version_3 == "NO": csv_0_seul.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f%s%i%s%i%s%i%s%i%s%i\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep)) csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f%s%i%s%i%s%i%s%i%s%i\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep)) else: # Q3 on ajoute altitude, pdop, distance au point precedent et la dérive # puis AZIMUTH et NBSART = 0 a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \ {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};0;0;0;0;{10};{11:.7f}" . \ format(numero_point, XY[0],XY[1],XY_L93[0],XY_L93[1], XY[2],XY[5],ma_distance,derive,mon_azimuth, result[0],XY[7]) a_ecrire_detail = ";0;0;0;0;0\n" a_ecrire_complet = a_ecrire + a_ecrire_detail csv_0_seul.write(a_ecrire_complet) csv_avec_0.write(a_ecrire_complet) elif comptage == NB_VIRGULES and len( diamsF ) > 0: # si le nombre de diamètre après filtrage != 0 alors mesures nbsart = len(diamsF) if XY[7] != 0: nbsarm = len(diamsF) / (XY[7] * 1000 / 3600) else: nbsarm = 0 if nbsarm > 1 and nbsarm < max_sarments_metre: diam = sum(diamsF) / len(diamsF) biom = 3.1416 * (diam / 2) * (diam / 2) * nbsarm nbsarmm2 = nbsarm / eer * 100 nbsarcep = nbsarm * eec / 100 biommm2 = biom / eer * 100 biomgm2 = biom * d * hv / eer biomgcep = biom * d * hv * eec / 100 / 100 if version_3 == "NO": csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%.2f%s%.2f%s%.2f%s%s%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep)) csv_sans_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%.2f%s%.2f%s%.2f%s%s%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f\n" \ %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep)) else: # Q3 on ajoute altitude, pdop,distance au point precedent et risque de dérive # puis AZIMUTH et NBSART a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \ {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};{10}; \ {11:.2f}; {12:.2f};{13:.2f};{14};{15:.7f}" . \ format( numero_point, XY[0], XY[1], XY_L93[0] ,XY_L93[1], XY[2],XY[5],ma_distance,derive,mon_azimuth,nbsart, nbsarm,diam,biom,result[0],XY[7]) a_ecrire_detail = ";{0:.7f};{1:.7f};{2:.7f};{3:.7f};{4:.7f}\n". \ format( nbsarmm2, nbsarcep,biommm2,biomgm2,biomgcep) a_ecrire_complet = a_ecrire + a_ecrire_detail csv_avec_0.write(a_ecrire_complet) csv_sans_0.write(a_ecrire_complet) # Memorise diametre filtré pour histo for n in range(len(diamsF)): diametre_filtre.write("%f%s" % (diamsF[n], ";")) except: aMsg = "{0} Erreur bloquante durant filtrage : pour la ligne brute numéro {1}". \ format ( PHYSIOCAP_STOP, numero_point) physiocap_error(self, aMsg) err.write(aMsg) # on écrit la ligne dans le fichier ERREUR # Pour monter directement exception raise physiocap_exception_err_csv(nom_court_csv_concat) if version_3 == "NO": vecteur_segment = None vecteur_segment_brise = None else: if len(info_lignes_sans_coupure) != nombre_segments_sans_coupure: physiocap_error( self, "{0} on a trouvé {1} segments et {2} infos". \ format( PHYSIOCAP_INFO, nombre_segments_sans_coupure, len( info_lignes_sans_coupure))) raise physiocap_exception_calcul_segment_invalid( "Segment et leurs infos sont différents") i = 0 for info_segment in info_lignes_sans_coupure: i = i + 1 try: physiocap_log( "{0} Segment {1} contient {2} points et une dérive moyenne de {3:.1f}". \ format( PHYSIOCAP_INFO, i, info_segment[NOMBRE], info_segment[DERIVE]), TRACE_SEGMENT) physiocap_log( "gid des points :{0} \net les sans mesure\n{1}". \ format(info_segment[GID_GARDE], info_segment[GID_SANS_MESURE]), TRACE_SEGMENT) except: physiocap_error( self, "Problème : manque attribut dans info segment") raise physiocap_exception_calcul_segment_invalid( "Un attribut n'est pas présent") # try: # physiocap_log( "Date début {0} et fin {1}". \ # format( info_segment[DATE_DEBUT], info_segment[DATE_FIN]), # TRACE_SEGMENT) # except: # physiocap_error( self, "Problème : pas de date dans le segment") # raise physiocap_exception_calcul_segment_invalid( "Date non présente") # Creer les lignes simplifiés ou brisés de ces segments et infos vecteur_segment = physiocap_segment_vers_vecteur( self, chemin_session, nom_dir_segment, nom_session, mes_lignes_sans_coupure, info_lignes_sans_coupure, version_3) vecteur_segment_brise = physiocap_segment_vers_vecteur( self, chemin_session, nom_dir_segment, nom_session, mes_lignes_sans_coupure, info_lignes_sans_coupure, version_3, "BRISE") physiocap_log( "{0} {1} Fin du filtrage OK des {2} lignes.". \ format( PHYSIOCAP_INFO, PHYSIOCAP_UNI, str(numero_point - 1)), leModeDeTrace) return vecteur_segment, vecteur_segment_brise
def generateFootprintsForFilmVertical(self): self.reloadFpLayer() self.reloadCpLayer() # Error wenn nur ein punkt vorhanden if self.cpLayer.featureCount() > 1: caps = self.fpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: #Get FORM1 from FilmInfoDict f1 = self.currentFilmInfoDict["form1"] # Image height f2 = self.currentFilmInfoDict["form2"] # Image width iterFeatures = self.cpLayer.getFeatures() iterNext = self.cpLayer.getFeatures() existingFootpints = QgsVectorLayerUtils.getValues( self.fpLayer, "bildnummer")[0] ft = QgsFeature() ftNext = QgsFeature() iterNext.nextFeature(ftNext) fpFeats = [] kappasToUpdate = {} # iterate over points from CP Layer > LON, LAT i = 0 while iterFeatures.nextFeature(ft): i += 1 iterNext.nextFeature(ftNext) p = QgsPointXY(ft.geometry().asPoint()) if ft['bildnummer'] in existingFootpints: pPrevGeom = QgsGeometry(ft.geometry()) #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD'])) continue if i == 1: pPrevGeom = QgsGeometry(ftNext.geometry()) #if iterNext.isClosed(): # #use pPrev as pNext # pNext = QgsPoint(pPrev) #else: # pNext = QgsPoint(ftNext.geometry().asPoint()) #kappa = p.azimuth(pPrev) #kappa = p.azimuth(pNext) # d = math.sqrt(2*((f1/2 * ft['MASS']/1000)**2)) d1 = f1 / 2 * ft['massstab'] / 1000 d2 = f2 / 2 * ft['massstab'] / 1000 #QMessageBox.warning(None, u"Bild Nummern", "{0}".format(d)) calcCrs = QgsCoordinateReferenceSystem() calcCrs.createFromProj4(self.Proj4Utm(p)) ctF = QgsCoordinateTransform(self.cpLayer.crs(), calcCrs, QgsProject.instance()) cpMetric = QgsGeometry(ft.geometry()) cpMetric.transform(ctF) pPrevGeom.transform(ctF) pMetric = QgsPointXY(cpMetric.asPoint()) pPrevMetric = QgsPointXY(pPrevGeom.asPoint()) kappaMetric = pMetric.azimuth(pPrevMetric) pPrevGeom = QgsGeometry(ft.geometry()) left = pMetric.x() - d2 bottom = pMetric.y() - d1 right = pMetric.x() + d2 top = pMetric.y() + d1 #R = 6371 #D = (d/1000) #cpLat = math.radians(p.y()) #cpLon = math.radians(p.x()) #urLat = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*math.cos(urBrng) ) #urLon = cpLon + math.atan2(math.sin(urBrng)*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(urLat)) #top = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R) ) #bottom = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*-1 ) #lat = math.asin( math.sin(cpLat)*math.cos(D/R) ) #right = cpLon + math.atan2(math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #left = cpLon + math.atan2(-1*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #QMessageBox.warning(None, u"Bild Nummern", "{0}, {1}, {2}, {3}".format(math.degrees(top), math.degrees(bottom), math.degrees(left), math.degrees(right))) #rect = QgsRectangle(math.degrees(left), math.degrees(bottom), math.degrees(right), math.degrees(top)) #l = math.degrees(left) #b = math.degrees(bottom) #r = math.degrees(right) #t = math.degrees(top) p1 = QgsGeometry.fromPointXY(QgsPointXY(left, bottom)) p2 = QgsGeometry.fromPointXY(QgsPointXY(right, bottom)) p3 = QgsGeometry.fromPointXY(QgsPointXY(right, top)) p4 = QgsGeometry.fromPointXY(QgsPointXY(left, top)) #p1.rotate(kappa+90, p) #p2.rotate(kappa+90, p) #p3.rotate(kappa+90, p) #p4.rotate(kappa+90, p) pol = [[ p1.asPoint(), p2.asPoint(), p3.asPoint(), p4.asPoint() ]] geom = QgsGeometry.fromPolygonXY(pol) geom.rotate(kappaMetric, pMetric) #Transform to DestinationCRS ctB = QgsCoordinateTransform(calcCrs, self.fpLayer.crs(), QgsProject.instance()) geom.transform(ctB) feat = QgsFeature(self.fpLayer.fields()) feat.setGeometry(geom) feat.setAttribute('filmnummer', self.currentFilmNumber) feat.setAttribute('bildnummer', ft['bildnummer']) da = QgsDistanceArea() da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym()) feat.setAttribute('shape_length', da.measurePerimeter(geom)) feat.setAttribute('shape_area', da.measureArea(geom)) fpFeats.append(feat) # update Kappa in cpLayer kappasToUpdate[ft.id()] = { ft.fieldNameIndex('kappa'): kappaMetric } iterFeatures.close() iterNext.close() resCAVs = self.cpLayer.dataProvider().changeAttributeValues( kappasToUpdate) QgsMessageLog.logMessage( f"Kappa Update for {kappasToUpdate}, Success: {resCAVs}", tag="APIS", level=Qgis.Success if resCAVs else Qgis.Critical) (res, outFeats) = self.fpLayer.dataProvider().addFeatures(fpFeats) self.fpLayer.updateExtents() if self.canvas.isCachingEnabled(): self.fpLayer.triggerRepaint() else: self.canvas.refresh() else: #Caps QMessageBox.warning(None, "Layer Capabilities!", "Layer Capabilities!") else: #small feature count QMessageBox.warning( None, "Footprints", "Zum Berechnen der senkrecht Footprint müssen mindestens zwei Bilder kartiert werden!" )
def onSaveAddCenterPoint(self): #QMessageBox.warning(None, u"Film Nummer", u"{0},{1},{2}".format(self.imageCenterPoint.x(), self.imageCenterPoint.y(), type(self.imageCenterPoint))) self.reloadCpLayer() #Prepare Image Numbers if self.isOblique: fromImageNumber = self.uiImageNumberFromSpn.value() toImageNumber = self.uiImageNumberToSpn.value() if fromImageNumber > toImageNumber: QMessageBox.warning( None, u"Bild Nummern", u"Die erste Bildnummer darf nicht größer als die zweite sein." ) return else: imageNumbers = range(fromImageNumber, toImageNumber + 1) else: imageNumbers = [self.uiImageNumberSpn.value()] # filmImageNumbers = [] # for imageNumber in imageNumbers: # filmImageNumbers.append('{0}.{1:03d}'.format(self.currentFilmNumber, imageNumber)) # QMessageBox.warning(None, u"Bild Nummern", ",".join(imageNumbers)) # for filmImageNumber in self.cpLayer.getValues("BILD"): # QMessageBox.warning(None, u"Bild Nummern", "{0}".format(filmImageNumber)) # Check if Image Number in Table for imageNumber in imageNumbers: # QMessageBox.warning(None, u"Bild Nummern", u"{0}".format(QgsVectorLayerUtils.getValues(self.cpLayer, "bildnummer_nn"))) if imageNumber in QgsVectorLayerUtils.getValues( self.cpLayer, "bildnummer_nn")[0]: QMessageBox.warning( None, u"Bild Nummern", u"Ein Bild mit der Nummer {0} wurde bereits kartiert". format(imageNumber)) return caps = self.cpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: features = [] feat = QgsFeature(self.cpLayer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(self.imageCenterPoint)) # From Film Table # filmFields = ["form1", "form2", "weise", "kammerkonstante"] feat.setAttribute( 'filmnummer_hh_jjjj_mm', self.currentFilmInfoDict["filmnummer_hh_jjjj_mm"]) feat.setAttribute('filmnummer_nn', self.currentFilmInfoDict["filmnummer_nn"]) feat.setAttribute('filmnummer', self.currentFilmNumber) #Date TODAY now = QDate.currentDate() feat.setAttribute('datum_ersteintrag', now.toString("yyyy-MM-dd")) feat.setAttribute('datum_aenderung', now.toString("yyyy-MM-dd")) # Iterate over Project Selection List und String mit ; trennung generieren feat.setAttribute('copyright', self.currentFilmInfoDict["copyright"]) # By Default Fix Value feat.setAttribute('etikett', 0) # Get Projects from Projekte Liste items = [] # From Input (Radius, Höhe, Schlüsslewort, Beschreibung) if self.isOblique: feat.setAttribute('radius', float(self.uiImageDiameterSpn.value() / 2)) feat.setAttribute('beschreibung', self.uiImageDescriptionEdit.text()) h = self.uiFlightHeightObliqueSpn.value() for j in range(self.uiProjectObliqueList.count()): items.append(self.uiProjectObliqueList.item(j)) else: h = self.uiFlightHeightVerticalSpn.value() feat.setAttribute('fokus', self.currentFilmInfoDict["kammerkonstante"]) if not self.currentFilmInfoDict[ "kammerkonstante"] or not self.currentFilmInfoDict[ "kammerkonstante"] > 0: feat.setAttribute('massstab', 0) else: feat.setAttribute( 'massstab', h / self.currentFilmInfoDict["kammerkonstante"] * 1000) for j in range(self.uiProjectVerticalList.count()): items.append(self.uiProjectVerticalList.item(j)) feat.setAttribute('projekt', ";".join([i.text() for i in items])) feat.setAttribute('hoehe', h) # Calculated/Derived feat.setAttribute('longitude', self.imageCenterPoint.x()) feat.setAttribute('latitude', self.imageCenterPoint.y()) countryCode = self.getCountryCode() feat.setAttribute('land', countryCode) if countryCode == 'AUT': # get meridian and epsg Code meridian, epsgGK = GetMeridianAndEpsgGK( self.imageCenterPoint.x()) # get KG Coordinates gk = TransformGeometry( QgsGeometry().fromPointXY(self.imageCenterPoint), self.cpLayer.crs(), QgsCoordinateReferenceSystem(f"EPSG:{epsgGK}")) gkx = gk.asPoint().y() # Hochwert gky = gk.asPoint().x() # Rechtswert else: meridian = None gkx = None gky = None feat.setAttribute('meridian', meridian) feat.setAttribute('gkx', gkx) # Hochwert feat.setAttribute('gky', gky) # Rechtswert for imageNumber in imageNumbers: f = QgsFeature(feat) f.setAttribute('bildnummer_nn', imageNumber) bn = '{0}.{1:03d}'.format(self.currentFilmNumber, imageNumber) f.setAttribute('bildnummer', bn) if self.isOblique: image = os.path.normpath( self.settings.value("APIS/image_dir") + '\\' + self.currentFilmNumber + '\\' + bn.replace('.', '_') + '.jpg') exif = GetExifForImage(image, altitude=True, longitude=True, latitude=True, exposure_time=True, focal_length=True, fnumber=True) if "altitude" in exif and exif["altitude"]: f.setAttribute('hoehe', exif["altitude"]) f.setAttribute( 'gps_longitude', exif["longitude"] if "longitude" in exif else None) f.setAttribute( 'gps_latitude', exif["latitude"] if "latitude" in exif else None) if "longitude" in exif and "latitude" in exif and exif[ "longitude"] and exif["latitude"]: capturePoint = QgsPointXY(exif["longitude"], exif["latitude"]) kappa = capturePoint.azimuth(self.imageCenterPoint) else: kappa = None f.setAttribute('kappa', kappa) f.setAttribute( 'belichtungszeit', exif["exposure_time"] if "exposure_time" in exif else None) f.setAttribute('fokus', exif["focal_length"] if "focal_length" in exif else None) # FocalLength if "focal_length" in exif and "fnumber" in exif and exif[ "focal_length"] and exif["fnumber"]: blende = exif["focal_length"] / exif[ "fnumber"] # effecitve aperture (diameter of entrance pupil) = focalLength / fNumber else: blende = None f.setAttribute('blende', blende) features.append(f) (res, outFeats) = self.cpLayer.dataProvider().addFeatures(features) self.cpLayer.updateExtents() if res and self.isOblique: self.generateFootprintsForFilmOblique() #QMessageBox.warning(None, u"Film Nummer", u"{0},{1}".format(res, outFeats)) else: QMessageBox.warning(None, u"Layer Capabilities!") if self.canvas.isCachingEnabled(): self.cpLayer.triggerRepaint() else: self.canvas.refresh() self.onCancelAddCenterPoint()