1 : /******************************************************************************
2 : * $Id: ogdidataset.cpp 20588 2010-09-12 16:29:21Z 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 20588 2010-09-12 16:29:21Z 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 0 : 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 0 : 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 0 : 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 : 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 0 : CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
356 : int nWinXSize, int nWinYSize,
357 : 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 0 : CPLErr OGDIRasterBand::AdviseRead( int nXOff, int nYOff,
494 : int nXSize, int nYSize,
495 : int nBufXSize, int nBufYSize,
496 : 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 26664 : GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
553 :
554 : {
555 : ecs_Result *psResult;
556 : int nClientID;
557 26664 : char **papszImages=NULL, **papszMatrices=NULL;
558 :
559 26664 : if( !EQUALN(poOpenInfo->pszFilename,"gltp:",5) )
560 26664 : 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 : CPLFree(pszURL);
626 0 : return NULL;
627 : }
628 :
629 : /* -------------------------------------------------------------------- */
630 : /* collect the list of images and matrices available. */
631 : /* -------------------------------------------------------------------- */
632 0 : if( nC2 == -1 )
633 : {
634 0 : CollectLayers( nClientID, &papszImages, &papszMatrices );
635 : }
636 : else
637 : {
638 0 : char *pszLayerName = CPLStrdup( pszURL+nC2+1 );
639 :
640 0 : if( pszLayerName[0] == '"' )
641 : {
642 0 : int nOut = 0;
643 :
644 0 : for( i = 1; pszLayerName[i] != '\0'; i++ )
645 : {
646 0 : if( pszLayerName[i+1] == '"' && pszLayerName[i] == '\\' )
647 0 : pszLayerName[nOut++] = pszLayerName[++i];
648 0 : else if( pszLayerName[i] != '"' )
649 0 : pszLayerName[nOut++] = pszLayerName[i];
650 : else
651 0 : break;
652 : }
653 0 : pszLayerName[nOut] = '\0';
654 : }
655 :
656 0 : if( EQUAL(pszURL+nC1+1,"Image") )
657 0 : papszImages = CSLAddString( papszImages, pszLayerName );
658 : else
659 0 : papszMatrices = CSLAddString( papszMatrices, pszLayerName );
660 :
661 0 : CPLFree( pszLayerName );
662 : }
663 :
664 0 : CPLFree( pszURL );
665 :
666 : /* -------------------------------------------------------------------- */
667 : /* If this is a 3.1 server (ie, it support */
668 : /* cln_GetLayerCapabilities()) and it has no raster layers then */
669 : /* we can assume it must be a vector datastore. End without an */
670 : /* error in case the application wants to try this through */
671 : /* OGR. */
672 : /* -------------------------------------------------------------------- */
673 0 : psResult = cln_GetVersion(nClientID);
674 :
675 0 : if( (ECSERROR(psResult) || atof(ECSTEXT(psResult)) >= 3.1)
676 : && CSLCount(papszMatrices) == 0
677 : && CSLCount(papszImages) == 0 )
678 : {
679 : CPLDebug( "OGDIDataset",
680 : "While this is an OGDI datastore, it does not appear to\n"
681 : "have any identifiable raster layers. Perhaps it is a\n"
682 0 : "vector datastore?" );
683 0 : cln_DestroyClient( nClientID );
684 0 : return NULL;
685 : }
686 :
687 : /* -------------------------------------------------------------------- */
688 : /* Create a corresponding GDALDataset. */
689 : /* -------------------------------------------------------------------- */
690 : OGDIDataset *poDS;
691 :
692 0 : poDS = new OGDIDataset();
693 :
694 0 : poDS->nClientID = nClientID;
695 0 : poDS->SetDescription( poOpenInfo->pszFilename );
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* Capture some information from the file that is of interest. */
699 : /* -------------------------------------------------------------------- */
700 0 : psResult = cln_GetGlobalBound( nClientID );
701 0 : if( ECSERROR(psResult) )
702 : {
703 : CPLError( CE_Failure, CPLE_AppDefined,
704 0 : "%s", psResult->message );
705 0 : return NULL;
706 : }
707 :
708 0 : poDS->sGlobalBounds = ECSREGION(psResult);
709 :
710 0 : psResult = cln_GetServerProjection(nClientID);
711 0 : if( ECSERROR(psResult) )
712 : {
713 : CPLError( CE_Failure, CPLE_AppDefined,
714 0 : "%s", psResult->message );
715 0 : return NULL;
716 : }
717 :
718 0 : OGRSpatialReference oSRS;
719 :
720 0 : if( oSRS.importFromProj4( ECSTEXT(psResult) ) == OGRERR_NONE )
721 : {
722 0 : poDS->pszProjection = NULL;
723 0 : oSRS.exportToWkt( &(poDS->pszProjection) );
724 : }
725 : else
726 : {
727 : CPLError( CE_Warning, CPLE_NotSupported,
728 : "untranslatable PROJ.4 projection: %s\n",
729 0 : ECSTEXT(psResult) );
730 0 : poDS->pszProjection = CPLStrdup("");
731 : }
732 :
733 : /* -------------------------------------------------------------------- */
734 : /* Select the global region. */
735 : /* -------------------------------------------------------------------- */
736 0 : psResult = cln_SelectRegion( nClientID, &(poDS->sGlobalBounds) );
737 0 : if( ECSERROR(psResult) )
738 : {
739 : CPLError( CE_Failure, CPLE_AppDefined,
740 0 : "%s", psResult->message );
741 0 : return NULL;
742 : }
743 :
744 0 : poDS->sCurrentBounds = poDS->sGlobalBounds;
745 :
746 : /* -------------------------------------------------------------------- */
747 : /* If we have only one layer try to find the corresponding */
748 : /* capabilities, and override the global bounds and resolution */
749 : /* based on it. */
750 : /* -------------------------------------------------------------------- */
751 0 : if( CSLCount(papszMatrices) + CSLCount(papszImages) == 1 )
752 : {
753 0 : if( CSLCount(papszMatrices) == 1 )
754 0 : OverrideGlobalInfo( poDS, papszMatrices[0] );
755 : else
756 0 : OverrideGlobalInfo( poDS, papszImages[0] );
757 : }
758 :
759 : /* -------------------------------------------------------------------- */
760 : /* Otherwise setup a subdataset list. */
761 : /* -------------------------------------------------------------------- */
762 : else
763 : {
764 : int i;
765 :
766 0 : for( i = 0; papszMatrices != NULL && papszMatrices[i] != NULL; i++ )
767 0 : poDS->AddSubDataset( "Matrix", papszMatrices[i] );
768 :
769 0 : for( i = 0; papszImages != NULL && papszImages[i] != NULL; i++ )
770 0 : poDS->AddSubDataset( "Image", papszImages[i] );
771 : }
772 :
773 : /* -------------------------------------------------------------------- */
774 : /* Establish raster info. */
775 : /* -------------------------------------------------------------------- */
776 : poDS->nRasterXSize = (int)
777 : (((poDS->sGlobalBounds.east - poDS->sGlobalBounds.west)
778 0 : / poDS->sGlobalBounds.ew_res) + 0.5);
779 :
780 : poDS->nRasterYSize = (int)
781 : (((poDS->sGlobalBounds.north - poDS->sGlobalBounds.south)
782 0 : / poDS->sGlobalBounds.ns_res) + 0.5);
783 :
784 : /* -------------------------------------------------------------------- */
785 : /* Create band information objects. */
786 : /* -------------------------------------------------------------------- */
787 0 : for( i=0; papszMatrices != NULL && papszMatrices[i] != NULL; i++)
788 : {
789 0 : if( CSLFindString( papszImages, papszMatrices[i] ) == -1 )
790 : poDS->SetBand( poDS->GetRasterCount()+1,
791 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
792 0 : papszMatrices[i], Matrix, 0 ) );
793 : }
794 :
795 0 : for( i=0; papszImages != NULL && papszImages[i] != NULL; i++)
796 : {
797 : OGDIRasterBand *poBand;
798 :
799 : poBand = new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
800 0 : papszImages[i], Image, 0 );
801 :
802 0 : poDS->SetBand( poDS->GetRasterCount()+1, poBand );
803 :
804 : /* special case for RGBt Layers */
805 0 : if( poBand->nOGDIImageType == 1 )
806 : {
807 : poDS->SetBand( poDS->GetRasterCount()+1,
808 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
809 0 : papszImages[i], Image, 1 ));
810 : poDS->SetBand( poDS->GetRasterCount()+1,
811 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
812 0 : papszImages[i], Image, 2 ));
813 : poDS->SetBand( poDS->GetRasterCount()+1,
814 : new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
815 0 : papszImages[i], Image, 3 ));
816 : }
817 : }
818 :
819 0 : CSLDestroy( papszMatrices );
820 0 : CSLDestroy( papszImages );
821 :
822 0 : return( poDS );
823 : }
824 :
825 : /************************************************************************/
826 : /* AddSubDataset() */
827 : /************************************************************************/
828 :
829 0 : void OGDIDataset::AddSubDataset( const char *pszType, const char *pszLayer )
830 :
831 : {
832 : char szName[80];
833 0 : int nCount = CSLCount( papszSubDatasets ) / 2;
834 :
835 0 : sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
836 : papszSubDatasets =
837 : CSLSetNameValue( papszSubDatasets, szName,
838 0 : CPLSPrintf( "%s:\"%s\":%s", GetDescription(), pszLayer, pszType ) );
839 :
840 0 : sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
841 : papszSubDatasets =
842 : CSLSetNameValue( papszSubDatasets, szName,
843 0 : CPLSPrintf( "%s as %s", pszLayer, pszType ) );
844 0 : }
845 :
846 : /************************************************************************/
847 : /* CollectLayers() */
848 : /************************************************************************/
849 :
850 0 : CPLErr OGDIDataset::CollectLayers( int nClientID,
851 : char ***ppapszImages,
852 : char ***ppapszMatrices )
853 :
854 : {
855 : const ecs_LayerCapabilities *psLayer;
856 : int iLayer;
857 :
858 0 : for( iLayer = 0;
859 : (psLayer = cln_GetLayerCapabilities(nClientID,iLayer)) != NULL;
860 : iLayer++ )
861 : {
862 0 : if( psLayer->families[Image] )
863 : {
864 0 : *ppapszImages = CSLAddString( *ppapszImages, psLayer->name );
865 : }
866 0 : if( psLayer->families[Matrix] )
867 : {
868 0 : *ppapszMatrices = CSLAddString( *ppapszMatrices, psLayer->name );
869 : }
870 : }
871 :
872 0 : return CE_None;
873 : }
874 :
875 : /************************************************************************/
876 : /* OverrideGlobalInfo() */
877 : /* */
878 : /* Override the global bounds and resolution based on a layers */
879 : /* capabilities, if possible. */
880 : /************************************************************************/
881 :
882 0 : CPLErr OGDIDataset::OverrideGlobalInfo( OGDIDataset *poDS,
883 : const char *pszLayer )
884 :
885 : {
886 : const ecs_LayerCapabilities *psLayer;
887 : int iLayer;
888 :
889 0 : for( iLayer = 0;
890 : (psLayer = cln_GetLayerCapabilities(poDS->nClientID,iLayer)) != NULL;
891 : iLayer++ )
892 : {
893 0 : if( EQUAL(psLayer->name, pszLayer) )
894 : {
895 0 : poDS->sGlobalBounds.north = psLayer->srs_north;
896 0 : poDS->sGlobalBounds.south = psLayer->srs_south;
897 0 : poDS->sGlobalBounds.east = psLayer->srs_east;
898 0 : poDS->sGlobalBounds.west = psLayer->srs_west;
899 0 : poDS->sGlobalBounds.ew_res = psLayer->srs_ewres;
900 0 : poDS->sGlobalBounds.ns_res = psLayer->srs_nsres;
901 : }
902 : }
903 :
904 0 : return CE_None;
905 : }
906 :
907 : /************************************************************************/
908 : /* GetProjectionRef() */
909 : /************************************************************************/
910 :
911 0 : const char *OGDIDataset::GetProjectionRef()
912 :
913 : {
914 0 : return( pszProjection );
915 : }
916 :
917 : /************************************************************************/
918 : /* GetGeoTransform() */
919 : /************************************************************************/
920 :
921 0 : CPLErr OGDIDataset::GetGeoTransform( double * padfTransform )
922 :
923 : {
924 0 : padfTransform[0] = sGlobalBounds.west;
925 0 : padfTransform[1] = sGlobalBounds.ew_res;
926 0 : padfTransform[2] = 0.0;
927 :
928 0 : padfTransform[3] = sGlobalBounds.north;
929 0 : padfTransform[4] = 0.0;
930 0 : padfTransform[5] = -sGlobalBounds.ns_res;
931 :
932 0 : return( CE_None );
933 : }
934 :
935 : /************************************************************************/
936 : /* GetInternalHandle() */
937 : /************************************************************************/
938 :
939 0 : void *OGDIDataset::GetInternalHandle( const char * pszRequest )
940 :
941 : {
942 0 : if( EQUAL(pszRequest,"ClientID") )
943 0 : return (void *) nClientID;
944 : else
945 0 : return NULL;
946 : }
947 :
948 : /************************************************************************/
949 : /* GDALRegister_OGDI() */
950 : /************************************************************************/
951 :
952 1135 : void GDALRegister_OGDI()
953 :
954 : {
955 : GDALDriver *poDriver;
956 :
957 1135 : if (! GDAL_CHECK_VERSION("GDAL/OGDI driver"))
958 0 : return;
959 :
960 1135 : if( GDALGetDriverByName( "OGDI" ) == NULL )
961 : {
962 1093 : poDriver = new GDALDriver();
963 :
964 1093 : poDriver->SetDescription( "OGDI" );
965 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
966 1093 : "OGDI Bridge" );
967 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
968 1093 : "frmt_ogdi.html" );
969 :
970 1093 : poDriver->pfnOpen = OGDIDataset::Open;
971 :
972 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
973 : }
974 : }
975 :
|