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 : #include <ogr_feature.h>
31 : #include "ogr_p.h"
32 :
33 : #include <kml/dom.h>
34 : #include <iostream>
35 :
36 : using kmldom::ExtendedDataPtr;
37 : using kmldom::SchemaPtr;
38 : using kmldom::SchemaDataPtr;
39 : using kmldom::SimpleDataPtr;
40 :
41 : using kmldom::TimeStampPtr;
42 : using kmldom::TimeSpanPtr;
43 : using kmldom::TimePrimitivePtr;
44 :
45 : using kmldom::PointPtr;
46 : using kmldom::LineStringPtr;
47 : using kmldom::PolygonPtr;
48 : using kmldom::MultiGeometryPtr;
49 : using kmldom::GeometryPtr;
50 :
51 :
52 : #include "ogr_libkml.h"
53 :
54 : #include "ogrlibkmlfield.h"
55 :
56 : void ogr2altitudemode_rec (
57 : GeometryPtr poKmlGeometry,
58 : int iAltitudeMode,
59 0 : int isGX )
60 : {
61 :
62 0 : PointPtr poKmlPoint;
63 0 : LineStringPtr poKmlLineString;
64 0 : PolygonPtr poKmlPolygon;
65 0 : MultiGeometryPtr poKmlMultiGeometry;
66 :
67 : size_t nGeom;
68 : size_t i;
69 :
70 0 : switch ( poKmlGeometry->Type ( ) ) {
71 :
72 : case kmldom::Type_Point:
73 0 : poKmlPoint = AsPoint ( poKmlGeometry );
74 :
75 0 : if ( !isGX )
76 0 : poKmlPoint->set_altitudemode ( iAltitudeMode );
77 : else
78 0 : poKmlPoint->set_gx_altitudemode ( iAltitudeMode );
79 :
80 0 : break;
81 :
82 : case kmldom::Type_LineString:
83 0 : poKmlLineString = AsLineString ( poKmlGeometry );
84 :
85 0 : if ( !isGX )
86 0 : poKmlLineString->set_altitudemode ( iAltitudeMode );
87 : else
88 0 : poKmlLineString->set_gx_altitudemode ( iAltitudeMode );
89 :
90 0 : break;
91 :
92 : case kmldom::Type_LinearRing:
93 0 : break;
94 :
95 : case kmldom::Type_Polygon:
96 0 : poKmlPolygon = AsPolygon ( poKmlGeometry );
97 :
98 0 : if ( !isGX )
99 0 : poKmlPolygon->set_altitudemode ( iAltitudeMode );
100 : else
101 0 : poKmlPolygon->set_gx_altitudemode ( iAltitudeMode );
102 :
103 0 : break;
104 :
105 : case kmldom::Type_MultiGeometry:
106 0 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
107 :
108 0 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
109 0 : for ( i = 0; i < nGeom; i++ ) {
110 : ogr2altitudemode_rec ( poKmlMultiGeometry->
111 : get_geometry_array_at ( i ), iAltitudeMode,
112 0 : isGX );
113 : }
114 :
115 : break;
116 :
117 : default:
118 : break;
119 :
120 0 : }
121 :
122 0 : }
123 :
124 : void ogr2extrude_rec (
125 : int nExtrude,
126 0 : GeometryPtr poKmlGeometry )
127 : {
128 :
129 0 : PointPtr poKmlPoint;
130 0 : LineStringPtr poKmlLineString;
131 0 : PolygonPtr poKmlPolygon;
132 0 : MultiGeometryPtr poKmlMultiGeometry;
133 :
134 : size_t nGeom;
135 : size_t i;
136 :
137 0 : switch ( poKmlGeometry->Type ( ) ) {
138 : case kmldom::Type_Point:
139 0 : poKmlPoint = AsPoint ( poKmlGeometry );
140 0 : poKmlPoint->set_extrude ( nExtrude );
141 0 : break;
142 :
143 : case kmldom::Type_LineString:
144 0 : poKmlLineString = AsLineString ( poKmlGeometry );
145 0 : poKmlLineString->set_extrude ( nExtrude );
146 0 : break;
147 :
148 : case kmldom::Type_LinearRing:
149 0 : break;
150 :
151 : case kmldom::Type_Polygon:
152 0 : poKmlPolygon = AsPolygon ( poKmlGeometry );
153 0 : poKmlPolygon->set_extrude ( nExtrude );
154 0 : break;
155 :
156 : case kmldom::Type_MultiGeometry:
157 0 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
158 :
159 0 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
160 0 : for ( i = 0; i < nGeom; i++ ) {
161 : ogr2extrude_rec ( nExtrude,
162 : poKmlMultiGeometry->
163 0 : get_geometry_array_at ( i ) );
164 : }
165 : break;
166 :
167 : default:
168 : break;
169 :
170 0 : }
171 0 : }
172 :
173 : void ogr2tessellate_rec (
174 : int nTessellate,
175 0 : GeometryPtr poKmlGeometry )
176 : {
177 :
178 0 : LineStringPtr poKmlLineString;
179 0 : PolygonPtr poKmlPolygon;
180 0 : MultiGeometryPtr poKmlMultiGeometry;
181 :
182 : size_t nGeom;
183 : size_t i;
184 :
185 0 : switch ( poKmlGeometry->Type ( ) ) {
186 :
187 : case kmldom::Type_Point:
188 0 : break;
189 :
190 : case kmldom::Type_LineString:
191 0 : poKmlLineString = AsLineString ( poKmlGeometry );
192 0 : poKmlLineString->set_tessellate ( nTessellate );
193 0 : break;
194 :
195 : case kmldom::Type_LinearRing:
196 0 : break;
197 :
198 : case kmldom::Type_Polygon:
199 0 : poKmlPolygon = AsPolygon ( poKmlGeometry );
200 :
201 0 : poKmlPolygon->set_tessellate ( nTessellate );
202 0 : break;
203 :
204 : case kmldom::Type_MultiGeometry:
205 0 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
206 :
207 0 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
208 0 : for ( i = 0; i < nGeom; i++ ) {
209 : ogr2tessellate_rec ( nTessellate,
210 : poKmlMultiGeometry->
211 0 : get_geometry_array_at ( i ) );
212 : }
213 :
214 : break;
215 :
216 : default:
217 : break;
218 :
219 0 : }
220 0 : }
221 :
222 : /******************************************************************************
223 : function to output ogr fields in kml
224 :
225 : args:
226 : poOgrFeat pointer to the feature the field is in
227 : poOgrLayer pointer to the layer the feature is in
228 : poKmlFactory pointer to the libkml dom factory
229 : poKmlPlacemark pointer to the placemark to add to
230 :
231 : returns:
232 : nothing
233 :
234 : env vars:
235 : LIBKML_TIMESTAMP_FIELD default: OFTDate or OFTDateTime named timestamp
236 : LIBKML_TIMESPAN_BEGIN_FIELD default: OFTDate or OFTDateTime named begin
237 : LIBKML_TIMESPAN_END_FIELD default: OFTDate or OFTDateTime named end
238 : LIBKML_DESCRIPTION_FIELD default: none
239 : LIBKML_NAME_FIELD default: OFTString field named name
240 :
241 :
242 : ******************************************************************************/
243 :
244 :
245 :
246 : void field2kml (
247 : OGRFeature * poOgrFeat,
248 : OGRLIBKMLLayer * poOgrLayer,
249 : KmlFactory * poKmlFactory,
250 9 : PlacemarkPtr poKmlPlacemark )
251 : {
252 : int i;
253 :
254 9 : SchemaDataPtr poKmlSchemaData = poKmlFactory->CreateSchemaData ( );
255 9 : SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema ( );
256 :
257 : /***** set the url to the schema *****/
258 :
259 9 : if ( poKmlSchema && poKmlSchema->has_id ( ) ) {
260 9 : std::string oKmlSchemaID = poKmlSchema->get_id ( );
261 :
262 :
263 9 : std::string oKmlSchemaURL = "#";
264 9 : oKmlSchemaURL.append ( oKmlSchemaID );
265 :
266 9 : poKmlSchemaData->set_schemaurl ( oKmlSchemaURL );
267 : }
268 :
269 9 : const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
270 : const char *descfield =
271 9 : CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
272 : const char *tsfield =
273 9 : CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
274 : const char *beginfield =
275 9 : CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
276 9 : const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
277 : const char *altitudeModefield =
278 9 : CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
279 : const char *tessellatefield =
280 9 : CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
281 : const char *extrudefield =
282 9 : CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
283 : const char *visibilityfield =
284 9 : CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
285 :
286 9 : TimeSpanPtr poKmlTimeSpan = NULL;
287 :
288 9 : int nFields = poOgrFeat->GetFieldCount ( );
289 9 : int iSkip1 = -1;
290 9 : int iSkip2 = -1;
291 :
292 25 : for ( i = 0; i < nFields; i++ ) {
293 :
294 : /***** if the field is set to skip, do so *****/
295 :
296 16 : if ( i == iSkip1 || i == iSkip2 )
297 0 : continue;
298 :
299 : /***** if the field isn't set just bail now *****/
300 :
301 16 : if ( !poOgrFeat->IsFieldSet ( i ) )
302 14 : continue;
303 :
304 2 : OGRFieldDefn *poOgrFieldDef = poOgrFeat->GetFieldDefnRef ( i );
305 2 : OGRFieldType type = poOgrFieldDef->GetType ( );
306 2 : const char *name = poOgrFieldDef->GetNameRef ( );
307 :
308 2 : SimpleDataPtr poKmlSimpleData = NULL;
309 : int year,
310 : month,
311 : day,
312 : hour,
313 : min,
314 : sec,
315 : tz;
316 :
317 2 : switch ( type ) {
318 :
319 : case OFTString: // String of ASCII chars
320 : {
321 :
322 : /***** name *****/
323 :
324 2 : if ( EQUAL ( name, namefield ) ) {
325 : poKmlPlacemark->set_name ( poOgrFeat->
326 1 : GetFieldAsString ( i ) );
327 2 : continue;
328 : }
329 :
330 : /***** description *****/
331 :
332 1 : else if ( EQUAL ( name, descfield ) ) {
333 : poKmlPlacemark->set_description ( poOgrFeat->
334 1 : GetFieldAsString ( i ) );
335 : continue;
336 : }
337 :
338 : /***** altitudemode *****/
339 :
340 0 : else if ( EQUAL ( name, altitudeModefield ) ) {
341 : const char *pszAltitudeMode =
342 0 : poOgrFeat->GetFieldAsString ( i );
343 :
344 0 : int isGX = FALSE;
345 0 : int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
346 :
347 0 : if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
348 0 : iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
349 :
350 0 : else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
351 0 : iAltitudeMode = kmldom::ALTITUDEMODE_RELATIVETOGROUND;
352 :
353 0 : else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
354 0 : iAltitudeMode = kmldom::ALTITUDEMODE_ABSOLUTE;
355 :
356 0 : else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
357 : iAltitudeMode =
358 0 : kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR;
359 0 : isGX = TRUE;
360 : }
361 :
362 0 : else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
363 : iAltitudeMode =
364 0 : kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR;
365 0 : isGX = TRUE;
366 : }
367 :
368 :
369 0 : if ( poKmlPlacemark->has_geometry ( ) ) {
370 : GeometryPtr poKmlGeometry =
371 0 : poKmlPlacemark->get_geometry ( );
372 :
373 : ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
374 0 : isGX );
375 :
376 : }
377 :
378 : continue;
379 : }
380 :
381 : /***** timestamp *****/
382 :
383 0 : else if ( EQUAL ( name, tsfield ) ) {
384 :
385 : TimeStampPtr poKmlTimeStamp =
386 0 : poKmlFactory->CreateTimeStamp ( );
387 0 : poKmlTimeStamp->set_when ( poOgrFeat->GetFieldAsString ( i ) );
388 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
389 :
390 0 : continue;
391 : }
392 :
393 : /***** begin *****/
394 :
395 0 : if ( EQUAL ( name, beginfield ) ) {
396 :
397 0 : if ( !poKmlTimeSpan ) {
398 0 : poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( );
399 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
400 : }
401 :
402 0 : poKmlTimeSpan->set_begin ( poOgrFeat->GetFieldAsString ( i ) );
403 :
404 : continue;
405 :
406 : }
407 :
408 : /***** end *****/
409 :
410 0 : else if ( EQUAL ( name, endfield ) ) {
411 :
412 0 : if ( !poKmlTimeSpan ) {
413 0 : poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( );
414 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
415 : }
416 :
417 0 : poKmlTimeSpan->set_end ( poOgrFeat->GetFieldAsString ( i ) );
418 :
419 : continue;
420 : }
421 :
422 : /***** other *****/
423 :
424 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
425 0 : poKmlSimpleData->set_name ( name );
426 : poKmlSimpleData->set_text ( poOgrFeat->
427 0 : GetFieldAsString ( i ) );
428 :
429 0 : break;
430 : }
431 :
432 : case OFTDate: // Date
433 : {
434 : poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
435 0 : &hour, &min, &sec, &tz );
436 :
437 : int iTimeField;
438 :
439 0 : for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
440 0 : if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
441 0 : continue;
442 :
443 : OGRFieldDefn *poOgrFieldDef2 =
444 0 : poOgrFeat->GetFieldDefnRef ( i );
445 0 : OGRFieldType type2 = poOgrFieldDef2->GetType ( );
446 0 : const char *name2 = poOgrFieldDef2->GetNameRef ( );
447 :
448 0 : if ( EQUAL ( name2, name ) && type2 == OFTTime &&
449 : ( EQUAL ( name, tsfield ) ||
450 : EQUAL ( name, beginfield ) ||
451 : EQUAL ( name, endfield ) ) ) {
452 :
453 : int year2,
454 : month2,
455 : day2,
456 : hour2,
457 : min2,
458 : sec2,
459 : tz2;
460 :
461 : poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2,
462 : &month2, &day2, &hour2,
463 0 : &min2, &sec2, &tz2 );
464 :
465 0 : hour = hour2;
466 0 : min = min2;
467 0 : sec = sec2;
468 0 : tz = tz2;
469 :
470 0 : if ( 0 > iSkip1 )
471 0 : iSkip1 = iTimeField;
472 : else
473 0 : iSkip2 = iTimeField;
474 : }
475 : }
476 :
477 0 : goto Do_DateTime;
478 :
479 : }
480 :
481 :
482 : case OFTTime: // Time
483 : {
484 : poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
485 0 : &hour, &min, &sec, &tz );
486 :
487 : int iTimeField;
488 :
489 0 : for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
490 0 : if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
491 0 : continue;
492 :
493 : OGRFieldDefn *poOgrFieldDef2 =
494 0 : poOgrFeat->GetFieldDefnRef ( i );
495 0 : OGRFieldType type2 = poOgrFieldDef2->GetType ( );
496 0 : const char *name2 = poOgrFieldDef2->GetNameRef ( );
497 :
498 0 : if ( EQUAL ( name2, name ) && type2 == OFTTime &&
499 : ( EQUAL ( name, tsfield ) ||
500 : EQUAL ( name, beginfield ) ||
501 : EQUAL ( name, endfield ) ) ) {
502 :
503 : int year2,
504 : month2,
505 : day2,
506 : hour2,
507 : min2,
508 : sec2,
509 : tz2;
510 :
511 : poOgrFeat->GetFieldAsDateTime ( iTimeField, &year2,
512 : &month2, &day2, &hour2,
513 0 : &min2, &sec2, &tz2 );
514 :
515 0 : year = year2;
516 0 : month = month2;
517 0 : day = day2;
518 :
519 0 : if ( 0 > iSkip1 )
520 0 : iSkip1 = iTimeField;
521 : else
522 0 : iSkip2 = iTimeField;
523 : }
524 : }
525 :
526 0 : goto Do_DateTime;
527 :
528 : }
529 :
530 : case OFTDateTime: // Date and Time
531 : {
532 : poOgrFeat->GetFieldAsDateTime ( i, &year, &month, &day,
533 0 : &hour, &min, &sec, &tz );
534 :
535 0 : Do_DateTime:
536 : /***** timestamp *****/
537 :
538 0 : if ( EQUAL ( name, tsfield ) ) {
539 :
540 : char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
541 0 : min, sec, tz );
542 :
543 : TimeStampPtr poKmlTimeStamp =
544 0 : poKmlFactory->CreateTimeStamp ( );
545 0 : poKmlTimeStamp->set_when ( timebuf );
546 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeStamp );
547 0 : CPLFree( timebuf );
548 :
549 0 : continue;
550 : }
551 :
552 : /***** begin *****/
553 :
554 0 : if ( EQUAL ( name, beginfield ) ) {
555 :
556 : char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
557 0 : min, sec, tz );
558 :
559 0 : if ( !poKmlTimeSpan ) {
560 0 : poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( );
561 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
562 : }
563 :
564 0 : poKmlTimeSpan->set_begin ( timebuf );
565 0 : CPLFree( timebuf );
566 :
567 : continue;
568 :
569 : }
570 :
571 : /***** end *****/
572 :
573 0 : else if ( EQUAL ( name, endfield ) ) {
574 :
575 : char *timebuf = OGRGetXMLDateTime ( year, month, day, hour,
576 0 : min, sec, tz );
577 :
578 :
579 0 : if ( !poKmlTimeSpan ) {
580 0 : poKmlTimeSpan = poKmlFactory->CreateTimeSpan ( );
581 0 : poKmlPlacemark->set_timeprimitive ( poKmlTimeSpan );
582 : }
583 :
584 0 : poKmlTimeSpan->set_end ( timebuf );
585 0 : CPLFree( timebuf );
586 :
587 : continue;
588 : }
589 :
590 : /***** other *****/
591 :
592 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
593 0 : poKmlSimpleData->set_name ( name );
594 : poKmlSimpleData->set_text ( poOgrFeat->
595 0 : GetFieldAsString ( i ) );
596 :
597 0 : break;
598 : }
599 :
600 : case OFTStringList: // Array of strings
601 : case OFTBinary: // Raw Binary data
602 :
603 : /***** other *****/
604 :
605 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
606 0 : poKmlSimpleData->set_name ( name );
607 0 : poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
608 :
609 0 : break;
610 : case OFTInteger: // Simple 32bit integer
611 :
612 : /***** extrude *****/
613 :
614 0 : if ( EQUAL ( name, extrudefield ) ) {
615 :
616 0 : if ( poKmlPlacemark->has_geometry ( )
617 : && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
618 : GeometryPtr poKmlGeometry =
619 0 : poKmlPlacemark->get_geometry ( );
620 : ogr2extrude_rec ( poOgrFeat->GetFieldAsInteger ( i ),
621 0 : poKmlGeometry );
622 : }
623 : continue;
624 : }
625 :
626 : /***** tessellate *****/
627 :
628 :
629 0 : if ( EQUAL ( name, tessellatefield ) ) {
630 :
631 0 : if ( poKmlPlacemark->has_geometry ( )
632 : && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
633 : GeometryPtr poKmlGeometry =
634 0 : poKmlPlacemark->get_geometry ( );
635 : ogr2tessellate_rec ( poOgrFeat->GetFieldAsInteger ( i ),
636 0 : poKmlGeometry );
637 : }
638 :
639 : continue;
640 : }
641 :
642 :
643 : /***** visibility *****/
644 :
645 0 : if ( EQUAL ( name, visibilityfield ) ) {
646 0 : if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) )
647 : poKmlPlacemark->set_visibility ( poOgrFeat->
648 0 : GetFieldAsInteger ( i ) );
649 :
650 : continue;
651 : }
652 :
653 : /***** other *****/
654 :
655 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
656 0 : poKmlSimpleData->set_name ( name );
657 0 : poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
658 :
659 0 : break;
660 : case OFTIntegerList: // List of 32bit integers
661 : case OFTReal: // Double Precision floating point
662 :
663 : /***** other *****/
664 :
665 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
666 0 : poKmlSimpleData->set_name ( name );
667 0 : poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
668 :
669 0 : break;
670 : case OFTRealList: // List of doubles
671 :
672 : case OFTWideStringList: // deprecated
673 : default:
674 :
675 : /***** other *****/
676 :
677 0 : poKmlSimpleData = poKmlFactory->CreateSimpleData ( );
678 0 : poKmlSimpleData->set_name ( name );
679 0 : poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
680 :
681 : break;
682 : }
683 0 : poKmlSchemaData->add_simpledata ( poKmlSimpleData );
684 : }
685 :
686 : /***** dont add it to the placemark unless there is data *****/
687 :
688 9 : if ( poKmlSchemaData->get_simpledata_array_size ( ) > 0 ) {
689 : ExtendedDataPtr poKmlExtendedData =
690 0 : poKmlFactory->CreateExtendedData ( );
691 0 : poKmlExtendedData->add_schemadata ( poKmlSchemaData );
692 0 : poKmlPlacemark->set_extendeddata ( poKmlExtendedData );
693 : }
694 :
695 9 : return;
696 : }
697 :
698 : /******************************************************************************
699 : recursive function to read altitude mode from the geometry
700 : ******************************************************************************/
701 :
702 : int kml2altitudemode_rec (
703 : GeometryPtr poKmlGeometry,
704 : int *pnAltitudeMode,
705 69 : int *pbIsGX )
706 : {
707 :
708 69 : PointPtr poKmlPoint;
709 69 : LineStringPtr poKmlLineString;
710 69 : PolygonPtr poKmlPolygon;
711 69 : MultiGeometryPtr poKmlMultiGeometry;
712 :
713 : size_t nGeom;
714 : size_t i;
715 :
716 69 : switch ( poKmlGeometry->Type ( ) ) {
717 :
718 : case kmldom::Type_Point:
719 19 : poKmlPoint = AsPoint ( poKmlGeometry );
720 :
721 19 : if ( poKmlPoint->has_altitudemode ( ) ) {
722 4 : *pnAltitudeMode = poKmlPoint->get_altitudemode ( );
723 4 : return TRUE;
724 : }
725 15 : else if ( poKmlPoint->has_gx_altitudemode ( ) ) {
726 0 : *pnAltitudeMode = poKmlPoint->get_gx_altitudemode ( );
727 0 : *pbIsGX = TRUE;
728 0 : return TRUE;
729 : }
730 :
731 15 : break;
732 :
733 : case kmldom::Type_LineString:
734 15 : poKmlLineString = AsLineString ( poKmlGeometry );
735 :
736 15 : if ( poKmlLineString->has_altitudemode ( ) ) {
737 2 : *pnAltitudeMode = poKmlLineString->get_altitudemode ( );
738 2 : return TRUE;
739 : }
740 13 : else if ( poKmlLineString->has_gx_altitudemode ( ) ) {
741 0 : *pnAltitudeMode = poKmlLineString->get_gx_altitudemode ( );
742 0 : *pbIsGX = TRUE;
743 0 : return TRUE;
744 : }
745 13 : break;
746 :
747 : case kmldom::Type_LinearRing:
748 3 : break;
749 :
750 : case kmldom::Type_Polygon:
751 21 : poKmlPolygon = AsPolygon ( poKmlGeometry );
752 :
753 21 : if ( poKmlPolygon->has_altitudemode ( ) ) {
754 8 : *pnAltitudeMode = poKmlPolygon->get_altitudemode ( );
755 8 : return TRUE;
756 : }
757 13 : else if ( poKmlPolygon->has_gx_altitudemode ( ) ) {
758 0 : *pnAltitudeMode = poKmlPolygon->get_gx_altitudemode ( );
759 0 : *pbIsGX = TRUE;
760 0 : return TRUE;
761 : }
762 :
763 13 : break;
764 :
765 : case kmldom::Type_MultiGeometry:
766 11 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
767 :
768 11 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
769 26 : for ( i = 0; i < nGeom; i++ ) {
770 15 : if ( kml2altitudemode_rec ( poKmlMultiGeometry->
771 : get_geometry_array_at ( i ),
772 : pnAltitudeMode, pbIsGX ) )
773 0 : return TRUE;
774 : }
775 :
776 : break;
777 :
778 : default:
779 : break;
780 :
781 : }
782 :
783 55 : return FALSE;
784 : }
785 :
786 : /******************************************************************************
787 : recursive function to read extrude from the geometry
788 : ******************************************************************************/
789 :
790 : int kml2extrude_rec (
791 : GeometryPtr poKmlGeometry,
792 69 : int *pnExtrude )
793 : {
794 :
795 69 : PointPtr poKmlPoint;
796 69 : LineStringPtr poKmlLineString;
797 69 : PolygonPtr poKmlPolygon;
798 69 : MultiGeometryPtr poKmlMultiGeometry;
799 :
800 : size_t nGeom;
801 : size_t i;
802 :
803 69 : switch ( poKmlGeometry->Type ( ) ) {
804 :
805 : case kmldom::Type_Point:
806 19 : poKmlPoint = AsPoint ( poKmlGeometry );
807 :
808 19 : if ( poKmlPoint->has_extrude ( ) ) {
809 2 : *pnExtrude = poKmlPoint->get_extrude ( );
810 2 : return TRUE;
811 : }
812 :
813 17 : break;
814 :
815 : case kmldom::Type_LineString:
816 15 : poKmlLineString = AsLineString ( poKmlGeometry );
817 :
818 15 : if ( poKmlLineString->has_extrude ( ) ) {
819 0 : *pnExtrude = poKmlLineString->get_extrude ( );
820 0 : return TRUE;
821 : }
822 :
823 15 : break;
824 :
825 : case kmldom::Type_LinearRing:
826 3 : break;
827 :
828 : case kmldom::Type_Polygon:
829 21 : poKmlPolygon = AsPolygon ( poKmlGeometry );
830 :
831 21 : if ( poKmlPolygon->has_extrude ( ) ) {
832 8 : *pnExtrude = poKmlPolygon->get_extrude ( );
833 8 : return TRUE;
834 : }
835 :
836 13 : break;
837 :
838 : case kmldom::Type_MultiGeometry:
839 11 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
840 :
841 11 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
842 26 : for ( i = 0; i < nGeom; i++ ) {
843 15 : if ( kml2extrude_rec ( poKmlMultiGeometry->
844 : get_geometry_array_at ( i ), pnExtrude ) )
845 0 : return TRUE;
846 : }
847 :
848 : break;
849 :
850 : default:
851 : break;
852 :
853 : }
854 :
855 59 : return FALSE;
856 : }
857 :
858 : /******************************************************************************
859 : recursive function to read tessellate from the geometry
860 : ******************************************************************************/
861 :
862 : int kml2tessellate_rec (
863 : GeometryPtr poKmlGeometry,
864 69 : int *pnTessellate )
865 : {
866 :
867 69 : LineStringPtr poKmlLineString;
868 69 : PolygonPtr poKmlPolygon;
869 69 : MultiGeometryPtr poKmlMultiGeometry;
870 :
871 : size_t nGeom;
872 : size_t i;
873 :
874 69 : switch ( poKmlGeometry->Type ( ) ) {
875 :
876 : case kmldom::Type_Point:
877 19 : break;
878 :
879 : case kmldom::Type_LineString:
880 15 : poKmlLineString = AsLineString ( poKmlGeometry );
881 :
882 15 : if ( poKmlLineString->has_tessellate ( ) ) {
883 6 : *pnTessellate = poKmlLineString->get_tessellate ( );
884 6 : return TRUE;
885 : }
886 :
887 9 : break;
888 :
889 : case kmldom::Type_LinearRing:
890 3 : break;
891 :
892 : case kmldom::Type_Polygon:
893 21 : poKmlPolygon = AsPolygon ( poKmlGeometry );
894 :
895 21 : if ( poKmlPolygon->has_tessellate ( ) ) {
896 0 : *pnTessellate = poKmlPolygon->get_tessellate ( );
897 0 : return TRUE;
898 : }
899 :
900 21 : break;
901 :
902 : case kmldom::Type_MultiGeometry:
903 11 : poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
904 :
905 11 : nGeom = poKmlMultiGeometry->get_geometry_array_size ( );
906 26 : for ( i = 0; i < nGeom; i++ ) {
907 15 : if ( kml2tessellate_rec ( poKmlMultiGeometry->
908 : get_geometry_array_at ( i ),
909 : pnTessellate ) )
910 0 : return TRUE;
911 : }
912 :
913 : break;
914 :
915 : default:
916 : break;
917 :
918 : }
919 :
920 63 : return FALSE;
921 : }
922 :
923 : /******************************************************************************
924 : function to read kml into ogr fields
925 : ******************************************************************************/
926 :
927 : void kml2field (
928 : OGRFeature * poOgrFeat,
929 54 : PlacemarkPtr poKmlPlacemark )
930 : {
931 :
932 54 : const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
933 : const char *descfield =
934 54 : CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
935 : const char *tsfield =
936 54 : CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
937 : const char *beginfield =
938 54 : CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
939 54 : const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
940 : const char *altitudeModefield =
941 54 : CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
942 : const char *tessellatefield =
943 54 : CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
944 : const char *extrudefield =
945 54 : CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
946 : const char *visibilityfield =
947 54 : CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
948 :
949 : /***** name *****/
950 :
951 54 : if ( poKmlPlacemark->has_name ( ) ) {
952 22 : const std::string oKmlName = poKmlPlacemark->get_name ( );
953 22 : int iField = poOgrFeat->GetFieldIndex ( namefield );
954 :
955 22 : if ( iField > -1 )
956 22 : poOgrFeat->SetField ( iField, oKmlName.c_str ( ) );
957 : }
958 :
959 : /***** description *****/
960 :
961 54 : if ( poKmlPlacemark->has_description ( ) ) {
962 13 : const std::string oKmlDesc = poKmlPlacemark->get_description ( );
963 13 : int iField = poOgrFeat->GetFieldIndex ( descfield );
964 :
965 13 : if ( iField > -1 )
966 13 : poOgrFeat->SetField ( iField, oKmlDesc.c_str ( ) );
967 : }
968 :
969 54 : if ( poKmlPlacemark->has_timeprimitive ( ) ) {
970 : TimePrimitivePtr poKmlTimePrimitive =
971 0 : poKmlPlacemark->get_timeprimitive ( );
972 :
973 : /***** timestamp *****/
974 :
975 0 : if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeStamp ) ) {
976 0 : TimeStampPtr poKmlTimeStamp = AsTimeStamp ( poKmlTimePrimitive );
977 :
978 0 : if ( poKmlTimeStamp->has_when ( ) ) {
979 0 : const std::string oKmlWhen = poKmlTimeStamp->get_when ( );
980 :
981 :
982 0 : int iField = poOgrFeat->GetFieldIndex ( tsfield );
983 :
984 0 : if ( iField > -1 ) {
985 : int nYear,
986 : nMonth,
987 : nDay,
988 : nHour,
989 : nMinute,
990 : nTZ;
991 : float fSecond;
992 :
993 0 : if ( OGRParseXMLDateTime
994 : ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour,
995 : &nMinute, &fSecond, &nTZ ) )
996 : poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
997 : nHour, nMinute, ( int )fSecond,
998 0 : nTZ );
999 0 : }
1000 0 : }
1001 : }
1002 :
1003 : /***** timespan *****/
1004 :
1005 0 : if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeSpan ) ) {
1006 0 : TimeSpanPtr poKmlTimeSpan = AsTimeSpan ( poKmlTimePrimitive );
1007 :
1008 : /***** begin *****/
1009 :
1010 0 : if ( poKmlTimeSpan->has_begin ( ) ) {
1011 0 : const std::string oKmlWhen = poKmlTimeSpan->get_begin ( );
1012 :
1013 :
1014 0 : int iField = poOgrFeat->GetFieldIndex ( beginfield );
1015 :
1016 0 : if ( iField > -1 ) {
1017 : int nYear,
1018 : nMonth,
1019 : nDay,
1020 : nHour,
1021 : nMinute,
1022 : nTZ;
1023 : float fSecond;
1024 :
1025 0 : if ( OGRParseXMLDateTime
1026 : ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour,
1027 : &nMinute, &fSecond, &nTZ ) )
1028 : poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
1029 : nHour, nMinute, ( int )fSecond,
1030 0 : nTZ );
1031 0 : }
1032 : }
1033 :
1034 : /***** end *****/
1035 :
1036 0 : if ( poKmlTimeSpan->has_end ( ) ) {
1037 0 : const std::string oKmlWhen = poKmlTimeSpan->get_end ( );
1038 :
1039 :
1040 0 : int iField = poOgrFeat->GetFieldIndex ( endfield );
1041 :
1042 0 : if ( iField > -1 ) {
1043 : int nYear,
1044 : nMonth,
1045 : nDay,
1046 : nHour,
1047 : nMinute,
1048 : nTZ;
1049 : float fSecond;
1050 :
1051 0 : if ( OGRParseXMLDateTime
1052 : ( oKmlWhen.c_str ( ), &nYear, &nMonth, &nDay, &nHour,
1053 : &nMinute, &fSecond, &nTZ ) )
1054 : poOgrFeat->SetField ( iField, nYear, nMonth, nDay,
1055 : nHour, nMinute, ( int )fSecond,
1056 0 : nTZ );
1057 0 : }
1058 0 : }
1059 0 : }
1060 : }
1061 :
1062 :
1063 54 : if ( poKmlPlacemark->has_geometry ( ) ) {
1064 54 : GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry ( );
1065 :
1066 : /***** altitudeMode *****/
1067 :
1068 :
1069 54 : int bIsGX = FALSE;
1070 54 : int nAltitudeMode = -1;
1071 :
1072 54 : int iField = poOgrFeat->GetFieldIndex ( altitudeModefield );
1073 :
1074 54 : if ( iField > -1 ) {
1075 :
1076 54 : if ( kml2altitudemode_rec ( poKmlGeometry,
1077 : &nAltitudeMode, &bIsGX ) ) {
1078 :
1079 14 : if ( !bIsGX ) {
1080 :
1081 14 : switch ( nAltitudeMode ) {
1082 : case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
1083 0 : poOgrFeat->SetField ( iField, "clampToGround" );
1084 0 : break;
1085 :
1086 : case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
1087 12 : poOgrFeat->SetField ( iField, "relativeToGround" );
1088 12 : break;
1089 :
1090 : case kmldom::ALTITUDEMODE_ABSOLUTE:
1091 2 : poOgrFeat->SetField ( iField, "absolute" );
1092 : break;
1093 :
1094 : }
1095 : }
1096 :
1097 : else {
1098 0 : switch ( nAltitudeMode ) {
1099 : case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
1100 0 : poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
1101 0 : break;
1102 :
1103 : case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
1104 0 : poOgrFeat->SetField ( iField, "clampToSeaFloor" );
1105 : break;
1106 : }
1107 :
1108 : }
1109 : }
1110 :
1111 : }
1112 :
1113 : /***** tessellate *****/
1114 :
1115 54 : int nTessellate = -1;
1116 :
1117 54 : kml2tessellate_rec ( poKmlGeometry, &nTessellate );
1118 :
1119 54 : iField = poOgrFeat->GetFieldIndex ( tessellatefield );
1120 54 : if ( iField > -1 )
1121 54 : poOgrFeat->SetField ( iField, nTessellate );
1122 :
1123 : /***** extrude *****/
1124 :
1125 54 : int nExtrude = -1;
1126 :
1127 54 : kml2extrude_rec ( poKmlGeometry, &nExtrude );
1128 :
1129 54 : iField = poOgrFeat->GetFieldIndex ( extrudefield );
1130 54 : if ( iField > -1 )
1131 54 : poOgrFeat->SetField ( iField, nExtrude );
1132 :
1133 : }
1134 :
1135 : /***** visibility *****/
1136 :
1137 54 : int nVisibility = -1;
1138 :
1139 54 : if ( poKmlPlacemark->has_visibility ( ) )
1140 19 : nVisibility = poKmlPlacemark->get_visibility ( );
1141 :
1142 54 : int iField = poOgrFeat->GetFieldIndex ( visibilityfield );
1143 :
1144 54 : if ( iField > -1 )
1145 54 : poOgrFeat->SetField ( iField, nVisibility );
1146 :
1147 54 : ExtendedDataPtr poKmlExtendedData = NULL;
1148 :
1149 54 : if ( poKmlPlacemark->has_extendeddata ( ) ) {
1150 0 : poKmlExtendedData = poKmlPlacemark->get_extendeddata ( );
1151 :
1152 : /***** loop over the schemadata_arrays *****/
1153 :
1154 0 : size_t nSchemaData = poKmlExtendedData->get_schemadata_array_size ( );
1155 :
1156 : size_t iSchemaData;
1157 :
1158 0 : for ( iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ ) {
1159 : SchemaDataPtr poKmlSchemaData =
1160 0 : poKmlExtendedData->get_schemadata_array_at ( iSchemaData );
1161 :
1162 : /***** loop over the simpledata array *****/
1163 :
1164 : size_t nSimpleData =
1165 0 : poKmlSchemaData->get_simpledata_array_size ( );
1166 :
1167 : size_t iSimpleData;
1168 :
1169 0 : for ( iSimpleData = 0; iSimpleData < nSimpleData; iSimpleData++ ) {
1170 : SimpleDataPtr poKmlSimpleData =
1171 0 : poKmlSchemaData->get_simpledata_array_at ( iSimpleData );
1172 :
1173 : /***** find the field index *****/
1174 :
1175 0 : int iField = -1;
1176 :
1177 0 : if ( poKmlSimpleData->has_name ( ) ) {
1178 0 : const string oName = poKmlSimpleData->get_name ( );
1179 0 : const char *pszName = oName.c_str ( );
1180 :
1181 0 : iField = poOgrFeat->GetFieldIndex ( pszName );
1182 : }
1183 :
1184 : /***** if it has trxt set the field *****/
1185 :
1186 0 : if ( iField > -1 && poKmlSimpleData->has_text ( ) ) {
1187 0 : const string oText = poKmlSimpleData->get_text ( );
1188 :
1189 0 : poOgrFeat->SetField ( iField, oText.c_str ( ) );
1190 : }
1191 : }
1192 : }
1193 54 : }
1194 :
1195 54 : }
1196 :
1197 : /******************************************************************************
1198 : function create a simplefield from a FieldDefn
1199 : ******************************************************************************/
1200 :
1201 : SimpleFieldPtr FieldDef2kml (
1202 : OGRFieldDefn * poOgrFieldDef,
1203 2 : KmlFactory * poKmlFactory )
1204 : {
1205 :
1206 2 : SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField ( );
1207 2 : const char *pszFieldName = poOgrFieldDef->GetNameRef ( );
1208 :
1209 2 : poKmlSimpleField->set_name ( pszFieldName );
1210 :
1211 4 : const char *namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD", "Name" );
1212 : const char *descfield =
1213 2 : CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD", "description" );
1214 : const char *tsfield =
1215 2 : CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD", "timestamp" );
1216 : const char *beginfield =
1217 2 : CPLGetConfigOption ( "LIBKML_BEGIN_FIELD", "begin" );
1218 2 : const char *endfield = CPLGetConfigOption ( "LIBKML_END_FIELD", "end" );
1219 : const char *altitudeModefield =
1220 2 : CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD", "altitudeMode" );
1221 : const char *tessellatefield =
1222 2 : CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD", "tessellate" );
1223 : const char *extrudefield =
1224 2 : CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD", "extrude" );
1225 : const char *visibilityfield =
1226 2 : CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD", "visibility" );
1227 :
1228 :
1229 2 : SimpleDataPtr poKmlSimpleData = NULL;
1230 :
1231 2 : switch ( poOgrFieldDef->GetType ( ) ) {
1232 :
1233 : case OFTInteger:
1234 : case OFTIntegerList:
1235 0 : if ( EQUAL ( pszFieldName, tessellatefield ) ||
1236 : EQUAL ( pszFieldName, extrudefield ) ||
1237 : EQUAL ( pszFieldName, visibilityfield ) )
1238 0 : break;
1239 0 : poKmlSimpleField->set_type ( "int" );
1240 0 : return poKmlSimpleField;
1241 : case OFTReal:
1242 : case OFTRealList:
1243 0 : poKmlSimpleField->set_type ( "float" );
1244 0 : return poKmlSimpleField;
1245 : case OFTBinary:
1246 0 : poKmlSimpleField->set_type ( "bool" );
1247 0 : return poKmlSimpleField;
1248 : case OFTString:
1249 : case OFTStringList:
1250 2 : if ( EQUAL ( pszFieldName, namefield ) ||
1251 : EQUAL ( pszFieldName, descfield ) ||
1252 : EQUAL ( pszFieldName, altitudeModefield ) )
1253 2 : break;
1254 0 : poKmlSimpleField->set_type ( "string" );
1255 0 : return poKmlSimpleField;
1256 :
1257 : /***** kml has these types but as timestamp/timespan *****/
1258 :
1259 : case OFTDate:
1260 : case OFTTime:
1261 : case OFTDateTime:
1262 0 : if ( EQUAL ( pszFieldName, tsfield )
1263 : || EQUAL ( pszFieldName, beginfield )
1264 : || EQUAL ( pszFieldName, endfield ) )
1265 0 : break;
1266 : default:
1267 0 : poKmlSimpleField->set_type ( "string" );
1268 0 : return poKmlSimpleField;
1269 : }
1270 :
1271 2 : return NULL;
1272 : }
1273 :
1274 : /******************************************************************************
1275 : function to add the simpleFields in a schema to a featuredefn
1276 : ******************************************************************************/
1277 :
1278 : void kml2FeatureDef (
1279 : SchemaPtr poKmlSchema,
1280 0 : OGRFeatureDefn * poOgrFeatureDefn )
1281 : {
1282 :
1283 0 : size_t nSimpleFields = poKmlSchema->get_simplefield_array_size ( );
1284 : size_t iSimpleField;
1285 :
1286 0 : for ( iSimpleField = 0; iSimpleField < nSimpleFields; iSimpleField++ ) {
1287 : SimpleFieldPtr poKmlSimpleField =
1288 0 : poKmlSchema->get_simplefield_array_at ( iSimpleField );
1289 :
1290 0 : const char *pszType = "string";
1291 0 : const char *pszName = "Unknown";
1292 :
1293 0 : if ( poKmlSimpleField->has_type ( ) ) {
1294 0 : const string oType = poKmlSimpleField->get_type ( );
1295 :
1296 0 : pszType = oType.c_str ( );
1297 : }
1298 :
1299 0 : if ( poKmlSimpleField->has_displayname ( ) ) {
1300 0 : const string oName = poKmlSimpleField->get_displayname ( );
1301 :
1302 0 : pszName = oName.c_str ( );
1303 : }
1304 :
1305 0 : else if ( poKmlSimpleField->has_name ( ) ) {
1306 0 : const string oName = poKmlSimpleField->get_name ( );
1307 :
1308 0 : pszName = oName.c_str ( );
1309 : }
1310 :
1311 0 : if ( EQUAL ( pszType, "string" ) ) {
1312 : OGRFieldDefn oOgrFieldName (
1313 : pszName,
1314 0 : OFTString );
1315 :
1316 0 : poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
1317 : }
1318 0 : if ( EQUAL ( pszType, "int" ) ) {
1319 : OGRFieldDefn oOgrFieldName (
1320 : pszName,
1321 0 : OFTInteger );
1322 :
1323 0 : poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
1324 : }
1325 0 : if ( EQUAL ( pszType, "float" ) ) {
1326 : OGRFieldDefn oOgrFieldName (
1327 : pszName,
1328 0 : OFTReal );
1329 :
1330 0 : poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
1331 : }
1332 0 : if ( EQUAL ( pszType, "bool" ) ) {
1333 : OGRFieldDefn oOgrFieldName (
1334 : pszName,
1335 0 : OFTBinary );
1336 :
1337 0 : poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
1338 : }
1339 :
1340 :
1341 : }
1342 :
1343 :
1344 : return;
1345 896 : }
|