1 /******************************************************************************
2 * $Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
3 *
4 * Project: OGR/DODS Interface
5 * Purpose: Implements OGRDODSSequenceLayer class, which implements the
6 * "Simple Sequence" access strategy.
7 * Author: Frank Warmerdam, warmerdam@pobox.com
8 *
9 ******************************************************************************
10 * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "cpl_conv.h"
32 #include "ogr_dods.h"
33 #include "cpl_string.h"
34
35 CPL_CVSID("$Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
36
37 /************************************************************************/
38 /* OGRDODSSequenceLayer() */
39 /************************************************************************/
40
OGRDODSSequenceLayer(OGRDODSDataSource * poDSIn,const char * pszTargetIn,AttrTable * poOGRLayerInfoIn)41 OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
42 const char *pszTargetIn,
43 AttrTable *poOGRLayerInfoIn )
44
45 : OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn )
46
47 {
48 pszSubSeqPath = "profile"; // hardcode for now.
49 panSubSeqSize = NULL;
50 iLastSuperSeq = -1;
51
52 /* -------------------------------------------------------------------- */
53 /* What is the layer name? */
54 /* -------------------------------------------------------------------- */
55 string oLayerName;
56 const char *pszLayerName = pszTargetIn;
57
58 if( poOGRLayerInfo != NULL )
59 {
60 oLayerName = poOGRLayerInfo->get_attr( "layer_name" );
61 if( strlen(oLayerName.c_str()) > 0 )
62 pszLayerName = oLayerName.c_str();
63 }
64
65 poFeatureDefn = new OGRFeatureDefn( pszLayerName );
66 poFeatureDefn->Reference();
67
68 /* -------------------------------------------------------------------- */
69 /* Fetch the target variable. */
70 /* -------------------------------------------------------------------- */
71 Sequence *seq = dynamic_cast<Sequence *>(poDS->poDDS->var( pszTargetIn ));
72
73 poTargetVar = seq;
74 poSuperSeq = FindSuperSequence( seq );
75
76 /* -------------------------------------------------------------------- */
77 /* X/Y/Z fields. */
78 /* -------------------------------------------------------------------- */
79 if( poOGRLayerInfo != NULL )
80 {
81 AttrTable *poField = poOGRLayerInfo->find_container("x_field");
82 if( poField != NULL )
83 oXField.Initialize( poField, poTargetVar, poSuperSeq );
84
85 poField = poOGRLayerInfo->find_container("y_field");
86 if( poField != NULL )
87 oYField.Initialize( poField, poTargetVar, poSuperSeq );
88
89 poField = poOGRLayerInfo->find_container("z_field");
90 if( poField != NULL )
91 oZField.Initialize( poField, poTargetVar, poSuperSeq );
92 }
93
94 /* -------------------------------------------------------------------- */
95 /* If we have no layerinfo, then check if there are obvious x/y */
96 /* fields. */
97 /* -------------------------------------------------------------------- */
98 else
99 {
100 string oTargName = pszTargetIn;
101 string oSSTargName;
102 string x, y;
103
104 if( poSuperSeq != NULL )
105 oSSTargName = OGRDODSGetVarPath( poSuperSeq );
106 else
107 oSSTargName = "impossiblexxx";
108
109 if( poDS->poDDS->var( oTargName + ".lon" ) != NULL
110 && poDS->poDDS->var( oTargName + ".lat" ) != NULL )
111 {
112 oXField.Initialize( (oTargName + ".lon").c_str(), "dds",
113 poTargetVar, poSuperSeq );
114 oYField.Initialize( (oTargName + ".lat").c_str(), "dds",
115 poTargetVar, poSuperSeq );
116 }
117 else if( poDS->poDDS->var( oSSTargName + ".lon" ) != NULL
118 && poDS->poDDS->var( oSSTargName + ".lat" ) != NULL )
119 {
120 oXField.Initialize( (oSSTargName + ".lon").c_str(), "dds",
121 poTargetVar, poSuperSeq );
122 oYField.Initialize( (oSSTargName + ".lat").c_str(), "dds",
123 poTargetVar, poSuperSeq );
124 }
125 }
126
127 /* -------------------------------------------------------------------- */
128 /* Add fields for the contents of the sequence. */
129 /* -------------------------------------------------------------------- */
130 Sequence::Vars_iter v_i;
131
132 for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
133 BuildFields( *v_i, NULL, NULL );
134
135 /* -------------------------------------------------------------------- */
136 /* Add fields for the contents of the super-sequence if we have */
137 /* one. */
138 /* -------------------------------------------------------------------- */
139 if( poSuperSeq != NULL )
140 {
141 for( v_i = poSuperSeq->var_begin();
142 v_i != poSuperSeq->var_end();
143 v_i++ )
144 BuildFields( *v_i, NULL, NULL );
145 }
146 }
147
148 /************************************************************************/
149 /* ~OGRDODSSequenceLayer() */
150 /************************************************************************/
151
~OGRDODSSequenceLayer()152 OGRDODSSequenceLayer::~OGRDODSSequenceLayer()
153
154 {
155 }
156
157 /************************************************************************/
158 /* FindSuperSequence() */
159 /* */
160 /* Are we a subsequence of a sequence? */
161 /************************************************************************/
162
FindSuperSequence(BaseType * poChild)163 Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
164
165 {
166 BaseType *poParent;
167
168 for( poParent = poChild->get_parent();
169 poParent != NULL;
170 poParent = poParent->get_parent() )
171 {
172 if( poParent->type() == dods_sequence_c )
173 {
174 return dynamic_cast<Sequence *>( poParent );
175 }
176 }
177
178 return NULL;
179 }
180
181 /************************************************************************/
182 /* BuildFields() */
183 /* */
184 /* Build the field definition or definitions corresponding to */
185 /* the passed variable and it's children (if it has them). */
186 /************************************************************************/
187
BuildFields(BaseType * poFieldVar,const char * pszPathToVar,const char * pszPathToSequence)188 int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
189 const char *pszPathToVar,
190 const char *pszPathToSequence )
191
192 {
193 OGRFieldDefn oField( "", OFTInteger );
194
195 /* -------------------------------------------------------------------- */
196 /* Setup field name, including path if non-local. */
197 /* -------------------------------------------------------------------- */
198 if( pszPathToVar == NULL )
199 oField.SetName( poFieldVar->name().c_str() );
200 else
201 oField.SetName( CPLSPrintf( "%s.%s", pszPathToVar,
202 poFieldVar->name().c_str() ) );
203
204 /* -------------------------------------------------------------------- */
205 /* Capture this field definition. */
206 /* -------------------------------------------------------------------- */
207 switch( poFieldVar->type() )
208 {
209 case dods_byte_c:
210 case dods_int16_c:
211 case dods_uint16_c:
212 case dods_int32_c:
213 case dods_uint32_c:
214 if( pszPathToSequence )
215 oField.SetType( OFTIntegerList );
216 else
217 oField.SetType( OFTInteger );
218 break;
219
220 case dods_float32_c:
221 case dods_float64_c:
222 if( pszPathToSequence )
223 oField.SetType( OFTRealList );
224 else
225 oField.SetType( OFTReal );
226 break;
227
228 case dods_str_c:
229 case dods_url_c:
230 if( pszPathToSequence )
231 oField.SetType( OFTStringList );
232 else
233 oField.SetType( OFTString );
234 break;
235
236 case dods_sequence_c:
237 {
238 Sequence *seq = dynamic_cast<Sequence *>( poFieldVar );
239 Sequence::Vars_iter v_i;
240
241 // We don't support a 3rd level of sequence nesting.
242 if( pszPathToSequence != NULL )
243 return FALSE;
244
245 // We don't explore down into the target sequence if we
246 // are recursing from a supersequence.
247 if( poFieldVar == this->poTargetVar )
248 return FALSE;
249
250 for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
251 {
252 BuildFields( *v_i, oField.GetNameRef(), oField.GetNameRef() );
253 }
254 }
255 return FALSE;
256
257 default:
258 return FALSE;
259 }
260
261 /* -------------------------------------------------------------------- */
262 /* Add field to feature defn, and capture mapping. */
263 /* -------------------------------------------------------------------- */
264 poFeatureDefn->AddFieldDefn( &oField );
265
266 papoFields = (OGRDODSFieldDefn **)
267 CPLRealloc( papoFields, sizeof(void*) * poFeatureDefn->GetFieldCount());
268
269 papoFields[poFeatureDefn->GetFieldCount()-1] =
270 new OGRDODSFieldDefn();
271
272 papoFields[poFeatureDefn->GetFieldCount()-1]->Initialize(
273 OGRDODSGetVarPath(poFieldVar).c_str(), "dds",
274 poTargetVar, poSuperSeq );
275
276
277 if( pszPathToSequence )
278 papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence
279 = CPLStrdup( pszPathToSequence );
280
281 return TRUE;
282 }
283
284 /************************************************************************/
285 /* GetFieldValue() */
286 /************************************************************************/
287
GetFieldValue(OGRDODSFieldDefn * poFDefn,int nFeatureId,Sequence * seq)288 BaseType *OGRDODSSequenceLayer::GetFieldValue( OGRDODSFieldDefn *poFDefn,
289 int nFeatureId,
290 Sequence *seq )
291
292 {
293 if( seq == NULL )
294 seq = dynamic_cast<Sequence *>(poTargetVar);
295
296 if( !poFDefn->bValid )
297 return NULL;
298
299 /* ==================================================================== */
300 /* Fetch the actual value. */
301 /* ==================================================================== */
302
303 /* -------------------------------------------------------------------- */
304 /* Simple case of a direct field within the sequence object. */
305 /* -------------------------------------------------------------------- */
306 if( poFDefn->iFieldIndex >= 0 && poFDefn->bRelativeToSequence )
307 {
308 return seq->var_value( nFeatureId, poFDefn->iFieldIndex );
309 }
310 else if( poFDefn->iFieldIndex >= 0 && poFDefn->bRelativeToSuperSequence )
311 {
312 return poSuperSeq->var_value( iLastSuperSeq, poFDefn->iFieldIndex );
313 }
314
315 /* -------------------------------------------------------------------- */
316 /* More complex case where we need to drill down by name. */
317 /* -------------------------------------------------------------------- */
318 if( poFDefn->bRelativeToSequence )
319 return seq->var_value( nFeatureId, poFDefn->pszFieldName );
320 else if( poSuperSeq != NULL && poFDefn->bRelativeToSuperSequence )
321 return poSuperSeq->var_value( iLastSuperSeq, poFDefn->pszFieldName );
322 else
323 return poDataDDS->var( poFDefn->pszFieldName );
324 }
325
326 /************************************************************************/
327 /* BaseTypeToDouble() */
328 /************************************************************************/
329
BaseTypeToDouble(BaseType * poBT)330 double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
331
332 {
333 switch( poBT->type() )
334 {
335 case dods_byte_c:
336 {
337 signed char byVal;
338 void *pValPtr = &byVal;
339
340 poBT->buf2val( &pValPtr );
341 return (double) byVal;
342 }
343 break;
344
345 case dods_int16_c:
346 {
347 GInt16 nIntVal;
348 void *pValPtr = &nIntVal;
349
350 poBT->buf2val( &pValPtr );
351 return (double) nIntVal;
352 }
353 break;
354
355 case dods_uint16_c:
356 {
357 GUInt16 nIntVal;
358 void *pValPtr = &nIntVal;
359
360 poBT->buf2val( &pValPtr );
361 return (double) nIntVal;
362 }
363 break;
364
365 case dods_int32_c:
366 {
367 GInt32 nIntVal;
368 void *pValPtr = &nIntVal;
369
370 poBT->buf2val( &pValPtr );
371 return (double) nIntVal;
372 }
373 break;
374
375 case dods_uint32_c:
376 {
377 GUInt32 nIntVal;
378 void *pValPtr = &nIntVal;
379
380 poBT->buf2val( &pValPtr );
381 return (double) nIntVal;
382 }
383 break;
384
385 case dods_float32_c:
386 return dynamic_cast<Float32 *>(poBT)->value();
387
388 case dods_float64_c:
389 return dynamic_cast<Float64 *>(poBT)->value();
390
391 case dods_str_c:
392 case dods_url_c:
393 {
394 string *poStrVal = NULL;
395 double dfResult;
396
397 poBT->buf2val( (void **) &poStrVal );
398 dfResult = CPLAtof(poStrVal->c_str());
399 delete poStrVal;
400 return dfResult;
401 }
402 break;
403
404 default:
405 CPLAssert( FALSE );
406 break;
407 }
408
409 return 0.0;
410 }
411
412 /************************************************************************/
413 /* GetFieldValueAsDouble() */
414 /************************************************************************/
415
GetFieldValueAsDouble(OGRDODSFieldDefn * poFDefn,int nFeatureId)416 double OGRDODSSequenceLayer::GetFieldValueAsDouble( OGRDODSFieldDefn *poFDefn,
417 int nFeatureId )
418
419 {
420 BaseType *poBT;
421
422 poBT = GetFieldValue( poFDefn, nFeatureId, NULL );
423 if( poBT == NULL )
424 return 0.0;
425
426 return BaseTypeToDouble( poBT );
427 }
428
429 /************************************************************************/
430 /* GetFeature() */
431 /************************************************************************/
432
GetFeature(GIntBig nFeatureId)433 OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
434
435 {
436 /* -------------------------------------------------------------------- */
437 /* Ensure we have the dataset. */
438 /* -------------------------------------------------------------------- */
439 if( !ProvideDataDDS() )
440 return NULL;
441
442 Sequence *seq = dynamic_cast<Sequence *>(poTargetVar);
443
444 /* -------------------------------------------------------------------- */
445 /* Figure out what the super and subsequence number this */
446 /* feature will be, and validate it. If there is not super */
447 /* sequence the feature id is the subsequence number. */
448 /* -------------------------------------------------------------------- */
449 int iSubSeq = -1;
450
451 if( nFeatureId < 0 || nFeatureId >= nRecordCount )
452 return NULL;
453
454 if( poSuperSeq == NULL )
455 iSubSeq = nFeatureId;
456 else
457 {
458 int nSeqOffset = 0, iSuperSeq;
459
460 // for now we just scan through till find find out what
461 // super sequence this in. In the long term we need a better (cached)
462 // approach that doesn't involve this quadratic cost.
463 for( iSuperSeq = 0;
464 iSuperSeq < nSuperSeqCount;
465 iSuperSeq++ )
466 {
467 if( nSeqOffset + panSubSeqSize[iSuperSeq] > nFeatureId )
468 {
469 iSubSeq = nFeatureId - nSeqOffset;
470 break;
471 }
472 nSeqOffset += panSubSeqSize[iSuperSeq];
473 }
474
475 CPLAssert( iSubSeq != -1 );
476
477 // Make sure we have the right target var ... the one
478 // corresponding to our current super sequence.
479 if( iSuperSeq != iLastSuperSeq )
480 {
481 iLastSuperSeq = iSuperSeq;
482 poTargetVar = poSuperSeq->var_value( iSuperSeq, pszSubSeqPath );
483 seq = dynamic_cast<Sequence *>(poTargetVar);
484 }
485 }
486
487 /* -------------------------------------------------------------------- */
488 /* Create the feature being read. */
489 /* -------------------------------------------------------------------- */
490 OGRFeature *poFeature;
491
492 poFeature = new OGRFeature( poFeatureDefn );
493 poFeature->SetFID( nFeatureId );
494 m_nFeaturesRead++;
495
496 /* -------------------------------------------------------------------- */
497 /* Process all the regular data fields. */
498 /* -------------------------------------------------------------------- */
499 int iField;
500
501 for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
502 {
503 if( papoFields[iField]->pszPathToSequence )
504 continue;
505
506 BaseType *poFieldVar = GetFieldValue( papoFields[iField], iSubSeq,
507 NULL );
508
509 if( poFieldVar == NULL )
510 continue;
511
512 switch( poFieldVar->type() )
513 {
514 case dods_byte_c:
515 {
516 signed char byVal;
517 void *pValPtr = &byVal;
518
519 poFieldVar->buf2val( &pValPtr );
520 poFeature->SetField( iField, byVal );
521 }
522 break;
523
524 case dods_int16_c:
525 {
526 GInt16 nIntVal;
527 void *pValPtr = &nIntVal;
528
529 poFieldVar->buf2val( &pValPtr );
530 poFeature->SetField( iField, nIntVal );
531 }
532 break;
533
534 case dods_uint16_c:
535 {
536 GUInt16 nIntVal;
537 void *pValPtr = &nIntVal;
538
539 poFieldVar->buf2val( &pValPtr );
540 poFeature->SetField( iField, nIntVal );
541 }
542 break;
543
544 case dods_int32_c:
545 {
546 GInt32 nIntVal;
547 void *pValPtr = &nIntVal;
548
549 poFieldVar->buf2val( &pValPtr );
550 poFeature->SetField( iField, nIntVal );
551 }
552 break;
553
554 case dods_uint32_c:
555 {
556 GUInt32 nIntVal;
557 void *pValPtr = &nIntVal;
558
559 poFieldVar->buf2val( &pValPtr );
560 poFeature->SetField( iField, (int) nIntVal );
561 }
562 break;
563
564 case dods_float32_c:
565 poFeature->SetField( iField,
566 dynamic_cast<Float32 *>(poFieldVar)->value());
567 break;
568
569 case dods_float64_c:
570 poFeature->SetField( iField,
571 dynamic_cast<Float64 *>(poFieldVar)->value());
572 break;
573
574 case dods_str_c:
575 case dods_url_c:
576 {
577 string *poStrVal = NULL;
578 poFieldVar->buf2val( (void **) &poStrVal );
579 poFeature->SetField( iField, poStrVal->c_str() );
580 delete poStrVal;
581 }
582 break;
583
584 default:
585 break;
586 }
587 }
588
589 /* -------------------------------------------------------------------- */
590 /* Handle data nested in sequences. */
591 /* -------------------------------------------------------------------- */
592 for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
593 {
594 OGRDODSFieldDefn *poFD = papoFields[iField];
595 const char *pszPathFromSubSeq;
596
597 if( poFD->pszPathToSequence == NULL )
598 continue;
599
600 CPLAssert( strlen(poFD->pszPathToSequence)
601 < strlen(poFD->pszFieldName)-1 );
602
603 if( strstr(poFD->pszFieldName,poFD->pszPathToSequence) != NULL )
604 pszPathFromSubSeq =
605 strstr(poFD->pszFieldName,poFD->pszPathToSequence)
606 + strlen(poFD->pszPathToSequence) + 1;
607 else
608 continue;
609
610 /* -------------------------------------------------------------------- */
611 /* Get the sequence out of which this variable will be collected. */
612 /* -------------------------------------------------------------------- */
613 BaseType *poFieldVar = seq->var_value( iSubSeq,
614 poFD->pszPathToSequence );
615 Sequence *poSubSeq;
616 int nSubSeqCount;
617
618 if( poFieldVar == NULL )
619 continue;
620
621 poSubSeq = dynamic_cast<Sequence *>( poFieldVar );
622 if( poSubSeq == NULL )
623 continue;
624
625 nSubSeqCount = poSubSeq->number_of_rows();
626
627 /* -------------------------------------------------------------------- */
628 /* Allocate array to put values into. */
629 /* -------------------------------------------------------------------- */
630 OGRFieldDefn *poOFD = poFeature->GetFieldDefnRef( iField );
631 int *panIntList = NULL;
632 double *padfDblList = NULL;
633 char **papszStrList = NULL;
634
635 if( poOFD->GetType() == OFTIntegerList )
636 {
637 panIntList = (int *) CPLCalloc(sizeof(int),nSubSeqCount);
638 }
639 else if( poOFD->GetType() == OFTRealList )
640 {
641 padfDblList = (double *) CPLCalloc(sizeof(double),nSubSeqCount);
642 }
643 else if( poOFD->GetType() == OFTStringList )
644 {
645 papszStrList = (char **) CPLCalloc(sizeof(char*),nSubSeqCount+1);
646 }
647 else
648 continue;
649
650 /* -------------------------------------------------------------------- */
651 /* Loop, fetching subsequence values. */
652 /* -------------------------------------------------------------------- */
653 int iSubIndex;
654 for( iSubIndex = 0; iSubIndex < nSubSeqCount; iSubIndex++ )
655 {
656 poFieldVar = poSubSeq->var_value( iSubIndex, pszPathFromSubSeq );
657
658 if( poFieldVar == NULL )
659 continue;
660
661 switch( poFieldVar->type() )
662 {
663 case dods_byte_c:
664 {
665 signed char byVal;
666 void *pValPtr = &byVal;
667
668 poFieldVar->buf2val( &pValPtr );
669 panIntList[iSubIndex] = byVal;
670 }
671 break;
672
673 case dods_int16_c:
674 {
675 GInt16 nIntVal;
676 void *pValPtr = &nIntVal;
677
678 poFieldVar->buf2val( &pValPtr );
679 panIntList[iSubIndex] = nIntVal;
680 }
681 break;
682
683 case dods_uint16_c:
684 {
685 GUInt16 nIntVal;
686 void *pValPtr = &nIntVal;
687
688 poFieldVar->buf2val( &pValPtr );
689 panIntList[iSubIndex] = nIntVal;
690 }
691 break;
692
693 case dods_int32_c:
694 {
695 GInt32 nIntVal;
696 void *pValPtr = &nIntVal;
697
698 poFieldVar->buf2val( &pValPtr );
699 panIntList[iSubIndex] = nIntVal;
700 }
701 break;
702
703 case dods_uint32_c:
704 {
705 GUInt32 nIntVal;
706 void *pValPtr = &nIntVal;
707
708 poFieldVar->buf2val( &pValPtr );
709 panIntList[iSubIndex] = nIntVal;
710 }
711 break;
712
713 case dods_float32_c:
714 padfDblList[iSubIndex] =
715 dynamic_cast<Float32 *>(poFieldVar)->value();
716 break;
717
718 case dods_float64_c:
719 padfDblList[iSubIndex] =
720 dynamic_cast<Float64 *>(poFieldVar)->value();
721 break;
722
723 case dods_str_c:
724 case dods_url_c:
725 {
726 string *poStrVal = NULL;
727 poFieldVar->buf2val( (void **) &poStrVal );
728 papszStrList[iSubIndex] = CPLStrdup( poStrVal->c_str() );
729 delete poStrVal;
730 }
731 break;
732
733 default:
734 break;
735 }
736 }
737
738 /* -------------------------------------------------------------------- */
739 /* Apply back to feature. */
740 /* -------------------------------------------------------------------- */
741 if( poOFD->GetType() == OFTIntegerList )
742 {
743 poFeature->SetField( iField, nSubSeqCount, panIntList );
744 CPLFree(panIntList);
745 }
746 else if( poOFD->GetType() == OFTRealList )
747 {
748 poFeature->SetField( iField, nSubSeqCount, padfDblList );
749 CPLFree(padfDblList);
750 }
751 else if( poOFD->GetType() == OFTStringList )
752 {
753 poFeature->SetField( iField, papszStrList );
754 CSLDestroy( papszStrList );
755 }
756 }
757
758 /* ==================================================================== */
759 /* Fetch the geometry. */
760 /* ==================================================================== */
761 if( oXField.bValid && oYField.bValid )
762 {
763 int iXField = poFeature->GetFieldIndex( oXField.pszFieldName );
764 int iYField = poFeature->GetFieldIndex( oYField.pszFieldName );
765 int iZField = -1;
766
767 if( oZField.bValid )
768 iZField = poFeature->GetFieldIndex(oZField.pszFieldName);
769
770 /* -------------------------------------------------------------------- */
771 /* If we can't find the values in attributes then use the more */
772 /* general mechanism to fetch the value. */
773 /* -------------------------------------------------------------------- */
774
775 if( iXField == -1 || iYField == -1
776 || (oZField.bValid && iZField == -1) )
777 {
778 poFeature->SetGeometryDirectly(
779 new OGRPoint( GetFieldValueAsDouble( &oXField, iSubSeq ),
780 GetFieldValueAsDouble( &oYField, iSubSeq ),
781 GetFieldValueAsDouble( &oZField, iSubSeq ) ) );
782 }
783 /* -------------------------------------------------------------------- */
784 /* If the fields are list values, then build a linestring. */
785 /* -------------------------------------------------------------------- */
786 else if( poFeature->GetFieldDefnRef(iXField)->GetType() == OFTRealList
787 && poFeature->GetFieldDefnRef(iYField)->GetType() == OFTRealList )
788 {
789 const double *padfX, *padfY, *padfZ = NULL;
790 int nPointCount, i;
791 OGRLineString *poLS = new OGRLineString();
792
793 padfX = poFeature->GetFieldAsDoubleList( iXField, &nPointCount );
794 padfY = poFeature->GetFieldAsDoubleList( iYField, &nPointCount );
795 if( iZField != -1 )
796 padfZ = poFeature->GetFieldAsDoubleList(iZField,&nPointCount);
797
798 poLS->setPoints( nPointCount, (double *) padfX, (double *) padfY,
799 (double *) padfZ );
800
801 // Make a pass clearing out NaN or Inf values.
802 for( i = 0; i < nPointCount; i++ )
803 {
804 double dfX = poLS->getX(i);
805 double dfY = poLS->getY(i);
806 double dfZ = poLS->getZ(i);
807 int bReset = FALSE;
808
809 if( OGRDODSIsDoubleInvalid( &dfX ) )
810 {
811 dfX = 0.0;
812 bReset = TRUE;
813 }
814 if( OGRDODSIsDoubleInvalid( &dfY ) )
815 {
816 dfY = 0.0;
817 bReset = TRUE;
818 }
819 if( OGRDODSIsDoubleInvalid( &dfZ ) )
820 {
821 dfZ = 0.0;
822 bReset = TRUE;
823 }
824
825 if( bReset )
826 poLS->setPoint( i, dfX, dfY, dfZ );
827 }
828
829 poFeature->SetGeometryDirectly( poLS );
830 }
831
832 /* -------------------------------------------------------------------- */
833 /* Otherwise build a point. */
834 /* -------------------------------------------------------------------- */
835 else
836 {
837 poFeature->SetGeometryDirectly(
838 new OGRPoint(
839 poFeature->GetFieldAsDouble( iXField ),
840 poFeature->GetFieldAsDouble( iYField ),
841 poFeature->GetFieldAsDouble( iZField ) ) );
842 }
843 }
844
845 return poFeature;
846 }
847
848 /************************************************************************/
849 /* GetFeatureCount() */
850 /************************************************************************/
851
GetFeatureCount(int bForce)852 GIntBig OGRDODSSequenceLayer::GetFeatureCount( int bForce )
853
854 {
855 if( !bDataLoaded && !bForce )
856 return -1;
857
858 ProvideDataDDS();
859
860 return nRecordCount;
861 }
862
863 /************************************************************************/
864 /* ProvideDataDDS() */
865 /************************************************************************/
866
ProvideDataDDS()867 int OGRDODSSequenceLayer::ProvideDataDDS()
868
869 {
870 if( bDataLoaded )
871 return poTargetVar != NULL;
872
873 int bResult = OGRDODSLayer::ProvideDataDDS();
874
875 if( !bResult )
876 return bResult;
877
878 // If we are in nested sequence mode, we now need to properly set
879 // the poTargetVar based on the current step in the supersequence.
880 poSuperSeq = FindSuperSequence( poTargetVar );
881
882 /* ==================================================================== */
883 /* Figure out the record count. */
884 /* ==================================================================== */
885 /* -------------------------------------------------------------------- */
886 /* For simple sequences without a supersequence just return the */
887 /* count of elements. */
888 /* -------------------------------------------------------------------- */
889 if( poSuperSeq == NULL )
890 nRecordCount = dynamic_cast<Sequence *>(poTargetVar)->number_of_rows();
891
892 /* -------------------------------------------------------------------- */
893 /* Otherwise we have to count up all the target sequence */
894 /* instances for each of the super sequence items. */
895 /* -------------------------------------------------------------------- */
896 else
897 {
898 int iSuper;
899
900 nSuperSeqCount = poSuperSeq->number_of_rows();
901 panSubSeqSize = (int *) calloc(sizeof(int),nSuperSeqCount);
902 nRecordCount = 0;
903 for( iSuper = 0; iSuper < nSuperSeqCount; iSuper++ )
904 {
905 Sequence *poSubSeq = dynamic_cast<Sequence *>(
906 poSuperSeq->var_value( iSuper, pszSubSeqPath ) );
907
908 panSubSeqSize[iSuper] = poSubSeq->number_of_rows();
909 nRecordCount += poSubSeq->number_of_rows();
910 }
911 }
912
913 return poTargetVar != NULL;
914 }
915
916 /* IEEE Constants:
917
918 http://www.psc.edu/general/software/packages/ieee/ieee.html
919
920 Single Precision:
921
922 S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
923 0 1 8 9 31
924
925 The value V represented by the word may be determined as follows:
926
927 * If E=255 and F is nonzero, then V=NaN ("Not a number")
928 * If E=255 and F is zero and S is 1, then V=-Infinity
929 * If E=255 and F is zero and S is 0, then V=Infinity
930 * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
931 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
932 * If E=0 and F is zero and S is 1, then V=-0
933 * If E=0 and F is zero and S is 0, then V=0
934
935 In particular,
936
937 0 00000000 00000000000000000000000 = 0
938 1 00000000 00000000000000000000000 = -0
939
940 0 11111111 00000000000000000000000 = Infinity
941 1 11111111 00000000000000000000000 = -Infinity
942
943 0 11111111 00000100000000000000000 = NaN
944 1 11111111 00100010001001010101010 = NaN
945
946 0 10000000 00000000000000000000000 = +1 * 2**(128-127) * 1.0 = 2
947 0 10000001 10100000000000000000000 = +1 * 2**(129-127) * 1.101 = 6.5
948 1 10000001 10100000000000000000000 = -1 * 2**(129-127) * 1.101 = -6.5
949
950 0 00000001 00000000000000000000000 = +1 * 2**(1-127) * 1.0 = 2**(-126)
951 0 00000000 10000000000000000000000 = +1 * 2**(-126) * 0.1 = 2**(-127)
952 0 00000000 00000000000000000000001 = +1 * 2**(-126) *
953 0.00000000000000000000001 =
954 2**(-149) (Smallest positive value)
955
956 Double Precision:
957
958 The IEEE double precision floating point standard representation requires a 64 bit word, which may be represented as numbered from 0 to 63, left to right. The first bit is the sign bit, S, the next eleven bits are the exponent bits, 'E', and the final 52 bits are the fraction 'F':
959
960 S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
961 0 1 11 12 63
962
963 The value V represented by the word may be determined as follows:
964
965 * If E=2047 and F is nonzero, then V=NaN ("Not a number")
966 * If E=2047 and F is zero and S is 1, then V=-Infinity
967 * If E=2047 and F is zero and S is 0, then V=Infinity
968 * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
969 * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are "unnormalized" values.
970 * If E=0 and F is zero and S is 1, then V=-0
971 * If E=0 and F is zero and S is 0, then V=0
972
973 */
974
975 /************************************************************************/
976 /* OGRDODSIsFloatInvalid() */
977 /* */
978 /* For now we are really just checking if the value is NaN, Inf */
979 /* or -Inf. */
980 /************************************************************************/
981
982
OGRDODSIsFloatInvalid(const float * pfValToCheck)983 int OGRDODSIsFloatInvalid( const float * pfValToCheck )
984
985 {
986 const unsigned char *pabyValToCheck = (unsigned char *) pfValToCheck;
987
988 #if CPL_IS_LSB == 0
989 if( (pabyValToCheck[0] & 0x7f) == 0x7f
990 && (pabyValToCheck[1] & 0x80) == 0x80 )
991 return TRUE;
992 else
993 return FALSE;
994 #else
995 if( (pabyValToCheck[3] & 0x7f) == 0x7f
996 && (pabyValToCheck[2] & 0x80) == 0x80 )
997 return TRUE;
998 else
999 return FALSE;
1000 #endif
1001 }
1002
1003 /************************************************************************/
1004 /* OGRDODSIsDoubleInvalid() */
1005 /* */
1006 /* For now we are really just checking if the value is NaN, Inf */
1007 /* or -Inf. */
1008 /************************************************************************/
1009
1010
OGRDODSIsDoubleInvalid(const double * pdfValToCheck)1011 int OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
1012
1013 {
1014 const unsigned char *pabyValToCheck = (unsigned char *) pdfValToCheck;
1015
1016 #if CPL_IS_LSB == 0
1017 if( (pabyValToCheck[0] & 0x7f) == 0x7f
1018 && (pabyValToCheck[1] & 0xf0) == 0xf0 )
1019 return TRUE;
1020 else
1021 return FALSE;
1022 #else
1023 if( (pabyValToCheck[7] & 0x7f) == 0x7f
1024 && (pabyValToCheck[6] & 0xf0) == 0xf0 )
1025 return TRUE;
1026 else
1027 return FALSE;
1028 #endif
1029 }
1030