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 : * SPDX-License-Identifier: MIT 11 : *****************************************************************************/ 12 : 13 : #include "ogrsf_frmts.h" 14 : 15 : #include "ogrlibkmldrivercore.h" 16 : 17 : /************************************************************************/ 18 : /* OGRLIBKMLDriverIdentify() */ 19 : /************************************************************************/ 20 : 21 46508 : int OGRLIBKMLDriverIdentify(GDALOpenInfo *poOpenInfo) 22 : 23 : { 24 46508 : if (!poOpenInfo->bStatOK) 25 42708 : return FALSE; 26 3800 : if (poOpenInfo->bIsDirectory) 27 370 : return -1; 28 : 29 3430 : const char *pszExt = CPLGetExtension(poOpenInfo->pszFilename); 30 3430 : if (EQUAL(pszExt, "kml") || EQUAL(pszExt, "kmz")) 31 : { 32 253 : return TRUE; 33 : } 34 : 35 3177 : if (poOpenInfo->pabyHeader && 36 3172 : (strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), "<kml") != 37 3172 : nullptr || 38 3172 : strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader), "<kml:kml") != 39 : nullptr)) 40 : { 41 0 : return TRUE; 42 : } 43 : 44 3177 : return FALSE; 45 : } 46 : 47 : /************************************************************************/ 48 : /* OGRLIBKMLDriverSetCommonMetadata() */ 49 : /************************************************************************/ 50 : 51 1317 : void OGRLIBKMLDriverSetCommonMetadata(GDALDriver *poDriver) 52 : { 53 1317 : poDriver->SetDescription(DRIVER_NAME); 54 1317 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 55 1317 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 56 1317 : poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES"); 57 1317 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 58 1317 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 59 1317 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 60 1317 : "Keyhole Markup Language (LIBKML)"); 61 1317 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "kml kmz"); 62 1317 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/libkml.html"); 63 1317 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); 64 : 65 1317 : poDriver->SetMetadataItem( 66 : GDAL_DMD_CREATIONOPTIONLIST, 67 : "<CreationOptionList>" 68 : " <Option name='DOCUMENT_ID' type='string' description='Id of the " 69 : "root <Document> node' default='root_doc'/>" 70 : " <Option name='AUTHOR_NAME' type='string' description='Name in " 71 : "<atom:Author> element'/>" 72 : " <Option name='AUTHOR_URI' type='string' description='URI in " 73 : "<atom:Author> element'/>" 74 : " <Option name='AUTHOR_EMAIL' type='string' description='Email in " 75 : "<atom:Author> element'/>" 76 : " <Option name='LINK' type='string' description='Href of " 77 : "<atom:link> element'/>" 78 : " <Option name='PHONENUMBER' type='string' description='Value of " 79 : "<phoneNumber> element'/>" 80 : " <Option name='NAME' type='string' description='Value of " 81 : "<name> element of top container'/>" 82 : " <Option name='VISIBILITY' type='integer' description='Value of " 83 : "<visibility> element of top container (0/1)'/>" 84 : " <Option name='OPEN' type='integer' description='Value of " 85 : "<open> element of top container (0/1)'/>" 86 : " <Option name='SNIPPET' type='string' description='Value of " 87 : "<snippet> element of top container'/>" 88 : " <Option name='DESCRIPTION' type='string' description='Value of " 89 : "<description> element of top container'/>" 90 : " <Option name='LISTSTYLE_TYPE' type='string-select' " 91 : "description='Value of <listItemType> element of top container'>" 92 : " <Value>check</Value>" 93 : " <Value>radioFolder</Value>" 94 : " <Value>checkOffOnly</Value>" 95 : " <Value>checkHideChildren</Value>" 96 : " </Option>" 97 : " <Option name='LISTSTYLE_ICON_HREF' type='string' description='URL " 98 : "of the icon to display for the main folder. Sets the href element of " 99 : "the <ItemIcon> element'/>" 100 : " <Option name='*_BALLOONSTYLE_BGCOLOR' type='string' " 101 : "description='Background color of a <BallonStyle> element if a " 102 : "style X is defined'/>" 103 : " <Option name='*_BALLOONSTYLE_TEXT' type='string' description='Text " 104 : "of a <BallonStyle> element if a style X is defined'/>" 105 : " <Option name='NLC_MINREFRESHPERIOD' type='float' " 106 : "description='<minRefreshPeriod> element of a " 107 : "<NetworkLinkControl> element'/>" 108 : " <Option name='NLC_MAXSESSIONLENGTH' type='float' " 109 : "description='<maxSessionLength> element of a " 110 : "<NetworkLinkControl> element'/>" 111 : " <Option name='NLC_COOKIE' type='string' description='<cookie> " 112 : "element of a <NetworkLinkControl> element'/>" 113 : " <Option name='NLC_MESSAGE' type='string' " 114 : "description='<message> element of a <NetworkLinkControl> " 115 : "element'/>" 116 : " <Option name='NLC_LINKNAME' type='string' " 117 : "description='<linkName> element of a <NetworkLinkControl> " 118 : "element'/>" 119 : " <Option name='NLC_LINKDESCRIPTION' type='string' " 120 : "description='<linkDescription> element of a " 121 : "<NetworkLinkControl> element'/>" 122 : " <Option name='NLC_LINKSNIPPET' type='string' " 123 : "description='<linkSnippet> element of a " 124 : "<NetworkLinkControl> element'/>" 125 : " <Option name='NLC_EXPIRES' type='string' description='Date to set " 126 : "in <expires> element of a <NetworkLinkControl> element'/>" 127 : " <Option name='UPDATE_TARGETHREF' type='string' description='If set, " 128 : "a NetworkLinkControl KML file with an <Update> element will be " 129 : "generated'/>" 130 1317 : "</CreationOptionList>"); 131 : 132 1317 : poDriver->SetMetadataItem( 133 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 134 : "<LayerCreationOptionList>" 135 : " <Option name='NAME' type='string' description='Value of " 136 : "<name> element of layer container'/>" 137 : " <Option name='VISIBILITY' type='integer' description='Value of " 138 : "<visibility> element of layer container (0/1)'/>" 139 : " <Option name='OPEN' type='integer' description='Value of " 140 : "<open> element of layer container (0/1)'/>" 141 : " <Option name='SNIPPET' type='string' description='Value of " 142 : "<snippet> element of layer container'/>" 143 : " <Option name='DESCRIPTION' type='string' description='Value of " 144 : "<description> element of layer container'/>" 145 : " <Option name='LOOKAT_LONGITUDE' type='float' " 146 : "description='<longitude> of a <LookAt> element at layer " 147 : "level' min='-180' max='180'/>" 148 : " <Option name='LOOKAT_LATITUDE' type='float' " 149 : "description='<latitude> of a <LookAt> element at layer " 150 : "level' min='-90' max='90'/>" 151 : " <Option name='LOOKAT_RANGE' type='float' description='<range> " 152 : "of a <LookAt> element at layer level' min='0'/>" 153 : " <Option name='LOOKAT_HEADING' type='float' " 154 : "description='<heading> of a <LookAt> element at layer " 155 : "level'/>" 156 : " <Option name='LOOKAT_TILT' type='float' description='<tilt> " 157 : "of a <LookAt> element at layer level'/>" 158 : " <Option name='LOOKAT_ALTITUDE' type='float' " 159 : "description='<altitude> of a <LookAt> element at layer " 160 : "level'/>" 161 : " <Option name='LOOKAT_ALTITUDEMODE' type='string-select' " 162 : "description='<altitudeMode> of a <LookAt> element at " 163 : "layer level'>" 164 : " <Value>clampToGround</Value>" 165 : " <Value>relativeToGround</Value>" 166 : " <Value>absolute</Value>" 167 : " <Value>clampToSeaFloor</Value>" 168 : " <Value>relativeToSeaFloor</Value>" 169 : " </Option>" 170 : " <Option name='CAMERA_LONGITUDE' type='float' " 171 : "description='<longitude> of a <Camera> element at layer " 172 : "level' min='-180' max='180'/>" 173 : " <Option name='CAMERA_LATITUDE' type='float' " 174 : "description='<latitude> of a <Camera> element at layer " 175 : "level' min='-90' max='90'/>" 176 : " <Option name='CAMERA_HEADING' type='float' " 177 : "description='<heading> of a <Camera> element at layer " 178 : "level'/>" 179 : " <Option name='CAMERA_TILT' type='float' description='<tilt> " 180 : "of a <Camera> element at layer level'/>" 181 : " <Option name='CAMERA_ROLL' type='float' description='<roll> " 182 : "of a <Camera> element at layer level'/>" 183 : " <Option name='CAMERA_ALTITUDE' type='float' " 184 : "description='<altitude> of a <Camera> element at layer " 185 : "level'/>" 186 : " <Option name='CAMERA_ALTITUDEMODE' type='string-select' " 187 : "description='<altitudeMode> of a <Camera> element at " 188 : "layer level'>" 189 : " <Value>clampToGround</Value>" 190 : " <Value>relativeToGround</Value>" 191 : " <Value>absolute</Value>" 192 : " <Value>clampToSeaFloor</Value>" 193 : " <Value>relativeToSeaFloor</Value>" 194 : " </Option>" 195 : " <Option name='ADD_REGION' type='boolean' description='Whether to " 196 : "generate a <Region> element to control when objects of the " 197 : "layer are visible or not' default='NO'/>" 198 : " <Option name='REGION_XMIN' type='float' description='West " 199 : "coordinate of the region' min='-180' max='180'/>" 200 : " <Option name='REGION_YMIN' type='float' description='South " 201 : "coordinate of the region' min='-90' max='90'/>" 202 : " <Option name='REGION_XMAX' type='float' description='East " 203 : "coordinate of the region' min='-180' max='180'/>" 204 : " <Option name='REGION_YMAX' type='float' description='North " 205 : "coordinate of the region' min='-90' max='90'/>" 206 : " <Option name='REGION_MIN_LOD_PIXELS' type='float' " 207 : "description='minimum size in pixels of the region so that it is " 208 : "displayed' default='256'/>" 209 : " <Option name='REGION_MAX_LOD_PIXELS' type='float' " 210 : "description='maximum size in pixels of the region so that it is " 211 : "displayed (-1=infinite)' default='-1'/>" 212 : " <Option name='REGION_MIN_FADE_EXTENT' type='float' " 213 : "description='distance over which the geometry fades, from fully " 214 : "opaque to fully transparent' default='0'/>" 215 : " <Option name='REGION_MAX_FADE_EXTENT' type='float' " 216 : "description='distance over which the geometry fades, from fully " 217 : "transparent to fully opaque' default='0'/>" 218 : " <Option name='SO_HREF' type='string' description='URL of the image " 219 : "to display in a <ScreenOverlay>'/>" 220 : " <Option name='SO_NAME' type='string' description='<name> of a " 221 : "<ScreenOverlay>'/>" 222 : " <Option name='SO_DESCRIPTION' type='string' " 223 : "description='<description> of a <ScreenOverlay>'/>" 224 : " <Option name='SO_OVERLAY_X' type='float' description='x attribute " 225 : "of the <overlayXY> of a <ScreenOverlay>'/>" 226 : " <Option name='SO_OVERLAY_Y' type='float' description='y attribute " 227 : "of the <overlayXY> of a <ScreenOverlay>'/>" 228 : " <Option name='SO_OVERLAY_XUNITS' type='string-select' " 229 : "description='xunits attribute of the <overlayXY> of a " 230 : "<ScreenOverlay>'>" 231 : " <Value>fraction</Value>" 232 : " <Value>pixels</Value>" 233 : " <Value>insetPixels</Value>" 234 : " </Option>" 235 : " <Option name='SO_OVERLAY_YUNITS' type='string-select' " 236 : "description='yunits attribute of the <overlayXY> of a " 237 : "<ScreenOverlay>'>" 238 : " <Value>fraction</Value>" 239 : " <Value>pixels</Value>" 240 : " <Value>insetPixels</Value>" 241 : " </Option>" 242 : " <Option name='SO_SCREEN_X' type='float' description='x attribute of " 243 : "the <screenXY> of a <ScreenOverlay>' default='0.05'/>" 244 : " <Option name='SO_SCREEN_Y' type='float' description='y attribute of " 245 : "the <screenXY> of a <ScreenOverlay>' default='0.05'/>" 246 : " <Option name='SO_SCREEN_XUNITS' type='string-select' " 247 : "description='xunits attribute of the <screenXY> of a " 248 : "<ScreenOverlay>' default='fraction'>" 249 : " <Value>fraction</Value>" 250 : " <Value>pixels</Value>" 251 : " <Value>insetPixels</Value>" 252 : " </Option>" 253 : " <Option name='SO_SCREEN_YUNITS' type='string-select' " 254 : "description='yunits attribute of the <screenXY> of a " 255 : "<ScreenOverlay>' default='fraction'>" 256 : " <Value>fraction</Value>" 257 : " <Value>pixels</Value>" 258 : " <Value>insetPixels</Value>" 259 : " </Option>" 260 : " <Option name='SO_SIZE_X' type='float' description='x attribute of " 261 : "the <sizeXY> of a <ScreenOverlay>'/>" 262 : " <Option name='SO_SIZE_Y' type='float' description='y attribute of " 263 : "the <sizeXY> of a <ScreenOverlay>'/>" 264 : " <Option name='SO_SIZE_XUNITS' type='string-select' " 265 : "description='xunits attribute of the <sizeXY> of a " 266 : "<ScreenOverlay>'>" 267 : " <Value>fraction</Value>" 268 : " <Value>pixels</Value>" 269 : " <Value>insetPixels</Value>" 270 : " </Option>" 271 : " <Option name='SO_SIZE_YUNITS' type='string-select' " 272 : "description='yunits attribute of the <sizeXY> of a " 273 : "<ScreenOverlay>'>" 274 : " <Value>fraction</Value>" 275 : " <Value>pixels</Value>" 276 : " <Value>insetPixels</Value>" 277 : " </Option>" 278 : " <Option name='FOLDER' type='boolean' description='Whether to " 279 : "generate a <Folder> element for layers, instead of a " 280 : "<Document>' default='NO'/>" 281 : " <Option name='LISTSTYLE_TYPE' type='string-select' " 282 : "description='Value of <listItemType> element of layer " 283 : "container'>" 284 : " <Value>check</Value>" 285 : " <Value>radioFolder</Value>" 286 : " <Value>checkOffOnly</Value>" 287 : " <Value>checkHideChildren</Value>" 288 : " </Option>" 289 : " <Option name='LISTSTYLE_ICON_HREF' type='string' description='URL " 290 : "of the icon to display for the layer folder. Sets the href element of " 291 : "the <ItemIcon> element'/>" 292 1317 : "</LayerCreationOptionList>"); 293 : 294 1317 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 295 1317 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES, 296 1317 : "Integer Real String"); 297 1317 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES, "YES"); 298 1317 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_READ, "YES"); 299 1317 : poDriver->SetMetadataItem(GDAL_DCAP_FEATURE_STYLES_WRITE, "YES"); 300 1317 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES"); 301 : 302 1317 : poDriver->pfnIdentify = OGRLIBKMLDriverIdentify; 303 1317 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES"); 304 1317 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES"); 305 1317 : } 306 : 307 : /************************************************************************/ 308 : /* DeclareDeferredOGRLIBKMLPlugin() */ 309 : /************************************************************************/ 310 : 311 : #ifdef PLUGIN_FILENAME 312 1595 : void DeclareDeferredOGRLIBKMLPlugin() 313 : { 314 1595 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 315 : { 316 302 : return; 317 : } 318 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME); 319 : #ifdef PLUGIN_INSTALLATION_MESSAGE 320 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE, 321 : PLUGIN_INSTALLATION_MESSAGE); 322 : #endif 323 1293 : OGRLIBKMLDriverSetCommonMetadata(poDriver); 324 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver); 325 : } 326 : #endif