Line data Source code
1 : /******************************************************************************
2 : * $Id$
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 : typedef struct
33 : {
34 : char *pszFilename;
35 : DTEDInfo *psInfo;
36 :
37 : GInt16 **papanProfiles;
38 :
39 : int nLLLong;
40 : int nLLLat;
41 : } DTEDCachedFile;
42 :
43 : typedef struct
44 : {
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'.", pszPath);
80 : #endif
81 0 : return NULL;
82 : }
83 : }
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Create the stream and initialize it. */
87 : /* -------------------------------------------------------------------- */
88 :
89 0 : psStream = (DTEDPtStream *)CPLCalloc(sizeof(DTEDPtStream), 1);
90 0 : psStream->nLevel = nLevel;
91 0 : psStream->pszPath = CPLStrdup(pszPath);
92 0 : psStream->nOpenFiles = 0;
93 0 : psStream->pasCF = NULL;
94 0 : psStream->nLastFile = -1;
95 :
96 0 : for (i = 0; i < DTEDMD_MAX + 1; i++)
97 0 : psStream->apszMetadata[i] = NULL;
98 :
99 0 : if (nLevel == 0)
100 0 : psStream->dfPixelSize = 1.0 / 120.0;
101 0 : else if (nLevel == 1)
102 0 : psStream->dfPixelSize = 1.0 / 1200.0;
103 : else /* if( nLevel == 2 ) */
104 0 : psStream->dfPixelSize = 1.0 / 3600.0;
105 :
106 0 : return (void *)psStream;
107 : }
108 :
109 : /************************************************************************/
110 : /* DTEDPtStreamNewTile() */
111 : /* */
112 : /* Create a new DTED file file, add it to our list, and make it */
113 : /* "current". */
114 : /************************************************************************/
115 :
116 0 : static int DTEDPtStreamNewTile(DTEDPtStream *psStream, int nCrLong, int nCrLat)
117 :
118 : {
119 : DTEDInfo *psInfo;
120 : char szFile[128];
121 : char chNSHemi, chEWHemi;
122 : char *pszFullFilename;
123 : const char *pszError;
124 :
125 : /* work out filename */
126 0 : if (nCrLat < 0)
127 0 : chNSHemi = 's';
128 : else
129 0 : chNSHemi = 'n';
130 :
131 0 : if (nCrLong < 0)
132 0 : chEWHemi = 'w';
133 : else
134 0 : chEWHemi = 'e';
135 :
136 0 : snprintf(szFile, sizeof(szFile), "%c%03d%c%03d.dt%d", chEWHemi,
137 : ABS(nCrLong), chNSHemi, ABS(nCrLat), psStream->nLevel);
138 :
139 : pszFullFilename =
140 0 : CPLStrdup(CPLFormFilename(psStream->pszPath, szFile, NULL));
141 :
142 : /* create the dted file */
143 0 : pszError = DTEDCreate(pszFullFilename, psStream->nLevel, nCrLat, nCrLong);
144 0 : if (pszError != NULL)
145 : {
146 : #ifndef AVOID_CPL
147 0 : CPLError(CE_Failure, CPLE_OpenFailed,
148 : "Failed to create DTED file `%s'.\n%s", pszFullFilename,
149 : pszError);
150 : #endif
151 0 : return FALSE;
152 : }
153 :
154 0 : psInfo = DTEDOpen(pszFullFilename, "rb+", FALSE);
155 :
156 0 : if (psInfo == NULL)
157 : {
158 0 : CPLFree(pszFullFilename);
159 0 : return FALSE;
160 : }
161 :
162 : /* add cached file to stream */
163 0 : psStream->nOpenFiles++;
164 0 : psStream->pasCF = CPLRealloc(psStream->pasCF,
165 0 : sizeof(DTEDCachedFile) * psStream->nOpenFiles);
166 :
167 0 : psStream->pasCF[psStream->nOpenFiles - 1].psInfo = psInfo;
168 0 : psStream->pasCF[psStream->nOpenFiles - 1].papanProfiles =
169 0 : CPLCalloc(sizeof(GInt16 *), psInfo->nXSize);
170 0 : psStream->pasCF[psStream->nOpenFiles - 1].pszFilename = pszFullFilename;
171 0 : psStream->pasCF[psStream->nOpenFiles - 1].nLLLat = nCrLat;
172 0 : psStream->pasCF[psStream->nOpenFiles - 1].nLLLong = nCrLong;
173 :
174 0 : psStream->nLastFile = psStream->nOpenFiles - 1;
175 :
176 0 : return TRUE;
177 : }
178 :
179 : /************************************************************************/
180 : /* DTEDWritePtLL() */
181 : /************************************************************************/
182 :
183 0 : static int DTEDWritePtLL(CPL_UNUSED DTEDPtStream *psStream,
184 : DTEDCachedFile *psCF, double dfLong, double dfLat,
185 : double dfElev)
186 : {
187 : /* -------------------------------------------------------------------- */
188 : /* Determine what profile this belongs in, and initialize the */
189 : /* profile if it doesn't already exist. */
190 : /* -------------------------------------------------------------------- */
191 0 : DTEDInfo *psInfo = psCF->psInfo;
192 : int iProfile, i, iRow;
193 :
194 0 : iProfile = (int)((dfLong - psInfo->dfULCornerX) / psInfo->dfPixelSizeX);
195 0 : iProfile = MAX(0, MIN(psInfo->nXSize - 1, iProfile));
196 :
197 0 : if (psCF->papanProfiles[iProfile] == NULL)
198 : {
199 0 : psCF->papanProfiles[iProfile] =
200 0 : CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
201 :
202 0 : for (i = 0; i < psInfo->nYSize; i++)
203 0 : psCF->papanProfiles[iProfile][i] = DTED_NODATA_VALUE;
204 : }
205 :
206 : /* -------------------------------------------------------------------- */
207 : /* Establish where we fit in the profile. */
208 : /* -------------------------------------------------------------------- */
209 0 : iRow = (int)((psInfo->dfULCornerY - dfLat) / psInfo->dfPixelSizeY);
210 0 : iRow = MAX(0, MIN(psInfo->nYSize - 1, iRow));
211 :
212 0 : psCF->papanProfiles[iProfile][iRow] = (GInt16)floor(dfElev + 0.5);
213 :
214 0 : return TRUE;
215 : }
216 :
217 : /************************************************************************/
218 : /* DTEDWritePt() */
219 : /* */
220 : /* Write a single point out, creating a new file if necessary */
221 : /* to hold it. */
222 : /************************************************************************/
223 :
224 0 : int DTEDWritePt(void *hStream, double dfLong, double dfLat, double dfElev)
225 :
226 : {
227 0 : DTEDPtStream *psStream = (DTEDPtStream *)hStream;
228 : int i;
229 : DTEDInfo *psInfo;
230 0 : int bOnBoundary = FALSE;
231 :
232 : /* -------------------------------------------------------------------- */
233 : /* Determine if we are in a boundary region ... that is in the */
234 : /* area of the edge "pixel" that is shared with adjacent */
235 : /* tiles. */
236 : /* -------------------------------------------------------------------- */
237 0 : if ((floor(dfLong - 0.5 * psStream->dfPixelSize) !=
238 0 : floor(dfLong + 0.5 * psStream->dfPixelSize)) ||
239 0 : (floor(dfLat - 0.5 * psStream->dfPixelSize) !=
240 0 : floor(dfLat + 0.5 * psStream->dfPixelSize)))
241 : {
242 0 : bOnBoundary = TRUE;
243 0 : psStream->nLastFile = -1;
244 : }
245 :
246 : /* ==================================================================== */
247 : /* Handle case where the tile is not on a boundary. We only */
248 : /* need one output tile. */
249 : /* ==================================================================== */
250 : /* -------------------------------------------------------------------- */
251 : /* Is the last file used still applicable? */
252 : /* -------------------------------------------------------------------- */
253 0 : if (!bOnBoundary)
254 : {
255 0 : if (psStream->nLastFile != -1)
256 : {
257 0 : psInfo = psStream->pasCF[psStream->nLastFile].psInfo;
258 :
259 0 : if (dfLat > psInfo->dfULCornerY ||
260 0 : dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY ||
261 0 : dfLong < psInfo->dfULCornerX ||
262 0 : dfLong > psInfo->dfULCornerX + 1.0 + psInfo->dfPixelSizeX)
263 0 : psStream->nLastFile = -1;
264 : }
265 :
266 : /* --------------------------------------------------------------------
267 : */
268 : /* Search for the file to write to. */
269 : /* --------------------------------------------------------------------
270 : */
271 0 : for (i = 0; i < psStream->nOpenFiles && psStream->nLastFile == -1; i++)
272 : {
273 0 : psInfo = psStream->pasCF[i].psInfo;
274 :
275 0 : if (!(dfLat > psInfo->dfULCornerY ||
276 0 : dfLat < psInfo->dfULCornerY - 1.0 - psInfo->dfPixelSizeY ||
277 0 : dfLong < psInfo->dfULCornerX ||
278 0 : dfLong > psInfo->dfULCornerX + 1.0 + psInfo->dfPixelSizeX))
279 : {
280 0 : psStream->nLastFile = i;
281 : }
282 : }
283 :
284 : /* --------------------------------------------------------------------
285 : */
286 : /* If none found, create a new file. */
287 : /* --------------------------------------------------------------------
288 : */
289 0 : if (psStream->nLastFile == -1)
290 : {
291 : int nCrLong, nCrLat;
292 :
293 0 : nCrLong = (int)floor(dfLong);
294 0 : nCrLat = (int)floor(dfLat);
295 :
296 0 : if (!DTEDPtStreamNewTile(psStream, nCrLong, nCrLat))
297 0 : return FALSE;
298 : }
299 :
300 : /* --------------------------------------------------------------------
301 : */
302 : /* Write data out to selected tile. */
303 : /* --------------------------------------------------------------------
304 : */
305 0 : return DTEDWritePtLL(psStream, psStream->pasCF + psStream->nLastFile,
306 : dfLong, dfLat, dfElev);
307 : }
308 :
309 : /* ==================================================================== */
310 : /* Handle case where we are on a boundary. We may be writing */
311 : /* the value to as many as four tiles. */
312 : /* ==================================================================== */
313 : else
314 : {
315 : int nLatMin, nLatMax, nLongMin, nLongMax;
316 : int nCrLong, nCrLat;
317 :
318 0 : nLongMin = (int)floor(dfLong - 0.5 * psStream->dfPixelSize);
319 0 : nLongMax = (int)floor(dfLong + 0.5 * psStream->dfPixelSize);
320 0 : nLatMin = (int)floor(dfLat - 0.5 * psStream->dfPixelSize);
321 0 : nLatMax = (int)floor(dfLat + 0.5 * psStream->dfPixelSize);
322 :
323 0 : for (nCrLong = nLongMin; nCrLong <= nLongMax; nCrLong++)
324 : {
325 0 : for (nCrLat = nLatMin; nCrLat <= nLatMax; nCrLat++)
326 : {
327 0 : psStream->nLastFile = -1;
328 :
329 : /* --------------------------------------------------------------------
330 : */
331 : /* Find this tile in our existing list. */
332 : /* --------------------------------------------------------------------
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 : */
346 : /* Create the tile if not found. */
347 : /* --------------------------------------------------------------------
348 : */
349 0 : if (psStream->nLastFile == -1)
350 : {
351 0 : if (!DTEDPtStreamNewTile(psStream, nCrLong, nCrLat))
352 0 : return FALSE;
353 : }
354 :
355 : /* --------------------------------------------------------------------
356 : */
357 : /* Write to the tile. */
358 : /* --------------------------------------------------------------------
359 : */
360 0 : if (!DTEDWritePtLL(psStream,
361 0 : psStream->pasCF + psStream->nLastFile,
362 : dfLong, dfLat, dfElev))
363 0 : return FALSE;
364 : }
365 : }
366 : }
367 :
368 0 : return TRUE;
369 : }
370 :
371 : /************************************************************************/
372 : /* DTEDClosePtStream() */
373 : /************************************************************************/
374 :
375 0 : void DTEDClosePtStream(void *hStream)
376 :
377 : {
378 0 : DTEDPtStream *psStream = (DTEDPtStream *)hStream;
379 : int iFile, iMD;
380 :
381 : /* -------------------------------------------------------------------- */
382 : /* Flush all DTED files. */
383 : /* -------------------------------------------------------------------- */
384 0 : for (iFile = 0; iFile < psStream->nOpenFiles; iFile++)
385 : {
386 : int iProfile;
387 0 : DTEDCachedFile *psCF = psStream->pasCF + iFile;
388 :
389 0 : for (iProfile = 0; iProfile < psCF->psInfo->nXSize; iProfile++)
390 : {
391 0 : if (psCF->papanProfiles[iProfile] != NULL)
392 : {
393 0 : DTEDWriteProfile(psCF->psInfo, iProfile,
394 0 : psCF->papanProfiles[iProfile]);
395 0 : CPLFree(psCF->papanProfiles[iProfile]);
396 : }
397 : }
398 :
399 0 : CPLFree(psCF->papanProfiles);
400 :
401 0 : for (iMD = 0; iMD <= DTEDMD_MAX; iMD++)
402 : {
403 0 : if (psStream->apszMetadata[iMD] != NULL)
404 0 : DTEDSetMetadata(psCF->psInfo, (DTEDMetaDataCode)iMD,
405 0 : psStream->apszMetadata[iMD]);
406 : }
407 :
408 0 : DTEDClose(psCF->psInfo);
409 : }
410 :
411 : /* -------------------------------------------------------------------- */
412 : /* Final cleanup. */
413 : /* -------------------------------------------------------------------- */
414 :
415 0 : for (iMD = 0; iMD < DTEDMD_MAX + 1; iMD++)
416 0 : CPLFree(psStream->apszMetadata[iMD]);
417 :
418 0 : CPLFree(psStream->pasCF);
419 0 : CPLFree(psStream->pszPath);
420 0 : CPLFree(psStream);
421 0 : }
422 :
423 : /************************************************************************/
424 : /* DTEDFillPixel() */
425 : /************************************************************************/
426 0 : static void DTEDFillPixel(DTEDInfo *psInfo, GInt16 **papanProfiles,
427 : GInt16 **papanDstProfiles, int iX, int iY,
428 : int nPixelSearchDist, float *pafKernel)
429 :
430 : {
431 0 : int nKernelWidth = 2 * nPixelSearchDist + 1;
432 : int nXMin, nXMax, nYMin, nYMax;
433 0 : double dfCoefSum = 0.0, dfValueSum = 0.0;
434 : int iXS, iYS;
435 :
436 0 : nXMin = MAX(0, iX - nPixelSearchDist);
437 0 : nXMax = MIN(psInfo->nXSize - 1, iX + nPixelSearchDist);
438 0 : nYMin = MAX(0, iY - nPixelSearchDist);
439 0 : nYMax = MIN(psInfo->nYSize - 1, iY + nPixelSearchDist);
440 :
441 0 : for (iXS = nXMin; iXS <= nXMax; iXS++)
442 : {
443 0 : GInt16 *panThisProfile = papanProfiles[iXS];
444 :
445 0 : if (panThisProfile == NULL)
446 0 : continue;
447 :
448 0 : for (iYS = nYMin; iYS <= nYMax; iYS++)
449 : {
450 0 : if (panThisProfile[iYS] != DTED_NODATA_VALUE)
451 : {
452 : int iXK, iYK;
453 : float fKernelCoef;
454 :
455 0 : iXK = iXS - iX + nPixelSearchDist;
456 0 : iYK = iYS - iY + nPixelSearchDist;
457 :
458 0 : fKernelCoef = pafKernel[iXK + iYK * nKernelWidth];
459 0 : dfCoefSum += fKernelCoef;
460 0 : dfValueSum += (double)fKernelCoef * (double)panThisProfile[iYS];
461 : }
462 : }
463 : }
464 :
465 0 : if (dfCoefSum == 0.0)
466 0 : papanDstProfiles[iX][iY] = DTED_NODATA_VALUE;
467 : else
468 0 : papanDstProfiles[iX][iY] = (GInt16)floor(dfValueSum / dfCoefSum + 0.5);
469 0 : }
470 :
471 : /************************************************************************/
472 : /* DTEDFillPtStream() */
473 : /* */
474 : /* Apply simple inverse distance interpolator to all no-data */
475 : /* pixels based on available values within the indicated search */
476 : /* distance (rectangular). */
477 : /************************************************************************/
478 :
479 0 : void DTEDFillPtStream(void *hStream, int nPixelSearchDist)
480 :
481 : {
482 0 : DTEDPtStream *psStream = (DTEDPtStream *)hStream;
483 : int iFile, nKernelWidth;
484 : float *pafKernel;
485 : int iX, iY;
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Setup inverse distance weighting kernel. */
489 : /* -------------------------------------------------------------------- */
490 0 : nKernelWidth = 2 * nPixelSearchDist + 1;
491 0 : pafKernel = (float *)CPLMalloc(sizeof(float) * nKernelWidth * nKernelWidth);
492 :
493 0 : for (iX = 0; iX < nKernelWidth; iX++)
494 : {
495 0 : for (iY = 0; iY < nKernelWidth; iY++)
496 : {
497 0 : pafKernel[iX + iY * nKernelWidth] =
498 0 : (float)(1.0 /
499 0 : sqrt((nPixelSearchDist - iX) * (nPixelSearchDist - iX) +
500 0 : (nPixelSearchDist - iY) *
501 0 : (nPixelSearchDist - iY)));
502 : }
503 : }
504 :
505 : /* ==================================================================== */
506 : /* Process each cached file. */
507 : /* ==================================================================== */
508 0 : for (iFile = 0; iFile < psStream->nOpenFiles; iFile++)
509 : {
510 0 : DTEDInfo *psInfo = psStream->pasCF[iFile].psInfo;
511 0 : GInt16 **papanProfiles = psStream->pasCF[iFile].papanProfiles;
512 : GInt16 **papanDstProfiles;
513 :
514 : papanDstProfiles =
515 0 : (GInt16 **)CPLCalloc(sizeof(GInt16 *), psInfo->nXSize);
516 :
517 : /* --------------------------------------------------------------------
518 : */
519 : /* Setup output image. */
520 : /* --------------------------------------------------------------------
521 : */
522 0 : for (iX = 0; iX < psInfo->nXSize; iX++)
523 : {
524 0 : papanDstProfiles[iX] =
525 0 : (GInt16 *)CPLMalloc(sizeof(GInt16) * psInfo->nYSize);
526 : }
527 :
528 : /* --------------------------------------------------------------------
529 : */
530 : /* Interpolate all missing values, and copy over available values.
531 : */
532 : /* --------------------------------------------------------------------
533 : */
534 0 : for (iX = 0; iX < psInfo->nXSize; iX++)
535 : {
536 0 : for (iY = 0; iY < psInfo->nYSize; iY++)
537 : {
538 0 : if (papanProfiles[iX] == NULL ||
539 0 : papanProfiles[iX][iY] == DTED_NODATA_VALUE)
540 : {
541 0 : DTEDFillPixel(psInfo, papanProfiles, papanDstProfiles, iX,
542 : iY, nPixelSearchDist, pafKernel);
543 : }
544 : else
545 : {
546 0 : papanDstProfiles[iX][iY] = papanProfiles[iX][iY];
547 : }
548 : }
549 : }
550 : /* --------------------------------------------------------------------
551 : */
552 : /* Push new values back into cache. */
553 : /* --------------------------------------------------------------------
554 : */
555 0 : for (iX = 0; iX < psInfo->nXSize; iX++)
556 : {
557 0 : CPLFree(papanProfiles[iX]);
558 0 : papanProfiles[iX] = papanDstProfiles[iX];
559 : }
560 :
561 0 : CPLFree(papanDstProfiles);
562 : }
563 :
564 0 : CPLFree(pafKernel);
565 0 : }
566 :
567 : /************************************************************************/
568 : /* DTEDPtStreamSetMetadata() */
569 : /************************************************************************/
570 :
571 0 : void DTEDPtStreamSetMetadata(void *hStream, DTEDMetaDataCode eCode,
572 : const char *pszValue)
573 :
574 : {
575 0 : DTEDPtStream *psStream = (DTEDPtStream *)hStream;
576 :
577 0 : if ((int)eCode >= 0 && eCode < DTEDMD_MAX + 1)
578 : {
579 0 : CPLFree(psStream->apszMetadata[eCode]);
580 0 : psStream->apszMetadata[eCode] = CPLStrdup(pszValue);
581 : }
582 0 : }
583 :
584 : /************************************************************************/
585 : /* DTEDPtStreamTrimEdgeOnlyTiles() */
586 : /* */
587 : /* Erase all tiles that only have boundary values set. */
588 : /************************************************************************/
589 :
590 0 : void DTEDPtStreamTrimEdgeOnlyTiles(void *hStream)
591 :
592 : {
593 0 : DTEDPtStream *psStream = (DTEDPtStream *)hStream;
594 : int iFile;
595 :
596 0 : for (iFile = psStream->nOpenFiles - 1; iFile >= 0; iFile--)
597 : {
598 0 : DTEDInfo *psInfo = psStream->pasCF[iFile].psInfo;
599 0 : GInt16 **papanProfiles = psStream->pasCF[iFile].papanProfiles;
600 0 : int iProfile, iPixel, bGotNonEdgeData = FALSE;
601 :
602 0 : for (iProfile = 1; iProfile < psInfo->nXSize - 1; iProfile++)
603 : {
604 0 : if (papanProfiles[iProfile] == NULL)
605 0 : continue;
606 :
607 0 : for (iPixel = 1; iPixel < psInfo->nYSize - 1; iPixel++)
608 : {
609 0 : if (papanProfiles[iProfile][iPixel] != DTED_NODATA_VALUE)
610 : {
611 0 : bGotNonEdgeData = TRUE;
612 0 : break;
613 : }
614 : }
615 : }
616 :
617 0 : if (bGotNonEdgeData)
618 0 : continue;
619 :
620 : /* Remove this tile */
621 :
622 0 : for (iProfile = 0; iProfile < psInfo->nXSize; iProfile++)
623 : {
624 0 : if (papanProfiles[iProfile] != NULL)
625 0 : CPLFree(papanProfiles[iProfile]);
626 : }
627 0 : CPLFree(papanProfiles);
628 :
629 0 : DTEDClose(psInfo);
630 :
631 0 : VSIUnlink(psStream->pasCF[iFile].pszFilename);
632 0 : CPLFree(psStream->pasCF[iFile].pszFilename);
633 :
634 0 : memmove(psStream->pasCF + iFile, psStream->pasCF + iFile + 1,
635 0 : sizeof(DTEDCachedFile) * (psStream->nOpenFiles - iFile - 1));
636 0 : psStream->nOpenFiles--;
637 : }
638 0 : }
|