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