class Cu_Video_TrackerDialog(QtGui.QDialog): def __init__(self, iface): QtGui.QDialog.__init__(self) # Set up the user interface from Designer. self.ui = Ui_Form() self.ui.setupUi(self) self.iface = iface self.ui.sourceLoad_pushButton.clicked.connect(self.OpenButton) self.ui.replayPlay_pushButton.clicked.connect(self.PlayPauseButton) QObject.connect(self.ui.replay_mapTool_pushButton, SIGNAL("toggled(bool)"), self.replayMapTool_toggled) self.positionMarker = None settings = QSettings() settings.beginGroup("/plugins/PlayerPlugin") self.replay_followPosition = settings.value("followPosition", True, type=bool) settings.setValue("followPosition", self.replay_followPosition) QObject.connect(self.iface.mapCanvas(), SIGNAL("mapToolSet(QgsMapTool*)"), self.mapToolChanged) self.mapTool = ReplayMapTool(self.iface.mapCanvas(), self) self.mapTool_previous = None self.mapToolChecked = property(self.__getMapToolChecked, self.__setMapToolChecked) QObject.connect(self.ui.replayPosition_horizontalSlider, SIGNAL('sliderMoved(int)'), self.replayPosition_sliderMoved) QObject.connect(self.ui.addpoint_button, SIGNAL('clicked()'), self.snapshot) QObject.connect(self.ui.ExporText_button, SIGNAL('clicked()'), self.exportText) QObject.connect(self.ui.ExporShp_button, SIGNAL('clicked()'), self.exportShp) QObject.connect(self.ui.ExporSqlite_button, SIGNAL('clicked()'), self.exportSqlite) QObject.connect(self.ui.ExporKML_button, SIGNAL('clicked()'), self.exportKML) QObject.connect(self.ui.Help, SIGNAL('clicked()'), self.Help) self.PlayPuase = 0 # Puase=0,Play=1 self.Close = 0 # select video=1 , Close=0 self.adactProjection = False self.createLayer = 0 # Default layer=1,create by user=2,load existent=else self.videoWidget = Phonon.VideoWidget(self.ui.video_widget) def OpenButton(self): if self.Close == 1: if self.positionMarker != None: self.iface.mapCanvas().scene().removeItem(self.positionMarker) self.positionMarker = None self.Close = 0 self.ui.replay_mapTool_pushButton.setChecked(False) self.ui.sourceLoad_pushButton.setText('Open...') self.createLayer = 0 self.timer.stop() ##self.timer2.stop() self.media_obj.stop() self.iface.mapCanvas().unsetMapTool(self.mapTool) self.close() else: self.path = QtGui.QFileDialog.getOpenFileName( self, self.tr("Select Video files")) self.csvFile = open(self.path + '.csv', "rb") Filereader = csv.DictReader(self.csvFile) self.CSVLayer = QgsVectorLayer("LineString", "GPS Tracking", "memory") self.latt = [] self.lonn = [] self.timeh = [] self.timem = [] self.times = [] i = 0 for row in Filereader: self.latt.append(float(row['lon'])) self.lonn.append(float(row['lat'])) if row['time_h'] != '': self.timeh.append(int(row['time_h'])) self.timem.append(int(row['time_m'])) self.times.append(int(row['time_s'])) #create tracker layer (line layer) for i in xrange(0, len(self.latt) - 1, 1): point_start = QgsPoint(self.latt[i], self.lonn[i]) point_end = QgsPoint(self.latt[i + 1], self.lonn[i + 1]) line = QgsGeometry.fromPolyline([point_start, point_end]) self.pr = self.CSVLayer.dataProvider() afeature = QgsFeature() afeature.setGeometry( QgsGeometry.fromPolyline([point_start, point_end])) self.pr.addFeatures([afeature]) self.CSVLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([self.CSVLayer]) SelectLayer, ok = QInputDialog.getItem( self.iface.mainWindow(), "Layer chooser", "Choose point layer", ('Default point layer', 'Creat new point layer', 'Load existent point layer')) if SelectLayer == 'Load existent point layer': self.newLayerPath = QtGui.QFileDialog.getOpenFileName() if not self.newLayerPath is None: name = self.newLayerPath.split("/")[-1][0:-4] self.vl = QgsVectorLayer(self.newLayerPath, name, "ogr") self.pr = self.vl.dataProvider() fields = self.pr.fields() field_names = [field.name() for field in fields] f = "Image link" fnd = self.vl.fieldNameIndex(f) fn = field_names[fnd] if not fn == f: self.pr.addAttributes( [QgsField("Image link", QVariant.String)]) QgsMapLayerRegistry.instance().addMapLayer(self.CSVLayer) QgsMapLayerRegistry.instance().addMapLayer(self.vl) elif SelectLayer == 'Default point layer': self.vl = QgsVectorLayer("Point?crs=epsg:4326&index=yes", "point", "memory") self.pr = self.vl.dataProvider() self.pr.addAttributes([ QgsField('id', QVariant.Int), QgsField('Name', QVariant.String), QgsField('Description', QVariant.String), QgsField('Type', QVariant.String), QgsField("Lon", QVariant.String), QgsField("Lat", QVariant.String), QgsField('East UTM', QVariant.String), QgsField('North UTM', QVariant.String), QgsField('Image link', QVariant.String) ]) # update layer's extent self.vl.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.CSVLayer) QgsMapLayerRegistry.instance().addMapLayers([self.vl]) self.createLayer = 1 else: # Creat new point layer by user self.createLayer = 2 self.vl = QgsVectorLayer("Point?crs=epsg:4326&index=yes", "point", "memory") self.pr = self.vl.dataProvider() # table manager dialog self.dialoga = TableManager(self.iface, self.vl, self.CSVLayer) self.dialoga.exec_() #set point label palyr = QgsPalLayerSettings() palyr.readFromLayer(self.vl) palyr.enabled = True palyr.fieldName = 'id' palyr.placement = QgsPalLayerSettings.Upright palyr.setDataDefinedProperty(QgsPalLayerSettings.Size, True, True, '14', '') palyr.writeToLayer(self.vl) if self.positionMarker == None: self.positionMarker = PositionMarker(self.iface.mapCanvas()) self.media_src = Phonon.MediaSource(self.path) self.media_obj = Phonon.MediaObject(self) self.media_obj.setCurrentSource(self.media_src) Phonon.createPath(self.media_obj, self.videoWidget) # set audio ## audio_out = Phonon.AudioOutput(Phonon.VideoCategory, self) ## Phonon.createPath(self.media_obj, audio_out) self.ui.video_widget.resizeEvent = self.Resize() self.media_obj.setTickInterval(100) self.timer = QtCore.QTimer() QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.Timer) self.PlayPuase = 1 self.ui.sourceLoad_pushButton.setText('Close') self.Close = 1 #load file selector self.media_obj.play() #phonon play self.timer.start(1000) self.ui.replayPlay_pushButton.setEnabled(True) self.ui.addpoint_button.setEnabled(True) def Resize(self): a = self.ui.video_widget.frameSize() b = self.videoWidget.frameSize() if a != b: self.videoWidget.resize(a) def CurrentPos(self): end = self.media_obj.totalTime() pos = self.media_obj.currentTime() if pos == end: self.timer.stop() self.media_obj.pause() if self.PlayPuase == 1: self.PlayPuase = 0 else: Pos = pos / 1000 self.ui.replayPosition_label.setText( str(datetime.timedelta(seconds=int(Pos))) + '/' + str(datetime.timedelta(seconds=(int(end / 1000))))) return int(Pos) def Timer(self): if self.PlayPuase == 1: self.updateReplayPosition() self.SetSlide() else: pass def TimeOffset(self): self.current_second = [] self.time_offset = [] if self.timeh != []: for i in xrange(0, len(self.timeh), 1): h_second = int(self.timeh[i]) * 60 * 60 m_second = int(self.timem[i]) * 60 s_second = int(self.times[i]) c_second = h_second + m_second + s_second self.current_second.append(c_second) t_of = int( int(self.current_second[i]) - int(self.current_second[0])) self.time_offset.append(t_of) else: #find time offset for i in xrange(0, len(self.latt), 1): # Number of record in csv self.NumRec = len(self.latt) #create new list start at 0 self.L_Num = range(len(self.latt)) #time interval self.t_interval = ((self.media_obj.totalTime() / 1000) / float(self.NumRec - 1)) t_of = self.L_Num[i] * self.t_interval self.time_offset.append(t_of) return self.time_offset def updateReplayPosition(self): pos = self.CurrentPos() # find the nearest timestamp offset of position time in logging data TimeOffset = self.TimeOffset() i = min(range(len(TimeOffset)), key=lambda x: abs(TimeOffset[x] - ((pos)))) if pos - 1 == (self.media_obj.totalTime() / 1000 - 1): self.media_obj.stop() if pos - TimeOffset[i] == 0: self.lat_new = self.latt[i] self.lon_new = self.lonn[i] else: if pos < TimeOffset[i]: Dlat = self.latt[i] - self.latt[i - 1] Dlon = self.lonn[i] - self.lonn[i - 1] Dtime = TimeOffset[i] - TimeOffset[i - 1] else: Dlat = self.latt[i + 1] - self.latt[i] Dlon = self.lonn[i + 1] - self.lonn[i] Dtime = TimeOffset[i + 1] - TimeOffset[i] Dti = float(pos - TimeOffset[i]) Dlat_i = Dlat * (Dti / Dtime) Dlon_i = Dlon * (Dti / Dtime) self.lat_new = self.latt[i] + Dlat_i self.lon_new = self.lonn[i] + Dlon_i self.lat, self.lon = self.lat_new, self.lon_new self.Point = QgsPoint() self.Point.set(self.lat, self.lon) canvas = self.iface.mapCanvas() mapRenderer = canvas.mapRenderer() crsSrc = QgsCoordinateReferenceSystem(4326) # WGS 84 crsDest = mapRenderer.destinationCrs() xform = QgsCoordinateTransform( crsSrc, crsDest) #usage: xform.transform(QgsPoint) self.positionMarker.setHasPosition(True) self.Point = xform.transform(self.Point) self.positionMarker.newCoords(self.Point) if self.replay_followPosition: extent = self.iface.mapCanvas().extent() boundaryExtent = QgsRectangle(extent) boundaryExtent.scale(1.0) if not boundaryExtent.contains(QgsRectangle(self.Point, self.Point)): extentCenter = self.Point newExtent = QgsRectangle(extentCenter.x() - extent.width() / 1.7, extentCenter.y() - extent.height() / 1.7, extentCenter.x() + extent.width() / 17, extentCenter.y() + extent.height() / 1.7) self.iface.mapCanvas().setExtent(newExtent) self.iface.mapCanvas().refresh() East, North, alt = self.transform_wgs84_to_utm(self.lat_new, self.lon_new) self.ui.E.setText('Easting : ' + str(East)) self.ui.N.setText('Northing : ' + str(North)) self.ui.lat.setText('Latitude : ' + str(self.lon_new)) self.ui.lon.setText('Longitude : ' + str(self.lat_new)) def PlayPauseButton(self): if self.PlayPuase == 1: self.media_obj.pause() self.timer.stop() self.PlayPuase = 0 else: self.media_obj.play() self.timer.start(0) self.PlayPuase = 1 def replayMapTool_toggled(self, checked): """Enable/disable replay map tool""" self.useMapTool(checked) def useMapTool(self, use): """ afer you click on it, you can seek the video just clicking on the gps track """ if use: if self.iface.mapCanvas().mapTool() != self.mapTool: self.mapTool_previous = self.iface.mapCanvas().mapTool() self.iface.mapCanvas().setMapTool(self.mapTool) else: if self.mapTool_previous != None: self.iface.mapCanvas().setMapTool(self.mapTool_previous) else: self.iface.mapCanvas().unsetMapTool(self.mapTool) def mapToolChanged(self, tool): """Handle map tool changes outside plugin""" if (tool != self.mapTool) and self.mapToolChecked: self.mapTool_previous = None self.mapToolChecked = False def __getMapToolChecked(self): return self.replay_mapTool_pushButton.isChecked() def __setMapToolChecked(self, val): self.replay_mapTool_pushButton.setChecked(val) def findNearestPointInRecording(self, toPoint): """ Find the point nearest to the specified point (in map coordinates) """ for i in xrange(0, len(self.latt), 1): if (str(self.latt[i]))[0:7] == str(toPoint.x())[0:7] and (str( self.lonn[i]))[0:7] == (str(toPoint.y()))[0:7]: adj = (self.time_offset[i]) - (self.time_offset[0]) lat, lon = (self.latt[i]), (self.lonn[i]) Point = QgsPoint() Point.set(lat, lon) self.positionMarker.newCoords(Point) self.Seek(adj) break def Seek(self, pos): if self.PlayPuase == 0: self.timer.stop() self.media_obj.seek(pos * 1000) self.media_obj.play() self.timer.start(0) self.PlayPuase = 1 else: self.media_obj.seek(pos * 1000) self.timer.start(1000) def replayPosition_sliderMoved(self, pos): """Handle moving of replay position slider by user""" self.Seek(pos) def SetSlide(self): end = self.media_obj.totalTime() pos = self.media_obj.currentTime() self.endtime = (self.media_obj.totalTime() / 1000) self.ui.replayPosition_horizontalSlider.setMinimum(0) self.ui.replayPosition_horizontalSlider.setMaximum((self.endtime)) if not pos == end: pos = float(self.CurrentPos()) self.ui.replayPosition_horizontalSlider.setValue(pos) def AddPoint(self, toPoint): if self.PlayPuase == 1: self.media_obj.pause() self.timer.stop() self.PlayPuase = 0 else: pass last_desc = '///' fc = int(self.pr.featureCount() + 1) if self.createLayer == 1: self.vl.dataProvider() filename = self.path + '__' + str(self.getImageFileName()) + '.jpg' p = QPixmap.grabWidget(self.videoWidget) p.save(filename) (Name, ok) = QInputDialog.getText(self.iface.mainWindow(), "Attributes", "Name", QLineEdit.Normal, last_desc) (Description, ok) = QInputDialog.getText(self.iface.mainWindow(), "Attributes", "Description", QLineEdit.Normal, last_desc) (Type, ok) = QInputDialog.getText(self.iface.mainWindow(), "Attributes", "Type", QLineEdit.Normal, last_desc) # create the feature feature = QgsFeature() lat, lon = toPoint.x(), toPoint.y() Point = QgsPoint() Point.set(lat, lon) EastUTM, NorthUTM, alt = self.transform_wgs84_to_utm(lat, lon) feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes([ fc, Name, Description, Type, lat, lon, EastUTM, NorthUTM, self.path + '__' + str(self.getImageFileName()) + '.jpg' ]) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename, self.path + '__' + str(self.getImageFileName()) + '.jpg') elif self.createLayer == 2: p = QPixmap.grabWidget(self.videoWidget) fields = self.pr.fields() attributes = [] lat, lon = toPoint.x(), toPoint.y() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon': attributes.append(lat) elif a == 'Lat': attributes.append(lon) else: if b == 'String': (a, ok) = QInputDialog.getText(self.iface.mainWindow(), "Attributes", a + ' = ' + b, QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a, ok) = QInputDialog.getDouble(self.iface.mainWindow(), "Attributes", a + ' = ' + b, decimals=10) attributes.append(a) elif b == 'Integer': (a, ok) = QInputDialog.getInt(self.iface.mainWindow(), "Attributes", a + ' = ' + b) attributes.append(a) feature = QgsFeature() Point = QgsPoint() Point.set(lat, lon) #use in new table filename = self.path + '__' + str(self.getImageFileName()) + '.jpg' p.save(filename) attributes.append(filename) feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename, self.path + '__' + str(self.getImageFileName()) + '.jpg') else: p = QPixmap.grabWidget(self.videoWidget) fields = self.pr.fields() attributes = [] lat, lon = toPoint.x(), toPoint.y() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon': attributes.append(lat) elif a == 'Lat': attributes.append(lon) else: if b == 'String': (a, ok) = QInputDialog.getText(self.iface.mainWindow(), "Attributes", a + ' = ' + b, QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a, ok) = QInputDialog.getDouble(self.iface.mainWindow(), "Attributes", a + ' = ' + b, decimals=10) attributes.append(a) elif b == 'Integer': (a, ok) = QInputDialog.getInt(self.iface.mainWindow(), "Attributes", a + ' = ' + b) attributes.append(a) feature = QgsFeature() Point = QgsPoint() Point.set(lat, lon) #use in existent table feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) filename = self.path + '__' + str(self.getImageFileName()) + '.jpg' p.save(filename) field_index = self.pr.fieldNameIndex('Image link') feature.setAttribute(field_index, filename) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename, self.path + '__' + str(self.getImageFileName()) + '.jpg') self.ui.ExporText_button.setEnabled(True) self.ui.ExporShp_button.setEnabled(True) self.ui.ExporSqlite_button.setEnabled(True) self.ui.ExporKML_button.setEnabled(True) def getImageFileName(self): current_time_now = time.time() ctn_int = int(current_time_now) return ctn_int def transform_wgs84_to_utm(self, lon, lat): def get_utm_zone(longitude): return (int(1 + (longitude + 180.0) / 6.0)) def is_northern(latitude): """ Determines if given latitude is a northern for UTM """ if (latitude < 0.0): return 0 else: return 1 utm_coordinate_system = osr.SpatialReference() utm_coordinate_system.SetWellKnownGeogCS( "WGS84") # Set geographic coordinate system to handle lat/lon utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat)) wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS( ) # Clone ONLY the geographic coordinate system # create transform component wgs84_to_utm_transform = osr.CoordinateTransformation( wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>) return wgs84_to_utm_transform.TransformPoint( lon, lat, 0) # returns easting, northing, altitude def snapshot(self): Point = QgsPoint(self.Point) Point.set(self.lat, self.lon) self.positionMarker.newCoords(Point) self.AddPoint(Point) def Help(self): path_help = 'C:/Users/Administrator/.qgis2' os.startfile(path_help + '/python/plugins/Cu_Video_Tracker/How to.pdf') def exportText(self): toCSV = QgsVectorFileWriter.writeAsVectorFormat( self.vl, self.path + '_' 'point' + '.csv', "TIS-620", None, "CSV") debug = self.path + '_' 'point' + '.csv' QtGui.QMessageBox.information(self, 'Export to', debug) def exportShp(self): toShp = QgsVectorFileWriter.writeAsVectorFormat( self.vl, self.path + '_' 'point' + '.shp', "utf-8", None, "ESRI Shapefile") debug = self.path + '_' 'point' + '.shp' QtGui.QMessageBox.information(self, 'Export to', debug) def exportSqlite(self): toSql = QgsVectorFileWriter.writeAsVectorFormat( self.vl, self.path + '_' 'point' + '.sqlite', "utf-8", None, "SQLite") debug = self.path + '_' 'point' + '.sqlite' QtGui.QMessageBox.information(self, 'Export to', debug) def exportKML(self): toSql = QgsVectorFileWriter.writeAsVectorFormat( self.vl, self.path + '_' 'point' + '.kml', "utf-8", None, "KML") debug = self.path + '_' 'point' + '.kml' QtGui.QMessageBox.information(self, 'Export to', debug)
class QGisMap(QtWidgets.QWidget, Ui_Form): def __init__(self,projectfile,MainWidget): QtWidgets.QMainWindow.__init__(self) if os.name == 'nt': ffmpeg = os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe' versione = 'ffmpeg.exe' else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' versione = 'ffmpeg' if os.path.exists(ffmpeg) == True: self.setupUi(self) self.setWindowFlags(Qt.WindowStaysOnTopHint) self.Main = MainWidget self.projectfile = projectfile with open(self.projectfile,'r') as File: for line in File: if line[0:19] == 'Video file location': self.videoFile = line.split('=')[-1][1:-1] elif line[0:23] == 'Video start at msecond:': self.fps = (1 / (float(line.split()[7]))) * 1000 self.StartMsecond = int(line.split()[4]) elif line[0:4] == 'DB =': DB = line.split('=')[-1][1:-1] if DB == 'None': self.DB = None else: self.DB = DB break self.pushButton_3.setCheckable(True) self.EnableMapTool = False self.ExtractTool = 0 self.dockWidget_4.hide() self.GPXList = [] self.positionMarker=PositionMarker(self.Main.iface.mapCanvas()) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) self.player = QMediaPlayer() self.player.setVideoOutput(self.video_frame) self.playButton.clicked.connect(self.PlayPause) self.muteButton.clicked.connect(self.MuteUnmute) self.toolButton_11.clicked.connect(self.SkipBackward) self.toolButton_12.clicked.connect(self.SkipForward) self.SkipBacktoolButton_8.clicked.connect(self.BackwardFrame) self.SkipFortoolButton_9.clicked.connect(self.ForwardFrame) self.toolButton_4.clicked.connect(self.ExtractToolbar) self.toolButton_5.clicked.connect(self.close) self.pushButtonCut_2.clicked.connect(self.ExtractCommand) self.pushButtonCutA_6.clicked.connect(self.ExtractFromA) self.pushButtonCutB_6.clicked.connect(self.ExtractToB) self.pushButton_5.clicked.connect(self.CancelVertex) self.progressBar.hide() self.Main.pushButton_2.hide() self.Main.pushButton_8.hide() self.Main.groupBox.show() self.Main.groupBox_4.hide() self.ExtractA = False self.ExtractB = False self.ExtractedDirectory = None self.pushButtonCut_2.setEnabled(False) self.toolButton_6.setEnabled(False) self.LoadGPXVideoFromPrj(self.projectfile) else: ret = QMessageBox.warning(self, "Warning", 'missing ffmpeg binaries, please download it from https://github.com/sagost/VideoUavTracker/blob/master/FFMPEG/'+versione+' and paste it in /.qgis3/python/plugins/Video_UAV_Tracker/FFMPEG/ ', QMessageBox.Ok) self.close() def LoadGPXVideoFromPrj(self,VideoGisPrj): self.Polyline = [] with open(VideoGisPrj,'r') as File: Counter = 0 for line in File: if Counter < 5: pass else: line = line.split() lat = float(line[0]) lon = float(line[1]) ele = float(line[2]) speed = float(line[3]) course = float(line[4]) time = line[5] Point = [lat,lon,ele,speed,course,time] qgsPoint = QgsPoint(lon,lat) self.Polyline.append(qgsPoint) self.GPXList.append(Point) Counter = Counter + 1 self.GpsLayer = QgsVectorLayer("LineString?crs=epsg:4326", self.videoFile.split('.')[-2].split('/')[-1], "memory") self.pr = self.GpsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolyline(self.Polyline)) self.pr.addFeatures([feat]) self.GpsLayer.updateExtents() if self.DB != None: try: self.DBLayer = QgsVectorLayer(self.DB,self.DB.split('.')[-2].split('/')[-1],'ogr') QgsProject.instance().addMapLayers([self.DBLayer,self.GpsLayer]) self.AddPointMapTool = AddPointTool(self.Main.iface.mapCanvas(),self.DBLayer,self) self.toolButton_6.clicked.connect(self.AddPointTool) self.toolButton_6.setEnabled(True) except: ret = QMessageBox.warning(self, "Warning", str(self.DB)+' is not a valid shapefile.', QMessageBox.Ok) return else: QgsProject.instance().addMapLayers([self.GpsLayer]) self.duration = len(self.GPXList) self.ExtractToB = self.duration self.horizontalSlider.setSingleStep(1000) self.horizontalSlider.setMinimum(0) self.horizontalSlider.setMaximum(len(self.GPXList)*1000) url = QUrl.fromLocalFile(str(self.videoFile)) mc = QMediaContent(url) self.player.setMedia(mc) self.player.setPosition(self.StartMsecond) self.player.play() self.horizontalSlider.sliderMoved.connect(self.setPosition) self.player.stateChanged.connect(self.mediaStateChanged) self.player.positionChanged.connect(self.positionChanged) self.pushButton_3.clicked.connect(self.MapTool) self.skiptracktool = SkipTrackTool( self.Main.iface.mapCanvas(),self.GpsLayer , self) def AddPointTool(self): self.Main.iface.mapCanvas().setMapTool(self.AddPointMapTool) def MapTool(self): if self.EnableMapTool == False: self.Main.iface.mapCanvas().setMapTool(self.skiptracktool) self.pushButton_3.setChecked(True) self.EnableMapTool = True else: self.Main.iface.mapCanvas().unsetMapTool(self.skiptracktool) self.pushButton_3.setChecked(False) self.EnableMapTool = False def closeEvent(self, *args, **kwargs): try: self.player.stop() self.Main.iface.mapCanvas().scene().removeItem(self.positionMarker) self.CancelVertex() self.Main.pushButton_2.show() #self.Main.horizontalSpacer_2.show() self.Main.groupBox.hide() self.Main.pushButton_8.show() self.Main.groupBox_4.show() self.dockWidget_2.close() except: pass return QtWidgets.QWidget.closeEvent(self, *args, **kwargs) def mediaStateChanged(self, state): if self.player.state() == QMediaPlayer.PlayingState: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPause)) else: self.playButton.setIcon( self.style().standardIcon(QStyle.SP_MediaPlay)) def setPosition(self, position): self.player.setPosition(position+self.StartMsecond) def secTotime(self,seconds): m, s = divmod(seconds, 60) h, m = divmod(m, 60) return "%d:%02d:%02d" % (h, m, s) def positionChanged(self, progress): if progress < self.StartMsecond: self.player.setPosition(self.StartMsecond) progress = self.StartMsecond AssociatedGps = round((progress - self.StartMsecond )/1000) self.DisplayPoint(AssociatedGps) totalTime = self.secTotime(self.duration) actualTime = self.secTotime((progress - self.StartMsecond )/1000) self.replayPosition_label.setText(actualTime + ' / '+totalTime) if not self.horizontalSlider.isSliderDown(): self.horizontalSlider.setValue(progress - self.StartMsecond ) def DisplayPoint(self,Point): if Point >= len(self.GPXList): Point = len(self.GPXList) - 1 gpx = self.GPXList[Point] lat = round(gpx[0],7) lon = round(gpx[1],7) ele = gpx[2] speed = gpx[3] course = gpx[4] time = gpx[5] Point = QgsPointXY() Point.set(lon, lat) canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) self.positionMarker.setHasPosition(True) self.Point = xform.transform(Point) self.positionMarker.newCoords(self.Point) self.positionMarker.angle = float(course) extent = canvas.extent() boundaryExtent=QgsRectangle(extent) boundaryExtent.scale(0.7) if not boundaryExtent.contains(QgsRectangle(Point, self.Point)): extentCenter= self.Point newExtent=QgsRectangle( extentCenter.x()-extent.width()/2, extentCenter.y()-extent.height()/2, extentCenter.x()+extent.width()/2, extentCenter.y()+extent.height()/2 ) self.Main.iface.mapCanvas().setExtent(newExtent) self.Main.iface.mapCanvas().refresh() self.Main.label_14.setText('GPS Time: '+str(time)) self.Main.label_15.setText('Course: '+"%.2f" % (course)) self.Main.label_16.setText('Ele: '+"%.2f" %(ele)) self.Main.label_17.setText('Speed m/s: '+"%.2f" %(speed)) self.Main.label_19.setText('Lat : '+str(lat)) self.Main.label_18.setText('Lon : '+str(lon)) def MuteUnmute(self): if self.player.mediaStatus() == 6 : if self.player.isMuted() == 1: self.player.setMuted(0) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolume)) elif self.player.isMuted() == 0: self.player.setMuted(1) self.muteButton.setIcon( self.style().standardIcon(QStyle.SP_MediaVolumeMuted)) def SkipForward(self): position = self.player.position() self.player.setPosition(position+1000) def SkipBackward(self): position = self.player.position() self.player.setPosition(position-1000) def ForwardFrame(self): position = self.player.position() self.player.setPosition(position+int(self.fps)) def BackwardFrame(self): position = self.player.position() self.player.setPosition(position-int(self.fps)) def PlayPause(self): if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() else: self.player.play() def findNearestPointInRecording(self, x,y): ClickPt = QgsPoint(x,y) Low = ClickPt.distanceSquared(self.Polyline[0]) NearPoint = 0 Counter = 0 for Point in self.Polyline: dist = ClickPt.distanceSquared(Point) if dist < Low: Low = dist NearPoint = Counter Counter = Counter + 1 else: Counter = Counter + 1 self.setPosition(NearPoint*1000) def ExtractSingleFrameOnTime(self, pos, outputfile): if os.name == 'nt': ffmpeg = ('"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"') os.popen(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str('"' +self.videoFile+ '"')+ ' -t 1 '+str('"'+outputfile+'"')) else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' os.system(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str(self.videoFile)+' -t 1 '+str(outputfile)) def AddPoint(self,x,y): self.Main.iface.mapCanvas().unsetMapTool(self.AddPointMapTool) Point = QgsPointXY(x,y) pos = self.player.position() if self.player.state() == QMediaPlayer.PlayingState: self.player.pause() a = self.DBLayer.name() last_desc = '///' LayerName =str(a) last_desc2 = LayerName + ' Point N ' directory = str(self.DB.split('.')[0])+'_Image/' if not os.path.exists(directory): os.makedirs(directory) fc = int(self.DBLayer.featureCount()) self.ExtractSingleFrameOnTime(pos,directory+LayerName+'_'+str(fc)+'_.jpg') fields = self.DBLayer.fields() attributes = [] lat,lon = Point.y(), Point.x() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon(WGS84)': attributes.append(str(lon)) elif a == 'Lat(WGS84)': attributes.append(str(lat)) elif a == 'Image link': attributes.append(str(directory+LayerName+'_'+str(fc)+'_.jpg')) else: if b == 'String': (a,ok) = QInputDialog.getText( self.Main.iface.mainWindow(), "Attributes", a + ' = String', QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a,ok) = QInputDialog.getDouble( self.Main.iface.mainWindow(), "Attributes", a + ' = Real', decimals = 10) attributes.append(a) elif b == 'Integer64': (a,ok) = QInputDialog.getInt( self.Main.iface.mainWindow(), "Attributes", a + ' = Integer') attributes.append(a) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) self.DBLayer.startEditing() self.DBLayer.addFeature(feature) self.DBLayer.commitChanges() self.DBLayer.triggerRepaint() def ExtractCommand(self): if self.ExtractToB <= self.ExtractFromA: ret = QMessageBox.warning(self, "Warning", '"To B" point must be after "from A" point', QMessageBox.Ok) self.CancelVertex() else: if os.name == 'nt': ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"' else: ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg' Directory,_ = QFileDialog.getSaveFileName(caption= 'Save georeferenced images') if Directory: self.progressBar.show() self.progressBar.setValue(0) start = self.ExtractFromA if self.comboBox_6.currentText() == 'seconds': finish = self.ExtractToB - self.ExtractFromA fps = self.doubleSpinBox_2.value() if fps < 1.0: fps = 1.0 / fps elif fps > 1: fps = 1.0 / fps if os.name == 'nt': os.popen(str(ffmpeg+ ' -ss ' + str(start) + ' -i '+ str('"'+self.videoFile+'"')+ ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + '"'+Directory + '_%d.png'+'"')) else: os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + Directory + '_%d.png') else: txtGPSFile = open(Directory + 'UTM_Coordinates.txt', 'w') txtGPSFile.close() txtGPSFile = open(Directory+ 'UTM_Coordinates.txt', 'a') txtGPSFile.write('filename # East UTM # North UTM # Ele '+ '\n') finish = self.ExtractToB meters = self.doubleSpinBox_2.value() Timerange = range(start, finish + 1) RemainToUseMeterTotal = 0 if os.name == 'nt': os.popen(ffmpeg+' -ss '+ str(start) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' + '"'+Directory + '_sec_' + str(start)+'.00.png'+'"') else: os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(start)+'.00.png') lonUTM, latUTM,quotainutile = self.transform_wgs84_to_utm(float(self.GPXList[start][1]) , float(self.GPXList[start][0])) ele = float(self.GPXList[start][2]) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(start)+'.00.png,'+' '+ str(lonUTM) + ', '+ str(latUTM) + ', ' + str(ele) + '\n') for i in Timerange: progessBarValue = ((i-start) * 100) // len(Timerange) self.progressBar.setValue(int(progessBarValue)) latitude1,longitude1 = float(self.GPXList[i][0]) ,float(self.GPXList[i][1]) latitude2,longitude2 = float(self.GPXList[i+1][0]) ,float(self.GPXList[i+1][1]) ele1 = float(self.GPXList[i][2]) ele2 = float(self.GPXList[i+1][2]) Calculus = Geodesic.WGS84.Inverse(latitude1, longitude1, latitude2, longitude2) DistanceBetweenPoint = Calculus['s12'] Azimuth = Calculus['azi2'] SpeedMeterSecond = DistanceBetweenPoint #GPS refresh rate is actually 1, change parameter for different rates # Time = 1 if RemainToUseMeterTotal == 0: if DistanceBetweenPoint >= meters: decimalSecondToAdd = meters / DistanceBetweenPoint RemainToUseMeter = DistanceBetweenPoint - meters if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') while RemainToUseMeter > meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') if RemainToUseMeter == meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' +str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') RemainToUseMeterTotal = 0 elif RemainToUseMeter < meters: RemainToUseMeterTotal = RemainToUseMeter pass else: RemainToUseMeterTotal = meters - DistanceBetweenPoint elif RemainToUseMeterTotal > 0: if DistanceBetweenPoint >= (meters - RemainToUseMeterTotal) : decimalSecondToAdd = (meters - RemainToUseMeterTotal) / DistanceBetweenPoint RemainToUseMeter = DistanceBetweenPoint - (meters - RemainToUseMeterTotal) if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') while RemainToUseMeter > meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') if RemainToUseMeter == meters: decimalSecondToAddMore = meters / SpeedMeterSecond RemainToUseMeter = RemainToUseMeter - meters decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore if os.name == 'nt': os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"') else: os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png') CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] ) Z = ele1 + decimalSecondToAdd*(ele2 - ele1) txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n') RemainToUseMeterTotal = 0 elif RemainToUseMeter < meters: RemainToUseMeterTotal = RemainToUseMeter else: RemainToUseMeterTotal = (meters - DistanceBetweenPoint) + RemainToUseMeterTotal txtGPSFile.close() self.progressBar.hide() def ExtractFromA(self): if self.ExtractA == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex) self.ExtractA = False self.ExtractFromA = round((self.player.position()- self.StartMsecond )/1000) canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) latitude,longitude = self.Polyline[self.ExtractFromA].y(), self.Polyline[self.ExtractFromA].x() self.ExtractAVertex = QgsVertexMarker(canvas) self.ExtractAVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude))) self.ExtractAVertex.setColor(QColor(0,255,0)) self.ExtractAVertex.setIconSize(10) self.ExtractAVertex.setIconType(QgsVertexMarker.ICON_X) self.ExtractAVertex.setPenWidth(10) self.ExtractA = True if self.ExtractB == True: self.pushButtonCut_2.setEnabled(True) else: self.pushButtonCut_2.setEnabled(False) def ExtractToB(self): if self.ExtractB == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex) self.ExtractB = False self.ExtractToB = round((self.player.position()- self.StartMsecond )/1000) if self.ExtractA == True: if self.ExtractToB > self.ExtractFromA: canvas = self.Main.iface.mapCanvas() crsSrc = QgsCoordinateReferenceSystem(4326) # .gpx is in WGS 84 crsDest = QgsProject.instance().crs() xform = QgsCoordinateTransform(crsSrc, crsDest) latitude,longitude = self.Polyline[self.ExtractToB].y(), self.Polyline[self.ExtractToB].x() self.ExtractBVertex = QgsVertexMarker(canvas) self.ExtractBVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude))) self.ExtractBVertex.setColor(QColor(255,0,0)) self.ExtractBVertex.setIconSize(10) self.ExtractBVertex.setIconType(QgsVertexMarker.ICON_X) self.ExtractBVertex.setPenWidth(10) self.ExtractB = True self.pushButtonCut_2.setEnabled(True) else: self.pushButtonCut_2.setEnabled(False) def CancelVertex(self): if self.ExtractA == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex) self.ExtractA = False if self.ExtractB == True: self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex) self.ExtractB = False self.pushButtonCut_2.setEnabled(False) def ExtractToolbar(self): if self.ExtractTool == 0: self.dockWidget_4.show() self.ExtractTool = 1 else: self.dockWidget_4.hide() self.ExtractTool = 0 def transform_wgs84_to_utm(self, lon, lat): def get_utm_zone(longitude): return (int(1+(longitude+180.0)/6.0)) def is_northern(latitude): """ Determines if given latitude is a northern for UTM """ if (latitude < 0.0): return 0 else: return 1 utm_coordinate_system = osr.SpatialReference() utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat)) wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>) return wgs84_to_utm_transform.TransformPoint(lon, lat, 0) # returns easting, northing, altitude
class trackGps: def __init__(self, iface): # Save reference to the QGIS interface self.globalpath = os.path.dirname(os.path.abspath(__file__)) self.iface = iface self.guiStarted = False # signal to destructor that this isn't actually been displayed yet self.read = ReadGpsd(self.iface) # create dock widget from ui file print os.path.join(self.globalpath,"DockWidget.ui") self.dock = uic.loadUi(os.path.join(self.globalpath,"DockWidget.ui")) self.canvas = self.iface.mapCanvas() # Default options self.GPSSettings = QSettings() # indication that this is the first time for the plugin self.firstTime = self.GPSSettings.value("trackGpsGPSSettings/firstTime", True, type=bool) # index of marker for GPS position (this is the arrow) self.markerNumber = self.GPSSettings.value("trackGpsGPSSettings/markerNumber", 0, type=int) # default is black for marker fill color self.markerFillColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/markerFillColor", QColor(0,0,0))) # default is yellow for marker outline color self.markerOutlineColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/markerOutlineColor", QColor(255,255,0))) # width of tracking line self.trackLineWidth = self.GPSSettings.value("trackGpsGPSSettings/trackLineWidth", 3, type=int) # color of tracking line (default is red) self.lineColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/lineColor", QColor(255,0,0))) self.saveInSHAPEFile = self.GPSSettings.value("trackGpsGPSSettings/saveInSHAPEFile", False, type=bool) # now recover/set the values for the serial port connection self.searchAllConnectionsSpeeds = self.GPSSettings.value("trackGpsGPSSettings/searchAllConnectionsSpeeds", True, type=bool) self.serialPortNumber = self.GPSSettings.value("trackGpsGPSSettings/serialPortNumber", 0, type=int) self.serialPortSpeed = self.GPSSettings.value("trackGpsGPSSettings/serialPortSpeed", 0, type=int) # set GPS connection values if they were recovered from a previous session if not self.searchAllConnectionsSpeeds: self.read.setConnectionValues(self.serialPortNumber, self.serialPortSpeed) # initialize the graphic elements for the GPS position self.positionMarker = PositionMarker(self.canvas, self.markerNumber, self.markerFillColor, self.markerOutlineColor) self.rubberBand = QgsRubberBand(self.canvas) self.rubberBand.setColor(self.lineColor) self.rubberBand.setWidth(self.trackLineWidth) self.rubberBandS = [] self.GPSPositions = [] # array of positions in current track self.GPSTracks = [] # array of all tracks def __del__(self): if self.guiStarted: # time to save plugin options as settings GPSSettings = QSettings() # indication that this is the first time for the plugin GPSSettings.setValue("trackGpsGPSSettings/firstTime", self.firstTime) GPSSettings.setValue("trackGpsGPSSettings/searchAllConnectionsSpeeds", bool(self.searchAllConnectionsSpeeds)) GPSSettings.setValue("trackGpsGPSSettings/markerNumber", self.markerNumber) GPSSettings.setValue("trackGpsGPSSettings/markerFillColor", self.markerFillColor) GPSSettings.setValue("trackGpsGPSSettings/markerOutlineColor", self.markerOutlineColor) GPSSettings.setValue("trackGpsGPSSettings/trackLineWidth", self.trackLineWidth) GPSSettings.setValue("trackGpsGPSSettings/lineColor", self.lineColor) GPSSettings.setValue("trackGpsGPSSettings/saveInSHAPEFile", self.saveInSHAPEFile) GPSSettings.setValue("trackGpsGPSSettings/serialPortNumber", self.serialPortNumber) GPSSettings.setValue("trackGpsGPSSettings/serialPortSpeed", self.serialPortSpeed) GPSSettings.synch() QMessageBox.information(self.iface.mainWindow(),"Class trackGPS Ending","trackGPS is being destroyed!") def initGui(self): self.guiStarted = True # signal that the GPS dialog was displayed if self.firstTime: self.firstTime = False QMessageBox.information(self.iface.mainWindow(),"Track GPS location","Since this is the first time"+\ " that you have used the 'Track GPS location' plugin please consult the help "+\ "in the plugin menu") # Create actions for plugin self.actionStart = QAction(QIcon(":/plugins/trackgps/Satellite-22.png"), "Start GPS Tracking", self.iface.mainWindow()) self.actionStart.setWhatsThis("Open GPS Connection and Start Tracking") self.actionStop = QAction(QIcon(":/plugins/trackgps/Satellite-22.png"), "Stop GPS Tracking", self.iface.mainWindow()) self.actionStop.setWhatsThis("Close the GPS Connection and Stop Tracking") self.actionOptions = QAction(QIcon(":/plugins/trackgps/options.png"),"Set GPS Tracking Options", self.iface.mainWindow()) self.actionOptions.setWhatsThis("Set the various GPS Connection/Tracking Options") # add help menu item self.helpAction = QAction(QIcon(":/plugins/trackgps/images/help-browser.png"), "GPS Tracking Help", self.iface.mainWindow()) # New Track actions set up here self.dock.btnStartNewTrack.setDisabled(True) # Starting New Tracks is disabled at start QObject.connect(self.dock.btnStartNewTrack, SIGNAL("clicked()"), self.startNewTrack) # Connect the actions to its methods QObject.connect(self.actionStart, SIGNAL("activated()"), self.toogleGather) QObject.connect(self.actionStop, SIGNAL("activated()"), self.toogleGather) QObject.connect(self.actionOptions, SIGNAL("activated()"), self.showGPSMenuOptions) QObject.connect(self.dock.btnStart, SIGNAL("clicked()"), self.toogleGather) QObject.connect(self.read, SIGNAL("readCoords(PyQt_PyObject)"), self.setCoords) QObject.connect(self.read, SIGNAL("connectionFailed(PyQt_PyObject)"), self.connectionFailed) QObject.connect(self.read, SIGNAL("connectionMade()"), self.connectionMade) QObject.connect(self.helpAction, SIGNAL("activated()"), self.helpWindow) # Add menu items for action self.iface.addPluginToMenu("beeGPS", self.actionOptions) self.iface.addPluginToMenu("beeGPS", self.actionStart) self.iface.addPluginToMenu("beeGPS", self.helpAction) myPluginMenu = self.iface.pluginMenu() QObject.connect(myPluginMenu, SIGNAL("aboutToShow()"), self.updateTrackGPSMenu) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock) def helpWindow(self): window = HelpForm("TheQGISGPSTrackerPlugin.html",self.iface.mainWindow()) window.show() def updateTrackGPSMenu(self): if self.read.running: self.iface.addPluginToMenu("beeGPS", self.actionStop) self.iface.removePluginMenu("beeGPS", self.actionStart) else: self.iface.addPluginToMenu("beeGPS", self.actionStart) self.iface.removePluginMenu("beeGPS", self.actionStop) def startNewTrack(self): self.read.stop() # close serial port self.rubberBandS.append(self.rubberBand) self.showGPSMenuOptions() # give user opportunity to change display options #if len(self.GPSPositions) > 0: # temporary section to display positional information # QMessageBox.information(self.iface.mainWindow(),"trackGPS","There are: " + str(len(self.GPSPositions)) + " GPS Positions in the current track") # for i in range(len(self.GPSPositions)): # QMessageBox.information(self.iface.mainWindow(),"trackGPS","Position #" + str(i) + ": Latitude=" + str(self.GPSPositions[i].latitude)) self.rubberBand=QgsRubberBand(self.canvas) # start new rubber band if len(self.GPSPositions) > 0 and self.saveInSHAPEFile: self.GPSTracks.append(self.GPSPositions) # save GPSPositions to GPSTracks self.GPSPositions = [] #reset of array contenent the current position self.startGather() # open serial port and record new track def unload(self): # Remove the plugin menu item self.iface.removePluginMenu("beeGPS", self.actionStart) self.iface.removePluginMenu("beeGPS", self.actionStop) self.iface.removePluginMenu("beeGPS", self.actionOptions) def startGather(self): #update all of the GPS display options self.positionMarker.markerNumber = self.markerNumber self.positionMarker.fillColor = self.markerFillColor self.positionMarker.outlineColor = self.markerOutlineColor self.rubberBand.setColor(self.lineColor) self.rubberBand.setWidth(self.trackLineWidth) self.positionMarker.show() # get destination crs of the canvas dest_crs = self.canvas.mapRenderer().destinationCrs() #print "destination crs:",dest_crs.description() # create transform object from WGS84 (GPS) to canvas CRS self.transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem(self.read.session.datumEPSG,\ QgsCoordinateReferenceSystem.EpsgCrsId ),dest_crs) self.read.start() self.read.exec_() def setCoords(self, aGPSPosition): boolDistance = True boolTime = True #Controllo se è la prima acquisizione valutando la dimensione di GPSPosition[] a 0, in caso positivo acquisisco. if len(self.GPSPositions) == 0: self.GPSPositions.append(aGPSPosition) else: #Metodo tresholdAcquisition() per l'acquisizione dei punti "live" in base alla soglia di distanza che ritorna #TRUE in caso la soglia sia stata superata, altrimenti FALSE boolDistance = self.tresholdAcquisition(aGPSPosition) #Controllo che tresholdAcquisition() abbia ritornato TRUE altrimenti passo al punto successivo if boolDistance == False: return #Metodo timeIntervals() per l'acquisizione dei punti "live" in base alla soglia di tempo che ritorna TRUE in caso #la soglia sia stata superata e acquisita, altrimenti FALSE boolTime = self.timeIntervals(aGPSPosition) #Controllo che timeIntervals() abbia ritornato TRUE altrimenti passo al punto successivo if boolTime == False: return else: self.GPSPositions.append(aGPSPosition) # display raw values self.dock.date.setText(aGPSPosition.theDateTime) self.dock.lat.setText(str(aGPSPosition.latitude) + ' ' + aGPSPosition.latitudeNS) self.dock.lon.setText(str(aGPSPosition.longitude) + ' ' + aGPSPosition.longitudeEW) self.dock.lineBearing.setText("%5.1i"%aGPSPosition.bearing) self.dock.lineSpeed.setText("%5.1i"%aGPSPosition.speed) self.dock.lineHDOP.setText(str(aGPSPosition.hdop)) if aGPSPosition.fixQuality == 0: self.dock.lineQuality.setText("Fix not available") elif aGPSPosition.fixQuality == 1: self.dock.lineQuality.setText("GPS fix") else: self.dock.lineQuality.setText("Differential GPS fix") # display arrow on the map latitude = aGPSPosition.latitude if aGPSPosition.latitudeNS == 'N' else aGPSPosition.latitude * -1.0 longitude = aGPSPosition.longitude if aGPSPosition.longitudeEW == 'E' else aGPSPosition.longitude * -1.0 p=self.transform.transform(QgsPoint(longitude, latitude)) self.rubberBand.addPoint(p) self.positionMarker.setHasPosition(True) self.positionMarker.newCoords(p,aGPSPosition.bearing) doRefresh = False if doRefresh: # move map to keep marker at center curext = self.canvas.extent() p1 = QgsPoint(p.x() - curext.width()/2, p.y() - curext.height()/2) p2 = QgsPoint(p.x() + curext.width()/2, p.y() + curext.height()/2) self.canvas.setExtent(QgsRectangle (p1,p2)) self.canvas.refresh() def stopGather(self): self.read.stop() self.positionMarker.hide() if len(self.GPSPositions) > 0: # and self.saveInSHAPEFile: self.GPSTracks.append(self.GPSPositions) # save GPSPositions to GPSTracks # if len(self.GPSTracks) > 0 and self.saveInSHAPEFile: if self.saveInSHAPEFile: # this is temporary # option to save SHAPE file is on, prompt for filename and write the tracks to the file self.makeShapeFiles() if len(self.GPSTracks) > 0: answer = QMessageBox.question(self.iface.mainWindow(),"Erase Tracks?","Erase the currently displayed tracks?",\ QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if answer == QMessageBox.Yes: for band in self.rubberBandS: band.reset() self.rubberBand.reset() self.canvas.refresh() self.rubberBandS = [] self.GPSPositions = [] self.GPSTracks = [] def toogleGather(self): if self.read.running: QMessageBox.information(self.iface.mainWindow(),"GPS Tracker","Stopping GPS Tracking",QMessageBox.Ok) self.stopGather() self.dock.btnStart.setText("Start") self.dock.gpsInformation.setText("Gets GPS Receiver Information") self.dock.btnStartNewTrack.setDisabled(True) else: self.dock.btnStart.setText("Connecting, please be patient....") self.startGather() if self.read.session.connected: self.dock.btnStart.setText("Stop") def connectionMade(self): # QMessageBox.information(self.iface.mainWindow(),"trackGps","GPS Receiver Connected on port: %s at %i baud\n"%\ # (self.read.session.portName,self.read.session.baudRate),QMessageBox.Ok,0) self.dock.gpsInformation.setText("GPS Connected on port: %s at %i baud"%(self.read.session.portName,\ self.read.session.baudRate)) self.dock.btnStart.setText("Stop") self.dock.btnStartNewTrack.setDisabled(False) # save connection values in session parameters self.serialPortNumber = self.read.session.port self.serialPortSpeed = self.read.session.baudRates.index(self.read.session.baudRate) self.searchAllConnectionsSpeeds = False def connectionFailed(self, msg): QMessageBox.warning(self.iface.mainWindow(),"beeGPS", "Connection to GPSConnection failed\n%s"%(msg),QMessageBox.Ok,0) if self.read.session.connected: self.read.stop() self.dock.btnStart.setText("Start") self.dock.btnStartNewTrack.setDisabled(True) # Starting New Tracks is disabled at start def showGPSMenuOptions(self): myGPSOptionsDlg = GPSTrackerOptions(self) isOK = myGPSOptionsDlg.exec_() if isOK: if myGPSOptionsDlg.cbxMarkerType.currentIndex() != self.markerNumber: self.markerNumber = myGPSOptionsDlg.cbxMarkerType.currentIndex() if myGPSOptionsDlg.lineColor != self.lineColor: self.lineColor = myGPSOptionsDlg.lineColor if myGPSOptionsDlg.markerFillColor != self.markerFillColor: self.markerFillColor = myGPSOptionsDlg.markerFillColor if myGPSOptionsDlg.markerOutlineColor != self.markerOutlineColor: self.markerOutlineColor = myGPSOptionsDlg.markerOutlineColor if myGPSOptionsDlg.sbxTrackWidth.value() != self.trackLineWidth: self.trackLineWidth = myGPSOptionsDlg.sbxTrackWidth.value() if myGPSOptionsDlg.cbxSaveGPSTrack.isChecked() != self.saveInSHAPEFile: self.saveInSHAPEFile = myGPSOptionsDlg.cbxSaveGPSTrack.isChecked() def makeShapeFiles(self): myFileName = QgsProject.instance().fileName() myFileName = str(myFileName) # if this is a windows OS then the filename needs to have '/' converted to '\' if myFileName.find('windows') != 0 or myFileName.find('Windows') != 0: myFileName = os.path.normpath(myFileName) myFilePath = os.path.dirname(myFileName) myShapeFileNamesDlg = ShapeFileNames(myFilePath) isOK = myShapeFileNamesDlg.exec_() CRS = QgsCoordinateReferenceSystem() crsIsOk = CRS.createFromOgcWmsCrs("EPSG:%d" % self.GPSTracks[0][0].datumEPSG) if not crsIsOk: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating CRS from"+\ " EPSG ID:" + str(self.GPSTracks[0][0].datumEPSG)) if isOK and crsIsOk: if len(myShapeFileNamesDlg.lnePointsFileName.text()) > 0: # set up the fields for the Points SHAPE file box = QgsFields() box.append(QgsField("LATITUDE", QVariant.Double , "Real", 9, 6)) box.append(QgsField("LONGITUDE", QVariant.Double, "Real", 10, 6)) box.append(QgsField("NUMOFSATS", QVariant.Int, "Integer", 2, 0)) box.append(QgsField("HDOP", QVariant.Double, "Real", 4, 2)) box.append(QgsField("DATETIME", QVariant.String, "String", 19, 0)) box.append(QgsField("FIXTYPE", QVariant.String, "String", 1, 0)) box.append(QgsField("BEARING", QVariant.Double, "Real", 6, 2)) box.append(QgsField("SPEED-KPH", QVariant.Double, "Real", 5, 1)) box.append(QgsField("TRACKNUM", QVariant.Int, "Integer", 2, 0)) # set up the CRS # open the points SHAPE file pointsFile, fileOK = self.createSHAPEfile(myShapeFileNamesDlg.lnePointsFileName.text(),box,QGis.WKBPoint,CRS) if fileOK: for j in range(len(self.GPSTracks)): for i in range(len(self.GPSTracks[j])): theFeature = QgsFeature() latitude = self.GPSTracks[j][i].latitude if self.GPSTracks[j][i].latitudeNS == 'S': latitude = -latitude longitude = self.GPSTracks[j][i].longitude if self.GPSTracks[j][i].longitudeEW == 'W': longitude = -longitude theFeature.setGeometry(QgsGeometry.fromPoint(QgsPoint(longitude,latitude))) theFeature.setAttributes([0, latitude]) theFeature.setAttributes([1, longitude]) theFeature.setAttributes([2, self.GPSTracks[j][i].numSatellites]) theFeature.setAttributes([3, self.GPSTracks[j][i].hdop]) theFeature.setAttributes([4, self.GPSTracks[j][i].theDateTime]) theFeature.setAttributes([5, self.GPSTracks[j][i].fixQuality]) theFeature.setAttributes([6, self.GPSTracks[j][i].bearing]) theFeature.setAttributes([7, self.GPSTracks[j][i].speed]) theFeature.setAttributes([8, j+1]) pointsFile.addFeature(theFeature) del pointsFile # del file object to force a flush and close if len(myShapeFileNamesDlg.lneLinesFileName.text()) > 0: # set up the fields for the Lines SHAPE file lines_box = QgsFields() lines_box.append(QgsField("SDATETIME", QVariant.String, "String", 19, 0)) lines_box.append(QgsField("EDATETIME", QVariant.String, "String", 19, 0)) lines_box.append(QgsField("TRACKNUM", QVariant.Int, "Integer", 2, 0)) linesFile, fileOK = self.createSHAPEfile(myShapeFileNamesDlg.lneLinesFileName.text(),lines_box,QGis.WKBLineString,CRS) if fileOK: for j in range(len(self.GPSTracks)): theFeature = QgsFeature() pointsList = [] for i in range(len(self.GPSTracks[j])): latitude = self.GPSTracks[j][i].latitude if self.GPSTracks[j][i].latitudeNS == 'S': latitude = -latitude longitude = self.GPSTracks[j][i].longitude if self.GPSTracks[j][i].longitudeEW == 'W': longitude = -longitude pointsList.append(QgsPoint(longitude,latitude)) theFeature.setGeometry(QgsGeometry.fromPolyline(pointsList)) theFeature.setAttributes([0, self.GPSTracks[j][0].theDateTime]) theFeature.setAttributes([1, self.GPSTracks[j][len(self.GPSTracks[j])-1].theDateTime]) theFeature.setAttributes([2, j+1]) linesFile.addFeature(theFeature) del linesFile # del file object to force a flush and close def createSHAPEfile(self,fileName, fileFields, fileType, crs): ''' this function creates a new, empty shape file for use in writing points or lines Returns: SHAPEfile, status if status == True then SHAPEfile is OK to use, if False then an error occured and cannot use SHAPEFile Input Parameters: fileName = full name of the SHAPE file to be created fileFields = map of QgsFields to use for the attributes of the SHAPE file fileType = QGis.WKBPoint for points file <or> QGis.WKBLine for lines file crs = the QgsCoordinateReferenceSystem to use for the file ''' status = True # default is no error SHAPEfile = QgsVectorFileWriter(fileName,"CP1250",fileFields,fileType,crs) typeName = 'Points' if fileType == QGis.WKBPoint else 'Lines' if SHAPEfile.hasError() != QgsVectorFileWriter.NoError: status = False # report an error if SHAPEfile.hasError() == QgsVectorFileWriter.ErrDriverNotFound: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrDriverNotFound\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrCreateDataSource: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrCreateDataSource\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrCreateLayer: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrCreateLayer\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrAttributeTypeUnsupported: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrAttributeTypeUnsupported\' - saving " + typeName + " is aborted") else: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'UNKOWN ERROR\' saving " + typeName + " is aborted") return SHAPEfile,status #Metodo per l'acquisizione tramite soglia di distanza def tresholdAcquisition(self, aGPSPosition): #Costanti per il calcolo della distanza R_Terra = 6372.795477598 acquisito = False #Acquisisco la soglia di distanza, da input e la converto in float soglia = self.dock.lineTreshold.text() if not soglia.isnumeric(): self.read.stop() self.positionMarker.hide() self.dock.btnStart.setText("Start") self.dock.gpsInformation.setText("Gets GPS Receiver Information") QMessageBox.warning(self.iface.mainWindow(),"ATENZIONE","Inserire solo valori numerici nella soglia di distanza.") else: soglia = float(soglia) soglia = soglia / 1000 #Conversione dei gradi in radianti lat_alfa = math.radians(aGPSPosition.latitude) lat_beta = math.radians(self.GPSPositions[-1].latitude) lon_alfa = math.radians(aGPSPosition.longitude) lon_beta = math.radians(self.GPSPositions[-1].longitude) #Calcolo la differenza di lat e lon dLat = lat_alfa - lat_beta dLon = lon_alfa - lon_beta a = math.sin(dLat/2)*math.sin(dLat/2)+math.sin(dLon/2)*math.sin(dLon/2)* math.cos(lat_alfa) * math.cos(lat_beta) #Calcolo il terzo lato del triangolo sferico c = 2*math.atan2(math.sqrt(a),math.sqrt(1-a)) distanza = c * R_Terra #Controllo con la soglia di distanza e eventualmente acquisisco if distanza > soglia: acquisito = True return acquisito #Metodo timeIntervals() per il controllo della soglia temporale def timeIntervals(self, aGPSPosition): #Variabile booleana di ritorno acquisito = False #Stringa per il formato della data formato = '%Y-%m-%d %H:%M:%S' #Metto le due date, quella dell'ultima acquisizione e quella da valutare in due stringhe dataA = aGPSPosition.theDateTime dataB = self.GPSPositions[-1].theDateTime #Tramite il metodo time.strptime() realizziamo due strutte tempo per le due date struct_A = time.strptime(dataA,formato) struct_B = time.strptime(dataB,formato) #Otteniamo i valori di confronto confrontoA = datetime.datetime.fromtimestamp(time.mktime(struct_A)) confrontoB = datetime.datetime.fromtimestamp(time.mktime(struct_B)) #Otteniamo la differenza differenza = (confrontoA - confrontoB).seconds #Acquisisco la soglia di distanza temporale e gestisco eventualmente l'inserimento di valori non numerici intervalli = self.dock.lineTimeIntervals.text() if not intervalli.isnumeric(): self.read.stop() self.positionMarker.hide() self.dock.btnStart.setText("Start") self.dock.gpsInformation.setText("Gets GPS Receiver Information") QMessageBox.warning(self.iface.mainWindow(),"ATENZIONE","Inserire solo valori numerici nella soglia temporale.") else: intervalli = float(intervalli) #Controllo se la differenza e maggiore della soglia if differenza > intervalli: acquisito = True return acquisito
class trackGps: def __init__(self, iface): # Save reference to the QGIS interface self.globalpath = os.path.dirname(os.path.abspath(__file__)) self.iface = iface self.guiStarted = False # signal to destructor that this isn't actually been displayed yet self.read = ReadGpsd(self.iface) # create dock widget from ui file print os.path.join(self.globalpath,"DockWidget.ui") self.dock = uic.loadUi(os.path.join(self.globalpath,"DockWidget.ui")) self.canvas = self.iface.mapCanvas() # Default options self.GPSSettings = QSettings() # indication that this is the first time for the plugin self.firstTime = self.GPSSettings.value("trackGpsGPSSettings/firstTime",QVariant(bool(True))).toBool() # index of marker for GPS position (this is the arrow) self.markerNumber, isOK = self.GPSSettings.value("trackGpsGPSSettings/markerNumber",QVariant(int(0))).toInt() # default is black for marker fill color self.markerFillColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/markerFillColor",QVariant(QColor(0,0,0)))) # default is yellow for marker outline color self.markerOutlineColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/markerOutlineColor",QVariant(QColor(255,255,0)))) # width of tracking line self.trackLineWidth, isOK = self.GPSSettings.value("trackGpsGPSSettings/trackLineWidth",QVariant(int(3))).toInt() # color of tracking line (default is red) self.lineColor = QColor(self.GPSSettings.value("trackGpsGPSSettings/lineColor",QVariant(QColor(255,0,0)))) self.saveInSHAPEFile = self.GPSSettings.value("trackGpsGPSSettings/saveInSHAPEFile",QVariant(bool(False))).toBool() # now recover/set the values for the serial port connection self.searchAllConnectionsSpeeds = self.GPSSettings.value("trackGpsGPSSettings/searchAllConnectionsSpeeds", QVariant(bool(True))).toBool() self.serialPortNumber, isOK = self.GPSSettings.value("trackGpsGPSSettings/serialPortNumber",QVariant(int(0))).toInt() self.serialPortSpeed, isOK = self.GPSSettings.value("trackGpsGPSSettings/serialPortSpeed",QVariant(int(0))).toInt() # set GPS connection values if they were recovered from a previous session if not self.searchAllConnectionsSpeeds: self.read.setConnectionValues(self.serialPortNumber,self.serialPortSpeed) # initialize the graphic elements for the GPS position self.positionMarker=PositionMarker(self.canvas, self.markerNumber, self.markerFillColor, self.markerOutlineColor) self.rubberBand=QgsRubberBand(self.canvas) self.rubberBand.setColor(self.lineColor) self.rubberBand.setWidth(self.trackLineWidth) self.rubberBandS = [] self.GPSPositions = [] # array of positions in current track self.GPSTracks = [] # array of all tracks def __del__(self): """This method is used to save the settings for use the next time this plugin is used""" if self.guiStarted: # time to save plugin options as settings GPSSettings = QSettings() # indication that this is the first time for the plugin GPSSettings.setValue("trackGpsGPSSettings/firstTime",QVariant(self.firstTime)) GPSSettings.setValue("trackGpsGPSSettings/searchAllConnectionsSpeeds", QVariant(bool(self.searchAllConnectionsSpeeds))) GPSSettings.setValue("trackGpsGPSSettings/markerNumber",QVariant(self.markerNumber)) GPSSettings.setValue("trackGpsGPSSettings/markerFillColor",QVariant(self.markerFillColor)) GPSSettings.setValue("trackGpsGPSSettings/markerOutlineColor",QVariant(self.markerOutlineColor)) GPSSettings.setValue("trackGpsGPSSettings/trackLineWidth",QVariant(self.trackLineWidth)) GPSSettings.setValue("trackGpsGPSSettings/lineColor",QVariant(self.lineColor)) GPSSettings.setValue("trackGpsGPSSettings/saveInSHAPEFile",QVariant(self.saveInSHAPEFile)) GPSSettings.setValue("trackGpsGPSSettings/serialPortNumber",QVariant(self.serialPortNumber)) GPSSettings.setValue("trackGpsGPSSettings/serialPortSpeed",QVariant(self.serialPortSpeed)) GPSSettings.synch() QMessageBox.information(self.iface.mainWindow(),"Class trackGPS Ending","trackGPS is being destroyed!") def initGui(self): self.guiStarted = True # signal that the GPS dialog was displayed if self.firstTime: self.firstTime = False QMessageBox.information(self.iface.mainWindow(),"Track GPS location","Since this is the first time"+\ " that you have used the 'Track GPS location' plugin please consult the help "+\ "in the plugin menu") # Create actions for plugin self.actionStart = QAction(QIcon(":/plugins/trackgps/Satellite-22.png"), "Start GPS Tracking", self.iface.mainWindow()) self.actionStart.setWhatsThis("Open GPS Connection and Start Tracking") self.actionStop = QAction(QIcon(":/plugins/trackgps/Satellite-22.png"), "Stop GPS Tracking", self.iface.mainWindow()) self.actionStop.setWhatsThis("Close the GPS Connection and Stop Tracking") self.actionOptions = QAction(QIcon(":/plugins/trackgps/options.png"),"Set GPS Tracking Options", self.iface.mainWindow()) self.actionOptions.setWhatsThis("Set the various GPS Connection/Tracking Options") # add help menu item self.helpAction = QAction(QIcon(":/plugins/trackgps/images/help-browser.png"), "GPS Tracking Help", self.iface.mainWindow()) # New Track actions set up here self.dock.btnStartNewTrack.setDisabled(True) # Starting New Tracks is disabled at start QObject.connect(self.dock.btnStartNewTrack, SIGNAL("clicked()"), self.startNewTrack) # Connect the actions to its methods QObject.connect(self.actionStart, SIGNAL("activated()"), self.toogleGather) QObject.connect(self.actionStop, SIGNAL("activated()"), self.toogleGather) QObject.connect(self.actionOptions, SIGNAL("activated()"), self.showGPSMenuOptions) QObject.connect(self.dock.btnStart, SIGNAL("clicked()"), self.toogleGather) QObject.connect(self.read, SIGNAL("readCoords(PyQt_PyObject)"), self.setCoords) QObject.connect(self.read, SIGNAL("connectionFailed(PyQt_PyObject)"), self.connectionFailed) QObject.connect(self.read, SIGNAL("connectionMade()"), self.connectionMade) QObject.connect(self.helpAction, SIGNAL("activated()"), self.helpWindow) # Add menu items for action self.iface.addPluginToMenu("Track GPS location", self.actionOptions) self.iface.addPluginToMenu("Track GPS location", self.actionStart) self.iface.addPluginToMenu("Track GPS location", self.helpAction) myPluginMenu = self.iface.pluginMenu() QObject.connect(myPluginMenu, SIGNAL("aboutToShow()"), self.updateTrackGPSMenu) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock) def helpWindow(self): window = HelpForm("TheQGISGPSTrackerPlugin.html",self.iface.mainWindow()) window.show() def updateTrackGPSMenu(self): if self.read.running: self.iface.addPluginToMenu("Track GPS location", self.actionStop) self.iface.removePluginMenu("Track GPS location", self.actionStart) else: self.iface.addPluginToMenu("Track GPS location", self.actionStart) self.iface.removePluginMenu("Track GPS location", self.actionStop) def startNewTrack(self): self.read.stop() # close serial port self.rubberBandS.append(self.rubberBand) self.showGPSMenuOptions() # give user opportunity to change display options #if len(self.GPSPositions) > 0: # temporary section to display positional information # QMessageBox.information(self.iface.mainWindow(),"trackGPS","There are: " + str(len(self.GPSPositions)) + " GPS Positions in the current track") # for i in range(len(self.GPSPositions)): # QMessageBox.information(self.iface.mainWindow(),"trackGPS","Position #" + str(i) + ": Latitude=" + str(self.GPSPositions[i].latitude)) self.rubberBand=QgsRubberBand(self.canvas) # start new rubber band if len(self.GPSPositions) > 0 and self.saveInSHAPEFile: self.GPSTracks.append(self.GPSPositions) # save GPSPositions to GPSTracks self.GPSPositions = [] self.startGather() # open serial port and record new track def unload(self): # Remove the plugin menu item self.iface.removePluginMenu("Track GPS location", self.actionStart) self.iface.removePluginMenu("Track GPS location", self.actionStop) self.iface.removePluginMenu("Track GPS location", self.actionOptions) def startGather(self): #update all of the GPS display options self.positionMarker.markerNumber = self.markerNumber self.positionMarker.fillColor = self.markerFillColor self.positionMarker.outlineColor = self.markerOutlineColor self.rubberBand.setColor(self.lineColor) self.rubberBand.setWidth(self.trackLineWidth) self.positionMarker.show() # get destination crs of the canvas dest_crs = self.canvas.mapRenderer().destinationSrs() print "destination crs:",dest_crs.description() # create transform object from WGS84 (GPS) to canvas CRS self.transform = QgsCoordinateTransform(QgsCoordinateReferenceSystem(self.read.session.datumEPSG,\ QgsCoordinateReferenceSystem.EpsgCrsId ),dest_crs) self.read.start() self.read.exec_() def setCoords (self,aGPSPosition): """SLOT: show read coordinates""" # display raw values self.GPSPositions.append(aGPSPosition) self.dock.date.setText(aGPSPosition.theDateTime) self.dock.lat.setText(str(aGPSPosition.latitude) + ' ' + aGPSPosition.latitudeNS) self.dock.lon.setText(str(aGPSPosition.longitude) + ' ' + aGPSPosition.longitudeEW) self.dock.lineBearing.setText("%5.1i"%aGPSPosition.bearing) self.dock.lineSpeed.setText("%5.1i"%aGPSPosition.speed) # display arrow on the map latitude = aGPSPosition.latitude if aGPSPosition.latitudeNS == 'N' else aGPSPosition.latitude * -1.0 longitude = aGPSPosition.longitude if aGPSPosition.longitudeEW == 'E' else aGPSPosition.longitude * -1.0 p=self.transform.transform(QgsPoint(longitude, latitude)) self.rubberBand.addPoint(p) self.positionMarker.setHasPosition(True) self.positionMarker.newCoords(p,aGPSPosition.bearing) # move map to keep marker at center curext = self.canvas.extent() p1 = QgsPoint(p.x()-curext.width()/2,p.y()-curext.height()/2) p2 = QgsPoint(p.x()+curext.width()/2,p.y()+curext.height()/2) self.canvas.setExtent(QgsRectangle (p1,p2)) self.canvas.refresh() def stopGather(self): self.read.stop() self.positionMarker.hide() if len(self.GPSPositions) > 0: # and self.saveInSHAPEFile: self.GPSTracks.append(self.GPSPositions) # save GPSPositions to GPSTracks # if len(self.GPSTracks) > 0 and self.saveInSHAPEFile: if self.saveInSHAPEFile: # this is temporary # option to save SHAPE file is on, prompt for filename and write the tracks to the file # QMessageBox.information(self.iface.mainWindow(),"trackGPS","There are: " + str(len(self.GPSTracks)) + " GPS tracks in the current track") # for j in range(len(self.GPSTracks)): # QMessageBox.information(self.iface.mainWindow(),"trackGPS","In track #" + str(j) + " There are: " + str(len(self.GPSTracks[j])) + " GPS Positions") # for i in range(len(self.GPSTracks[j])): # QMessageBox.information(self.iface.mainWindow(),"trackGPS","Position #" + str(i) + ": Latitude=" + str(self.GPSTracks[j][i].latitude)) self.makeShapeFiles() if len(self.GPSTracks) > 0: answer = QMessageBox.question(self.iface.mainWindow(),"Erase Tracks?","Erase the currently displayed tracks?",\ QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if answer == QMessageBox.Yes: for band in self.rubberBandS: band.reset() self.rubberBand.reset() self.canvas.refresh() self.rubberBandS = [] self.GPSPositions = [] self.GPSTracks = [] def toogleGather(self): if self.read.running: QMessageBox.information(self.iface.mainWindow(),"GPS Tracker","Stopping GPS Tracking",QMessageBox.Ok) self.stopGather() self.dock.btnStart.setText("Start") self.dock.gpsInformation.setText("Gets GPS Receiver Information") self.dock.btnStartNewTrack.setDisabled(True) else: self.dock.btnStart.setText("Connecting, please be patient....") self.startGather() if self.read.session.connected: self.dock.btnStart.setText("Stop") def connectionMade(self): # QMessageBox.information(self.iface.mainWindow(),"trackGps","GPS Receiver Connected on port: %s at %i baud\n"%\ # (self.read.session.portName,self.read.session.baudRate),QMessageBox.Ok,0) self.dock.gpsInformation.setText("GPS Connected on port: %s at %i baud"%(self.read.session.portName,\ self.read.session.baudRate)) self.dock.btnStart.setText("Stop") self.dock.btnStartNewTrack.setDisabled(False) # save connection values in session parameters self.serialPortNumber = self.read.session.port self.serialPortSpeed = self.read.session.baudRates.index(self.read.session.baudRate) self.searchAllConnectionsSpeeds = False def connectionFailed(self,msg): QMessageBox.warning(self.iface.mainWindow(),"trackGps","Connection to GPSConnection failed\n%s"%(msg),QMessageBox.Ok,0) if self.read.session.connected: self.read.stop() self.dock.btnStart.setText("Start") self.dock.btnStartNewTrack.setDisabled(True) # Starting New Tracks is disabled at start def showGPSMenuOptions(self): """ Function to handle all GPS Tracking Options """ # myGPSOptionsDlg = GPSTrackerOptions(self) isOK = myGPSOptionsDlg.exec_() if isOK: if myGPSOptionsDlg.cbxMarkerType.currentIndex() != self.markerNumber: self.markerNumber = \ myGPSOptionsDlg.cbxMarkerType.currentIndex() if myGPSOptionsDlg.lineColor != self.lineColor: self.lineColor = myGPSOptionsDlg.lineColor if myGPSOptionsDlg.markerFillColor != self.markerFillColor: self.markerFillColor = \ myGPSOptionsDlg.markerFillColor if myGPSOptionsDlg.markerOutlineColor != self.markerOutlineColor: self.markerOutlineColor = \ myGPSOptionsDlg.markerOutlineColor if myGPSOptionsDlg.sbxTrackWidth.value() != self.trackLineWidth: self.trackLineWidth = \ myGPSOptionsDlg.sbxTrackWidth.value() if myGPSOptionsDlg.cbxSaveGPSTrack.isChecked() != self.saveInSHAPEFile: self.saveInSHAPEFile =\ myGPSOptionsDlg.cbxSaveGPSTrack.isChecked() def makeShapeFiles(self): """ Function to save data to SHAPE files """ myFileName = QgsProject.instance().fileName() myFileName = str(myFileName) # if this is a windows OS then the filename needs to have '/' converted to '\' if myFileName.find('windows') != 0 or myFileName.find('Windows') != 0: myFileName = os.path.normpath(myFileName) myFilePath = os.path.dirname(myFileName) #mymessage = 'QGIS Project Pathname=\'' + myFilePath + '\'' #QMessageBox.information(self.iface.mainWindow(),"trackGps",mymessage,QMessageBox.Ok) myShapeFileNamesDlg = ShapeFileNames(myFilePath) isOK = myShapeFileNamesDlg.exec_() CRS = QgsCoordinateReferenceSystem() crsIsOk = CRS.createFromEpsg(self.GPSTracks[0][0].datumEPSG) if not crsIsOk: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating CRS from"+\ " EPSG ID:" + str(self.GPSTracks[0][0].datumEPSG)) if isOK and crsIsOk: if len(myShapeFileNamesDlg.lnePointsFileName.text()) > 0: # set up the fields for the Points SHAPE file latf = QgsField ("LATITUDE", QVariant.Double, "Real", 9, 6) lonf = QgsField ("LONGITUDE", QVariant.Double, "Real", 10, 6) nums = QgsField ("NUMOFSATS", QVariant.Int, "Integer", 2, 0) hdop = QgsField ("HDOP", QVariant.Double, "Real", 4, 2) theDateTime = QgsField ("DATETIME", QVariant.String, "String", 19, 0) fixType = QgsField ("FIXTYPE", QVariant.String, "String", 1, 0) #fixType = QgsField ("FIXTYPE", QVariant.String) #fixType.setLength(1) bearing = QgsField ("BEARING", QVariant.Double, "Real", 6, 2) speed = QgsField ("SPEED-KPH", QVariant.Double, "Real", 5, 1) trackNumber = QgsField ("TRACKNUM", QVariant.Int, "Integer", 2, 0) qFields = {} qFields[0] = latf qFields[1] = lonf qFields[2] = nums qFields[3] = hdop qFields[4] = theDateTime qFields[5] = fixType qFields[6] = bearing qFields[7] = speed qFields[8] = trackNumber # set up the CRS # open the points SHAPE file # pointsFile = QgsVectorFileWriter(myShapeFileNamesDlg.lnePointsFileName.text(),"System",qFields,QGis.WKBPoint,CRS) pointsFile, fileOK = self.createSHAPEfile(myShapeFileNamesDlg.lnePointsFileName.text(),qFields,QGis.WKBPoint,CRS) if fileOK: for j in range(len(self.GPSTracks)): for i in range(len(self.GPSTracks[j])): theFeature = QgsFeature() latitude = self.GPSTracks[j][i].latitude if self.GPSTracks[j][i].latitudeNS == 'S': latitude = -latitude longitude = self.GPSTracks[j][i].longitude if self.GPSTracks[j][i].longitudeEW == 'W': longitude = -longitude theFeature.setGeometry(QgsGeometry.fromPoint(QgsPoint(longitude,latitude))) theFeature.addAttribute(0, QVariant(latitude)) theFeature.addAttribute(1, QVariant(longitude)) theFeature.addAttribute(2, QVariant(self.GPSTracks[j][i].numSatellites)) theFeature.addAttribute(3, QVariant(self.GPSTracks[j][i].hdop)) theFeature.addAttribute(4, QVariant(self.GPSTracks[j][i].theDateTime)) theFeature.addAttribute(5, QVariant(self.GPSTracks[j][i].fixQuality)) theFeature.addAttribute(6, QVariant(self.GPSTracks[j][i].bearing)) theFeature.addAttribute(7, QVariant(self.GPSTracks[j][i].speed)) theFeature.addAttribute(8, QVariant(j+1)) pointsFile.addFeature(theFeature) del pointsFile # del file object to force a flush and close if len(myShapeFileNamesDlg.lneLinesFileName.text()) > 0: # set up the fields for the Lines SHAPE file startDateTime = QgsField ("SDATETIME", QVariant.String, "String", 19, 0) endDateTime = QgsField ("EDATETIME", QVariant.String, "String", 19, 0) trackNumber = QgsField ("TRACKNUM", QVariant.Int, "Integer", 2, 0) qFields = {} qFields[0] = startDateTime qFields[1] = endDateTime qFields[2] = trackNumber linesFile, fileOK = self.createSHAPEfile(myShapeFileNamesDlg.lneLinesFileName.text(),qFields,QGis.WKBLineString,CRS) if fileOK: for j in range(len(self.GPSTracks)): theFeature = QgsFeature() pointsList = [] for i in range(len(self.GPSTracks[j])): latitude = self.GPSTracks[j][i].latitude if self.GPSTracks[j][i].latitudeNS == 'S': latitude = -latitude longitude = self.GPSTracks[j][i].longitude if self.GPSTracks[j][i].longitudeEW == 'W': longitude = -longitude pointsList.append(QgsPoint(longitude,latitude)) theFeature.setGeometry(QgsGeometry.fromPolyline(pointsList)) theFeature.addAttribute(0, QVariant(self.GPSTracks[j][0].theDateTime)) theFeature.addAttribute(1, QVariant(self.GPSTracks[j][len(self.GPSTracks[j])-1].theDateTime)) theFeature.addAttribute(2, QVariant(j+1)) linesFile.addFeature(theFeature) del linesFile # del file object to force a flush and close def createSHAPEfile(self,fileName,fileFields,fileType,crs): ''' this function creates a new, empty shape file for use in writing points or lines Returns: SHAPEfile, status if status == True then SHAPEfile is OK to use, if False then an error occured and cannot use SHAPEFile Input Parameters: fileName = full name of the SHAPE file to be created fileFields = map of QgsFields to use for the attributes of the SHAPE file fileType = QGis.WKBPoint for points file <or> QGis.WKBLine for lines file crs = the QgsCoordinateReferenceSystem to use for the file ''' status = True # default is no error SHAPEfile = QgsVectorFileWriter(fileName,"CP1250",fileFields,fileType,crs) typeName = 'Points' if fileType == QGis.WKBPoint else 'Lines' if SHAPEfile.hasError() != QgsVectorFileWriter.NoError: status = False # report an error if SHAPEfile.hasError() == QgsVectorFileWriter.ErrDriverNotFound: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrDriverNotFound\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrCreateDataSource: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrCreateDataSource\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrCreateLayer: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrCreateLayer\' - saving " + typeName + " is aborted") elif SHAPEfile.hasError() == QgsVectorFileWriter.ErrAttributeTypeUnsupported: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'ErrAttributeTypeUnsupported\' - saving " + typeName + " is aborted") else: QMessageBox.warning(self.iface.mainWindow(),"trackGPS - makeShapeFiles","Error creating " + typeName + " SHAPE file" +\ " ERROR=\'UNKOWN ERROR\' saving " + typeName + " is aborted") return SHAPEfile,status
class FlyingTrackerDialog(QtGui.QDockWidget, FORM_CLASS): def __init__(self, iface, parent=None): """Constructor.""" super(FlyingTrackerDialog, self).__init__(parent) self.setupUi(self) self.iface = iface self.course_comboBox.clear() self.lcdNumberWpt.display(1) self.GpsFixlcdNumber.display(0) self.SatelliteslcdNumber.display(0) self.pushButtonDisconnect.hide() self.pushButtonConnect.clicked.connect(self.Connect) self.pushButtonDisconnect.clicked.connect(self.Disconnect) self.pushCloseButton.clicked.connect(self.Close) self.LoadtoolButton.clicked.connect(self.FillComboBox) self.wptplus_toolButton.clicked.connect(self.NextWpt) self.wptmin_toolButton.clicked.connect(self.BackWpt) QtCore.QObject.connect(self.wptplus_toolButton, QtCore.SIGNAL("valueChanged(int)"), self.AdjNxtWpt) QtCore.QObject.connect(self.wptmin_toolButton, QtCore.SIGNAL("valueChanged(int)"), self.AdjNxtWpt) self.ZoomIntoolButton.clicked.connect(self.ZoomIn) self.ZoomOuttoolButton.clicked.connect(self.ZoomOut) shortcut = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_S), self.iface.mainWindow()) shortcut.setContext(QtCore.Qt.ApplicationShortcut) shortcut.activated.connect(self.ZoomIn) shortcut2 = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_A), self.iface.mainWindow()) shortcut2.setContext(QtCore.Qt.ApplicationShortcut) shortcut2.activated.connect(self.ZoomOut) shortcut3 = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_X), self.iface.mainWindow()) shortcut3.setContext(QtCore.Qt.ApplicationShortcut) shortcut3.activated.connect(self.NextWpt) shortcut4 = QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Z), self.iface.mainWindow()) shortcut4.setContext(QtCore.Qt.ApplicationShortcut) shortcut4.activated.connect(self.BackWpt) self.timer = QtCore.QTimer() QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.SendSerial) self.NxtWptRubber = False self.PositionMarker = False self.RubberBand = False self.WptVertexSignal = False self.trackCounter = 4 def AdjNxtWpt(self): if self.WptVertexSignal == True: self.iface.mapCanvas().scene().removeItem(self.WptVertex) del self.WptVertex self.WptVertexSignal = False if self.NxtWptRubber == True: self.iface.mapCanvas().scene().removeItem(self.rdue) del self.rdue self.iface.mapCanvas().scene().removeItem(self.rtre) del self.rtre self.NxtWptRubber = False canvas = self.iface.mapCanvas() mapRenderer = canvas.mapRenderer() crsSrc = QgsCoordinateReferenceSystem(4326) # NMEA is in WGS 84 crsDest = mapRenderer.destinationCrs() xform = QgsCoordinateTransform(crsSrc, crsDest) WptValue = int(self.lcdNumberWpt.value()) try: Wpt = self.pts[WptValue - 1] except IndexError: return self.WptVertex = QgsVertexMarker(self.iface.mapCanvas()) self.WptVertex.setIconSize(20) self.WptVertex.setIconType(QgsVertexMarker.ICON_X) self.WptVertex.setPenWidth(20) self.WptVertex.setCenter(xform.transform(Wpt)) self.WptVertexSignal = True if WptValue != 1: Wpt2 = self.pts[WptValue - 2] self.rdue = QgsRubberBand(self.iface.mapCanvas(), False) # False = not a polygon pointsdue = [xform.transform(Wpt), xform.transform(Wpt2)] self.rdue.setColor(QtGui.QColor(255, 0, 0)) self.rdue.setWidth(8) self.rdue.setLineStyle(QtCore.Qt.PenStyle(QtCore.Qt.DotLine)) self.rdue.setToGeometry(QgsGeometry.fromPolyline(pointsdue), None) #creation of NextWayPoint rubberband self.rtre = QgsRubberBand(self.iface.mapCanvas(), False) pointstre = self.pts[0:WptValue - 1] for i in xrange(len(pointstre)): pointstre[i] = xform.transform(pointstre[i]) self.rtre.setColor(QtGui.QColor(127, 0, 255)) self.rtre.setWidth(8) self.rtre.setLineStyle(QtCore.Qt.PenStyle(QtCore.Qt.DotLine)) self.rtre.setToGeometry(QgsGeometry.fromPolyline(pointstre), None) self.NxtWptRubber = True def Connect(self): try: self.positionMarker = PositionMarker(self.iface.mapCanvas()) self.PositionMarker = True portName = self.comboBox.currentText() self.ser = serial.Serial(portName, 38400) layername = self.course_comboBox.itemData( self.course_comboBox.currentIndex()) RouteLayer = QgsMapLayerRegistry.instance().mapLayer(layername) RouteLayer.selectAll() feats = RouteLayer.selectedFeatures() RouteLayer.removeSelection() feat = feats[0] geom = feat.geometry() self.pts = geom.asPolyline() SourceIntCRS = int(RouteLayer.crs().authid().split(':')[1]) if SourceIntCRS != 4326: SourceIntCRS = int(RouteLayer.crs().authid().split(':')[1]) SourceCRS = QgsCoordinateReferenceSystem(SourceIntCRS) DestCRS = QgsCoordinateReferenceSystem(4326) xformRouteLayer = QgsCoordinateTransform(SourceCRS, DestCRS) for i in xrange(len(self.pts)): x = self.pts[i][0] y = self.pts[i][ 1] #if track layer is not in WGS84 Geographic every coordinate is transformed TmpPoint = QgsPoint(x, y) Tmp2Point = xformRouteLayer.transform(TmpPoint) self.pts[i] = Tmp2Point self.TrackLayer = QgsVectorLayer("Point?crs=epsg:4326&index=yes", "Flight_track", "memory") self.TrackLayerProvider = self.TrackLayer.dataProvider() self.TrackLayerProvider.addAttributes([ QgsField("id", QtCore.QVariant.Int), QgsField('Time', QtCore.QVariant.String), QgsField('Ele', QtCore.QVariant.String), ]) QgsMapLayerRegistry.instance().addMapLayer(self.TrackLayer) symbols = self.TrackLayer.rendererV2().symbols() symbol = symbols[0] symbol.setColor(QtGui.QColor(0, 255, 0)) self.iface.legendInterface().refreshLayerSymbology(self.TrackLayer) if self.lcdNumberWpt.value() == 0: self.lcdNumberWpt.display(1) elif self.lcdNumberWpt.value() > len(self.pts): self.lcdNumberWpt.display(1) self.InRouteTolerance = float( self.DTrack_spinBox.value() ) #if we are distant from route less than this value path become green, otherwise red self.CompassTolerance = self.DCompass_spinBox.value( ) #if compass to next wpt confront to actual compass diverge less than this value projection of direction become green, otherwise red self.WptArrivedTolerance = float( self.DWpt_spinBox.value() ) #if we pass near a wpt less than this value (in meters) the program will set the next wpt self.EleTolerance = float( self.DHeightspinBox.value() ) #if our elevation diverge from planned elevation more than this value our cursor will be red, otherwise green canvas = self.iface.mapCanvas() mapRenderer = canvas.mapRenderer() crsSrc = QgsCoordinateReferenceSystem(4326) # NMEA is in WGS 84 crsDest = mapRenderer.destinationCrs() self.backxform = QgsCoordinateTransform(crsDest, crsSrc) self.xform = QgsCoordinateTransform( crsSrc, crsDest) #usage: xform.transform(QgsPoint) self.AdjNxtWpt() self.timer.start(1000) except: pass def SendSerial(self): thread = Thread(target=self.ReadSerial) thread.start() thread.join() def Disconnect(self, serialPort): self.timer.stop() self.lcdNumberSpeed.display(0) self.lcdNumberCompass.display(0) try: self.iface.mapCanvas().scene().removeItem(self.WptVertex) self.ser.close() self.iface.mapCanvas().scene().removeItem(self.r) self.iface.mapCanvas().scene().removeItem(self.runo) self.iface.mapCanvas().scene().removeItem(self.positionMarker) del self.WptVertex del self.r del self.runo except: pass self.iface.mapCanvas().setRotation(0) self.RubberBand = False if self.NxtWptRubber == True: self.iface.mapCanvas().scene().removeItem(self.rdue) self.iface.mapCanvas().scene().removeItem(self.rtre) del self.rdue del self.rtre self.NxtWptRubber = False else: pass self.WptVertexSignal = False self.lcdNumberHeights.display(0) self.lcdNumberSpeed.display(0) self.lcdNumberCompass.display(0) self.lcdCompassWpt.display(0) self.GpsFixlcdNumber.display(0) self.SatelliteslcdNumber.display(0) def FillComboBox(self): try: self.comboBox.clear() portlist = [] system_name = platform.system() if system_name == "Windows": # Scan for available ports. available = [] for i in range(256): try: s = serial.Serial(i) available.append(i) s.close() except serial.SerialException: #Search for active serial port pass #print available list1 = available elif system_name == "Darwin": # Mac #print glob.glob('/dev/tty*') + glob.glob('/dev/cu*') list1 = glob.glob('/dev/tty*') + glob.glob('/dev/cu*') else: # Assume Linux or something else #print glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') list1 = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') for i in list1: try: serial.Serial(i).close() portlist.append(i) except IOError: pass for x in portlist: self.comboBox.addItem(x) self.course_comboBox.clear() LayerRegistryItem = QgsMapLayerRegistry.instance().mapLayers() for id, layer in LayerRegistryItem.iteritems(): if layer.type() == QgsMapLayer.VectorLayer: self.course_comboBox.addItem(layer.name(), id) layername = self.course_comboBox.itemData( self.course_comboBox.currentIndex()) RouteLayer = QgsMapLayerRegistry.instance().mapLayer(layername) RouteLayer.selectAll() RouteLayer.featureCount() feats = RouteLayer.selectedFeatures() RouteLayer.removeSelection() feat = feats[0] geom = feat.geometry() self.pts = geom.asPolyline() SourceIntCRS = int(RouteLayer.crs().authid().split(':')[1]) if SourceIntCRS != 4326: SourceIntCRS = int(RouteLayer.crs().authid().split(':')[1]) SourceCRS = QgsCoordinateReferenceSystem(SourceIntCRS) DestCRS = QgsCoordinateReferenceSystem(4326) xformRouteLayer = QgsCoordinateTransform(SourceCRS, DestCRS) for i in xrange(len(self.pts)): x = self.pts[i][0] y = self.pts[i][ 1] #if track layer is not in WGS84 Geographic every coordinate is transformed TmpPoint = QgsPoint(x, y) Tmp2Point = xformRouteLayer.transform(TmpPoint) self.pts[i] = Tmp2Point self.AdjNxtWpt() except: pass def Close(self): self.timer.stop() self.lcdNumberHeights.display(0) self.lcdNumberSpeed.display(0) self.lcdNumberCompass.display(0) self.lcdCompassWpt.display(0) self.course_comboBox.clear() if self.PositionMarker == True: self.iface.mapCanvas().scene().removeItem(self.positionMarker) if self.NxtWptRubber == True: self.iface.mapCanvas().scene().removeItem(self.rdue) self.iface.mapCanvas().scene().removeItem(self.rtre) del self.rdue del self.rtre self.NxtWptRubber = False else: pass if self.WptVertexSignal == True: self.iface.mapCanvas().scene().removeItem(self.WptVertex) del self.WptVertex self.WptVertexSignal = False self.close() def ZoomIn(self): self.iface.mapCanvas().zoomIn() def ZoomOut(self): self.iface.mapCanvas().zoomOut() def NextWpt(self): try: currentValue = self.lcdNumberWpt.value() if currentValue == len(self.pts): pass else: self.lcdNumberWpt.display(currentValue + 1) self.AdjNxtWpt() except: pass def BackWpt(self): try: currentValue = self.lcdNumberWpt.value() if currentValue >= 2: self.lcdNumberWpt.display(currentValue - 1) self.AdjNxtWpt() except: pass def ReadSerial(self): if self.trackCounter > 5: self.trackCounter = 4 self.trackCounter = self.trackCounter + 1 # when it arrive to 5 a gps point is painted (default is 4) GPGGA = 0 GPVTG = 0 data = self.ser.read(1) n = self.ser.inWaiting() if n: data = data + self.ser.read(n) if re.search("\r\n", data): # Since we found a CRLF, split it out data2 = data.split("\r\n") for i in range(len(data2)): if data2[i][0:6] == '$GPGGA': GPGGA = data2[i].split(',') #print GPGGA elif data2[i][0:6] == '$GPVTG': GPVTG = data2[i].split(',') #print GPRMC if GPGGA == 0: #print 'mancato' return elif GPVTG == 0: #print 'mancato' return else: decimalsLat = (float(GPGGA[2][2:])) / 60 degreeLat = float(GPGGA[2][0:2]) decimalsLon = (float(GPGGA[4][3:])) / 60 degreeLon = float(GPGGA[4][0:3]) Lat = degreeLat + decimalsLat Lon = degreeLon + decimalsLon if GPGGA[5] == 'W': Lon = -Lon if GPGGA[3] == 'S': Lat = -Lat Ele = float(GPGGA[9]) Compass = float(GPVTG[1]) Speed = (float(GPVTG[7])) # in Km/h GpsFix = int(GPGGA[6]) GpsSatellites = int(GPGGA[7]) self.ser.flushInput() self.ser.flushOutput() self.GpsFixlcdNumber.display(GpsFix) self.SatelliteslcdNumber.display(GpsSatellites) if self.RubberBand == True: self.iface.mapCanvas().scene().removeItem(self.r) del self.r self.RubberBand = False Point = QgsPoint() Point.set(Lon, Lat) TransfPoint = self.xform.transform(Point) canvas = self.iface.mapCanvas() if Compass <= 180: #canvas.setRotation(-(Compass-self.rotation)) canvas.setRotation( -Compass ) # set canvas rotation according to: UP of the map = Compass Direction else: Compass = 360 - Compass canvas.setRotation(Compass) canvas.setCenter(TransfPoint) self.positionMarker.newCoords( TransfPoint) # Put the arrow on screen #self.positionMarker.angle = 0.0 WptValue = int(self.lcdNumberWpt.value()) WptE = self.pts[WptValue - 1][0] WptN = self.pts[WptValue - 1][1] GeodesicAircraftToWpt = Geodesic.WGS84.Inverse( Lat, Lon, WptN, WptE) distance = GeodesicAircraftToWpt['s12'] azim = GeodesicAircraftToWpt[ 'azi1'] #determine azimuth from next wpt if azim < 0: azim += 360 if distance <= self.WptArrivedTolerance: # tolerance in meter for next wpt self.NextWpt() #feetEle = Ele * 3.2808399 #meters to feet if self.comboBox_2.currentText() == 'ft.': feetEle = Ele * 3.2808399 #Convert if needed self.lcdNumberHeights.display(feetEle) else: self.lcdNumberHeights.display(Ele) if self.comboBox_3.currentText() != 'km/h': Speed = Speed * 0.53995694 #Convert if needed self.lcdNumberSpeed.display(float(Speed)) else: self.lcdNumberSpeed.display(float(Speed)) self.lcdNumberCompass.display(float(Compass)) self.lcdCompassWpt.display(azim) canvasInPixel = canvas.getCoordinateTransform() ExtentHeightInPixel = canvasInPixel.mapHeight() ExtentWidthInPixel = canvasInPixel.mapWidth() LocateCompassProjectionEndInMapUnit = canvasInPixel.toMapPoint( ExtentWidthInPixel / 2.0, ExtentHeightInPixel - (ExtentHeightInPixel * 0.95)) self.r = QgsRubberBand(self.iface.mapCanvas(), False) # False = not a polygon #points = [TransfPoint, QgsPoint(x,y)] #creazione della proiezione della prua su mappa points = [TransfPoint, LocateCompassProjectionEndInMapUnit] self.r.setWidth(8) self.r.setToGeometry(QgsGeometry.fromPolyline(points), None) if abs(Compass - azim) <= self.CompassTolerance: #Compass tolerance self.r.setColor(QtGui.QColor(0, 255, 0)) else: self.r.setColor(QtGui.QColor(255, 0, 0)) self.RubberBand = True try: self.iface.mapCanvas().scene().removeItem( self.runo) # remove track for first waypoint except: pass if WptValue != 1: #DistanceFromLineTolerance = 100 #meter set distance from route BackwardLat = self.rdue.asGeometry().asPolyline()[1][ 1] #start to design a QgsRectangle buffer around current route to confront to Point BackwardLon = self.rdue.asGeometry().asPolyline()[1][0] BackwardPoint = QgsPoint(BackwardLon, BackwardLat) BackwardPointTransformed = self.backxform.transform( BackwardPoint) GeodesicWptWpt = Geodesic.WGS84.Inverse( BackwardPointTransformed.y(), BackwardPointTransformed.x(), WptN, WptE) #GeodesicWptWpt = Geodesic.WGS84.Inverse(BackwardLat, BackwardLon, WptN, WptE) WptWptCompass = GeodesicWptWpt['azi1'] if WptWptCompass < 0: WptWptCompass += 360 #print WptWptCompass WptWptCompassRight = WptWptCompass + 90 if WptWptCompassRight > 360: WptWptCompassRight = WptWptCompassRight - 360 #print WptWptCompassRight WptWptCompassLeft = WptWptCompass - 90 if WptWptCompassLeft < 0: WptWptCompassLeft += 360 #print WptWptCompassLeft origin = geopy.Point(WptN, WptE) URBufferVertex = vincenty( meters=self.InRouteTolerance).destination( origin, WptWptCompassRight) URBufferVertexPoint = QgsPoint(URBufferVertex.longitude, URBufferVertex.latitude) ULBufferVertex = vincenty( meters=self.InRouteTolerance).destination( origin, WptWptCompassLeft) ULBufferVertexPoint = QgsPoint(ULBufferVertex.longitude, ULBufferVertex.latitude) del origin origin = geopy.Point(BackwardPointTransformed.y(), BackwardPointTransformed.x()) DRBufferVertex = vincenty( meters=self.InRouteTolerance).destination( origin, WptWptCompassRight) DRBufferVertexPoint = QgsPoint(DRBufferVertex.longitude, DRBufferVertex.latitude) DLBufferVertex = vincenty( meters=self.InRouteTolerance).destination( origin, WptWptCompassLeft) DLBufferVertexPoint = QgsPoint(DLBufferVertex.longitude, DLBufferVertex.latitude) del origin gPolygon = QgsGeometry.fromPolygon([[ URBufferVertexPoint, ULBufferVertexPoint, DLBufferVertexPoint, DRBufferVertexPoint ]]) if not gPolygon.contains(Point): self.rdue.setColor(QtGui.QColor(255, 0, 0)) #print 'noncontiene' else: self.rdue.setColor(QtGui.QColor(0, 255, 0)) #print 'contiene' else: self.runo = QgsRubberBand(self.iface.mapCanvas(), False) points = [TransfPoint, self.xform.transform(self.pts[0]) ] # draw track for first waypoint self.runo.setColor(QtGui.QColor(255, 0, 0)) self.runo.setWidth(6) self.runo.setLineStyle( QtCore.Qt.PenStyle(QtCore.Qt.DotLine)) self.runo.setToGeometry(QgsGeometry.fromPolyline(points), None) #if abs(float((self.fixedHeightspinBox.value()/ 3.2808399)) - (feetEle/ 3.2808399)) <= self.EleTolerance: #ele tolerance expressed in meters if abs(self.fixedHeightspinBox.value() - Ele) <= self.EleTolerance: self.positionMarker.setHasPosition( True) #True or False to change color else: self.positionMarker.setHasPosition(False) if self.trackCounter == 5: #pass fc = int(self.TrackLayerProvider.featureCount()) time = str(GPGGA[1])[0:2] + ':' + str( GPGGA[1])[2:4] + ':' + str( GPGGA[1])[4:6] # timestamp for GPX layer feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes([fc, time, Ele]) self.TrackLayer.startEditing() self.TrackLayer.addFeature(feature, True) self.TrackLayer.commitChanges() self.TrackLayer.setCacheImage(None) self.TrackLayer.triggerRepaint() self.trackCounter = 0 return
class GatherPlugin(QObject): """ Main Gahterer plugin class - handles interaction with QGis and organizes all the recording stuff. """ def __init__(self, iface): QObject.__init__(self) self.iface = iface def initGui(self): """ Initialize plugin's UI """ self.initLogging() self.recording=False self.loadPlugins() self.loadConfiguration() self.rubberBand=None self.lastPosition=None self.timer=None self.previousPaths=[] #previews of previously recorded paths self.gpsDaemon=GpsDaemon(self, self) self.canvas=self.iface.mapCanvas() self.gatherer=None self.dockWidget=None self.dockWidget_simple=None self.dockWidget=DockWidget(self) self.dockWidget_simple=DockWidget_simple(self) self.actionDockWidget=QAction("Show Gatherer dock widget",self.iface.mainWindow()) self.actionDockWidget.setCheckable(True) QObject.connect(self.actionDockWidget, SIGNAL("triggered()"), self.showHideDockWidget) self.iface.addPluginToMenu("Qgis-&mapper", self.actionDockWidget) QObject.connect(self.dockWidget, SIGNAL("visibilityChanged(bool)"), lambda : self.__dockwidgetVisibilityChanged(0)) QObject.connect(self.dockWidget_simple, SIGNAL("visibilityChanged(bool)"), lambda : self.__dockwidgetVisibilityChanged(1)) SourcePlugins.initializeUI(self.dockWidget.dataInputPlugins_tabWidget) self.curDockWidget=None self.showInterface(self.interface_simple) self.canvas=self.iface.mapCanvas() self.positionMarker=PositionMarker(self.canvas) self.connect(self.gpsDaemon, SIGNAL("newTrackPoint(PyQt_PyObject)"), self.gotNewTrackPoint) def unload(self): """ Cleanup and unload the plugin """ self.canvas.scene().removeItem(self.positionMarker) self.positionMarker=None if self.recording: self.recordingStop() self.saveConfiguration() SourcePlugins.unloadPlugins() self.gpsDaemon.terminate() self.dockWidget.unload() self.showInterface(None) del self.dockWidget del self.dockWidget_simple self.iface.removePluginMenu("Qgis-&mapper",self.actionDockWidget) del self.actionDockWidget logging.debug("Plugin terminated.") def initLogging(self): """ set up rotating log file handler with custom formatting """ handler = logging.handlers.RotatingFileHandler(logFilePath, maxBytes=1024*1024*10, backupCount=5) formatter = logging.Formatter("%(asctime)s %(levelname)-8s %(message)s") handler.setFormatter(formatter) logger = logging.getLogger() # root logger logger.setLevel(logging.DEBUG) logger.addHandler(handler) logging.debug("Plugin started.") def loadPlugins(self): """Load all existing plugins""" SourcePlugins.loadPlugins(self) def loadConfiguration(self): """ Load configuration from settings """ self.last_preview_scale=25 settings = QSettings() settings.beginGroup("/plugins/GatherPlugin") # GUI self.interface_simple = settings.value("interface/simple", QVariant(False)).toBool() # output directory must be a python string self.output_directory = str( settings.value("output/directory", QVariant(os.path.expanduser("~/qgismapper/data/"))).toString() ) self.output_append = settings.value("output/append", QVariant(0)).toInt()[0] self.preview_followPosition = settings.value("preview/followPosition", QVariant(True)).toBool() self.preview_scale = settings.value("preview/scale", QVariant(25)).toInt()[0] self.preview_keepPaths = settings.value("preview/keepPaths", QVariant(True)).toBool() # gps self.gps_source = settings.value("gps/source", QVariant("serial")).toString() self.gps_reconnectInterval = settings.value("gps/reconnectInterval", QVariant(2)).toInt()[0] self.gps_attemptsDuringRecording = settings.value("gps/attemptsDuringRecording", QVariant(3)).toInt()[0] self.gps_initFile = settings.value("gps/initFile", QVariant()).toString() self.gps_serial = settings.value("gps/serial/device", QVariant("/dev/rfcomm0")).toString() self.gps_serialBauds = settings.value("gps/serial/bauds", QVariant(38400)).toInt()[0] self.gps_file = settings.value("gps/file/path", QVariant(os.path.expanduser("~/nmea_log"))).toString() self.gps_fileCharsPerSecond = settings.value("gps/file/charsPerSecond", QVariant(300)).toInt()[0] self.gps_gpsdHost = settings.value("gps/gpsd/host", QVariant("localhost")).toString() self.gps_gpsdPort = settings.value("gps/gpsd/port", QVariant(2947)).toInt()[0] # compass self.compass_use = settings.value("compass/use", QVariant(False)).toBool() self.compass_device = settings.value("compass/device", QVariant("/dev/ttyUSB0")).toString() self.compass_bauds = settings.value("compass/bauds", QVariant(19200)).toInt()[0] def saveConfiguration(self): """ Save configuration to settings """ settings = QSettings() settings.beginGroup("/plugins/GatherPlugin") # GUI settings.setValue("interface/simple", QVariant(self.interface_simple)) settings.setValue("output/directory", QVariant(self.output_directory)) settings.setValue("output/append", QVariant(self.output_append)) settings.setValue("preview/followPosition", QVariant(self.preview_followPosition)) settings.setValue("preview/scale", QVariant(self.preview_scale)) settings.setValue("preview/keepPaths", QVariant(self.preview_keepPaths)) # gps settings.setValue("gps/source", QVariant(self.gps_source)) settings.setValue("gps/reconnectInterval", QVariant(self.gps_reconnectInterval)) settings.setValue("gps/attemptsDuringRecording", QVariant(self.gps_attemptsDuringRecording)) settings.setValue("gps/initFile", QVariant(self.gps_initFile)) settings.setValue("gps/serial/device", QVariant(self.gps_serial)) settings.setValue("gps/serial/bauds", QVariant(self.gps_serialBauds)) settings.setValue("gps/file/path", QVariant(self.gps_file)) settings.setValue("gps/file/charsPerSecond", QVariant(self.gps_fileCharsPerSecond)) settings.setValue("gps/gpsd/host", QVariant(self.gps_gpsdHost)) settings.setValue("gps/gpsd/port", QVariant(self.gps_gpsdPort)) # compass settings.setValue("compass/use", QVariant(self.compass_use)) settings.setValue("compass/device", QVariant(self.compass_device)) settings.setValue("compass/bauds", QVariant(self.compass_bauds)) def recordingStart(self): """ Start new recording (only call if there isn't any). """ # check that we have gps input if not self.isGpsConnected(): QMessageBox.warning(self.dockWidget, self.tr("Warning"), self.tr("GPS device isn't connected!\n\nPlease configure GPS input.")) self.dockWidget.recording = False return # check we have position if self.getNmeaParser().fix == "none": if QMessageBox.warning(self.dockWidget, self.tr("Warning"), self.tr("GPS doesn't have a valid position.\n\nDo you really want to start recording?"), QMessageBox.Yes|QMessageBox.No) != QMessageBox.Yes: self.dockWidget.recording = False return self.recordingStartPathPreview() if not self.recordingStartGatherer(): self.recordingStop() QMessageBox.information(self.dockWidget, self.tr("Warning"), self.tr("Recording was cancelled during initialization..."), self.tr("Ok")) return self.dockWidget.recording=True self.dockWidget_simple.recording=True #start a timer to keep the thread running... self.timer = QTimer() QObject.connect(self.timer, SIGNAL("timeout()"), self.runStatusTicker) self.timer.start(10) self.recording=True def recordingStop(self): """ Stop ongoing recording (only call if there is some). """ self.recordingStopGatherer() if self.timer!=None: self.timer.stop() self.timer=None #we need to correctly terminate recording by processing events, #this leads to processGathererEvent_recordingTerminated() QCoreApplication.processEvents() self.recordingStopPathPreview() self.dockWidget.recording=False self.dockWidget_simple.recording=False self.recording=False def recordingStartGatherer(self): """Start data gatherer thread""" self.gatherer=Gatherer.Gatherer(self) if not self.gatherer.alive: self.gatherer=None #don't try to stop the thread, as it's not running/alive return False QObject.connect(self.gatherer, SIGNAL("gathererEvent(PyQt_PyObject)"), self.processGathererEvent) self.gatherer.start() return True def recordingStopGatherer(self): """Terminate data gatherer thread""" if self.gatherer!=None: self.gatherer.stop() #QObject.disconnect(gathererEvent) is done automatically... def recordingStartPathPreview(self): """Initialize previewing recorded path""" self.rubberBand=QgsRubberBand(self.canvas) self.rubberBand.setColor(Qt.red) self.rubberBand.setWidth(3) self.rubberBand.reset(False) def recordingStopPathPreview(self): """Terminate previewing recorded path""" self.rubberBand.setColor(Qt.green) self.previousPaths.append(self.rubberBand) self.rubberBand=None if not self.preview_keepPaths: self.removePathPreviews() else: self.canvas.refresh() def removePathPreviews(self): """Remove recorded path previews from the map canvas""" for rb in self.previousPaths: self.canvas.scene().removeItem(rb) SourcePlugins.callMethodOnEach("clearMapCanvasItems", ()) self.previousPaths=[] self.canvas.refresh() def recordingSwitch(self): """ If recording is on, turn it of - and the opposite :-) """ if self.recording==False: self.recordingStart() else: self.recordingStop() def runStatusTicker(self): """ Make it possible for python to switch threads and if the gathering thread is not alive anymore, let the user know. """ if self.gatherer!=None: self.gatherer.msleep(1) def getLastDataSubdirectory(root): """ Returns last used data directory (including the time postfix). If no directory can be found, it returns empty string. The root parameter is data directory (specified by user), where the recordings are stored. """ dirs=[f for f in sorted(os.listdir(root)) if os.path.isdir(os.path.join(root, f))] r=re.compile("[0-9]*-[0-9]*-[0-9]*_[0-9]*-[0-9]*-[0-9]*") dirs=[f for f in dirs if r.match(f)!=None] if len(dirs)!=0: return root+dirs[-1]+"/" else: return "" getLastDataSubdirectory=staticmethod(getLastDataSubdirectory) def processGathererEvent(self, data): try: apply(getattr(self, "processGathererEvent_"+data[0]), data[1:]) except: traceback.print_exc(file=sys.stdout) def processGathererEvent_newTrackPoint(self, lat, lon, angle): """Process 'new track point' event from gatherer.""" try: if self.rubberBand and (lat!=0 or lon!=0): self.rubberBand.addPoint(QgsPoint(lon, lat)) except: traceback.print_exc(file=sys.stdout) def gotNewTrackPoint(self, pt): """ update position marker """ (lat, lon, angle, fix)=pt if lat!=0 or lon!=0: self.lastPosition=QgsPoint(lon, lat) self.lastAngle=angle self.lastFix=fix self.updatePositionMarker() self.updateExtent() def processGathererEvent_recordingTerminated(self, onUserRequest): """Process 'recording terminated' event from gatherer.""" self.gatherer.terminateAndCleanup() self.gatherer=None if not onUserRequest: self.recordingStop() QMessageBox.information(self.dockWidget, self.tr("Warning"), self.tr("Recording was cancelled by the gatherer thread (probably because of some communication error)..."), self.tr("Ok") ) def updateExtent(self): """Set correct map canvas extent for the current position and redraw.""" extent=self.canvas.extent() if not self.preview_followPosition or self.lastPosition==None: pos=extent.center() else: boundaryExtent=QgsRectangle(extent) boundaryExtent.scale(0.5) if not boundaryExtent.contains(QgsRectangle(self.lastPosition, self.lastPosition)): pos=self.lastPosition else: pos=extent.center() if self.preview_scale!=self.last_preview_scale or pos!=extent.center(): scale=pow(float(self.preview_scale)/99, 2)*0.4+0.0001 newExtent=QgsRectangle(pos.x()-scale/2, pos.y()-scale/2, pos.x()+scale/2, pos.y()+scale/2) self.last_preview_scale=self.preview_scale self.canvas.setExtent(newExtent) self.canvas.refresh() def updatePositionMarker(self): """Update position marker for the current position/orientation""" if self.positionMarker is None: return self.positionMarker.setHasPosition(self.lastFix) self.positionMarker.newCoords(self.lastPosition) self.positionMarker.angle=self.lastAngle def getNmeaParser(self): """Returns the NMEA gps data parser object (useful to gather current pos. info)""" return self.gpsDaemon.nmeaParser def isGpsConnected(self): """Returns, whether the gatherer is connected to gps device""" return self.gpsDaemon.isGpsConnected() def showInterface(self, simple): """Show the specified version (simple or full) of user interface""" self.interface_simple=simple if self.curDockWidget!=None: self.iface.removeDockWidget(self.curDockWidget) if simple: self.curDockWidget=self.dockWidget_simple else: self.curDockWidget=self.dockWidget if simple!=None: self.iface.addDockWidget(Qt.RightDockWidgetArea, self.curDockWidget) def getRecordingEnabledAuxCheckbox(self, source): """ Returns checkbox widget for the specified source (string, e.g. 'Audio'), that informs user about recording status in the simple version of interface. Returns None, if specified source's checkbox isn't available. """ return self.dockWidget_simple.getRecordingEnabledCheckbox(source) def showHideDockWidget(self): if self.curDockWidget.isVisible(): self.curDockWidget.hide() else: self.curDockWidget.show() def __dockwidgetVisibilityChanged(self, which): if self.curDockWidget.isVisible(): self.actionDockWidget.setChecked(True) else: self.actionDockWidget.setChecked(False)
class Cu_Video_TrackerDialog(QtGui.QDialog): def __init__(self, iface): QtGui.QDialog.__init__(self) # Set up the user interface from Designer. self.ui = Ui_Form() self.ui.setupUi(self) self.iface = iface self.ui.sourceLoad_pushButton.clicked.connect(self.OpenButton) self.ui.replayPlay_pushButton.clicked.connect(self.PlayPauseButton) QObject.connect(self.ui.replay_mapTool_pushButton, SIGNAL("toggled(bool)"), self.replayMapTool_toggled) self.positionMarker=None settings = QSettings() settings.beginGroup("/plugins/PlayerPlugin") self.replay_followPosition = settings.value("followPosition", True, type=bool) settings.setValue("followPosition", self.replay_followPosition) QObject.connect(self.iface.mapCanvas(), SIGNAL("mapToolSet(QgsMapTool*)"), self.mapToolChanged) self.mapTool=ReplayMapTool(self.iface.mapCanvas(), self) self.mapTool_previous=None self.mapToolChecked = property(self.__getMapToolChecked, self.__setMapToolChecked) QObject.connect(self.ui.replayPosition_horizontalSlider, SIGNAL( 'sliderMoved(int)'), self.replayPosition_sliderMoved) QObject.connect(self.ui.addpoint_button, SIGNAL('clicked()'),self.snapshot) QObject.connect(self.ui.ExporText_button, SIGNAL('clicked()'),self.exportText) QObject.connect(self.ui.ExporShp_button, SIGNAL('clicked()'),self.exportShp) QObject.connect(self.ui.ExporSqlite_button, SIGNAL('clicked()'),self.exportSqlite) QObject.connect(self.ui.ExporKML_button, SIGNAL('clicked()'),self.exportKML) QObject.connect(self.ui.Help, SIGNAL('clicked()'),self.Help) self.PlayPuase = 0 # Puase=0,Play=1 self.Close = 0 # select video=1 , Close=0 self.adactProjection = False self.createLayer = 0 # Default layer=1,create by user=2,load existent=else self.videoWidget = Phonon.VideoWidget(self.ui.video_widget) def OpenButton(self): if self.Close == 1: if self.positionMarker != None: self.iface.mapCanvas().scene().removeItem(self.positionMarker) self.positionMarker = None self.Close = 0 self.ui.replay_mapTool_pushButton.setChecked(False) self.ui.sourceLoad_pushButton.setText('Open...') self.createLayer = 0 self.timer.stop() ##self.timer2.stop() self.media_obj.stop() self.iface.mapCanvas().unsetMapTool(self.mapTool) self.close() else: self.path = QtGui.QFileDialog.getOpenFileName(self,self.tr("Select Video files")) self.csvFile = open(self.path + '.csv',"rb") Filereader = csv.DictReader(self.csvFile) self.CSVLayer = QgsVectorLayer("LineString","GPS Tracking","memory") self.latt = [] self.lonn = [] self.timeh = [] self.timem = [] self.times = [] i=0 for row in Filereader: self.latt.append(float(row['lon'])) self.lonn.append(float(row['lat'])) if row['time_h'] != '': self.timeh.append(int(row['time_h'])) self.timem.append(int(row['time_m'])) self.times.append(int(row['time_s'])) #create tracker layer (line layer) for i in xrange(0,len(self.latt)-1,1): point_start = QgsPoint(self.latt[i],self.lonn[i]) point_end = QgsPoint(self.latt[i+1],self.lonn[i+1]) line = QgsGeometry.fromPolyline([point_start,point_end]) self.pr = self.CSVLayer.dataProvider() afeature = QgsFeature() afeature.setGeometry(QgsGeometry.fromPolyline([point_start,point_end])) self.pr.addFeatures( [ afeature ] ) self.CSVLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([self.CSVLayer]) SelectLayer,ok = QInputDialog.getItem(self.iface.mainWindow(),"Layer chooser","Choose point layer",('Default point layer','Creat new point layer','Load existent point layer')) if SelectLayer == 'Load existent point layer': self.newLayerPath = QtGui.QFileDialog.getOpenFileName() if not self.newLayerPath is None: name = self.newLayerPath.split("/")[-1][0:-4] self.vl = QgsVectorLayer(self.newLayerPath, name, "ogr") self.pr = self.vl.dataProvider() fields = self.pr.fields() field_names = [field.name() for field in fields] f = "Image link" fnd = self.vl.fieldNameIndex(f) fn = field_names[fnd] if not fn == f: self.pr.addAttributes([QgsField("Image link", QVariant.String)]) QgsMapLayerRegistry.instance().addMapLayer(self.CSVLayer) QgsMapLayerRegistry.instance().addMapLayer(self.vl) elif SelectLayer == 'Default point layer': self.vl = QgsVectorLayer("Point?crs=epsg:4326&index=yes","point", "memory") self.pr = self.vl.dataProvider() self.pr.addAttributes( [ QgsField('id', QVariant.Int), QgsField('Name', QVariant.String), QgsField('Description', QVariant.String), QgsField('Type', QVariant.String), QgsField("Lon", QVariant.String), QgsField("Lat", QVariant.String), QgsField('East UTM', QVariant.String), QgsField('North UTM',QVariant.String), QgsField('Image link', QVariant.String)] ) # update layer's extent self.vl.updateExtents() QgsMapLayerRegistry.instance().addMapLayer( self.CSVLayer ) QgsMapLayerRegistry.instance().addMapLayers([self.vl]) self.createLayer = 1 else: # Creat new point layer by user self.createLayer = 2 self.vl = QgsVectorLayer("Point?crs=epsg:4326&index=yes","point", "memory") self.pr = self.vl.dataProvider() # table manager dialog self.dialoga = TableManager(self.iface, self.vl,self.CSVLayer) self.dialoga.exec_() #set point label palyr = QgsPalLayerSettings() palyr.readFromLayer(self.vl) palyr.enabled = True palyr.fieldName = 'id' palyr.placement= QgsPalLayerSettings.Upright palyr.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,'14','') palyr.writeToLayer(self.vl) if self.positionMarker==None: self.positionMarker=PositionMarker(self.iface.mapCanvas()) self.media_src = Phonon.MediaSource(self.path) self.media_obj = Phonon.MediaObject(self) self.media_obj.setCurrentSource(self.media_src) Phonon.createPath(self.media_obj, self.videoWidget) # set audio ## audio_out = Phonon.AudioOutput(Phonon.VideoCategory, self) ## Phonon.createPath(self.media_obj, audio_out) self.ui.video_widget.resizeEvent = self.Resize() self.media_obj.setTickInterval(100) self.timer = QtCore.QTimer() QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.Timer) self.PlayPuase =1 self.ui.sourceLoad_pushButton.setText('Close') self.Close = 1 #load file selector self.media_obj.play() #phonon play self.timer.start(1000) self.ui.replayPlay_pushButton.setEnabled(True) self.ui.addpoint_button.setEnabled(True) def Resize(self): a = self.ui.video_widget.frameSize() b = self.videoWidget.frameSize() if a != b: self.videoWidget.resize(a) def CurrentPos(self): end = self.media_obj.totalTime() pos = self.media_obj.currentTime() if pos == end: self.timer.stop() self.media_obj.pause() if self.PlayPuase == 1: self.PlayPuase = 0 else: Pos = pos/1000 self.ui.replayPosition_label.setText(str(datetime.timedelta(seconds=int(Pos))) + '/' + str(datetime.timedelta(seconds=(int(end/1000))))) return int(Pos) def Timer(self): if self.PlayPuase == 1: self.updateReplayPosition() self.SetSlide() else: pass def TimeOffset(self): self.current_second =[] self.time_offset =[] if self.timeh != []: for i in xrange(0,len(self.timeh),1): h_second = int(self.timeh[i])*60*60 m_second = int(self.timem[i])*60 s_second = int(self.times[i]) c_second = h_second + m_second + s_second self.current_second.append(c_second) t_of = int(int(self.current_second[i]) -int(self.current_second[0])) self.time_offset.append(t_of) else: #find time offset for i in xrange(0,len(self.latt),1): # Number of record in csv self.NumRec = len(self.latt) #create new list start at 0 self.L_Num = range(len(self.latt)) #time interval self.t_interval = ((self.media_obj.totalTime()/1000)/float(self.NumRec - 1)) t_of = self.L_Num[i] * self.t_interval self.time_offset.append(t_of) return self.time_offset def updateReplayPosition(self): pos = self.CurrentPos() # find the nearest timestamp offset of position time in logging data TimeOffset = self.TimeOffset() i = min(range(len(TimeOffset)),key=lambda x: abs(TimeOffset[x]-((pos)))) if pos-1 == (self.media_obj.totalTime()/1000-1): self.media_obj.stop() if pos - TimeOffset[i] == 0: self.lat_new = self.latt[i] self.lon_new = self.lonn[i] else: if pos < TimeOffset[i]: Dlat = self.latt[i]- self.latt[i-1] Dlon = self.lonn[i]- self.lonn[i-1] Dtime = TimeOffset[i] - TimeOffset[i-1] else: Dlat = self.latt[i+1]- self.latt[i] Dlon = self.lonn[i+1]- self.lonn[i] Dtime = TimeOffset[i+1] - TimeOffset[i] Dti = float(pos -TimeOffset[i]) Dlat_i = Dlat*(Dti/Dtime) Dlon_i = Dlon*(Dti/Dtime) self.lat_new = self.latt[i]+ Dlat_i self.lon_new = self.lonn[i] + Dlon_i self.lat,self.lon = self.lat_new,self.lon_new self.Point = QgsPoint() self.Point.set(self.lat,self.lon) canvas = self.iface.mapCanvas() mapRenderer = canvas.mapRenderer() crsSrc = QgsCoordinateReferenceSystem(4326) # WGS 84 crsDest = mapRenderer.destinationCrs() xform = QgsCoordinateTransform(crsSrc, crsDest) #usage: xform.transform(QgsPoint) self.positionMarker.setHasPosition(True) self.Point = xform.transform(self.Point) self.positionMarker.newCoords(self.Point) if self.replay_followPosition: extent=self.iface.mapCanvas().extent() boundaryExtent=QgsRectangle(extent) boundaryExtent.scale(1.0) if not boundaryExtent.contains(QgsRectangle(self.Point, self.Point)): extentCenter= self.Point newExtent=QgsRectangle(extentCenter.x()-extent.width()/1.7,extentCenter.y()-extent.height()/1.7,extentCenter.x()+extent.width()/17,extentCenter.y()+extent.height()/1.7) self.iface.mapCanvas().setExtent(newExtent) self.iface.mapCanvas().refresh() East,North,alt = self.transform_wgs84_to_utm(self.lat_new,self.lon_new) self.ui.E.setText ('Easting : ' + str(East)) self.ui.N.setText ('Northing : ' + str(North)) self.ui.lat.setText ('Latitude : ' + str(self.lon_new)) self.ui.lon.setText('Longitude : ' + str(self.lat_new)) def PlayPauseButton(self): if self.PlayPuase == 1: self.media_obj.pause() self.timer.stop() self.PlayPuase = 0 else: self.media_obj.play() self.timer.start(0) self.PlayPuase = 1 def replayMapTool_toggled(self, checked): """Enable/disable replay map tool""" self.useMapTool(checked) def useMapTool(self, use): """ afer you click on it, you can seek the video just clicking on the gps track """ if use: if self.iface.mapCanvas().mapTool()!=self.mapTool: self.mapTool_previous=self.iface.mapCanvas().mapTool() self.iface.mapCanvas().setMapTool(self.mapTool) else: if self.mapTool_previous!=None: self.iface.mapCanvas().setMapTool(self.mapTool_previous) else: self.iface.mapCanvas().unsetMapTool(self.mapTool) def mapToolChanged(self, tool): """Handle map tool changes outside plugin""" if (tool!=self.mapTool) and self.mapToolChecked: self.mapTool_previous=None self.mapToolChecked=False def __getMapToolChecked(self): return self.replay_mapTool_pushButton.isChecked() def __setMapToolChecked(self, val): self.replay_mapTool_pushButton.setChecked(val) def findNearestPointInRecording(self, toPoint): """ Find the point nearest to the specified point (in map coordinates) """ for i in xrange(0,len(self.latt),1): if(str(self.latt[i]))[0:7] == str(toPoint.x())[0:7]and (str(self.lonn[i]))[0:7]==(str(toPoint.y()))[0:7]: adj = (self.time_offset[i]) - (self.time_offset[0]) lat,lon =(self.latt[i]) , (self.lonn[i]) Point = QgsPoint() Point.set(lat,lon) self.positionMarker.newCoords(Point) self.Seek(adj) break def Seek (self, pos): if self.PlayPuase == 0: self.timer.stop() self.media_obj.seek(pos*1000) self.media_obj.play() self.timer.start(0) self.PlayPuase =1 else: self.media_obj.seek(pos*1000) self.timer.start(1000) def replayPosition_sliderMoved(self,pos): """Handle moving of replay position slider by user""" self.Seek(pos) def SetSlide(self): end = self.media_obj.totalTime() pos = self.media_obj.currentTime() self.endtime = (self.media_obj.totalTime()/1000) self.ui.replayPosition_horizontalSlider.setMinimum(0) self.ui.replayPosition_horizontalSlider.setMaximum((self.endtime)) if not pos == end: pos = float(self.CurrentPos()) self.ui.replayPosition_horizontalSlider.setValue(pos) def AddPoint (self,toPoint): if self.PlayPuase == 1: self.media_obj.pause() self.timer.stop() self.PlayPuase = 0 else: pass last_desc = '///' fc = int(self.pr.featureCount()+1) if self.createLayer == 1: self.vl.dataProvider() filename = self.path + '__'+ str(self.getImageFileName()) + '.jpg' p= QPixmap.grabWidget(self.videoWidget) p.save(filename) (Name,ok) = QInputDialog.getText( self.iface.mainWindow(), "Attributes", "Name", QLineEdit.Normal, last_desc) (Description,ok) = QInputDialog.getText( self.iface.mainWindow(), "Attributes", "Description", QLineEdit.Normal, last_desc) (Type,ok) = QInputDialog.getText( self.iface.mainWindow(), "Attributes", "Type", QLineEdit.Normal, last_desc) # create the feature feature = QgsFeature() lat,lon = toPoint.x(), toPoint.y() Point = QgsPoint() Point.set(lat,lon) EastUTM,NorthUTM,alt= self.transform_wgs84_to_utm(lat, lon) feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes([fc,Name,Description,Type,lat,lon,EastUTM,NorthUTM,self.path + '__'+ str(self.getImageFileName()) + '.jpg']) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename,self.path + '__'+ str(self.getImageFileName()) + '.jpg') elif self.createLayer == 2: p= QPixmap.grabWidget(self.videoWidget) fields = self.pr.fields() attributes = [] lat,lon = toPoint.x(), toPoint.y() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon': attributes.append(lat) elif a == 'Lat': attributes.append(lon) else: if b == 'String': (a,ok) = QInputDialog.getText( self.iface.mainWindow(), "Attributes", a + ' = ' + b, QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a,ok) = QInputDialog.getDouble( self.iface.mainWindow(), "Attributes", a + ' = ' + b, decimals = 10) attributes.append(a) elif b == 'Integer': (a,ok) = QInputDialog.getInt( self.iface.mainWindow(), "Attributes", a + ' = ' + b) attributes.append(a) feature = QgsFeature() Point = QgsPoint() Point.set(lat,lon) #use in new table filename = self.path + '__'+ str(self.getImageFileName()) + '.jpg' p.save(filename) attributes.append(filename) feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename,self.path + '__'+ str(self.getImageFileName()) + '.jpg') else: p= QPixmap.grabWidget(self.videoWidget) fields = self.pr.fields() attributes = [] lat,lon = toPoint.x(), toPoint.y() for field in fields: a = str(field.name()) b = str(field.typeName()) if a == 'id': fcnr = fc attributes.append(fcnr) elif a == 'Lon': attributes.append(lat) elif a == 'Lat': attributes.append(lon) else: if b == 'String': (a,ok) = QInputDialog.getText( self.iface.mainWindow(), "Attributes", a + ' = ' + b, QLineEdit.Normal) attributes.append(a) elif b == 'Real': (a,ok) = QInputDialog.getDouble( self.iface.mainWindow(), "Attributes", a + ' = ' + b, decimals = 10) attributes.append(a) elif b == 'Integer': (a,ok) = QInputDialog.getInt( self.iface.mainWindow(), "Attributes", a + ' = ' + b) attributes.append(a) feature = QgsFeature() Point = QgsPoint() Point.set(lat,lon) #use in existent table feature.setGeometry(QgsGeometry.fromPoint(Point)) feature.setAttributes(attributes) filename = self.path + '__'+ str(self.getImageFileName()) + '.jpg' p.save(filename) field_index = self.pr.fieldNameIndex('Image link') feature.setAttribute(field_index, filename) self.vl.startEditing() self.vl.addFeature(feature, True) self.vl.commitChanges() self.vl.setCacheImage(None) self.vl.triggerRepaint() os.rename(filename,self.path + '__'+ str(self.getImageFileName()) + '.jpg') self.ui.ExporText_button.setEnabled(True) self.ui.ExporShp_button.setEnabled(True) self.ui.ExporSqlite_button.setEnabled(True) self.ui.ExporKML_button.setEnabled(True) def getImageFileName(self): current_time_now = time.time() ctn_int = int(current_time_now) return ctn_int def transform_wgs84_to_utm(self, lon, lat): def get_utm_zone(longitude): return (int(1+(longitude+180.0)/6.0)) def is_northern(latitude): """ Determines if given latitude is a northern for UTM """ if (latitude < 0.0): return 0 else: return 1 utm_coordinate_system = osr.SpatialReference() utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat)) wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system # create transform component wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>) return wgs84_to_utm_transform.TransformPoint(lon, lat, 0) # returns easting, northing, altitude def snapshot(self): Point = QgsPoint(self.Point) Point.set(self.lat,self.lon) self.positionMarker.newCoords(Point) self.AddPoint(Point) def Help(self): path_help = 'C:/Users/Administrator/.qgis2' os.startfile(path_help + '/python/plugins/Cu_Video_Tracker/How to.pdf') def exportText(self): toCSV = QgsVectorFileWriter.writeAsVectorFormat(self.vl, self.path + '_''point'+'.csv', "TIS-620", None, "CSV") debug = self.path + '_''point'+'.csv' QtGui.QMessageBox.information(self, 'Export to', debug ) def exportShp(self): toShp = QgsVectorFileWriter.writeAsVectorFormat(self.vl, self.path + '_''point'+'.shp',"utf-8",None,"ESRI Shapefile") debug = self.path + '_''point'+'.shp' QtGui.QMessageBox.information(self, 'Export to', debug ) def exportSqlite(self): toSql = QgsVectorFileWriter.writeAsVectorFormat(self.vl, self.path + '_''point'+'.sqlite',"utf-8",None,"SQLite") debug = self.path + '_''point'+'.sqlite' QtGui.QMessageBox.information(self, 'Export to', debug ) def exportKML(self): toSql = QgsVectorFileWriter.writeAsVectorFormat(self.vl, self.path + '_''point'+'.kml',"utf-8",None,"KML") debug = self.path + '_''point'+'.kml' QtGui.QMessageBox.information(self, 'Export to', debug )