Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: KML Driver 4 : * Purpose: Specialization of the kml class, only for vectors in kml files. 5 : * Author: Jens Oberender, j.obi@troja.net 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2007, Jens Oberender 9 : * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com> 10 : * 11 : * SPDX-License-Identifier: MIT 12 : ****************************************************************************/ 13 : 14 : #include "cpl_port.h" 15 : #include "kmlvector.h" 16 : 17 : #include <string> 18 : 19 : #include "cpl_conv.h" 20 : #include "cpl_error.h" 21 : // #include "kmlnode.h" 22 : #include "kmlutility.h" 23 : 24 5675 : bool KMLVector::isLeaf(std::string const &sIn) const 25 : { 26 15851 : return sIn.compare("name") == 0 || sIn.compare("coordinates") == 0 || 27 15851 : sIn.compare("altitudeMode") == 0 || sIn.compare("description") == 0; 28 : } 29 : 30 : // Container - FeatureContainer - Feature 31 : 32 5994 : bool KMLVector::isContainer(std::string const &sIn) const 33 : { 34 11577 : return sIn.compare("Folder") == 0 || sIn.compare("Document") == 0 || 35 11577 : sIn.compare("kml") == 0; 36 : } 37 : 38 6130 : bool KMLVector::isFeatureContainer(std::string const &sIn) const 39 : { 40 12249 : return sIn.compare("MultiGeometry") == 0 || 41 6119 : sIn.compare("MultiPolygon") == 0 // non conformant 42 6118 : || sIn.compare("MultiLineString") == 0 // non conformant 43 6117 : || sIn.compare("MultiPoint") == 0 // non conformant 44 12249 : || sIn.compare("Placemark") == 0; 45 : } 46 : 47 4756 : bool KMLVector::isFeature(std::string const &sIn) const 48 : { 49 9275 : return sIn.compare("Polygon") == 0 || sIn.compare("LineString") == 0 || 50 9275 : sIn.compare("Point") == 0; 51 : } 52 : 53 5726 : bool KMLVector::isRest(std::string const &sIn) const 54 : { 55 11228 : return sIn.compare("outerBoundaryIs") == 0 || 56 11228 : sIn.compare("innerBoundaryIs") == 0 || 57 11192 : sIn.compare("LinearRing") == 0; 58 : } 59 : 60 147 : void KMLVector::findLayers(KMLNode *poNode, int bKeepEmptyContainers) 61 : { 62 147 : bool bEmpty = true; 63 : 64 : // Start with the trunk 65 147 : if (nullptr == poNode) 66 : { 67 24 : nNumLayers_ = 0; 68 24 : poNode = poTrunk_; 69 : } 70 : 71 294 : if (isFeature(poNode->getName()) || isFeatureContainer(poNode->getName()) || 72 147 : (isRest(poNode->getName()) && poNode->getName().compare("kml") != 0)) 73 : { 74 0 : return; 75 : } 76 147 : else if (isContainer(poNode->getName())) 77 : { 78 738 : for (std::size_t z = 0; z < poNode->countChildren(); z++) 79 : { 80 591 : if (isContainer(poNode->getChild(z)->getName())) 81 : { 82 123 : findLayers(poNode->getChild(z), bKeepEmptyContainers); 83 : } 84 468 : else if (isFeatureContainer(poNode->getChild(z)->getName())) 85 : { 86 254 : bEmpty = false; 87 : } 88 : } 89 : 90 147 : if (bKeepEmptyContainers && poNode->getName() == "Folder") 91 : { 92 6 : if (!bEmpty) 93 3 : poNode->eliminateEmpty(this); 94 : } 95 141 : else if (bEmpty) 96 : { 97 63 : return; 98 : } 99 : 100 84 : Nodetype nodeType = poNode->getType(); 101 162 : if (bKeepEmptyContainers || isFeature(Nodetype2String(nodeType)) || 102 3 : nodeType == Mixed || nodeType == MultiGeometry || 103 162 : nodeType == MultiPoint || nodeType == MultiLineString || 104 0 : nodeType == MultiPolygon) 105 : { 106 84 : poNode->setLayerNumber(nNumLayers_++); 107 84 : papoLayers_ = static_cast<KMLNode **>( 108 84 : CPLRealloc(papoLayers_, nNumLayers_ * sizeof(KMLNode *))); 109 84 : papoLayers_[nNumLayers_ - 1] = poNode; 110 : } 111 : else 112 : { 113 0 : CPLDebug("KML", "We have a strange type here for node %s: %s", 114 0 : poNode->getName().c_str(), 115 0 : Nodetype2String(poNode->getType()).c_str()); 116 : } 117 : } 118 : else 119 : { 120 0 : CPLDebug("KML", 121 : "There is something wrong! Define KML_DEBUG to see details"); 122 0 : if (CPLGetConfigOption("KML_DEBUG", nullptr) != nullptr) 123 0 : print(); 124 : } 125 : } 126 : 127 1892 : void KMLVector::findSchemas(KMLNode *poNode) 128 : { 129 1892 : if (nullptr == poNode) 130 : { 131 24 : poNode = poTrunk_; 132 : } 133 1892 : if (poNode->getType() == Schema) 134 : { 135 2 : std::string osSchemaId; 136 3 : for (const auto *poAttr : poNode->getAttributes()) 137 : { 138 2 : if (poAttr->sName == "id") 139 1 : osSchemaId = poAttr->sValue; 140 : } 141 1 : if (!osSchemaId.empty()) 142 : { 143 2 : std::vector<std::unique_ptr<OGRFieldDefn>> fields; 144 : 145 4 : for (std::size_t z = 0; z < poNode->countChildren(); z++) 146 : { 147 3 : auto poChild = poNode->getChild(z); 148 3 : if (poChild->getType() == SimpleField) 149 : { 150 6 : std::string osAttrName; 151 6 : std::string osAttrType; 152 9 : for (const auto *poAttr : poChild->getAttributes()) 153 : { 154 6 : if (poAttr->sName == "name") 155 3 : osAttrName = poAttr->sValue; 156 3 : else if (poAttr->sName == "type") 157 3 : osAttrType = poAttr->sValue; 158 : } 159 3 : if (!osAttrName.empty() && !osAttrType.empty()) 160 : { 161 3 : if (osAttrType == "string") 162 1 : fields.push_back(std::make_unique<OGRFieldDefn>( 163 2 : osAttrName.c_str(), OFTString)); 164 2 : else if (osAttrType == "float") 165 1 : fields.push_back(std::make_unique<OGRFieldDefn>( 166 2 : osAttrName.c_str(), OFTReal)); 167 1 : else if (osAttrType == "int") 168 1 : fields.push_back(std::make_unique<OGRFieldDefn>( 169 2 : osAttrName.c_str(), OFTInteger)); 170 : } 171 : } 172 : } 173 : 174 1 : oMapSchemas_[osSchemaId] = std::move(fields); 175 : } 176 : } 177 : else 178 : { 179 3759 : for (std::size_t z = 0; z < poNode->countChildren(); z++) 180 : { 181 1868 : findSchemas(poNode->getChild(z)); 182 : } 183 : } 184 1892 : }