📄 qgsgpxprovider.cpp
字号:
/*************************************************************************** qgsgpxprovider.cpp - Data provider for GPS eXchange files ------------------- begin : 2004-04-14 copyright : (C) 2004 by Lars Luthman email : larsl@users.sourceforge.net Partly based on qgsdelimitedtextprovider.cpp, (C) 2004 Gary E. Sherman ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* $Id: qgsgpxprovider.cpp 8257 2008-03-21 00:45:50Z jef $ */#include <algorithm>#include <iostream>#include <limits>#include <cstring>#include <cmath>// Changed #include <qapp.h> to <qapplication.h>. Apparently some// debian distros do not include the qapp.h wrapper and the compilation// fails. [gsherman]#include <QApplication>#include <QFile>#include <QTextStream>#include <QObject>#include "qgis.h"#include "qgsapplication.h"#include "qgsdataprovider.h"#include "qgsfeature.h"#include "qgsfield.h"#include "qgsgeometry.h"#include "qgsspatialrefsys.h"#include "qgsrect.h"#include "qgsgpxprovider.h"#include "gpsdata.h"#include "qgslogger.h"const char* QgsGPXProvider::attr[] = { "name", "elevation", "symbol", "number", "comment", "description", "source", "url", "url name" };const QString GPX_KEY = "gpx";const QString GPX_DESCRIPTION = QObject::tr("GPS eXchange format provider");QgsGPXProvider::QgsGPXProvider(QString uri) : QgsVectorDataProvider(uri){ // assume that it won't work mValid = false; // we always use UTF-8 mEncoding = QTextCodec::codecForName("utf8"); // get the filename and the type parameter from the URI int fileNameEnd = uri.find('?'); if (fileNameEnd == -1 || uri.mid(fileNameEnd + 1, 5) != "type=") { QgsLogger::warning(tr("Bad URI - you need to specify the feature type.")); return; } QString typeStr = uri.mid(fileNameEnd + 6); mFeatureType = (typeStr == "waypoint" ? WaypointType : (typeStr == "route" ? RouteType : TrackType)); // set up the attributes and the geometry type depending on the feature type attributeFields[NameAttr] = QgsField(attr[NameAttr], QVariant::String, "text"); if (mFeatureType == WaypointType) { attributeFields[EleAttr] = QgsField(attr[EleAttr], QVariant::Double, "double"); attributeFields[SymAttr] = QgsField(attr[SymAttr], QVariant::String, "text"); } else if (mFeatureType == RouteType || mFeatureType == TrackType) { attributeFields[NumAttr] = QgsField(attr[NumAttr], QVariant::Int, "int"); } attributeFields[CmtAttr] = QgsField(attr[CmtAttr], QVariant::String, "text"); attributeFields[DscAttr] = QgsField(attr[DscAttr], QVariant::String, "text"); attributeFields[SrcAttr] = QgsField(attr[SrcAttr], QVariant::String, "text"); attributeFields[URLAttr] = QgsField(attr[URLAttr], QVariant::String, "text"); attributeFields[URLNameAttr] = QgsField(attr[URLNameAttr], QVariant::String, "text"); mFileName = uri.left(fileNameEnd); // set the selection rectangle to null mSelectionRectangle = 0; // parse the file data = GPSData::getData(mFileName); if (data == 0) { return; } mValid = true;}QgsGPXProvider::~QgsGPXProvider(){ GPSData::releaseData(mFileName);}QString QgsGPXProvider::storageType() const{ return tr("GPS eXchange file");}int QgsGPXProvider::capabilities() const{ return QgsVectorDataProvider::AddFeatures | QgsVectorDataProvider::DeleteFeatures | QgsVectorDataProvider::ChangeAttributeValues;}bool QgsGPXProvider::getNextFeature(QgsFeature& feature){ bool result = false; QgsAttributeList::const_iterator iter; if (mFeatureType == WaypointType) { // go through the list of waypoints and return the first one that is in // the bounds rectangle for (; mWptIter != data->waypointsEnd(); ++mWptIter) { const Waypoint* wpt; wpt = &(*mWptIter); if (boundsCheck(wpt->lon, wpt->lat)) { feature.setFeatureId(wpt->id); result = true; // some wkb voodoo if(mFetchGeom) { char* geo = new char[21]; std::memset(geo, 0, 21); geo[0] = QgsApplication::endian(); geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBPoint; std::memcpy(geo+5, &wpt->lon, sizeof(double)); std::memcpy(geo+13, &wpt->lat, sizeof(double)); feature.setGeometryAndOwnership((unsigned char *)geo, sizeof(wkbPoint)); } feature.setValid(true); // add attributes if they are wanted for (iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter) { switch (*iter) { case NameAttr: feature.addAttribute(NameAttr, QVariant(wpt->name)); break; case EleAttr: if (wpt->ele != -std::numeric_limits<double>::max()) feature.addAttribute(EleAttr, QVariant(wpt->ele)); break; case SymAttr: feature.addAttribute(SymAttr, QVariant(wpt->sym)); break; case CmtAttr: feature.addAttribute(CmtAttr, QVariant(wpt->cmt)); break; case DscAttr: feature.addAttribute(DscAttr, QVariant(wpt->desc)); break; case SrcAttr: feature.addAttribute(SrcAttr, QVariant(wpt->src)); break; case URLAttr: feature.addAttribute(URLAttr, QVariant(wpt->url)); break; case URLNameAttr: feature.addAttribute(URLNameAttr, QVariant(wpt->urlname)); break; } } ++mWptIter; break; } } } else if (mFeatureType == RouteType) { // go through the routes and return the first one that is in the bounds // rectangle for (; mRteIter != data->routesEnd(); ++mRteIter) { const Route* rte; rte = &(*mRteIter); if (rte->points.size() == 0) continue; const QgsRect& b(*mSelectionRectangle); if ((rte->xMax >= b.xMin()) && (rte->xMin <= b.xMax()) && (rte->yMax >= b.yMin()) && (rte->yMin <= b.yMax())) { feature.setFeatureId(rte->id); result = true; // some wkb voodoo if(mFetchGeom) { int nPoints = rte->points.size(); char* geo = new char[9 + 16 * nPoints]; std::memset(geo, 0, 9 + 16 * nPoints); geo[0] = QgsApplication::endian(); geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBLineString; std::memcpy(geo + 5, &nPoints, 4); for (uint i = 0; i < rte->points.size(); ++i) { std::memcpy(geo + 9 + 16 * i, &rte->points[i].lon, sizeof(double)); std::memcpy(geo + 9 + 16 * i + 8, &rte->points[i].lat, sizeof(double)); } feature.setGeometryAndOwnership((unsigned char *)geo, 9 + 16 * nPoints); } feature.setValid(true); // add attributes if they are wanted for (iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter) { switch (*iter) { case NameAttr: feature.addAttribute(NameAttr, QVariant(rte->name)); break; case NumAttr: if (rte->number != std::numeric_limits<int>::max()) feature.addAttribute(NumAttr, QVariant(rte->number)); break; case CmtAttr: feature.addAttribute(CmtAttr, QVariant(rte->cmt)); break; case DscAttr: feature.addAttribute(DscAttr, QVariant(rte->desc)); break; case SrcAttr: feature.addAttribute(SrcAttr, QVariant(rte->src)); break; case URLAttr: feature.addAttribute(URLAttr, QVariant(rte->url)); break; case URLNameAttr: feature.addAttribute(URLNameAttr, QVariant(rte->urlname)); break; } } ++mRteIter; break; } } } else if (mFeatureType == TrackType) { // go through the tracks and return the first one that is in the bounds // rectangle for (; mTrkIter != data->tracksEnd(); ++mTrkIter) { const Track* trk; trk = &(*mTrkIter); QgsLogger::debug("GPX feature track segments: ", trk->segments.size(), __FILE__, __FUNCTION__, __LINE__); if (trk->segments.size() == 0) continue; // A track consists of several segments. Add all those segments into one. int totalPoints = 0;; for (std::vector<TrackSegment>::size_type i = 0; i < trk->segments.size(); i ++) { totalPoints += trk->segments[i].points.size(); } if (totalPoints == 0) continue; QgsDebugMsg("GPX feature track total points: " + QString::number(totalPoints)); const QgsRect& b(*mSelectionRectangle); if ((trk->xMax >= b.xMin()) && (trk->xMin <= b.xMax()) && (trk->yMax >= b.yMin()) && (trk->yMin <= b.yMax())) { feature.setFeatureId(trk->id); result = true; // some wkb voodoo if(mFetchGeom) { char* geo = new char[9 + 16 * totalPoints]; if (!geo) { QgsDebugMsg("Too large track!!!"); return false; } std::memset(geo, 0, 9 + 16 * totalPoints); geo[0] = QgsApplication::endian(); geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBLineString; std::memcpy(geo + 5, &totalPoints, 4); int thisPoint = 0; for(std::vector<TrackSegment>::size_type k = 0; k < trk->segments.size(); k++) { int nPoints = trk->segments[k].points.size(); for (int i = 0; i < nPoints; ++i) { std::memcpy(geo + 9 + 16 * thisPoint, &trk->segments[k].points[i].lon, sizeof(double)); std::memcpy(geo + 9 + 16 * thisPoint + 8, &trk->segments[k].points[i].lat, sizeof(double)); thisPoint++; } } feature.setGeometryAndOwnership((unsigned char *)geo, 9 + 16 * totalPoints); } feature.setValid(true); // add attributes if they are wanted for (iter = mAttributesToFetch.begin(); iter != mAttributesToFetch.end(); ++iter) { switch (*iter) { case NameAttr: feature.addAttribute(NameAttr, QVariant(trk->name)); break; case NumAttr: if (trk->number != std::numeric_limits<int>::max()) feature.addAttribute(NumAttr, QVariant(trk->number)); break; case CmtAttr: feature.addAttribute(CmtAttr, QVariant(trk->cmt)); break; case DscAttr: feature.addAttribute(DscAttr, QVariant(trk->desc)); break; case SrcAttr: feature.addAttribute(SrcAttr, QVariant(trk->src)); break; case URLAttr: feature.addAttribute(URLAttr, QVariant(trk->url)); break; case URLNameAttr: feature.addAttribute(URLNameAttr, QVariant(trk->urlname)); break; } } ++mTrkIter; break; } } } return result;}void QgsGPXProvider::select(QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, bool useIntersect){ if(rect.isEmpty()) { mSelectionRectangle = new QgsRect(extent()); } else { mSelectionRectangle = new QgsRect(rect); } mAttributesToFetch = fetchAttributes; mFetchGeom = fetchGeometry; reset();}// Return the extent of the layerQgsRect QgsGPXProvider::extent(){ return data->getExtent();}/** * Return the feature type */QGis::WKBTYPE QgsGPXProvider::geometryType() const{ if (mFeatureType == WaypointType) return QGis::WKBPoint; if (mFeatureType == RouteType || mFeatureType == TrackType) return QGis::WKBLineString; return QGis::WKBUnknown;}/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -