Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: KML Translator 4 : * Purpose: Implements OGRLIBKMLDriver 5 : * Author: Brian Case, rush at winkey dot org 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2010, Brian Case 9 : * 10 : * Permission is hereby granted, free of charge, to any person obtaining a 11 : * copy of this software and associated documentation files (the "Software"), 12 : * to deal in the Software without restriction, including without limitation 13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 : * and/or sell copies of the Software, and to permit persons to whom the 15 : * Software is furnished to do so, subject to the following conditions: 16 : * 17 : * The above copyright notice and this permission notice shall be included 18 : * in all copies or substantial portions of the Software. 19 : * 20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 : * DEALINGS IN THE SOFTWARE. 27 : *****************************************************************************/ 28 : 29 : #include "ogrsf_frmts.h" 30 : 31 : #include "ogrlibkmldrivercore.h" 32 : 33 : /************************************************************************/ 34 : /* OGRLIBKMLDriverIdentify() */ 35 : /************************************************************************/ 36 : 37 43772 : int OGRLIBKMLDriverIdentify(GDALOpenInfo *poOpenInfo) 38 : 39 : { 40 43772 : if (!poOpenInfo->bStatOK) 41 40271 : return FALSE; 42 3501 : if (poOpenInfo->bIsDirectory) 43 343 : return -1; 44 : 45 3158 : const char *pszExt = CPLGetExtension(poOpenInfo->pszFilename); 46 3158 : if (EQUAL(pszExt, "kml") || EQUAL(pszExt, "kmz")) 47 : { 48 159 : return TRUE; 49 : } 50 : 51 2999 : if (poOpenInfo->pabyHeader && 52 2994 : (strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), "<kml") != 53 2994 : nullptr || 54 2994 : strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), "<kml:kml") != 55 : nullptr)) 56 : { 57 0 : return TRUE; 58 : } 59 : 60 2999 : return FALSE; 61 : } 62 : 63 : /************************************************************************/ 64 : /* OGRLIBKMLDriverSetCommonMetadata() */ 65 : /************************************************************************/ 66 : 67 1234 : void OGRLIBKMLDriverSetCommonMetadata(GDALDriver *poDriver) 68 : { 69 1234 : poDriver->SetDescription(DRIVER_NAME); 70 1234 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 71 1234 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 72 1234 : poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES"); 73 1234 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 74 1234 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 75 1234 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 76 1234 : "Keyhole Markup Language (LIBKML)"); 77 1234 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "kml kmz"); 78 1234 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/libkml.html"); 79 1234 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); 80 : 81 1234 : poDriver->SetMetadataItem( 82 : GDAL_DMD_CREATIONOPTIONLIST, 83 : "<CreationOptionList>" 84 : " <Option name='DOCUMENT_ID' type='string' description='Id of the " 85 : "root <Document> node' default='root_doc'/>" 86 : " <Option name='AUTHOR_NAME' type='string' description='Name in " 87 : "<atom:Author> element'/>" 88 : " <Option name='AUTHOR_URI' type='string' description='URI in " 89 : "<atom:Author> element'/>" 90 : " <Option name='AUTHOR_EMAIL' type='string' description='Email in " 91 : "<atom:Author> element'/>" 92 : " <Option name='LINK' type='string' description='Href of " 93 : "<atom:link> element'/>" 94 : " <Option name='PHONENUMBER' type='string' description='Value of " 95 : "<phoneNumber> element'/>" 96 : " <Option name='NAME' type='string' description='Value of " 97 : "<name> element of top container'/>" 98 : " <Option name='VISIBILITY' type='integer' description='Value of " 99 : "<visibility> element of top container (0/1)'/>" 100 : " <Option name='OPEN' type='integer' description='Value of " 101 : "<open> element of top container (0/1)'/>" 102 : " <Option name='SNIPPET' type='string' description='Value of " 103 : "<snippet> element of top container'/>" 104 : " <Option name='DESCRIPTION' type='string' description='Value of " 105 : "<description> element of top container'/>" 106 : " <Option name='LISTSTYLE_TYPE' type='string-select' " 107 : "description='Value of <listItemType> element of top container'>" 108 : " <Value>check</Value>" 109 : " <Value>radioFolder</Value>" 110 : " <Value>checkOffOnly</Value>" 111 : " <Value>checkHideChildren</Value>" 112 : " </Option>" 113 : " <Option name='LISTSTYLE_ICON_HREF' type='string' description='URL " 114 : "of the icon to display for the main folder. Sets the href element of " 115 : "the <ItemIcon> element'/>" 116 : " <Option name='*_BALLOONSTYLE_BGCOLOR' type='string' " 117 : "description='Background color of a <BallonStyle> element if a " 118 : "style X is defined'/>" 119 : " <Option name='*_BALLOONSTYLE_TEXT' type='string' description='Text " 120 : "of a <BallonStyle> element if a style X is defined'/>" 121 : " <Option name='NLC_MINREFRESHPERIOD' type='float' " 122 : "description='<minRefreshPeriod> element of a " 123 : "<NetworkLinkControl> element'/>" 124 : " <Option name='NLC_MAXSESSIONLENGTH' type='float' " 125 : "description='<maxSessionLength> element of a " 126 : "<NetworkLinkControl> element'/>" 127 : " <Option name='NLC_COOKIE' type='string' description='<cookie> " 128 : "element of a <NetworkLinkControl> element'/>" 129 : " <Option name='NLC_MESSAGE' type='string' " 130 : "description='<message> element of a <NetworkLinkControl> " 131 : "element'/>" 132 : " <Option name='NLC_LINKNAME' type='string' " 133 : "description='<linkName> element of a <NetworkLinkControl> " 134 : "element'/>" 135 : " <Option name='NLC_LINKDESCRIPTION' type='string' " 136 : "description='<linkDescription> element of a " 137 : "<NetworkLinkControl> element'/>" 138 : " <Option name='NLC_LINKSNIPPET' type='string' " 139 : "description='<linkSnippet> element of a " 140 : "<NetworkLinkControl> element'/>" 141 : " <Option name='NLC_EXPIRES' type='string' description='Date to set " 142 : "in <expires> element of a <NetworkLinkControl> element'/>" 143 : " <Option name='UPDATE_TARGETHREF' type='string' description='If set, " 144 : "a NetworkLinkControl KML file with an <Update> element will be " 145 : "generated'/>" 146 1234 : "</CreationOptionList>"); 147 : 148 1234 : poDriver->SetMetadataItem( 149 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 150 : "<LayerCreationOptionList>" 151 : " <Option name='NAME' type='string' description='Value of " 152 : "<name> element of layer container'/>" 153 : " <Option name='VISIBILITY' type='integer' description='Value of " 154 : "<visibility> element of layer container (0/1)'/>" 155 : " <Option name='OPEN' type='integer' description='Value of " 156 : "<open> element of layer container (0/1)'/>" 157 : " <Option name='SNIPPET' type='string' description='Value of " 158 : "<snippet> element of layer container'/>" 159 : " <Option name='DESCRIPTION' type='string' description='Value of " 160 : "<description> element of layer container'/>" 161 : " <Option name='LOOKAT_LONGITUDE' type='float' " 162 : "description='<longitude> of a <LookAt> element at layer " 163 : "level' min='-180' max='180'/>" 164 : " <Option name='LOOKAT_LATITUDE' type='float' " 165 : "description='<latitude> of a <LookAt> element at layer " 166 : "level' min='-90' max='90'/>" 167 : " <Option name='LOOKAT_RANGE' type='float' description='<range> " 168 : "of a <LookAt> element at layer level' min='0'/>" 169 : " <Option name='LOOKAT_HEADING' type='float' " 170 : "description='<heading> of a <LookAt> element at layer " 171 : "level'/>" 172 : " <Option name='LOOKAT_TILT' type='float' description='<tilt> " 173 : "of a <LookAt> element at layer level'/>" 174 : " <Option name='LOOKAT_ALTITUDE' type='float' " 175 : "description='<altitude> of a <LookAt> element at layer " 176 : "level'/>" 177 : " <Option name='LOOKAT_ALTITUDEMODE' type='string-select' " 178 : "description='<altitudeMode> of a <LookAt> element at " 179 : "layer level'>" 180 : " <Value>clampToGround</Value>" 181 : " <Value>relativeToGround</Value>" 182 : " <Value>absolute</Value>" 183 : " <Value>clampToSeaFloor</Value>" 184 : " <Value>relativeToSeaFloor</Value>" 185 : " </Option>" 186 : " <Option name='CAMERA_LONGITUDE' type='float' " 187 : "description='<longitude> of a <Camera> element at layer " 188 : "level' min='-180' max='180'/>" 189 : " <Option name='CAMERA_LATITUDE' type='float' " 190 : "description='<latitude> of a <Camera> element at layer " 191 : "level' min='-90' max='90'/>" 192 : " <Option name='CAMERA_HEADING' type='float' " 193 : "description='<heading> of a <Camera> element at layer " 194 : "level'/>" 195 : " <Option name='CAMERA_TILT' type='float' description='<tilt> " 196 : "of a <Camera> element at layer level'/>" 197 : " <Option name='CAMERA_ROLL' type='float' description='<roll> " 198 : "of a <Camera> element at layer level'/>" 199 : " <Option name='CAMERA_ALTITUDE' type='float' " 200 : "description='<altitude> of a <Camera> element at layer " 201 : "level'/>" 202 : " <Option name='CAMERA_ALTITUDEMODE' type='string-select' " 203 : "description='<altitudeMode> of a <Camera> element at " 204 : "layer level'>" 205 : " <Value>clampToGround</Value>" 206 : " <Value>relativeToGround</Value>" 207 : " <Value>absolute</Value>" 208 : " <Value>clampToSeaFloor</Value>" 209 : " <Value>relativeToSeaFloor</Value>" 210 : " </Option>" 211 : " <Option name='ADD_REGION' type='boolean' description='Whether to " 212 : "generate a <Region> element to control when objects of the " 213 : "layer are visible or not' default='NO'/>" 214 : " <Option name='REGION_XMIN' type='float' description='West " 215 : "coordinate of the region' min='-180' max='180'/>" 216 : " <Option name='REGION_YMIN' type='float' description='South " 217 : "coordinate of the region' min='-90' max='90'/>" 218 : " <Option name='REGION_XMAX' type='float' description='East " 219 : "coordinate of the region' min='-180' max='180'/>" 220 : " <Option name='REGION_YMAX' type='float' description='North " 221 : "coordinate of the region' min='-90' max='90'/>" 222 : " <Option name='REGION_MIN_LOD_PIXELS' type='float' " 223 : "description='minimum size in pixels of the region so that it is " 224 : "displayed' default='256'/>" 225 : " <Option name='REGION_MAX_LOD_PIXELS' type='float' " 226 : "description='maximum size in pixels of the region so that it is " 227 : "displayed (-1=infinite)' default='-1'/>" 228 : " <Option name='REGION_MIN_FADE_EXTENT' type='float' " 229 : "description='distance over which the geometry fades, from fully " 230 : "opaque to fully transparent' default='0'/>" 231 : " <Option name='REGION_MAX_FADE_EXTENT' type='float' " 232 : "description='distance over which the geometry fades, from fully " 233 : "transparent to fully opaque' default='0'/>" 234 : " <Option name='SO_HREF' type='string' description='URL of the image " 235 : "to display in a <ScreenOverlay>'/>" 236 : " <Option name='SO_NAME' type='string' description='<name> of a " 237 : "<ScreenOverlay>'/>" 238 : " <Option name='SO_DESCRIPTION' type='string' " 239 : "description='<description> of a <ScreenOverlay>'/>" 240 : " <Option name='SO_OVERLAY_X' type='float' description='x attribute " 241 : "of the <overlayXY> of a <ScreenOverlay>'/>" 242 : " <Option name='SO_OVERLAY_Y' type='float' description='y attribute " 243 : "of the <overlayXY> of a <ScreenOverlay>'/>" 244 : " <Option name='SO_OVERLAY_XUNITS' type='string-select' " 245 : "description='xunits attribute of the <overlayXY> of a " 246 : "<ScreenOverlay>'>" 247 : " <Value>fraction</Value>" 248 : " <Value>pixels</Value>" 249 : " <Value>insetPixels</Value>" 250 : " </Option>" 251 : " <Option name='SO_OVERLAY_YUNITS' type='string-select' " 252 : "description='yunits attribute of the <overlayXY> of a " 253 : "<ScreenOverlay>'>" 254 : " <Value>fraction</Value>" 255 : " <Value>pixels</Value>" 256 : " <Value>insetPixels</Value>" 257 : " </Option>" 258 : " <Option name='SO_SCREEN_X' type='float' description='x attribute of " 259 : "the <screenXY> of a <ScreenOverlay>' default='0.05'/>" 260 : " <Option name='SO_SCREEN_Y' type='float' description='y attribute of " 261 : "the <screenXY> of a <ScreenOverlay>' default='0.05'/>" 262 : " <Option name='SO_SCREEN_XUNITS' type='string-select' " 263 : "description='xunits attribute of the <screenXY> of a " 264 : "<ScreenOverlay>' default='fraction'>" 265 : " <Value>fraction</Value>" 266 : " <Value>pixels</Value>" 267 : " <Value>insetPixels</Value>" 268 : " </Option>" 269 : " <Option name='SO_SCREEN_YUNITS' type='string-select' " 270 : "description='yunits attribute of the <screenXY> of a " 271 : "<ScreenOverlay>' default='fraction'>" 272 : " <Value>fraction</Value>" 273 : " <Value>pixels</Value>" 274 : " <Value>insetPixels</Value>" 275 : " </Option>" 276 : " <Option name='SO_SIZE_X' type='float' description='x attribute of " 277 : "the <sizeXY> of a <ScreenOverlay>'/>" 278 : " <Option name='SO_SIZE_Y' type='float' description='y attribute of " 279 : "the <sizeXY> of a <ScreenOverlay>'/>" 280 : " <Option name='SO_SIZE_XUNITS' type='string-select' " 281 : "description='xunits attribute of the <sizeXY> of a " 282 : "<ScreenOverlay>'>" 283 : " <Value>fraction</Value>" 284 : " <Value>pixels</Value>" 285 : " <Value>insetPixels</Value>" 286 : " </Option>" 287 : " <Option name='SO_SIZE_YUNITS' type='string-select' " 288 : "description='yunits attribute of the <sizeXY> of a " 289 : "<ScreenOverlay>'>" 290 : " <Value>fraction</Value>" 291 : " <Value>pixels</Value>" 292 : " <Value>insetPixels</Value>" 293 : " </Option>" 294 : " <Option name='FOLDER' type='boolean' description='Whether to " 295 : "generate a <Folder> element for layers, instead of a " 296 : "<Document>' default='NO'/>" 297 : " <Option name='LISTSTYLE_TYPE' type='string-select' " 298 : "description='Value of <listItemType> element of layer " 299 : "container'>" 300 : " <Value>check</Value>" 301 : " <Value>radioFolder</Value>" 302 : " <Value>checkOffOnly</Value>" 303 : " <Value>checkHideChildren</Value>" 304 : " </Option>" 305 : " <Option name='LISTSTYLE_ICON_HREF' type='string' description='URL " 306 : "of the icon to display for the layer folder. Sets the href element of " 307 : "the <ItemIcon> element'/>" 308 1234 : "</LayerCreationOptionList>"); 309 : 310 1234 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 311 1234 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES, 312 1234 : "Integer Real String"); 313 1234 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES"); 314 1234 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES"); 315 1234 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES"); 316 1234 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES"); 317 : 318 1234 : poDriver->pfnIdentify = OGRLIBKMLDriverIdentify; 319 1234 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 320 1234 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES"); 321 1234 : } 322 : 323 : /************************************************************************/ 324 : /* DeclareDeferredOGRLIBKMLPlugin() */ 325 : /************************************************************************/ 326 : 327 : #ifdef PLUGIN_FILENAME 328 1512 : void DeclareDeferredOGRLIBKMLPlugin() 329 : { 330 1512 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 331 : { 332 295 : return; 333 : } 334 1217 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); 335 : #ifdef PLUGIN_INSTALLATION_MESSAGE 336 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, 337 : PLUGIN_INSTALLATION_MESSAGE); 338 : #endif 339 1217 : OGRLIBKMLDriverSetCommonMetadata(poDriver); 340 1217 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 341 : } 342 : #endif