1 : /******************************************************************************
2 : * $Id: dted_ptstream.c 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: DTED Translator
5 : * Purpose: DTED Point Stream Writer.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "dted_api.h"
31 :
32 : CPL_CVSID("$Id: dted_ptstream.c 10645 2007-01-18 02:22:39Z warmerdam $");
33 :
34 : typedef struct {
35 : char *pszFilename;
36 : DTEDInfo *psInfo;
37 :
38 : GInt16 **papanProfiles;
39 :
40 : int nLLLong;
41 : int nLLLat;
42 : } DTEDCachedFile;
43 :
44 : typedef struct {
45 : int nLevel;
46 : char *pszPath;
47 :
48 : double dfPixelSize;
49 :
50 : int nOpenFiles;
51 : DTEDCachedFile *pasCF;
52 :
53 : int nLastFile;
54 :
55 : char *apszMetadata[DTEDMD_MAX+1];
56 : } DTEDPtStream;
57 :
58 : /************************************************************************/
59 : /* DTEDCreatePtStream() */
60 : /************************************************************************/
61 :
62 0 : void *DTEDCreatePtStream( const char *pszPath, int nLevel )
63 :
64 : {
65 : DTEDPtStream *psStream;
66 : int i;
67 : VSIStatBuf sStat;
68 :
69 : /* -------------------------------------------------------------------- */
70 : /* Does the target directory already exist? If not try to */
71 : /* create it. */
72 : /* -------------------------------------------------------------------- */
73 0 : if( CPLStat( pszPath, &sStat ) != 0 )
74 : {
75 0 : if( VSIMkdir( pszPath, 0755 ) != 0 )
76 : {
77 : #ifndef AVOID_CPL
78 0 : CPLError( CE_Failure, CPLE_OpenFailed,
79 : "Unable to find, or create directory `%s'.",
80 : pszPath );
81 : #endif
82 0 : return NULL;
83 : }
84 : }
85 :
86 : /* -------------------------------------------------------------------- */
87 : /* Create the stream and initialize it. */
88 : /* -------------------------------------------------------------------- */
89 :
90 0 : psStream = (DTEDPtStream *) CPLCalloc( sizeof(DTEDPtStream), 1 );
91 0 : psStream->nLevel = nLevel;
92 0 : psStream->pszPath = CPLStrdup( pszPath );
93 0 : psStream->nOpenFiles = 0;
94 0 : psStream->pasCF = NULL;
95 0 : psStream->nLastFile = -1;
96 :
97 0 : for( i = 0; i < DTEDMD_MAX+1; i++ )
98 0 : psStream->apszMetadata[i] = NULL;
99 :
100 0 : if( nLevel == 0 )
101 0 : psStream->dfPixelSize = 1.0 / 120.0;
102 0 : else if( nLevel == 1 )
103 0 : psStream->dfPixelSize = 1.0 / 1200.0;
104 0 : else if( nLevel == 2 )
105 0 : psStream->dfPixelSize = 1.0 / 3600.0;
106 : else
107 0 : psStream->dfPixelSize = 1.0 / 3600.0;
108 :
109 0 : return (void *) psStream;
110 : }
111 :
112 : /************************************************************************/
113 : /* DTEDPtStreamNewTile() */
114 : /* */
115 : /* Create a new DTED file file, add it to our list, and make it */
116 : /* "current". */
117 : /************************************************************************/
118 :
119 0 : static int DTEDPtStreamNewTile( DTEDPtStream *psStream,
120 : int nCrLong, int nCrLat )
121 :
122 : {
123 : DTEDInfo *psInfo;
124 : char szFile[128];
125 : char chNSHemi, chEWHemi;
126 : char *pszFullFilename;
127 : const char *pszError;
128 :
129 : /* work out filename */
130 0 : if( nCrLat < 0 )
131 0 : chNSHemi = 's';
132 : else
133 0 : chNSHemi = 'n';
134 :
135 0 : if( nCrLong < 0 )
136 0 : chEWHemi = 'w';
137 : else
138 0 : chEWHemi = 'e';
139 :
140 0 : sprintf( szFile, "%c%03d%c%03d.dt%d",
141 : chEWHemi, ABS(nCrLong), chNSHemi, ABS(nCrLat),
142 : psStream->nLevel );
143 :
144 0 : pszFullFilename =
145 0 : CPLStrdup(CPLFormFilename( psStream->pszPath, szFile, NULL ));
146 :
147 : /* create the dted file */
148 0 : pszError = DTEDCreate( pszFullFilename, psStream->nLevel,
149 : nCrLat, nCrLong );
150 0 : if( pszError != NULL )
151 : {
152 : #ifndef AVOID_CPL
153 0 : CPLError( CE_Failure, CPLE_OpenFailed,
154 : "Failed to create DTED file `%s'.\n%s",
155 : pszFullFilename, pszError );
156 : #endif
157 0 : return FALSE;
158 : }
159 :
160 0 : psInfo = DTEDOpen( pszFullFilename, "rb+", FALSE );
161 :
162 0 : if( psInfo == NULL )
163 : {
164 0 : CPLFree( pszFullFilename );
165 0 : return FALSE;
166 : }
167 :
168 : /* add cached file to stream */
169 0 : psStream->nOpenFiles++;
170 0 : psStream->pasCF =
171 0 : CPLRealloc(psStream->pasCF,
172 : sizeof(DTEDCachedFile)*psStream->nOpenFiles);
173 :
174 0 : psStream->pasCF[psStream->nOpenFiles-1].psInfo = psInfo;
175 0 : psStream->pasCF[psStream->nOpenFiles-1].papanProfiles =
176 0 : CPLCalloc(sizeof(GInt16*),psInfo->nXSize);
177 0 : psStream->pasCF[psStream->nOpenFiles-1].pszFilename = pszFullFilename;
178 0 : psStream->pasCF[psStream->nOpenFiles-1].nLLLat = nCrLat;
179 0 : psStream->pasCF[psStream->nOpenFiles-1].nLLLong = nCrLong;
180 :
181 0 : psStream->nLastFile = psStream->nOpenFiles-1;
182 :
183 0 : return TRUE;
184 : }
185 :
186 : /************************************************************************/
187 : /* DTEDWritePtLL() */
188 : /************************************************************************/
189 :
190 0 : static int DTEDWritePtLL( DTEDPtStream *psStream,
191 : DTEDCachedFile *psCF,
192 : double dfLong, double dfLat, double dfElev )
193 :
194 : {
195 : /* -------------------------------------------------------------------- */
196 : /* Determine what profile this belongs in, and initialize the */
197 : /* profile if it doesn't already exist. */
198 : /* -------------------------------------------------------------------- */
199 0 : DTEDInfo *psInfo = psCF->psInfo;
200 : int iProfile, i, iRow;
201 :
202 0 : iProfile = (int) ((dfLong - psInfo->dfULCornerX) / psInfo->dfPixelSizeX);
203 0 : iProfile = MAX(0,MIN(psInfo->nXSize-1,iProfile));
204 :
205 0 : if( psCF->papanProfiles[iProfile] == NULL )
206 : {
207 0 : psCF->papanProfiles[iProfile] =
208 0 : CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
209 :
210 0 : for( i = 0; i < psInfo->nYSize; i++ )
211 0 : psCF->papanProfiles[iProfile][i] = DTED_NODATA_VALUE;
212 : }
213 :
214 : /* -------------------------------------------------------------------- */
215 : /* Establish where we fit in the profile. */
216 : /* -------------------------------------------------------------------- */
217 0 : iRow = (int) ((psInfo->dfULCornerY-dfLat) / psInfo->dfPixelSizeY);
218 0 : iRow = MAX(0,MIN(psInfo->nYSize-1,iRow));
219 :
220 0 : psCF->papanProfiles[iProfile][iRow] = (GInt16) floor(dfElev+0.5);
221 :
222 0 : return TRUE;
223 : }
224 :
225 : /************************************************************************/
226 : /* DTEDWritePt() */
227 : /* */
228 : /* Write a single point out, creating a new file if necessary */
229 : /* to hold it. */
230 : /************************************************************************/
231 :
232 0 : int DTEDWritePt( void *hStream, double dfLong, double dfLat, double dfElev )
233 :
234 : {
235 0 : DTEDPtStream *psStream = (DTEDPtStream *) hStream;
236 : int i;
237 : DTEDInfo *psInfo;
238 0 : int bOnBoundary = FALSE;
239 :
240 : /* -------------------------------------------------------------------- */
241 : /* Determine if we are in a boundary region ... that is in the */
242 : /* area of the edge "pixel" that is shared with adjacent */
243 : /* tiles. */
244 : /* -------------------------------------------------------------------- */
245 0 : if( (floor(dfLong - 0.5*psStream->dfPixelSize)
246 0 : != floor(dfLong + 0.5*psStream->dfPixelSize))
247 0 : || (floor(dfLat - 0.5*psStream->dfPixelSize)
248 0 : != floor(dfLat + 0.5*psStream->dfPixelSize)) )
249 : {
250 0 : bOnBoundary = TRUE;
251 0 : psStream->nLastFile = -1;
252 : }
253 :
254 : /* ==================================================================== */
255 : /* Handle case where the tile is not on a boundary. We only */
256 : /* need one output tile. */
257 : /* ==================================================================== */
258 : /* -------------------------------------------------------------------- */
259 : /* Is the last file used still applicable? */
260 : /* -------------------------------------------------------------------- */
261 0 : if( !bOnBoundary )
262 : {
263 0 : if( psStream->nLastFile != -1 )
264 : {
265 0 : psInfo = psStream->pasCF[psStream->nLastFile].psInfo;
266 :
267 0 : if( dfLat > psInfo->dfULCornerY
268 0 : || dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY
269 0 : || dfLong < psInfo->dfULCornerX
270 0 : || dfLong > psInfo->dfULCornerX + 1.0 + psInfo->dfPixelSizeX )
271 0 : psStream->nLastFile = -1;
272 : }
273 :
274 : /* -------------------------------------------------------------------- */
275 : /* Search for the file to write to. */
276 : /* -------------------------------------------------------------------- */
277 0 : for( i = 0; i < psStream->nOpenFiles && psStream->nLastFile == -1; i++ )
278 : {
279 0 : psInfo = psStream->pasCF[i].psInfo;
280 :
281 0 : if( !(dfLat > psInfo->dfULCornerY
282 0 : || dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY
283 0 : || dfLong < psInfo->dfULCornerX
284 0 : || dfLong > psInfo->dfULCornerX + 1.0 + psInfo->dfPixelSizeX) )
285 : {
286 0 : psStream->nLastFile = i;
287 : }
288 : }
289 :
290 : /* -------------------------------------------------------------------- */
291 : /* If none found, create a new file. */
292 : /* -------------------------------------------------------------------- */
293 0 : if( psStream->nLastFile == -1 )
294 : {
295 : int nCrLong, nCrLat;
296 :
297 0 : nCrLong = (int) floor(dfLong);
298 0 : nCrLat = (int) floor(dfLat);
299 :
300 0 : if( !DTEDPtStreamNewTile( psStream, nCrLong, nCrLat ) )
301 0 : return FALSE;
302 : }
303 :
304 : /* -------------------------------------------------------------------- */
305 : /* Write data out to selected tile. */
306 : /* -------------------------------------------------------------------- */
307 0 : return DTEDWritePtLL( psStream, psStream->pasCF + psStream->nLastFile,
308 : dfLong, dfLat, dfElev );
309 : }
310 :
311 : /* ==================================================================== */
312 : /* Handle case where we are on a boundary. We may be writing */
313 : /* the value to as many as four tiles. */
314 : /* ==================================================================== */
315 : else
316 : {
317 : int nLatMin, nLatMax, nLongMin, nLongMax;
318 : int nCrLong, nCrLat;
319 :
320 0 : nLongMin = (int) floor( dfLong - 0.5*psStream->dfPixelSize );
321 0 : nLongMax = (int) floor( dfLong + 0.5*psStream->dfPixelSize );
322 0 : nLatMin = (int) floor( dfLat - 0.5*psStream->dfPixelSize );
323 0 : nLatMax = (int) floor( dfLat + 0.5*psStream->dfPixelSize );
324 :
325 0 : for( nCrLong = nLongMin; nCrLong <= nLongMax; nCrLong++ )
326 : {
327 0 : for( nCrLat = nLatMin; nCrLat <= nLatMax; nCrLat++ )
328 : {
329 0 : psStream->nLastFile = -1;
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* Find this tile in our existing list. */
333 : /* -------------------------------------------------------------------- */
334 0 : for( i = 0; i < psStream->nOpenFiles; i++ )
335 : {
336 0 : if( psStream->pasCF[i].nLLLong == nCrLong
337 0 : && psStream->pasCF[i].nLLLat == nCrLat )
338 : {
339 0 : psStream->nLastFile = i;
340 0 : break;
341 : }
342 : }
343 :
344 : /* -------------------------------------------------------------------- */
345 : /* Create the tile if not found. */
346 : /* -------------------------------------------------------------------- */
347 0 : if( psStream->nLastFile == -1 )
348 : {
349 0 : if( !DTEDPtStreamNewTile( psStream, nCrLong, nCrLat ) )
350 0 : return FALSE;
351 : }
352 :
353 : /* -------------------------------------------------------------------- */
354 : /* Write to the tile. */
355 : /* -------------------------------------------------------------------- */
356 0 : if( !DTEDWritePtLL( psStream,
357 0 : psStream->pasCF + psStream->nLastFile,
358 : dfLong, dfLat, dfElev ) )
359 0 : return FALSE;
360 : }
361 : }
362 : }
363 :
364 0 : return TRUE;
365 : }
366 :
367 : /************************************************************************/
368 : /* DTEDClosePtStream() */
369 : /************************************************************************/
370 :
371 0 : void DTEDClosePtStream( void *hStream )
372 :
373 : {
374 0 : DTEDPtStream *psStream = (DTEDPtStream *) hStream;
375 : int iFile, iMD;
376 :
377 : /* -------------------------------------------------------------------- */
378 : /* Flush all DTED files. */
379 : /* -------------------------------------------------------------------- */
380 0 : for( iFile = 0; iFile < psStream->nOpenFiles; iFile++ )
381 : {
382 : int iProfile;
383 0 : DTEDCachedFile *psCF = psStream->pasCF + iFile;
384 :
385 0 : for( iProfile = 0; iProfile < psCF->psInfo->nXSize; iProfile++ )
386 : {
387 0 : if( psCF->papanProfiles[iProfile] != NULL )
388 : {
389 0 : DTEDWriteProfile( psCF->psInfo, iProfile,
390 0 : psCF->papanProfiles[iProfile] );
391 0 : CPLFree( psCF->papanProfiles[iProfile] );
392 : }
393 : }
394 :
395 0 : CPLFree( psCF->papanProfiles );
396 :
397 0 : for( iMD = 0; iMD < DTEDMD_MAX+1; iMD++ )
398 : {
399 0 : if( psStream->apszMetadata[iMD] != NULL )
400 0 : DTEDSetMetadata( psCF->psInfo, iMD,
401 0 : psStream->apszMetadata[iMD] );
402 : }
403 :
404 0 : DTEDClose( psCF->psInfo );
405 : }
406 :
407 : /* -------------------------------------------------------------------- */
408 : /* Final cleanup. */
409 : /* -------------------------------------------------------------------- */
410 :
411 0 : for( iMD = 0; iMD < DTEDMD_MAX+1; iMD++ )
412 0 : CPLFree( psStream->apszMetadata[iMD] );
413 :
414 0 : CPLFree( psStream->pasCF );
415 0 : CPLFree( psStream->pszPath );
416 0 : CPLFree( psStream );
417 0 : }
418 :
419 : /************************************************************************/
420 : /* DTEDFillPixel() */
421 : /************************************************************************/
422 :
423 0 : void DTEDFillPixel( DTEDInfo *psInfo, GInt16 **papanProfiles,
424 : GInt16 **papanDstProfiles, int iX, int iY,
425 : int nPixelSearchDist, float *pafKernel )
426 :
427 : {
428 0 : int nKernelWidth = 2 * nPixelSearchDist + 1;
429 : int nXMin, nXMax, nYMin, nYMax;
430 0 : double dfCoefSum = 0.0, dfValueSum = 0.0;
431 : int iXS, iYS;
432 :
433 0 : nXMin = MAX(0,iX - nPixelSearchDist);
434 0 : nXMax = MIN(psInfo->nXSize-1,iX + nPixelSearchDist);
435 0 : nYMin = MAX(0,iY - nPixelSearchDist);
436 0 : nYMax = MIN(psInfo->nYSize-1,iY + nPixelSearchDist);
437 :
438 0 : for( iXS = nXMin; iXS <= nXMax; iXS++ )
439 : {
440 0 : GInt16 *panThisProfile = papanProfiles[iXS];
441 :
442 0 : if( panThisProfile == NULL )
443 0 : continue;
444 :
445 0 : for( iYS = nYMin; iYS <= nYMax; iYS++ )
446 : {
447 0 : if( panThisProfile[iYS] != DTED_NODATA_VALUE )
448 : {
449 : int iXK, iYK;
450 : float fKernelCoef;
451 :
452 0 : iXK = iXS - iX + nPixelSearchDist;
453 0 : iYK = iYS - iY + nPixelSearchDist;
454 :
455 0 : fKernelCoef = pafKernel[iXK + iYK * nKernelWidth];
456 0 : dfCoefSum += fKernelCoef;
457 0 : dfValueSum += fKernelCoef * panThisProfile[iYS];
458 : }
459 : }
460 : }
461 :
462 0 : if( dfCoefSum == 0.0 )
463 0 : papanDstProfiles[iX][iY] = DTED_NODATA_VALUE;
464 : else
465 0 : papanDstProfiles[iX][iY] =
466 0 : (GInt16) floor(dfValueSum / dfCoefSum + 0.5);
467 0 : }
468 :
469 : /************************************************************************/
470 : /* DTEDFillPtStream() */
471 : /* */
472 : /* Apply simple inverse distance interpolator to all no-data */
473 : /* pixels based on available values within the indicated search */
474 : /* distance (rectangular). */
475 : /************************************************************************/
476 :
477 0 : void DTEDFillPtStream( void *hStream, int nPixelSearchDist )
478 :
479 : {
480 0 : DTEDPtStream *psStream = (DTEDPtStream *) hStream;
481 : int iFile, nKernelWidth;
482 : float *pafKernel;
483 : int iX, iY;
484 :
485 : /* -------------------------------------------------------------------- */
486 : /* Setup inverse distance weighting kernel. */
487 : /* -------------------------------------------------------------------- */
488 0 : nKernelWidth = 2 * nPixelSearchDist + 1;
489 0 : pafKernel = (float *) CPLMalloc(nKernelWidth*nKernelWidth*sizeof(float));
490 :
491 0 : for( iX = 0; iX < nKernelWidth; iX++ )
492 : {
493 0 : for( iY = 0; iY < nKernelWidth; iY++ )
494 : {
495 0 : pafKernel[iX + iY * nKernelWidth] = (float) (1.0 /
496 0 : sqrt( (nPixelSearchDist-iX) * (nPixelSearchDist-iX)
497 0 : + (nPixelSearchDist-iY) * (nPixelSearchDist-iY) ));
498 : }
499 : }
500 :
501 : /* ==================================================================== */
502 : /* Process each cached file. */
503 : /* ==================================================================== */
504 0 : for( iFile = 0; iFile < psStream->nOpenFiles; iFile++ )
505 : {
506 0 : DTEDInfo *psInfo = psStream->pasCF[iFile].psInfo;
507 0 : GInt16 **papanProfiles = psStream->pasCF[iFile].papanProfiles;
508 : GInt16 **papanDstProfiles;
509 :
510 0 : papanDstProfiles = (GInt16 **)
511 0 : CPLCalloc(sizeof(GInt16*),psInfo->nXSize);
512 :
513 : /* -------------------------------------------------------------------- */
514 : /* Setup output image. */
515 : /* -------------------------------------------------------------------- */
516 0 : for( iX = 0; iX < psInfo->nXSize; iX++ )
517 : {
518 0 : papanDstProfiles[iX] = (GInt16 *)
519 : CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
520 : }
521 :
522 : /* -------------------------------------------------------------------- */
523 : /* Interpolate all missing values, and copy over available values. */
524 : /* -------------------------------------------------------------------- */
525 0 : for( iX = 0; iX < psInfo->nXSize; iX++ )
526 : {
527 0 : for( iY = 0; iY < psInfo->nYSize; iY++ )
528 : {
529 0 : if( papanProfiles[iX] == NULL
530 0 : || papanProfiles[iX][iY] == DTED_NODATA_VALUE )
531 : {
532 0 : DTEDFillPixel( psInfo, papanProfiles, papanDstProfiles,
533 : iX, iY, nPixelSearchDist, pafKernel );
534 : }
535 : else
536 : {
537 0 : papanDstProfiles[iX][iY] = papanProfiles[iX][iY];
538 : }
539 : }
540 : }
541 : /* -------------------------------------------------------------------- */
542 : /* Push new values back into cache. */
543 : /* -------------------------------------------------------------------- */
544 0 : for( iX = 0; iX < psInfo->nXSize; iX++ )
545 : {
546 0 : CPLFree( papanProfiles[iX] );
547 0 : papanProfiles[iX] = papanDstProfiles[iX];
548 : }
549 :
550 0 : CPLFree( papanDstProfiles );
551 : }
552 :
553 0 : CPLFree( pafKernel );
554 0 : }
555 :
556 : /************************************************************************/
557 : /* DTEDPtStreamSetMetadata() */
558 : /************************************************************************/
559 :
560 0 : void DTEDPtStreamSetMetadata( void *hStream, DTEDMetaDataCode eCode,
561 : const char *pszValue )
562 :
563 : {
564 0 : DTEDPtStream *psStream = (DTEDPtStream *) hStream;
565 :
566 0 : if( eCode >= 0 && eCode < DTEDMD_MAX+1 )
567 : {
568 0 : CPLFree( psStream->apszMetadata[eCode] );
569 0 : psStream->apszMetadata[eCode] = CPLStrdup( pszValue );
570 : }
571 0 : }
572 :
573 : /************************************************************************/
574 : /* DTEDPtStreamTrimEdgeOnlyTiles() */
575 : /* */
576 : /* Erase all tiles that only have boundary values set. */
577 : /************************************************************************/
578 :
579 0 : void DTEDPtStreamTrimEdgeOnlyTiles( void *hStream )
580 :
581 : {
582 0 : DTEDPtStream *psStream = (DTEDPtStream *) hStream;
583 : int iFile;
584 :
585 0 : for( iFile = psStream->nOpenFiles-1; iFile >= 0; iFile-- )
586 : {
587 0 : DTEDInfo *psInfo = psStream->pasCF[iFile].psInfo;
588 0 : GInt16 **papanProfiles = psStream->pasCF[iFile].papanProfiles;
589 0 : int iProfile, iPixel, bGotNonEdgeData = FALSE;
590 :
591 0 : for( iProfile = 1; iProfile < psInfo->nXSize-1; iProfile++ )
592 : {
593 0 : if( papanProfiles[iProfile] == NULL )
594 0 : continue;
595 :
596 0 : for( iPixel = 1; iPixel < psInfo->nYSize-1; iPixel++ )
597 : {
598 0 : if( papanProfiles[iProfile][iPixel] != DTED_NODATA_VALUE )
599 : {
600 0 : bGotNonEdgeData = TRUE;
601 0 : break;
602 : }
603 : }
604 : }
605 :
606 0 : if( bGotNonEdgeData )
607 0 : continue;
608 :
609 : /* Remove this tile */
610 :
611 0 : for( iProfile = 0; iProfile < psInfo->nXSize; iProfile++ )
612 : {
613 0 : if( papanProfiles[iProfile] != NULL )
614 0 : CPLFree( papanProfiles[iProfile] );
615 : }
616 0 : CPLFree( papanProfiles );
617 :
618 0 : DTEDClose( psInfo );
619 :
620 0 : VSIUnlink( psStream->pasCF[iFile].pszFilename );
621 0 : CPLFree( psStream->pasCF[iFile].pszFilename );
622 :
623 0 : memmove( psStream->pasCF + iFile,
624 0 : psStream->pasCF + iFile + 1,
625 0 : sizeof(DTEDCachedFile) * (psStream->nOpenFiles-iFile-1) );
626 0 : psStream->nOpenFiles--;
627 : }
628 0 : }
|