📄 qgswfsprovider.cpp
字号:
complexTypeType = typeElement.attribute("type"); if(complexTypeType.isEmpty()) { return 3; } //remove the namespace on complexTypeType if(complexTypeType.contains(":")) { complexTypeType = complexTypeType.section(":", 1, 1); } //find <complexType name=complexTypeType QDomNodeList complexTypeNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "complexType"); for(uint i = 0; i < complexTypeNodeList.length(); ++i) { if(complexTypeNodeList.at(i).toElement().attribute("name") == complexTypeType) { complexTypeElement = complexTypeNodeList.at(i).toElement(); break; } } } if(complexTypeElement.isNull()) { return 4; } //we have the relevant <complexType> element. Now find out the geometry and the thematic attributes QDomNodeList attributeNodeList = complexTypeElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element"); if(attributeNodeList.size() < 1) { return 5; } for(uint i = 0; i < attributeNodeList.length(); ++i) { QDomElement attributeElement = attributeNodeList.at(i).toElement(); //attribute name QString name = attributeElement.attribute("name"); //attribute type QString type = attributeElement.attribute("type"); //is it a geometry attribute? if(type.startsWith("gml:") && type.endsWith("PropertyType")) { geometryAttribute = name; } else //todo: distinguish between numerical and non-numerical types { fields[fields.size()] = QgsField(name, QVariant::String, type); } } return 0;}int QgsWFSProvider::guessAttributesFromFile(const QString& uri, QString& geometryAttribute, std::list<QString>& thematicAttributes) const{ QFile gmlFile(uri); if(!gmlFile.open(QIODevice::ReadOnly)) { return 1; } QDomDocument gmlDoc; if(!gmlDoc.setContent(&gmlFile, true)) { return 2; //xml file not readable or not valid } //find gmlCollection element QDomElement featureCollectionElement = gmlDoc.documentElement(); //get the first feature to guess attributes QDomNodeList featureList = featureCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember"); if(featureList.size() < 1) { return 3; //we need at least one attribute } QDomElement featureElement = featureList.at(0).toElement(); QDomNode attributeNode = featureElement.firstChild().firstChild(); if(attributeNode.isNull()) { return 4; } QString attributeText; QDomElement attributeChildElement; QString attributeChildLocalName; while(!attributeNode.isNull())//loop over attributes { QString attributeNodeName = attributeNode.toElement().localName(); attributeChildElement = attributeNode.firstChild().toElement(); if(attributeChildElement.isNull())//no child element means it is a thematic attribute for sure { thematicAttributes.push_back(attributeNode.toElement().localName()); attributeNode = attributeNode.nextSibling(); continue; } attributeChildLocalName = attributeChildElement.localName(); if(attributeChildLocalName == "Point" || attributeChildLocalName == "LineString" || \attributeChildLocalName == "Polygon" || attributeChildLocalName == "MultiPoint" || \attributeChildLocalName == "MultiLineString" || attributeChildLocalName == "MultiPolygon" || \ attributeChildLocalName == "Surface" || attributeChildLocalName == "MultiSurface") { geometryAttribute = attributeNode.toElement().localName(); //a geometry attribute } else { thematicAttributes.push_back(attributeNode.toElement().localName()); //a thematic attribute } attributeNode = attributeNode.nextSibling(); } return 0;}int QgsWFSProvider::getExtentFromGML2(QgsRect* extent, const QDomElement& wfsCollectionElement) const{ QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "boundedBy"); if(boundedByList.length() < 1) { return 1; } QDomElement boundedByElement = boundedByList.at(0).toElement(); QDomNode childNode = boundedByElement.firstChild(); if(childNode.isNull()) { return 2; } //support <gml:Box>, <gml:coordinates> and <gml:Envelope>,<gml::lowerCorner>,<gml::upperCorner>. What //about <gml:Envelope>, <gml:pos>? QString bboxName = childNode.localName(); if(bboxName != "Box") { return 3; } QDomNode coordinatesNode = childNode.firstChild(); if(coordinatesNode.localName() == "coordinates") { std::list<QgsPoint> boundingPoints; if(readGML2Coordinates(boundingPoints, coordinatesNode.toElement()) != 0) { return 5; } if(boundingPoints.size() != 2) { return 6; } std::list<QgsPoint>::const_iterator it = boundingPoints.begin(); extent->setXmin(it->x()); extent->setYmin(it->y()); ++it; extent->setXmax(it->x()); extent->setYmax(it->y()); return 0; } else if(coordinatesNode.localName() == "coord") { //first <coord> element QDomElement xElement, yElement; bool conversion1, conversion2; //string->double conversion success xElement = coordinatesNode.firstChild().toElement(); yElement = xElement.nextSibling().toElement(); if(xElement.isNull() || yElement.isNull()) { return 7; } double x1 = xElement.text().toDouble(&conversion1); double y1 = yElement.text().toDouble(&conversion2); if(!conversion1 || !conversion2) { return 8; } //second <coord> element coordinatesNode = coordinatesNode.nextSibling(); xElement = coordinatesNode.firstChild().toElement(); yElement = xElement.nextSibling().toElement(); if(xElement.isNull() || yElement.isNull()) { return 9; } double x2 = xElement.text().toDouble(&conversion1); double y2 = yElement.text().toDouble(&conversion2); if(!conversion1 || !conversion2) { return 10; } extent->setXmin(x1); extent->setYmin(y1); extent->setXmax(x2); extent->setYmax(y2); return 0; } else { return 11; //no valid tag for the bounding box }}int QgsWFSProvider::setSRSFromGML2(const QDomElement& wfsCollectionElement){ QgsDebugMsg("entering QgsWFSProvider::setSRSFromGML"); //search <gml:boundedBy> QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "boundedBy"); if(boundedByList.size() < 1) { QgsDebugMsg("Error, could not find boundedBy element"); return 1; } //search <gml:Envelope> QDomElement boundedByElem = boundedByList.at(0).toElement(); QDomNodeList boxList = boundedByElem.elementsByTagNameNS(GML_NAMESPACE, "Box"); if(boxList.size() < 1) { QgsDebugMsg("Error, could not find Envelope element"); return 2; } QDomElement boxElem = boxList.at(0).toElement(); //getAttribute 'srsName' QString srsName = boxElem.attribute("srsName"); if(srsName.isEmpty()) { QgsDebugMsg("Error, srsName is empty"); return 3; } QgsDebugMsg("srsName is: " +srsName); //extract the EPSG id int epsgId; bool conversionSuccess; if(srsName.contains("#"))//geoserver has "http://www.opengis.net/gml/srs/epsg.xml#4326" { epsgId = srsName.section("#", 1, 1).toInt(&conversionSuccess); if(!conversionSuccess) { return 4; } } else if(srsName.contains(":"))//mapserver has "EPSG:4326" { epsgId = srsName.section(":", 1, 1).toInt(&conversionSuccess); if(!conversionSuccess) { return 5; } } if(!mSourceSRS.createFromEpsg(epsgId)) { QgsDebugMsg("Error, creation of QgsSpatialRefSys failed"); return 6; } return 0;} int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute){ QDomNodeList featureTypeNodeList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember"); QDomElement currentFeatureMemberElem; QDomElement layerNameElem; QDomNode currentAttributeChild; QDomElement currentAttributeElement; int counter = 0; QgsFeature* f = 0; unsigned char* wkb = 0; int wkbSize = 0; QGis::WKBTYPE currentType; QgsRect featureBBox; GEOS_GEOM::Envelope* geosBBox; mFeatureCount = 0; for(int i = 0; i < featureTypeNodeList.size(); ++i) { f = new QgsFeature(counter); currentFeatureMemberElem = featureTypeNodeList.at(i).toElement(); //the first child element is always <namespace:layer> layerNameElem = currentFeatureMemberElem.firstChild().toElement(); //the children are the attributes currentAttributeChild = layerNameElem.firstChild(); int attr = 0; bool numeric = false; while(!currentAttributeChild.isNull()) { currentAttributeElement = currentAttributeChild.toElement(); if(currentAttributeElement.localName() != "boundedBy") { currentAttributeElement.text().toDouble(&numeric); if((currentAttributeElement.localName()) != geometryAttribute) //a normal attribute { if(numeric) { f->addAttribute(attr++, QVariant(currentAttributeElement.text().toDouble())); } else { f->addAttribute(attr++, QVariant(currentAttributeElement.text())); } } else //a geometry attribute { getWkbFromGML2(currentAttributeElement, &wkb, &wkbSize, ¤tType); mWKBType = currentType; //a more sophisticated method is necessary f->setGeometryAndOwnership(wkb, wkbSize); } } currentAttributeChild = currentAttributeChild.nextSibling(); } if(wkb && wkbSize > 0) { //insert bbox and pointer to feature into search tree featureBBox = f->geometry()->boundingBox(); geosBBox = new GEOS_GEOM::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax()); mSpatialIndex.insert(geosBBox, (void*)f); mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, f)); ++mFeatureCount; } ++counter; } return 0;}int QgsWFSProvider::getWkbFromGML2(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const{ QDomNode geometryChild = geometryElement.firstChild(); if(geometryChild.isNull()) { return 1; } QDomElement geometryTypeElement = geometryChild.toElement(); QString geomType = geometryTypeElement.localName(); if(geomType == "Point") { return getWkbFromGML2Point(geometryTypeElement, wkb, wkbSize, type); } else if(geomType == "LineString") { return getWkbFromGML2LineString(geometryTypeElement, wkb, wkbSize, type); } else if(geomType == "Polygon") { return getWkbFromGML2Polygon(geometryTypeElement, wkb, wkbSize, type); } else if(geomType == "MultiPoint") { return getWkbFromGML2MultiPoint(geometryTypeElement, wkb, wkbSize, type); } else if(geomType == "MultiLineString") { return getWkbFromGML2MultiLineString(geometryTypeElement, wkb, wkbSize, type); } else if(geomType == "MultiPolygon") { return getWkbFromGML2MultiPolygon(geometryTypeElement, wkb, wkbSize, type); } else //unknown type { *wkb = 0; *wkbSize = 0; } return 0;}int QgsWFSProvider::getWkbFromGML2Point(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const{ QDomNodeList coordList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates"); if(coordList.size() < 1) { return 1; } QDomElement coordElement = coordList.at(0).toElement(); std::list<QgsPoint> pointCoordinate; if(readGML2Coordinates(pointCoordinate, coordElement) != 0) { return 2; } if(pointCoordinate.size() < 1) { return 3; } std::list<QgsPoint>::const_iterator point_it = pointCoordinate.begin(); char e = QgsApplication::endian(); double x = point_it->x(); double y = point_it->y(); int size = 1 + sizeof(int) + 2 * sizeof(double); *wkb = new unsigned char[size]; *wkbSize = size; *type = QGis::WKBPoint; int wkbPosition = 0; //current offset from wkb beginning (in bytes) memcpy(&(*wkb)[wkbPosition], &e, 1); wkbPosition += 1; memcpy(&(*wkb)[wkbPosition], type, sizeof(int)); wkbPosition += sizeof(int); memcpy(&(*wkb)[wkbPosition], &x, sizeof(double)); wkbPosition += sizeof(double); memcpy(&(*wkb)[wkbPosition], &y, sizeof(double)); return 0;}int QgsWFSProvider::getWkbFromGML2Polygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const{ //read all the coordinates (as QgsPoint) into memory. Each linear ring has an entry in the vector std::vector<std::list<QgsPoint> > ringCoordinates; //read coordinates for outer boundary QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "outerBoundaryIs"); if(outerBoundaryList.size() < 1) //outer ring is necessary { return 1; } QDomElement coordinatesElement = outerBoundaryList.at(0).firstChild().firstChild().toElement(); if(coordinatesElement.isNull()) { return 2; } std::list<QgsPoint> exteriorPointList; if(readGML2Coordinates(exteriorPointList, coordinatesElement) != 0) { return 3; } ringCoordinates.push_back(exteriorPointList); //read coordinates for inner boundary QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "innerBoundaryIs"); for(int i = 0; i < innerBoundaryList.size(); ++i) { std::list<QgsPoint> interiorPointList; QDomElement coordinatesElement = innerBoundaryList.at(i).firstChild().firstChild().toElement(); if(coordinatesElement.isNull()) { return 4; } if(readGML2Coordinates(interiorPointList, coordinatesElement) != 0) { return 5; } ringCoordinates.push_back(interiorPointList); } //calculate number of bytes to allocate int nrings = ringCoordinates.size(); int npoints = 0;//total number of points for(std::vector<std::list<QgsPoint> >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it) { npoints += it->size(); } int size = 1 + 2 * sizeof(int) + nrings * sizeof(int) + 2 * npoints * sizeof(double); *wkb = new unsigned char[size]; *wkbSize = size; *type = QGis::WKBPolygon; char e = QgsApplication::endian(); int wkbPosition = 0; //current offset from wkb beginning (in bytes) int nPointsInRing = 0; double x, y; //fill the contents into *wkb memcpy(&(*wkb)[wkbPosition], &e, 1); wkbPosition += 1; memcpy(&(*wkb)[wkbPosition], type, sizeof(int)); wkbPosition += sizeof(int); memcpy(&(*wkb)[wkbPosition], &nrings, sizeof(int)); wkbPosition += sizeof(int);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -