1 : /******************************************************************************
2 : * $Id: ogdidataset.cpp 17664 2009-09-21 21:16:45Z rouault $
3 : *
4 : * Name: ogdidataset.cpp
5 : * Project: OGDI Bridge
6 : * Purpose: Main driver for OGDI.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 1998, Frank Warmerdam
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 <math.h>
32 : #include "ecs.h"
33 : #include "gdal_priv.h"
34 : #include "cpl_string.h"
35 : #include "ogr_spatialref.h"
36 :
37 : CPL_CVSID("$Id: ogdidataset.cpp 17664 2009-09-21 21:16:45Z rouault $");
38 :
39 : CPL_C_START
40 : void GDALRegister_OGDI(void);
41 : CPL_C_END
42 :
43 : /************************************************************************/
44 : /* ==================================================================== */
45 : /* OGDIDataset */
46 : /* ==================================================================== */
47 : /************************************************************************/
48 :
49 : class OGDIRasterBand;
50 :
51 : class CPL_DLL OGDIDataset : public GDALDataset
52 : {
53 : friend class OGDIRasterBand;
54 :
55 : int nClientID;
56 :
57 : ecs_Region sGlobalBounds;
58 : ecs_Region sCurrentBounds;
59 : int nCurrentBand;
60 : int nCurrentIndex;
61 :
62 : char *pszProjection;
63 :
64 : static CPLErr CollectLayers(int, char***,char***);
65 : static CPLErr OverrideGlobalInfo(OGDIDataset*,const char *);
66 :
67 : void AddSubDataset( const char *pszType, const char *pszLayer );
68 : char **papszSubDatasets;
69 :
70 : public:
71 : OGDIDataset();
72 : ~OGDIDataset();
73 :
74 : static GDALDataset *Open( GDALOpenInfo * );
75 :
76 : int GetClientID() { return nClientID; }
77 :
78 : virtual const char *GetProjectionRef(void);
79 : virtual CPLErr GetGeoTransform( double * );
80 :
81 : virtual void *GetInternalHandle( const char * );
82 :
83 : virtual char **GetMetadata( const char * pszDomain = "" );
84 : };
85 :
86 : /************************************************************************/
87 : /* ==================================================================== */
88 : /* OGDIRasterBand */
89 : /* ==================================================================== */
90 : /************************************************************************/
91 :
92 : class OGDIRasterBand : public GDALRasterBand
93 : {
94 : friend class OGDIDataset;
95 :
96 : int nOGDIImageType; /* ie. 1 for RGB */
97 :
98 : char *pszLayerName;
99 : ecs_Family eFamily;
100 :
101 : int nComponent; /* varies only for RGB layers */
102 :
103 : GDALColorTable *poCT;
104 :
105 : virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
106 : void *, int, int, GDALDataType,
107 : int, int );
108 :
109 : CPLErr EstablishAccess( int nXOff, int nYOff,
110 : int nXSize, int nYSize,
111 : int nBufXSize, int nBufYSize );
112 :
113 : public:
114 :
115 : OGDIRasterBand( OGDIDataset *, int, const char *,
116 : ecs_Family, int );
117 : ~OGDIRasterBand();
118 :
119 : virtual CPLErr IReadBlock( int, int, void * );
120 : virtual int HasArbitraryOverviews();
121 : virtual GDALColorInterp GetColorInterpretation();
122 : virtual GDALColorTable *GetColorTable();
123 :
124 : virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
125 : int nBufXSize, int nBufYSize,
126 : GDALDataType eDT, char **papszOptions );
127 :
128 : };
129 :
130 : /************************************************************************/
131 : /* OGDIRasterBand() */
132 : /************************************************************************/
133 :
134 : OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDS, int nBand,
135 : const char * pszName, ecs_Family eFamily,
136 0 : int nComponent )
137 :
138 : {
139 : ecs_Result *psResult;
140 :
141 0 : this->poDS = poDS;
142 0 : this->nBand = nBand;
143 0 : this->eFamily = eFamily;
144 0 : this->pszLayerName = CPLStrdup(pszName);
145 0 : this->nComponent = nComponent;
146 0 : poCT = NULL;
147 :
148 : /* -------------------------------------------------------------------- */
149 : /* Make this layer current. */
150 : /* -------------------------------------------------------------------- */
151 : EstablishAccess( 0, 0,
152 : poDS->GetRasterXSize(), poDS->GetRasterYSize(),
153 0 : poDS->GetRasterXSize(), poDS->GetRasterYSize() );
154 :
155 : /* -------------------------------------------------------------------- */
156 : /* Get the raster info. */
157 : /* -------------------------------------------------------------------- */
158 0 : psResult = cln_GetRasterInfo( poDS->nClientID );
159 0 : if( ECSERROR(psResult) )
160 : {
161 : CPLError( CE_Failure, CPLE_AppDefined,
162 0 : "%s", psResult->message );
163 : }
164 :
165 : /* -------------------------------------------------------------------- */
166 : /* Establish if we have meaningful colortable information. */
167 : /* -------------------------------------------------------------------- */
168 0 : if( eFamily == Matrix )
169 : {
170 : int i;
171 :
172 0 : poCT = new GDALColorTable();
173 :
174 0 : for( i = 0; i < (int) ECSRASTERINFO(psResult).cat.cat_len; i++ ) {
175 : GDALColorEntry sEntry;
176 :
177 0 : sEntry.c1 = ECSRASTERINFO(psResult).cat.cat_val[i].r;
178 0 : sEntry.c2 = ECSRASTERINFO(psResult).cat.cat_val[i].g;
179 0 : sEntry.c3 = ECSRASTERINFO(psResult).cat.cat_val[i].b;
180 0 : sEntry.c4 = 255;
181 :
182 : poCT->SetColorEntry( ECSRASTERINFO(psResult).cat.cat_val[i].no_cat,
183 0 : &sEntry );
184 : }
185 : }
186 :
187 : /* -------------------------------------------------------------------- */
188 : /* Get the GDAL data type. Eventually we might use the */
189 : /* category info to establish what to do here. */
190 : /* -------------------------------------------------------------------- */
191 0 : if( eFamily == Matrix )
192 0 : eDataType = GDT_Byte;
193 0 : else if( ECSRASTERINFO(psResult).width == 1 )
194 0 : eDataType = GDT_Byte;
195 0 : else if( ECSRASTERINFO(psResult).width == 2 )
196 0 : eDataType = GDT_Byte;
197 0 : else if( ECSRASTERINFO(psResult).width == 3 )
198 0 : eDataType = GDT_UInt16;
199 0 : else if( ECSRASTERINFO(psResult).width == 4 )
200 0 : eDataType = GDT_Int16;
201 0 : else if( ECSRASTERINFO(psResult).width == 5 )
202 0 : eDataType = GDT_Int32;
203 : else
204 0 : eDataType = GDT_UInt32;
205 :
206 0 : nOGDIImageType = ECSRASTERINFO(psResult).width;
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Currently only works for strips */
210 : /* -------------------------------------------------------------------- */
211 0 : nBlockXSize = poDS->GetRasterXSize();
212 0 : nBlockYSize = 1;
213 0 : }
214 :
215 : /************************************************************************/
216 : /* ~OGDIRasterBand() */
217 : /************************************************************************/
218 :
219 0 : OGDIRasterBand::~OGDIRasterBand()
220 :
221 : {
222 0 : FlushCache();
223 0 : CPLFree( pszLayerName );
224 0 : }
225 :
226 : /************************************************************************/
227 : /* IReadBlock() */
228 : /************************************************************************/
229 :
230 0 : CPLErr OGDIRasterBand::IReadBlock( int, int nBlockYOff, void * pImage )
231 :
232 : {
233 : return IRasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1,
234 : pImage, nBlockXSize, 1, eDataType,
235 0 : GDALGetDataTypeSize(eDataType)/8, 0 );
236 : }
237 :
238 : /************************************************************************/
239 : /* IRasterIO() */
240 : /************************************************************************/
241 :
242 : CPLErr OGDIRasterBand::IRasterIO( GDALRWFlag eRWFlag,
243 : int nXOff, int nYOff, int nXSize, int nYSize,
244 : void * pData, int nBufXSize, int nBufYSize,
245 : GDALDataType eBufType,
246 0 : int nPixelSpace, int nLineSpace )
247 :
248 : {
249 0 : OGDIDataset *poODS = (OGDIDataset *) poDS;
250 : CPLErr eErr;
251 : #ifdef notdef
252 : CPLDebug( "OGDIRasterBand",
253 : "RasterIO(%d,%d,%d,%d -> %dx%d)",
254 : nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
255 : #endif
256 :
257 : /* -------------------------------------------------------------------- */
258 : /* Establish access at the desired resolution. */
259 : /* -------------------------------------------------------------------- */
260 : eErr = EstablishAccess( nXOff, nYOff, nXSize, nYSize,
261 0 : nBufXSize, nBufYSize );
262 0 : if( eErr != CE_None )
263 0 : return eErr;
264 :
265 : /* -------------------------------------------------------------------- */
266 : /* Read back one scanline at a time, till request is satisfied. */
267 : /* -------------------------------------------------------------------- */
268 : int iScanline;
269 :
270 0 : for( iScanline = 0; iScanline < nBufYSize; iScanline++ )
271 : {
272 : ecs_Result *psResult;
273 : void *pLineData;
274 0 : pLineData = ((unsigned char *) pData) + iScanline * nLineSpace;
275 :
276 0 : poODS->nCurrentIndex++;
277 0 : psResult = cln_GetNextObject( poODS->nClientID );
278 :
279 0 : if( ECSERROR(psResult) )
280 : {
281 : CPLError( CE_Failure, CPLE_AppDefined,
282 0 : "%s", psResult->message );
283 0 : return( CE_Failure );
284 : }
285 :
286 0 : if( eFamily == Matrix )
287 : {
288 : GDALCopyWords( ECSRASTER(psResult), GDT_UInt32, 4,
289 : pLineData, eBufType, nPixelSpace,
290 0 : nBufXSize );
291 : }
292 0 : else if( nOGDIImageType == 1 )
293 : {
294 : GDALCopyWords( ((GByte *) ECSRASTER(psResult)) + nComponent,
295 : GDT_Byte, 4,
296 0 : pLineData, eBufType, nPixelSpace, nBufXSize );
297 :
298 0 : if( nComponent == 3 )
299 : {
300 : int i;
301 :
302 0 : for( i = 0; i < nBufXSize; i++ )
303 : {
304 0 : if( ((GByte *) pLineData)[i] != 0 )
305 0 : ((GByte *) pLineData)[i] = 255;
306 : else
307 0 : ((GByte *) pLineData)[i] = 0;
308 :
309 : }
310 : }
311 : }
312 0 : else if( nOGDIImageType == 2 )
313 : {
314 : GDALCopyWords( ECSRASTER(psResult), GDT_Byte, 1,
315 : pLineData, eBufType, nPixelSpace,
316 0 : nBufXSize );
317 : }
318 0 : else if( nOGDIImageType == 3 )
319 : {
320 : GDALCopyWords( ECSRASTER(psResult), GDT_UInt16, 2,
321 : pLineData, eBufType, nPixelSpace,
322 0 : nBufXSize );
323 : }
324 0 : else if( nOGDIImageType == 4 )
325 : {
326 : GDALCopyWords( ECSRASTER(psResult), GDT_Int16, 2,
327 : pLineData, eBufType, nPixelSpace,
328 0 : nBufXSize );
329 : }
330 0 : else if( nOGDIImageType == 5 )
331 : {
332 : GDALCopyWords( ECSRASTER(psResult), GDT_Int32, 4,
333 : pLineData, eBufType, nPixelSpace,
334 0 : nBufXSize );
335 : }
336 : }
337 :
338 0 : return CE_None;
339 : }
340 :
341 : /************************************************************************/
342 : /* HasArbitraryOverviews() */
343 : /************************************************************************/
344 :
345 0 : int OGDIRasterBand::HasArbitraryOverviews()
346 :
347 : {
348 0 : return TRUE;
349 : }
350 :
351 : /************************************************************************/
352 : /* EstablishAccess() */
353 : /************************************************************************/
354 :
355 : CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
356 : int nWinXSize, int nWinYSize,
357 0 : int nBufXSize, int nBufYSize )
358 :
359 : {
360 : ecs_Result *psResult;
361 0 : OGDIDataset *poODS = (OGDIDataset *) poDS;
362 :
363 : /* -------------------------------------------------------------------- */
364 : /* Is this already the current band? If not, make it so now. */
365 : /* -------------------------------------------------------------------- */
366 0 : if( poODS->nCurrentBand != nBand )
367 : {
368 : ecs_LayerSelection sSelection;
369 :
370 0 : sSelection.Select = pszLayerName;
371 0 : sSelection.F = eFamily;
372 :
373 : CPLDebug( "OGDIRasterBand", "<EstablishAccess: SelectLayer(%s)>",
374 0 : pszLayerName );
375 0 : psResult = cln_SelectLayer( poODS->nClientID, &sSelection );
376 0 : if( ECSERROR(psResult) )
377 : {
378 : CPLError( CE_Failure, CPLE_AppDefined,
379 0 : "%s", psResult->message );
380 0 : return CE_Failure;
381 : }
382 :
383 0 : poODS->nCurrentBand = nBand;
384 0 : poODS->nCurrentIndex = -1;
385 : }
386 :
387 : /* -------------------------------------------------------------------- */
388 : /* What region would represent this resolution and window? */
389 : /* -------------------------------------------------------------------- */
390 : ecs_Region sWin;
391 0 : double dfNSTolerance = 0.0000001;
392 :
393 : sWin.west = nXOff * poODS->sGlobalBounds.ew_res
394 0 : + poODS->sGlobalBounds.west;
395 : sWin.east = (nXOff+nWinXSize) * poODS->sGlobalBounds.ew_res
396 0 : + poODS->sGlobalBounds.west;
397 0 : sWin.ew_res = poODS->sGlobalBounds.ew_res*(nWinXSize/(double)nBufXSize);
398 :
399 : sWin.north = poODS->sGlobalBounds.north
400 0 : - nYOff*poODS->sGlobalBounds.ns_res;
401 0 : if( nBufYSize == 1 && nWinYSize == 1 )
402 : {
403 : sWin.ns_res = sWin.ew_res
404 0 : * (poODS->sGlobalBounds.ns_res / poODS->sGlobalBounds.ew_res);
405 : nWinYSize = (int) ((sWin.north - poODS->sGlobalBounds.south + sWin.ns_res*0.9)
406 0 : / sWin.ns_res);
407 :
408 0 : sWin.south = sWin.north - nWinYSize * sWin.ns_res;
409 0 : dfNSTolerance = MAX(poODS->sCurrentBounds.ns_res,sWin.ns_res);
410 : }
411 0 : else if( nBufYSize == 1 )
412 : {
413 : sWin.ns_res = poODS->sGlobalBounds.ns_res
414 0 : *(nWinYSize/(double)nBufYSize);
415 : nWinYSize = (int) ((sWin.north - poODS->sGlobalBounds.south + sWin.ns_res*0.9)
416 0 : / sWin.ns_res);
417 :
418 0 : sWin.south = sWin.north - nWinYSize * sWin.ns_res;
419 0 : dfNSTolerance = MAX(poODS->sCurrentBounds.ns_res,sWin.ns_res);
420 : }
421 : else
422 : {
423 : sWin.ns_res = poODS->sGlobalBounds.ns_res
424 0 : *(nWinYSize/(double)nBufYSize);
425 0 : sWin.south = sWin.north - nWinYSize * sWin.ns_res;
426 0 : dfNSTolerance = sWin.ns_res * 0.001;
427 : }
428 :
429 0 : if( poODS->nCurrentIndex != 0
430 : || ABS(sWin.west - poODS->sCurrentBounds.west) > 0.0001
431 : || ABS(sWin.east - poODS->sCurrentBounds.east) > 0.0001
432 : || ABS(sWin.north - (poODS->sCurrentBounds.north - poODS->nCurrentIndex * poODS->sCurrentBounds.ns_res)) > dfNSTolerance
433 : || ABS(sWin.ew_res/poODS->sCurrentBounds.ew_res - 1.0) > 0.0001
434 : || ABS(sWin.ns_res - poODS->sCurrentBounds.ns_res) > dfNSTolerance )
435 : {
436 : CPLDebug( "OGDIRasterBand",
437 : "<EstablishAccess: Set Region(%d,%d,%d,%d,%d,%d>",
438 0 : nXOff, nYOff, nWinXSize, nWinYSize, nBufXSize, nBufYSize );
439 :
440 0 : psResult = cln_SelectRegion( poODS->nClientID, &sWin );
441 0 : if( ECSERROR(psResult) )
442 : {
443 : CPLError( CE_Failure, CPLE_AppDefined,
444 0 : "%s", psResult->message );
445 0 : return CE_Failure;
446 : }
447 :
448 0 : poODS->sCurrentBounds = sWin;
449 0 : poODS->nCurrentIndex = 0;
450 : }
451 :
452 0 : return CE_None;
453 : }
454 :
455 : /************************************************************************/
456 : /* GetColorInterpretation() */
457 : /************************************************************************/
458 :
459 0 : GDALColorInterp OGDIRasterBand::GetColorInterpretation()
460 :
461 : {
462 0 : if( poCT != NULL )
463 0 : return GCI_PaletteIndex;
464 0 : else if( nOGDIImageType == 1 && eFamily == Image && nComponent == 0 )
465 0 : return GCI_RedBand;
466 0 : else if( nOGDIImageType == 1 && eFamily == Image && nComponent == 1 )
467 0 : return GCI_GreenBand;
468 0 : else if( nOGDIImageType == 1 && eFamily == Image && nComponent == 2 )
469 0 : return GCI_BlueBand;
470 0 : else if( nOGDIImageType == 1 && eFamily == Image && nComponent == 3 )
471 0 : return GCI_AlphaBand;
472 : else
473 0 : return GCI_Undefined;
474 : }
475 :
476 : /************************************************************************/
477 : /* GetColorTable() */
478 : /************************************************************************/
479 :
480 0 : GDALColorTable *OGDIRasterBand::GetColorTable()
481 :
482 : {
483 0 : return poCT;
484 : }
485 :
486 : /************************************************************************/
487 : /* AdviseRead() */
488 : /* */
489 : /* Allow the application to give us a hint in advance how they */
490 : /* want the data. */
491 : /************************************************************************/
492 :
493 : CPLErr OGDIRasterBand::AdviseRead( int nXOff, int nYOff,
494 : int nXSize, int nYSize,
495 : int nBufXSize, int nBufYSize,
496 0 : GDALDataType eDT, char **papszOptions )
497 :
498 : {
499 : return EstablishAccess( nXOff, nYOff, nXSize, nYSize,
500 0 : nBufXSize, nBufYSize );
501 : }
502 :
503 : /************************************************************************/
504 : /* ==================================================================== */
505 : /* OGDIDataset */
506 : /* ==================================================================== */
507 : /************************************************************************/
508 :
509 :
510 : /************************************************************************/
511 : /* OGDIDataset() */
512 : /************************************************************************/
513 :
514 0 : OGDIDataset::OGDIDataset()
515 :
516 : {
517 0 : nClientID = -1;
518 0 : nCurrentBand = -1;
519 0 : nCurrentIndex = -1;
520 0 : papszSubDatasets = NULL;
521 0 : }
522 :
523 : /************************************************************************/
524 : /* ~OGDIDataset() */
525 : /************************************************************************/
526 :
527 0 : OGDIDataset::~OGDIDataset()
528 :
529 : {
530 0 : cln_DestroyClient( nClientID );
531 0 : CSLDestroy( papszSubDatasets );
532 0 : CPLFree( pszProjection );
533 0 : }
534 :
535 : /************************************************************************/
536 : /* GetMetadata() */
537 : /************************************************************************/
538 :
539 0 : char **OGDIDataset::GetMetadata( const char *pszDomain )
540 :
541 : {
542 0 : if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
543 0 : return papszSubDatasets;
544 : else
545 0 : return GDALDataset::GetMetadata( pszDomain );
546 : }
547 :
548 : /************************************************************************/
549 : /* Open() */
550 : /************************************************************************/
551 :
552 11272 : GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
553 :
554 : {
555 : ecs_Result *psResult;
556 : int nClientID;
557 11272 : char **papszImages=NULL, **papszMatrices=NULL;
558 :
559 11272 : if( !EQUALN(poOpenInfo->pszFilename,"gltp:",5) )
560 11272 : return( NULL );
561 :
562 : /* -------------------------------------------------------------------- */
563 : /* Confirm the requested access is supported. */
564 : /* -------------------------------------------------------------------- */
565 0 : if( poOpenInfo->eAccess == GA_Update )
566 : {
567 : CPLError( CE_Failure, CPLE_NotSupported,
568 : "The OGDI driver does not support update access to existing"
569 0 : " datasets.\n" );
570 0 : return NULL;
571 : }
572 :
573 : /* -------------------------------------------------------------------- */
574 : /* Has the user hardcoded a layer and family in the URL? */
575 : /* Honour quoted strings for the layer name, since some layers */
576 : /* (ie. RPF/CADRG) have embedded colons. */
577 : /* -------------------------------------------------------------------- */
578 0 : int nC1=-1, nC2=-1, i, bInQuotes = FALSE;
579 0 : char *pszURL = CPLStrdup(poOpenInfo->pszFilename);
580 :
581 0 : for( i = strlen(pszURL)-1; i > 0; i-- )
582 : {
583 0 : if( pszURL[i] == '/' )
584 0 : break;
585 :
586 0 : if( pszURL[i] == '"' && pszURL[i-1] != '\\' )
587 0 : bInQuotes = !bInQuotes;
588 :
589 0 : else if( pszURL[i] == ':' && !bInQuotes )
590 : {
591 0 : if( nC1 == -1 )
592 : {
593 0 : nC1 = i;
594 0 : pszURL[nC1] = '\0';
595 : }
596 0 : else if( nC2 == -1 )
597 : {
598 0 : nC2 = i;
599 0 : pszURL[nC2] = '\0';
600 : }
601 : }
602 : }
603 :
604 : /* -------------------------------------------------------------------- */
605 : /* If we got a "family", and it is a vector family then return */
606 : /* quietly. */
607 : /* -------------------------------------------------------------------- */
608 0 : if( nC2 != -1
609 : && !EQUAL(pszURL+nC1+1,"Matrix")
610 : && !EQUAL(pszURL+nC1+1,"Image") )
611 : {
612 0 : CPLFree( pszURL );
613 0 : return NULL;
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Open the client interface. */
618 : /* -------------------------------------------------------------------- */
619 0 : psResult = cln_CreateClient( &nClientID, pszURL );
620 :
621 0 : if( ECSERROR(psResult) )
622 : {
623 : CPLError( CE_Failure, CPLE_AppDefined,
624 0 : "%s", psResult->message );
625 0 : return NULL;
626 : }
627 :
628 : /* -------------------------------------------------------------------- */
629 : /* collect the list of images and matrices available. */
630 : /* -------------------------------------------------------------------- */
631 0 : if( nC2 == -1 )
632 : {
633 0 : CollectLayers( nClientID, &papszImages, &papszMatrices );
634 : }
635 : else
636 : {
637 0 : char *pszLayerName = CPLStrdup( pszURL+nC2+1 );
638 :
639 0 : if( pszLayerName[0] == '"' )
640 : {
641 0 : int nOut = 0;
642 :
643 0 : for( i = 1; pszLayerName[i] != '\0'; i++ )
644 : {
645 0 : if( pszLayerName[i+1] == '"' && pszLayerName[i] == '\\' )
646 0 : pszLayerName[nOut++] = pszLayerName[++i];
647 0 : else if( pszLayerName[i] != '"' )
648 0 : pszLayerName[nOut++] = pszLayerName[i];
649 : else
650 0 : break;
651 : }
652 0 : pszLayerName[nOut] = '\0';
653 : }
654 :
655 0 : if( EQUAL(pszURL+nC1+1,"Image") )
656 0 : papszImages = CSLAddString( papszImages, pszLayerName );
657 : else
658 0 : papszMatrices = CSLAddString( papszMatrices, pszLayerName );
659 :
660 0 : CPLFree( pszLayerName );
661 : }
662 :
663 0 : CPLFree( pszURL );
664 :
665 : /* -------------------------------------------------------------------- */
666 : /* If this is a 3.1 server (ie, it support */
667 : /* cln_GetLayerCapabilities()) and it has no raster layers then */
668 : /* we can assume it must be a vector datastore. End without an */
669 : /* error in case the application wants to try this through */
670 : /* OGR. */
671 : /* -------------------------------------------------------------------- */
672 0 : psResult = cln_GetVersion(nClientID);
673 :
674 0 : if( (ECSERROR(psResult) || atof(ECSTEXT(psResult)) >= 3.1)
675 : && CSLCount(papszMatrices) == 0
676 : && CSLCount(papszImages) == 0 )
677 : {
678 : CPLDebug( "OGDIDataset",
679 : "While this is an OGDI datastore, it does not appear to\n"
680 : "have any identifiable raster layers. Perhaps it is a\n"
681 0 : "vector datastore?" );
682 0 : cln_DestroyClient( nClientID );
683 0 : return NULL;
684 : }
685 :
686 : /* -------------------------------------------------------------------- */
687 : /* Create a corresponding GDALDataset. */
688 : /* -------------------------------------------------------------------- */
689 : OGDIDataset *poDS;
690 :
691 0 : poDS = new OGDIDataset();
692 :
693 0 : poDS->nClientID = nClientID;
694 0 : poDS->SetDescription( poOpenInfo->pszFilename );
695 :
696 : /* -------------------------------------------------------------------- */
697 : /* Capture some information from the file that is of interest. */
698 : /* -------------------------------------------------------------------- */
699 0 : psResult = cln_GetGlobalBound( nClientID );
700 0 : if( ECSERROR(psResult) )
701 : {
702 : CPLError( CE_Failure, CPLE_AppDefined,
703 0 : "%s", psResult->message );
704 0 : return NULL;
705 : }
706 :
707 0 : poDS->sGlobalBounds = ECSREGION(psResult);
708 :
709 0 : psResult = cln_GetServerProjection(nClientID);
710 0 : if( ECSERROR(psResult) )
711 : {
712 : CPLError( CE_Failure, CPLE_AppDefined,
713 0 : "%s", psResult->message );
714 0 : return NULL;
715 : }
716 :
717 0 : OGRSpatialReference oSRS;
718 :
719 0 : if( oSRS.importFromProj4( ECSTEXT(psResult) ) == OGRERR_NONE )
720 : {
721 0 : poDS->pszProjection = NULL;
722 0 : oSRS.exportToWkt( &(poDS->pszProjection) );
723 : }
724 : else
725 : {
726 : CPLError( CE_Warning, CPLE_NotSupported,
727 : "untranslatable PROJ.4 projection: %s\n",
728 0 : ECSTEXT(psResult) );
729 0 : poDS->pszProjection = CPLStrdup("");
730 : }
731 :
732 : /* -------------------------------------------------------------------- */
733 : /* Select the global region. */
734 : /* -------------------------------------------------------------------- */
735 0 : psResult = cln_SelectRegion( nClientID, &(poDS->sGlobalBounds) );
736 0 : if( ECSERROR(psResult) )
737 : {
738 : CPLError( CE_Failure, CPLE_AppDefined,
739 0 : "%s", psResult->message );
740 0 : return NULL;
741 : }
742 :
743 0 : poDS->sCurrentBounds = poDS->sGlobalBounds;
744 :
745 : /* -------------------------------------------------------------------- */
746 : /* If we have only one layer try to find the corresponding */
747 : /* capabilities, and override the global bounds and resolution */
748 : /* based on it. */
749 : /* -------------------------------------------------------------------- */
750 0 : if( CSLCount(papszMatrices) + CSLCount(papszImages) == 1 )
751 : {
752 0 : if( CSLCount(papszMatrices) == 1 )
753 0 : OverrideGlobalInfo( poDS, papszMatrices[0] );
754 : else
755 0 : OverrideGlobalInfo( poDS, papszImages[0] );
756 : }
757 :
758 : /* -------------------------------------------------------------------- */
759 : /* Otherwise setup a subdataset list. */
760 : /* -------------------------------------------------------------------- */
761 : else
762 : {
763 : int i;
764 :
765 0 : for( i = 0; papszMatrices != NULL && papszMatrices[i] != NULL; i++ )
766 0 : poDS->AddSubDataset( "Matrix", papszMatrices[i] );
767 :
768 0 : for( i = 0; papszImages != NULL && papszImages[i] != NULL; i++ )
769 0 : poDS->AddSubDataset( "Image", papszImages[i] );
770 : }
771 :
772 : /* -------------------------------------------------------------------- */
773 : /* Establish raster info. */
774 : /* -------------------------------------------------------------------- */
775 : poDS->nRasterXSize = (int)
776 : (((poDS->sGlobalBounds.east - poDS->sGlobalBounds.west)
777 0 : / poDS->sGlobalBounds.ew_res) + 0.5);
778 :
779 : poDS->nRasterYSize = (int)
780 : (((poDS->sGlobalBounds.north - poDS->sGlobalBounds.south)
781 0 : / poDS->sGlobalBounds.ns_res) + 0.5);
782 :
783 : /* -------------------------------------------------------------------- */
784 : /* Create band information objects. */
785 : /* -------------------------------------------------------------------- */
786 0 : for( i=0; papszMatrices != NULL && papszMatrices[i] != NULL; i++)
787 : {
788 0 : if( CSLFindString( papszImages, papszMatrices[i] ) == -1 )
789 : poDS->SetBand( poDS->GetRasterCount()+1,
790 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
791 0 : papszMatrices[i], Matrix, 0 ) );
792 : }
793 :
794 0 : for( i=0; papszImages != NULL && papszImages[i] != NULL; i++)
795 : {
796 : OGDIRasterBand *poBand;
797 :
798 : poBand = new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
799 0 : papszImages[i], Image, 0 );
800 :
801 0 : poDS->SetBand( poDS->GetRasterCount()+1, poBand );
802 :
803 : /* special case for RGBt Layers */
804 0 : if( poBand->nOGDIImageType == 1 )
805 : {
806 : poDS->SetBand( poDS->GetRasterCount()+1,
807 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
808 0 : papszImages[i], Image, 1 ));
809 : poDS->SetBand( poDS->GetRasterCount()+1,
810 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
811 0 : papszImages[i], Image, 2 ));
812 : poDS->SetBand( poDS->GetRasterCount()+1,
813 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
814 0 : papszImages[i], Image, 3 ));
815 : }
816 : }
817 :
818 0 : CSLDestroy( papszMatrices );
819 0 : CSLDestroy( papszImages );
820 :
821 0 : return( poDS );
822 : }
823 :
824 : /************************************************************************/
825 : /* AddSubDataset() */
826 : /************************************************************************/
827 :
828 0 : void OGDIDataset::AddSubDataset( const char *pszType, const char *pszLayer )
829 :
830 : {
831 : char szName[80];
832 0 : int nCount = CSLCount( papszSubDatasets ) / 2;
833 :
834 0 : sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
835 : papszSubDatasets =
836 : CSLSetNameValue( papszSubDatasets, szName,
837 0 : CPLSPrintf( "%s:\"%s\":%s", GetDescription(), pszLayer, pszType ) );
838 :
839 0 : sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
840 : papszSubDatasets =
841 : CSLSetNameValue( papszSubDatasets, szName,
842 0 : CPLSPrintf( "%s as %s", pszLayer, pszType ) );
843 0 : }
844 :
845 : /************************************************************************/
846 : /* CollectLayers() */
847 : /************************************************************************/
848 :
849 : CPLErr OGDIDataset::CollectLayers( int nClientID,
850 : char ***ppapszImages,
851 0 : char ***ppapszMatrices )
852 :
853 : {
854 : const ecs_LayerCapabilities *psLayer;
855 : int iLayer;
856 :
857 0 : for( iLayer = 0;
858 : (psLayer = cln_GetLayerCapabilities(nClientID,iLayer)) != NULL;
859 : iLayer++ )
860 : {
861 0 : if( psLayer->families[Image] )
862 : {
863 0 : *ppapszImages = CSLAddString( *ppapszImages, psLayer->name );
864 : }
865 0 : if( psLayer->families[Matrix] )
866 : {
867 0 : *ppapszMatrices = CSLAddString( *ppapszMatrices, psLayer->name );
868 : }
869 : }
870 :
871 0 : return CE_None;
872 : }
873 :
874 : /************************************************************************/
875 : /* OverrideGlobalInfo() */
876 : /* */
877 : /* Override the global bounds and resolution based on a layers */
878 : /* capabilities, if possible. */
879 : /************************************************************************/
880 :
881 : CPLErr OGDIDataset::OverrideGlobalInfo( OGDIDataset *poDS,
882 0 : const char *pszLayer )
883 :
884 : {
885 : const ecs_LayerCapabilities *psLayer;
886 : int iLayer;
887 :
888 0 : for( iLayer = 0;
889 : (psLayer = cln_GetLayerCapabilities(poDS->nClientID,iLayer)) != NULL;
890 : iLayer++ )
891 : {
892 0 : if( EQUAL(psLayer->name, pszLayer) )
893 : {
894 0 : poDS->sGlobalBounds.north = psLayer->srs_north;
895 0 : poDS->sGlobalBounds.south = psLayer->srs_south;
896 0 : poDS->sGlobalBounds.east = psLayer->srs_east;
897 0 : poDS->sGlobalBounds.west = psLayer->srs_west;
898 0 : poDS->sGlobalBounds.ew_res = psLayer->srs_ewres;
899 0 : poDS->sGlobalBounds.ns_res = psLayer->srs_nsres;
900 : }
901 : }
902 :
903 0 : return CE_None;
904 : }
905 :
906 : /************************************************************************/
907 : /* GetProjectionRef() */
908 : /************************************************************************/
909 :
910 0 : const char *OGDIDataset::GetProjectionRef()
911 :
912 : {
913 0 : return( pszProjection );
914 : }
915 :
916 : /************************************************************************/
917 : /* GetGeoTransform() */
918 : /************************************************************************/
919 :
920 0 : CPLErr OGDIDataset::GetGeoTransform( double * padfTransform )
921 :
922 : {
923 0 : padfTransform[0] = sGlobalBounds.west;
924 0 : padfTransform[1] = sGlobalBounds.ew_res;
925 0 : padfTransform[2] = 0.0;
926 :
927 0 : padfTransform[3] = sGlobalBounds.north;
928 0 : padfTransform[4] = 0.0;
929 0 : padfTransform[5] = -sGlobalBounds.ns_res;
930 :
931 0 : return( CE_None );
932 : }
933 :
934 : /************************************************************************/
935 : /* GetInternalHandle() */
936 : /************************************************************************/
937 :
938 0 : void *OGDIDataset::GetInternalHandle( const char * pszRequest )
939 :
940 : {
941 0 : if( EQUAL(pszRequest,"ClientID") )
942 0 : return (void *) nClientID;
943 : else
944 0 : return NULL;
945 : }
946 :
947 : /************************************************************************/
948 : /* GDALRegister_OGDI() */
949 : /************************************************************************/
950 :
951 409 : void GDALRegister_OGDI()
952 :
953 : {
954 : GDALDriver *poDriver;
955 :
956 409 : if (! GDAL_CHECK_VERSION("GDAL/OGDI driver"))
957 0 : return;
958 :
959 409 : if( GDALGetDriverByName( "OGDI" ) == NULL )
960 : {
961 392 : poDriver = new GDALDriver();
962 :
963 392 : poDriver->SetDescription( "OGDI" );
964 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
965 392 : "OGDI Bridge" );
966 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
967 392 : "frmt_ogdi.html" );
968 :
969 392 : poDriver->pfnOpen = OGDIDataset::Open;
970 :
971 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
972 : }
973 : }
974 :
|