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 "ogr_libkml.h"
30 : //#include "cpl_conv.h"
31 : //#include "cpl_string.h"
32 : #include "cpl_error.h"
33 :
34 : #include <kml/dom.h>
35 :
36 : using kmldom::KmlFactory;
37 : using kmldom::PlacemarkPtr;
38 : using kmldom::Placemark;
39 : using kmldom::DocumentPtr;
40 : using kmldom::ContainerPtr;
41 : using kmldom::FeaturePtr;
42 : using kmldom::GroundOverlayPtr;
43 : using kmldom::KmlPtr;
44 : using kmldom::Kml;
45 : using kmlengine::KmzFile;
46 : using kmlengine::KmlFile;
47 : using kmlengine::Bbox;
48 : using kmldom::ExtendedDataPtr;
49 : using kmldom::SchemaDataPtr;
50 : using kmldom::DataPtr;
51 :
52 : #include "ogrlibkmlfeature.h"
53 : #include "ogrlibkmlfield.h"
54 : #include "ogrlibkmlstyle.h"
55 :
56 : /******************************************************************************
57 : OGRLIBKMLLayer constructor
58 :
59 : Args: pszLayerName the name of the layer
60 : poSpatialRef the spacial Refrance for the layer
61 : eGType the layers geometry type
62 : poOgrDS pointer to the datasource the layer is in
63 : poKmlRoot pointer to the root kml element of the layer
64 : pszFileName the filename of the layer
65 : bNew true if its a new layer
66 : bUpdate true if the layer is writeable
67 :
68 : Returns: nothing
69 :
70 : ******************************************************************************/
71 :
72 52 : OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
73 : OGRSpatialReference * poSpatialRef,
74 : OGRwkbGeometryType eGType,
75 : OGRLIBKMLDataSource * poOgrDS,
76 : ElementPtr poKmlRoot,
77 : ContainerPtr poKmlContainer,
78 : const char *pszFileName,
79 : int bNew,
80 52 : int bUpdate )
81 : {
82 :
83 52 : m_poStyleTable = NULL;
84 52 : iFeature = 0;
85 52 : nFeatures = 0;
86 52 : nFID = 1;
87 :
88 52 : this->bUpdate = bUpdate;
89 52 : m_pszName = CPLStrdup ( pszLayerName );
90 52 : m_pszFileName = CPLStrdup ( pszFileName );
91 52 : m_poOgrDS = poOgrDS;
92 :
93 52 : m_poOgrSRS = new OGRSpatialReference ( NULL );
94 52 : m_poOgrSRS->SetWellKnownGeogCS ( "WGS84" );
95 :
96 52 : m_poOgrFeatureDefn = new OGRFeatureDefn ( pszLayerName );
97 52 : m_poOgrFeatureDefn->Reference ( );
98 52 : m_poOgrFeatureDefn->SetGeomType ( eGType );
99 :
100 : /***** store the root element pointer *****/
101 :
102 52 : m_poKmlLayerRoot = poKmlRoot;
103 :
104 : /***** store the layers container *****/
105 :
106 52 : m_poKmlLayer = poKmlContainer;
107 :
108 : /***** was the layer created from a DS::Open *****/
109 :
110 52 : m_bReadGroundOverlay = CSLTestBoolean(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
111 :
112 52 : if ( !bNew ) {
113 :
114 : /***** get the number of features on the layer *****/
115 :
116 46 : nFeatures = m_poKmlLayer->get_feature_array_size ( );
117 :
118 : /***** add the name and desc fields *****/
119 :
120 : const char *namefield =
121 46 : CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
122 : const char *descfield =
123 46 : CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
124 : const char *tsfield =
125 46 : CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
126 : const char *beginfield =
127 46 : CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
128 : const char *endfield =
129 46 : CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
130 : const char *altitudeModefield =
131 46 : CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
132 : const char *tessellatefield =
133 46 : CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
134 : const char *extrudefield =
135 46 : CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
136 : const char *visibilityfield =
137 46 : CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
138 : const char *drawOrderfield =
139 46 : CPLGetConfigOption ( "LIBKML_DRAWORDER_FIELD", "drawOrder" );
140 : const char *iconfield =
141 46 : CPLGetConfigOption ( "LIBKML_ICON_FIELD", "icon" );
142 :
143 : OGRFieldDefn oOgrFieldName (
144 : namefield,
145 46 : OFTString );
146 :
147 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
148 :
149 : OGRFieldDefn oOgrFieldDesc (
150 : descfield,
151 46 : OFTString );
152 :
153 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldDesc );
154 :
155 : OGRFieldDefn oOgrFieldTs (
156 : tsfield,
157 46 : OFTDateTime );
158 :
159 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldTs );
160 :
161 : OGRFieldDefn oOgrFieldBegin (
162 : beginfield,
163 46 : OFTDateTime );
164 :
165 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldBegin );
166 :
167 : OGRFieldDefn oOgrFieldEnd (
168 : endfield,
169 46 : OFTDateTime );
170 :
171 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldEnd );
172 :
173 : OGRFieldDefn oOgrFieldAltitudeMode (
174 : altitudeModefield,
175 46 : OFTString );
176 :
177 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldAltitudeMode );
178 :
179 : OGRFieldDefn oOgrFieldTessellate (
180 : tessellatefield,
181 46 : OFTInteger );
182 :
183 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldTessellate );
184 :
185 : OGRFieldDefn oOgrFieldExtrude (
186 : extrudefield,
187 46 : OFTInteger );
188 :
189 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldExtrude );
190 :
191 : OGRFieldDefn oOgrFieldVisibility (
192 : visibilityfield,
193 46 : OFTInteger );
194 :
195 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldVisibility );
196 :
197 : OGRFieldDefn oOgrFieldDrawOrder (
198 : drawOrderfield,
199 46 : OFTInteger );
200 :
201 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldDrawOrder );
202 :
203 : OGRFieldDefn oOgrFieldIcon (
204 : iconfield,
205 46 : OFTString );
206 :
207 46 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldIcon );
208 :
209 : /***** get the styles *****/
210 :
211 46 : if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) )
212 12 : ParseStyles ( AsDocument ( m_poKmlLayer ), &m_poStyleTable );
213 :
214 : /***** get the schema if the layer is a Document *****/
215 :
216 46 : m_poKmlSchema = NULL;
217 :
218 46 : if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) ) {
219 12 : DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
220 :
221 12 : if ( poKmlDocument->get_schema_array_size ( ) ) {
222 2 : m_poKmlSchema = poKmlDocument->get_schema_array_at ( 0 );
223 2 : kml2FeatureDef ( m_poKmlSchema, m_poOgrFeatureDefn );
224 12 : }
225 : }
226 :
227 : /***** the schema is somewhere else *****/
228 :
229 46 : if (m_poKmlSchema == NULL) {
230 :
231 : /***** try to find the correct schema *****/
232 :
233 44 : FeaturePtr poKmlFeature;
234 :
235 : /***** find the first placemark *****/
236 :
237 142 : do {
238 82 : if ( iFeature >= nFeatures )
239 11 : break;
240 :
241 : poKmlFeature =
242 71 : m_poKmlLayer->get_feature_array_at ( iFeature++ );
243 :
244 71 : } while ( poKmlFeature->Type ( ) != kmldom::Type_Placemark );
245 :
246 87 : if ( iFeature <= nFeatures && poKmlFeature &&
247 43 : poKmlFeature->Type ( ) == kmldom::Type_Placemark &&
248 : poKmlFeature->has_extendeddata ( ) ) {
249 :
250 : ExtendedDataPtr poKmlExtendedData = poKmlFeature->
251 5 : get_extendeddata ( );
252 :
253 5 : if ( poKmlExtendedData->get_schemadata_array_size ( ) > 0 ) {
254 : SchemaDataPtr poKmlSchemaData = poKmlExtendedData->
255 5 : get_schemadata_array_at ( 0 );
256 :
257 5 : if ( poKmlSchemaData->has_schemaurl ( ) ) {
258 :
259 : std::string oKmlSchemaUrl = poKmlSchemaData->
260 5 : get_schemaurl ( );
261 5 : if ( ( m_poKmlSchema =
262 : m_poOgrDS->FindSchema ( oKmlSchemaUrl.
263 : c_str ( ) ) ) ) {
264 : kml2FeatureDef ( m_poKmlSchema,
265 3 : m_poOgrFeatureDefn );
266 5 : }
267 5 : }
268 : }
269 0 : else if ( poKmlExtendedData->get_data_array_size() > 0 )
270 : {
271 : /* Use the <Data> of the first placemark to build the feature definition */
272 : /* If others have different fields, too bad... */
273 : int bLaunderFieldNames =
274 0 : CSLTestBoolean(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
275 0 : size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
276 0 : for(size_t i=0; i < nDataArraySize; i++)
277 : {
278 0 : const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
279 0 : if (data->has_name())
280 : {
281 0 : CPLString osName = data->get_name();
282 0 : if (bLaunderFieldNames)
283 0 : osName = LaunderFieldNames(osName);
284 : OGRFieldDefn oOgrField ( osName,
285 0 : OFTString );
286 0 : m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
287 : }
288 : }
289 5 : }
290 : }
291 :
292 44 : iFeature = 0;
293 :
294 : }
295 :
296 :
297 :
298 : /***** check if any features are another layer *****/
299 :
300 46 : m_poOgrDS->ParseLayers ( m_poKmlLayer, poSpatialRef );
301 :
302 : }
303 :
304 : /***** it was from a DS::CreateLayer *****/
305 :
306 : else {
307 :
308 : /***** mark the layer as updated *****/
309 :
310 6 : bUpdated = TRUE;
311 :
312 : /***** create a new schema *****/
313 :
314 6 : KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory ( );
315 :
316 6 : m_poKmlSchema = poKmlFactory->CreateSchema ( );
317 :
318 : /***** set the id on the new schema *****/
319 :
320 6 : std::string oKmlSchemaID = m_pszName;
321 6 : oKmlSchemaID.append ( ".schema" );
322 6 : m_poKmlSchema->set_id ( oKmlSchemaID );
323 : }
324 :
325 :
326 :
327 :
328 52 : }
329 :
330 : /******************************************************************************
331 : OGRLIBKMLLayer Destructor
332 :
333 : Args: none
334 :
335 : Returns: nothing
336 :
337 : ******************************************************************************/
338 :
339 52 : OGRLIBKMLLayer::~OGRLIBKMLLayer ( )
340 : {
341 :
342 52 : CPLFree ( ( void * )m_pszName );
343 52 : CPLFree ( ( void * )m_pszFileName );
344 52 : m_poOgrSRS->Release();
345 :
346 52 : m_poOgrFeatureDefn->Release ( );
347 :
348 :
349 52 : }
350 :
351 :
352 : /******************************************************************************
353 : Method to get the next feature on the layer
354 :
355 : Args: none
356 :
357 : Returns: The next feature, or NULL if there is no more
358 :
359 : this function copyed from the sqlite driver
360 : ******************************************************************************/
361 :
362 500 : OGRFeature *OGRLIBKMLLayer::GetNextFeature()
363 :
364 : {
365 90 : for( ; TRUE; )
366 : {
367 : OGRFeature *poFeature;
368 :
369 500 : poFeature = GetNextRawFeature();
370 500 : if( poFeature == NULL )
371 124 : return NULL;
372 :
373 376 : if( (m_poFilterGeom == NULL
374 : || FilterGeometry( poFeature->GetGeometryRef() ) )
375 : && (m_poAttrQuery == NULL
376 : || m_poAttrQuery->Evaluate( poFeature )) )
377 286 : return poFeature;
378 :
379 90 : delete poFeature;
380 : }
381 : }
382 :
383 : /******************************************************************************
384 : Method to get the next feature on the layer
385 :
386 : Args: none
387 :
388 : Returns: The next feature, or NULL if there is no more
389 :
390 : ******************************************************************************/
391 :
392 500 : OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
393 : )
394 : {
395 500 : FeaturePtr poKmlFeature;
396 500 : OGRFeature *poOgrFeature = NULL;
397 :
398 1100 : do {
399 610 : if ( iFeature >= nFeatures )
400 124 : break;
401 :
402 486 : poKmlFeature = m_poKmlLayer->get_feature_array_at ( iFeature++ );
403 :
404 486 : } while ( poKmlFeature->Type ( ) != kmldom::Type_Placemark &&
405 128 : !(m_bReadGroundOverlay && poKmlFeature->Type ( ) == kmldom::Type_GroundOverlay) );
406 :
407 :
408 500 : if ( iFeature <= nFeatures && poKmlFeature )
409 : {
410 395 : if (poKmlFeature->Type ( ) == kmldom::Type_Placemark )
411 : {
412 : poOgrFeature =
413 : kml2feat ( AsPlacemark ( poKmlFeature ), m_poOgrDS, this,
414 358 : m_poOgrFeatureDefn, m_poOgrSRS );
415 358 : poOgrFeature->SetFID(nFID ++);
416 : }
417 37 : else if ( m_bReadGroundOverlay && poKmlFeature->Type ( ) == kmldom::Type_GroundOverlay )
418 : {
419 : poOgrFeature =
420 : kmlgroundoverlay2feat ( AsGroundOverlay ( poKmlFeature ), m_poOgrDS, this,
421 18 : m_poOgrFeatureDefn, m_poOgrSRS );
422 18 : poOgrFeature->SetFID(nFID ++);
423 : }
424 : }
425 :
426 500 : return poOgrFeature;
427 : }
428 :
429 : /******************************************************************************
430 : method to add a feature to a layer
431 :
432 : Args: poOgrFeat pointer to the feature to add
433 :
434 : Returns: OGRERR_NONE, or OGRERR_UNSUPPORTED_OPERATION of the layer is
435 : not writeable
436 :
437 : ******************************************************************************/
438 :
439 27 : OGRErr OGRLIBKMLLayer::CreateFeature (
440 : OGRFeature * poOgrFeat )
441 : {
442 :
443 27 : if ( !bUpdate )
444 0 : return OGRERR_UNSUPPORTED_OPERATION;
445 :
446 : PlacemarkPtr poKmlPlacemark =
447 27 : feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory ( ) );
448 :
449 27 : m_poKmlLayer->add_feature ( poKmlPlacemark );
450 :
451 : /***** mark the layer as updated *****/
452 :
453 27 : bUpdated = TRUE;
454 27 : m_poOgrDS->Updated ( );
455 :
456 27 : return OGRERR_NONE;
457 : }
458 :
459 : /******************************************************************************
460 : method to get the number of features on the layer
461 :
462 : Args: bForce no effect as of now
463 :
464 : Returns: the number of feateres on the layer
465 :
466 : Note: the result can include links, folders and other items that are
467 : not supported by OGR
468 :
469 : ******************************************************************************/
470 :
471 75 : int OGRLIBKMLLayer::GetFeatureCount (
472 : int bForce )
473 : {
474 :
475 :
476 75 : int i = 0;
477 105 : if (m_poFilterGeom != NULL || m_poAttrQuery != NULL ) {
478 30 : i = OGRLayer::GetFeatureCount( bForce );
479 : }
480 :
481 : else {
482 : size_t iKmlFeature;
483 45 : size_t nKmlFeatures = m_poKmlLayer->get_feature_array_size ( );
484 :
485 193 : for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
486 148 : const kmldom::FeaturePtr& f(m_poKmlLayer->get_feature_array_at ( iKmlFeature ));
487 148 : if ( f->IsA( kmldom::Type_Placemark ) || (m_bReadGroundOverlay && f->IsA( kmldom::Type_GroundOverlay )) ) {
488 113 : i++;
489 : }
490 : }
491 : }
492 :
493 75 : return i;
494 : }
495 :
496 : /******************************************************************************
497 : GetExtent()
498 :
499 : Args: psExtent pointer to the Envelope to store the result in
500 : bForce no effect as of now
501 :
502 : Returns: nothing
503 :
504 : ******************************************************************************/
505 :
506 10 : OGRErr OGRLIBKMLLayer::GetExtent (
507 : OGREnvelope * psExtent,
508 : int bForce )
509 : {
510 10 : Bbox oKmlBbox;
511 :
512 10 : if ( kmlengine::
513 : GetFeatureBounds ( AsFeature ( m_poKmlLayer ), &oKmlBbox ) ) {
514 8 : psExtent->MinX = oKmlBbox.get_west ( );
515 8 : psExtent->MinY = oKmlBbox.get_south ( );
516 8 : psExtent->MaxX = oKmlBbox.get_east ( );
517 8 : psExtent->MaxY = oKmlBbox.get_north ( );
518 :
519 8 : return OGRERR_NONE;
520 : }
521 : else
522 2 : return OGRLayer::GetExtent(psExtent, bForce);
523 : }
524 :
525 :
526 :
527 :
528 : /******************************************************************************
529 : Method to create a field on a layer
530 :
531 : Args: poField pointer to the Field Definition to add
532 : bApproxOK no effect as of now
533 :
534 : Returns: OGRERR_NONE on success or OGRERR_UNSUPPORTED_OPERATION if the
535 : layer is not writeable
536 :
537 : ******************************************************************************/
538 :
539 9 : OGRErr OGRLIBKMLLayer::CreateField (
540 : OGRFieldDefn * poField,
541 : int bApproxOK )
542 : {
543 :
544 9 : if ( !bUpdate )
545 0 : return OGRERR_UNSUPPORTED_OPERATION;
546 :
547 9 : SimpleFieldPtr poKmlSimpleField = NULL;
548 :
549 9 : if ( (poKmlSimpleField =
550 : FieldDef2kml ( poField, m_poOgrDS->GetKmlFactory ( ) )) != NULL )
551 3 : m_poKmlSchema->add_simplefield ( poKmlSimpleField );
552 :
553 9 : m_poOgrFeatureDefn->AddFieldDefn ( poField );
554 :
555 : /***** mark the layer as updated *****/
556 :
557 9 : bUpdated = TRUE;
558 9 : m_poOgrDS->Updated ( );
559 :
560 9 : return OGRERR_NONE;
561 : }
562 :
563 :
564 : /******************************************************************************
565 : method to write the datasource to disk
566 :
567 : Args: none
568 :
569 : Returns nothing
570 :
571 : ******************************************************************************/
572 :
573 0 : OGRErr OGRLIBKMLLayer::SyncToDisk (
574 : )
575 : {
576 :
577 0 : return OGRERR_NONE;
578 : }
579 :
580 : /******************************************************************************
581 : method to get a layers style table
582 :
583 : Args: none
584 :
585 : Returns: pointer to the layers style table, or NULL if it does
586 : not have one
587 :
588 : ******************************************************************************/
589 :
590 222 : OGRStyleTable *OGRLIBKMLLayer::GetStyleTable (
591 : )
592 : {
593 :
594 222 : return m_poStyleTable;
595 : }
596 :
597 : /******************************************************************************
598 : method to write a style table to a layer
599 :
600 : Args: poStyleTable pointer to the style table to add
601 :
602 : Returns: nothing
603 :
604 : note: this method assumes ownership of the style table
605 : ******************************************************************************/
606 :
607 0 : void OGRLIBKMLLayer::SetStyleTableDirectly (
608 : OGRStyleTable * poStyleTable )
609 : {
610 :
611 0 : if ( !bUpdate )
612 0 : return;
613 :
614 0 : KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory ( );
615 :
616 0 : if ( m_poStyleTable )
617 0 : delete m_poStyleTable;
618 :
619 0 : m_poStyleTable = poStyleTable;
620 :
621 0 : if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) ) {
622 :
623 : /***** delete all the styles *****/
624 :
625 0 : DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
626 0 : size_t nKmlStyles = poKmlDocument->get_schema_array_size ( );
627 : int iKmlStyle;
628 :
629 0 : for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
630 0 : poKmlDocument->DeleteStyleSelectorAt ( iKmlStyle );
631 : }
632 :
633 : /***** add the new style table to the document *****/
634 :
635 : styletable2kml ( poStyleTable, poKmlFactory,
636 0 : AsContainer ( poKmlDocument ) );
637 :
638 : }
639 :
640 : /***** mark the layer as updated *****/
641 :
642 0 : bUpdated = TRUE;
643 0 : m_poOgrDS->Updated ( );
644 :
645 0 : return;
646 : }
647 :
648 : /******************************************************************************
649 : method to write a style table to a layer
650 :
651 : Args: poStyleTable pointer to the style table to add
652 :
653 : Returns: nothing
654 :
655 : note: this method copys the style table, and the user will still be
656 : responsible for its destruction
657 : ******************************************************************************/
658 :
659 0 : void OGRLIBKMLLayer::SetStyleTable (
660 : OGRStyleTable * poStyleTable )
661 : {
662 :
663 0 : if ( !bUpdate )
664 0 : return;
665 :
666 0 : if ( poStyleTable )
667 0 : SetStyleTableDirectly ( poStyleTable->Clone ( ) );
668 : else
669 0 : SetStyleTableDirectly ( NULL );
670 0 : return;
671 : }
672 :
673 : /******************************************************************************
674 : Test if capability is available.
675 :
676 : Args: pszCap layer capability name to test
677 :
678 : Returns: True if the layer supports the capability, otherwise false
679 :
680 : ******************************************************************************/
681 :
682 80 : int OGRLIBKMLLayer::TestCapability (
683 : const char *pszCap )
684 : {
685 80 : int result = FALSE;
686 :
687 80 : if ( EQUAL ( pszCap, OLCRandomRead ) )
688 10 : result = FALSE;
689 70 : else if ( EQUAL ( pszCap, OLCSequentialWrite ) )
690 10 : result = bUpdate;
691 60 : else if ( EQUAL ( pszCap, OLCRandomWrite ) )
692 10 : result = FALSE;
693 50 : else if ( EQUAL ( pszCap, OLCFastFeatureCount ) )
694 0 : result = FALSE;
695 50 : else if ( EQUAL ( pszCap, OLCFastSetNextByIndex ) )
696 10 : result = FALSE;
697 40 : else if ( EQUAL ( pszCap, OLCCreateField ) )
698 0 : result = bUpdate;
699 40 : else if ( EQUAL ( pszCap, OLCDeleteFeature ) )
700 10 : result = FALSE;
701 30 : else if ( EQUAL(pszCap, OLCStringsAsUTF8) )
702 10 : result = TRUE;
703 :
704 80 : return result;
705 : }
706 :
707 : /************************************************************************/
708 : /* LaunderFieldNames() */
709 : /************************************************************************/
710 :
711 0 : CPLString OGRLIBKMLLayer::LaunderFieldNames(CPLString osName)
712 : {
713 0 : CPLString osLaunderedName;
714 0 : for(int i=0;i<(int)osName.size();i++)
715 : {
716 0 : char ch = osName[i];
717 0 : if ((ch >= '0' && ch <= '9') ||
718 : (ch >= 'a' && ch <= 'z') ||
719 : (ch >= 'A' && ch <= 'Z') ||
720 : (ch == '_'))
721 0 : osLaunderedName += ch;
722 : else
723 0 : osLaunderedName += "_";
724 : }
725 0 : return osLaunderedName;
726 : }
|