]> git.pld-linux.org Git - packages/bes.git/blob - bes-missing.patch
- x32 rebuild
[packages/bes.git] / bes-missing.patch
1 diff -Nur bes-3.12.0/functions.orig/swath2grid/AbstractDataset.cpp bes-3.12.0/functions/swath2grid/AbstractDataset.cpp
2 --- bes-3.12.0/functions.orig/swath2grid/AbstractDataset.cpp    1970-01-01 01:00:00.000000000 +0100
3 +++ bes-3.12.0/functions/swath2grid/AbstractDataset.cpp 2014-03-03 15:47:38.046899595 +0100
4 @@ -0,0 +1,1238 @@
5 +/******************************************************************************
6 + * $Id: AbstractDataset.cpp 2011-07-19 16:24:00Z $
7 + *
8 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
9 + *                      for Earth Observation: Open Source Reference Implementation
10 + * Purpose:  AbstractDataset implementation for providing an abstract data
11 + *                      model for multiple data source.
12 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
13 + *
14 + ******************************************************************************
15 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
16 + *
17 + * Permission is hereby granted, free of charge, to any person obtaining a
18 + * copy of this software and associated documentation files (the "Software"),
19 + * to deal in the Software without restriction, including without limitation
20 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21 + * and/or sell copies of the Software, and to permit persons to whom the
22 + * Software is furnished to do so, subject to the following conditions:
23 + *
24 + * The above copyright notice and this permission notice shall be included
25 + * in all copies or substantial portions of the Software.
26 + *
27 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 + * DEALINGS IN THE SOFTWARE.
34 + ****************************************************************************/
35 +
36 +#include "AbstractDataset.h"
37 +
38 +/************************************************************************/
39 +/* ==================================================================== */
40 +/*                           AbstractDataset                            */
41 +/* ==================================================================== */
42 +/************************************************************************/
43 +
44 +/**
45 + * \class AbstractDataset "AbstractDataset.h"
46 + *
47 + * An abstract dataset encapsulating one or more raster bands, which is
48 + * based on GDALDataset, and add the support to metadata model: ISO 19115
49 + * and 1SO 19115 (2). A series of Fetch functions are provided for the
50 + * implementation of Web Coverage Service.
51 + *
52 + * Use WCSTCreateDataset() to create a AbstractDataset for a named coverage
53 + * identifier and band list.
54 + */
55 +
56 +/************************************************************************/
57 +/*                            AbstractDataset()                         */
58 +/************************************************************************/
59 +AbstractDataset::AbstractDataset()
60 +{
61 +}
62 +
63 +/************************************************************************/
64 +/*                            AbstractDataset()                         */
65 +/************************************************************************/
66 +
67 +/**
68 + * \brief Constructor of an AbstractDataset.
69 + *
70 + * This is the accepted method of opening an abstract dataset and allocating
71 + * all resources associated with it.
72 + */
73 +
74 +AbstractDataset::AbstractDataset(const string& id, vector<int> &rBandList) :
75 +       ms_CoverageID(id), mv_BandList(rBandList)
76 +{
77 +}
78 +
79 +/************************************************************************/
80 +/*                            ~AbstractDataset()                        */
81 +/************************************************************************/
82 +
83 +/**
84 + * \brief Destroy an open AbstractDataset object.
85 + *
86 + * This is the accepted method of closing a AbstractDataset dataset and
87 + * deallocating all resources associated with it.
88 + */
89 +
90 +AbstractDataset::~AbstractDataset()
91 +{
92 +       if (maptr_DS.get())
93 +               GDALClose(maptr_DS.release());
94 +}
95 +
96 +/************************************************************************/
97 +/*                            InitialDataset()                          */
98 +/************************************************************************/
99 +
100 +/**
101 + * \brief Initialize the data set.
102 + *
103 + * This is the virtual function for initializing abstract dataste. The
104 + * subclasses of AbstarctDataset will call SetNativeCRS(), SetGeoTransform()
105 + * and SetGDALDataset() to initialize an abstarct dataset.
106 + *
107 + * @param isSimple The WCS request type.  When user executing a DescribeCoverage
108 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
109 + *
110 + * @return CE_None on success or CE_Failure on failure.
111 + */
112 +
113 +CPLErr AbstractDataset::InitialDataset(const int isSimple)
114 +{
115 +       return CE_Failure;
116 +}
117 +
118 +/************************************************************************/
119 +/*                            GetGDALDataset()                          */
120 +/************************************************************************/
121 +
122 +/**
123 + * \brief Get the GDALDataset object from AbstarctDataset.
124 + *
125 + * An AbstarctDataset encapsulating one GDALDataset. GetGDALDataset()
126 + * returns a GDALDatset object, which is used to fetch its information
127 + * through GDAL APIs.
128 + *
129 + * @return GDALDatset object.
130 + */
131 +
132 +GDALDataset* AbstractDataset::GetGDALDataset()
133 +{
134 +       return maptr_DS.get();
135 +}
136 +
137 +/************************************************************************/
138 +/*                            SetGDALDataset()                          */
139 +/************************************************************************/
140 +
141 +/**
142 + * \brief Set the GDALDataset object to AbstarctDataset.
143 + *
144 + * This is the virtual function for setting the abstract dataset by
145 + * calling GDAL functions.
146 + *
147 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
148 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
149 + *
150 + * @return CE_None on success or CE_Failure on failure.
151 + */
152 +
153 +CPLErr AbstractDataset::SetGDALDataset(const int isSimple)
154 +{
155 +       return CE_Failure;
156 +}
157 +
158 +/************************************************************************/
159 +/*                            GetNativeCRS()                            */
160 +/************************************************************************/
161 +
162 +/**
163 + * \brief Get the Native CRS of an AbstarctDataset.
164 + *
165 + * The method will return the CRS obejct, which is an OGRSpatialReference
166 + * object.
167 + *
168 + * @return an OGRSpatialReference object corresponding the native CRS of
169 + * coverage.
170 + */
171 +
172 +const OGRSpatialReference& AbstractDataset::GetNativeCRS()
173 +{
174 +       return mo_NativeCRS;
175 +}
176 +
177 +/************************************************************************/
178 +/*                            SetNativeCRS()                            */
179 +/************************************************************************/
180 +
181 +/**
182 + * \brief Set the Native CRS for an AbstarctDataset.
183 + *
184 + * The method will set the CRS for an AbstractDataset as an native CRS. For
185 + * some served coverage, GDAL could not tell its native CRS, this method
186 + * should be called to set its native CRS.
187 + *
188 + * @return CE_None on success or CE_Failure on failure.
189 + */
190 +
191 +CPLErr AbstractDataset::SetNativeCRS()
192 +{
193 +       char* wktStr = (char*) maptr_DS->GetProjectionRef();
194 +
195 +       if (wktStr && OGRERR_NONE == mo_NativeCRS.importFromWkt(&wktStr))
196 +               return CE_None;
197 +
198 +       return CE_Failure;
199 +}
200 +
201 +/************************************************************************/
202 +/*                            SetGeoTransform()                         */
203 +/************************************************************************/
204 +
205 +/**
206 + * \brief Set the affine GeoTransform matrix for a coverage.
207 + *
208 + * The method will set a GeoTransform matrix for a coverage. The method
209 + * GetGeoTransform of GDAL library will be called to get the matrix.
210 + *
211 + * @return CE_None on success or CE_Failure on failure.
212 + */
213 +
214 +CPLErr AbstractDataset::SetGeoTransform()
215 +{
216 +       if (CE_None != maptr_DS->GetGeoTransform(md_Geotransform))
217 +               return CE_Failure;
218 +
219 +       //Is the returned matrix correct? check the resolution values;
220 +       if(md_Geotransform[2] == 0 && md_Geotransform[5] == 0)
221 +               return CE_Failure;
222 +
223 +       mb_GeoTransformSet = TRUE;
224 +
225 +       return CE_None;
226 +}
227 +
228 +/************************************************************************/
229 +/*                            GetGeoTransform()                         */
230 +/************************************************************************/
231 +
232 +/**
233 + * \brief Fetch the affine transformation coefficients.
234 + *
235 + * Fetches the coefficients for transforming between pixel/line (P,L) raster
236 + * space, and projection coordinates (Xp,Yp) space.
237 + *
238 + * \code
239 + *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
240 + *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
241 + * \endcode
242 + *
243 + * In a north up image, padfTransform[1] is the pixel width, and
244 + * padfTransform[5] is the pixel height.  The upper left corner of the
245 + * upper left pixel is at position (padfTransform[0],padfTransform[3]).
246 + *
247 + * The default transform is (0,1,0,0,0,1) and should be returned even when
248 + * a CE_Failure error is returned, such as for formats that don't support
249 + * transformation to projection coordinates.
250 + *
251 + * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
252 + * OGC Grid Coverages pixel/line to projection transformation schemes.
253 + * Eventually this method will be depreciated in favour of a more general
254 + * scheme.
255 + *
256 + * @param geoTrans an existing six double buffer into which the
257 + * transformation will be placed.
258 + *
259 + * @return TRUE on success or FALSE on failure.
260 + */
261 +
262 +int AbstractDataset::GetGeoTransform(double geoTrans[])
263 +{
264 +       if (!mb_GeoTransformSet)//Geo-Transform not setup in each data driver, then set default.
265 +       {
266 +               geoTrans[0]=0.0;
267 +               geoTrans[0]=1.0;
268 +               geoTrans[0]=0.0;
269 +               geoTrans[0]=0.0;
270 +               geoTrans[0]=0.0;
271 +               geoTrans[0]=1.0;
272 +               return FALSE;
273 +       }
274 +
275 +       memcpy(geoTrans, md_Geotransform, sizeof(double) * 6);
276 +
277 +       return TRUE;
278 +}
279 +
280 +/************************************************************************/
281 +/*                            GetCoverageID()                           */
282 +/************************************************************************/
283 +
284 +/**
285 + * \brief Fetch the identifier of a coverage.
286 + *
287 + * The method will return the coverage identifier related to the abstarct
288 + * dataset. As to TRMM data, the coverage identifier likes:
289 + * TRMM:/Volumes/RAIDL1/GeoData/TRMM/TRMM_3B42_daily.2000.hdf:Daily
290 + *
291 + * As to MODIS data, the coverage identifier likes:
292 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MOD15A2/2007/MYD15A2.A2007241.h12v09.005.2007256053902.hdf":MOD_Grid_MOD15A2:Lai_1km
293 + *
294 + * @return the string of coverage identifier.
295 + */
296 +
297 +string AbstractDataset::GetCoverageID()
298 +{
299 +       return ms_CoverageID;
300 +}
301 +
302 +/************************************************************************/
303 +/*                            GetResourceFileName()                     */
304 +/************************************************************************/
305 +
306 +/**
307 + * \brief Fetch the resource file name of a coverage.
308 + *
309 + * The method will return the full path corresponding the file contained
310 + * coverage.
311 + *
312 + * @return the string of resource file path.
313 + */
314 +
315 +string AbstractDataset::GetResourceFileName()
316 +{
317 +       return ms_SrcFilename;
318 +}
319 +
320 +/************************************************************************/
321 +/*                            GetDatasetName()                          */
322 +/************************************************************************/
323 +
324 +/**
325 + * \brief Fetch the dataset name of a coverage.
326 + *
327 + * The method will return the data set name corresponding the file contained
328 + * coverage. For example, MOD09GQ data has the coverage identifier as following;
329 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
330 + *
331 + * sur_refl_b01_1 is seemed as the dataset name.
332 + *
333 + * @return the string of dataset name.
334 + */
335 +
336 +string AbstractDataset::GetDatasetName()
337 +{
338 +       return ms_DatasetName;
339 +}
340 +
341 +/************************************************************************/
342 +/*                            GetDataTypeName()                         */
343 +/************************************************************************/
344 +
345 +/**
346 + * \brief Fetch the dataset type name of a coverage.
347 + *
348 + * The method will return the data set name corresponding the file contained
349 + * coverage. For example, MOD09GQ data has the coverage identifier as following;
350 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
351 + *
352 + * MODIS_Grid_2D is seemed as the dataset type name.
353 + *
354 + * @return the string of dataset type name.
355 + */
356 +
357 +string AbstractDataset::GetDataTypeName()
358 +{
359 +       return ms_DataTypeName;
360 +}
361 +
362 +/************************************************************************/
363 +/*                            GetDataTypeName()                         */
364 +/************************************************************************/
365 +
366 +/**
367 + * \brief Fetch the dataset description of a coverage.
368 + *
369 + * The method will build a description for the coverage. The coverage
370 + * extent, dataset name, dataset type name will be contained in the
371 + * description,
372 + *
373 + * @return the string of dataset description.
374 + */
375 +
376 +string AbstractDataset::GetDatasetDescription()
377 +{
378 +       //[15x2030x1354] Band JPEG2000 (16-bit unsigned integer)
379 +       string rtnBuf;
380 +       int aiDimSizes[3];
381 +       int nBandCount = maptr_DS->GetRasterCount();
382 +       string pszString;
383 +       if (nBandCount > 1)
384 +       {
385 +               aiDimSizes[0] = nBandCount;
386 +               aiDimSizes[1] = GetImageYSize();
387 +               aiDimSizes[2] = GetImageXSize();
388 +               pszString = SPrintArray(GDT_UInt32, aiDimSizes, 3, "x");
389 +       }
390 +       else
391 +       {
392 +               aiDimSizes[0] = GetImageYSize();
393 +               aiDimSizes[1] = GetImageXSize();
394 +               pszString = SPrintArray(GDT_UInt32, aiDimSizes, 2, "x");
395 +       }
396 +
397 +       rtnBuf = "[" + pszString + "] " + ms_DatasetName + " " + ms_DataTypeName + " (" +
398 +                       GDALGetDataTypeName(maptr_DS->GetRasterBand(1)->GetRasterDataType()) + ")";
399 +
400 +       return rtnBuf;
401 +}
402 +
403 +/************************************************************************/
404 +/*                            GetNativeFormat()                         */
405 +/************************************************************************/
406 +
407 +/**
408 + * \brief Fetch the native format of a coverage.
409 + *
410 + * The method will return the native format of a coverage. GDAL API
411 + * GDALGetDriverShortName() will be called to generate the format.
412 + *
413 + * @return the string of dataset native format, in forms of GDAL Formats
414 + * Code. See http://gdal.org/formats_list.html for details.
415 + */
416 +
417 +string AbstractDataset::GetNativeFormat()
418 +{
419 +       return ms_NativeFormat;
420 +}
421 +
422 +/************************************************************************/
423 +/*                            IsbGeoTransformSet()                      */
424 +/************************************************************************/
425 +
426 +/**
427 + * \brief Determine whether set the affine geoTransform for a coverage.
428 + *
429 + * The method will return the status of the affine GeoTransform matrix.
430 + *
431 + * @return TRUE if set already or FALSE on failure..
432 + */
433 +
434 +int AbstractDataset::IsbGeoTransformSet()
435 +{
436 +       return mb_GeoTransformSet;
437 +}
438 +
439 +/************************************************************************/
440 +/*                            GetNativeBBox()                           */
441 +/************************************************************************/
442 +
443 +/**
444 + * \brief Fetch the bounding box of a coverage under the native CRS.
445 + *
446 + * The method will fetch the bounding box of the coverage under native CRS.
447 + * The sequence of values stored in array is: xmin, xmax, ymin, ymax
448 + *
449 + * @param bBox an existing four double buffer into which the
450 + * native bounding box values will be placed.
451 + */
452 +
453 +void AbstractDataset::GetNativeBBox(double bBox[])
454 +{
455 +       if (mb_GeoTransformSet)
456 +       {
457 +               bBox[0] = md_Geotransform[0];
458 +               bBox[1] = bBox[0] + GetImageXSize() * md_Geotransform[1];
459 +               bBox[3] = md_Geotransform[3];
460 +               bBox[2] = bBox[3] + GetImageYSize() * md_Geotransform[5];
461 +       }
462 +       else
463 +       {
464 +               bBox[0] = 0;
465 +               bBox[1] = maptr_DS->GetRasterXSize() - 1;
466 +               bBox[2] = 0;
467 +               bBox[3] = maptr_DS->GetRasterYSize() - 1;
468 +       }
469 +}
470 +
471 +/************************************************************************/
472 +/*                            GetGeoMinMax()                            */
473 +/************************************************************************/
474 +
475 +/**
476 + * \brief Fetch the bounding box of a coverage under EPSG:4326.
477 + *
478 + * The method will fetch the bounding box of the coverage under EPSG:4326
479 + * CRS. The sequence of values stored in array is: xmin, xmax, ymin, ymax
480 + *
481 + * @param bBox an existing four double buffer into which the geographic
482 + * bounding box values will be placed.
483 + *
484 + * @return CE_None on success or CE_Failure on failure.
485 + */
486 +
487 +CPLErr AbstractDataset::GetGeoMinMax(double geoMinMax[])
488 +{
489 +       if (!mb_GeoTransformSet)
490 +       {
491 +               SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
492 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to get Geo-BoundingBox coordinates");
493 +               return CE_Failure;
494 +       }
495 +
496 +       geoMinMax[0] = md_Geotransform[0];
497 +       geoMinMax[1] = geoMinMax[0] + GetImageXSize() * md_Geotransform[1];
498 +       geoMinMax[3] = md_Geotransform[3];
499 +       geoMinMax[2] = geoMinMax[3] + GetImageYSize() * md_Geotransform[5];
500 +
501 +
502 +       if (mo_NativeCRS.IsGeographic() || Find_Compare_SubStr(ms_DataTypeName, "MODIS"))//for modis data
503 +       {
504 +               geoMinMax[0] = (geoMinMax[0] >= -180.0) ? geoMinMax[0] : -180.0;
505 +               geoMinMax[1] = (geoMinMax[1] <=  180.0) ? geoMinMax[1] :  180.0;
506 +               geoMinMax[2] = (geoMinMax[2] >=  -90.0) ? geoMinMax[2] :  -90.0;
507 +               geoMinMax[3] = (geoMinMax[3] <=   90.0) ? geoMinMax[3] :   90.0;
508 +               return CE_None;
509 +       }
510 +
511 +       OGRSpatialReference oGeoSRS;
512 +       oGeoSRS.CopyGeogCSFrom(&mo_NativeCRS);
513 +
514 +       My2DPoint llPt(geoMinMax[0], geoMinMax[2]);
515 +       My2DPoint urPt(geoMinMax[1], geoMinMax[3]);
516 +       if (CE_None != bBox_transFormmate(mo_NativeCRS, oGeoSRS, llPt, urPt))
517 +       {
518 +               SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
519 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to transform bounding box coordinates to geographic coordinates.");
520 +               return CE_Failure;
521 +       }
522 +
523 +       geoMinMax[0] = llPt.mi_X;
524 +       geoMinMax[1] = urPt.mi_X;
525 +       geoMinMax[2] = llPt.mi_Y;
526 +       geoMinMax[3] = urPt.mi_Y;
527 +
528 +       return CE_None;
529 +}
530 +
531 +
532 +/************************************************************************/
533 +/*                            GetImageXSize()                           */
534 +/************************************************************************/
535 +
536 +/**
537 + * \brief Fetch coverage width in pixels.
538 + *
539 + * The method will return the width of coverage in pixels. GDAL API
540 + * GetRasterXSize() will be called to generate the width value.
541 + *
542 + * @return the width in pixels of raster bands in this coverage.
543 + */
544 +
545 +int AbstractDataset::GetImageXSize()
546 +{
547 +       return maptr_DS->GetRasterXSize();
548 +}
549 +
550 +/************************************************************************/
551 +/*                            GetImageYSize()                           */
552 +/************************************************************************/
553 +
554 +/**
555 + * \brief Fetch coverage height in pixels.
556 + *
557 + * The method will return the height of coverage in pixels. GDAL API
558 + * GetRasterYSize() will be called to generate the height value.
559 + *
560 + * @return the height in pixels of raster bands in this coverage.
561 + */
562 +int AbstractDataset::GetImageYSize()
563 +{
564 +       return maptr_DS->GetRasterYSize();
565 +}
566 +
567 +/************************************************************************/
568 +/*                        GetCoverageBeginTime()                        */
569 +/************************************************************************/
570 +
571 +/**
572 + * \brief Fetch the begin date/time of a coverage.
573 + *
574 + * The method will return the begin date/time of a coverage. For MODIS data,
575 + * each granule will cover a range of time; for TRMM data, the daily data
576 + * will cover a whole day, and monthly data will cover a whole month.
577 + *
578 + * @return the string of begin date/time corresponding to the coverage.
579 + */
580 +
581 +string AbstractDataset::GetCoverageBeginTime()
582 +{
583 +       return ms_CoverageBeginTime;
584 +}
585 +
586 +/************************************************************************/
587 +/*                        GetCoverageBeginTime()                        */
588 +/************************************************************************/
589 +
590 +/**
591 + * \brief Fetch the end date/time of a coverage.
592 + *
593 + * The method will return the end date/time of a coverage. For MODIS data,
594 + * each granule will cover a range of time; for TRMM data, the daily data
595 + * will cover a whole day, and monthly data will cover a whole month.
596 + *
597 + * @return the string of end date/time corresponding to the coverage.
598 + */
599 +
600 +string AbstractDataset::GetCoverageEndTime()
601 +{
602 +       return ms_CoverageEndTime;
603 +}
604 +
605 +/************************************************************************/
606 +/*                        getCoverageSubType()                          */
607 +/************************************************************************/
608 +
609 +/**
610 + * \brief Fetch the coverage type.
611 + *
612 + * The method will return the type of the coverage, such as
613 + * "ReferenceableDataset" and "RectifiedDataset".
614 + *
615 + * @return the string of coverage type.
616 + */
617 +
618 +string AbstractDataset::GetCoverageSubType()
619 +{
620 +       return ms_CoverageSubType;
621 +}
622 +
623 +/************************************************************************/
624 +/*                        getFieldQuantityDef()                         */
625 +/************************************************************************/
626 +
627 +/**
628 + * \brief Fetch the field units of a coverage.
629 + *
630 + * The method will return the field units of coverage. For example to
631 + * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, units equals
632 + * to reflectance.
633 + *
634 + * @return the string of coverage field units.
635 + */
636 +
637 +string AbstractDataset::GetFieldQuantityDef()
638 +{
639 +       return ms_FieldQuantityDef;
640 +}
641 +
642 +/************************************************************************/
643 +/*                        GetAllowValues()                              */
644 +/************************************************************************/
645 +
646 +/**
647 + * \brief Fetch the allow values of a coverage.
648 + *
649 + * The method will return the valid range of a coverage. For example to
650 + * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, valid_range
651 + * equals to (-100, 16000).
652 + *
653 + * @return the string of valid range of a coverage, in the forms of "min, max".
654 + */
655 +
656 +string AbstractDataset::GetAllowValues()
657 +{
658 +       return ms_AllowRanges;
659 +}
660 +
661 +/************************************************************************/
662 +/*                        GetISO19115Metadata()                         */
663 +/************************************************************************/
664 +
665 +/**
666 + * \brief Fetch the coverage metadata which is compliant to ISO 19115:2003
667 + * - GeoGraphic information -- Metadata; and ISO 19115(2):2009 - GeoGraphic
668 + * information -- Metadata -- Part 2.
669 + *
670 + * The method will return the metadata of a coverage based on ISO 19115
671 + * and ISO 19115(2).
672 + *
673 + * ISO 19115:2003 defines the schema required for
674 + * describing geographic information and services. It provides information
675 + * about the identification, the extent, the quality, the spatial and temporal
676 + * schema, spatial reference, and distribution of digital geographic data.
677 + *
678 + * ISO 19115-2:2009 extends the existing geographic metadata standard by
679 + * defining the schema required for describing imagery and gridded data.
680 + * It provides information about the properties of the measuring equipment
681 + * used to acquire the data, the geometry of the measuring process employed
682 + * by the equipment, and the production process used to digitize the raw data.
683 + * This extension deals with metadata needed to describe the derivation of
684 + * geographic information from raw data, including the properties of the
685 + * measuring system, and the numerical methods and computational procedures
686 + * used in the derivation. The metadata required to address coverage data in
687 + * general is addressed sufficiently in the general part of ISO 19115.
688 + *
689 + * @return the string of metadata of a coverage.
690 + */
691 +
692 +string AbstractDataset::GetISO19115Metadata()
693 +{
694 +       return ms_ISO19115Metadata;
695 +}
696 +
697 +/************************************************************************/
698 +/*                        GetCoverageArchiveTime()                      */
699 +/************************************************************************/
700 +
701 +/**
702 + * \brief Fetch the archive date/time of this dataset.
703 + *
704 + * The method will return the archive date/time of dataset (granule).
705 + *
706 + * @return The string of archive date/time.
707 + */
708 +
709 +string AbstractDataset::GetCoverageArchiveTime()
710 +{
711 +       return ms_CoverageArchiveTime;
712 +}
713 +
714 +/************************************************************************/
715 +/*                        GetCoveragePlatform()                         */
716 +/************************************************************************/
717 +
718 +/**
719 + * \brief Fetch the platform name of this dataset.
720 + *
721 + * The method will return the platform name of dataset (granule).
722 + *
723 + * @return The string of platform name.
724 + */
725 +
726 +string AbstractDataset::GetCoveragePlatform()
727 +{
728 +       return ms_CoveragePlatform;
729 +}
730 +
731 +/************************************************************************/
732 +/*                        GetCoverageInstrument()                       */
733 +/************************************************************************/
734 +
735 +/**
736 + * \brief Fetch the instrument name of this dataset.
737 + *
738 + * The method will return the instrument name of dataset (granule).
739 + *
740 + * @return The string of instrument name.
741 + */
742 +
743 +string AbstractDataset::GetCoverageInstrument()
744 +{
745 +       return ms_CoverageInstrument;
746 +}
747 +
748 +/************************************************************************/
749 +/*                        GetCoverageInstrument()                       */
750 +/************************************************************************/
751 +
752 +/**
753 + * \brief Fetch the sensor name of this dataset.
754 + *
755 + * The method will return the sensor name of dataset (granule).
756 + *
757 + * @return The string of sensor name.
758 + */
759 +
760 +string AbstractDataset::GetCoverageSensor()
761 +{
762 +       return ms_CoverageSensor;
763 +}
764 +
765 +/************************************************************************/
766 +/*                        GetImageBandCount()                           */
767 +/************************************************************************/
768 +
769 +/**
770 + * \brief Fetch the number of raster bands on this dataset.
771 + *
772 + * The method will return the number of raster bands on this dataset. GDAL
773 + * API GetRasterCount() will be called to get the count number.
774 + *
775 + * @return the number of raster bands on this dataset.
776 + */
777 +
778 +int AbstractDataset::GetImageBandCount()
779 +{
780 +       return maptr_DS->GetRasterCount();
781 +}
782 +
783 +/************************************************************************/
784 +/*                        getMissingValue()                             */
785 +/************************************************************************/
786 +
787 +/**
788 + * \brief Fetch the filled value (missing value) of a coverage.
789 + *
790 + * The method will return the filled value of a coverage.
791 + *
792 + * @return the value of filled value of a coverage.
793 + */
794 +
795 +const double& AbstractDataset::GetMissingValue()
796 +{
797 +       return md_MissingValue;
798 +}
799 +
800 +/************************************************************************/
801 +/*                        GetProjectionRef()                            */
802 +/************************************************************************/
803 +
804 +/**
805 + * \brief Fetch the native projection reference of a coverage.
806 + *
807 + * The method will return the the native projection reference of a coverage.
808 + *
809 + * @return the string of the native projection reference of a coverage.
810 + */
811 +
812 +string AbstractDataset::GetProjectionRef()
813 +{
814 +       char* pszProjection = NULL;
815 +       mo_NativeCRS.exportToWkt(&pszProjection);
816 +       string tmpStr = pszProjection;
817 +       CPLFree(pszProjection);
818 +
819 +       return tmpStr;
820 +}
821 +
822 +/************************************************************************/
823 +/*                        SetMetaDataList()                             */
824 +/************************************************************************/
825 +
826 +/**
827 + * \brief Set the metadata list for this coverage based on dataset object.
828 + *
829 + * The method will set the metadata list for the coverage based on its
830 + * corresponding GDALDataset object. Will be implemented in the subclasses
831 + * of AbstractDataset.
832 + *
833 + * @param hSrc the GDALDataset object corresponding to coverage.
834 + *
835 + * @return CE_Failure.
836 + */
837 +
838 +CPLErr AbstractDataset::SetMetaDataList(GDALDataset* hSrc)
839 +{
840 +       return CE_Failure;
841 +}
842 +
843 +/************************************************************************/
844 +/*                        GetMetaDataList()                             */
845 +/************************************************************************/
846 +
847 +/**
848 + * \brief Fetch the metadata list for this coverage.
849 + *
850 + * The method will return the metadata list for the coverage.
851 + *
852 + * @return the list of metadate.
853 + */
854 +
855 +vector<string> AbstractDataset::GetMetaDataList()
856 +{
857 +       return mv_MetaDataList;
858 +}
859 +
860 +/************************************************************************/
861 +/*                            GetBandList()                             */
862 +/************************************************************************/
863 +
864 +/**
865 + * \brief Fetch the contained band list of request coverage.
866 + *
867 + * The method will return the contained band list of request coverage.
868 + *
869 + * @return the band array.
870 + */
871 +
872 +vector<int> AbstractDataset::GetBandList()
873 +{
874 +       return mv_BandList;
875 +}
876 +
877 +/************************************************************************/
878 +/*                        getNativeCRS_URN()                            */
879 +/************************************************************************/
880 +
881 +/**
882 + * \brief Fetch the native CRS code of coverage.
883 + *
884 + * The method will return the native CRS code of coverage.
885 + *
886 + * @return the string of the URN for native CRS of coverage.
887 + */
888 +
889 +string AbstractDataset::GetNativeCRS_URN()
890 +{
891 +       string urn;
892 +
893 +       if (mo_NativeCRS.IsProjected())
894 +       {
895 +               const char* nativeAuthorityName =
896 +                               mo_NativeCRS.GetAuthorityName("PROJCS");
897 +               const char* nativeAuthorityCode =
898 +                               mo_NativeCRS.GetAuthorityCode("PROJCS");
899 +
900 +               urn = "urn:ogc:def:crs:";
901 +
902 +               if (nativeAuthorityName && (EQUAL(nativeAuthorityName,"EPSG")
903 +                               || EQUAL(nativeAuthorityName,"OGP")
904 +                               || EQUAL(nativeAuthorityName,"OGC")))
905 +                       urn += (string) nativeAuthorityName + (string) ":6.3:";
906 +               else
907 +                       urn += "CSISS:0.0:";
908 +
909 +               if (nativeAuthorityCode)
910 +                       urn += (string) nativeAuthorityCode;
911 +               else
912 +                       urn += "80000000";
913 +       }
914 +       else if (mo_NativeCRS.IsGeographic())
915 +       {
916 +               const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
917 +               const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
918 +
919 +               urn = "urn:ogc:def:crs:";
920 +               if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
921 +                               || EQUAL(geoAuthorityName,"OGP")
922 +                               || EQUAL(geoAuthorityName,"OGC")))
923 +                       urn += (string) geoAuthorityName + (string) ":6.3:";
924 +               else
925 +                       urn += "CSISS:0.0:";
926 +
927 +               if (geoAuthorityCode)
928 +                       urn += (string) geoAuthorityCode;
929 +               else
930 +                       urn += "70000000";
931 +       }
932 +       else
933 +               urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
934 +
935 +       return urn;
936 +}
937 +
938 +/************************************************************************/
939 +/*                        GetGeoCRS_URN()                               */
940 +/************************************************************************/
941 +
942 +/**
943 + * \brief Fetch the Geographic CRS code of coverage.
944 + *
945 + * The method will return the Geographic CRS code of coverage.
946 + *
947 + * @return the URN for Geographic CRS of coverage.
948 + */
949 +
950 +string AbstractDataset::GetGeoCRS_URN()
951 +{
952 +       string urn;
953 +
954 +       if (mo_NativeCRS.IsProjected() || mo_NativeCRS.IsGeographic())
955 +       {
956 +               const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
957 +               const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
958 +
959 +               urn = "urn:ogc:def:crs:";
960 +               if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
961 +                               || EQUAL(geoAuthorityName,"OGP")
962 +                               || EQUAL(geoAuthorityName,"OGC")))
963 +                       urn += (string) geoAuthorityName + (string) ":6.3:";
964 +               else
965 +                       urn += "CSISS:0.0:";
966 +
967 +               if (geoAuthorityCode)
968 +                       urn += (string) geoAuthorityCode;
969 +               else
970 +                       urn += "70000000";
971 +
972 +       }
973 +       else
974 +               urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
975 +
976 +       return urn;
977 +}
978 +
979 +/************************************************************************/
980 +/*                        IsCrossingIDL()                               */
981 +/************************************************************************/
982 +
983 +/**
984 + * \brief Determine whether the extend of coverage cross the International
985 + * Date Line (IDL).
986 + *
987 + * The method will return the status of whether the extend of coverage
988 + * cross the International Date Line (IDL).
989 + *
990 + * @return the TRUE of the coverage extent cross the IDL, otherwise FALSE.
991 + */
992 +
993 +int AbstractDataset::IsCrossingIDL()
994 +{
995 +       double bboxArray[4];
996 +       GetNativeBBox(bboxArray);
997 +
998 +       OGRSpatialReference latlonSRS;
999 +       latlonSRS.SetWellKnownGeogCS("WGS84");
1000 +       My2DPoint llPtex(bboxArray[0], bboxArray[2]);
1001 +       My2DPoint urPtex(bboxArray[1], bboxArray[3]);
1002 +       bBox_transFormmate(mo_NativeCRS, latlonSRS, llPtex, urPtex);
1003 +
1004 +       int bCrossCenter = false;
1005 +       if(urPtex.mi_X < 0 && llPtex.mi_X > 0)
1006 +               bCrossCenter = true;
1007 +
1008 +       return bCrossCenter;
1009 +}
1010 +
1011 +/************************************************************************/
1012 +/*                        GetSuggestedWarpResolution()                  */
1013 +/************************************************************************/
1014 +
1015 +/**
1016 + * \brief Get the suggested warp option, method 1.
1017 + *
1018 + * @return CE_Failure if an error occurs, otherwise CE_None.
1019 + */
1020 +
1021 +CPLErr AbstractDataset::GetSuggestedWarpResolution(    OGRSpatialReference& dstCRS,
1022 +                                                                                                       double adfDstGeoTransform[],
1023 +                                                                                                       int &nPixels,
1024 +                                                                                                       int &nLines)
1025 +{
1026 +       if (!dstCRS.IsProjected() && !dstCRS.IsGeographic())
1027 +       {
1028 +               adfDstGeoTransform[0] = 0;
1029 +               adfDstGeoTransform[1] = 1;
1030 +               adfDstGeoTransform[2] = 0;
1031 +               adfDstGeoTransform[3] = 0;
1032 +               adfDstGeoTransform[4] = 0;
1033 +               adfDstGeoTransform[5] = 1;
1034 +
1035 +               nPixels = GetImageXSize();
1036 +               nLines = GetImageYSize();
1037 +
1038 +       }
1039 +       else if (dstCRS.IsSame(&mo_NativeCRS))
1040 +       {
1041 +               memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
1042 +               nPixels = GetImageXSize();
1043 +               nLines = GetImageYSize();
1044 +       }
1045 +       else
1046 +       {
1047 +               char *pszDstWKT;
1048 +               dstCRS.exportToWkt(&pszDstWKT);
1049 +               char *pszSrcWKT;
1050 +               mo_NativeCRS.exportToWkt(&pszSrcWKT);
1051 +
1052 +               void *hTransformArg = GDALCreateGenImgProjTransformer(maptr_DS.get(),
1053 +                               (const char*) pszSrcWKT, NULL, (const char*) pszDstWKT, TRUE, 1000.0, 0);
1054 +               OGRFree(pszDstWKT);
1055 +               OGRFree(pszSrcWKT);
1056 +               if (hTransformArg == NULL)
1057 +               {
1058 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
1059 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create GDAL GenImgProjTransformer.");
1060 +
1061 +                       return CE_Failure;
1062 +               }
1063 +               /* -------------------------------------------------------------------- */
1064 +               /*      Get approximate output definition.                              */
1065 +               /* -------------------------------------------------------------------- */
1066 +               if (GDALSuggestedWarpOutput(maptr_DS.get(), GDALGenImgProjTransform,
1067 +                               hTransformArg, adfDstGeoTransform, &nPixels, &nLines) != CE_None)
1068 +               {
1069 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
1070 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Computing Output Resolution.");
1071 +
1072 +                       return CE_Failure;
1073 +               }
1074 +
1075 +               GDALDestroyGenImgProjTransformer(hTransformArg);
1076 +       }
1077 +
1078 +       return CE_None;
1079 +}
1080 +
1081 +/************************************************************************/
1082 +/*                        GetSuggestedWarpResolution2()                 */
1083 +/************************************************************************/
1084 +
1085 +/**
1086 + * \brief Get the suggested warp option, method 2.
1087 + *
1088 + * @return CE_Failure if an error occurs, otherwise CE_None.
1089 + */
1090 +
1091 +CPLErr AbstractDataset::GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS,
1092 +                                                                                                       double adfDstGeoTransform[],
1093 +                                                                                                       int &nPixels,
1094 +                                                                                                       int &nLines)
1095 +{
1096 +       if (dstCRS.IsLocal())
1097 +       {
1098 +               adfDstGeoTransform[0] = 0;
1099 +               adfDstGeoTransform[1] = 1;
1100 +               adfDstGeoTransform[2] = 0;
1101 +               adfDstGeoTransform[3] = 0;
1102 +               adfDstGeoTransform[4] = 0;
1103 +               adfDstGeoTransform[5] = 1;
1104 +
1105 +               nPixels = GetImageXSize();
1106 +               nLines = GetImageYSize();
1107 +       }
1108 +       else if (dstCRS.IsSame(&mo_NativeCRS))
1109 +       {
1110 +               memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
1111 +               nPixels = GetImageXSize();
1112 +               nLines = GetImageYSize();
1113 +       }
1114 +       else
1115 +       {
1116 +               double bboxArray[4];
1117 +               GetNativeBBox(bboxArray);
1118 +
1119 +               My2DPoint llPt(bboxArray[0], bboxArray[2]);
1120 +               My2DPoint urPt(bboxArray[1], bboxArray[3]);
1121 +               if (CE_None != bBox_transFormmate(mo_NativeCRS, dstCRS, llPt, urPt))
1122 +               {
1123 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution2()");
1124 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform bounding box Coordinate.");
1125 +                       return CE_Failure;
1126 +               }
1127 +
1128 +               double xRes, yRes;
1129 +               if(IsCrossingIDL())
1130 +               {
1131 +                       yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
1132 +                       xRes = fabs((llPt.mi_X - urPt.mi_X) / GetImageXSize());
1133 +                       nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
1134 +                       nPixels = fabs((llPt.mi_X - urPt.mi_X) / xRes + 0.5);
1135 +               }else
1136 +               {
1137 +                       xRes = (urPt.mi_X - llPt.mi_X) / GetImageXSize();
1138 +                       yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
1139 +                       nPixels = (urPt.mi_X - llPt.mi_X) / xRes + 0.5;
1140 +                       nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
1141 +               }
1142 +
1143 +               xRes = MIN(xRes,yRes);
1144 +               yRes = MIN(xRes,yRes);
1145 +
1146 +               adfDstGeoTransform[0] = llPt.mi_X;
1147 +               adfDstGeoTransform[1] = xRes;
1148 +               adfDstGeoTransform[2] = 0;
1149 +               adfDstGeoTransform[3] = urPt.mi_Y;
1150 +               adfDstGeoTransform[4] = 0;
1151 +               adfDstGeoTransform[5] = -yRes;
1152 +       }
1153 +
1154 +       return CE_None;
1155 +}
1156 +
1157 +/************************************************************************/
1158 +/*                           DatasetWarper()                            */
1159 +/************************************************************************/
1160 +
1161 +/**
1162 + * Wrap the dataset to a GDALDataset object based on input parameters.
1163 + *
1164 + * @return the warpped GDALDataset object.
1165 + */
1166 +/************************************************************************/
1167 +/*                        DatasetWarper()                               */
1168 +/************************************************************************/
1169 +
1170 +/**
1171 + * \brief Wrap the dataset to a GDALDataset object based on input parameters.
1172 + *
1173 + * @return GDALDatset object.
1174 + */
1175 +
1176 +GDALDataset* AbstractDataset::DatasetWarper(int& IsRefDS,
1177 +                                                                                       OGRSpatialReference& dstCRS,
1178 +                                                                                       int& iDstRasterXsize,
1179 +                                                                                       int& iDstRasterYsize,
1180 +                                                                                       double pDstGeoTransform[],
1181 +                                                                                       GDALResampleAlg eResampleAlg)
1182 +{
1183 +       OGRSpatialReference locCRS=dstCRS;
1184 +       if (dstCRS.IsLocal())
1185 +               locCRS=mo_NativeCRS;
1186 +
1187 +       if((mo_NativeCRS.IsSame(&locCRS) &&
1188 +                       iDstRasterXsize == maptr_DS->GetRasterXSize() &&
1189 +                       iDstRasterYsize == maptr_DS->GetRasterYSize())&&
1190 +                       CPLIsEqual(md_Geotransform[0],pDstGeoTransform[0])&&
1191 +                       CPLIsEqual(md_Geotransform[1],pDstGeoTransform[1])&&
1192 +                       CPLIsEqual(md_Geotransform[3],pDstGeoTransform[3])&&
1193 +                       CPLIsEqual(md_Geotransform[5],pDstGeoTransform[5]))
1194 +       {
1195 +               IsRefDS = TRUE;
1196 +               return maptr_DS.get();
1197 +       }
1198 +
1199 +       char *sDstCRS_WKT;
1200 +       locCRS.exportToWkt(&sDstCRS_WKT);
1201 +
1202 +       /* Create a memory data-set for re-projection */
1203 +       GDALDriverH poDriver = GDALGetDriverByName("MEM");
1204 +
1205 +       int nBand = maptr_DS->GetRasterCount();
1206 +       GDALDataset* hMemDS = (GDALDataset*) GDALCreate(poDriver, "", iDstRasterXsize,
1207 +                       iDstRasterYsize, nBand, GDALGetRasterDataType(maptr_DS->GetRasterBand(1)), NULL);
1208 +       if (NULL == hMemDS)
1209 +       {
1210 +               GDALClose(poDriver);
1211 +               OGRFree(sDstCRS_WKT);
1212 +               return NULL;
1213 +       }
1214 +
1215 +       hMemDS->SetProjection(sDstCRS_WKT);
1216 +       hMemDS->SetGeoTransform(pDstGeoTransform);
1217 +
1218 +       for (int i = 1; i <= nBand; i++)
1219 +       {
1220 +               hMemDS->GetRasterBand(i)->SetNoDataValue(md_MissingValue);
1221 +       }
1222 +
1223 +       /* -------------------------------------------------------------------- */
1224 +       /*      Perform the re-projection.                                       */
1225 +       /* -------------------------------------------------------------------- */
1226 +       char *srcWKT;
1227 +       mo_NativeCRS.exportToWkt(&srcWKT);
1228 +       if (CE_None != GDALReprojectImage(maptr_DS.get(), srcWKT, hMemDS,
1229 +                       sDstCRS_WKT, eResampleAlg, 0, 0.125, NULL, NULL, NULL))
1230 +       {
1231 +               GDALClose(poDriver);
1232 +               GDALClose(GDALDatasetH(hMemDS));
1233 +               OGRFree(sDstCRS_WKT);
1234 +               OGRFree(srcWKT);
1235 +               return NULL;
1236 +       }
1237 +       IsRefDS = FALSE;
1238 +       OGRFree(sDstCRS_WKT);
1239 +       OGRFree(srcWKT);
1240 +
1241 +       return hMemDS;
1242 +}
1243 diff -Nur bes-3.12.0/functions.orig/swath2grid/AbstractDataset.h bes-3.12.0/functions/swath2grid/AbstractDataset.h
1244 --- bes-3.12.0/functions.orig/swath2grid/AbstractDataset.h      1970-01-01 01:00:00.000000000 +0100
1245 +++ bes-3.12.0/functions/swath2grid/AbstractDataset.h   2014-03-03 15:47:38.050232928 +0100
1246 @@ -0,0 +1,150 @@
1247 +/******************************************************************************
1248 + * $Id: AbstractDataset.h 2011-07-19 16:24:00Z $
1249 + *
1250 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
1251 + *                      for Earth Observation: Open Source Reference Implementation
1252 + * Purpose:  AbstractDataset class definition
1253 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
1254 + *
1255 + ******************************************************************************
1256 + * * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
1257 + *
1258 + * Permission is hereby granted, free of charge, to any person obtaining a
1259 + * copy of this software and associated documentation files (the "Software"),
1260 + * to deal in the Software without restriction, including without limitation
1261 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1262 + * and/or sell copies of the Software, and to permit persons to whom the
1263 + * Software is furnished to do so, subject to the following conditions:
1264 + *
1265 + * The above copyright notice and this permission notice shall be included
1266 + * in all copies or substantial portions of the Software.
1267 + *
1268 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1269 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1270 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1271 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1272 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1273 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1274 + * DEALINGS IN THE SOFTWARE.
1275 + ****************************************************************************/
1276 +
1277 +#ifndef ABSTRACTDATASET_H_
1278 +#define ABSTRACTDATASET_H_
1279 +
1280 +#include <vector>
1281 +#include <memory>
1282 +
1283 +#include <gdal.h>
1284 +#include <gdal_priv.h>
1285 +#include <gdalwarper.h>
1286 +#include <ogrsf_frmts.h>
1287 +#include <ogr_spatialref.h>
1288 +#include <cpl_conv.h>
1289 +#include <cpl_minixml.h>
1290 +#include <vrtdataset.h>
1291 +
1292 +#include "wcsUtil.h"
1293 +
1294 +using namespace std;
1295 +
1296 +/* ******************************************************************** */
1297 +/*                             AbstractDataset                          */
1298 +/* ******************************************************************** */
1299 +
1300 +//! Abstract dataset model definition. Based on GDAL dataset model.
1301 +class AbstractDataset {
1302 +
1303 +protected:
1304 +    auto_ptr<GDALDataset> maptr_DS;
1305 +
1306 +    // Coverage Information Related
1307 +    string ms_CoverageID;
1308 +    string ms_CoverageBeginTime;
1309 +    string ms_CoverageEndTime;
1310 +    string ms_CoverageSubType;
1311 +    string ms_CoverageArchiveTime;
1312 +    string ms_CoveragePlatform;
1313 +    string ms_CoverageInstrument;
1314 +    string ms_CoverageSensor;
1315 +    string ms_SrcFilename;
1316 +    string ms_DatasetName;
1317 +    string ms_DataTypeName;
1318 +    string ms_NativeFormat;
1319 +    string ms_FieldQuantityDef;
1320 +    string ms_AllowRanges;
1321 +    string ms_ISO19115Metadata;
1322 +
1323 +    vector<int> mv_BandList;
1324 +    vector<string> mv_MetaDataList;
1325 +
1326 +    double md_Geotransform[6];
1327 +    double md_GeoMinMax[4]; // Order: xmin, xmax, ymin, ymax
1328 +    double md_MissingValue;
1329 +
1330 +    int mb_GeoTransformSet;
1331 +    int mb_IsVirtualDS;
1332 +
1333 +    OGRSpatialReference mo_NativeCRS;
1334 +
1335 +protected:
1336 +    AbstractDataset();
1337 +    virtual CPLErr SetNativeCRS();
1338 +    virtual CPLErr SetGeoTransform();
1339 +    virtual CPLErr SetGDALDataset(const int isSimple = 0);
1340 +    virtual CPLErr SetMetaDataList(GDALDataset*);
1341 +
1342 +public:
1343 +    AbstractDataset(const string&, vector<int> &);
1344 +    virtual ~AbstractDataset();
1345 +
1346 +    GDALDataset* GetGDALDataset();
1347 +
1348 +    // Virtual Functions Definition
1349 +    virtual CPLErr InitialDataset(const int isSimple = 0);
1350 +
1351 +    // Fetch Function Related
1352 +    const OGRSpatialReference& GetNativeCRS();
1353 +    const double& GetMissingValue();
1354 +    int GetGeoTransform(double geoTrans[]);
1355 +    vector<string> GetMetaDataList();
1356 +    vector<int> GetBandList();
1357 +    void GetNativeBBox(double bBox[]);
1358 +    CPLErr GetGeoMinMax(double geoMinMax[]);
1359 +
1360 +    int GetImageBandCount();
1361 +    int GetImageXSize();
1362 +    int GetImageYSize();
1363 +    string GetResourceFileName();
1364 +    string GetDatasetName();
1365 +    string GetDataTypeName();
1366 +    string GetNativeFormat();
1367 +    string GetCoverageID();
1368 +    string GetDatasetDescription();
1369 +    string GetNativeCRS_URN();
1370 +    string GetGeoCRS_URN();
1371 +    string GetProjectionRef();
1372 +    string GetCoverageBeginTime();
1373 +    string GetCoverageEndTime();
1374 +    string GetCoverageSubType();
1375 +    string GetFieldQuantityDef();
1376 +    string GetAllowValues();
1377 +    string GetISO19115Metadata();
1378 +    string GetCoverageArchiveTime();
1379 +    string GetCoveragePlatform();
1380 +    string GetCoverageInstrument();
1381 +    string GetCoverageSensor();
1382 +
1383 +    // Fetch Variables Status Related
1384 +    int IsbGeoTransformSet();
1385 +    int IsCrossingIDL();
1386 +
1387 +    CPLErr GetSuggestedWarpResolution(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
1388 +                                      int &nLines);
1389 +    CPLErr GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
1390 +                                       int &nLines);
1391 +
1392 +    GDALDataset* DatasetWarper(int& IsRefDS, OGRSpatialReference& dstCRS, int& iDstRasterXsize, int& iDstRasterYsize,
1393 +                               double pDstGeoTransform[], GDALResampleAlg eResampleAlg = GRA_NearestNeighbour);
1394 +};
1395 +
1396 +#endif /*ABSTRACTDATASET_H_*/
1397 diff -Nur bes-3.12.0/functions.orig/swath2grid/airs.nc.0.data.bescmd bes-3.12.0/functions/swath2grid/airs.nc.0.data.bescmd
1398 --- bes-3.12.0/functions.orig/swath2grid/airs.nc.0.data.bescmd  1970-01-01 01:00:00.000000000 +0100
1399 +++ bes-3.12.0/functions/swath2grid/airs.nc.0.data.bescmd       2014-03-03 15:47:38.050232928 +0100
1400 @@ -0,0 +1,13 @@
1401 +<?xml version="1.0" encoding="UTF-8"?>
1402 +<request reqID ="some_unique_value" >
1403 +    <setContext name="dap_format">dap2</setContext>
1404 +    <setContext name="xdap_accept">3.3</setContext>
1405 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
1406 +    <define name="d">
1407 +          <container name="c">
1408 +              <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
1409 +          </container>
1410 +    </define>
1411 +    <get type="dods" definition="d"/>
1412 +</request>
1413 +
1414 diff -Nur bes-3.12.0/functions.orig/swath2grid/airs.nc.0.ddx.bescmd bes-3.12.0/functions/swath2grid/airs.nc.0.ddx.bescmd
1415 --- bes-3.12.0/functions.orig/swath2grid/airs.nc.0.ddx.bescmd   1970-01-01 01:00:00.000000000 +0100
1416 +++ bes-3.12.0/functions/swath2grid/airs.nc.0.ddx.bescmd        2014-03-03 15:47:38.053566262 +0100
1417 @@ -0,0 +1,13 @@
1418 +<?xml version="1.0" encoding="UTF-8"?>
1419 +<request reqID ="some_unique_value" >
1420 +    <setContext name="dap_format">dap2</setContext>
1421 +    <setContext name="xdap_accept">3.3</setContext>
1422 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
1423 +    <define name="d">
1424 +          <container name="c">
1425 +              <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
1426 +          </container>
1427 +    </define>
1428 +    <get type="das" definition="d"/>
1429 +</request>
1430 +
1431 diff -Nur bes-3.12.0/functions.orig/swath2grid/airs.nc.1.err.bescmd bes-3.12.0/functions/swath2grid/airs.nc.1.err.bescmd
1432 --- bes-3.12.0/functions.orig/swath2grid/airs.nc.1.err.bescmd   1970-01-01 01:00:00.000000000 +0100
1433 +++ bes-3.12.0/functions/swath2grid/airs.nc.1.err.bescmd        2014-03-03 15:47:38.043566262 +0100
1434 @@ -0,0 +1,13 @@
1435 +<?xml version="1.0" encoding="UTF-8"?>
1436 +<request reqID ="some_unique_value" >
1437 +    <setContext name="dap_format">dap2</setContext>
1438 +    <setContext name="xdap_accept">3.3</setContext>
1439 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
1440 +    <define name="d">
1441 +          <container name="c">
1442 +              <constraint>swath2grid()</constraint>
1443 +          </container>
1444 +    </define>
1445 +    <get type="dods" definition="d"/>
1446 +</request>
1447 +
1448 diff -Nur bes-3.12.0/functions.orig/swath2grid/bes.conf.in bes-3.12.0/functions/swath2grid/bes.conf.in
1449 --- bes-3.12.0/functions.orig/swath2grid/bes.conf.in    1970-01-01 01:00:00.000000000 +0100
1450 +++ bes-3.12.0/functions/swath2grid/bes.conf.in 2014-03-03 15:47:38.050232928 +0100
1451 @@ -0,0 +1,48 @@
1452 +BES.ServerAdministrator=root@null.dev
1453 +
1454 +BES.User=user_name
1455 +BES.Group=group_name
1456 +
1457 +BES.LogName=./bes.log
1458 +BES.LogVerbose=no
1459 +
1460 +BES.modules=dap,cmd,nc,h4,fong,fonc
1461 +BES.module.dap=@libdir@/bes/libdap_module.so
1462 +BES.module.cmd=@libdir@/bes/libdap_xml_module.so
1463 +
1464 +BES.module.nc=@libdir@/bes/libnc_module.so
1465 +BES.module.h4=@libdir@/bes/libhdf4_module.so
1466 +
1467 +BES.module.fong=@libdir@/bes/libfong_module.so
1468 +BES.module.fonc=@libdir@/bes/libfonc_module.so
1469 +
1470 +BES.Catalog.catalog.RootDirectory=@abs_top_srcdir@
1471 +BES.Data.RootDirectory=/dev/null
1472 +
1473 +BES.Catalog.catalog.TypeMatch=nc:.*.nc(.bz2|.gz|.Z)?$;h4:.*.(hdf|HDF|eos)(.bz2|.gz|.Z)?$;
1474 +
1475 +BES.Catalog.catalog.Include=;
1476 +BES.Catalog.catalog.Exclude=^\..*;
1477 +
1478 +BES.FollowSymLinks=No
1479 +BES.Catalog.catalog.FollowSymLinks=No
1480 +
1481 +BES.ServerPort=10002
1482 +
1483 +BES.CacheDir=/tmp
1484 +BES.CachePrefix=bes_cache
1485 +BES.CacheSize=500
1486 +
1487 +BES.Container.Persistence=strict
1488 +
1489 +BES.Memory.GlobalArea.EmergencyPoolSize=1
1490 +BES.Memory.GlobalArea.MaximumHeapSize=20
1491 +BES.Memory.GlobalArea.Verbose=no
1492 +BES.Memory.GlobalArea.ControlHeap=no
1493 +
1494 +BES.ProcessManagerMethod=multiple
1495 +
1496 +BES.DefaultResponseMethod=POST
1497 +
1498 +FONg.TempDirectory=@abs_top_srcdir@/tests
1499 +
1500 diff -Nur bes-3.12.0/functions.orig/swath2grid/BoundingBox.cpp bes-3.12.0/functions/swath2grid/BoundingBox.cpp
1501 --- bes-3.12.0/functions.orig/swath2grid/BoundingBox.cpp        1970-01-01 01:00:00.000000000 +0100
1502 +++ bes-3.12.0/functions/swath2grid/BoundingBox.cpp     2014-03-03 15:47:38.050232928 +0100
1503 @@ -0,0 +1,360 @@
1504 +/******************************************************************************
1505 + * $Id: BoundingBox.cpp 2011-07-19 16:24:00Z $
1506 + *
1507 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
1508 + *                      for Earth Observation: Open Source Reference Implementation
1509 + * Purpose:  BoundingBox class implementation, enable transform bounding box
1510 + *                      between different CRS
1511 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
1512 + *
1513 + ******************************************************************************
1514 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
1515 + *
1516 + * Permission is hereby granted, free of charge, to any person obtaining a
1517 + * copy of this software and associated documentation files (the "Software"),
1518 + * to deal in the Software without restriction, including without limitation
1519 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1520 + * and/or sell copies of the Software, and to permit persons to whom the
1521 + * Software is furnished to do so, subject to the following conditions:
1522 + *
1523 + * The above copyright notice and this permission notice shall be included
1524 + * in all copies or substantial portions of the Software.
1525 + *
1526 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1527 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1528 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1529 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1530 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1531 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1532 + * DEALINGS IN THE SOFTWARE.
1533 + ****************************************************************************/
1534 +
1535 +#include <vector>
1536 +#include <iostream>
1537 +
1538 +#include "BoundingBox.h"
1539 +#include "wcs_error.h"
1540 +
1541 +using namespace std;
1542 +
1543 +My2DPoint::~My2DPoint()
1544 +{
1545 +
1546 +}
1547 +
1548 +BoundingBox::BoundingBox()
1549 +{
1550 +
1551 +}
1552 +
1553 +BoundingBox::~BoundingBox()
1554 +{
1555 +
1556 +}
1557 +
1558 +BoundingBox BoundingBox::TransformWorkExtend(OGRSpatialReference &dstCRS, int &IsOK)
1559 +{
1560 +       if (mo_CRS.IsSame(&dstCRS))
1561 +       {
1562 +               IsOK = TRUE;
1563 +               return *this;
1564 +       }
1565 +
1566 +       OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&mo_CRS, &dstCRS);
1567 +       if (poCT == NULL)
1568 +       {
1569 +               IsOK = FALSE;
1570 +               return *this;
1571 +       }
1572 +
1573 +       double xdes = (mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
1574 +
1575 +       if (mo_CRS.IsGeographic()
1576 +                       && mo_UpperRightPT.mi_X < mo_LowerLeftPT.mi_X
1577 +                       && mo_LowerLeftPT.mi_X > 0 && mo_UpperRightPT.mi_X < 0)
1578 +       {
1579 +               xdes = (360 + mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
1580 +       }
1581 +
1582 +       vector<double> x;
1583 +       vector<double> y;
1584 +       //up and down edge
1585 +       for (double stepX = mo_LowerLeftPT.mi_X; stepX < mo_UpperRightPT.mi_X; stepX
1586 +                       += xdes)
1587 +       {
1588 +               x.push_back(stepX);
1589 +               y.push_back(mo_UpperRightPT.mi_Y);
1590 +               x.push_back(stepX);
1591 +               y.push_back(mo_LowerLeftPT.mi_Y);
1592 +       }
1593 +       x.push_back(mo_UpperRightPT.mi_X);
1594 +       y.push_back(mo_UpperRightPT.mi_Y);
1595 +       x.push_back(mo_UpperRightPT.mi_X);
1596 +       y.push_back(mo_LowerLeftPT.mi_Y);
1597 +
1598 +       double yMin = numeric_limits<double>::max();
1599 +       double yMax = numeric_limits<double>::min();
1600 +
1601 +       int k = 0;
1602 +       vector<int> bSuccess;
1603 +       vector<double> tmpX;
1604 +       vector<double> tmpY;
1605 +
1606 +       for (unsigned int i = 0; i < x.size(); i++)
1607 +       {
1608 +               tmpX.push_back(x[i]);
1609 +               tmpY.push_back(y[i]);
1610 +               bSuccess.push_back(0);
1611 +       }
1612 +
1613 +       poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
1614 +
1615 +       for (unsigned int n = 0; n < x.size(); n++)
1616 +       {
1617 +               if (bSuccess[n])
1618 +               {
1619 +                       ++k;
1620 +                       yMin = MIN(yMin,tmpY[n]);
1621 +                       yMax = MAX(yMax,tmpY[n]);
1622 +               }
1623 +       }
1624 +
1625 +       if (k < 80)
1626 +       {
1627 +               IsOK = FALSE;
1628 +               OCTDestroyCoordinateTransformation(poCT);
1629 +               return *this;
1630 +       }
1631 +
1632 +       //find xmin on left edge and xmax on right edge
1633 +       double xMin;
1634 +       double xMax;
1635 +
1636 +       double tmpPTX[2];
1637 +       double tmpPTY[2];
1638 +
1639 +       int isSucc[2];
1640 +
1641 +       tmpPTX[0] = mo_LowerLeftPT.mi_X;
1642 +       tmpPTX[1] = mo_LowerLeftPT.mi_X;
1643 +       tmpPTY[0] = mo_LowerLeftPT.mi_Y;
1644 +       tmpPTY[1] = mo_UpperRightPT.mi_Y;
1645 +
1646 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
1647 +       if (isSucc[0] && isSucc[1])
1648 +       {
1649 +               xMin = MIN(tmpPTX[0],tmpPTX[1]);
1650 +       }
1651 +       else
1652 +       {
1653 +               OCTDestroyCoordinateTransformation(poCT);
1654 +               IsOK = FALSE;
1655 +               return *this;
1656 +       }
1657 +
1658 +       tmpPTX[0] = mo_UpperRightPT.mi_X;
1659 +       tmpPTX[1] = mo_UpperRightPT.mi_X;
1660 +       tmpPTY[0] = mo_UpperRightPT.mi_Y;
1661 +       tmpPTY[1] = mo_LowerLeftPT.mi_Y;
1662 +
1663 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
1664 +       if (isSucc[0] && isSucc[1])
1665 +       {
1666 +               xMax = MAX(tmpPTX[0],tmpPTX[1]);
1667 +       }
1668 +       else
1669 +       {
1670 +               OCTDestroyCoordinateTransformation(poCT);
1671 +               IsOK = FALSE;
1672 +               return *this;
1673 +       }
1674 +
1675 +       BoundingBox bbox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
1676 +
1677 +       if (dstCRS.IsGeographic())
1678 +       {
1679 +               if (xMin > 180)
1680 +                       xMin = xMin - 360;
1681 +               if (xMax > 180)
1682 +                       xMax = xMax - 360;
1683 +
1684 +               if (xMin >= 180.)
1685 +                       xMin = 180.;
1686 +               if (xMin <= -180.)
1687 +                       xMin = -180.;
1688 +               if (xMax >= 180.)
1689 +                       xMax = 180.;
1690 +               if (xMax <= -180.)
1691 +                       xMax = -180.;
1692 +
1693 +               if (yMin < 0.)
1694 +                       yMin = 0.;
1695 +               if (yMax > 90.)
1696 +                       yMax = 90.;
1697 +       }
1698 +       OCTDestroyCoordinateTransformation(poCT);
1699 +       IsOK = TRUE;
1700 +       return BoundingBox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
1701 +}
1702 +
1703 +BoundingBox BoundingBox::Transform(const double GeoTransform[])
1704 +{
1705 +       My2DPoint llPt;
1706 +       My2DPoint urPt;
1707 +       llPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_LowerLeftPT.mi_X + GeoTransform[2] * mo_LowerLeftPT.mi_Y;
1708 +       llPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_LowerLeftPT.mi_X + GeoTransform[5] * mo_LowerLeftPT.mi_Y;
1709 +       urPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_UpperRightPT.mi_X + GeoTransform[2] * mo_UpperRightPT.mi_Y;
1710 +       urPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_UpperRightPT.mi_X + GeoTransform[5] * mo_UpperRightPT.mi_Y;
1711 +
1712 +       return BoundingBox(llPt,urPt,mo_CRS);
1713 +}
1714 +
1715 +/**
1716 + * Transform Coordinates of lowercorner_left and upcorner_right
1717 + * lowLeft, upRight.
1718 + * the return value has considered the case of image area crossing 180/-180 longitude line,
1719 + * so lowLeft.x maybe bigger than upRight.x
1720 + */
1721 +CPLErr CPL_STDCALL bBox_transFormmate(OGRSpatialReference& oSrcCRS,
1722 +               OGRSpatialReference& oDesCRS, My2DPoint& lowLeft, My2DPoint& upRight)
1723 +{
1724 +       if (oSrcCRS.IsSame(&oDesCRS))
1725 +               return CE_None;
1726 +
1727 +       OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&oSrcCRS, &oDesCRS);
1728 +       if (poCT == NULL)
1729 +       {
1730 +               SetWCS_ErrorLocator("bBox_transFormmate()");
1731 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create \"OGRCoordinateTransformation\"");
1732 +               return CE_Failure;
1733 +       }
1734 +
1735 +       double xdes = (upRight.mi_X - lowLeft.mi_X) / 100;
1736 +       if (oSrcCRS.IsGeographic() && upRight.mi_X < lowLeft.mi_X && lowLeft.mi_X > 0 && upRight.mi_X < 0)
1737 +       {
1738 +               xdes = (360 + upRight.mi_X - lowLeft.mi_X) / 100;
1739 +       }
1740 +
1741 +       vector<double> x, y;
1742 +       //up and down edge
1743 +       for (double stepX = lowLeft.mi_X; stepX < upRight.mi_X; stepX += xdes)
1744 +       {
1745 +               x.push_back(stepX);
1746 +               y.push_back(upRight.mi_Y);
1747 +               x.push_back(stepX);
1748 +               y.push_back(lowLeft.mi_Y);
1749 +       }
1750 +       x.push_back(upRight.mi_X);
1751 +       y.push_back(upRight.mi_Y);
1752 +       x.push_back(upRight.mi_X);
1753 +       y.push_back(lowLeft.mi_Y);
1754 +
1755 +       double yMin = numeric_limits<double>::max();
1756 +       double yMax = -numeric_limits<double>::max();
1757 +
1758 +       int k = 0;
1759 +       vector<int> bSuccess;
1760 +       vector<double> tmpX;
1761 +       vector<double> tmpY;
1762 +
1763 +       for (unsigned int i = 0; i < x.size(); i++)
1764 +       {
1765 +               tmpX.push_back(x[i]);
1766 +               tmpY.push_back(y[i]);
1767 +               bSuccess.push_back(0);
1768 +       }
1769 +
1770 +       poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
1771 +
1772 +       for (unsigned int n = 0; n < x.size(); n++)
1773 +       {
1774 +               if (bSuccess[n])
1775 +               {
1776 +                       ++k;
1777 +                       yMin = MIN(yMin,tmpY[n]);
1778 +                       yMax = MAX(yMax,tmpY[n]);
1779 +               }
1780 +       }
1781 +
1782 +       if (k < 80)
1783 +       {
1784 +               OCTDestroyCoordinateTransformation(poCT);
1785 +               SetWCS_ErrorLocator("bBox_transFormmate()");
1786 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
1787 +               return CE_Failure;
1788 +       }
1789 +
1790 +       double xMin;
1791 +       double xMax;
1792 +
1793 +       //find xmin on left edge and xmax on right edge
1794 +       double tmpPTX[2];
1795 +       double tmpPTY[2];
1796 +       int isOK[2];
1797 +
1798 +       tmpPTX[0] = lowLeft.mi_X;
1799 +       tmpPTX[1] = lowLeft.mi_X;
1800 +       tmpPTY[0] = upRight.mi_Y;
1801 +       tmpPTY[1] = lowLeft.mi_Y;
1802 +
1803 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
1804 +       if (isOK[0] && isOK[1])
1805 +       {
1806 +               xMin = MIN(tmpPTX[0],tmpPTX[1]);
1807 +       }
1808 +       else
1809 +       {
1810 +               OCTDestroyCoordinateTransformation(poCT);
1811 +               SetWCS_ErrorLocator("bBox_transFormmate()");
1812 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
1813 +               return CE_Failure;
1814 +       }
1815 +
1816 +       tmpPTX[0] = upRight.mi_X;
1817 +       tmpPTX[1] = upRight.mi_X;
1818 +       tmpPTY[0] = upRight.mi_Y;
1819 +       tmpPTY[1] = lowLeft.mi_Y;
1820 +
1821 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
1822 +       if (isOK[0] && isOK[1])
1823 +       {
1824 +               xMax = MAX(tmpPTX[0],tmpPTX[1]);
1825 +       }
1826 +       else
1827 +       {
1828 +               SetWCS_ErrorLocator("bBox_transFormmate()");
1829 +               OCTDestroyCoordinateTransformation(poCT);
1830 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
1831 +               return CE_Failure;
1832 +       }
1833 +       
1834 +       lowLeft.mi_X = xMin;
1835 +       lowLeft.mi_Y = yMin;
1836 +       upRight.mi_X = xMax;
1837 +       upRight.mi_Y = yMax;
1838 +
1839 +       if (oDesCRS.IsGeographic())
1840 +       {
1841 +               if (xMin > 180)
1842 +                       lowLeft.mi_X = xMin - 360;
1843 +               if (xMax > 180)
1844 +                       upRight.mi_X = xMax - 360;
1845 +
1846 +               if (lowLeft.mi_X >= 180.)
1847 +                       lowLeft.mi_X = 180.;
1848 +               if (lowLeft.mi_X <= -180.)
1849 +                       lowLeft.mi_X = -180.;
1850 +               if (upRight.mi_X >= 180.)
1851 +                       upRight.mi_X = 180.;
1852 +               if (upRight.mi_X <= -180.)
1853 +                       upRight.mi_X = -180.;
1854 +
1855 +               if (lowLeft.mi_Y <= -90.)
1856 +                       lowLeft.mi_Y = -90.;
1857 +               if (upRight.mi_Y >= 90.)
1858 +                       upRight.mi_Y = 90.;
1859 +       }
1860 +       OCTDestroyCoordinateTransformation(poCT);
1861 +
1862 +       return CE_None;
1863 +}
1864 diff -Nur bes-3.12.0/functions.orig/swath2grid/BoundingBox.h bes-3.12.0/functions/swath2grid/BoundingBox.h
1865 --- bes-3.12.0/functions.orig/swath2grid/BoundingBox.h  1970-01-01 01:00:00.000000000 +0100
1866 +++ bes-3.12.0/functions/swath2grid/BoundingBox.h       2014-03-03 15:47:38.053566262 +0100
1867 @@ -0,0 +1,137 @@
1868 +/******************************************************************************
1869 + * $Id: BoundingBox.h 2011-07-19 16:24:00Z $
1870 + *
1871 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
1872 + *                      for Earth Observation: Open Source Reference Implementation
1873 + * Purpose:  BoundingBox class definition
1874 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
1875 + *
1876 + ******************************************************************************
1877 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
1878 + *
1879 + * Permission is hereby granted, free of charge, to any person obtaining a
1880 + * copy of this software and associated documentation files (the "Software"),
1881 + * to deal in the Software without restriction, including without limitation
1882 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1883 + * and/or sell copies of the Software, and to permit persons to whom the
1884 + * Software is furnished to do so, subject to the following conditions:
1885 + *
1886 + * The above copyright notice and this permission notice shall be included
1887 + * in all copies or substantial portions of the Software.
1888 + *
1889 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1890 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1891 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1892 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1893 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1894 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1895 + * DEALINGS IN THE SOFTWARE.
1896 + ****************************************************************************/
1897 +
1898 +#ifndef BOUNDINGBOX_H_
1899 +#define BOUNDINGBOX_H_
1900 +
1901 +#include <gdal.h>
1902 +#include <ogr_spatialref.h>
1903 +#include <limits>
1904 +#include <stdlib.h>
1905 +
1906 +using namespace std;
1907 +
1908 +/************************************************************************/
1909 +/* ==================================================================== */
1910 +/*                             My2DPoint                                */
1911 +/* ==================================================================== */
1912 +/************************************************************************/
1913 +
1914 +/**
1915 + * \class My2DPoint "BoundingBox.h"
1916 + *
1917 + * My2DPoint class is used to store the point coordinates.
1918 + */
1919 +
1920 +class My2DPoint
1921 +{
1922 +public:
1923 +       double mi_X;
1924 +       double mi_Y;
1925 +
1926 +       virtual ~My2DPoint();
1927 +
1928 +       My2DPoint()
1929 +       {
1930 +               mi_X = 0;
1931 +               mi_Y = 0;
1932 +       }
1933 +
1934 +       My2DPoint(const double& xx, const double& yy) :
1935 +               mi_X(xx), mi_Y(yy)
1936 +       {
1937 +       }
1938 +
1939 +       My2DPoint(const My2DPoint& p) :
1940 +               mi_X(p.mi_X), mi_Y(p.mi_Y)
1941 +       {
1942 +       }
1943 +
1944 +       My2DPoint& operator =(const My2DPoint& p)
1945 +       {
1946 +               mi_X = p.mi_X;
1947 +               mi_Y = p.mi_Y;
1948 +               return *this;
1949 +       }
1950 +};
1951 +
1952 +/************************************************************************/
1953 +/* ==================================================================== */
1954 +/*                             BoundingBox                              */
1955 +/* ==================================================================== */
1956 +/************************************************************************/
1957 +
1958 +/**
1959 + * \class BoundingBox "BoundingBox.h"
1960 + *
1961 + * BoundingBox class is used to transform bounding box between different
1962 + * Coordinate Reference System.
1963 + */
1964 +
1965 +class BoundingBox
1966 +{
1967 +public:
1968 +       My2DPoint mo_LowerLeftPT;
1969 +       My2DPoint mo_UpperRightPT;
1970 +       OGRSpatialReference mo_CRS;
1971 +
1972 +       BoundingBox(const My2DPoint& llpt, const My2DPoint& urpt, OGRSpatialReference& crs) :
1973 +               mo_LowerLeftPT(llpt), mo_UpperRightPT(urpt), mo_CRS(crs)
1974 +       {
1975 +
1976 +       }
1977 +
1978 +       BoundingBox(OGRSpatialReference& crs) :
1979 +               mo_LowerLeftPT(0,0), mo_UpperRightPT(0,0), mo_CRS(crs)
1980 +       {
1981 +
1982 +       }
1983 +       BoundingBox& operator =(const BoundingBox& box)
1984 +       {
1985 +               mo_LowerLeftPT = box.mo_LowerLeftPT;
1986 +               mo_UpperRightPT = box.mo_UpperRightPT;
1987 +               mo_CRS = box.mo_CRS;
1988 +               return *this;
1989 +       }
1990 +
1991 +       BoundingBox();
1992 +       virtual ~BoundingBox();
1993 +
1994 +       BoundingBox Transform(OGRSpatialReference&, int&);
1995 +       BoundingBox TransformWorkExtend(OGRSpatialReference&, int&);
1996 +       BoundingBox Transform(const double*);
1997 +};
1998 +
1999 +CPLErr CPL_DLL CPL_STDCALL bBox_transFormmate( OGRSpatialReference&,
2000 +                                                                                               OGRSpatialReference&,
2001 +                                                                                               My2DPoint& lowLeft,
2002 +                                                                                               My2DPoint& upRight);
2003 +
2004 +#endif /* BOUNDINGBOX_H_ */
2005 diff -Nur bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.cpp bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp
2006 --- bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.cpp        1970-01-01 01:00:00.000000000 +0100
2007 +++ bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp     2014-03-03 15:47:38.046899595 +0100
2008 @@ -0,0 +1,730 @@
2009 +
2010 +// -*- mode: c++; c-basic-offset:4 -*-
2011 +
2012 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
2013 +// Access Protocol.
2014 +
2015 +// Copyright (c) 2012 OPeNDAP, Inc.
2016 +// Author: James Gallagher <jgallagher@opendap.org>
2017 +//
2018 +// This library is free software; you can redistribute it and/or
2019 +// modify it under the terms of the GNU Lesser General Public
2020 +// License as published by the Free Software Foundation; either
2021 +// version 2.1 of the License, or (at your option) any later version.
2022 +//
2023 +// This library is distributed in the hope that it will be useful,
2024 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
2025 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2026 +// Lesser General Public License for more details.
2027 +//
2028 +// You should have received a copy of the GNU Lesser General Public
2029 +// License along with this library; if not, write to the Free Software
2030 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2031 +//
2032 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
2033 +
2034 +#include <cstdlib>
2035 +
2036 +#define DODS_DEBUG
2037 +
2038 +#include "DAP_Dataset.h"
2039 +
2040 +#include "Array.h"
2041 +#include "Grid.h"
2042 +#include "Float64.h"
2043 +
2044 +#include "ce_functions.h"
2045 +#include "util.h"
2046 +#include "debug.h"
2047 +
2048 +using namespace libdap;
2049 +using namespace std;
2050 +
2051 +#if 0
2052 +#define GOES_TIME_DEBUG FALSE
2053 +#endif
2054 +
2055 +namespace libdap {
2056 +
2057 +DAP_Dataset::DAP_Dataset()
2058 +{
2059 +}
2060 +
2061 +/************************************************************************/
2062 +/*                           ~DAP_Dataset()                             */
2063 +/************************************************************************/
2064 +
2065 +/**
2066 + * \brief Destroy an open DAP_Dataset object.
2067 + *
2068 + * This is the accepted method of closing a DAP_Dataset dataset and
2069 + * deallocating all resources associated with it.
2070 + */
2071 +
2072 +DAP_Dataset::~DAP_Dataset()
2073 +{
2074 +}
2075 +
2076 +/************************************************************************/
2077 +/*                           DAP_Dataset()                              */
2078 +/************************************************************************/
2079 +
2080 +/**
2081 + * \brief Create an DAP_Dataset object.
2082 + *
2083 + * This is the accepted method of creating a DAP_Dataset object and
2084 + * allocating all resources associated with it.
2085 + *
2086 + * @param id The coverage identifier.
2087 + *
2088 + * @param rBandList The field list selected for this coverage. For TRMM
2089 + * daily data, the user could specify multiple days range in request.
2090 + * Each day is seemed as one field.
2091 + *
2092 + * @return A DAP_Dataset object.
2093 + */
2094 +
2095 +DAP_Dataset::DAP_Dataset(const string& id, vector<int> &rBandList) :
2096 +        AbstractDataset(id, rBandList)
2097 +{
2098 +    md_MissingValue = 0;
2099 +    mb_GeoTransformSet = FALSE;
2100 +}
2101 +
2102 +/**
2103 + * @brief Initialize a DAP Dataset using Array objects already read.
2104 + *
2105 + *
2106 + */
2107 +
2108 +DAP_Dataset::DAP_Dataset(Array *src, Array *lat, Array *lon) :
2109 +        AbstractDataset(), m_src(src), m_lat(lat), m_lon(lon)
2110 +{
2111 +#if 1
2112 +    // TODO Remove these?
2113 +    DBG(cerr << "Registering GDAL drivers" << endl);
2114 +    GDALAllRegister();
2115 +    OGRRegisterAll();
2116 +#endif
2117 +
2118 +    CPLSetErrorHandler(CPLQuietErrorHandler);
2119 +
2120 +    // Read this from the 'missing_value' or '_FillValue' attributes
2121 +    string missing_value = m_src->get_attr_table().get_attr("missing_value");
2122 +    if (missing_value.empty())
2123 +        missing_value = m_src->get_attr_table().get_attr("_FillValue");
2124 +
2125 +    if (!missing_value.empty())
2126 +        md_MissingValue = atof(missing_value.c_str());
2127 +    else
2128 +        md_MissingValue = 0;
2129 +
2130 +    mb_GeoTransformSet = FALSE;
2131 +}
2132 +
2133 +/************************************************************************/
2134 +/*                           InitialDataset()                           */
2135 +/************************************************************************/
2136 +
2137 +/**
2138 + * \brief Initialize the GOES dataset with NetCDF format.
2139 +
2140 + * This method is the implementation for initializing a GOES dataset with NetCDF format.
2141 + * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
2142 + * will be called to initialize an GOES dataset.
2143 + *
2144 + * @note To use this, call this method and then access the GDALDataset that
2145 + * contains the reprojected array using maptr_DS.get().
2146 + *
2147 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
2148 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
2149 + *
2150 + * @return CE_None on success or CE_Failure on failure.
2151 + */
2152 +
2153 +CPLErr DAP_Dataset::InitialDataset(const int isSimple)
2154 +{
2155 +    DBG(cerr << "In InitialDataset" << endl);
2156 +
2157 +    // Might break that operation out so the remap is a separate call
2158 +    if (CE_None != SetNativeCRS() || CE_None != SetGeoTransform())
2159 +        throw Error("Could not set the dataset native CRS or the GeoTransform.");
2160 +
2161 +    DBG(cerr << "Before SetGDALDataset" << endl);
2162 +
2163 +    if (CE_None != SetGDALDataset(isSimple)) {
2164 +        GDALClose(maptr_DS.release());
2165 +        throw Error("Could not reproject the dataset.");
2166 +    }
2167 +
2168 +    return CE_None;
2169 +}
2170 +
2171 +/************************************************************************/
2172 +/*                            GetDAPArray()                            */
2173 +/************************************************************************/
2174 +
2175 +/**
2176 + * @brief Build a DAP Array from the GDALDataset
2177 + */
2178 +Array *DAP_Dataset::GetDAPArray()
2179 +{
2180 +    DBG(cerr << "In GetDAPArray" << endl);
2181 +    DBG(cerr << "maptr_DS: " << maptr_DS.get() << endl);
2182 +    DBG(cerr << "raster band count: " << maptr_DS->GetRasterCount() << endl);
2183 +
2184 +    // There should be just one band
2185 +    if (maptr_DS->GetRasterCount() != 1)
2186 +        throw Error("In function swath2grid(), expected a single raster band.");
2187 +
2188 +    // Get the x and y dimensions of the raster band
2189 +    int x = maptr_DS->GetRasterXSize();
2190 +    int y = maptr_DS->GetRasterYSize();
2191 +    GDALRasterBand *rb = maptr_DS->GetRasterBand(1);
2192 +    if (!rb)
2193 +        throw Error("In function swath2grid(), could not access the raster data.");
2194 +
2195 +    // Since the DAP_Dataset code works with all data values as doubles,
2196 +    // Assume the raster band has GDAL type GDT_Float64, but test anyway
2197 +    if (GDT_Float64 != rb->GetRasterDataType())
2198 +        throw Error("In function swath2grid(), expected raster data to be of type double.");
2199 +
2200 +    DBG(cerr << "Destination array will have dimensions: " << x << ", " << y << endl);
2201 +
2202 +    Array *a = new Array(m_src->name(), new Float64(m_src->name()));
2203 +
2204 +    // Make the result array have two dimensions
2205 +    Array::Dim_iter i = m_src->dim_begin();
2206 +
2207 +    a->append_dim(x, m_src->dimension_name(i));
2208 +    ++i;
2209 +
2210 +    if (i == m_src->dim_end())
2211 +        throw Error("In function swath2grid(), expected source array to have two dimensions (2).");
2212 +
2213 +    a->append_dim(y, m_src->dimension_name(i));
2214 +
2215 +    // Poke in the data values
2216 +    /* RasterIO (   GDALRWFlag  eRWFlag,
2217 +    int     nXOff,
2218 +    int     nYOff,
2219 +    int     nXSize,
2220 +    int     nYSize,
2221 +    void *  pData,
2222 +    int     nBufXSize,
2223 +    int     nBufYSize,
2224 +    GDALDataType    eBufType,
2225 +    int     nPixelSpace,
2226 +    int     nLineSpace
2227 +    ) */
2228 +    vector<double> data(x * y);
2229 +    rb->RasterIO(GF_Read, 0, 0, x, y, &data[0], x, y, GDT_Float64, 0, 0);
2230 +
2231 +    // NB: set_value() copies into new storage
2232 +    a->set_value(data, data.size());
2233 +
2234 +    // Now poke in some attributes
2235 +    // TODO Make these CF attributes
2236 +    string projection_info = maptr_DS->GetProjectionRef();
2237 +    string gcp_projection_info = maptr_DS->GetGCPProjection();
2238 +
2239 +    // This sets the instance variable that holds the geotransform coefs. These
2240 +    // are needed by the GetDAPGrid() method.
2241 +    if (CE_None != maptr_DS->GetGeoTransform (m_geo_transform_coef))
2242 +        throw Error("In function swath2grid(), could not access the geo transform data.");
2243 +
2244 +    DBG(cerr << "projection_info: " << projection_info << endl);
2245 +    DBG(cerr << "gcp_projection_info: " << gcp_projection_info << endl);
2246 +    DBG(cerr << "geo_transform coefs: " << double_to_string(m_geo_transform_coef[0]) << endl);
2247 +
2248 +    AttrTable &attr = a->get_attr_table();
2249 +    attr.append_attr("projection", "String", projection_info);
2250 +    attr.append_attr("gcp_projection", "String", gcp_projection_info);
2251 +    for (unsigned int i = 0; i < sizeof(m_geo_transform_coef); ++i) {
2252 +        attr.append_attr("geo_transform_coefs", "String", double_to_string(m_geo_transform_coef[i]));
2253 +    }
2254 +
2255 +    return a;
2256 +}
2257 +
2258 +/************************************************************************/
2259 +/*                            GetDAPGrid()                              */
2260 +/************************************************************************/
2261 +
2262 +/**
2263 + * @brief Build a DAP Grid from the GDALDataset
2264 + */
2265 +Grid *DAP_Dataset::GetDAPGrid()
2266 +{
2267 +    DBG(cerr << "In GetDAPGrid" << endl);
2268 +
2269 +    Array *a = GetDAPArray();
2270 +    Array::Dim_iter i = a->dim_begin();
2271 +    int lon_size = a->dimension_size(i);
2272 +    int lat_size = a->dimension_size(++i);
2273 +
2274 +    Grid *g = new Grid(a->name());
2275 +    g->add_var_nocopy(a, array);
2276 +
2277 +    // Add maps; assume lon, lat; only two dimensions
2278 +    Array *lon = new Array("longitude", new Float64("longitude"));
2279 +    lon->append_dim(lon_size);
2280 +
2281 +    vector<double> data(max(lon_size, lat_size)); // (re)use this for both lon and lat
2282 +
2283 +    // Compute values
2284 +    // u = a*x + b*y
2285 +    // v = c*x + d*y
2286 +    // u,v --> x,y --> lon,lat
2287 +    // The constants a, b, c, d are given by the 1, 2, 4, and 5 entries in the geotransform array.
2288 +
2289 +    if (m_geo_transform_coef[2] != 0)
2290 +       throw Error("The transformed data's Geographic projection should not be rotated.");
2291 +    for (int j = 0; j < lon_size; ++j) {
2292 +        data[j] = m_geo_transform_coef[1] * j + m_geo_transform_coef[0];
2293 +    }
2294 +
2295 +    // load (copy) values
2296 +    lon->set_value(&data[0], lon_size);
2297 +    // Set the map
2298 +    g->add_var_nocopy(lon, maps);
2299 +
2300 +    // Now do the latitude map
2301 +    Array *lat = new Array("latitude", new Float64("latitude"));
2302 +    lat->append_dim(lat_size);
2303 +
2304 +    if (m_geo_transform_coef[4] != 0)
2305 +       throw Error("The transformed data's Geographic projection should not be rotated.");
2306 +    for (int k = 0; k < lat_size; ++k) {
2307 +        data[k] = m_geo_transform_coef[5] * k + m_geo_transform_coef[3];
2308 +    }
2309 +
2310 +    lat->set_value(&data[0], lat_size);
2311 +    g->add_var_nocopy(lat, maps);
2312 +
2313 +    return g;
2314 +}
2315 +
2316 +/************************************************************************/
2317 +/*                            SetNativeCRS()                            */
2318 +/************************************************************************/
2319 +
2320 +/**
2321 + * \brief Set the Native CRS for a GOES dataset.
2322 + *
2323 + * The method will set the CRS for a GOES dataset as an native CRS.
2324 + *
2325 + * Since the original GOES data adopt satellite CRS to recored its value,
2326 + * like MODIS swath data, each data point has its corresponding latitude
2327 + * and longitude value, those coordinates could be fetched in another two fields.
2328 + *
2329 + * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
2330 + * both the latitude and longitude are existed.
2331 + *
2332 + * @return CE_None on success or CE_Failure on failure.
2333 + */
2334 +
2335 +CPLErr DAP_Dataset::SetNativeCRS()
2336 +{
2337 +    DBG(cerr << "In SetNativeCRS" << endl);
2338 +
2339 +    mo_NativeCRS.SetWellKnownGeogCS("WGS84");
2340 +
2341 +    return CE_None;
2342 +}
2343 +
2344 +/************************************************************************/
2345 +/*                           SetGeoTransform()                          */
2346 +/************************************************************************/
2347 +
2348 +/**
2349 + * \brief Set the affine GeoTransform matrix for a GOES data.
2350 + *
2351 + * The method will set a GeoTransform matrix for a GOES data
2352 + * by parsing the coordinates values existed in longitude and latitude field.
2353 + *
2354 + * The CRS for the bounding box is EPSG:4326.
2355 + *
2356 + * @return CE_None on success or CE_Failure on failure.
2357 + */
2358 +
2359 +CPLErr DAP_Dataset::SetGeoTransform()
2360 +{
2361 +    DBG(cerr << "In SetGeoTransform" << endl);
2362 +
2363 +    // TODO Look at this; is this correct
2364 +    // Assume the array is two dimensional
2365 +    Array::Dim_iter i = m_src->dim_begin();
2366 +#if 0
2367 +    // ORIGINAL code; maybe wrong
2368 +    int nXSize = m_src->dimension_size(i, true);
2369 +    int nYSize = m_src->dimension_size(i + 1, true);
2370 +#endif
2371 +    // Data are in row-major order, so the first dim is the Y-axis value
2372 +    int nYSize = m_src->dimension_size(i, true);
2373 +    int nXSize = m_src->dimension_size(i + 1, true);
2374 +
2375 +    mi_SrcImageXSize = nXSize;
2376 +    mi_SrcImageYSize = nYSize;
2377 +
2378 +    SetGeoBBoxAndGCPs(nXSize, nYSize);
2379 +
2380 +    double resX, resY;
2381 +    if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
2382 +        resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
2383 +    else
2384 +        resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
2385 +
2386 +    resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (nYSize - 1);
2387 +
2388 +    double res = MIN(resX, resY);
2389 +
2390 +    if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
2391 +        mi_RectifiedImageXSize = (int) ((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
2392 +    else
2393 +        mi_RectifiedImageXSize = (int) ((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
2394 +
2395 +    mi_RectifiedImageYSize = (int) fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
2396 +
2397 +    DBG(cerr << "Source image size: " << nXSize << ", " << nYSize << endl);
2398 +    DBG(cerr << "Rectified image size: " << mi_RectifiedImageXSize << ", " << mi_RectifiedImageYSize << endl);
2399 +
2400 +    md_Geotransform[0] = mdSrcGeoMinX;
2401 +    md_Geotransform[1] = res;
2402 +    md_Geotransform[2] = 0;
2403 +    md_Geotransform[3] = mdSrcGeoMaxY;
2404 +    md_Geotransform[4] = 0;
2405 +    md_Geotransform[5] = -res;
2406 +    mb_GeoTransformSet = TRUE;
2407 +
2408 +    return CE_None;
2409 +}
2410 +
2411 +/************************************************************************/
2412 +/*                         SetGeoBBoxAndGCPs()                          */
2413 +/************************************************************************/
2414 +
2415 +/**
2416 + * \brief Set the native geographical bounding box and GCP array for a GOES data.
2417 + *
2418 + * The method will set the native geographical bounding box
2419 + * by comparing the coordinates values existed in longitude and latitude field.
2420 + *
2421 + * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
2422 + *
2423 + * @return CE_None on success or CE_Failure on failure.
2424 + */
2425 +
2426 +void DAP_Dataset::SetGeoBBoxAndGCPs(int nXSize, int nYSize)
2427 +{
2428 +    DBG(cerr << "In SetGeoBBoxAndGCPs" << endl);
2429 +
2430 +    // reuse the Dim_iter for both lat and lon arrays
2431 +    Array::Dim_iter i = m_lat->dim_begin();
2432 +    int nLatXSize = m_lat->dimension_size(i, true);
2433 +    int nLatYSize = m_lat->dimension_size(i + 1, true);
2434 +    i = m_lon->dim_begin();
2435 +    int nLonXSize = m_lon->dimension_size(i, true);
2436 +    int nLonYSize = m_lon->dimension_size(i + 1, true);
2437 +
2438 +    if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
2439 +        throw Error("The size of latitude/longitude and data field does not match.");
2440 +
2441 +#if 0
2442 +    /*
2443 +     * Re-sample Standards:
2444 +     * Height | Width
2445 +     * (0, 500)                every other one pixel
2446 +     * [500, 1000)             every other two pixels
2447 +     * [1000,1500)             every other three pixels
2448 +     * [1500,2000)             every other four pixels
2449 +     * ... ...
2450 +     */
2451 +
2452 +    int xSpace = 1;
2453 +    int ySpace = 1;
2454 +    //setResampleStandard(poVDS, xSpace, ySpace);
2455 +
2456 +    // TODO understand how GMU picked this value.
2457 +    // xSpace and ySpace are the stride values for sampling in
2458 +    // the x and y dimensions.
2459 +    const int RESAMPLE_STANDARD = 500;
2460 +
2461 +    xSpace = int(nXSize / RESAMPLE_STANDARD) + 2;
2462 +    ySpace = int(nYSize / RESAMPLE_STANDARD) + 2;
2463 +#endif
2464 +
2465 +    m_lat->read();
2466 +    m_lon->read();
2467 +    double *dataLat = extract_double_array(m_lat);
2468 +    double *dataLon = extract_double_array(m_lon);
2469 +
2470 +    DBG(cerr << "Past lat/lon data read" << endl);
2471 +
2472 +    try {
2473 +
2474 +        mdSrcGeoMinX = 360;
2475 +        mdSrcGeoMaxX = -360;
2476 +        mdSrcGeoMinY = 90;
2477 +        mdSrcGeoMaxY = -90;
2478 +
2479 +        // Sample every other row and column
2480 +        int xSpace = 2;
2481 +        int ySpace = 2;
2482 +
2483 +        int nGCPs = 0;
2484 +        GDAL_GCP gdalCGP;
2485 +
2486 +        for (int iLine = 0; iLine < nYSize - ySpace; iLine += ySpace) {
2487 +            for (int iPixel = 0; iPixel < nXSize - xSpace; iPixel += xSpace) {
2488 +                double x = *(dataLon + (iLine * nYSize) + iPixel);
2489 +                double y = *(dataLat + (iLine * nYSize) + iPixel);
2490 +
2491 +                if (isValidLongitude(x) && isValidLatitude(y)) {
2492 +                    char pChr[64];
2493 +                    snprintf(pChr, 64, "%d", ++nGCPs);
2494 +                    GDALInitGCPs(1, &gdalCGP);
2495 +                    gdalCGP.pszId = strdup(pChr);
2496 +                    gdalCGP.pszInfo = strdup("");
2497 +                    gdalCGP.dfGCPLine = iLine;
2498 +                    gdalCGP.dfGCPPixel = iPixel;
2499 +                    gdalCGP.dfGCPX = x;
2500 +                    gdalCGP.dfGCPY = y;
2501 +
2502 +                    DBG2(cerr << "iLine, iPixel: " << iLine << ", " << iPixel << " --> x,y: " << x << ", " << y << endl);
2503 +
2504 +                    gdalCGP.dfGCPZ = 0;
2505 +                    m_gdalGCPs.push_back(gdalCGP);
2506 +
2507 +                    mdSrcGeoMinX = MIN(mdSrcGeoMinX, gdalCGP.dfGCPX);
2508 +                    mdSrcGeoMaxX = MAX(mdSrcGeoMaxX, gdalCGP.dfGCPX);
2509 +                    mdSrcGeoMinY = MIN(mdSrcGeoMinY, gdalCGP.dfGCPY);
2510 +                    mdSrcGeoMaxY = MAX(mdSrcGeoMaxY, gdalCGP.dfGCPY);
2511 +                }
2512 +            }
2513 +        }
2514 +    }
2515 +    catch (...) {
2516 +        delete[] dataLat;
2517 +        delete[] dataLon;
2518 +        throw;
2519 +    }
2520 +
2521 +    delete[] dataLat;
2522 +    delete[] dataLon;
2523 +
2524 +    DBG(cerr << "Leaving SetGeoBBoxAndGCPs" << endl);
2525 +}
2526 +
2527 +/************************************************************************/
2528 +/*                           SetGDALDataset()                           */
2529 +/************************************************************************/
2530 +
2531 +/**
2532 + * \brief Make a 'memory' dataset with one band
2533 + *
2534 + * @return CE_None on success or CE_Failure on failure.
2535 + */
2536 +
2537 +CPLErr DAP_Dataset::SetGDALDataset(const int isSimple)
2538 +{
2539 +    DBG(cerr << "In SetGDALDataset" << endl);
2540 +
2541 +    // NB: mi_RectifiedImageXSize & Y are set in SetGeoTransform()
2542 +    GDALDataType eBandType = GDT_Float64;
2543 +    // VRT, which was used in the original sample code, is not supported in this context, so I used MEM
2544 +    GDALDriverH poDriver = GDALGetDriverByName("MEM");
2545 +    if (!poDriver) {
2546 +        throw Error("Failed to get MEM driver (" + string(CPLGetLastErrorMsg()) + ").");
2547 +    }
2548 +
2549 +    GDALDataset* satDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
2550 +            1, eBandType, NULL);
2551 +    if (!satDataSet) {
2552 +        GDALClose(poDriver);
2553 +        throw Error("Failed to create MEM dataSet (" + string(CPLGetLastErrorMsg()) + ").");
2554 +    }
2555 +
2556 +    GDALRasterBand *poBand = satDataSet->GetRasterBand(1);
2557 +    poBand->SetNoDataValue(md_MissingValue);
2558 +
2559 +    m_src->read();
2560 +    double *data = extract_double_array(m_src);
2561 +    if (CE_None != poBand->RasterIO(GF_Write, 0, 0, mi_RectifiedImageXSize, mi_RectifiedImageYSize, data,
2562 +                    mi_SrcImageXSize, mi_SrcImageYSize, eBandType, 0, 0)) {
2563 +        GDALClose((GDALDatasetH) satDataSet);
2564 +        throw Error("Failed to set satellite data band to MEM DataSet (" + string(CPLGetLastErrorMsg()) + ").");
2565 +    }
2566 +    delete[] data;
2567 +
2568 +    //set GCPs for this VRTDataset
2569 +    if (CE_None != SetGCPGeoRef4VRTDataset(satDataSet)) {
2570 +        GDALClose((GDALDatasetH) satDataSet);
2571 +        throw Error("Could not georeference the virtual dataset (" + string(CPLGetLastErrorMsg()) + ").");
2572 +    }
2573 +
2574 +    DBG(cerr << "satDataSet: " << satDataSet << endl);
2575 +
2576 +    maptr_DS.reset(satDataSet);
2577 +
2578 +    if (isSimple)
2579 +        return CE_None;
2580 +
2581 +    return RectifyGOESDataSet();
2582 +}
2583 +
2584 +/************************************************************************/
2585 +/*                       SetGCPGeoRef4VRTDataset()                      */
2586 +/************************************************************************/
2587 +
2588 +/**
2589 + * \brief Set the GCP array for the VRT dataset.
2590 + *
2591 + * This method is used to set the GCP array to created VRT dataset based on GDAL
2592 + * method SetGCPs().
2593 + *
2594 + * @param poVDS The VRT dataset.
2595 + *
2596 + * @return CE_None on success or CE_Failure on failure.
2597 + */
2598 +
2599 +CPLErr DAP_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
2600 +{
2601 +    char* psTargetSRS;
2602 +    mo_NativeCRS.exportToWkt(&psTargetSRS);
2603 +
2604 +#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
2605 +    if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS)) {
2606 +        OGRFree(psTargetSRS);
2607 +        throw Error("Failed to set GCPs.");
2608 +    }
2609 +#else
2610 +    {
2611 +        if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
2612 +        {
2613 +            OGRFree( psTargetSRS );
2614 +            throw Error("Failed to set GCPs.");
2615 +        }
2616 +    }
2617 +#endif
2618 +
2619 +    OGRFree(psTargetSRS);
2620 +
2621 +    return CE_None;
2622 +}
2623 +#if 0
2624 +/************************************************************************/
2625 +/*                        SetMetaDataList()                             */
2626 +/************************************************************************/
2627 +
2628 +/**
2629 + * \brief Set the metadata list for this coverage.
2630 + *
2631 + * The method will set the metadata list for the coverage based on its
2632 + * corresponding GDALDataset object.
2633 + *
2634 + * @param hSrc the GDALDataset object corresponding to coverage.
2635 + *
2636 + * @return CE_None on success or CE_Failure on failure.
2637 + */
2638 +
2639 +CPLErr DAP_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
2640 +{
2641 +    // TODO Remove
2642 +#if 0
2643 +    mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
2644 +    mv_MetaDataList.push_back("unit=GVAR");
2645 +    mv_MetaDataList.push_back("FillValue=0");
2646 +    ms_FieldQuantityDef = "GVAR";
2647 +    ms_AllowRanges = "0 65535";
2648 +    ms_CoveragePlatform = "GOES-11";
2649 +    ms_CoverageInstrument = "GOES-11";
2650 +    ms_CoverageSensor = "Imager";
2651 +#endif
2652 +
2653 +    return CE_None;
2654 +}
2655 +#endif
2656 +/************************************************************************/
2657 +/*                          GetGeoMinMax()                              */
2658 +/************************************************************************/
2659 +
2660 +/**
2661 + * \brief Get the min/max coordinates of laitutude and longitude.
2662 + *
2663 + * The method will fetch the min/max coordinates of laitutude and longitude.
2664 + *
2665 + * @param geoMinMax an existing four double buffer into which the
2666 + * native geographical bounding box values will be placed.
2667 + *
2668 + * @return CE_None on success or CE_Failure on failure.
2669 + */
2670 +
2671 +CPLErr DAP_Dataset::GetGeoMinMax(double geoMinMax[])
2672 +{
2673 +    if (!mb_GeoTransformSet)
2674 +        return CE_Failure;
2675 +
2676 +    geoMinMax[0] = mdSrcGeoMinX;
2677 +    geoMinMax[2] = mdSrcGeoMinY;
2678 +    geoMinMax[1] = mdSrcGeoMaxX;
2679 +    geoMinMax[3] = mdSrcGeoMaxY;
2680 +
2681 +    return CE_None;
2682 +}
2683 +
2684 +/************************************************************************/
2685 +/*                          RectifyGOESDataSet()                        */
2686 +/************************************************************************/
2687 +
2688 +/**
2689 + * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
2690 + *
2691 + * The method will convert the GOES dataset from satellite CRS project to
2692 + * grid CRS based on GDAL API GDALReprojectImage;
2693 + *
2694 + * @return CE_None on success or CE_Failure on failure.
2695 + */
2696 +
2697 +CPLErr DAP_Dataset::RectifyGOESDataSet()
2698 +{
2699 +    DBG(cerr << "In RectifyGOESDataSet" << endl);
2700 +
2701 +    char *pszDstWKT;
2702 +    mo_NativeCRS.exportToWkt(&pszDstWKT);
2703 +
2704 +    GDALDriverH poDriver = GDALGetDriverByName("VRT"); // MEM
2705 +    GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
2706 +            maptr_DS->GetRasterCount(), maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
2707 +    if (NULL == rectDataSet) {
2708 +        GDALClose(poDriver);
2709 +        OGRFree(pszDstWKT);
2710 +        throw Error("Failed to create \"MEM\" dataSet.");
2711 +    }
2712 +
2713 +    rectDataSet->SetProjection(pszDstWKT);
2714 +    rectDataSet->SetGeoTransform(md_Geotransform);
2715 +
2716 +    DBG(cerr << "rectDataSet: " << rectDataSet << endl);
2717 +    DBG(cerr << "satDataSet: " << maptr_DS.get() << endl);
2718 +
2719 +    // FIXME Magic value of 0.125
2720 +    if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet, pszDstWKT,
2721 +            GRA_Lanczos /*GRA_NearestNeighbour*/, 0, 0.0/*0.125*/, NULL, NULL, NULL)) {
2722 +        GDALClose(rectDataSet);
2723 +        GDALClose(poDriver);
2724 +        OGRFree(pszDstWKT);
2725 +        throw Error("Failed to re-project satellite data from GCP CRS to geographical CRS.");
2726 +    }
2727 +
2728 +    OGRFree(pszDstWKT);
2729 +    GDALClose(maptr_DS.release());
2730 +
2731 +    maptr_DS.reset(rectDataSet);
2732 +
2733 +    DBG(cerr << "Leaving RectifyGOESDataSet" << endl);
2734 +
2735 +    return CE_None;
2736 +}
2737 +
2738 +} // namespace libdap
2739 diff -Nur bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.h bes-3.12.0/functions/swath2grid/DAP_Dataset.h
2740 --- bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.h  1970-01-01 01:00:00.000000000 +0100
2741 +++ bes-3.12.0/functions/swath2grid/DAP_Dataset.h       2014-03-03 15:47:38.050232928 +0100
2742 @@ -0,0 +1,142 @@
2743 +
2744 +// -*- mode: c++; c-basic-offset:4 -*-
2745 +
2746 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
2747 +// Access Protocol.
2748 +
2749 +// Copyright (c) 2012 OPeNDAP, Inc.
2750 +// Author: James Gallagher <jgallagher@opendap.org>
2751 +//
2752 +// This library is free software; you can redistribute it and/or
2753 +// modify it under the terms of the GNU Lesser General Public
2754 +// License as published by the Free Software Foundation; either
2755 +// version 2.1 of the License, or (at your option) any later version.
2756 +//
2757 +// This library is distributed in the hope that it will be useful,
2758 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
2759 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2760 +// Lesser General Public License for more details.
2761 +//
2762 +// You should have received a copy of the GNU Lesser General Public
2763 +// License along with this library; if not, write to the Free Software
2764 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
2765 +//
2766 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
2767 +
2768 +#ifndef DAP_DATASET_H_
2769 +#define DAP_DATASET_H_
2770 +
2771 +#include <string>
2772 +#include "AbstractDataset.h"
2773 +#include "wcsUtil.h"
2774 +
2775 +using namespace std;
2776 +
2777 +namespace libdap {
2778 +
2779 +class Array;
2780 +class Grid;
2781 +
2782 +/************************************************************************/
2783 +/* ==================================================================== */
2784 +/*                           DAP_Dataset                            */
2785 +/* ==================================================================== */
2786 +/************************************************************************/
2787 +
2788 +//! DAP_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
2789 +/**
2790 + * \class DAP_Dataset "DAP_Dataset.h"
2791 + *
2792 + * GOES satellites provide the kind of continuous monitoring necessary for
2793 + * intensive data analysis. They circle the Earth in a geosynchronous orbit,
2794 + * which means they orbit the equatorial plane of the Earth at a speed
2795 + * matching the Earth's rotation. This allows them to hover continuously
2796 + * over one position on the surface. The geosynchronous plane is about
2797 + * 35,800 km (22,300 miles) above the Earth, high enough to allow the
2798 + * satellites a full-disc view of the Earth. Because they stay above a
2799 + * fixed spot on the surface, they provide a constant vigil for the atmospheric
2800 + * "triggers" for severe weather conditions such as tornadoes, flash floods,
2801 + * hail storms, and hurricanes. When these conditions develop the GOES
2802 + * satellites are able to monitor storm development and track their movements.
2803 + *
2804 + * GOES satellite imagery is also used to estimate rainfall during
2805 + * the thunderstorms and hurricanes for flash flood warnings, as well
2806 + * as estimates snowfall accumulations and overall extent of snow cover.
2807 + * Such data help meteorologists issue winter storm warnings and spring
2808 + * snow melt advisories. Satellite sensors also detect ice fields and map
2809 + * the movements of sea and lake ice.
2810 + *
2811 + * For more inforamtion about NOAA GOES data, please access
2812 + * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
2813 + *
2814 + * DAP_Dataset is a subclass of AbstractDataset, which is used to
2815 + * process GOES Imager and Sounder products.
2816 + */
2817 +
2818 +class DAP_Dataset : public AbstractDataset {
2819 +protected:
2820 +    string m_ncLatDataSetName;
2821 +    string m_ncLonDataSetName;
2822 +    string m_ncCoverageIDName;
2823 +
2824 +    // Instead of using names and opening files with GDAL,
2825 +    // store pointers to Arrays read by the underlying DAP
2826 +    // server constraint evaluator.
2827 +    Array *m_src;
2828 +    Array *m_lat;
2829 +    Array *m_lon;
2830 +
2831 +    int mi_RectifiedImageXSize;
2832 +    int mi_RectifiedImageYSize;
2833 +    int mi_SrcImageXSize;
2834 +    int mi_SrcImageYSize;
2835 +
2836 +    double mb_LatLonBBox[4];
2837 +    double mdSrcGeoMinX;
2838 +    double mdSrcGeoMinY;
2839 +    double mdSrcGeoMaxX;
2840 +    double mdSrcGeoMaxY;
2841 +
2842 +    // This is not set until GetDAPArray() is called.
2843 +    double m_geo_transform_coef[6];
2844 +
2845 +    vector<GDAL_GCP> m_gdalGCPs;
2846 +
2847 +public:
2848 +    CPLErr SetGCPGeoRef4VRTDataset(GDALDataset*);
2849 +    void SetGeoBBoxAndGCPs(int xSize, int ySize);
2850 +    CPLErr RectifyGOESDataSet();
2851 +    CPLErr setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue);
2852 +
2853 +    int isValidLatitude(const double &lat)
2854 +    {
2855 +        return (lat >= -90 && lat <= 90);
2856 +    }
2857 +    int isValidLongitude(const double &lon)
2858 +    {
2859 +        return (lon >= -180 && lon <= 180);
2860 +    }
2861 +
2862 +    virtual CPLErr SetGeoTransform();
2863 +#if 0
2864 +    virtual CPLErr SetMetaDataList(GDALDataset* hSrcDS); //TODO Remove
2865 +#endif
2866 +    virtual CPLErr SetNativeCRS();
2867 +    virtual CPLErr SetGDALDataset(const int isSimple = 0);
2868 +    virtual CPLErr InitialDataset(const int isSimple = 0);
2869 +    virtual CPLErr GetGeoMinMax(double geoMinMax[]);
2870 +
2871 +public:
2872 +    DAP_Dataset();
2873 +    DAP_Dataset(const string& id, vector<int> &rBandList);
2874 +
2875 +    // Added jhrg 11/23/12
2876 +    DAP_Dataset(Array *src, Array *lat, Array *lon);
2877 +    Array *GetDAPArray();
2878 +    Grid *GetDAPGrid();
2879 +
2880 +    virtual ~DAP_Dataset();
2881 +};
2882 +
2883 +} // namespace libdap
2884 +#endif /* DAP_DATASET_H_ */
2885 diff -Nur bes-3.12.0/functions.orig/swath2grid/Makefile.am bes-3.12.0/functions/swath2grid/Makefile.am
2886 --- bes-3.12.0/functions.orig/swath2grid/Makefile.am    1970-01-01 01:00:00.000000000 +0100
2887 +++ bes-3.12.0/functions/swath2grid/Makefile.am 2014-03-03 15:47:38.056899595 +0100
2888 @@ -0,0 +1,106 @@
2889 +
2890 +# Build libswath2grid, part of libdap.
2891 +
2892 +AUTOMAKE_OPTIONS = foreign
2893
2894 +AM_CPPFLAGS = -I$(top_srcdir)/GNU -I$(top_srcdir) -I$(top_srcdir)/tests  -I$(top_srcdir)/dispatch $(XML2_CFLAGS) $(CURL_CFLAGS) 
2895 +AM_LDADD = 
2896 +
2897 +if CPPUNIT
2898 +AM_CPPFLAGS += $(CPPUNIT_CFLAGS)
2899 +AM_LDADD += $(CPPUNIT_LIBS)
2900 +endif
2901 +
2902 +# These are not used by automake but are often useful for certain types of
2903 +# debugging. The best way to use these is to run configure as:
2904 +#     export CXXFLAGS='...'; ./configure --disable-shared
2905 +# the --disable-shared is not required, but it seems to help with debuggers.
2906 +CXXFLAGS_DEBUG = -g3 -O0  -Wall -W -Wcast-align -Werror
2907 +TEST_COV_FLAGS = -ftest-coverage -fprofile-arcs
2908 +
2909 +# SUBDIRS = 
2910 +# DIST_SUBDIRS = 
2911 +
2912 +# This determines what gets built by make check
2913 +check_PROGRAMS = $(UNIT_TESTS)
2914 +
2915 +# This determines what gets run by 'make check.'
2916 +# Now (12/20/12) this fails; don't run until it works.
2917 +# TESTS = $(UNIT_TESTS)
2918 +
2919 +
2920 +noinst_LTLIBRARIES = libswath2grid.la
2921 +
2922 +libswath2grid_la_SOURCES = $(SRCS) $(HDRS)
2923 +libswath2grid_la_CPPFLAGS = $(GDAL_CFLAGS) $(XML2_CFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) -I$(top_srcdir)/dispatch
2924 +libswath2grid_la_LDFLAGS = 
2925 +libswath2grid_la_LIBADD = $(GDAL_LDFLAGS) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS)
2926 +
2927 +SRCS = AbstractDataset.cpp wcs_error.cpp    \
2928 +BoundingBox.cpp wcsUtil.cpp DAP_Dataset.cpp  reproj_functions.cc
2929 +
2930 +# NC_GOES_Dataset.cpp NC_GOES_Dataset.h
2931 +
2932 +HDRS = AbstractDataset.h wcs_error.h    \
2933 +BoundingBox.h wcsUtil.h DAP_Dataset.h reproj_functions.h
2934 +
2935 +if CPPUNIT
2936 +UNIT_TESTS = s2gTest
2937 +       
2938 +else
2939 +UNIT_TESTS =
2940 +
2941 +check-local:
2942 +       @echo ""
2943 +       @echo "**********************************************************"
2944 +       @echo "You must have cppunit 1.12.x or greater installed to run *"
2945 +       @echo "check target in unit-tests directory                     *"
2946 +       @echo "**********************************************************"
2947 +       @echo ""
2948 +endif
2949 +
2950 +s2gTest_SOURCES = s2gTest.cc
2951 +s2gTest_CPPFLAGS = $(AM_CPPFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) $(GDAL_CFLAGS)
2952 +s2gTest_LDADD = -ltest-types libswath2grid.la $(AM_LDADD)  $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS) $(GDAL_LDFLAGS) 
2953 +
2954 +if  LIBDAP
2955 +check-dap:
2956 +       @echo ""
2957 +       @echo "**********************************************************"
2958 +       @echo "USING DAP "
2959 +       @echo "DAP_CLIENT_CFLAGS:  " $(DAP_CLIENT_CFLAGS)
2960 +       @echo "DAP_SERVER_CFLAGS:  " $(DAP_SERVER_CFLAGS)
2961 +       @echo "DAP_CLIENT_LIBS:    " $(DAP_CLIENT_LIBS)
2962 +       @echo "DAP_SERVER_LIBS:    " $(DAP_SERVER_LIBS)
2963 +       @echo "**********************************************************"
2964 +       @echo ""
2965 +else
2966 +check-dap:
2967 +       @echo ""
2968 +       @echo "**********************************************************"
2969 +       @echo " Unable to locate DAP libraries!"
2970 +       @echo "**********************************************************"
2971 +       @echo ""
2972 +endif
2973 +
2974 +
2975 +if  GDAL_FOUND
2976 +check-gdal:
2977 +       @echo ""
2978 +       @echo "**********************************************************"
2979 +       @echo "Using gdal. "
2980 +       @echo "GDAL_CFLAGS:  " $(GDAL_CFLAGS)
2981 +       @echo "GDAL_LDFLAGS: " $(GDAL_LDFLAGS)
2982 +       @echo "**********************************************************"
2983 +       @echo ""
2984 +else
2985 +check-gdal:
2986 +       @echo ""
2987 +       @echo "**********************************************************"
2988 +       @echo "You must have gdal 12.15.12 or greater installed to run"
2989 +       @echo "check target in unit-tests directory                   "
2990 +       @echo "GDAL_VERSION: '$(GDAL_VERSION)'"
2991 +       @echo "prefix: '$(prefix)'"
2992 +       @echo "**********************************************************"
2993 +       @echo ""
2994 +endif
2995 diff -Nur bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.cpp bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.cpp
2996 --- bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.cpp    1970-01-01 01:00:00.000000000 +0100
2997 +++ bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.cpp 2014-03-03 15:47:38.053566262 +0100
2998 @@ -0,0 +1,625 @@
2999 +/******************************************************************************
3000 + * $Id: TRMM_Dataset.cpp 2011-07-19 16:24:00Z $
3001 + *
3002 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
3003 + *                      for Earth Observation: Open Source Reference Implementation
3004 + * Purpose:  NC_GOES_Dataset implementation for NOAA GOES data
3005 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
3006 + *
3007 + ******************************************************************************
3008 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
3009 + *
3010 + * Permission is hereby granted, free of charge, to any person obtaining a
3011 + * copy of this software and associated documentation files (the "Software"),
3012 + * to deal in the Software without restriction, including without limitation
3013 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
3014 + * and/or sell copies of the Software, and to permit persons to whom the
3015 + * Software is furnished to do so, subject to the following conditions:
3016 + *
3017 + * The above copyright notice and this permission notice shall be included
3018 + * in all copies or substantial portions of the Software.
3019 + *
3020 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3021 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3022 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
3023 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3024 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
3025 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
3026 + * DEALINGS IN THE SOFTWARE.
3027 + ****************************************************************************/
3028 +
3029 +#include "NC_GOES_Dataset.h"
3030 +
3031 +using namespace std;
3032 +
3033 +#define GOES_TIME_DEBUG FALSE
3034 +
3035 +NC_GOES_Dataset::NC_GOES_Dataset()
3036 +{
3037 +}
3038 +
3039 +/************************************************************************/
3040 +/*                           ~NC_GOES_Dataset()                         */
3041 +/************************************************************************/
3042 +
3043 +/**
3044 + * \brief Destroy an open NC_GOES_Dataset object.
3045 + *
3046 + * This is the accepted method of closing a NC_GOES_Dataset dataset and
3047 + * deallocating all resources associated with it.
3048 + */
3049 +
3050 +NC_GOES_Dataset::~NC_GOES_Dataset()
3051 +{
3052 +}
3053 +
3054 +/************************************************************************/
3055 +/*                           NC_GOES_Dataset()                          */
3056 +/************************************************************************/
3057 +
3058 +/**
3059 + * \brief Create an NC_GOES_Dataset object.
3060 + *
3061 + * This is the accepted method of creating a NC_GOES_Dataset object and
3062 + * allocating all resources associated with it.
3063 + *
3064 + * @param id The coverage identifier.
3065 + *
3066 + * @param rBandList The field list selected for this coverage. For TRMM
3067 + * daily data, the user could specify multiple days range in request.
3068 + * Each day is seemed as one field.
3069 + *
3070 + * @return A NC_GOES_Dataset object.
3071 + */
3072 +
3073 +NC_GOES_Dataset::NC_GOES_Dataset(const string& id, vector<int> &rBandList) :
3074 +       AbstractDataset(id, rBandList)
3075 +{
3076 +       md_MissingValue = 0;
3077 +       mb_GeoTransformSet = FALSE;
3078 +}
3079 +
3080 +/************************************************************************/
3081 +/*                           InitialDataset()                           */
3082 +/************************************************************************/
3083 +
3084 +/**
3085 + * \brief Initialize the GOES dataset with NetCDF format.
3086 +
3087 + * This method is the implementation for initializing a GOES dataset with NetCDF format.
3088 + * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
3089 + * will be called to initialize an GOES dataset.
3090 + *
3091 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
3092 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
3093 + *
3094 + * @return CE_None on success or CE_Failure on failure.
3095 + */
3096 +
3097 +CPLErr NC_GOES_Dataset::InitialDataset(const int isSimple)
3098 +{
3099 +       vector<string> strSet;
3100 +       unsigned int n = CsvburstCpp(ms_CoverageID, strSet, ':');
3101 +       if (n != 4)
3102 +       {
3103 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
3104 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Incorrect coverage ID.");
3105 +               return CE_Failure;
3106 +       }
3107 +
3108 +       ms_DataTypeName = strSet[0] + ":" + strSet[1];
3109 +       ms_SrcFilename = StrTrims(strSet[2], " \'\"");
3110 +       ms_DatasetName = strSet[3];
3111 +
3112 +       m_ncLatDataSetName = "NETCDF:" + ms_SrcFilename + ":latitude";
3113 +       m_ncLonDataSetName = "NETCDF:" + ms_SrcFilename + ":longitude";
3114 +       m_ncCoverageIDName = strSet[1] + ":" + strSet[2] + ":" + strSet[3];
3115 +
3116 +       GDALDataset* pSrc = (GDALDataset*) GDALOpenShared(m_ncCoverageIDName.c_str(), GA_ReadOnly);
3117 +       if (pSrc == NULL)
3118 +       {
3119 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
3120 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open file \"%s\".", ms_SrcFilename.c_str());
3121 +               return CE_Failure;
3122 +       }
3123 +
3124 +       ms_NativeFormat = GDALGetDriverShortName(pSrc->GetDriver());
3125 +
3126 +       //setmetalist
3127 +       SetMetaDataList(pSrc);
3128 +
3129 +       //set noValue
3130 +       unsigned int nBandCount = pSrc->GetRasterCount();
3131 +       if (nBandCount < 1)
3132 +       {
3133 +               GDALClose(pSrc);
3134 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
3135 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The GOES file does not contain any raster band.");
3136 +               return CE_Failure;
3137 +       }
3138 +
3139 +       maptr_DS.reset(pSrc);
3140 +
3141 +       //set moNativeCRS and mGeoTransform
3142 +       if (CE_None != SetNativeCRS() ||
3143 +               CE_None != SetGeoTransform() ||
3144 +               CE_None != SetGDALDataset(isSimple))
3145 +       {
3146 +               GDALClose(maptr_DS.release());
3147 +               return CE_Failure;
3148 +       }
3149 +
3150 +       return CE_None;
3151 +}
3152 +
3153 +/************************************************************************/
3154 +/*                            SetNativeCRS()                            */
3155 +/************************************************************************/
3156 +
3157 +/**
3158 + * \brief Set the Native CRS for a GOES dataset.
3159 + *
3160 + * The method will set the CRS for a GOES dataset as an native CRS.
3161 + *
3162 + * Since the original GOES data adopt satellite CRS to recored its value,
3163 + * like MODIS swath data, each data point has its corresponding latitude
3164 + * and longitude value, those coordinates could be fetched in another two fields.
3165 + *
3166 + * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
3167 + * both the latitude and longitude are existed.
3168 + *
3169 + * @return CE_None on success or CE_Failure on failure.
3170 + */
3171 +
3172 +CPLErr NC_GOES_Dataset::SetNativeCRS()
3173 +{
3174 +       if (CE_None == AbstractDataset::SetNativeCRS())
3175 +               return CE_None;
3176 +
3177 +       GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
3178 +       GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
3179 +
3180 +       if(hLatDS == NULL) {
3181 +               m_ncLatDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lat";
3182 +               hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
3183 +       }
3184 +
3185 +       if(hLonDS == NULL) {
3186 +               m_ncLonDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lon";
3187 +               hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
3188 +       }
3189 +
3190 +       if (hLatDS == NULL || hLonDS == NULL)
3191 +       {
3192 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetNativeCRS()");
3193 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open latitude/longitude sub-dataset.");
3194 +               return CE_Failure;
3195 +       }
3196 +
3197 +       mo_NativeCRS.SetWellKnownGeogCS("WGS84");
3198 +
3199 +       GDALClose(hLatDS);
3200 +       GDALClose(hLonDS);
3201 +
3202 +       return CE_None;
3203 +}
3204 +
3205 +/************************************************************************/
3206 +/*                           SetGeoTransform()                          */
3207 +/************************************************************************/
3208 +
3209 +/**
3210 + * \brief Set the affine GeoTransform matrix for a GOES data.
3211 + *
3212 + * The method will set a GeoTransform matrix for a GOES data
3213 + * by parsing the coordinates values existed in longitude and latitude field.
3214 + *
3215 + * The CRS for the bounding box is EPSG:4326.
3216 + *
3217 + * @return CE_None on success or CE_Failure on failure.
3218 + */
3219 +
3220 +CPLErr NC_GOES_Dataset::SetGeoTransform()
3221 +{
3222 +       if (CE_None == AbstractDataset::SetGeoTransform())
3223 +               return CE_None;
3224 +
3225 +       if (CE_None != SetGeoBBoxAndGCPs(maptr_DS.get()))
3226 +               return CE_Failure;
3227 +
3228 +       double resX, resY;
3229 +       if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
3230 +               resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
3231 +       else
3232 +               resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
3233 +
3234 +       resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (maptr_DS->GetRasterYSize() - 1);
3235 +
3236 +       double res = MIN(resX,resY);
3237 +
3238 +       if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
3239 +               mi_RectifiedImageXSize = (int)((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
3240 +       else
3241 +               mi_RectifiedImageXSize = (int)((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
3242 +
3243 +       mi_RectifiedImageYSize = (int)fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
3244 +
3245 +       md_Geotransform[0] = mdSrcGeoMinX;
3246 +       md_Geotransform[1] = res;
3247 +       md_Geotransform[2] = 0;
3248 +       md_Geotransform[3] = mdSrcGeoMaxY;
3249 +       md_Geotransform[4] = 0;
3250 +       md_Geotransform[5] = -res;
3251 +       mb_GeoTransformSet = TRUE;
3252 +
3253 +       return CE_None;
3254 +}
3255 +
3256 +CPLErr NC_GOES_Dataset::setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue)
3257 +{
3258 +       static int RESAMPLE_STANDARD = 500;
3259 +       int nXSize = hSrcDS->GetRasterXSize();
3260 +       int nYSize = hSrcDS->GetRasterYSize();
3261 +
3262 +       xRSValue = int(nXSize / RESAMPLE_STANDARD) + 2;
3263 +       yRSValue = int(nYSize / RESAMPLE_STANDARD) + 2;
3264 +
3265 +       return CE_None;
3266 +}
3267 +
3268 +/************************************************************************/
3269 +/*                         SetGeoBBoxAndGCPs()                          */
3270 +/************************************************************************/
3271 +
3272 +/**
3273 + * \brief Set the native geographical bounding box and GCP array for a GOES data.
3274 + *
3275 + * The method will set the native geographical bounding box
3276 + * by comparing the coordinates values existed in longitude and latitude field.
3277 + *
3278 + * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
3279 + *
3280 + * @return CE_None on success or CE_Failure on failure.
3281 + */
3282 +
3283 +CPLErr NC_GOES_Dataset::SetGeoBBoxAndGCPs(GDALDataset* poVDS)
3284 +{
3285 +       GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
3286 +       GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
3287 +
3288 +       int nXSize = poVDS->GetRasterXSize();
3289 +       int nYSize = poVDS->GetRasterYSize();
3290 +
3291 +       mi_GoesSrcImageXSize = nXSize;
3292 +       mi_GoesSrcImageYSize = nYSize;
3293 +
3294 +       int nLatXSize = hLatDS->GetRasterXSize();
3295 +       int nLatYSize = hLatDS->GetRasterYSize();
3296 +       int nLonXSize = hLonDS->GetRasterXSize();
3297 +       int nLonYSize = hLonDS->GetRasterYSize();
3298 +
3299 +       if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
3300 +       {
3301 +               GDALClose(hLatDS);
3302 +               GDALClose(hLonDS);
3303 +
3304 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGeoBBoxAndGCPs()");
3305 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The size of latitude/longitude and data field does not match.");
3306 +
3307 +               return CE_Failure;
3308 +       }
3309 +
3310 +       /*
3311 +       *       Re-sample Standards:
3312 +       *       Height | Width
3313 +       *       (0, 500)                every other one pixel
3314 +       *       [500, 1000)             every other two pixels
3315 +       *       [1000,1500)             every other three pixels
3316 +       *       [1500,2000)             every other four pixels
3317 +       *       ... ...
3318 +       */
3319 +
3320 +       int xSpace = 1;
3321 +       int ySpace = 1;
3322 +       setResampleStandard(poVDS, xSpace, ySpace);
3323 +
3324 +       int nGCPs = 0;
3325 +       GDAL_GCP gdalCGP;
3326 +
3327 +       GDALRasterBand *poBandLat = hLatDS->GetRasterBand(1);
3328 +       GDALRasterBand *poBandLon = hLonDS->GetRasterBand(1);
3329 +       GDALDataType eDT = poBandLat->GetRasterDataType();
3330 +       void *dataLat = NULL;
3331 +       void *dataLon = NULL;
3332 +
3333 +       mdSrcGeoMinX = 360;
3334 +       mdSrcGeoMaxX = -360;
3335 +       mdSrcGeoMinY = 90;
3336 +       mdSrcGeoMaxY = -90;
3337 +
3338 +       switch (eDT)
3339 +       {
3340 +       case GDT_Float32: //For GOES Imager and Sounder data
3341 +       {
3342 +               dataLat = (float *) CPLMalloc(nXSize * sizeof(float));
3343 +               dataLon = (float *) CPLMalloc(nXSize * sizeof(float));
3344 +
3345 +               for (int iLine = 0; iLine < nYSize; iLine += ySpace)
3346 +               {
3347 +                       if (iLine >= nYSize)
3348 +                               iLine = nYSize - 1;
3349 +
3350 +                       poBandLat->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLat, nXSize, 1, GDT_Float32, 0, 0);
3351 +                       poBandLon->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLon, nXSize, 1, GDT_Float32, 0, 0);
3352 +
3353 +                       for (int iPixel = 0; iPixel < nXSize; iPixel += xSpace)
3354 +                       {
3355 +                               if(iPixel >= nXSize)
3356 +                                       iPixel = nXSize - 1;
3357 +                               double x = *((float *) dataLon + iPixel);
3358 +                               double y = *((float *) dataLat + iPixel);
3359 +                               if (isValidLongitude(x) && isValidLatitude(y))
3360 +                               {
3361 +                                       char pChr[64];
3362 +                                       sprintf(pChr, "%d", ++nGCPs);
3363 +                                       GDALInitGCPs(1, &gdalCGP);
3364 +                                       gdalCGP.pszId = strdup(pChr);
3365 +                                       gdalCGP.pszInfo = strdup("");
3366 +                                       gdalCGP.dfGCPLine = iLine;
3367 +                                       gdalCGP.dfGCPPixel = iPixel;
3368 +                                       gdalCGP.dfGCPX = x;
3369 +                                       gdalCGP.dfGCPY = y;
3370 +                                       gdalCGP.dfGCPZ = 0;
3371 +                                       m_gdalGCPs.push_back(gdalCGP);
3372 +                                       mdSrcGeoMinX = MIN(mdSrcGeoMinX,gdalCGP.dfGCPX );
3373 +                                       mdSrcGeoMaxX = MAX(mdSrcGeoMaxX,gdalCGP.dfGCPX);
3374 +                                       mdSrcGeoMinY = MIN(mdSrcGeoMinY,gdalCGP.dfGCPY);
3375 +                                       mdSrcGeoMaxY = MAX(mdSrcGeoMaxY,gdalCGP.dfGCPY);
3376 +                               }
3377 +                       }
3378 +               }
3379 +
3380 +               VSIFree((float *) dataLat);
3381 +               VSIFree((float *) dataLon);
3382 +       }
3383 +               break;
3384 +
3385 +       default:
3386 +               break;
3387 +       }
3388 +
3389 +       GDALClose(hLatDS);
3390 +       GDALClose(hLonDS);
3391 +
3392 +       return CE_None;
3393 +}
3394 +
3395 +
3396 +/************************************************************************/
3397 +/*                           SetGDALDataset()                           */
3398 +/************************************************************************/
3399 +
3400 +/**
3401 + * \brief Set the GDALDataset object to GOES Imager and Sounder dataset.
3402 + *
3403 + * This method is used to set the GOES Imager and Sounder dataset based on GDAL
3404 + * class VRTDataset.
3405 + *
3406 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
3407 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
3408 + *
3409 + * @return CE_None on success or CE_Failure on failure.
3410 + */
3411 +
3412 +CPLErr NC_GOES_Dataset::SetGDALDataset(const int isSimple)
3413 +{
3414 +       for(int i = 1; i <= maptr_DS->GetRasterCount(); ++i)
3415 +               mv_BandList.push_back(i);
3416 +
3417 +       VRTDataset *poVDS = (VRTDataset *)VRTCreate(mi_RectifiedImageXSize, mi_RectifiedImageYSize);
3418 +       if (poVDS == NULL)
3419 +       {
3420 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGDALDataset()");
3421 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to create VRT DataSet.");
3422 +               return CE_Failure;
3423 +       }
3424 +
3425 +       VRTSourcedRasterBand *poVRTBand = NULL;
3426 +       GDALRasterBand *poSrcBand = NULL;
3427 +       GDALDataType eBandType;
3428 +       for (unsigned int i = 0; i < mv_BandList.size(); i++)
3429 +       {
3430 +               poSrcBand = maptr_DS->GetRasterBand(mv_BandList[i]);
3431 +               eBandType = poSrcBand->GetRasterDataType();
3432 +               poVDS->AddBand(eBandType, NULL);
3433 +               poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand(i + 1);
3434 +               poVRTBand->SetNoDataValue(md_MissingValue);
3435 +
3436 +               if (CE_None != poVRTBand->AddSimpleSource(poSrcBand, 0, 0,
3437 +                               mi_RectifiedImageXSize, mi_RectifiedImageYSize, 0, 0,
3438 +                               mi_RectifiedImageXSize, mi_RectifiedImageYSize, NULL, md_MissingValue))
3439 +               {
3440 +                       GDALClose((GDALDatasetH) poVDS);
3441 +                       SetWCS_ErrorLocator("NC_GOES_Dataset::setGDALDataset()");
3442 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Add Simple Source into VRT DataSet.");
3443 +                       return CE_Failure;
3444 +               }
3445 +       }
3446 +
3447 +       //set GCPs for this VRTDataset
3448 +       if (CE_None != SetGCPGeoRef4VRTDataset(poVDS))
3449 +       {
3450 +               GDALClose((GDALDatasetH) poVDS);
3451 +               return CE_Failure;
3452 +       }
3453 +
3454 +       GDALClose(maptr_DS.release());
3455 +       maptr_DS.reset(poVDS);
3456 +
3457 +       if (isSimple)
3458 +               return CE_None;
3459 +
3460 +       return RectifyGOESDataSet();
3461 +}
3462 +
3463 +/************************************************************************/
3464 +/*                       SetGCPGeoRef4VRTDataset()                      */
3465 +/************************************************************************/
3466 +
3467 +/**
3468 + * \brief Set the GCP array for the VRT dataset.
3469 + *
3470 + * This method is used to set the GCP array to created VRT dataset based on GDAL
3471 + * method SetGCPs().
3472 + *
3473 + * @param poVDS The VRT dataset.
3474 + *
3475 + * @return CE_None on success or CE_Failure on failure.
3476 + */
3477 +
3478 +CPLErr NC_GOES_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
3479 +{
3480 +       char* psTargetSRS;
3481 +       mo_NativeCRS.exportToWkt(&psTargetSRS);
3482 +
3483 +#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
3484 +       if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS))
3485 +       {
3486 +               OGRFree(psTargetSRS);
3487 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
3488 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to set GCPs.");
3489 +
3490 +               return CE_Failure;
3491 +       }
3492 +#else
3493 +       {
3494 +               if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
3495 +               {
3496 +                       OGRFree( psTargetSRS );
3497 +                       SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
3498 +                       WCS_Error(CE_Failure,OGC_WCS_NoApplicableCode,"Failed to set GCPs.");
3499 +
3500 +                       return CE_Failure;
3501 +               }
3502 +       }
3503 +#endif
3504 +
3505 +       OGRFree(psTargetSRS);
3506 +
3507 +       return CE_None;
3508 +}
3509 +
3510 +/************************************************************************/
3511 +/*                        SetMetaDataList()                             */
3512 +/************************************************************************/
3513 +
3514 +/**
3515 + * \brief Set the metadata list for this coverage.
3516 + *
3517 + * The method will set the metadata list for the coverage based on its
3518 + * corresponding GDALDataset object.
3519 + *
3520 + * @param hSrc the GDALDataset object corresponding to coverage.
3521 + *
3522 + * @return CE_None on success or CE_Failure on failure.
3523 + */
3524 +
3525 +CPLErr NC_GOES_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
3526 +{
3527 +       mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
3528 +       mv_MetaDataList.push_back("unit=GVAR");
3529 +       mv_MetaDataList.push_back("FillValue=0");
3530 +       ms_FieldQuantityDef = "GVAR";
3531 +       ms_AllowRanges = "0 65535";
3532 +       ms_CoveragePlatform = "GOES-11";
3533 +       ms_CoverageInstrument = "GOES-11";
3534 +       ms_CoverageSensor = "Imager";
3535 +
3536 +       return CE_None;
3537 +}
3538 +
3539 +/************************************************************************/
3540 +/*                          GetGeoMinMax()                              */
3541 +/************************************************************************/
3542 +
3543 +/**
3544 + * \brief Get the min/max coordinates of laitutude and longitude.
3545 + *
3546 + * The method will fetch the min/max coordinates of laitutude and longitude.
3547 + *
3548 + * @param geoMinMax an existing four double buffer into which the
3549 + * native geographical bounding box values will be placed.
3550 + *
3551 + * @return CE_None on success or CE_Failure on failure.
3552 + */
3553 +
3554 +CPLErr NC_GOES_Dataset::GetGeoMinMax(double geoMinMax[])
3555 +{
3556 +       if (!mb_GeoTransformSet)
3557 +               return CE_Failure;
3558 +
3559 +       geoMinMax[0] = mdSrcGeoMinX;
3560 +       geoMinMax[2] = mdSrcGeoMinY;
3561 +       geoMinMax[1] = mdSrcGeoMaxX;
3562 +       geoMinMax[3] = mdSrcGeoMaxY;
3563 +
3564 +       return CE_None;
3565 +}
3566 +
3567 +/************************************************************************/
3568 +/*                          GetGeoMinMax()                              */
3569 +/************************************************************************/
3570 +
3571 +/**
3572 + * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
3573 + *
3574 + * The method will convert the GOES dataset from satellite CRS project to
3575 + * grid CRS based on GDAL API GDALReprojectImage;
3576 + *
3577 + * @return CE_None on success or CE_Failure on failure.
3578 + */
3579 +
3580 +CPLErr NC_GOES_Dataset::RectifyGOESDataSet()
3581 +{
3582 +       char *pszDstWKT;
3583 +       mo_NativeCRS.exportToWkt(&pszDstWKT);
3584 +
3585 +       GDALDriverH poDriver = GDALGetDriverByName("MEM");
3586 +       GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize,
3587 +                       mi_RectifiedImageYSize, maptr_DS->GetRasterCount(),
3588 +                       maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
3589 +       if (NULL == rectDataSet)
3590 +       {
3591 +               GDALClose(poDriver);
3592 +               OGRFree(pszDstWKT);
3593 +               SetWCS_ErrorLocator("AbstractDataset::rectifyDataSet()");
3594 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
3595 +                               "Failed to create \"MEM\" dataSet.");
3596 +
3597 +               return CE_Failure;
3598 +       }
3599 +
3600 +       rectDataSet->SetProjection(pszDstWKT);
3601 +       rectDataSet->SetGeoTransform(md_Geotransform);
3602 +
3603 +       if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet,
3604 +                       pszDstWKT, GRA_NearestNeighbour, 0, 0.125, NULL, NULL, NULL))
3605 +       {
3606 +               GDALClose(rectDataSet);
3607 +               GDALClose(poDriver);
3608 +               OGRFree(pszDstWKT);
3609 +               SetWCS_ErrorLocator("AbstractDataset::RectifyDataSet()");
3610 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
3611 +                               "Failed to re-project GOES data from satellite GCP CRS to geographical CRS.");
3612 +
3613 +               return CE_Failure;
3614 +       }
3615 +
3616 +       OGRFree(pszDstWKT);
3617 +       GDALClose(maptr_DS.release());
3618 +
3619 +       maptr_DS.reset(rectDataSet);
3620 +
3621 +       return CE_None;
3622 +}
3623 +
3624 diff -Nur bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.h bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.h
3625 --- bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.h      1970-01-01 01:00:00.000000000 +0100
3626 +++ bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.h   2014-03-03 15:47:38.053566262 +0100
3627 @@ -0,0 +1,124 @@
3628 +/******************************************************************************
3629 + * $Id: NC_GOES_Dataset.h 2011-07-19 16:24:00Z $
3630 + *
3631 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
3632 + *                      for Earth Observation: Open Source Reference Implementation
3633 + * Purpose:  NC_GOES_Dataset class definition
3634 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
3635 + *
3636 + ******************************************************************************
3637 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
3638 + *
3639 + * Permission is hereby granted, free of charge, to any person obtaining a
3640 + * copy of this software and associated documentation files (the "Software"),
3641 + * to deal in the Software without restriction, including without limitation
3642 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
3643 + * and/or sell copies of the Software, and to permit persons to whom the
3644 + * Software is furnished to do so, subject to the following conditions:
3645 + *
3646 + * The above copyright notice and this permission notice shall be included
3647 + * in all copies or substantial portions of the Software.
3648 + *
3649 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3650 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3651 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
3652 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3653 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
3654 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
3655 + * DEALINGS IN THE SOFTWARE.
3656 + ****************************************************************************/
3657 +
3658 +#ifndef NC_GOES_DATASET_H_
3659 +#define NC_GOES_DATASET_H_
3660 +
3661 +#include <string>
3662 +#include "AbstractDataset.h"
3663 +#include "wcsUtil.h"
3664 +
3665 +using namespace std;
3666 +
3667 +/************************************************************************/
3668 +/* ==================================================================== */
3669 +/*                           NC_GOES_Dataset                            */
3670 +/* ==================================================================== */
3671 +/************************************************************************/
3672 +
3673 +//! NC_GOES_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
3674 +
3675 +/**
3676 + * \class NC_GOES_Dataset "NC_GOES_Dataset.h"
3677 + *
3678 + * GOES satellites provide the kind of continuous monitoring necessary for
3679 + * intensive data analysis. They circle the Earth in a geosynchronous orbit,
3680 + * which means they orbit the equatorial plane of the Earth at a speed
3681 + * matching the Earth's rotation. This allows them to hover continuously
3682 + * over one position on the surface. The geosynchronous plane is about
3683 + * 35,800 km (22,300 miles) above the Earth, high enough to allow the
3684 + * satellites a full-disc view of the Earth. Because they stay above a
3685 + * fixed spot on the surface, they provide a constant vigil for the atmospheric
3686 + * "triggers" for severe weather conditions such as tornadoes, flash floods,
3687 + * hail storms, and hurricanes. When these conditions develop the GOES
3688 + * satellites are able to monitor storm development and track their movements.
3689 + *
3690 + * GOES satellite imagery is also used to estimate rainfall during
3691 + * the thunderstorms and hurricanes for flash flood warnings, as well
3692 + * as estimates snowfall accumulations and overall extent of snow cover.
3693 + * Such data help meteorologists issue winter storm warnings and spring
3694 + * snow melt advisories. Satellite sensors also detect ice fields and map
3695 + * the movements of sea and lake ice.
3696 + *
3697 + * For more inforamtion about NOAA GOES data, please access
3698 + * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
3699 + *
3700 + * NC_GOES_Dataset is a subclass of AbstractDataset, which is used to
3701 + * process GOES Imager and Sounder products.
3702 + */
3703 +
3704 +class NC_GOES_Dataset : public AbstractDataset
3705 +{
3706 +protected:
3707 +       string  m_ncLatDataSetName;
3708 +       string  m_ncLonDataSetName;
3709 +       string  m_ncCoverageIDName;
3710 +       int     mi_RectifiedImageXSize;
3711 +       int     mi_RectifiedImageYSize;
3712 +       int             mi_GoesSrcImageXSize;
3713 +       int             mi_GoesSrcImageYSize;
3714 +
3715 +       double  mb_LatLonBBox[4];
3716 +       double  mdSrcGeoMinX;
3717 +       double  mdSrcGeoMinY;
3718 +       double  mdSrcGeoMaxX;
3719 +       double  mdSrcGeoMaxY;
3720 +
3721 +       vector<GDAL_GCP>                m_gdalGCPs;
3722 +
3723 +public:
3724 +       CPLErr SetGCPGeoRef4VRTDataset(GDALDataset* );
3725 +       CPLErr SetGeoBBoxAndGCPs(GDALDataset* hSrcDS);
3726 +       CPLErr RectifyGOESDataSet();
3727 +       CPLErr setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue);
3728 +
3729 +       int isValidLatitude(const double &lat)
3730 +       {
3731 +               return (lat >= -90 && lat <= 90);
3732 +       }
3733 +       int isValidLongitude(const double &lon)
3734 +       {
3735 +               return (lon >= -180 && lon <= 180);
3736 +       }
3737 +
3738 +       virtual CPLErr SetGeoTransform();
3739 +       virtual CPLErr SetMetaDataList(GDALDataset* hSrcDS);
3740 +       virtual CPLErr SetNativeCRS();
3741 +       virtual CPLErr SetGDALDataset(const int isSimple=0);
3742 +       virtual CPLErr InitialDataset(const int isSimple=0);
3743 +       virtual CPLErr GetGeoMinMax(double geoMinMax[]);
3744 +
3745 +public:
3746 +       NC_GOES_Dataset();
3747 +       NC_GOES_Dataset(const string& id, vector<int>  &rBandList);
3748 +       virtual ~NC_GOES_Dataset();
3749 +};
3750 +
3751 +#endif /* NC_GOES_DATASET_H_ */
3752 diff -Nur bes-3.12.0/functions.orig/swath2grid/reproj_functions.cc bes-3.12.0/functions/swath2grid/reproj_functions.cc
3753 --- bes-3.12.0/functions.orig/swath2grid/reproj_functions.cc    1970-01-01 01:00:00.000000000 +0100
3754 +++ bes-3.12.0/functions/swath2grid/reproj_functions.cc 2014-03-03 15:47:38.056899595 +0100
3755 @@ -0,0 +1,209 @@
3756 +// -*- mode: c++; c-basic-offset:4 -*-
3757 +
3758 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
3759 +// Access Protocol.
3760 +
3761 +// Copyright (c) 2002,2003 OPeNDAP, Inc.
3762 +// Author: James Gallagher <jgallagher@opendap.org>
3763 +//
3764 +// This library is free software; you can redistribute it and/or
3765 +// modify it under the terms of the GNU Lesser General Public
3766 +// License as published by the Free Software Foundation; either
3767 +// version 2.1 of the License, or (at your option) any later version.
3768 +//
3769 +// This library is distributed in the hope that it will be useful,
3770 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
3771 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3772 +// Lesser General Public License for more details.
3773 +//
3774 +// You should have received a copy of the GNU Lesser General Public
3775 +// License along with this library; if not, write to the Free Software
3776 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
3777 +//
3778 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
3779 +
3780 +// (c) COPYRIGHT URI/MIT 1999
3781 +// Please read the full copyright statement in the file COPYRIGHT_URI.
3782 +//
3783 +// Authors:
3784 +//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
3785 +
3786 +
3787 +// These functions are used by the CE evaluator
3788 +//
3789 +// 1/15/99 jhrg
3790 +
3791 +#include "config.h"
3792 +
3793 +#include <limits.h>
3794 +
3795 +#if 0
3796 +#include <cstdlib>      // used by strtod()
3797 +#include <cerrno>
3798 +#include <cmath>
3799 +#endif
3800 +#include <iostream>
3801 +#if 0
3802 +#include <vector>
3803 +#include <algorithm>
3804 +#endif
3805 +
3806 +// #include <gdal.h>
3807 +// #include <gdal_priv.h>
3808 +
3809 +#define DODS_DEBUG
3810 +
3811 +#include "BaseType.h"
3812 +
3813 +#include "Str.h"
3814 +#include "Array.h"
3815 +#include "Grid.h"
3816 +
3817 +#include "Error.h"
3818 +#include "debug.h"
3819 +
3820 +#include "DAP_Dataset.h"
3821 +#include "reproj_functions.h"
3822 +
3823 +//  We wrapped VC++ 6.x strtod() to account for a short coming
3824 +//  in that function in regards to "NaN".  I don't know if this
3825 +//  still applies in more recent versions of that product.
3826 +//  ROM - 12/2007
3827 +#ifdef WIN32
3828 +#include <limits>
3829 +double w32strtod(const char *, char **);
3830 +#endif
3831 +
3832 +using namespace std;
3833 +//using namespace libdap;
3834 +
3835 +namespace libdap {
3836 +
3837 +/**
3838 + * @todo The lat and lon arrays are passed in, but there's an assumption that the
3839 + * source data array and the two lat and lon arrays are the same shape. But the
3840 + * code does not actually test that.
3841 + *
3842 + * @todo Enable multiple bands paired with just the two lat/lon arrays? Not sure
3843 + * if that is a good idea...
3844 + */
3845 +void function_swath2array(int argc, BaseType * argv[], DDS &, BaseType **btpp)
3846 +{
3847 +    DBG(cerr << "Entering function_swath2array..." << endl);
3848 +
3849 +    // Use the same documentation for both swath2array and swath2grid
3850 +    string info = string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
3851 +               + "<function name=\"swath2array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid\">\n"
3852 +            + "</function>\n";
3853 +
3854 +    if (argc == 0) {
3855 +        Str *response = new Str("info");
3856 +        response->set_value(info);
3857 +        *btpp = response;
3858 +        return;
3859 +    }
3860 +
3861 +    // TODO Add optional fourth arg that lets the caller say which datum to use;
3862 +    // default to WGS84
3863 +    if (argc != 3)
3864 +       throw Error("The function swath2array() requires three arguments. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3865 +
3866 +    Array *src = dynamic_cast<Array*>(argv[0]);
3867 +    if (!src)
3868 +       throw Error("The first argument to swath2array() must be a data array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3869 +
3870 +    Array *lat = dynamic_cast<Array*>(argv[1]);
3871 +    if (!lat)
3872 +       throw Error("The second argument to swath2array() must be a latitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3873 +
3874 +    Array *lon = dynamic_cast<Array*>(argv[2]);
3875 +    if (!lon)
3876 +       throw Error("The third argument to swath2array() must be a longitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3877 +
3878 +    // The args passed into the function using argv[] are deleted after the call.
3879 +
3880 +    DAP_Dataset ds(src, lat, lon);
3881 +
3882 +    try {
3883 +        ds.InitialDataset(0);
3884 +
3885 +        *btpp = ds.GetDAPArray();
3886 +    }
3887 +    catch (Error &e) {
3888 +        DBG(cerr << "caught Error: " << e.get_error_message() << endl);
3889 +        throw e;
3890 +    }
3891 +    catch(...) {
3892 +        DBG(cerr << "caught unknown exception" << endl);
3893 +        throw;
3894 +    }
3895 +
3896 +    return;
3897 +}
3898 +
3899 +/**
3900 + * @todo The lat and lon arrays are passed in, but there's an assumption that the
3901 + * source data array and the two lat and lon arrays are the same shape. But the
3902 + * code does not actually test that.
3903 + *
3904 + * @todo Enable multiple bands paired with just the two lat/lon arrays? Not sure
3905 + * if that is a good idea...
3906 + */
3907 +void function_swath2grid(int argc, BaseType * argv[], DDS &, BaseType **btpp)
3908 +{
3909 +    DBG(cerr << "Entering function_swath2grid..." << endl);
3910 +
3911 +    string info = string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
3912 +               + "<function name=\"swath2grid\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid\">\n"
3913 +            + "</function>\n";
3914 +
3915 +    if (argc == 0) {
3916 +        Str *response = new Str("info");
3917 +        response->set_value(info);
3918 +        *btpp = response;
3919 +        return;
3920 +    }
3921 +
3922 +    // TODO Add optional fourth arg that lets the caller say which datum to use;
3923 +    // default to WGS84
3924 +    if (argc != 3)
3925 +       throw Error("The function swath2grid() requires three arguments. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3926 +
3927 +    Array *src = dynamic_cast<Array*>(argv[0]);
3928 +    if (!src)
3929 +       throw Error("The first argument to swath2grid() must be a data array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3930 +
3931 +    Array *lat = dynamic_cast<Array*>(argv[1]);
3932 +    if (!lat)
3933 +       throw Error("The second argument to swath2grid() must be a latitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3934 +
3935 +    Array *lon = dynamic_cast<Array*>(argv[2]);
3936 +    if (!lon)
3937 +       throw Error("The third argument to swath2grid() must be a longitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
3938 +
3939 +    // The args passed into the function using argv[] are deleted after the call.
3940 +
3941 +    DAP_Dataset ds(src, lat, lon);
3942 +
3943 +    try {
3944 +        ds.InitialDataset(0);
3945 +
3946 +        *btpp = ds.GetDAPGrid();
3947 +    }
3948 +    catch (Error &e) {
3949 +        DBG(cerr << "caught Error: " << e.get_error_message() << endl);
3950 +        throw e;
3951 +    }
3952 +    catch(...) {
3953 +        DBG(cerr << "caught unknown exception" << endl);
3954 +        throw;
3955 +    }
3956 +
3957 +    return;
3958 +}
3959 +
3960 +
3961 +
3962 +
3963 +
3964 +} // namespace libdap
3965 diff -Nur bes-3.12.0/functions.orig/swath2grid/reproj_functions.h bes-3.12.0/functions/swath2grid/reproj_functions.h
3966 --- bes-3.12.0/functions.orig/swath2grid/reproj_functions.h     1970-01-01 01:00:00.000000000 +0100
3967 +++ bes-3.12.0/functions/swath2grid/reproj_functions.h  2014-03-03 15:47:38.043566262 +0100
3968 @@ -0,0 +1,109 @@
3969 +
3970 +// -*- mode: c++; c-basic-offset:4 -*-
3971 +
3972 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
3973 +// Access Protocol.
3974 +
3975 +// Copyright (c) 2002,2003 OPeNDAP, Inc.
3976 +// Author: James Gallagher <jgallagher@opendap.org>
3977 +//
3978 +// This library is free software; you can redistribute it and/or
3979 +// modify it under the terms of the GNU Lesser General Public
3980 +// License as published by the Free Software Foundation; either
3981 +// version 2.1 of the License, or (at your option) any later version.
3982 +//
3983 +// This library is distributed in the hope that it will be useful,
3984 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
3985 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
3986 +// Lesser General Public License for more details.
3987 +//
3988 +// You should have received a copy of the GNU Lesser General Public
3989 +// License along with this library; if not, write to the Free Software
3990 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
3991 +//
3992 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
3993 +
3994 +// (c) COPYRIGHT URI/MIT 1999
3995 +// Please read the full copyright statement in the file COPYRIGHT_URI.
3996 +//
3997 +// Authors:
3998 +//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
3999 +
4000 +// Declarations for CE functions.
4001 +//
4002 +// 1/15/99 jhrg
4003 +
4004 +#ifndef _reproj_functions_h
4005 +#define _reproj_functions_h
4006 +
4007 +#include "BESAbstractModule.h"
4008 +#include "ServerFunction.h"
4009 +#include "ServerFunctionsList.h"
4010 +
4011 +namespace libdap {
4012 +
4013 +void function_swath2array(int argc, BaseType * argv[], DDS &, BaseType **btpp);
4014 +void function_swath2grid(int argc, BaseType * argv[], DDS &, BaseType **btpp);
4015 +
4016 +
4017 +class SwathToGrid: public libdap::ServerFunction {
4018 +public:
4019 +    SwathToGrid()
4020 +    {
4021 +        setName("swath2grid");
4022 +        setDescriptionString("This function echos back it's arguments as DAP data.");
4023 +        setUsageString("swath2grid(dataArray, latitudeArray, longitudeArray)");
4024 +        setRole("http://services.opendap.org/dap4/server-side-function/swath2grid");
4025 +        setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
4026 +        setFunction(libdap::function_swath2grid);
4027 +        setVersion("1.0");
4028 +    }
4029 +    virtual ~SwathToGrid()
4030 +    {
4031 +    }
4032 +
4033 +};
4034 +
4035 +class SwathToArray: public libdap::ServerFunction {
4036 +public:
4037 +    SwathToArray()
4038 +    {
4039 +        setName("swath2array");
4040 +        setDescriptionString("This function echos back it's arguments as DAP data.");
4041 +        setUsageString("swath2array(dataArray, latitudeArray, longitudeArray)");
4042 +        setRole("http://services.opendap.org/dap4/server-side-function/swath2array");
4043 +        setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2array");
4044 +        setFunction(libdap::function_swath2array);
4045 +        setVersion("1.0");
4046 +    }
4047 +    virtual ~SwathToArray()
4048 +    {
4049 +    }
4050 +
4051 +};
4052 +
4053 +
4054 +class ReProjectionFunctions: public BESAbstractModule {
4055 +public:
4056 +    ReProjectionFunctions()
4057 +    {
4058 +        libdap::ServerFunctionsList::TheList()->add_function(new libdap::SwathToGrid());
4059 +
4060 +        libdap::ServerFunctionsList::TheList()->add_function(new libdap::SwathToArray());
4061 +
4062 +    }
4063 +    virtual ~ReProjectionFunctions()
4064 +    {
4065 +    }
4066 +    virtual void initialize(const string &modname);
4067 +    virtual void terminate(const string &modname);
4068 +
4069 +    virtual void dump(ostream &strm) const;
4070 +};
4071 +
4072 +
4073 +
4074 +
4075 +} // namespace libdap
4076 +
4077 +#endif // _reproj_functions_h
4078 diff -Nur bes-3.12.0/functions.orig/swath2grid/s2gTest.cc bes-3.12.0/functions/swath2grid/s2gTest.cc
4079 --- bes-3.12.0/functions.orig/swath2grid/s2gTest.cc     1970-01-01 01:00:00.000000000 +0100
4080 +++ bes-3.12.0/functions/swath2grid/s2gTest.cc  2014-03-03 15:47:38.043566262 +0100
4081 @@ -0,0 +1,668 @@
4082 +
4083 +// -*- mode: c++; c-basic-offset:4 -*-
4084 +
4085 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4086 +// Access Protocol.
4087 +
4088 +// Copyright (c) 2012 OPeNDAP, Inc.
4089 +// Author: James Gallagher <jgallagher@opendap.org>
4090 +//
4091 +// This library is free software; you can redistribute it and/or
4092 +// modify it under the terms of the GNU Lesser General Public
4093 +// License as published by the Free Software Foundation; either
4094 +// version 2.1 of the License, or (at your option) any later version.
4095 +//
4096 +// This library is distributed in the hope that it will be useful,
4097 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
4098 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
4099 +// Lesser General Public License for more details.
4100 +//
4101 +// You should have received a copy of the GNU Lesser General Public
4102 +// License along with this library; if not, write to the Free Software
4103 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
4104 +//
4105 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
4106 +
4107 +// Tests for the AISResources class.
4108 +
4109 +#include <cppunit/TextTestRunner.h>
4110 +#include <cppunit/extensions/TestFactoryRegistry.h>
4111 +#include <cppunit/extensions/HelperMacros.h>
4112 +
4113 +#define DODS_DEBUG
4114 +//#define DODS_DEBUG2
4115 +
4116 +#include "BaseType.h"
4117 +#include "Array.h"
4118 +#include "Grid.h"
4119 +
4120 +#include "reproj_functions.h"
4121 +
4122 +#include "test/TestTypeFactory.h"
4123 +
4124 +#include "util.h"
4125 +#include "debug.h"
4126 +
4127 +#define THREE_ARRAY_1_DDS "three_array_1.dds"
4128 +#define THREE_ARRAY_1_DAS "three_array_1.das"
4129 +
4130 +using namespace CppUnit;
4131 +using namespace libdap;
4132 +using namespace std;
4133 +
4134 +int test_variable_sleep_interval = 0;
4135 +
4136 +/**
4137 + * Splits the string on the passed char. Returns vector of substrings.
4138 + * TODO make this work on situations where multiple spaces doesn't hose the split()
4139 + */
4140 +static vector<string> &split(const string &s, char delim, vector<string> &elems) {
4141 +    stringstream ss(s);
4142 +    string item;
4143 +    while (getline(ss, item, delim)) {
4144 +        elems.push_back(item);
4145 +    }
4146 +    return elems;
4147 +}
4148 +
4149 +/**
4150 + * Splits the string on the passed char. Returns vector of substrings.
4151 + */
4152 +static vector<string> split(const string &s, char delim = ' ') {
4153 +    vector<string> elems;
4154 +    return split(s, delim, elems);
4155 +}
4156 +
4157 +class s2gTest:public TestFixture
4158 +{
4159 +private:
4160 +    DDS * dds;
4161 +    TestTypeFactory btf;
4162 +    ConstraintEvaluator ce;
4163 +public:
4164 +    s2gTest():dds(0)
4165 +    {}
4166 +    ~s2gTest()
4167 +    {}
4168 +
4169 +    void setUp()
4170 +    {
4171 +        try {
4172 +            dds = new DDS(&btf);
4173 +            string dds_file = /*(string)TEST_SRC_DIR + "/" +*/ THREE_ARRAY_1_DDS ;
4174 +            dds->parse(dds_file);
4175 +            DAS das;
4176 +            string das_file = /*(string)TEST_SRC_DIR + "/" +*/ THREE_ARRAY_1_DAS ;
4177 +            das.parse(das_file);
4178 +            dds->transfer_attributes(&das);
4179 +
4180 +            DBG(dds->print_xml(stderr, false, "noBlob"));
4181 +
4182 +            // Load values into the array variables
4183 +            Array & t = dynamic_cast < Array & >(*dds->var("t"));
4184 +            Array & lon = dynamic_cast < Array & >(*dds->var("lon"));
4185 +            Array & lat = dynamic_cast < Array & >(*dds->var("lat"));
4186 +
4187 +            dods_float64 t_vals[10][10];
4188 +            for (int i = 0; i < 10; ++i)
4189 +                for (int j = 0; j < 10; ++j)
4190 +                    t_vals[i][j] = j + (i * 10);
4191 +            t.set_value(&t_vals[0][0], 100);
4192 +            t.set_read_p(true);
4193 +
4194 +            // Read real lat/lon values from a Level 1B file ascii dump
4195 +            fstream input("AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz.ascii.txt", fstream::in);
4196 +            if (input.eof() || input.fail())
4197 +                throw Error("Could not open lat/lon data in SetUp.");
4198 +            // Read a line of text to get to the start of the data.
4199 +            string line;
4200 +            getline(input, line);
4201 +            if (input.eof() || input.fail())
4202 +                throw Error("Could not read lat/lon data in SetUp.");
4203 +
4204 +            dods_float64 lon_vals[10][10];
4205 +            for (int i = 0; i < 10; ++i) {
4206 +                getline(input, line);
4207 +                if (input.eof() || input.fail())
4208 +                    throw Error("Could not read lon data from row " + long_to_string(i) + " in SetUp.");
4209 +                vector<string> vals = split(line, ',');
4210 +                for (unsigned int j = 1; j < vals.size(); ++j) {
4211 +                    DBG2(cerr << "loading in lon value: " << vals[j] << "' " << atof(vals[j].c_str()) << endl;)
4212 +                    lon_vals[i][j-1] = atof(vals[j].c_str());
4213 +                }
4214 +            }
4215 +            lon.set_value(&lon_vals[0][0], 100);
4216 +            lon.set_read_p(true);
4217 +
4218 +            dods_float64 lat_vals[10][10];
4219 +            for (int i = 0; i < 10; ++i) {
4220 +                getline(input, line);
4221 +                if (input.eof() || input.fail())
4222 +                    throw Error("Could not read lat data from row " + long_to_string(i) + " in SetUp.");
4223 +                vector<string> vals = split(line, ',');
4224 +                for (unsigned int j = 1; j < vals.size(); ++j) {
4225 +                    DBG2(cerr << "loading in lat value: " << vals[j] << "' " << atof(vals[j].c_str()) << endl;)
4226 +                    lat_vals[i][j-1] = atof(vals[j].c_str());
4227 +                }
4228 +            }
4229 +            lat.set_value(&lat_vals[0][0], 100);
4230 +            lat.set_read_p(true);
4231 +        }
4232 +
4233 +        catch (Error & e) {
4234 +            cerr << "SetUp (Error): " << e.get_error_message() << endl;
4235 +            throw;
4236 +        }
4237 +        catch(std::exception &e) {
4238 +            cerr << "SetUp (std::exception): " << e.what() << endl;
4239 +            throw;
4240 +        }
4241 +    }
4242 +
4243 +    void tearDown()
4244 +    {
4245 +        delete dds; dds = 0;
4246 +    }
4247 +
4248 +    CPPUNIT_TEST_SUITE( s2gTest );
4249 +
4250 +    CPPUNIT_TEST(no_arguments_test);
4251 +    CPPUNIT_TEST(array_return_test);
4252 +    CPPUNIT_TEST(grid_return_test);
4253 +
4254 +    CPPUNIT_TEST_SUITE_END();
4255 +
4256 +    void no_arguments_test()
4257 +    {
4258 +        try {
4259 +            BaseType *btp = 0;
4260 +            function_swath2array(0, 0, *dds, &btp);
4261 +            CPPUNIT_ASSERT(true);
4262 +        }
4263 +        catch (Error &e) {
4264 +            DBG(cerr << e.get_error_message() << endl);
4265 +            CPPUNIT_ASSERT(!"no_arguments_test() should not have failed");
4266 +        }
4267 +    }
4268 +
4269 +    void array_return_test()
4270 +    {
4271 +        try {
4272 +            BaseType *argv[3];
4273 +            argv[0] = dds->var("t");
4274 +            argv[1] = dds->var("lon");
4275 +            argv[2] = dds->var("lat");
4276 +
4277 +            BaseType *btp = 0;
4278 +            function_swath2array(3, argv, *dds, &btp);
4279 +
4280 +            DBG(cerr << "btp->name(): " << btp->name() << endl);
4281 +            CPPUNIT_ASSERT(btp->name() == "t");
4282 +            CPPUNIT_ASSERT(btp->type() == dods_array_c);
4283 +
4284 +            // Extract data; I know it's 10x16 from debugging output
4285 +            dods_float64 values[10][16];
4286 +            Array *a = static_cast<Array*>(btp);
4287 +            a->value(&values[0][0]);
4288 +        }
4289 +        catch (Error &e) {
4290 +            DBG(cerr << e.get_error_message() << endl);
4291 +            CPPUNIT_FAIL("array_return_test");
4292 +        }
4293 +    }
4294 +
4295 +#if 0
4296 +    void one_argument_not_a_grid_test()
4297 +    {
4298 +        try {
4299 +            BaseType *argv[1];
4300 +            argv[0] = dds->var("lat");
4301 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this, although it is not a grid");
4302 +            BaseType *btp = 0;
4303 +            function_grid(1, argv, *dds, &btp);
4304 +            CPPUNIT_ASSERT(!"one_argument_not_a_grid_test() should have failed");
4305 +        }
4306 +        catch (Error &e) {
4307 +            DBG(cerr << e.get_error_message() << endl);
4308 +            CPPUNIT_ASSERT(true);
4309 +        }
4310 +    }
4311 +
4312 +    void map_not_in_grid_test()
4313 +    {
4314 +        try {
4315 +            BaseType *argv[2];
4316 +            argv[0] = dds->var("a");
4317 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4318 +            argv[1] = new Str("");
4319 +            string expression = "3<second<=7";
4320 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4321 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4322 +            BaseType *btp = 0;
4323 +            function_grid(2, argv, *dds, &btp);
4324 +            CPPUNIT_ASSERT(!"map_not_in_grid_test() should have failed");
4325 +        }
4326 +        catch (Error &e) {
4327 +            DBG(cerr << e.get_error_message() << endl);
4328 +            CPPUNIT_ASSERT(true);
4329 +        }
4330 +    }
4331 +
4332 +    void one_dim_grid_test()
4333 +    {
4334 +        try {
4335 +            BaseType *argv[2];
4336 +            argv[0] = dds->var("a");
4337 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4338 +            argv[1] = new Str("");
4339 +            string expression = "3<first<=7";
4340 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4341 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4342 +
4343 +            BaseType *btp = 0;
4344 +            function_grid(2, argv, *dds, &btp);
4345 +            Grid &g = dynamic_cast<Grid&>(*btp);
4346 +
4347 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
4348 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
4349 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 4);
4350 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 7);
4351 +        }
4352 +        catch (Error &e) {
4353 +            DBG(cerr << e.get_error_message() << endl);
4354 +            CPPUNIT_ASSERT(!"one_dim_grid_test() should have worked");
4355 +        }
4356 +    }
4357 +
4358 +    void one_dim_grid_two_expressions_test()
4359 +    {
4360 +        try {
4361 +            BaseType *argv[3];
4362 +            argv[0] = dds->var("a");
4363 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4364 +
4365 +            argv[1] = new Str("");
4366 +            string expression = "first>3";
4367 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4368 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4369 +
4370 +            argv[2] = new Str("");
4371 +            expression = "first<=7";
4372 +            dynamic_cast<Str*>(argv[2])->val2buf(&expression);
4373 +            dynamic_cast<Str*>(argv[2])->set_read_p(true);
4374 +
4375 +            //function_grid(3, argv, *dds);
4376 +            BaseType *btp = 0;
4377 +            function_grid(3, argv, *dds, &btp);
4378 +            Grid &g = dynamic_cast<Grid&>(*btp);
4379 +
4380 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(3, argv, *dds));
4381 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
4382 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
4383 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 4);
4384 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 7);
4385 +        }
4386 +        catch (Error &e) {
4387 +            DBG(cerr << e.get_error_message() << endl);
4388 +            CPPUNIT_ASSERT(!"one_dim_grid_two_expressions_test() should have worked");
4389 +        }
4390 +    }
4391 +
4392 +    void one_dim_grid_descending_test()
4393 +    {
4394 +        try {
4395 +            BaseType *argv[2];
4396 +            argv[0] = dds->var("b");
4397 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4398 +            argv[1] = new Str("");
4399 +            string expression = "3<first<=7";
4400 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4401 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4402 +
4403 +            BaseType *btp = 0;
4404 +            function_grid(2, argv, *dds, &btp);
4405 +            Grid &g = dynamic_cast<Grid&>(*btp);
4406 +
4407 +            //function_grid(2, argv, *dds);
4408 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(2, argv, *dds));
4409 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
4410 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
4411 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 2);
4412 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 5);
4413 +        }
4414 +        catch (Error &e) {
4415 +            DBG(cerr << e.get_error_message() << endl);
4416 +            CPPUNIT_ASSERT(!"one_dim_grid_test() should have worked");
4417 +        }
4418 +    }
4419 +
4420 +    void one_dim_grid_two_expressions_descending_test()
4421 +    {
4422 +        try {
4423 +            BaseType *argv[3];
4424 +            argv[0] = dds->var("b");
4425 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4426 +
4427 +            argv[1] = new Str("");
4428 +            string expression = "first>3";
4429 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4430 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4431 +
4432 +            argv[2] = new Str("");
4433 +            expression = "first<=7";
4434 +            dynamic_cast<Str*>(argv[2])->val2buf(&expression);
4435 +            dynamic_cast<Str*>(argv[2])->set_read_p(true);
4436 +
4437 +            BaseType *btp = 0;
4438 +            function_grid(3, argv, *dds, &btp);
4439 +            Grid &g = dynamic_cast<Grid&>(*btp);
4440 +
4441 +            //function_grid(3, argv, *dds);
4442 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(3, argv, *dds));
4443 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
4444 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
4445 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 2);
4446 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 5);
4447 +        }
4448 +        catch (Error &e) {
4449 +            DBG(cerr << e.get_error_message() << endl);
4450 +            CPPUNIT_ASSERT(!"one_dim_grid_two_expressions_test() should have worked");
4451 +        }
4452 +    }
4453 +
4454 +    void one_dim_grid_noninclusive_values_test()
4455 +    {
4456 +        try {
4457 +            BaseType *argv[2];
4458 +            argv[0] = dds->var("a");
4459 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4460 +            argv[1] = new Str("");
4461 +            string expression = "7<first<=3";
4462 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4463 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4464 +
4465 +            BaseType *btp = 0;
4466 +            function_grid(2, argv, *dds, &btp);
4467 +            //Grid &g = dynamic_cast<Grid&>(*btp);
4468 +
4469 +            // function_grid(2, argv, *dds);
4470 +
4471 +            CPPUNIT_ASSERT(!"one_dim_grid_noninclusive_values_test() should not have worked");
4472 +        }
4473 +        catch (Error &e) {
4474 +            DBG(cerr << e.get_error_message() << endl);
4475 +            CPPUNIT_ASSERT(true);
4476 +        }
4477 +    }
4478 +
4479 +    // grid() is not required to handle this case. This test is not used.
4480 +    void values_outside_map_range_test()
4481 +    {
4482 +        try {
4483 +            BaseType *argv[2];
4484 +            argv[0] = dds->var("a");
4485 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
4486 +            argv[1] = new Str("");
4487 +            string expression = "3<=first<20";
4488 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
4489 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
4490 +
4491 +            BaseType *btp = 0;
4492 +            function_grid(2, argv, *dds, &btp);
4493 +            //Grid &g = dynamic_cast<Grid&>(*btp);
4494 +
4495 +            // function_grid(2, argv, *dds);
4496 +
4497 +            CPPUNIT_ASSERT(!"values_outside_map_range_test() should not have worked");
4498 +        }
4499 +        catch (Error &e) {
4500 +            DBG(cerr << e.get_error_message() << endl);
4501 +            CPPUNIT_ASSERT(true);
4502 +        }
4503 +    }
4504 +
4505 +    // linear_scale tests
4506 +    void linear_scale_args_test() {
4507 +        try {
4508 +            BaseType *btp = 0;
4509 +            function_linear_scale(0, 0, *dds, &btp);
4510 +            CPPUNIT_ASSERT(true);
4511 +        }
4512 +        catch (Error &e) {
4513 +            DBG(cerr << e.get_error_message() << endl);
4514 +            CPPUNIT_ASSERT(!"linear_scale_args_test: should not throw Error");
4515 +        }
4516 +    }
4517 +
4518 +    void linear_scale_array_test() {
4519 +        try {
4520 +            Array *a = dynamic_cast<Grid&>(*dds->var("a")).get_array();
4521 +            CPPUNIT_ASSERT(a);
4522 +            BaseType *argv[3];
4523 +            argv[0] = a;
4524 +            argv[1] = new Float64("");
4525 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);//m
4526 +            argv[2] = new Float64("");
4527 +            dynamic_cast<Float64*>(argv[2])->set_value(10);//b
4528 +            BaseType *scaled = 0;
4529 +            function_linear_scale(3, argv, *dds, &scaled);
4530 +            CPPUNIT_ASSERT(scaled->type() == dods_array_c
4531 +                           && scaled->var()->type() == dods_float64_c);
4532 +            double *values = extract_double_array(dynamic_cast<Array*>(scaled));
4533 +            CPPUNIT_ASSERT(values[0] == 10);
4534 +            CPPUNIT_ASSERT(values[1] == 10.1);
4535 +            CPPUNIT_ASSERT(values[9] == 10.9);
4536 +        }
4537 +        catch (Error &e) {
4538 +            DBG(cerr << e.get_error_message() << endl);
4539 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
4540 +        }
4541 +    }
4542 +
4543 +    void linear_scale_grid_test() {
4544 +        try {
4545 +            Grid *g = dynamic_cast<Grid*>(dds->var("a"));
4546 +            CPPUNIT_ASSERT(g);
4547 +            BaseType *argv[3];
4548 +            argv[0] = g;
4549 +            argv[1] = new Float64("");
4550 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);
4551 +            argv[2] = new Float64("");
4552 +            dynamic_cast<Float64*>(argv[2])->set_value(10);
4553 +            BaseType *scaled = 0;
4554 +            function_linear_scale(3, argv, *dds, &scaled);
4555 +            CPPUNIT_ASSERT(scaled->type() == dods_grid_c);
4556 +            Grid *g_s = dynamic_cast<Grid*>(scaled);
4557 +            CPPUNIT_ASSERT(g_s->get_array()->var()->type() == dods_float64_c);
4558 +            double *values = extract_double_array(g_s->get_array());
4559 +            CPPUNIT_ASSERT(values[0] == 10);
4560 +            CPPUNIT_ASSERT(values[1] == 10.1);
4561 +            CPPUNIT_ASSERT(values[9] == 10.9);
4562 +        }
4563 +        catch (Error &e) {
4564 +            DBG(cerr << e.get_error_message() << endl);
4565 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
4566 +        }
4567 +    }
4568 +
4569 +    void linear_scale_grid_attributes_test() {
4570 +        try {
4571 +            Grid *g = dynamic_cast<Grid*>(dds->var("a"));
4572 +            CPPUNIT_ASSERT(g);
4573 +            BaseType *argv[1];
4574 +            argv[0] = g;
4575 +            BaseType *scaled = 0;
4576 +            function_linear_scale(1, argv, *dds, &scaled);
4577 +            CPPUNIT_ASSERT(scaled->type() == dods_grid_c);
4578 +            Grid *g_s = dynamic_cast<Grid*>(scaled);
4579 +            CPPUNIT_ASSERT(g_s->get_array()->var()->type() == dods_float64_c);
4580 +            double *values = extract_double_array(g_s->get_array());
4581 +            CPPUNIT_ASSERT(values[0] == 10);
4582 +            CPPUNIT_ASSERT(values[1] == 10.1);
4583 +            CPPUNIT_ASSERT(values[9] == 10.9);
4584 +        }
4585 +        catch (Error &e) {
4586 +            DBG(cerr << e.get_error_message() << endl);
4587 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
4588 +        }
4589 +    }
4590 +
4591 +    // This tests the case where attributes are not found
4592 +    void linear_scale_grid_attributes_test2() {
4593 +        try {
4594 +            Grid *g = dynamic_cast<Grid*>(dds->var("b"));
4595 +            CPPUNIT_ASSERT(g);
4596 +            BaseType *argv[1];
4597 +            argv[0] = g;
4598 +            BaseType *btp = 0;
4599 +            function_linear_scale(1, argv, *dds, &btp);
4600 +            CPPUNIT_FAIL("Should not get here; no params passed and no attributes set for grid 'b'");
4601 +        }
4602 +        catch (Error &e) {
4603 +            DBG(cerr << e.get_error_message() << endl);
4604 +            CPPUNIT_ASSERT("Caught exception");
4605 +        }
4606 +    }
4607 +
4608 +    void linear_scale_scalar_test() {
4609 +        try {
4610 +            Int32 *i = new Int32("linear_scale_test_int32");
4611 +            CPPUNIT_ASSERT(i);
4612 +            i->set_value(1);
4613 +            BaseType *argv[3];
4614 +            argv[0] = i;
4615 +            argv[1] = new Float64("");
4616 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);//m
4617 +            argv[2] = new Float64("");
4618 +            dynamic_cast<Float64*>(argv[2])->set_value(10);//b
4619 +            BaseType *scaled = 0;
4620 +            function_linear_scale(3, argv, *dds, &scaled);
4621 +            CPPUNIT_ASSERT(scaled->type() == dods_float64_c);
4622 +
4623 +            CPPUNIT_ASSERT(dynamic_cast<Float64*>(scaled)->value() == 10.1);
4624 +        }
4625 +        catch (Error &e) {
4626 +            DBG(cerr << e.get_error_message() << endl);
4627 +            CPPUNIT_ASSERT(!"Error in linear_scale_scalar_test()");
4628 +        }
4629 +    }
4630 +
4631 +
4632 +    void function_dap_1_test() {
4633 +        try {
4634 +            Int32 *i = new Int32("function_dap_1_test_int32");
4635 +            CPPUNIT_ASSERT(i);
4636 +            i->set_value(2);
4637 +            BaseType *argv[1];
4638 +            argv[0] = i;
4639 +
4640 +            ConstraintEvaluator unused;
4641 +            function_dap(1, argv, *dds, unused);
4642 +
4643 +            CPPUNIT_ASSERT(dds->get_dap_major() == 2);
4644 +            CPPUNIT_ASSERT(dds->get_dap_minor() == 0);
4645 +        }
4646 +        catch (Error &e) {
4647 +            DBG(cerr << e.get_error_message() << endl);
4648 +            CPPUNIT_FAIL("Error in function_dap_1_test(): " + e.get_error_message());
4649 +        }
4650 +    }
4651 +
4652 +    void function_dap_2_test() {
4653 +        try {
4654 +            Float64 *d = new Float64("function_dap_1_test_float64");
4655 +            CPPUNIT_ASSERT(d);
4656 +            d->set_value(3.2);
4657 +            BaseType *argv[1];
4658 +            argv[0] = d;
4659 +
4660 +            ConstraintEvaluator unused;
4661 +            function_dap(1, argv, *dds, unused);
4662 +
4663 +            CPPUNIT_ASSERT(dds->get_dap_major() == 3);
4664 +            CPPUNIT_ASSERT(dds->get_dap_minor() == 2);
4665 +        }
4666 +        catch (Error &e) {
4667 +            DBG(cerr << e.get_error_message() << endl);
4668 +            CPPUNIT_FAIL("Error in function_dap_2_test(): " + e.get_error_message());
4669 +        }
4670 +    }
4671 +
4672 +    void function_dap_3_test() {
4673 +        try {
4674 +            cerr <<"In function_dap_3_test" << endl;
4675 +            ConstraintEvaluator unused;
4676 +            function_dap(0, 0, *dds, unused);
4677 +
4678 +            CPPUNIT_FAIL("Should have thrown an exception on no args");
4679 +                    }
4680 +        catch (Error &e) {
4681 +            DBG(cerr << e.get_error_message() << endl);
4682 +            CPPUNIT_ASSERT("Pass: Caught exception");
4683 +        }
4684 +    }
4685 +#endif
4686 +    void grid_return_test()
4687 +    {
4688 +        try {
4689 +            BaseType *argv[3];
4690 +            argv[0] = dds->var("t");
4691 +            argv[1] = dds->var("lon");
4692 +            argv[2] = dds->var("lat");
4693 +
4694 +            cerr << "Input values:" << endl;
4695 +            dods_float64 t_vals[10][10];
4696 +            Array *a = static_cast<Array*>(argv[0]);
4697 +            a->value(&t_vals[0][0]);
4698 +            for (int i = 0; i < 10; ++i) {
4699 +                for (int j = 0; j < 10; ++j) {
4700 +                    cerr << "t[" << i << "][" << j << "]: " <<  t_vals[i][j] << endl;
4701 +                }
4702 +            }
4703 +
4704 +            BaseType *btp = 0;
4705 +            function_swath2grid(3, argv, *dds, &btp);
4706 +
4707 +            DBG(cerr << "btp->name(): " << btp->name() << endl);
4708 +            CPPUNIT_ASSERT(btp->name() == "t");
4709 +            CPPUNIT_ASSERT(btp->type() == dods_grid_c);
4710 +
4711 +            // Extract data; I know it's 10x16 from debugging output
4712 +            dods_float64 values[10][16];
4713 +            Grid *g = static_cast<Grid*>(btp);
4714 +            g->get_array()->value(&values[0][0]);
4715 +
4716 +            Grid::Map_iter m = g->map_begin();
4717 +            dods_float64 lat[10];
4718 +            static_cast<Array*>(*m)->value(&lat[0]);
4719 +
4720 +            ++m;
4721 +            dods_float64 lon[16];
4722 +            static_cast<Array*>(*m)->value(&lon[0]);
4723 +
4724 +            cerr << "Output values:" << endl;
4725 +            for (int i = 0; i < 10; ++i) {
4726 +                for (int j = 0; j < 16; ++j) {
4727 +                    cerr << "t[" << i << "][" << j << "] == lon: " << lon[j] << ", lat: " << lat[i] << " val: " << values[i][j] << endl;
4728 +                }
4729 +            }
4730 +        }
4731 +        catch (Error &e) {
4732 +            DBG(cerr << e.get_error_message() << endl);
4733 +            CPPUNIT_FAIL("array_return_test");
4734 +        }
4735 +    }
4736 +};
4737 +
4738 +CPPUNIT_TEST_SUITE_REGISTRATION(s2gTest);
4739 +
4740 +int
4741 +main( int, char** )
4742 +{
4743 +    CppUnit::TextTestRunner runner;
4744 +    runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );
4745 +
4746 +    bool wasSuccessful = runner.run( "", false ) ;
4747 +
4748 +    return wasSuccessful ? 0 : 1;
4749 +}
4750 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/entries bes-3.12.0/functions/swath2grid/.svn/entries
4751 --- bes-3.12.0/functions.orig/swath2grid/.svn/entries   1970-01-01 01:00:00.000000000 +0100
4752 +++ bes-3.12.0/functions/swath2grid/.svn/entries        2014-03-03 15:47:34.366899750 +0100
4753 @@ -0,0 +1 @@
4754 +12
4755 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/format bes-3.12.0/functions/swath2grid/.svn/format
4756 --- bes-3.12.0/functions.orig/swath2grid/.svn/format    1970-01-01 01:00:00.000000000 +0100
4757 +++ bes-3.12.0/functions/swath2grid/.svn/format 2014-03-03 15:47:34.366899750 +0100
4758 @@ -0,0 +1 @@
4759 +12
4760 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/2c/2c1fb68452ecaa4ec099ab4ec2c2a3a62c6aa0d9.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/2c/2c1fb68452ecaa4ec099ab4ec2c2a3a62c6aa0d9.svn-base
4761 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/2c/2c1fb68452ecaa4ec099ab4ec2c2a3a62c6aa0d9.svn-base     1970-01-01 01:00:00.000000000 +0100
4762 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/2c/2c1fb68452ecaa4ec099ab4ec2c2a3a62c6aa0d9.svn-base  2014-03-03 15:47:37.593566281 +0100
4763 @@ -0,0 +1,116 @@
4764 +/******************************************************************************
4765 + * $Id: wcs_error.cpp 2011-07-19 16:24:00Z $
4766 + *
4767 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
4768 + *                      for Earth Observation: Open Source Reference Implementation
4769 + * Purpose:  WCS exception and error handler implementation, used to set
4770 + *                      the exception code and locator of WCS
4771 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
4772 + *
4773 + ******************************************************************************
4774 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
4775 + *
4776 + * Permission is hereby granted, free of charge, to any person obtaining a
4777 + * copy of this software and associated documentation files (the "Software"),
4778 + * to deal in the Software without restriction, including without limitation
4779 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4780 + * and/or sell copies of the Software, and to permit persons to whom the
4781 + * Software is furnished to do so, subject to the following conditions:
4782 + *
4783 + * The above copyright notice and this permission notice shall be included
4784 + * in all copies or substantial portions of the Software.
4785 + *
4786 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4787 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4788 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
4789 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4790 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
4791 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
4792 + * DEALINGS IN THE SOFTWARE.
4793 + ****************************************************************************/
4794 +
4795 +#include "wcs_error.h"
4796 +
4797 +static string WCS_ERROR_STRING="";
4798 +static string ERROR_LOCATOR="";
4799 +static string ExcptCodeText[] =
4800 +{
4801 +       "OperationNotSupported",
4802 +       "MissingParameterValue",
4803 +       "InvalidParameterValue",
4804 +       "VersionNegotiationFailed",
4805 +       "InvalidUpdateSequence",
4806 +       "OptionNotSupported",
4807 +       "NoApplicableCode",
4808 +       "NoSuchCoverage",
4809 +       "InvalidAxisLabel",
4810 +       "InvalidSubsetting"
4811 +};
4812 +
4813 +static int WCS_IsSoapMessage_Transform = 0;
4814 +
4815 +string CPL_STDCALL GetWCS_ErrorMsg()
4816 +{
4817 +       return WCS_ERROR_STRING;
4818 +}
4819 +
4820 +void CPL_STDCALL SetWCS_ErrorLocator(const char* loc)
4821 +{
4822 +       ERROR_LOCATOR = loc;
4823 +}
4824 +
4825 +void CPL_STDCALL WCS_ErrorHandler(CPLErr eErrClass,int err_no,const char *pszErrorMsg )
4826 +{
4827 +       WCS_ERROR_STRING.clear();
4828 +       string ExcCode;
4829 +
4830 +       if(err_no >= 300 && err_no <= 309)
4831 +               ExcCode = ExcptCodeText[err_no - 300];
4832 +       else
4833 +               ExcCode = ExcptCodeText[6];
4834 +
4835 +       if(WCS_IsSoapMessage_Transform)
4836 +       {
4837 +               WCS_ERROR_STRING  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
4838 +               WCS_ERROR_STRING += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n";
4839 +               WCS_ERROR_STRING += "<soap:Body>\n";
4840 +               WCS_ERROR_STRING += "<ExceptionReport xmlns=\"http://www.opengis.net/ows\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
4841 +               WCS_ERROR_STRING += "xsi:schemaLocation=\"http://www.opengis.net/ows/owsCommon.xsd\" version=\"0.3.20\" language=\"en\">\n";
4842 +               WCS_ERROR_STRING += "   <Exception exceptionCode=\"";
4843 +               WCS_ERROR_STRING += ExcCode;
4844 +               WCS_ERROR_STRING += "\" locator=\"";
4845 +               WCS_ERROR_STRING += ERROR_LOCATOR;
4846 +               WCS_ERROR_STRING += "\">\n";
4847 +               WCS_ERROR_STRING += "           <ExceptionText>" + string(pszErrorMsg) + "</ExceptionText>\n";
4848 +               WCS_ERROR_STRING += "   </Exception>\n";
4849 +               WCS_ERROR_STRING += "</ExceptionReport>\n";
4850 +               WCS_ERROR_STRING += "/soap:Body>\n";
4851 +               WCS_ERROR_STRING += "/<soap:Envelope>\n";
4852 +       }
4853 +       else
4854 +       {
4855 +               WCS_ERROR_STRING  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
4856 +               WCS_ERROR_STRING += "<ExceptionReport xmlns=\"http://www.opengis.net/ows\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
4857 +               WCS_ERROR_STRING += "xsi:schemaLocation=\"http://www.opengis.net/ows/owsCommon.xsd\" version=\"0.3.20\" language=\"en\">\n";
4858 +               WCS_ERROR_STRING += "   <Exception exceptionCode=\"";
4859 +               WCS_ERROR_STRING += ExcCode;
4860 +               WCS_ERROR_STRING += "\" locator=\"";
4861 +               WCS_ERROR_STRING += ERROR_LOCATOR;
4862 +               WCS_ERROR_STRING += "\">\n";
4863 +               WCS_ERROR_STRING += "           <ExceptionText>" + string(pszErrorMsg) + "</ExceptionText>\n";
4864 +               WCS_ERROR_STRING += "   </Exception>\n";
4865 +               WCS_ERROR_STRING += "</ExceptionReport>\n";
4866 +       }
4867 +
4868 +       return;
4869 +}
4870 +
4871 +void WCST_SetSoapMsgTrns(int isSoap)
4872 +{
4873 +       WCS_IsSoapMessage_Transform = isSoap;
4874 +}
4875 +
4876 +int    WCST_GetSoapMsgTrns()
4877 +{
4878 +       return WCS_IsSoapMessage_Transform;
4879 +}
4880 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/37/3738e631c59c1f5cded9ac6457cfcb35d402dba7.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/37/3738e631c59c1f5cded9ac6457cfcb35d402dba7.svn-base
4881 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/37/3738e631c59c1f5cded9ac6457cfcb35d402dba7.svn-base     1970-01-01 01:00:00.000000000 +0100
4882 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/37/3738e631c59c1f5cded9ac6457cfcb35d402dba7.svn-base  2014-03-03 15:47:37.810232939 +0100
4883 @@ -0,0 +1,10 @@
4884 +# three_array_1.dds
4885 +#
4886 +# Created on: Dec 12, 2012
4887 +#     Author: jimg
4888 +
4889 +Dataset {
4890 +    Float64 t[10][10];
4891 +    Float64 lon[10][10];
4892 +    Float64 lat[10][10];
4893 +} three_array_1;
4894 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/54/5408a8ae104fd8000f1d7015e95b1848047c9f56.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/54/5408a8ae104fd8000f1d7015e95b1848047c9f56.svn-base
4895 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/54/5408a8ae104fd8000f1d7015e95b1848047c9f56.svn-base     1970-01-01 01:00:00.000000000 +0100
4896 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/54/5408a8ae104fd8000f1d7015e95b1848047c9f56.svn-base  2014-03-03 15:47:37.806899605 +0100
4897 @@ -0,0 +1,81 @@
4898 +/******************************************************************************
4899 + * $Id: wcs_error.h 2011-07-19 16:24:00Z $
4900 + *
4901 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
4902 + *                      for Earth Observation: Open Source Reference Implementation
4903 + * Purpose:  WCS exception and error handler definition
4904 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
4905 + *
4906 + ******************************************************************************
4907 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
4908 + *
4909 + * Permission is hereby granted, free of charge, to any person obtaining a
4910 + * copy of this software and associated documentation files (the "Software"),
4911 + * to deal in the Software without restriction, including without limitation
4912 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
4913 + * and/or sell copies of the Software, and to permit persons to whom the
4914 + * Software is furnished to do so, subject to the following conditions:
4915 + *
4916 + * The above copyright notice and this permission notice shall be included
4917 + * in all copies or substantial portions of the Software.
4918 + *
4919 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
4920 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4921 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
4922 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4923 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
4924 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
4925 + * DEALINGS IN THE SOFTWARE.
4926 + ****************************************************************************/
4927 +
4928 +/************************************************************************
4929 + WCS Exception Code
4930 +
4931 + See OGC Web Services Common Standard [OGC 06-121r9] for details
4932 + Table 27 â€” Standard exception codes and meanings
4933 +       OperationNotSupported
4934 +       MissingParameterValue
4935 +       InvalidParameterValue
4936 +       VersionNegotiationFailed
4937 +       InvalidUpdateSequence
4938 +       OptionNotSupported
4939 +       NoApplicableCode
4940 +
4941 + See OGC® WCS 2.0 Interface Standard - Core [09-110r3] for details
4942 + Table 18 - Exception codes for GetCoverage operation
4943 +        NoSuchCoverage
4944 +        InvalidAxisLabel
4945 +        InvalidSubsetting
4946 +
4947 +*************************************************************************/
4948 +
4949 +#ifndef WCS_ERROR_H_
4950 +#define WCS_ERROR_H_
4951 +
4952 +#include <cpl_error.h>
4953 +#include <string>
4954 +
4955 +using namespace std;
4956 +
4957 +#define OGC_WCS_OperationNotSupported                  300
4958 +#define OGC_WCS_MissingParameterValue                  301
4959 +#define OGC_WCS_InvalidParameterValue                  302
4960 +#define OGC_WCS_VersionNegotiationFailed       303
4961 +#define OGC_WCS_InvalidUpdateSequence          304
4962 +#define OGC_WCS_OptionNotSupported                     305
4963 +#define OGC_WCS_NoApplicableCode                       306
4964 +
4965 +#define OGC_WCS_NoSuchCoverage                         307
4966 +#define OGC_WCS_InvalidAxisLabel                       308
4967 +#define OGC_WCS_InvalidSubsetting                      309
4968 +
4969 +void CPL_DLL CPL_STDCALL WCS_Error(CPLErr, int, const char*, ...);
4970 +void CPL_DLL CPL_STDCALL SetWCS_ErrorLocator(const char* loc);
4971 +void CPL_DLL CPL_STDCALL WCS_ErrorHandler(CPLErr, int, const char*);
4972 +string CPL_DLL CPL_STDCALL GetWCS_ErrorMsg();
4973 +
4974 +int    WCST_GetSoapMsgTrns();
4975 +void WCST_SetSoapMsgTrns(int);
4976 +
4977 +#define WCS_Error  CPLError
4978 +#endif /* WCS_ERROR_H_ */
4979 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/55/552f5680f38631504c1a309d875c7bbbf2bc2492.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/55/552f5680f38631504c1a309d875c7bbbf2bc2492.svn-base
4980 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/55/552f5680f38631504c1a309d875c7bbbf2bc2492.svn-base     1970-01-01 01:00:00.000000000 +0100
4981 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/55/552f5680f38631504c1a309d875c7bbbf2bc2492.svn-base  2014-03-03 15:47:37.846899604 +0100
4982 @@ -0,0 +1,142 @@
4983 +
4984 +// -*- mode: c++; c-basic-offset:4 -*-
4985 +
4986 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
4987 +// Access Protocol.
4988 +
4989 +// Copyright (c) 2012 OPeNDAP, Inc.
4990 +// Author: James Gallagher <jgallagher@opendap.org>
4991 +//
4992 +// This library is free software; you can redistribute it and/or
4993 +// modify it under the terms of the GNU Lesser General Public
4994 +// License as published by the Free Software Foundation; either
4995 +// version 2.1 of the License, or (at your option) any later version.
4996 +//
4997 +// This library is distributed in the hope that it will be useful,
4998 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
4999 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5000 +// Lesser General Public License for more details.
5001 +//
5002 +// You should have received a copy of the GNU Lesser General Public
5003 +// License along with this library; if not, write to the Free Software
5004 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
5005 +//
5006 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
5007 +
5008 +#ifndef DAP_DATASET_H_
5009 +#define DAP_DATASET_H_
5010 +
5011 +#include <string>
5012 +#include "AbstractDataset.h"
5013 +#include "wcsUtil.h"
5014 +
5015 +using namespace std;
5016 +
5017 +namespace libdap {
5018 +
5019 +class Array;
5020 +class Grid;
5021 +
5022 +/************************************************************************/
5023 +/* ==================================================================== */
5024 +/*                           DAP_Dataset                            */
5025 +/* ==================================================================== */
5026 +/************************************************************************/
5027 +
5028 +//! DAP_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
5029 +/**
5030 + * \class DAP_Dataset "DAP_Dataset.h"
5031 + *
5032 + * GOES satellites provide the kind of continuous monitoring necessary for
5033 + * intensive data analysis. They circle the Earth in a geosynchronous orbit,
5034 + * which means they orbit the equatorial plane of the Earth at a speed
5035 + * matching the Earth's rotation. This allows them to hover continuously
5036 + * over one position on the surface. The geosynchronous plane is about
5037 + * 35,800 km (22,300 miles) above the Earth, high enough to allow the
5038 + * satellites a full-disc view of the Earth. Because they stay above a
5039 + * fixed spot on the surface, they provide a constant vigil for the atmospheric
5040 + * "triggers" for severe weather conditions such as tornadoes, flash floods,
5041 + * hail storms, and hurricanes. When these conditions develop the GOES
5042 + * satellites are able to monitor storm development and track their movements.
5043 + *
5044 + * GOES satellite imagery is also used to estimate rainfall during
5045 + * the thunderstorms and hurricanes for flash flood warnings, as well
5046 + * as estimates snowfall accumulations and overall extent of snow cover.
5047 + * Such data help meteorologists issue winter storm warnings and spring
5048 + * snow melt advisories. Satellite sensors also detect ice fields and map
5049 + * the movements of sea and lake ice.
5050 + *
5051 + * For more inforamtion about NOAA GOES data, please access
5052 + * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
5053 + *
5054 + * DAP_Dataset is a subclass of AbstractDataset, which is used to
5055 + * process GOES Imager and Sounder products.
5056 + */
5057 +
5058 +class DAP_Dataset : public AbstractDataset {
5059 +protected:
5060 +    string m_ncLatDataSetName;
5061 +    string m_ncLonDataSetName;
5062 +    string m_ncCoverageIDName;
5063 +
5064 +    // Instead of using names and opening files with GDAL,
5065 +    // store pointers to Arrays read by the underlying DAP
5066 +    // server constraint evaluator.
5067 +    Array *m_src;
5068 +    Array *m_lat;
5069 +    Array *m_lon;
5070 +
5071 +    int mi_RectifiedImageXSize;
5072 +    int mi_RectifiedImageYSize;
5073 +    int mi_SrcImageXSize;
5074 +    int mi_SrcImageYSize;
5075 +
5076 +    double mb_LatLonBBox[4];
5077 +    double mdSrcGeoMinX;
5078 +    double mdSrcGeoMinY;
5079 +    double mdSrcGeoMaxX;
5080 +    double mdSrcGeoMaxY;
5081 +
5082 +    // This is not set until GetDAPArray() is called.
5083 +    double m_geo_transform_coef[6];
5084 +
5085 +    vector<GDAL_GCP> m_gdalGCPs;
5086 +
5087 +public:
5088 +    CPLErr SetGCPGeoRef4VRTDataset(GDALDataset*);
5089 +    void SetGeoBBoxAndGCPs(int xSize, int ySize);
5090 +    CPLErr RectifyGOESDataSet();
5091 +    CPLErr setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue);
5092 +
5093 +    int isValidLatitude(const double &lat)
5094 +    {
5095 +        return (lat >= -90 && lat <= 90);
5096 +    }
5097 +    int isValidLongitude(const double &lon)
5098 +    {
5099 +        return (lon >= -180 && lon <= 180);
5100 +    }
5101 +
5102 +    virtual CPLErr SetGeoTransform();
5103 +#if 0
5104 +    virtual CPLErr SetMetaDataList(GDALDataset* hSrcDS); //TODO Remove
5105 +#endif
5106 +    virtual CPLErr SetNativeCRS();
5107 +    virtual CPLErr SetGDALDataset(const int isSimple = 0);
5108 +    virtual CPLErr InitialDataset(const int isSimple = 0);
5109 +    virtual CPLErr GetGeoMinMax(double geoMinMax[]);
5110 +
5111 +public:
5112 +    DAP_Dataset();
5113 +    DAP_Dataset(const string& id, vector<int> &rBandList);
5114 +
5115 +    // Added jhrg 11/23/12
5116 +    DAP_Dataset(Array *src, Array *lat, Array *lon);
5117 +    Array *GetDAPArray();
5118 +    Grid *GetDAPGrid();
5119 +
5120 +    virtual ~DAP_Dataset();
5121 +};
5122 +
5123 +} // namespace libdap
5124 +#endif /* DAP_DATASET_H_ */
5125 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/5c/5c131461ae16583ef4babcd3a87404f41769d430.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/5c/5c131461ae16583ef4babcd3a87404f41769d430.svn-base
5126 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/5c/5c131461ae16583ef4babcd3a87404f41769d430.svn-base     1970-01-01 01:00:00.000000000 +0100
5127 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/5c/5c131461ae16583ef4babcd3a87404f41769d430.svn-base  2014-03-03 15:47:37.633566281 +0100
5128 @@ -0,0 +1,1238 @@
5129 +/******************************************************************************
5130 + * $Id: AbstractDataset.cpp 2011-07-19 16:24:00Z $
5131 + *
5132 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
5133 + *                      for Earth Observation: Open Source Reference Implementation
5134 + * Purpose:  AbstractDataset implementation for providing an abstract data
5135 + *                      model for multiple data source.
5136 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
5137 + *
5138 + ******************************************************************************
5139 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
5140 + *
5141 + * Permission is hereby granted, free of charge, to any person obtaining a
5142 + * copy of this software and associated documentation files (the "Software"),
5143 + * to deal in the Software without restriction, including without limitation
5144 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
5145 + * and/or sell copies of the Software, and to permit persons to whom the
5146 + * Software is furnished to do so, subject to the following conditions:
5147 + *
5148 + * The above copyright notice and this permission notice shall be included
5149 + * in all copies or substantial portions of the Software.
5150 + *
5151 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
5152 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5153 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
5154 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5155 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
5156 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
5157 + * DEALINGS IN THE SOFTWARE.
5158 + ****************************************************************************/
5159 +
5160 +#include "AbstractDataset.h"
5161 +
5162 +/************************************************************************/
5163 +/* ==================================================================== */
5164 +/*                           AbstractDataset                            */
5165 +/* ==================================================================== */
5166 +/************************************************************************/
5167 +
5168 +/**
5169 + * \class AbstractDataset "AbstractDataset.h"
5170 + *
5171 + * An abstract dataset encapsulating one or more raster bands, which is
5172 + * based on GDALDataset, and add the support to metadata model: ISO 19115
5173 + * and 1SO 19115 (2). A series of Fetch functions are provided for the
5174 + * implementation of Web Coverage Service.
5175 + *
5176 + * Use WCSTCreateDataset() to create a AbstractDataset for a named coverage
5177 + * identifier and band list.
5178 + */
5179 +
5180 +/************************************************************************/
5181 +/*                            AbstractDataset()                         */
5182 +/************************************************************************/
5183 +AbstractDataset::AbstractDataset()
5184 +{
5185 +}
5186 +
5187 +/************************************************************************/
5188 +/*                            AbstractDataset()                         */
5189 +/************************************************************************/
5190 +
5191 +/**
5192 + * \brief Constructor of an AbstractDataset.
5193 + *
5194 + * This is the accepted method of opening an abstract dataset and allocating
5195 + * all resources associated with it.
5196 + */
5197 +
5198 +AbstractDataset::AbstractDataset(const string& id, vector<int> &rBandList) :
5199 +       ms_CoverageID(id), mv_BandList(rBandList)
5200 +{
5201 +}
5202 +
5203 +/************************************************************************/
5204 +/*                            ~AbstractDataset()                        */
5205 +/************************************************************************/
5206 +
5207 +/**
5208 + * \brief Destroy an open AbstractDataset object.
5209 + *
5210 + * This is the accepted method of closing a AbstractDataset dataset and
5211 + * deallocating all resources associated with it.
5212 + */
5213 +
5214 +AbstractDataset::~AbstractDataset()
5215 +{
5216 +       if (maptr_DS.get())
5217 +               GDALClose(maptr_DS.release());
5218 +}
5219 +
5220 +/************************************************************************/
5221 +/*                            InitialDataset()                          */
5222 +/************************************************************************/
5223 +
5224 +/**
5225 + * \brief Initialize the data set.
5226 + *
5227 + * This is the virtual function for initializing abstract dataste. The
5228 + * subclasses of AbstarctDataset will call SetNativeCRS(), SetGeoTransform()
5229 + * and SetGDALDataset() to initialize an abstarct dataset.
5230 + *
5231 + * @param isSimple The WCS request type.  When user executing a DescribeCoverage
5232 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
5233 + *
5234 + * @return CE_None on success or CE_Failure on failure.
5235 + */
5236 +
5237 +CPLErr AbstractDataset::InitialDataset(const int isSimple)
5238 +{
5239 +       return CE_Failure;
5240 +}
5241 +
5242 +/************************************************************************/
5243 +/*                            GetGDALDataset()                          */
5244 +/************************************************************************/
5245 +
5246 +/**
5247 + * \brief Get the GDALDataset object from AbstarctDataset.
5248 + *
5249 + * An AbstarctDataset encapsulating one GDALDataset. GetGDALDataset()
5250 + * returns a GDALDatset object, which is used to fetch its information
5251 + * through GDAL APIs.
5252 + *
5253 + * @return GDALDatset object.
5254 + */
5255 +
5256 +GDALDataset* AbstractDataset::GetGDALDataset()
5257 +{
5258 +       return maptr_DS.get();
5259 +}
5260 +
5261 +/************************************************************************/
5262 +/*                            SetGDALDataset()                          */
5263 +/************************************************************************/
5264 +
5265 +/**
5266 + * \brief Set the GDALDataset object to AbstarctDataset.
5267 + *
5268 + * This is the virtual function for setting the abstract dataset by
5269 + * calling GDAL functions.
5270 + *
5271 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
5272 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
5273 + *
5274 + * @return CE_None on success or CE_Failure on failure.
5275 + */
5276 +
5277 +CPLErr AbstractDataset::SetGDALDataset(const int isSimple)
5278 +{
5279 +       return CE_Failure;
5280 +}
5281 +
5282 +/************************************************************************/
5283 +/*                            GetNativeCRS()                            */
5284 +/************************************************************************/
5285 +
5286 +/**
5287 + * \brief Get the Native CRS of an AbstarctDataset.
5288 + *
5289 + * The method will return the CRS obejct, which is an OGRSpatialReference
5290 + * object.
5291 + *
5292 + * @return an OGRSpatialReference object corresponding the native CRS of
5293 + * coverage.
5294 + */
5295 +
5296 +const OGRSpatialReference& AbstractDataset::GetNativeCRS()
5297 +{
5298 +       return mo_NativeCRS;
5299 +}
5300 +
5301 +/************************************************************************/
5302 +/*                            SetNativeCRS()                            */
5303 +/************************************************************************/
5304 +
5305 +/**
5306 + * \brief Set the Native CRS for an AbstarctDataset.
5307 + *
5308 + * The method will set the CRS for an AbstractDataset as an native CRS. For
5309 + * some served coverage, GDAL could not tell its native CRS, this method
5310 + * should be called to set its native CRS.
5311 + *
5312 + * @return CE_None on success or CE_Failure on failure.
5313 + */
5314 +
5315 +CPLErr AbstractDataset::SetNativeCRS()
5316 +{
5317 +       char* wktStr = (char*) maptr_DS->GetProjectionRef();
5318 +
5319 +       if (wktStr && OGRERR_NONE == mo_NativeCRS.importFromWkt(&wktStr))
5320 +               return CE_None;
5321 +
5322 +       return CE_Failure;
5323 +}
5324 +
5325 +/************************************************************************/
5326 +/*                            SetGeoTransform()                         */
5327 +/************************************************************************/
5328 +
5329 +/**
5330 + * \brief Set the affine GeoTransform matrix for a coverage.
5331 + *
5332 + * The method will set a GeoTransform matrix for a coverage. The method
5333 + * GetGeoTransform of GDAL library will be called to get the matrix.
5334 + *
5335 + * @return CE_None on success or CE_Failure on failure.
5336 + */
5337 +
5338 +CPLErr AbstractDataset::SetGeoTransform()
5339 +{
5340 +       if (CE_None != maptr_DS->GetGeoTransform(md_Geotransform))
5341 +               return CE_Failure;
5342 +
5343 +       //Is the returned matrix correct? check the resolution values;
5344 +       if(md_Geotransform[2] == 0 && md_Geotransform[5] == 0)
5345 +               return CE_Failure;
5346 +
5347 +       mb_GeoTransformSet = TRUE;
5348 +
5349 +       return CE_None;
5350 +}
5351 +
5352 +/************************************************************************/
5353 +/*                            GetGeoTransform()                         */
5354 +/************************************************************************/
5355 +
5356 +/**
5357 + * \brief Fetch the affine transformation coefficients.
5358 + *
5359 + * Fetches the coefficients for transforming between pixel/line (P,L) raster
5360 + * space, and projection coordinates (Xp,Yp) space.
5361 + *
5362 + * \code
5363 + *   Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
5364 + *   Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
5365 + * \endcode
5366 + *
5367 + * In a north up image, padfTransform[1] is the pixel width, and
5368 + * padfTransform[5] is the pixel height.  The upper left corner of the
5369 + * upper left pixel is at position (padfTransform[0],padfTransform[3]).
5370 + *
5371 + * The default transform is (0,1,0,0,0,1) and should be returned even when
5372 + * a CE_Failure error is returned, such as for formats that don't support
5373 + * transformation to projection coordinates.
5374 + *
5375 + * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
5376 + * OGC Grid Coverages pixel/line to projection transformation schemes.
5377 + * Eventually this method will be depreciated in favour of a more general
5378 + * scheme.
5379 + *
5380 + * @param geoTrans an existing six double buffer into which the
5381 + * transformation will be placed.
5382 + *
5383 + * @return TRUE on success or FALSE on failure.
5384 + */
5385 +
5386 +int AbstractDataset::GetGeoTransform(double geoTrans[])
5387 +{
5388 +       if (!mb_GeoTransformSet)//Geo-Transform not setup in each data driver, then set default.
5389 +       {
5390 +               geoTrans[0]=0.0;
5391 +               geoTrans[0]=1.0;
5392 +               geoTrans[0]=0.0;
5393 +               geoTrans[0]=0.0;
5394 +               geoTrans[0]=0.0;
5395 +               geoTrans[0]=1.0;
5396 +               return FALSE;
5397 +       }
5398 +
5399 +       memcpy(geoTrans, md_Geotransform, sizeof(double) * 6);
5400 +
5401 +       return TRUE;
5402 +}
5403 +
5404 +/************************************************************************/
5405 +/*                            GetCoverageID()                           */
5406 +/************************************************************************/
5407 +
5408 +/**
5409 + * \brief Fetch the identifier of a coverage.
5410 + *
5411 + * The method will return the coverage identifier related to the abstarct
5412 + * dataset. As to TRMM data, the coverage identifier likes:
5413 + * TRMM:/Volumes/RAIDL1/GeoData/TRMM/TRMM_3B42_daily.2000.hdf:Daily
5414 + *
5415 + * As to MODIS data, the coverage identifier likes:
5416 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MOD15A2/2007/MYD15A2.A2007241.h12v09.005.2007256053902.hdf":MOD_Grid_MOD15A2:Lai_1km
5417 + *
5418 + * @return the string of coverage identifier.
5419 + */
5420 +
5421 +string AbstractDataset::GetCoverageID()
5422 +{
5423 +       return ms_CoverageID;
5424 +}
5425 +
5426 +/************************************************************************/
5427 +/*                            GetResourceFileName()                     */
5428 +/************************************************************************/
5429 +
5430 +/**
5431 + * \brief Fetch the resource file name of a coverage.
5432 + *
5433 + * The method will return the full path corresponding the file contained
5434 + * coverage.
5435 + *
5436 + * @return the string of resource file path.
5437 + */
5438 +
5439 +string AbstractDataset::GetResourceFileName()
5440 +{
5441 +       return ms_SrcFilename;
5442 +}
5443 +
5444 +/************************************************************************/
5445 +/*                            GetDatasetName()                          */
5446 +/************************************************************************/
5447 +
5448 +/**
5449 + * \brief Fetch the dataset name of a coverage.
5450 + *
5451 + * The method will return the data set name corresponding the file contained
5452 + * coverage. For example, MOD09GQ data has the coverage identifier as following;
5453 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
5454 + *
5455 + * sur_refl_b01_1 is seemed as the dataset name.
5456 + *
5457 + * @return the string of dataset name.
5458 + */
5459 +
5460 +string AbstractDataset::GetDatasetName()
5461 +{
5462 +       return ms_DatasetName;
5463 +}
5464 +
5465 +/************************************************************************/
5466 +/*                            GetDataTypeName()                         */
5467 +/************************************************************************/
5468 +
5469 +/**
5470 + * \brief Fetch the dataset type name of a coverage.
5471 + *
5472 + * The method will return the data set name corresponding the file contained
5473 + * coverage. For example, MOD09GQ data has the coverage identifier as following;
5474 + * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
5475 + *
5476 + * MODIS_Grid_2D is seemed as the dataset type name.
5477 + *
5478 + * @return the string of dataset type name.
5479 + */
5480 +
5481 +string AbstractDataset::GetDataTypeName()
5482 +{
5483 +       return ms_DataTypeName;
5484 +}
5485 +
5486 +/************************************************************************/
5487 +/*                            GetDataTypeName()                         */
5488 +/************************************************************************/
5489 +
5490 +/**
5491 + * \brief Fetch the dataset description of a coverage.
5492 + *
5493 + * The method will build a description for the coverage. The coverage
5494 + * extent, dataset name, dataset type name will be contained in the
5495 + * description,
5496 + *
5497 + * @return the string of dataset description.
5498 + */
5499 +
5500 +string AbstractDataset::GetDatasetDescription()
5501 +{
5502 +       //[15x2030x1354] Band JPEG2000 (16-bit unsigned integer)
5503 +       string rtnBuf;
5504 +       int aiDimSizes[3];
5505 +       int nBandCount = maptr_DS->GetRasterCount();
5506 +       string pszString;
5507 +       if (nBandCount > 1)
5508 +       {
5509 +               aiDimSizes[0] = nBandCount;
5510 +               aiDimSizes[1] = GetImageYSize();
5511 +               aiDimSizes[2] = GetImageXSize();
5512 +               pszString = SPrintArray(GDT_UInt32, aiDimSizes, 3, "x");
5513 +       }
5514 +       else
5515 +       {
5516 +               aiDimSizes[0] = GetImageYSize();
5517 +               aiDimSizes[1] = GetImageXSize();
5518 +               pszString = SPrintArray(GDT_UInt32, aiDimSizes, 2, "x");
5519 +       }
5520 +
5521 +       rtnBuf = "[" + pszString + "] " + ms_DatasetName + " " + ms_DataTypeName + " (" +
5522 +                       GDALGetDataTypeName(maptr_DS->GetRasterBand(1)->GetRasterDataType()) + ")";
5523 +
5524 +       return rtnBuf;
5525 +}
5526 +
5527 +/************************************************************************/
5528 +/*                            GetNativeFormat()                         */
5529 +/************************************************************************/
5530 +
5531 +/**
5532 + * \brief Fetch the native format of a coverage.
5533 + *
5534 + * The method will return the native format of a coverage. GDAL API
5535 + * GDALGetDriverShortName() will be called to generate the format.
5536 + *
5537 + * @return the string of dataset native format, in forms of GDAL Formats
5538 + * Code. See http://gdal.org/formats_list.html for details.
5539 + */
5540 +
5541 +string AbstractDataset::GetNativeFormat()
5542 +{
5543 +       return ms_NativeFormat;
5544 +}
5545 +
5546 +/************************************************************************/
5547 +/*                            IsbGeoTransformSet()                      */
5548 +/************************************************************************/
5549 +
5550 +/**
5551 + * \brief Determine whether set the affine geoTransform for a coverage.
5552 + *
5553 + * The method will return the status of the affine GeoTransform matrix.
5554 + *
5555 + * @return TRUE if set already or FALSE on failure..
5556 + */
5557 +
5558 +int AbstractDataset::IsbGeoTransformSet()
5559 +{
5560 +       return mb_GeoTransformSet;
5561 +}
5562 +
5563 +/************************************************************************/
5564 +/*                            GetNativeBBox()                           */
5565 +/************************************************************************/
5566 +
5567 +/**
5568 + * \brief Fetch the bounding box of a coverage under the native CRS.
5569 + *
5570 + * The method will fetch the bounding box of the coverage under native CRS.
5571 + * The sequence of values stored in array is: xmin, xmax, ymin, ymax
5572 + *
5573 + * @param bBox an existing four double buffer into which the
5574 + * native bounding box values will be placed.
5575 + */
5576 +
5577 +void AbstractDataset::GetNativeBBox(double bBox[])
5578 +{
5579 +       if (mb_GeoTransformSet)
5580 +       {
5581 +               bBox[0] = md_Geotransform[0];
5582 +               bBox[1] = bBox[0] + GetImageXSize() * md_Geotransform[1];
5583 +               bBox[3] = md_Geotransform[3];
5584 +               bBox[2] = bBox[3] + GetImageYSize() * md_Geotransform[5];
5585 +       }
5586 +       else
5587 +       {
5588 +               bBox[0] = 0;
5589 +               bBox[1] = maptr_DS->GetRasterXSize() - 1;
5590 +               bBox[2] = 0;
5591 +               bBox[3] = maptr_DS->GetRasterYSize() - 1;
5592 +       }
5593 +}
5594 +
5595 +/************************************************************************/
5596 +/*                            GetGeoMinMax()                            */
5597 +/************************************************************************/
5598 +
5599 +/**
5600 + * \brief Fetch the bounding box of a coverage under EPSG:4326.
5601 + *
5602 + * The method will fetch the bounding box of the coverage under EPSG:4326
5603 + * CRS. The sequence of values stored in array is: xmin, xmax, ymin, ymax
5604 + *
5605 + * @param bBox an existing four double buffer into which the geographic
5606 + * bounding box values will be placed.
5607 + *
5608 + * @return CE_None on success or CE_Failure on failure.
5609 + */
5610 +
5611 +CPLErr AbstractDataset::GetGeoMinMax(double geoMinMax[])
5612 +{
5613 +       if (!mb_GeoTransformSet)
5614 +       {
5615 +               SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
5616 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to get Geo-BoundingBox coordinates");
5617 +               return CE_Failure;
5618 +       }
5619 +
5620 +       geoMinMax[0] = md_Geotransform[0];
5621 +       geoMinMax[1] = geoMinMax[0] + GetImageXSize() * md_Geotransform[1];
5622 +       geoMinMax[3] = md_Geotransform[3];
5623 +       geoMinMax[2] = geoMinMax[3] + GetImageYSize() * md_Geotransform[5];
5624 +
5625 +
5626 +       if (mo_NativeCRS.IsGeographic() || Find_Compare_SubStr(ms_DataTypeName, "MODIS"))//for modis data
5627 +       {
5628 +               geoMinMax[0] = (geoMinMax[0] >= -180.0) ? geoMinMax[0] : -180.0;
5629 +               geoMinMax[1] = (geoMinMax[1] <=  180.0) ? geoMinMax[1] :  180.0;
5630 +               geoMinMax[2] = (geoMinMax[2] >=  -90.0) ? geoMinMax[2] :  -90.0;
5631 +               geoMinMax[3] = (geoMinMax[3] <=   90.0) ? geoMinMax[3] :   90.0;
5632 +               return CE_None;
5633 +       }
5634 +
5635 +       OGRSpatialReference oGeoSRS;
5636 +       oGeoSRS.CopyGeogCSFrom(&mo_NativeCRS);
5637 +
5638 +       My2DPoint llPt(geoMinMax[0], geoMinMax[2]);
5639 +       My2DPoint urPt(geoMinMax[1], geoMinMax[3]);
5640 +       if (CE_None != bBox_transFormmate(mo_NativeCRS, oGeoSRS, llPt, urPt))
5641 +       {
5642 +               SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
5643 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to transform bounding box coordinates to geographic coordinates.");
5644 +               return CE_Failure;
5645 +       }
5646 +
5647 +       geoMinMax[0] = llPt.mi_X;
5648 +       geoMinMax[1] = urPt.mi_X;
5649 +       geoMinMax[2] = llPt.mi_Y;
5650 +       geoMinMax[3] = urPt.mi_Y;
5651 +
5652 +       return CE_None;
5653 +}
5654 +
5655 +
5656 +/************************************************************************/
5657 +/*                            GetImageXSize()                           */
5658 +/************************************************************************/
5659 +
5660 +/**
5661 + * \brief Fetch coverage width in pixels.
5662 + *
5663 + * The method will return the width of coverage in pixels. GDAL API
5664 + * GetRasterXSize() will be called to generate the width value.
5665 + *
5666 + * @return the width in pixels of raster bands in this coverage.
5667 + */
5668 +
5669 +int AbstractDataset::GetImageXSize()
5670 +{
5671 +       return maptr_DS->GetRasterXSize();
5672 +}
5673 +
5674 +/************************************************************************/
5675 +/*                            GetImageYSize()                           */
5676 +/************************************************************************/
5677 +
5678 +/**
5679 + * \brief Fetch coverage height in pixels.
5680 + *
5681 + * The method will return the height of coverage in pixels. GDAL API
5682 + * GetRasterYSize() will be called to generate the height value.
5683 + *
5684 + * @return the height in pixels of raster bands in this coverage.
5685 + */
5686 +int AbstractDataset::GetImageYSize()
5687 +{
5688 +       return maptr_DS->GetRasterYSize();
5689 +}
5690 +
5691 +/************************************************************************/
5692 +/*                        GetCoverageBeginTime()                        */
5693 +/************************************************************************/
5694 +
5695 +/**
5696 + * \brief Fetch the begin date/time of a coverage.
5697 + *
5698 + * The method will return the begin date/time of a coverage. For MODIS data,
5699 + * each granule will cover a range of time; for TRMM data, the daily data
5700 + * will cover a whole day, and monthly data will cover a whole month.
5701 + *
5702 + * @return the string of begin date/time corresponding to the coverage.
5703 + */
5704 +
5705 +string AbstractDataset::GetCoverageBeginTime()
5706 +{
5707 +       return ms_CoverageBeginTime;
5708 +}
5709 +
5710 +/************************************************************************/
5711 +/*                        GetCoverageBeginTime()                        */
5712 +/************************************************************************/
5713 +
5714 +/**
5715 + * \brief Fetch the end date/time of a coverage.
5716 + *
5717 + * The method will return the end date/time of a coverage. For MODIS data,
5718 + * each granule will cover a range of time; for TRMM data, the daily data
5719 + * will cover a whole day, and monthly data will cover a whole month.
5720 + *
5721 + * @return the string of end date/time corresponding to the coverage.
5722 + */
5723 +
5724 +string AbstractDataset::GetCoverageEndTime()
5725 +{
5726 +       return ms_CoverageEndTime;
5727 +}
5728 +
5729 +/************************************************************************/
5730 +/*                        getCoverageSubType()                          */
5731 +/************************************************************************/
5732 +
5733 +/**
5734 + * \brief Fetch the coverage type.
5735 + *
5736 + * The method will return the type of the coverage, such as
5737 + * "ReferenceableDataset" and "RectifiedDataset".
5738 + *
5739 + * @return the string of coverage type.
5740 + */
5741 +
5742 +string AbstractDataset::GetCoverageSubType()
5743 +{
5744 +       return ms_CoverageSubType;
5745 +}
5746 +
5747 +/************************************************************************/
5748 +/*                        getFieldQuantityDef()                         */
5749 +/************************************************************************/
5750 +
5751 +/**
5752 + * \brief Fetch the field units of a coverage.
5753 + *
5754 + * The method will return the field units of coverage. For example to
5755 + * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, units equals
5756 + * to reflectance.
5757 + *
5758 + * @return the string of coverage field units.
5759 + */
5760 +
5761 +string AbstractDataset::GetFieldQuantityDef()
5762 +{
5763 +       return ms_FieldQuantityDef;
5764 +}
5765 +
5766 +/************************************************************************/
5767 +/*                        GetAllowValues()                              */
5768 +/************************************************************************/
5769 +
5770 +/**
5771 + * \brief Fetch the allow values of a coverage.
5772 + *
5773 + * The method will return the valid range of a coverage. For example to
5774 + * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, valid_range
5775 + * equals to (-100, 16000).
5776 + *
5777 + * @return the string of valid range of a coverage, in the forms of "min, max".
5778 + */
5779 +
5780 +string AbstractDataset::GetAllowValues()
5781 +{
5782 +       return ms_AllowRanges;
5783 +}
5784 +
5785 +/************************************************************************/
5786 +/*                        GetISO19115Metadata()                         */
5787 +/************************************************************************/
5788 +
5789 +/**
5790 + * \brief Fetch the coverage metadata which is compliant to ISO 19115:2003
5791 + * - GeoGraphic information -- Metadata; and ISO 19115(2):2009 - GeoGraphic
5792 + * information -- Metadata -- Part 2.
5793 + *
5794 + * The method will return the metadata of a coverage based on ISO 19115
5795 + * and ISO 19115(2).
5796 + *
5797 + * ISO 19115:2003 defines the schema required for
5798 + * describing geographic information and services. It provides information
5799 + * about the identification, the extent, the quality, the spatial and temporal
5800 + * schema, spatial reference, and distribution of digital geographic data.
5801 + *
5802 + * ISO 19115-2:2009 extends the existing geographic metadata standard by
5803 + * defining the schema required for describing imagery and gridded data.
5804 + * It provides information about the properties of the measuring equipment
5805 + * used to acquire the data, the geometry of the measuring process employed
5806 + * by the equipment, and the production process used to digitize the raw data.
5807 + * This extension deals with metadata needed to describe the derivation of
5808 + * geographic information from raw data, including the properties of the
5809 + * measuring system, and the numerical methods and computational procedures
5810 + * used in the derivation. The metadata required to address coverage data in
5811 + * general is addressed sufficiently in the general part of ISO 19115.
5812 + *
5813 + * @return the string of metadata of a coverage.
5814 + */
5815 +
5816 +string AbstractDataset::GetISO19115Metadata()
5817 +{
5818 +       return ms_ISO19115Metadata;
5819 +}
5820 +
5821 +/************************************************************************/
5822 +/*                        GetCoverageArchiveTime()                      */
5823 +/************************************************************************/
5824 +
5825 +/**
5826 + * \brief Fetch the archive date/time of this dataset.
5827 + *
5828 + * The method will return the archive date/time of dataset (granule).
5829 + *
5830 + * @return The string of archive date/time.
5831 + */
5832 +
5833 +string AbstractDataset::GetCoverageArchiveTime()
5834 +{
5835 +       return ms_CoverageArchiveTime;
5836 +}
5837 +
5838 +/************************************************************************/
5839 +/*                        GetCoveragePlatform()                         */
5840 +/************************************************************************/
5841 +
5842 +/**
5843 + * \brief Fetch the platform name of this dataset.
5844 + *
5845 + * The method will return the platform name of dataset (granule).
5846 + *
5847 + * @return The string of platform name.
5848 + */
5849 +
5850 +string AbstractDataset::GetCoveragePlatform()
5851 +{
5852 +       return ms_CoveragePlatform;
5853 +}
5854 +
5855 +/************************************************************************/
5856 +/*                        GetCoverageInstrument()                       */
5857 +/************************************************************************/
5858 +
5859 +/**
5860 + * \brief Fetch the instrument name of this dataset.
5861 + *
5862 + * The method will return the instrument name of dataset (granule).
5863 + *
5864 + * @return The string of instrument name.
5865 + */
5866 +
5867 +string AbstractDataset::GetCoverageInstrument()
5868 +{
5869 +       return ms_CoverageInstrument;
5870 +}
5871 +
5872 +/************************************************************************/
5873 +/*                        GetCoverageInstrument()                       */
5874 +/************************************************************************/
5875 +
5876 +/**
5877 + * \brief Fetch the sensor name of this dataset.
5878 + *
5879 + * The method will return the sensor name of dataset (granule).
5880 + *
5881 + * @return The string of sensor name.
5882 + */
5883 +
5884 +string AbstractDataset::GetCoverageSensor()
5885 +{
5886 +       return ms_CoverageSensor;
5887 +}
5888 +
5889 +/************************************************************************/
5890 +/*                        GetImageBandCount()                           */
5891 +/************************************************************************/
5892 +
5893 +/**
5894 + * \brief Fetch the number of raster bands on this dataset.
5895 + *
5896 + * The method will return the number of raster bands on this dataset. GDAL
5897 + * API GetRasterCount() will be called to get the count number.
5898 + *
5899 + * @return the number of raster bands on this dataset.
5900 + */
5901 +
5902 +int AbstractDataset::GetImageBandCount()
5903 +{
5904 +       return maptr_DS->GetRasterCount();
5905 +}
5906 +
5907 +/************************************************************************/
5908 +/*                        getMissingValue()                             */
5909 +/************************************************************************/
5910 +
5911 +/**
5912 + * \brief Fetch the filled value (missing value) of a coverage.
5913 + *
5914 + * The method will return the filled value of a coverage.
5915 + *
5916 + * @return the value of filled value of a coverage.
5917 + */
5918 +
5919 +const double& AbstractDataset::GetMissingValue()
5920 +{
5921 +       return md_MissingValue;
5922 +}
5923 +
5924 +/************************************************************************/
5925 +/*                        GetProjectionRef()                            */
5926 +/************************************************************************/
5927 +
5928 +/**
5929 + * \brief Fetch the native projection reference of a coverage.
5930 + *
5931 + * The method will return the the native projection reference of a coverage.
5932 + *
5933 + * @return the string of the native projection reference of a coverage.
5934 + */
5935 +
5936 +string AbstractDataset::GetProjectionRef()
5937 +{
5938 +       char* pszProjection = NULL;
5939 +       mo_NativeCRS.exportToWkt(&pszProjection);
5940 +       string tmpStr = pszProjection;
5941 +       CPLFree(pszProjection);
5942 +
5943 +       return tmpStr;
5944 +}
5945 +
5946 +/************************************************************************/
5947 +/*                        SetMetaDataList()                             */
5948 +/************************************************************************/
5949 +
5950 +/**
5951 + * \brief Set the metadata list for this coverage based on dataset object.
5952 + *
5953 + * The method will set the metadata list for the coverage based on its
5954 + * corresponding GDALDataset object. Will be implemented in the subclasses
5955 + * of AbstractDataset.
5956 + *
5957 + * @param hSrc the GDALDataset object corresponding to coverage.
5958 + *
5959 + * @return CE_Failure.
5960 + */
5961 +
5962 +CPLErr AbstractDataset::SetMetaDataList(GDALDataset* hSrc)
5963 +{
5964 +       return CE_Failure;
5965 +}
5966 +
5967 +/************************************************************************/
5968 +/*                        GetMetaDataList()                             */
5969 +/************************************************************************/
5970 +
5971 +/**
5972 + * \brief Fetch the metadata list for this coverage.
5973 + *
5974 + * The method will return the metadata list for the coverage.
5975 + *
5976 + * @return the list of metadate.
5977 + */
5978 +
5979 +vector<string> AbstractDataset::GetMetaDataList()
5980 +{
5981 +       return mv_MetaDataList;
5982 +}
5983 +
5984 +/************************************************************************/
5985 +/*                            GetBandList()                             */
5986 +/************************************************************************/
5987 +
5988 +/**
5989 + * \brief Fetch the contained band list of request coverage.
5990 + *
5991 + * The method will return the contained band list of request coverage.
5992 + *
5993 + * @return the band array.
5994 + */
5995 +
5996 +vector<int> AbstractDataset::GetBandList()
5997 +{
5998 +       return mv_BandList;
5999 +}
6000 +
6001 +/************************************************************************/
6002 +/*                        getNativeCRS_URN()                            */
6003 +/************************************************************************/
6004 +
6005 +/**
6006 + * \brief Fetch the native CRS code of coverage.
6007 + *
6008 + * The method will return the native CRS code of coverage.
6009 + *
6010 + * @return the string of the URN for native CRS of coverage.
6011 + */
6012 +
6013 +string AbstractDataset::GetNativeCRS_URN()
6014 +{
6015 +       string urn;
6016 +
6017 +       if (mo_NativeCRS.IsProjected())
6018 +       {
6019 +               const char* nativeAuthorityName =
6020 +                               mo_NativeCRS.GetAuthorityName("PROJCS");
6021 +               const char* nativeAuthorityCode =
6022 +                               mo_NativeCRS.GetAuthorityCode("PROJCS");
6023 +
6024 +               urn = "urn:ogc:def:crs:";
6025 +
6026 +               if (nativeAuthorityName && (EQUAL(nativeAuthorityName,"EPSG")
6027 +                               || EQUAL(nativeAuthorityName,"OGP")
6028 +                               || EQUAL(nativeAuthorityName,"OGC")))
6029 +                       urn += (string) nativeAuthorityName + (string) ":6.3:";
6030 +               else
6031 +                       urn += "CSISS:0.0:";
6032 +
6033 +               if (nativeAuthorityCode)
6034 +                       urn += (string) nativeAuthorityCode;
6035 +               else
6036 +                       urn += "80000000";
6037 +       }
6038 +       else if (mo_NativeCRS.IsGeographic())
6039 +       {
6040 +               const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
6041 +               const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
6042 +
6043 +               urn = "urn:ogc:def:crs:";
6044 +               if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
6045 +                               || EQUAL(geoAuthorityName,"OGP")
6046 +                               || EQUAL(geoAuthorityName,"OGC")))
6047 +                       urn += (string) geoAuthorityName + (string) ":6.3:";
6048 +               else
6049 +                       urn += "CSISS:0.0:";
6050 +
6051 +               if (geoAuthorityCode)
6052 +                       urn += (string) geoAuthorityCode;
6053 +               else
6054 +                       urn += "70000000";
6055 +       }
6056 +       else
6057 +               urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
6058 +
6059 +       return urn;
6060 +}
6061 +
6062 +/************************************************************************/
6063 +/*                        GetGeoCRS_URN()                               */
6064 +/************************************************************************/
6065 +
6066 +/**
6067 + * \brief Fetch the Geographic CRS code of coverage.
6068 + *
6069 + * The method will return the Geographic CRS code of coverage.
6070 + *
6071 + * @return the URN for Geographic CRS of coverage.
6072 + */
6073 +
6074 +string AbstractDataset::GetGeoCRS_URN()
6075 +{
6076 +       string urn;
6077 +
6078 +       if (mo_NativeCRS.IsProjected() || mo_NativeCRS.IsGeographic())
6079 +       {
6080 +               const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
6081 +               const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
6082 +
6083 +               urn = "urn:ogc:def:crs:";
6084 +               if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
6085 +                               || EQUAL(geoAuthorityName,"OGP")
6086 +                               || EQUAL(geoAuthorityName,"OGC")))
6087 +                       urn += (string) geoAuthorityName + (string) ":6.3:";
6088 +               else
6089 +                       urn += "CSISS:0.0:";
6090 +
6091 +               if (geoAuthorityCode)
6092 +                       urn += (string) geoAuthorityCode;
6093 +               else
6094 +                       urn += "70000000";
6095 +
6096 +       }
6097 +       else
6098 +               urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
6099 +
6100 +       return urn;
6101 +}
6102 +
6103 +/************************************************************************/
6104 +/*                        IsCrossingIDL()                               */
6105 +/************************************************************************/
6106 +
6107 +/**
6108 + * \brief Determine whether the extend of coverage cross the International
6109 + * Date Line (IDL).
6110 + *
6111 + * The method will return the status of whether the extend of coverage
6112 + * cross the International Date Line (IDL).
6113 + *
6114 + * @return the TRUE of the coverage extent cross the IDL, otherwise FALSE.
6115 + */
6116 +
6117 +int AbstractDataset::IsCrossingIDL()
6118 +{
6119 +       double bboxArray[4];
6120 +       GetNativeBBox(bboxArray);
6121 +
6122 +       OGRSpatialReference latlonSRS;
6123 +       latlonSRS.SetWellKnownGeogCS("WGS84");
6124 +       My2DPoint llPtex(bboxArray[0], bboxArray[2]);
6125 +       My2DPoint urPtex(bboxArray[1], bboxArray[3]);
6126 +       bBox_transFormmate(mo_NativeCRS, latlonSRS, llPtex, urPtex);
6127 +
6128 +       int bCrossCenter = false;
6129 +       if(urPtex.mi_X < 0 && llPtex.mi_X > 0)
6130 +               bCrossCenter = true;
6131 +
6132 +       return bCrossCenter;
6133 +}
6134 +
6135 +/************************************************************************/
6136 +/*                        GetSuggestedWarpResolution()                  */
6137 +/************************************************************************/
6138 +
6139 +/**
6140 + * \brief Get the suggested warp option, method 1.
6141 + *
6142 + * @return CE_Failure if an error occurs, otherwise CE_None.
6143 + */
6144 +
6145 +CPLErr AbstractDataset::GetSuggestedWarpResolution(    OGRSpatialReference& dstCRS,
6146 +                                                                                                       double adfDstGeoTransform[],
6147 +                                                                                                       int &nPixels,
6148 +                                                                                                       int &nLines)
6149 +{
6150 +       if (!dstCRS.IsProjected() && !dstCRS.IsGeographic())
6151 +       {
6152 +               adfDstGeoTransform[0] = 0;
6153 +               adfDstGeoTransform[1] = 1;
6154 +               adfDstGeoTransform[2] = 0;
6155 +               adfDstGeoTransform[3] = 0;
6156 +               adfDstGeoTransform[4] = 0;
6157 +               adfDstGeoTransform[5] = 1;
6158 +
6159 +               nPixels = GetImageXSize();
6160 +               nLines = GetImageYSize();
6161 +
6162 +       }
6163 +       else if (dstCRS.IsSame(&mo_NativeCRS))
6164 +       {
6165 +               memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
6166 +               nPixels = GetImageXSize();
6167 +               nLines = GetImageYSize();
6168 +       }
6169 +       else
6170 +       {
6171 +               char *pszDstWKT;
6172 +               dstCRS.exportToWkt(&pszDstWKT);
6173 +               char *pszSrcWKT;
6174 +               mo_NativeCRS.exportToWkt(&pszSrcWKT);
6175 +
6176 +               void *hTransformArg = GDALCreateGenImgProjTransformer(maptr_DS.get(),
6177 +                               (const char*) pszSrcWKT, NULL, (const char*) pszDstWKT, TRUE, 1000.0, 0);
6178 +               OGRFree(pszDstWKT);
6179 +               OGRFree(pszSrcWKT);
6180 +               if (hTransformArg == NULL)
6181 +               {
6182 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
6183 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create GDAL GenImgProjTransformer.");
6184 +
6185 +                       return CE_Failure;
6186 +               }
6187 +               /* -------------------------------------------------------------------- */
6188 +               /*      Get approximate output definition.                              */
6189 +               /* -------------------------------------------------------------------- */
6190 +               if (GDALSuggestedWarpOutput(maptr_DS.get(), GDALGenImgProjTransform,
6191 +                               hTransformArg, adfDstGeoTransform, &nPixels, &nLines) != CE_None)
6192 +               {
6193 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
6194 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Computing Output Resolution.");
6195 +
6196 +                       return CE_Failure;
6197 +               }
6198 +
6199 +               GDALDestroyGenImgProjTransformer(hTransformArg);
6200 +       }
6201 +
6202 +       return CE_None;
6203 +}
6204 +
6205 +/************************************************************************/
6206 +/*                        GetSuggestedWarpResolution2()                 */
6207 +/************************************************************************/
6208 +
6209 +/**
6210 + * \brief Get the suggested warp option, method 2.
6211 + *
6212 + * @return CE_Failure if an error occurs, otherwise CE_None.
6213 + */
6214 +
6215 +CPLErr AbstractDataset::GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS,
6216 +                                                                                                       double adfDstGeoTransform[],
6217 +                                                                                                       int &nPixels,
6218 +                                                                                                       int &nLines)
6219 +{
6220 +       if (dstCRS.IsLocal())
6221 +       {
6222 +               adfDstGeoTransform[0] = 0;
6223 +               adfDstGeoTransform[1] = 1;
6224 +               adfDstGeoTransform[2] = 0;
6225 +               adfDstGeoTransform[3] = 0;
6226 +               adfDstGeoTransform[4] = 0;
6227 +               adfDstGeoTransform[5] = 1;
6228 +
6229 +               nPixels = GetImageXSize();
6230 +               nLines = GetImageYSize();
6231 +       }
6232 +       else if (dstCRS.IsSame(&mo_NativeCRS))
6233 +       {
6234 +               memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
6235 +               nPixels = GetImageXSize();
6236 +               nLines = GetImageYSize();
6237 +       }
6238 +       else
6239 +       {
6240 +               double bboxArray[4];
6241 +               GetNativeBBox(bboxArray);
6242 +
6243 +               My2DPoint llPt(bboxArray[0], bboxArray[2]);
6244 +               My2DPoint urPt(bboxArray[1], bboxArray[3]);
6245 +               if (CE_None != bBox_transFormmate(mo_NativeCRS, dstCRS, llPt, urPt))
6246 +               {
6247 +                       SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution2()");
6248 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform bounding box Coordinate.");
6249 +                       return CE_Failure;
6250 +               }
6251 +
6252 +               double xRes, yRes;
6253 +               if(IsCrossingIDL())
6254 +               {
6255 +                       yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
6256 +                       xRes = fabs((llPt.mi_X - urPt.mi_X) / GetImageXSize());
6257 +                       nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
6258 +                       nPixels = fabs((llPt.mi_X - urPt.mi_X) / xRes + 0.5);
6259 +               }else
6260 +               {
6261 +                       xRes = (urPt.mi_X - llPt.mi_X) / GetImageXSize();
6262 +                       yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
6263 +                       nPixels = (urPt.mi_X - llPt.mi_X) / xRes + 0.5;
6264 +                       nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
6265 +               }
6266 +
6267 +               xRes = MIN(xRes,yRes);
6268 +               yRes = MIN(xRes,yRes);
6269 +
6270 +               adfDstGeoTransform[0] = llPt.mi_X;
6271 +               adfDstGeoTransform[1] = xRes;
6272 +               adfDstGeoTransform[2] = 0;
6273 +               adfDstGeoTransform[3] = urPt.mi_Y;
6274 +               adfDstGeoTransform[4] = 0;
6275 +               adfDstGeoTransform[5] = -yRes;
6276 +       }
6277 +
6278 +       return CE_None;
6279 +}
6280 +
6281 +/************************************************************************/
6282 +/*                           DatasetWarper()                            */
6283 +/************************************************************************/
6284 +
6285 +/**
6286 + * Wrap the dataset to a GDALDataset object based on input parameters.
6287 + *
6288 + * @return the warpped GDALDataset object.
6289 + */
6290 +/************************************************************************/
6291 +/*                        DatasetWarper()                               */
6292 +/************************************************************************/
6293 +
6294 +/**
6295 + * \brief Wrap the dataset to a GDALDataset object based on input parameters.
6296 + *
6297 + * @return GDALDatset object.
6298 + */
6299 +
6300 +GDALDataset* AbstractDataset::DatasetWarper(int& IsRefDS,
6301 +                                                                                       OGRSpatialReference& dstCRS,
6302 +                                                                                       int& iDstRasterXsize,
6303 +                                                                                       int& iDstRasterYsize,
6304 +                                                                                       double pDstGeoTransform[],
6305 +                                                                                       GDALResampleAlg eResampleAlg)
6306 +{
6307 +       OGRSpatialReference locCRS=dstCRS;
6308 +       if (dstCRS.IsLocal())
6309 +               locCRS=mo_NativeCRS;
6310 +
6311 +       if((mo_NativeCRS.IsSame(&locCRS) &&
6312 +                       iDstRasterXsize == maptr_DS->GetRasterXSize() &&
6313 +                       iDstRasterYsize == maptr_DS->GetRasterYSize())&&
6314 +                       CPLIsEqual(md_Geotransform[0],pDstGeoTransform[0])&&
6315 +                       CPLIsEqual(md_Geotransform[1],pDstGeoTransform[1])&&
6316 +                       CPLIsEqual(md_Geotransform[3],pDstGeoTransform[3])&&
6317 +                       CPLIsEqual(md_Geotransform[5],pDstGeoTransform[5]))
6318 +       {
6319 +               IsRefDS = TRUE;
6320 +               return maptr_DS.get();
6321 +       }
6322 +
6323 +       char *sDstCRS_WKT;
6324 +       locCRS.exportToWkt(&sDstCRS_WKT);
6325 +
6326 +       /* Create a memory data-set for re-projection */
6327 +       GDALDriverH poDriver = GDALGetDriverByName("MEM");
6328 +
6329 +       int nBand = maptr_DS->GetRasterCount();
6330 +       GDALDataset* hMemDS = (GDALDataset*) GDALCreate(poDriver, "", iDstRasterXsize,
6331 +                       iDstRasterYsize, nBand, GDALGetRasterDataType(maptr_DS->GetRasterBand(1)), NULL);
6332 +       if (NULL == hMemDS)
6333 +       {
6334 +               GDALClose(poDriver);
6335 +               OGRFree(sDstCRS_WKT);
6336 +               return NULL;
6337 +       }
6338 +
6339 +       hMemDS->SetProjection(sDstCRS_WKT);
6340 +       hMemDS->SetGeoTransform(pDstGeoTransform);
6341 +
6342 +       for (int i = 1; i <= nBand; i++)
6343 +       {
6344 +               hMemDS->GetRasterBand(i)->SetNoDataValue(md_MissingValue);
6345 +       }
6346 +
6347 +       /* -------------------------------------------------------------------- */
6348 +       /*      Perform the re-projection.                                       */
6349 +       /* -------------------------------------------------------------------- */
6350 +       char *srcWKT;
6351 +       mo_NativeCRS.exportToWkt(&srcWKT);
6352 +       if (CE_None != GDALReprojectImage(maptr_DS.get(), srcWKT, hMemDS,
6353 +                       sDstCRS_WKT, eResampleAlg, 0, 0.125, NULL, NULL, NULL))
6354 +       {
6355 +               GDALClose(poDriver);
6356 +               GDALClose(GDALDatasetH(hMemDS));
6357 +               OGRFree(sDstCRS_WKT);
6358 +               OGRFree(srcWKT);
6359 +               return NULL;
6360 +       }
6361 +       IsRefDS = FALSE;
6362 +       OGRFree(sDstCRS_WKT);
6363 +       OGRFree(srcWKT);
6364 +
6365 +       return hMemDS;
6366 +}
6367 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/5c/5c3da4f5eaa9825bf8d68c07943d2343d2cf05e2.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/5c/5c3da4f5eaa9825bf8d68c07943d2343d2cf05e2.svn-base
6368 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/5c/5c3da4f5eaa9825bf8d68c07943d2343d2cf05e2.svn-base     1970-01-01 01:00:00.000000000 +0100
6369 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/5c/5c3da4f5eaa9825bf8d68c07943d2343d2cf05e2.svn-base  2014-03-03 15:47:37.810232939 +0100
6370 @@ -0,0 +1,150 @@
6371 +/******************************************************************************
6372 + * $Id: AbstractDataset.h 2011-07-19 16:24:00Z $
6373 + *
6374 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
6375 + *                      for Earth Observation: Open Source Reference Implementation
6376 + * Purpose:  AbstractDataset class definition
6377 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
6378 + *
6379 + ******************************************************************************
6380 + * * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
6381 + *
6382 + * Permission is hereby granted, free of charge, to any person obtaining a
6383 + * copy of this software and associated documentation files (the "Software"),
6384 + * to deal in the Software without restriction, including without limitation
6385 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6386 + * and/or sell copies of the Software, and to permit persons to whom the
6387 + * Software is furnished to do so, subject to the following conditions:
6388 + *
6389 + * The above copyright notice and this permission notice shall be included
6390 + * in all copies or substantial portions of the Software.
6391 + *
6392 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6393 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6394 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
6395 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6396 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
6397 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
6398 + * DEALINGS IN THE SOFTWARE.
6399 + ****************************************************************************/
6400 +
6401 +#ifndef ABSTRACTDATASET_H_
6402 +#define ABSTRACTDATASET_H_
6403 +
6404 +#include <vector>
6405 +#include <memory>
6406 +
6407 +#include <gdal.h>
6408 +#include <gdal_priv.h>
6409 +#include <gdalwarper.h>
6410 +#include <ogrsf_frmts.h>
6411 +#include <ogr_spatialref.h>
6412 +#include <cpl_conv.h>
6413 +#include <cpl_minixml.h>
6414 +#include <vrtdataset.h>
6415 +
6416 +#include "wcsUtil.h"
6417 +
6418 +using namespace std;
6419 +
6420 +/* ******************************************************************** */
6421 +/*                             AbstractDataset                          */
6422 +/* ******************************************************************** */
6423 +
6424 +//! Abstract dataset model definition. Based on GDAL dataset model.
6425 +class AbstractDataset {
6426 +
6427 +protected:
6428 +    auto_ptr<GDALDataset> maptr_DS;
6429 +
6430 +    // Coverage Information Related
6431 +    string ms_CoverageID;
6432 +    string ms_CoverageBeginTime;
6433 +    string ms_CoverageEndTime;
6434 +    string ms_CoverageSubType;
6435 +    string ms_CoverageArchiveTime;
6436 +    string ms_CoveragePlatform;
6437 +    string ms_CoverageInstrument;
6438 +    string ms_CoverageSensor;
6439 +    string ms_SrcFilename;
6440 +    string ms_DatasetName;
6441 +    string ms_DataTypeName;
6442 +    string ms_NativeFormat;
6443 +    string ms_FieldQuantityDef;
6444 +    string ms_AllowRanges;
6445 +    string ms_ISO19115Metadata;
6446 +
6447 +    vector<int> mv_BandList;
6448 +    vector<string> mv_MetaDataList;
6449 +
6450 +    double md_Geotransform[6];
6451 +    double md_GeoMinMax[4]; // Order: xmin, xmax, ymin, ymax
6452 +    double md_MissingValue;
6453 +
6454 +    int mb_GeoTransformSet;
6455 +    int mb_IsVirtualDS;
6456 +
6457 +    OGRSpatialReference mo_NativeCRS;
6458 +
6459 +protected:
6460 +    AbstractDataset();
6461 +    virtual CPLErr SetNativeCRS();
6462 +    virtual CPLErr SetGeoTransform();
6463 +    virtual CPLErr SetGDALDataset(const int isSimple = 0);
6464 +    virtual CPLErr SetMetaDataList(GDALDataset*);
6465 +
6466 +public:
6467 +    AbstractDataset(const string&, vector<int> &);
6468 +    virtual ~AbstractDataset();
6469 +
6470 +    GDALDataset* GetGDALDataset();
6471 +
6472 +    // Virtual Functions Definition
6473 +    virtual CPLErr InitialDataset(const int isSimple = 0);
6474 +
6475 +    // Fetch Function Related
6476 +    const OGRSpatialReference& GetNativeCRS();
6477 +    const double& GetMissingValue();
6478 +    int GetGeoTransform(double geoTrans[]);
6479 +    vector<string> GetMetaDataList();
6480 +    vector<int> GetBandList();
6481 +    void GetNativeBBox(double bBox[]);
6482 +    CPLErr GetGeoMinMax(double geoMinMax[]);
6483 +
6484 +    int GetImageBandCount();
6485 +    int GetImageXSize();
6486 +    int GetImageYSize();
6487 +    string GetResourceFileName();
6488 +    string GetDatasetName();
6489 +    string GetDataTypeName();
6490 +    string GetNativeFormat();
6491 +    string GetCoverageID();
6492 +    string GetDatasetDescription();
6493 +    string GetNativeCRS_URN();
6494 +    string GetGeoCRS_URN();
6495 +    string GetProjectionRef();
6496 +    string GetCoverageBeginTime();
6497 +    string GetCoverageEndTime();
6498 +    string GetCoverageSubType();
6499 +    string GetFieldQuantityDef();
6500 +    string GetAllowValues();
6501 +    string GetISO19115Metadata();
6502 +    string GetCoverageArchiveTime();
6503 +    string GetCoveragePlatform();
6504 +    string GetCoverageInstrument();
6505 +    string GetCoverageSensor();
6506 +
6507 +    // Fetch Variables Status Related
6508 +    int IsbGeoTransformSet();
6509 +    int IsCrossingIDL();
6510 +
6511 +    CPLErr GetSuggestedWarpResolution(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
6512 +                                      int &nLines);
6513 +    CPLErr GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
6514 +                                       int &nLines);
6515 +
6516 +    GDALDataset* DatasetWarper(int& IsRefDS, OGRSpatialReference& dstCRS, int& iDstRasterXsize, int& iDstRasterYsize,
6517 +                               double pDstGeoTransform[], GDALResampleAlg eResampleAlg = GRA_NearestNeighbour);
6518 +};
6519 +
6520 +#endif /*ABSTRACTDATASET_H_*/
6521 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/60/603732a6a8a375d944ca25f03c7720f3d4f8e069.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/60/603732a6a8a375d944ca25f03c7720f3d4f8e069.svn-base
6522 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/60/603732a6a8a375d944ca25f03c7720f3d4f8e069.svn-base     1970-01-01 01:00:00.000000000 +0100
6523 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/60/603732a6a8a375d944ca25f03c7720f3d4f8e069.svn-base  2014-03-03 15:47:37.593566281 +0100
6524 @@ -0,0 +1,381 @@
6525 +/******************************************************************************\r
6526 + * $Id: wcsUtil.h 2011-07-19 16:24:00Z $\r
6527 + *\r
6528 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)\r
6529 + *                      for Earth Observation: Open Source Reference Implementation\r
6530 + * Purpose:  WCS Utility Function definition\r
6531 + * Author:   Yuanzheng Shao, yshao3@gmu.edu\r
6532 + *\r
6533 + ******************************************************************************\r
6534 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>\r
6535 + *\r
6536 + * Permission is hereby granted, free of charge, to any person obtaining a\r
6537 + * copy of this software and associated documentation files (the "Software"),\r
6538 + * to deal in the Software without restriction, including without limitation\r
6539 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
6540 + * and/or sell copies of the Software, and to permit persons to whom the\r
6541 + * Software is furnished to do so, subject to the following conditions:\r
6542 + *\r
6543 + * The above copyright notice and this permission notice shall be included\r
6544 + * in all copies or substantial portions of the Software.\r
6545 + *\r
6546 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
6547 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
6548 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
6549 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
6550 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
6551 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
6552 + * DEALINGS IN THE SOFTWARE.\r
6553 + ****************************************************************************/\r
6554 +\r
6555 +#ifndef WCSUTIL_H_\r
6556 +#define WCSUTIL_H_\r
6557 +\r
6558 +#include <iostream>\r
6559 +#include <fstream>\r
6560 +#include <sstream>\r
6561 +#include <vector>\r
6562 +#include <stdlib.h>\r
6563 +#include <time.h>\r
6564 +\r
6565 +#include <cpl_string.h>\r
6566 +#include "wcs_error.h"\r
6567 +#include "BoundingBox.h"\r
6568 +\r
6569 +using namespace std;\r
6570 +\r
6571 +#ifndef EQUAL\r
6572 +#if defined(WIN32) || defined(WIN32CE)\r
6573 +#  define EQUALN(a,b,n)           (strnicmp(a,b,n)==0)\r
6574 +#  define EQUAL(a,b)              (stricmp(a,b)==0)\r
6575 +#else\r
6576 +#  define EQUALN(a,b,n)           (strncasecmp(a,b,n)==0)\r
6577 +#  define EQUAL(a,b)              (strcasecmp(a,b)==0)\r
6578 +#endif\r
6579 +#endif\r
6580 +\r
6581 +#ifndef TRUE\r
6582 +#define TRUE 1\r
6583 +#endif\r
6584 +#ifndef FALSE\r
6585 +#define FALSE 0\r
6586 +#endif\r
6587 +\r
6588 +#ifndef NULL\r
6589 +#define NULL 0\r
6590 +#endif\r
6591 +\r
6592 +#ifdef WINDOWS\r
6593 +#define DELIMITER "\\"\r
6594 +#else\r
6595 +#define DELIMITER "/"\r
6596 +#endif\r
6597 +\r
6598 +const int SHORT_NAME_LEN = 128;\r
6599 +const int MAX_NAME_LEN = 512;\r
6600 +const int MAX_LIST_LEN = 1024;\r
6601 +const int MAX_LINE_LEN = 65536;\r
6602 +\r
6603 +\r
6604 +// -----------------------------------------------------------------------\r
6605 +// CGI (Common Gateway Interface) related class and functions\r
6606 +// -----------------------------------------------------------------------\r
6607 +enum CGI_METHOD_FLAG\r
6608 +{\r
6609 +       UN_KNOWN, HTTP_GET, HTTP_XML_POST\r
6610 +};\r
6611 +\r
6612 +/************************************************************************/\r
6613 +/* ==================================================================== */\r
6614 +/*                             WCSCGI                                   */\r
6615 +/* ==================================================================== */\r
6616 +/************************************************************************/\r
6617 +\r
6618 +/**\r
6619 + * \class WCSCGI "wcsUtil.h"\r
6620 + *\r
6621 + * WCSCGI class is used to acquire WCS request, both GET and POST method\r
6622 + * are supported.\r
6623 + */\r
6624 +\r
6625 +class WCSCGI\r
6626 +{\r
6627 +private:\r
6628 +       string ms_CGIContent;\r
6629 +       CGI_METHOD_FLAG me_CGIMethod;\r
6630 +\r
6631 +public:\r
6632 +       WCSCGI()\r
6633 +       {\r
6634 +               me_CGIMethod = UN_KNOWN;\r
6635 +       }\r
6636 +\r
6637 +       CPLErr Run();\r
6638 +\r
6639 +       string GetRqstContent()\r
6640 +       {\r
6641 +               return ms_CGIContent;\r
6642 +       }\r
6643 +\r
6644 +       CGI_METHOD_FLAG GetCGImethod()\r
6645 +       {\r
6646 +               return me_CGIMethod;\r
6647 +       }\r
6648 +};\r
6649 +\r
6650 +/************************************************************************/\r
6651 +/* ==================================================================== */\r
6652 +/*                             StringList                               */\r
6653 +/* ==================================================================== */\r
6654 +/************************************************************************/\r
6655 +\r
6656 +class StringList\r
6657 +{\r
6658 +private:\r
6659 +       vector<string> strings;\r
6660 +\r
6661 +public:\r
6662 +       StringList(const string& sstrings, const char delimiter);\r
6663 +       StringList(const string& sstrings, const string& delimiters);\r
6664 +       StringList(){ }\r
6665 +\r
6666 +       int indexof(string qstr);\r
6667 +\r
6668 +       void add(string newstr)\r
6669 +       {\r
6670 +               strings.push_back(newstr);\r
6671 +       }\r
6672 +\r
6673 +       void clear()\r
6674 +       {\r
6675 +               strings.clear();\r
6676 +       }\r
6677 +\r
6678 +       int size()\r
6679 +       {\r
6680 +               return strings.size();\r
6681 +       }\r
6682 +\r
6683 +       string& operator [](int index)\r
6684 +       {\r
6685 +               return strings[index];\r
6686 +       }\r
6687 +\r
6688 +       void append(StringList & s);\r
6689 +       void append(const string sstrings, const char delimiter);\r
6690 +       void append(const string sstrings, const string& delimiters);\r
6691 +\r
6692 +       string toString()\r
6693 +       {\r
6694 +               string s = "";\r
6695 +               for (int i = 0; i < size(); i++)\r
6696 +                       s += strings[i];\r
6697 +               return s;\r
6698 +       }\r
6699 +\r
6700 +       string toString(const char delimiter)\r
6701 +       {\r
6702 +               string s = "";\r
6703 +               for (int i = 0; i < size(); i++)\r
6704 +                       s += strings[i] + delimiter;\r
6705 +               return s;\r
6706 +       }\r
6707 +\r
6708 +       string toString(const string& delimiters)\r
6709 +       {\r
6710 +               string s = "";\r
6711 +               for (int i = 0; i < size(); i++)\r
6712 +                       s += strings[i] + delimiters;\r
6713 +               return s;\r
6714 +       }\r
6715 +};\r
6716 +\r
6717 +class S2C\r
6718 +{\r
6719 +\r
6720 +private:\r
6721 +       char buf[MAX_LINE_LEN];\r
6722 +\r
6723 +public:\r
6724 +       S2C(string s)\r
6725 +       {\r
6726 +               s.copy(buf, string::npos);\r
6727 +               buf[s.size()] = 0;\r
6728 +       }\r
6729 +\r
6730 +       char * c_str()\r
6731 +       {\r
6732 +               return buf;\r
6733 +       }\r
6734 +\r
6735 +};\r
6736 +\r
6737 +/************************************************************************/\r
6738 +/* ==================================================================== */\r
6739 +/*                             KVP                                      */\r
6740 +/* ==================================================================== */\r
6741 +/************************************************************************/\r
6742 +\r
6743 +class KVP\r
6744 +{\r
6745 +public:\r
6746 +       string name, value;\r
6747 +\r
6748 +       KVP& operator =(const KVP &id)\r
6749 +       {\r
6750 +               name = id.name;\r
6751 +               value = id.value;\r
6752 +               return *this;\r
6753 +       }\r
6754 +\r
6755 +       KVP& operator =(const KVP *pid)\r
6756 +       {\r
6757 +               name = pid->name;\r
6758 +               value = pid->value;\r
6759 +               return *this;\r
6760 +       }\r
6761 +\r
6762 +       KVP(string n, string v) :\r
6763 +               name(n), value(v)\r
6764 +       {\r
6765 +       }\r
6766 +\r
6767 +       KVP(string namevaluepair);\r
6768 +};\r
6769 +\r
6770 +\r
6771 +/************************************************************************/\r
6772 +/* ==================================================================== */\r
6773 +/*                             KVPsReader                               */\r
6774 +/* ==================================================================== */\r
6775 +/************************************************************************/\r
6776 +\r
6777 +class KVPsReader\r
6778 +{\r
6779 +protected:\r
6780 +       vector<KVP> m_kvps;\r
6781 +\r
6782 +public:\r
6783 +       KVPsReader()\r
6784 +       {\r
6785 +       }\r
6786 +\r
6787 +       ~KVPsReader()\r
6788 +       {\r
6789 +       }\r
6790 +\r
6791 +       KVPsReader(const string& urlStr, const char &tok);\r
6792 +\r
6793 +       KVP& operator [](const int index)\r
6794 +       {\r
6795 +               return m_kvps[index];\r
6796 +       }\r
6797 +\r
6798 +       int size()\r
6799 +       {\r
6800 +               return m_kvps.size();\r
6801 +       }\r
6802 +\r
6803 +       string getValue(const string &keyname);\r
6804 +       string getValue(const string &keyname, const string &defaultvalue);\r
6805 +       vector<string> getValues(const string &keyname);\r
6806 +};\r
6807 +\r
6808 +/************************************************************************/\r
6809 +/* ==================================================================== */\r
6810 +/*                             CFGReader                                */\r
6811 +/* ==================================================================== */\r
6812 +/************************************************************************/\r
6813 +class CFGReader\r
6814 +{\r
6815 +protected:\r
6816 +       vector<KVP> kvps;\r
6817 +\r
6818 +public:\r
6819 +       CFGReader(const string &configfilename);\r
6820 +\r
6821 +       KVP& operator [](const int index)\r
6822 +       {\r
6823 +               return kvps[index];\r
6824 +       }\r
6825 +\r
6826 +       int size()\r
6827 +       {\r
6828 +               return kvps.size();\r
6829 +       }\r
6830 +\r
6831 +       string getValue(const string &keyname);\r
6832 +       string getValue(const string &keyname, const string &defaultvalue);\r
6833 +};\r
6834 +\r
6835 +\r
6836 +// -----------------------------------------------------------------------\r
6837 +// Extra Template Functions\r
6838 +//             Exchange()                              --- used to exchange values\r
6839 +//             convertToString()               --- convert value to string\r
6840 +//             convertFromString               --- convert string to values\r
6841 +// -----------------------------------------------------------------------\r
6842 +template<class T>\r
6843 +static void Exchange(T & a, T & b)\r
6844 +{\r
6845 +       T t;\r
6846 +       t = a;\r
6847 +       a = b;\r
6848 +       b = t;\r
6849 +}\r
6850 +\r
6851 +template <class T>\r
6852 +static string convertToString(T &value)\r
6853 +{\r
6854 +       stringstream ss;\r
6855 +       ss<<value;\r
6856 +       string rtnstr = ss.str();\r
6857 +       return rtnstr;\r
6858 +}\r
6859 +\r
6860 +template <class T>\r
6861 +static void convertFromString(T &value, const string& s)\r
6862 +{\r
6863 +       stringstream ss(s);\r
6864 +       ss>>value;\r
6865 +}\r
6866 +\r
6867 +\r
6868 +// -----------------------------------------------------------------------\r
6869 +// Extra Utility Functions\r
6870 +// -----------------------------------------------------------------------\r
6871 +CPL_C_START\r
6872 +\r
6873 +// String Operation Related\r
6874 +int CPL_DLL CPL_STDCALL                CsvburstCpp(const std::string& line, std::vector<std::string>  &strSet, const char tok);\r
6875 +int CPL_DLL CPL_STDCALL                CsvburstComplexCpp(const string& line, vector<string> &strSet, const char* tok);\r
6876 +int CPL_DLL CPL_STDCALL                Find_Compare_SubStr(string line, string sub);\r
6877 +void CPL_DLL CPL_STDCALL               Strslip(const char* str, const char* arrStr[], const char leftdlm, const char rightdlm);\r
6878 +string CPL_DLL CPL_STDCALL             StrReplace(string& str, const string oldSubStr, const string newStr);\r
6879 +string CPL_DLL CPL_STDCALL             SPrintArray(GDALDataType eDataType, const void *paDataArray, int nValues, const char *pszDelimiter);\r
6880 +string CPL_DLL CPL_STDCALL             StrTrimHead(const string &str);\r
6881 +string CPL_DLL CPL_STDCALL             StrTrimTail(const string &str);\r
6882 +string CPL_DLL CPL_STDCALL             StrTrims(const std::string&, const char*);\r
6883 +string CPL_DLL CPL_STDCALL             StrTrim(const string &str);\r
6884 +\r
6885 +// Date Time Operation Related\r
6886 +int CPL_DLL CPL_STDCALL                CompareDateTime_GreaterThan(string time1, string time2);\r
6887 +int CPL_DLL CPL_STDCALL                ConvertDateTimeToSeconds(string datetime);\r
6888 +string CPL_DLL CPL_STDCALL             GetTimeString(int code);\r
6889 +\r
6890 +// Directory Operation Related\r
6891 +CPLErr CPL_DLL CPL_STDCALL             GetFileNameList(char* dir, std::vector<string> &strList);\r
6892 +string CPL_DLL CPL_STDCALL             MakeTempFile(string dir, string covID, string suffix);\r
6893 +string CPL_DLL CPL_STDCALL             GetUUID();\r
6894 +\r
6895 +// Request Parser Operation\r
6896 +void CPL_DLL CPL_STDCALL               GetSubSetTime(const string& subsetstr, vector<string> &subsetvalue);\r
6897 +string CPL_DLL CPL_STDCALL             GetSubSetLatLon(const string& subsetstr, vector<double> &subsetvalue);\r
6898 +string CPL_DLL CPL_STDCALL             GetSingleValue(const string& subsetstr);\r
6899 +\r
6900 +CPLErr CPL_DLL CPL_STDCALL             GetTRMMBandList(string start, string end, std::vector<int> &bandList);\r
6901 +void CPL_DLL CPL_STDCALL               GetCornerPoints(const GDAL_GCP* &pGCPList, const int &nGCPs, My2DPoint& lowLeft, My2DPoint& upRight);\r
6902 +\r
6903 +CPL_C_END\r
6904 +\r
6905 +#endif /*WCSUTIL_H_*/\r
6906 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/6e/6e49290949c78333bcb94209de0ac91b27fca46c.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/6e/6e49290949c78333bcb94209de0ac91b27fca46c.svn-base
6907 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/6e/6e49290949c78333bcb94209de0ac91b27fca46c.svn-base     1970-01-01 01:00:00.000000000 +0100
6908 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/6e/6e49290949c78333bcb94209de0ac91b27fca46c.svn-base  2014-03-03 15:47:38.040232929 +0100
6909 @@ -0,0 +1,209 @@
6910 +// -*- mode: c++; c-basic-offset:4 -*-
6911 +
6912 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
6913 +// Access Protocol.
6914 +
6915 +// Copyright (c) 2002,2003 OPeNDAP, Inc.
6916 +// Author: James Gallagher <jgallagher@opendap.org>
6917 +//
6918 +// This library is free software; you can redistribute it and/or
6919 +// modify it under the terms of the GNU Lesser General Public
6920 +// License as published by the Free Software Foundation; either
6921 +// version 2.1 of the License, or (at your option) any later version.
6922 +//
6923 +// This library is distributed in the hope that it will be useful,
6924 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
6925 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
6926 +// Lesser General Public License for more details.
6927 +//
6928 +// You should have received a copy of the GNU Lesser General Public
6929 +// License along with this library; if not, write to the Free Software
6930 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
6931 +//
6932 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
6933 +
6934 +// (c) COPYRIGHT URI/MIT 1999
6935 +// Please read the full copyright statement in the file COPYRIGHT_URI.
6936 +//
6937 +// Authors:
6938 +//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
6939 +
6940 +
6941 +// These functions are used by the CE evaluator
6942 +//
6943 +// 1/15/99 jhrg
6944 +
6945 +#include "config.h"
6946 +
6947 +#include <limits.h>
6948 +
6949 +#if 0
6950 +#include <cstdlib>      // used by strtod()
6951 +#include <cerrno>
6952 +#include <cmath>
6953 +#endif
6954 +#include <iostream>
6955 +#if 0
6956 +#include <vector>
6957 +#include <algorithm>
6958 +#endif
6959 +
6960 +// #include <gdal.h>
6961 +// #include <gdal_priv.h>
6962 +
6963 +#define DODS_DEBUG
6964 +
6965 +#include "BaseType.h"
6966 +
6967 +#include "Str.h"
6968 +#include "Array.h"
6969 +#include "Grid.h"
6970 +
6971 +#include "Error.h"
6972 +#include "debug.h"
6973 +
6974 +#include "DAP_Dataset.h"
6975 +#include "reproj_functions.h"
6976 +
6977 +//  We wrapped VC++ 6.x strtod() to account for a short coming
6978 +//  in that function in regards to "NaN".  I don't know if this
6979 +//  still applies in more recent versions of that product.
6980 +//  ROM - 12/2007
6981 +#ifdef WIN32
6982 +#include <limits>
6983 +double w32strtod(const char *, char **);
6984 +#endif
6985 +
6986 +using namespace std;
6987 +//using namespace libdap;
6988 +
6989 +namespace libdap {
6990 +
6991 +/**
6992 + * @todo The lat and lon arrays are passed in, but there's an assumption that the
6993 + * source data array and the two lat and lon arrays are the same shape. But the
6994 + * code does not actually test that.
6995 + *
6996 + * @todo Enable multiple bands paired with just the two lat/lon arrays? Not sure
6997 + * if that is a good idea...
6998 + */
6999 +void function_swath2array(int argc, BaseType * argv[], DDS &, BaseType **btpp)
7000 +{
7001 +    DBG(cerr << "Entering function_swath2array..." << endl);
7002 +
7003 +    // Use the same documentation for both swath2array and swath2grid
7004 +    string info = string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
7005 +               + "<function name=\"swath2array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid\">\n"
7006 +            + "</function>\n";
7007 +
7008 +    if (argc == 0) {
7009 +        Str *response = new Str("info");
7010 +        response->set_value(info);
7011 +        *btpp = response;
7012 +        return;
7013 +    }
7014 +
7015 +    // TODO Add optional fourth arg that lets the caller say which datum to use;
7016 +    // default to WGS84
7017 +    if (argc != 3)
7018 +       throw Error("The function swath2array() requires three arguments. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7019 +
7020 +    Array *src = dynamic_cast<Array*>(argv[0]);
7021 +    if (!src)
7022 +       throw Error("The first argument to swath2array() must be a data array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7023 +
7024 +    Array *lat = dynamic_cast<Array*>(argv[1]);
7025 +    if (!lat)
7026 +       throw Error("The second argument to swath2array() must be a latitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7027 +
7028 +    Array *lon = dynamic_cast<Array*>(argv[2]);
7029 +    if (!lon)
7030 +       throw Error("The third argument to swath2array() must be a longitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7031 +
7032 +    // The args passed into the function using argv[] are deleted after the call.
7033 +
7034 +    DAP_Dataset ds(src, lat, lon);
7035 +
7036 +    try {
7037 +        ds.InitialDataset(0);
7038 +
7039 +        *btpp = ds.GetDAPArray();
7040 +    }
7041 +    catch (Error &e) {
7042 +        DBG(cerr << "caught Error: " << e.get_error_message() << endl);
7043 +        throw e;
7044 +    }
7045 +    catch(...) {
7046 +        DBG(cerr << "caught unknown exception" << endl);
7047 +        throw;
7048 +    }
7049 +
7050 +    return;
7051 +}
7052 +
7053 +/**
7054 + * @todo The lat and lon arrays are passed in, but there's an assumption that the
7055 + * source data array and the two lat and lon arrays are the same shape. But the
7056 + * code does not actually test that.
7057 + *
7058 + * @todo Enable multiple bands paired with just the two lat/lon arrays? Not sure
7059 + * if that is a good idea...
7060 + */
7061 +void function_swath2grid(int argc, BaseType * argv[], DDS &, BaseType **btpp)
7062 +{
7063 +    DBG(cerr << "Entering function_swath2grid..." << endl);
7064 +
7065 +    string info = string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
7066 +               + "<function name=\"swath2grid\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid\">\n"
7067 +            + "</function>\n";
7068 +
7069 +    if (argc == 0) {
7070 +        Str *response = new Str("info");
7071 +        response->set_value(info);
7072 +        *btpp = response;
7073 +        return;
7074 +    }
7075 +
7076 +    // TODO Add optional fourth arg that lets the caller say which datum to use;
7077 +    // default to WGS84
7078 +    if (argc != 3)
7079 +       throw Error("The function swath2grid() requires three arguments. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7080 +
7081 +    Array *src = dynamic_cast<Array*>(argv[0]);
7082 +    if (!src)
7083 +       throw Error("The first argument to swath2grid() must be a data array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7084 +
7085 +    Array *lat = dynamic_cast<Array*>(argv[1]);
7086 +    if (!lat)
7087 +       throw Error("The second argument to swath2grid() must be a latitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7088 +
7089 +    Array *lon = dynamic_cast<Array*>(argv[2]);
7090 +    if (!lon)
7091 +       throw Error("The third argument to swath2grid() must be a longitude array. See http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
7092 +
7093 +    // The args passed into the function using argv[] are deleted after the call.
7094 +
7095 +    DAP_Dataset ds(src, lat, lon);
7096 +
7097 +    try {
7098 +        ds.InitialDataset(0);
7099 +
7100 +        *btpp = ds.GetDAPGrid();
7101 +    }
7102 +    catch (Error &e) {
7103 +        DBG(cerr << "caught Error: " << e.get_error_message() << endl);
7104 +        throw e;
7105 +    }
7106 +    catch(...) {
7107 +        DBG(cerr << "caught unknown exception" << endl);
7108 +        throw;
7109 +    }
7110 +
7111 +    return;
7112 +}
7113 +
7114 +
7115 +
7116 +
7117 +
7118 +} // namespace libdap
7119 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/70/709a0a2aa7313d6e4d90f84b63deb2616bfe3284.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/70/709a0a2aa7313d6e4d90f84b63deb2616bfe3284.svn-base
7120 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/70/709a0a2aa7313d6e4d90f84b63deb2616bfe3284.svn-base     1970-01-01 01:00:00.000000000 +0100
7121 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/70/709a0a2aa7313d6e4d90f84b63deb2616bfe3284.svn-base  2014-03-03 15:47:38.036899596 +0100
7122 @@ -0,0 +1,1278 @@
7123 +/******************************************************************************\r
7124 + * $Id: wcsUtil.cpp 2011-07-19 16:24:00Z $\r
7125 + *\r
7126 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)\r
7127 + *                      for Earth Observation: Open Source Reference Implementation\r
7128 + * Purpose:  WCS Utility Function implementation\r
7129 + * Author:   Yuanzheng Shao, yshao3@gmu.edu\r
7130 + *\r
7131 + ******************************************************************************\r
7132 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>\r
7133 + *\r
7134 + * Permission is hereby granted, free of charge, to any person obtaining a\r
7135 + * copy of this software and associated documentation files (the "Software"),\r
7136 + * to deal in the Software without restriction, including without limitation\r
7137 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
7138 + * and/or sell copies of the Software, and to permit persons to whom the\r
7139 + * Software is furnished to do so, subject to the following conditions:\r
7140 + *\r
7141 + * The above copyright notice and this permission notice shall be included\r
7142 + * in all copies or substantial portions of the Software.\r
7143 + *\r
7144 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
7145 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
7146 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
7147 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
7148 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
7149 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
7150 + * DEALINGS IN THE SOFTWARE.\r
7151 + ****************************************************************************/\r
7152 +\r
7153 +#include <unistd.h>\r
7154 +#include <dirent.h>\r
7155 +#include <sys/stat.h>\r
7156 +#include <stdexcept>\r
7157 +#include <uuid/uuid.h>\r
7158 +#include "wcsUtil.h"\r
7159 +//#include "mfhdf.h"\r
7160 +\r
7161 +/************************************************************************/\r
7162 +/*                          GetUUID()                                   */\r
7163 +/************************************************************************/\r
7164 +\r
7165 +/**\r
7166 + * \brief Used to get UUID string.\r
7167 + *\r
7168 + * This method will return a UUID, such as: cd32eb56-412c-11e0-9cce-67750f871b94\r
7169 + *\r
7170 + * @return A generated UUID string.\r
7171 + */\r
7172 +\r
7173 +string CPL_STDCALL GetUUID()\r
7174 +{\r
7175 +       uuid_t uuid;\r
7176 +       uuid_generate(uuid);\r
7177 +       char uuidstr[36];\r
7178 +       uuid_unparse(uuid, uuidstr);\r
7179 +       return uuidstr;\r
7180 +}\r
7181 +\r
7182 +/************************************************************************/\r
7183 +/*                          SPrintArray()                               */\r
7184 +/************************************************************************/\r
7185 +\r
7186 +/**\r
7187 + * \brief Print a string based on coverage realted parameters.\r
7188 + *\r
7189 + * This method will return a UUID, such as: cd32eb56-412c-11e0-9cce-67750f871b94\r
7190 + *\r
7191 + * @return A generated UUID string.\r
7192 + */\r
7193 +\r
7194 +string CPL_STDCALL SPrintArray(GDALDataType eDataType, const void *paDataArray, int nValues, const char *pszDelimiter)\r
7195 +{\r
7196 +       char *pszString, *pszField;\r
7197 +       int i, iFieldSize, iStringSize;\r
7198 +\r
7199 +       iFieldSize = 32 + strlen(pszDelimiter);\r
7200 +       pszField = (char *) CPLMalloc(iFieldSize + 1);\r
7201 +       iStringSize = nValues * iFieldSize + 1;\r
7202 +       pszString = (char *) CPLMalloc(iStringSize);\r
7203 +       memset(pszString, 0, iStringSize);\r
7204 +       for (i = 0; i < nValues; i++)\r
7205 +       {\r
7206 +               switch (eDataType)\r
7207 +               {\r
7208 +               case GDT_Byte:\r
7209 +                       sprintf(pszField, "%d%s", ((GByte *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7210 +                       break;\r
7211 +               case GDT_UInt16:\r
7212 +                       sprintf(pszField, "%u%s", ((GUInt16 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7213 +                       break;\r
7214 +               case GDT_Int16:\r
7215 +               default:\r
7216 +                       sprintf(pszField, "%d%s", ((GInt16 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7217 +                       break;\r
7218 +               case GDT_UInt32:\r
7219 +                       sprintf(pszField, "%u%s", ((GUInt32 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7220 +                       break;\r
7221 +               case GDT_Int32:\r
7222 +                       sprintf(pszField, "%d%s", ((GInt32 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7223 +                       break;\r
7224 +               case GDT_Float32:\r
7225 +                       sprintf(pszField, "%.7g%s", ((float *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7226 +                       break;\r
7227 +               case GDT_Float64:\r
7228 +                       sprintf(pszField, "%.15g%s", ((double *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
7229 +                       break;\r
7230 +               }\r
7231 +               strcat(pszString, pszField);\r
7232 +       }\r
7233 +\r
7234 +       CPLFree(pszField);\r
7235 +\r
7236 +       return string(pszString);\r
7237 +}\r
7238 +\r
7239 +/************************************************************************/\r
7240 +/*                          StrTrimHead()                               */\r
7241 +/************************************************************************/\r
7242 +\r
7243 +/**\r
7244 + * \brief Trim s string's head.\r
7245 + *\r
7246 + * This method will trim a string's head, remove the sapce and line break\r
7247 + * in the head of a string.\r
7248 + *\r
7249 + * @param str The string to be processed.\r
7250 + *\r
7251 + * @return A head-trimmed string.\r
7252 + */\r
7253 +\r
7254 +string CPL_STDCALL StrTrimHead(const string &str)\r
7255 +{\r
7256 +       string::size_type p = 0;\r
7257 +       /* leading space? */\r
7258 +       while ((p < str.size()) && (str[p] == ' ' || str[p] == '\t' || str[p] == 13 || str[p] == 10))\r
7259 +               p++;\r
7260 +       if (p >= str.size())\r
7261 +               return "";\r
7262 +       else\r
7263 +               return str.substr(p);\r
7264 +}\r
7265 +\r
7266 +/************************************************************************/\r
7267 +/*                          StrTrimTail()                               */\r
7268 +/************************************************************************/\r
7269 +\r
7270 +/**\r
7271 + * \brief Trim s string's tail.\r
7272 + *\r
7273 + * This method will trim a string's tail, remove the sapce and line break\r
7274 + * in the tail of a string.\r
7275 + *\r
7276 + * @param str The string to be processed.\r
7277 + *\r
7278 + * @return A tail-trimmed string.\r
7279 + */\r
7280 +\r
7281 +string CPL_STDCALL StrTrimTail(const string &str)\r
7282 +{\r
7283 +       string::size_type p = str.size() - 1;\r
7284 +       while (p >= 0 && (str[p] == ' ' || str[p] == '\t' || str[p] == 13 || str[p] == 10))\r
7285 +               p--;\r
7286 +       if (p < 0)\r
7287 +               return "";\r
7288 +       else\r
7289 +               return str.substr(0, p + 1);\r
7290 +}\r
7291 +\r
7292 +/************************************************************************/\r
7293 +/*                          StrTrim()                                   */\r
7294 +/************************************************************************/\r
7295 +\r
7296 +/**\r
7297 + * \brief Trim s string's head and tail.\r
7298 + *\r
7299 + * This method will trim a string's head and tail, remove the sapce and\r
7300 + * line break in both the head and end of a string.\r
7301 + *\r
7302 + * @param str The string to be processed.\r
7303 + *\r
7304 + * @return A trimmed string.\r
7305 + */\r
7306 +\r
7307 +string CPL_STDCALL StrTrim(const string &str)\r
7308 +{\r
7309 +       string s = StrTrimTail(str);\r
7310 +       return StrTrimHead(s);\r
7311 +}\r
7312 +\r
7313 +/************************************************************************/\r
7314 +/*                          StrTrims()                                  */\r
7315 +/************************************************************************/\r
7316 +\r
7317 +/**\r
7318 + * \brief Trim s string's head and tail based on delimiter string.\r
7319 + *\r
7320 + * This method will trim a string's head and tail based on delimiter\r
7321 + * string, and return the trimmed string.\r
7322 + *\r
7323 + * @param srcStr The string to be processed.\r
7324 + *\r
7325 + * @param tok The delimiter string used to trim the string.\r
7326 + *\r
7327 + * @return A trimmed string.\r
7328 + */\r
7329 +\r
7330 +string CPL_STDCALL StrTrims(const string& srcStr, const char* tok)\r
7331 +{\r
7332 +       if (srcStr.empty())\r
7333 +               return srcStr;\r
7334 +\r
7335 +       string::size_type beginIdx, endIdx;\r
7336 +       beginIdx = srcStr.find_first_not_of(tok);\r
7337 +       endIdx = srcStr.find_last_not_of(tok);\r
7338 +\r
7339 +       if (beginIdx != string::npos && endIdx != string::npos)\r
7340 +               return srcStr.substr(beginIdx, endIdx - beginIdx + 1);\r
7341 +       else\r
7342 +               return "";\r
7343 +}\r
7344 +\r
7345 +/************************************************************************/\r
7346 +/*                          Strslip()                                   */\r
7347 +/************************************************************************/\r
7348 +\r
7349 +/**\r
7350 + * \brief Slice a string and split it into an array.\r
7351 + *\r
7352 + * This method will slice a string based on left and right delimiter, and then\r
7353 + * split the slipped part into an array.\r
7354 + *\r
7355 + * @param str The string to be processed, such as "longitude[15.5,23.5]"\r
7356 + *\r
7357 + * @param arrStr The two dimension array to place the sliced results.\r
7358 + *\r
7359 + * @param leftdlm The left delimiter used to slip the string, such as '['.\r
7360 + *\r
7361 + * @param rightdlm The right delimiter used to slip the string, such as ']'.\r
7362 + */\r
7363 +\r
7364 +void CPL_STDCALL Strslip(const char* str, const char* arrStr[], const char leftdlm, const char rightdlm)\r
7365 +{\r
7366 +       char* pdest1 = 0;\r
7367 +       char* pdest2 = 0;\r
7368 +\r
7369 +       arrStr[0] = str;\r
7370 +       pdest1 = (char*)strchr(str, leftdlm);\r
7371 +       if (!pdest1)\r
7372 +       {\r
7373 +               arrStr[1] = str;\r
7374 +               return;\r
7375 +       }\r
7376 +\r
7377 +       pdest2 = (char*)strrchr(str, rightdlm);\r
7378 +       if (!pdest2)\r
7379 +               return;\r
7380 +\r
7381 +       arrStr[1] = pdest1 + 1;\r
7382 +       *pdest1 = '\0';\r
7383 +       *pdest2 = '\0';\r
7384 +\r
7385 +       return;\r
7386 +}\r
7387 +\r
7388 +/************************************************************************/\r
7389 +/*                          CsvburstComplexCpp()                        */\r
7390 +/************************************************************************/\r
7391 +\r
7392 +/**\r
7393 + * \brief Slice a string based on single or multiple delimiter(s), and\r
7394 + * then store the results to array.\r
7395 + *\r
7396 + * This method will slice a string based on specified delimiter(s), and then\r
7397 + * place the sliced string parts to a array.\r
7398 + *\r
7399 + * @param line The string to be processed.\r
7400 + *\r
7401 + * @param strSet The array to place the sliced results.\r
7402 + *\r
7403 + * @param tok The delimiter string used to slice the string.\r
7404 + *\r
7405 + * @return The size of the sliced parts.\r
7406 + */\r
7407 +\r
7408 +int CPL_STDCALL CsvburstComplexCpp(const string& line, vector<string> &strSet, const char *tok)\r
7409 +{\r
7410 +       if (line.empty() || line == "")\r
7411 +               return 0;\r
7412 +\r
7413 +       strSet.clear();\r
7414 +       string::size_type firstPos, idx;\r
7415 +\r
7416 +       firstPos = idx = 0;\r
7417 +       idx = line.find_first_of(tok, firstPos);\r
7418 +\r
7419 +       while (idx != string::npos)\r
7420 +       {\r
7421 +               string tmpStr = StrTrim(line.substr(firstPos, (idx - firstPos)));\r
7422 +               if (!tmpStr.empty() && tmpStr != "")\r
7423 +                       strSet.push_back(tmpStr);\r
7424 +\r
7425 +               firstPos = idx + 1;\r
7426 +               if (firstPos == string::npos)\r
7427 +                       break;\r
7428 +               idx = line.find_first_of(tok, firstPos);\r
7429 +       }\r
7430 +\r
7431 +       if (firstPos != string::npos)\r
7432 +       {\r
7433 +               strSet.push_back(StrTrim(line.substr(firstPos)));\r
7434 +       }\r
7435 +\r
7436 +       return strSet.size();\r
7437 +}\r
7438 +\r
7439 +/************************************************************************/\r
7440 +/*                          CsvburstCpp()                               */\r
7441 +/************************************************************************/\r
7442 +\r
7443 +/**\r
7444 + * \brief Slice a string based on single delimiter, and then store the results to array.\r
7445 + *\r
7446 + * This method will slice a string based on specified single delimiter, and then\r
7447 + * place the sliced string parts to a array.\r
7448 + *\r
7449 + * @param line The string to be processed, such as "12,34,56".\r
7450 + *\r
7451 + * @param strSet The array to place the sliced results.\r
7452 + *\r
7453 + * @param tok The delimiter character used to slice the string, such as ','.\r
7454 + *\r
7455 + * @return The size of the sliced parts.\r
7456 + */\r
7457 +\r
7458 +int CPL_STDCALL CsvburstCpp(const string& line, vector<string> &strSet, const char tok)\r
7459 +{\r
7460 +       if (line.empty() || line == "")\r
7461 +               return 0;\r
7462 +\r
7463 +       strSet.clear();\r
7464 +       string::size_type firstPos, idx;\r
7465 +       string::size_type panfuPos;\r
7466 +       panfuPos = 0;\r
7467 +       firstPos = idx = 0;\r
7468 +\r
7469 +       idx = line.find_first_of(tok, firstPos);\r
7470 +\r
7471 +       while (idx != string::npos)\r
7472 +       {\r
7473 +               if(line[idx-2] == '\"' || line[idx-2] == '\'')//Add By Yuanzheng Shao\r
7474 +               {\r
7475 +                       firstPos = idx + 1;\r
7476 +                       if (firstPos == string::npos)\r
7477 +                               break;\r
7478 +                       panfuPos = idx-2;\r
7479 +                       idx = line.find_first_of(tok, firstPos);\r
7480 +\r
7481 +                       string tmpStr = StrTrim(line.substr(panfuPos, (idx - panfuPos)));\r
7482 +                       if (!tmpStr.empty() && tmpStr != "")\r
7483 +                               strSet.push_back(tmpStr);\r
7484 +\r
7485 +                       firstPos = idx + 1;\r
7486 +                       idx = line.find_first_of(tok, firstPos);\r
7487 +               }\r
7488 +               else\r
7489 +               {\r
7490 +                       string tmpStr = StrTrim(line.substr(firstPos, (idx - firstPos)));\r
7491 +                       if (!tmpStr.empty() && tmpStr != "")\r
7492 +                               strSet.push_back(tmpStr);\r
7493 +\r
7494 +                       firstPos = idx + 1;\r
7495 +                       if (firstPos == string::npos)\r
7496 +                               break;\r
7497 +                       idx = line.find_first_of(tok, firstPos);\r
7498 +               }\r
7499 +       }\r
7500 +\r
7501 +       if (firstPos != string::npos)\r
7502 +       {\r
7503 +               strSet.push_back(StrTrim(line.substr(firstPos)));\r
7504 +       }\r
7505 +\r
7506 +       return strSet.size();\r
7507 +}\r
7508 +\r
7509 +/************************************************************************/\r
7510 +/*                          Find_Compare_SubStr()                       */\r
7511 +/************************************************************************/\r
7512 +\r
7513 +/**\r
7514 + * \brief Find the substring in a string.\r
7515 + *\r
7516 + * This method will find a substring in a string.\r
7517 + *\r
7518 + * @param line The string to be processed.\r
7519 + *\r
7520 + * @param sub The substring to be compared.\r
7521 + *\r
7522 + * @return TRUE if find the substring, otherwise FALSE.\r
7523 + */\r
7524 +\r
7525 +int CPL_STDCALL Find_Compare_SubStr(string line, string sub)\r
7526 +{\r
7527 +       if (line.empty() || line == "" || sub.empty() || sub == "")\r
7528 +               return 0;\r
7529 +\r
7530 +       for (unsigned int i = 0; i < line.size(); ++i)\r
7531 +       {\r
7532 +               line[i] = (char) toupper((char) line[i]);\r
7533 +       }\r
7534 +       for (unsigned int j = 0; j < sub.size(); ++j)\r
7535 +       {\r
7536 +               sub[j] = (char) toupper((char) sub[j]);\r
7537 +       }\r
7538 +\r
7539 +       if (string::npos == line.find(sub))\r
7540 +               return 0;\r
7541 +       else\r
7542 +               return 1;\r
7543 +}\r
7544 +\r
7545 +/************************************************************************/\r
7546 +/*                          GetFileNameList()                           */\r
7547 +/************************************************************************/\r
7548 +\r
7549 +/**\r
7550 + * \brief Fetch the file name list under the specified directory.\r
7551 + *\r
7552 + * This method will fetch the file name list under the specified directory,\r
7553 + * and store the results to a array.\r
7554 + *\r
7555 + * @param dir The directory name.\r
7556 + *\r
7557 + * @param strList The array used to place the results.\r
7558 + *\r
7559 + * @return CE_None on success or CE_Failure on failure.\r
7560 + */\r
7561 +\r
7562 +CPLErr CPL_STDCALL GetFileNameList(char* dir, vector<string> &strList)\r
7563 +{\r
7564 +       char pwdBuf[256];\r
7565 +       char *pwd=getcwd (pwdBuf, 256);\r
7566 +       DIR *dp;\r
7567 +       struct dirent *entry;\r
7568 +       struct stat statbuf;\r
7569 +       if ((dp = opendir(dir)) == NULL)\r
7570 +       {\r
7571 +               SetWCS_ErrorLocator("getFileNameList()");\r
7572 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Open Director %s", dir);\r
7573 +               return CE_Failure;\r
7574 +       }\r
7575 +\r
7576 +       if (dir[strlen(dir) - 1] == '/')\r
7577 +               dir[strlen(dir) - 1] = '\0';\r
7578 +\r
7579 +       chdir(dir);\r
7580 +\r
7581 +       while ((entry = readdir(dp)) != NULL)\r
7582 +       {\r
7583 +               lstat(entry->d_name, &statbuf);\r
7584 +               if (S_ISDIR(statbuf.st_mode))\r
7585 +               {\r
7586 +                       /* Found a directory, but ignore . and .. */\r
7587 +                       if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)\r
7588 +                               continue;\r
7589 +                       /* Recurse at a new indent level */\r
7590 +                       string subdir = dir;\r
7591 +                       subdir = subdir + "/" + entry->d_name;\r
7592 +                       GetFileNameList((char*)subdir.c_str(), strList);\r
7593 +               }\r
7594 +               else if (S_ISREG(statbuf.st_mode))\r
7595 +               {\r
7596 +                       string fname = getcwd(NULL, 0);\r
7597 +                       fname = fname + "/" + entry->d_name;\r
7598 +                       strList.push_back(fname);\r
7599 +               }\r
7600 +       }\r
7601 +       chdir(pwd);\r
7602 +       closedir(dp);\r
7603 +\r
7604 +       return CE_None;\r
7605 +}\r
7606 +\r
7607 +/************************************************************************/\r
7608 +/*                             Julian2Date()                            */\r
7609 +/************************************************************************/\r
7610 +\r
7611 +/**\r
7612 + * \brief Convert the Julian days to date string.\r
7613 + *\r
7614 + * This method will convert the days of year to its date string (YYYY-MM-DD);\r
7615 + *\r
7616 + * @param year The year of days.\r
7617 + *\r
7618 + * @param days The Julian days.\r
7619 + *\r
7620 + * @return The date string.\r
7621 + */\r
7622 +\r
7623 +string Julian2Date(int year, int days)\r
7624 +{\r
7625 +       bool leapyear = ((year%4==0 && year%100!=0) || year%400==0) ? true : false;\r
7626 +       int month, day;\r
7627 +\r
7628 +       int leapArr[24] = {1, 31, 32, 60, 61, 91, 92, 121, 122, 152, 153, 182, 183, 213, 214, 244,\r
7629 +               245, 274, 275, 305, 306, 335, 336, 366};\r
7630 +       int unLeArr[24] = {1, 31, 32, 59, 60, 90, 91, 120, 121, 151, 152, 181, 182, 212, 213, 243,\r
7631 +               244, 273, 274, 304, 305, 334, 335, 365};\r
7632 +\r
7633 +       if(leapyear) {\r
7634 +               for (int i = 0; i < 24; i += 2) {\r
7635 +                       if(days >= leapArr[i] && days <= leapArr[i+1]) {\r
7636 +                               month = int(i/2) + 1;\r
7637 +                               day = days - leapArr[i] + 1;\r
7638 +                               break;\r
7639 +                       }\r
7640 +               }\r
7641 +       } else {\r
7642 +               for (int i=0; i < 24; i += 2) {\r
7643 +                       if(days >= unLeArr[i] && days <= unLeArr[i+1]) {\r
7644 +                               month = int(i/2) + 1;\r
7645 +                               day = days - unLeArr[i] + 1;\r
7646 +                               break;\r
7647 +                       }\r
7648 +               }\r
7649 +       }\r
7650 +\r
7651 +       string monthStr = month<10 ? "0" + convertToString(month) : convertToString(month);\r
7652 +       string dayStr = day<10 ? "0" + convertToString(day) : convertToString(day);\r
7653 +\r
7654 +       return convertToString(year) + "-" + monthStr + "-" + dayStr;\r
7655 +}\r
7656 +\r
7657 +/************************************************************************/\r
7658 +/*                          GetTRMMBandList()                           */\r
7659 +/************************************************************************/\r
7660 +\r
7661 +/**\r
7662 + * \brief Fetch the day's list for TRMM data based on the range of date/time.\r
7663 + *\r
7664 + * This method will find day's list for TRMM data based on specified date/time\r
7665 + * range, and store the results to a array.\r
7666 + *\r
7667 + * @param start The start date/time.\r
7668 + *\r
7669 + * @param end The end date/time.\r
7670 + *\r
7671 + * @param bandList The array used to place the results.\r
7672 + *\r
7673 + * @return CE_None on success or CE_Failure on failure.\r
7674 + */\r
7675 +\r
7676 +CPLErr CPL_STDCALL GetTRMMBandList(string start, string end, std::vector<int> &bandList)\r
7677 +{\r
7678 +       //calculate 2000-06-01's days, start's days, end's days\r
7679 +       if(EQUAL(start.c_str(), "") && EQUAL(end.c_str(), ""))\r
7680 +               return CE_None;\r
7681 +\r
7682 +       string june1str = start.substr(0, 4) + "-06-01";\r
7683 +       long int june1sec = ConvertDateTimeToSeconds(june1str);\r
7684 +       long int startsec = 0, endsec = 0;\r
7685 +\r
7686 +       if(!EQUAL(start.c_str(), ""))\r
7687 +               startsec = ConvertDateTimeToSeconds(start);\r
7688 +       if(!EQUAL(end.c_str(), ""))\r
7689 +               endsec = ConvertDateTimeToSeconds(end);\r
7690 +\r
7691 +       int sdays = (int)(startsec - june1sec)/(24*3600) + 1;\r
7692 +       int edays = (int)(endsec - june1sec)/(24*3600) + 1;\r
7693 +\r
7694 +       sdays = (sdays < 0) ? 0 : sdays;\r
7695 +       edays = (edays < 0) ? sdays : edays;\r
7696 +\r
7697 +       for(int i = sdays; i <= edays; i++)\r
7698 +               bandList.push_back(i);\r
7699 +\r
7700 +       return CE_None;\r
7701 +}\r
7702 +\r
7703 +\r
7704 +/************************************************************************/\r
7705 +/*                          GetTimeString()                             */\r
7706 +/************************************************************************/\r
7707 +\r
7708 +/**\r
7709 + * \brief Fetch the current system time to a string.\r
7710 + *\r
7711 + * This method will get the current system time, and convert it to a string.\r
7712 + * The return date/time has two formats:\r
7713 + *             1: YYYYMMDDHHMMSS\r
7714 + *             2: YYYY-MM-DDTHH:MM:SSZ\r
7715 + *\r
7716 + * @param code The return string's format.\r
7717 + *\r
7718 + * @return The string corresponding to current system time.\r
7719 + */\r
7720 +\r
7721 +string GetTimeString(int code)\r
7722 +{\r
7723 +       struct tm* ptime;\r
7724 +       time_t now;\r
7725 +       time(&now);\r
7726 +       ptime = localtime(&now);\r
7727 +       int year = ptime->tm_year + 1900;\r
7728 +       int month = ptime->tm_mon + 1;\r
7729 +       int day = ptime->tm_mday;\r
7730 +       int hour = ptime->tm_hour;\r
7731 +       int minute = ptime->tm_min;\r
7732 +       int second = ptime->tm_sec;\r
7733 +       string ye, mo, da, ho, mi, se;\r
7734 +       ye = convertToString(year);\r
7735 +       mo = (month < 10) ? "0" + convertToString(month) : convertToString(month);\r
7736 +       da = (day < 10) ? "0" + convertToString(day) : convertToString(day);\r
7737 +       ho = (hour < 10)        ? "0" + convertToString(hour) : convertToString(hour);\r
7738 +       mi = (minute < 10)      ? "0" + convertToString(minute) : convertToString(minute);\r
7739 +       se = (second < 10)      ? "0" + convertToString(second) : convertToString(second);\r
7740 +\r
7741 +       string timestring;\r
7742 +       if(code == 1)\r
7743 +       {\r
7744 +               string part1 = ye + mo + da;\r
7745 +               string part2 = ho + mi + se;\r
7746 +               timestring = part1.append(part2);\r
7747 +       }\r
7748 +       else if(code == 2)\r
7749 +       {\r
7750 +               string part1 = ye + "-" + mo + "-" + da + "T";\r
7751 +               string part2 = ho + ":" + mi + ":" + se + "Z";\r
7752 +               timestring = part1.append(part2);\r
7753 +       }\r
7754 +\r
7755 +       return timestring;\r
7756 +}\r
7757 +\r
7758 +/************************************************************************/\r
7759 +/*                          MakeTempFile()                              */\r
7760 +/************************************************************************/\r
7761 +\r
7762 +/**\r
7763 + * \brief Generate a temporary file path.\r
7764 + *\r
7765 + * This method will generate a path for temporary file or output file,\r
7766 + * which is based on coverage identifier.\r
7767 + *\r
7768 + * @param dir The directory of the temporary file.\r
7769 + *\r
7770 + * @param covID The coverage identifier.\r
7771 + *\r
7772 + * @param suffix The suffix of the file format.\r
7773 + *\r
7774 + * @return The full path of the temporary file.\r
7775 + */\r
7776 +\r
7777 +string MakeTempFile(string dir, string covID, string suffix)\r
7778 +{\r
7779 +       string sOutFileName;\r
7780 +\r
7781 +       if (!dir.empty() && dir != "")\r
7782 +       {\r
7783 +               if (dir[dir.length() - 1] != '/')\r
7784 +               {\r
7785 +                       dir += "/";\r
7786 +               }\r
7787 +       }\r
7788 +       if (!suffix.empty() && suffix != "")\r
7789 +       {\r
7790 +               if (suffix[0] != '.')\r
7791 +                       suffix = "." + suffix;\r
7792 +       }\r
7793 +\r
7794 +       if(covID == "")\r
7795 +       {\r
7796 +               sOutFileName = dir + GetUUID() + suffix;\r
7797 +       }\r
7798 +       else if (EQUALN(covID.c_str(),"HDF4_EOS:EOS_SWATH:",19) ||\r
7799 +               EQUALN(covID.c_str(),"HDF4_EOS:EOS_GRID:",18) ||\r
7800 +               EQUALN(covID.c_str(),"HDF5:",5))\r
7801 +       {\r
7802 +               vector<string> strSet;\r
7803 +               int n = CsvburstCpp(covID, strSet, ':');\r
7804 +               if(n == 5){//Terra&Aqua\r
7805 +                       string srcFilePath = StrTrims(strSet[2], "\'\"");\r
7806 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
7807 +                       string datasetname = StrTrims(strSet[4], "\'\"");\r
7808 +                       datasetname = StrReplace(datasetname, " ", "_");\r
7809 +                       sOutFileName = dir + srcFileName + "." + datasetname + "." + GetTimeString(1) + suffix;\r
7810 +               }else if(n == 3) {//Aura\r
7811 +                       string srcFilePath = StrTrims(strSet[1], "\'\"");\r
7812 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
7813 +                       string datasetname = StrTrims(strSet[2], "\'\"");\r
7814 +                       datasetname = StrReplace(datasetname, "//", "");\r
7815 +                       datasetname = StrReplace(datasetname, "/", "_");\r
7816 +                       datasetname = StrReplace(datasetname, " ", "");\r
7817 +                       sOutFileName = dir + srcFileName + "." + datasetname + "." + GetTimeString(1) + suffix;\r
7818 +               }else\r
7819 +                       sOutFileName = dir + GetUUID() + suffix;\r
7820 +       }else if(EQUALN( covID.c_str(), "GOES:NetCDF:",12))\r
7821 +       {\r
7822 +               vector<string> strSet;\r
7823 +               int n = CsvburstCpp(covID, strSet, ':');\r
7824 +               if(n == 4){\r
7825 +                       string srcFilePath = StrTrims(strSet[2], " \'\"");\r
7826 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
7827 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
7828 +               }else\r
7829 +                       sOutFileName = dir + GetUUID() + suffix;\r
7830 +       }\r
7831 +       else if(EQUALN(covID.c_str(),"GEOTIFF:",8))\r
7832 +       {\r
7833 +               vector<string> strSet;\r
7834 +               int n = CsvburstCpp(covID, strSet, ':');\r
7835 +               if(n == 3){\r
7836 +                       string srcFilePath = StrTrims(strSet[1], " \'\"");\r
7837 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
7838 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
7839 +               }else\r
7840 +                       sOutFileName = dir + GetUUID() + suffix;\r
7841 +       }\r
7842 +       else if(EQUALN(covID.c_str(),"TRMM:",5))\r
7843 +       {\r
7844 +               vector<string> strSet;\r
7845 +               int n = CsvburstCpp(covID, strSet, ':');\r
7846 +               if(n == 3){\r
7847 +                       string srcFilePath = StrTrims(strSet[1], " \'\"");\r
7848 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
7849 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
7850 +               }else\r
7851 +                       sOutFileName = dir + GetUUID() + suffix;\r
7852 +       }\r
7853 +       else\r
7854 +               sOutFileName = dir + GetUUID() + suffix;\r
7855 +\r
7856 +       return sOutFileName;\r
7857 +}\r
7858 +\r
7859 +/************************************************************************/\r
7860 +/*                          StringList()                                */\r
7861 +/************************************************************************/\r
7862 +\r
7863 +/**\r
7864 + * \brief Constructor for StringList.\r
7865 + */\r
7866 +\r
7867 +StringList::StringList(const string& sstrings, const char delimiter)\r
7868 +{\r
7869 +       string str = sstrings + delimiter;\r
7870 +       string::size_type np, op = 0;\r
7871 +       while ((op < str.size())\r
7872 +                       && ((np = str.find(delimiter, op)) != string::npos))\r
7873 +       {\r
7874 +               add(str.substr(op, np - op));\r
7875 +               op = ++np;\r
7876 +       }\r
7877 +}\r
7878 +\r
7879 +// -----------------------------------------------------------------------\r
7880 +// string list constructor\r
7881 +// -----------------------------------------------------------------------\r
7882 +StringList::StringList(const string& sstrings, const string& delimiters)\r
7883 +{\r
7884 +       string str = sstrings + delimiters;\r
7885 +       string::size_type np, op = 0;\r
7886 +       while ((op < str.size()) && ((np = str.find(delimiters, op))\r
7887 +                       != string::npos))\r
7888 +       {\r
7889 +               add(str.substr(op, np - op));\r
7890 +               op = np + delimiters.length();\r
7891 +       }\r
7892 +}\r
7893 +\r
7894 +// -----------------------------------------------------------------------\r
7895 +// string list -- append\r
7896 +// -----------------------------------------------------------------------\r
7897 +void StringList::append(StringList & s)\r
7898 +{\r
7899 +       for (int i = 0; i < s.size(); i++)\r
7900 +               add(s[i]);\r
7901 +}\r
7902 +\r
7903 +// -----------------------------------------------------------------------\r
7904 +// string list -- append with delimiter\r
7905 +// -----------------------------------------------------------------------\r
7906 +void StringList::append(const string sstrings, const char delimiter)\r
7907 +{\r
7908 +       StringList n(sstrings, delimiter);\r
7909 +       append(n);\r
7910 +}\r
7911 +\r
7912 +// -----------------------------------------------------------------------\r
7913 +// string list -- append with delimiters\r
7914 +// -----------------------------------------------------------------------\r
7915 +void StringList::append(const string sstrings, const string& delimiters)\r
7916 +{\r
7917 +       StringList n(sstrings, delimiters);\r
7918 +       append(n);\r
7919 +}\r
7920 +\r
7921 +// -----------------------------------------------------------------------\r
7922 +// string list -- return the index for query string\r
7923 +// -----------------------------------------------------------------------\r
7924 +int StringList::indexof(string qstr)\r
7925 +{\r
7926 +       for (int i = 0; i < size(); i++)\r
7927 +       {\r
7928 +               if (strings[i] == qstr)\r
7929 +                       return i;\r
7930 +       }\r
7931 +       return -1;\r
7932 +}\r
7933 +\r
7934 +/************************************************************************/\r
7935 +/*                          KVP()                                       */\r
7936 +/************************************************************************/\r
7937 +\r
7938 +/**\r
7939 + * \brief Constructor for KVP.\r
7940 + *\r
7941 + * @param namevaluepair The key-value pair.\r
7942 + */\r
7943 +\r
7944 +KVP::KVP(string namevaluepair)\r
7945 +{\r
7946 +       StringList ss(namevaluepair, '=');\r
7947 +       if (ss.size() == 2)\r
7948 +       {\r
7949 +               name = StrTrim(ss[0]);\r
7950 +               value = StrTrim(ss[1]);\r
7951 +       }\r
7952 +       else\r
7953 +       {\r
7954 +               name = namevaluepair;\r
7955 +               value = "";\r
7956 +       }\r
7957 +}\r
7958 +\r
7959 +/************************************************************************/\r
7960 +/*                          CFGReader()                                 */\r
7961 +/************************************************************************/\r
7962 +\r
7963 +/**\r
7964 + * \brief Constructor for CFGReader.\r
7965 + *\r
7966 + * This method is used to load the configuration file for WCS. Each configuration\r
7967 + * item looks like a key-value pair, CFGReader() will read the file to memory and\r
7968 + * store the parameters to a KVP array.\r
7969 + *\r
7970 + * @param configfilename The full path of the configuration file.\r
7971 + */\r
7972 +\r
7973 +CFGReader::CFGReader(const string &configfilename)\r
7974 +{\r
7975 +       ifstream cfgfile(configfilename.c_str());\r
7976 +       if (!cfgfile)\r
7977 +       {\r
7978 +               SetWCS_ErrorLocator("CFGReader");\r
7979 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open configure file.");\r
7980 +               throw runtime_error("");\r
7981 +       }\r
7982 +\r
7983 +       char line[MAX_LINE_LEN];\r
7984 +       while (!cfgfile.eof())\r
7985 +       {\r
7986 +               cfgfile.getline(line, MAX_LINE_LEN - 1, '\n');\r
7987 +               if (!cfgfile.fail())\r
7988 +               {\r
7989 +                       if (line[0] != '#')\r
7990 +                       {\r
7991 +                               KVP kvp(line);\r
7992 +                               kvps.push_back(kvp);\r
7993 +                       }\r
7994 +               }\r
7995 +       }\r
7996 +\r
7997 +       cfgfile.close();\r
7998 +}\r
7999 +\r
8000 +/************************************************************************/\r
8001 +/*                          getValue()                                  */\r
8002 +/************************************************************************/\r
8003 +\r
8004 +/**\r
8005 + * \brief Fetch a configured item's value.\r
8006 + *\r
8007 + * This method is used to fetch a items value from a configuration file.\r
8008 + *\r
8009 + * @param keyname The item's name.\r
8010 + *\r
8011 + * @return The result string.\r
8012 + */\r
8013 +\r
8014 +string CFGReader::getValue(const string &keyname)\r
8015 +{\r
8016 +       for (int i = 0; i < size(); i++)\r
8017 +       {\r
8018 +               if (EQUAL(kvps[i].name.c_str(), keyname.c_str()))\r
8019 +                       return kvps[i].value;\r
8020 +       }\r
8021 +\r
8022 +       return "";\r
8023 +}\r
8024 +\r
8025 +/************************************************************************/\r
8026 +/*                          getValue()                                  */\r
8027 +/************************************************************************/\r
8028 +\r
8029 +/**\r
8030 + * \brief Fetch a configured item's value, with default value.\r
8031 + *\r
8032 + * This method is used to fetch a items value from a configuration file,\r
8033 + * if not found, use the default value.\r
8034 + *\r
8035 + * @param keyname The item's name.\r
8036 + *\r
8037 + * @param defaultvalue The item's default value.\r
8038 + *\r
8039 + * @return The result string.\r
8040 + */\r
8041 +\r
8042 +string CFGReader::getValue(const string &keyname, const string &defaultvalue)\r
8043 +{\r
8044 +       string ret = getValue(keyname);\r
8045 +       if (ret.empty() || ret == "")\r
8046 +               return defaultvalue;\r
8047 +       else\r
8048 +               return ret;\r
8049 +}\r
8050 +\r
8051 +/************************************************************************/\r
8052 +/*                          Run()                                       */\r
8053 +/************************************************************************/\r
8054 +\r
8055 +/**\r
8056 + * \brief The entry point for CGI program.\r
8057 + *\r
8058 + * This method is used to fetch CGI parameters. Supports both HTTP GET\r
8059 + * and POST method. POST content could be KVPs and XML string, and GET\r
8060 + * content must be KVPs.\r
8061 + *\r
8062 + * @return CE_None on success or CE_Failure on failure.\r
8063 + */\r
8064 +\r
8065 +CPLErr WCSCGI::Run()\r
8066 +{\r
8067 +       /* get request parameters*/\r
8068 +       char *gm = getenv("REQUEST_METHOD");\r
8069 +       if (NULL == gm)\r
8070 +       {\r
8071 +               SetWCS_ErrorLocator("WCSCGI::Run()");\r
8072 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Get \"REQUEST_METHOD\" Environment variable.");\r
8073 +               return CE_Failure;\r
8074 +       }\r
8075 +\r
8076 +       if (EQUAL(gm, "POST"))\r
8077 +               me_CGIMethod = HTTP_XML_POST;\r
8078 +       else if (EQUAL(gm, "GET"))\r
8079 +               me_CGIMethod = HTTP_GET;\r
8080 +       else\r
8081 +               me_CGIMethod = UN_KNOWN;\r
8082 +\r
8083 +       switch (me_CGIMethod)\r
8084 +       {\r
8085 +               case HTTP_XML_POST:\r
8086 +               {\r
8087 +                       char* aString = getenv("CONTENT_LENGTH");\r
8088 +                       if (NULL == aString || aString[0] == '\0')\r
8089 +                       {\r
8090 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Get \"CONTENT_LENGTH\" Environment variable.");\r
8091 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
8092 +                               return CE_Failure;\r
8093 +                       }\r
8094 +\r
8095 +                       unsigned int cLength = atoi(aString);\r
8096 +\r
8097 +                       string cString;\r
8098 +                       cString.resize(cLength + 1);\r
8099 +\r
8100 +                       if (cLength != fread((char*) cString.c_str(), 1, cLength, stdin))\r
8101 +                       {\r
8102 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
8103 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Read POST Data Stream from Internet.");\r
8104 +                               return CE_Failure;\r
8105 +                       }\r
8106 +\r
8107 +                       cString = StrReplace(cString, "&amps;", "%26");\r
8108 +                       cString = StrReplace(cString, "&amp;", "%26");\r
8109 +\r
8110 +                       string tmpStr = CPLUnescapeString(cString.c_str(), NULL, CPLES_URL);\r
8111 +                       ms_CGIContent = CPLUnescapeString((char*) tmpStr.c_str(), NULL, CPLES_XML);\r
8112 +\r
8113 +                       string::size_type beginIdx, endIdx;\r
8114 +\r
8115 +                       beginIdx = ms_CGIContent.find("<?");\r
8116 +                       endIdx = ms_CGIContent.rfind(">");\r
8117 +                       //The post contents could be KVPs\r
8118 +                       if (beginIdx != string::npos && endIdx != string::npos)\r
8119 +                               ms_CGIContent = ms_CGIContent.substr(beginIdx, endIdx - beginIdx + 1);\r
8120 +               }\r
8121 +                       break;\r
8122 +               case HTTP_GET:\r
8123 +               {\r
8124 +                       string tmpStr = getenv("QUERY_STRING");\r
8125 +                       tmpStr = StrReplace(tmpStr, "&amps;", "%26");\r
8126 +                       tmpStr = StrReplace(tmpStr, "&amp;", "%26");\r
8127 +                       if (tmpStr.empty() || tmpStr == "")\r
8128 +                       {\r
8129 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
8130 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "No \"QUERY_STRING\" Content.");\r
8131 +                               return CE_Failure;\r
8132 +                       }\r
8133 +\r
8134 +                       ms_CGIContent = CPLUnescapeString((char*) tmpStr.c_str(), NULL, CPLES_URL);\r
8135 +               }\r
8136 +                       break;\r
8137 +               default:\r
8138 +               {\r
8139 +                       SetWCS_ErrorLocator("WCSCGI::Run()");\r
8140 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Unkown \"REQUEST_METHOD\".");\r
8141 +                       return CE_Failure;\r
8142 +               }\r
8143 +       }\r
8144 +\r
8145 +       return CE_None;\r
8146 +}\r
8147 +\r
8148 +// -----------------------------------------------------------------------\r
8149 +// KVPsReader constructor\r
8150 +// -----------------------------------------------------------------------\r
8151 +KVPsReader::KVPsReader(const string& urlStr, const char &tok)\r
8152 +{\r
8153 +       StringList strLit(urlStr, tok);\r
8154 +\r
8155 +       for (int i = 0; i < strLit.size(); ++i)\r
8156 +       {\r
8157 +               KVP kvp(StrTrim(strLit[i]));\r
8158 +               m_kvps.push_back(kvp);\r
8159 +       }\r
8160 +}\r
8161 +\r
8162 +// -----------------------------------------------------------------------\r
8163 +// KVPsReader get value function\r
8164 +// -----------------------------------------------------------------------\r
8165 +string KVPsReader::getValue(const string &keyname)\r
8166 +{\r
8167 +       for (unsigned int i = 0; i < m_kvps.size(); i++)\r
8168 +       {\r
8169 +               if (EQUAL(m_kvps[i].name.c_str() , keyname.c_str()))\r
8170 +                       return m_kvps[i].value;\r
8171 +       }\r
8172 +       return "";\r
8173 +}\r
8174 +\r
8175 +\r
8176 +vector<string> KVPsReader::getValues(const string &keyname)\r
8177 +{\r
8178 +       vector<string> valuesList;\r
8179 +       for (unsigned int i = 0; i < m_kvps.size(); i++)\r
8180 +       {\r
8181 +               if (EQUAL(m_kvps[i].name.c_str() , keyname.c_str()))\r
8182 +                       valuesList.push_back(m_kvps[i].value);\r
8183 +       }\r
8184 +       return valuesList;\r
8185 +}\r
8186 +\r
8187 +// -----------------------------------------------------------------------\r
8188 +// KVPsReader get value function, with default value\r
8189 +// -----------------------------------------------------------------------\r
8190 +string KVPsReader::getValue(const string &keyname, const string &defaultvalue)\r
8191 +{\r
8192 +       string ret = getValue(keyname);\r
8193 +       if (ret.empty() || ret == "")\r
8194 +               return defaultvalue;\r
8195 +       else\r
8196 +               return ret;\r
8197 +}\r
8198 +\r
8199 +/************************************************************************/\r
8200 +/*                          StrReplace()                                */\r
8201 +/************************************************************************/\r
8202 +\r
8203 +/**\r
8204 + * \brief Replace a string.\r
8205 + *\r
8206 + * This method is used to replace a string with specified substring.\r
8207 + *\r
8208 + * @param str The string needs to be processed.\r
8209 + *\r
8210 + * @param oldSubStr The substring needs to be replaced.\r
8211 + *\r
8212 + * @param newStr The string will replace the oldSubStr.\r
8213 + *\r
8214 + * @return The processed string.\r
8215 + */\r
8216 +\r
8217 +string CPL_STDCALL StrReplace(string& str, const string oldSubStr, const string newStr)\r
8218 +{\r
8219 +       while(true)\r
8220 +       {\r
8221 +               string::size_type pos(0);\r
8222 +               if( ( pos = str.find(oldSubStr) ) != string::npos )\r
8223 +               {\r
8224 +                       str.replace( pos, oldSubStr.length(), newStr );\r
8225 +               }else {\r
8226 +                       break;\r
8227 +               }\r
8228 +       }\r
8229 +       return str;\r
8230 +}\r
8231 +\r
8232 +/************************************************************************/\r
8233 +/*                          GetSingleValue()                            */\r
8234 +/************************************************************************/\r
8235 +\r
8236 +/**\r
8237 + * \brief Get a single value from a special KVP part.\r
8238 + *\r
8239 + * This method is used to get value from a special KVP part.\r
8240 + *\r
8241 + * @param subsetstr The string needs to be processed, such as "subset=Long(11)".\r
8242 + *\r
8243 + * @return The processed string, such as "11".\r
8244 + */\r
8245 +\r
8246 +string CPL_STDCALL GetSingleValue(const string& subsetstr)\r
8247 +{\r
8248 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
8249 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
8250 +\r
8251 +       return StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 -1));\r
8252 +}\r
8253 +\r
8254 +/************************************************************************/\r
8255 +/*                          GetSubSetLatLon()                           */\r
8256 +/************************************************************************/\r
8257 +\r
8258 +/**\r
8259 + * \brief Get a subset spatial extent in WCS 2.0 request.\r
8260 + *\r
8261 + * This method is used to get values of spatial extent and place the values\r
8262 + * in an array, and return the CRS code for the coordinates of the extent.\r
8263 + *\r
8264 + * @param subsetstr The string needs to be processed,\r
8265 + * such as "subset=Lat,http://www.opengis.net/def/crs/EPSG/0/4326(32,47)".\r
8266 + *\r
8267 + * @param subsetvalue The array to place the spatial extent values.\r
8268 + *\r
8269 + * @return The processed string, such as "EPSG:4326".\r
8270 + */\r
8271 +\r
8272 +string CPL_STDCALL GetSubSetLatLon(const string& subsetstr, vector<double> &subsetvalue)\r
8273 +{\r
8274 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
8275 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
8276 +\r
8277 +       string value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 -1));\r
8278 +       vector<string> tmpV;\r
8279 +       CsvburstCpp(value, tmpV, ',');\r
8280 +\r
8281 +       for(unsigned int i = 0; i < tmpV.size(); i++)\r
8282 +       {\r
8283 +               double curD;\r
8284 +               convertFromString(curD, tmpV.at(i));\r
8285 +               subsetvalue.push_back(curD);\r
8286 +       }\r
8287 +\r
8288 +       string subsetProj;\r
8289 +       idx1 = subsetstr.find(',');\r
8290 +       idx2 = subsetstr.find('(');\r
8291 +       if(idx1 > idx2) \r
8292 +       {\r
8293 +               subsetProj = "EPSG:4326";\r
8294 +       }\r
8295 +       else\r
8296 +       {\r
8297 +               value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 - 1));\r
8298 +               if(value.find("http") != string::npos)\r
8299 +               {\r
8300 +                       string::size_type idx3 = value.find_last_of('/');\r
8301 +                       subsetProj = "EPSG:" + value.substr(idx3 + 1);\r
8302 +               }\r
8303 +               else\r
8304 +               {\r
8305 +                       subsetProj = value;\r
8306 +               }\r
8307 +\r
8308 +       }\r
8309 +\r
8310 +       return subsetProj;\r
8311 +}\r
8312 +\r
8313 +//subset=phenomenonTime("2006-08-01","2006-08-22T09:22:00Z")&\r
8314 +//subset=phenomenonTime("2006-08-01")&\r
8315 +void CPL_STDCALL GetSubSetTime(const string& subsetstr, vector<string> &subsetvalue)\r
8316 +{\r
8317 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
8318 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
8319 +       string value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 - 1));\r
8320 +       string valueN = StrReplace(value, "\"", "");\r
8321 +       CsvburstCpp(valueN, subsetvalue, ',');\r
8322 +}\r
8323 +\r
8324 +//time type 1: 2006-08-22T09:22:00Z\r
8325 +//time type 1: 2006-08-01\r
8326 +int CPL_STDCALL CompareDateTime_GreaterThan(string time1, string time2)\r
8327 +{\r
8328 +       time_t retval1 = 0;\r
8329 +       time_t retval2 = 0;\r
8330 +\r
8331 +       struct tm storage1 = {0,0,0,0,0,0,0,0,0};\r
8332 +       struct tm storage2 = {0,0,0,0,0,0,0,0,0};\r
8333 +\r
8334 +       char *p1 = NULL;\r
8335 +       char *p2 = NULL;\r
8336 +\r
8337 +       if(time1.find("T") != string::npos && time1.find("Z") != string::npos)\r
8338 +               p1 =    (char *)strptime(time1.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage1);\r
8339 +       else\r
8340 +               p1 = (char *)strptime(time1.c_str(), "%Y-%m-%d", &storage1);\r
8341 +\r
8342 +       if(time2.find("T") != string::npos && time2.find("Z") != string::npos)\r
8343 +               p2 =    (char *)strptime(time2.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage2);\r
8344 +       else\r
8345 +               p2 = (char *)strptime(time2.c_str(), "%Y-%m-%d", &storage2);\r
8346 +\r
8347 +       retval1 = mktime(&storage1);\r
8348 +       retval2 = mktime(&storage2);\r
8349 +\r
8350 +       if(retval1 == retval2)\r
8351 +               return 0;\r
8352 +       else if(retval1 > retval2)\r
8353 +               return 1;\r
8354 +       else\r
8355 +               return -1;\r
8356 +\r
8357 +}\r
8358 +\r
8359 +int CPL_STDCALL        ConvertDateTimeToSeconds(string datetime)\r
8360 +{\r
8361 +       time_t retval1 = 0;\r
8362 +       struct tm storage1 = {0,0,0,0,0,0,0,0,0};\r
8363 +       char *p1 = NULL;\r
8364 +\r
8365 +       if(datetime.find("T") != string::npos && datetime.find("Z") != string::npos)\r
8366 +               p1 =    (char *)strptime(datetime.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage1);\r
8367 +       else\r
8368 +               p1 = (char *)strptime(datetime.c_str(), "%Y-%m-%d", &storage1);\r
8369 +\r
8370 +       retval1 = mktime(&storage1);\r
8371 +\r
8372 +       return retval1;\r
8373 +}\r
8374 +\r
8375 +// -----------------------------------------------------------------------\r
8376 +// Find lower-left and upper-right corner point coordinate\r
8377 +// -----------------------------------------------------------------------\r
8378 +void CPL_STDCALL GetCornerPoints(const GDAL_GCP* &pGCPList, const int &nGCPs, My2DPoint& lowLeft, My2DPoint& upRight)\r
8379 +{\r
8380 +        double xLeft = (numeric_limits<double>::max)();\r
8381 +        double xRight = -xLeft;\r
8382 +        double yLower = (numeric_limits<double>::max)();\r
8383 +        double yUpper = -yLower;\r
8384 +\r
8385 +        for (int j = 0; j < nGCPs; j++)\r
8386 +        {\r
8387 +                yUpper = MAX(yUpper,pGCPList[j].dfGCPY);\r
8388 +                yLower = MIN(yLower,pGCPList[j].dfGCPY);\r
8389 +                if(pGCPList[j].dfGCPX != -999)//test MOD021KM.A2000065.1900.005.2008235220315.hdf, error GCP X value (-999)\r
8390 +                        xLeft = MIN(xLeft,pGCPList[j].dfGCPX);\r
8391 +                xRight = MAX(xRight,pGCPList[j].dfGCPX);\r
8392 +        }\r
8393 +\r
8394 +        lowLeft.mi_X = xLeft;\r
8395 +        lowLeft.mi_Y = yLower;\r
8396 +        upRight.mi_X = xRight;\r
8397 +        upRight.mi_Y = yUpper;\r
8398 +\r
8399 +        return;\r
8400 +}\r
8401 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/82/82ef297cba5eb92b8c25159c74318bee457c1f00.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/82/82ef297cba5eb92b8c25159c74318bee457c1f00.svn-base
8402 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/82/82ef297cba5eb92b8c25159c74318bee457c1f00.svn-base     1970-01-01 01:00:00.000000000 +0100
8403 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/82/82ef297cba5eb92b8c25159c74318bee457c1f00.svn-base  2014-03-03 15:47:37.983566265 +0100
8404 @@ -0,0 +1,106 @@
8405 +
8406 +# Build libswath2grid, part of libdap.
8407 +
8408 +AUTOMAKE_OPTIONS = foreign
8409
8410 +AM_CPPFLAGS = -I$(top_srcdir)/GNU -I$(top_srcdir) -I$(top_srcdir)/tests  -I$(top_srcdir)/dispatch $(XML2_CFLAGS) $(CURL_CFLAGS) 
8411 +AM_LDADD = 
8412 +
8413 +if CPPUNIT
8414 +AM_CPPFLAGS += $(CPPUNIT_CFLAGS)
8415 +AM_LDADD += $(CPPUNIT_LIBS)
8416 +endif
8417 +
8418 +# These are not used by automake but are often useful for certain types of
8419 +# debugging. The best way to use these is to run configure as:
8420 +#     export CXXFLAGS='...'; ./configure --disable-shared
8421 +# the --disable-shared is not required, but it seems to help with debuggers.
8422 +CXXFLAGS_DEBUG = -g3 -O0  -Wall -W -Wcast-align -Werror
8423 +TEST_COV_FLAGS = -ftest-coverage -fprofile-arcs
8424 +
8425 +# SUBDIRS = 
8426 +# DIST_SUBDIRS = 
8427 +
8428 +# This determines what gets built by make check
8429 +check_PROGRAMS = $(UNIT_TESTS)
8430 +
8431 +# This determines what gets run by 'make check.'
8432 +# Now (12/20/12) this fails; don't run until it works.
8433 +# TESTS = $(UNIT_TESTS)
8434 +
8435 +
8436 +noinst_LTLIBRARIES = libswath2grid.la
8437 +
8438 +libswath2grid_la_SOURCES = $(SRCS) $(HDRS)
8439 +libswath2grid_la_CPPFLAGS = $(GDAL_CFLAGS) $(XML2_CFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) -I$(top_srcdir)/dispatch
8440 +libswath2grid_la_LDFLAGS = 
8441 +libswath2grid_la_LIBADD = $(GDAL_LDFLAGS) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS)
8442 +
8443 +SRCS = AbstractDataset.cpp wcs_error.cpp    \
8444 +BoundingBox.cpp wcsUtil.cpp DAP_Dataset.cpp  reproj_functions.cc
8445 +
8446 +# NC_GOES_Dataset.cpp NC_GOES_Dataset.h
8447 +
8448 +HDRS = AbstractDataset.h wcs_error.h    \
8449 +BoundingBox.h wcsUtil.h DAP_Dataset.h reproj_functions.h
8450 +
8451 +if CPPUNIT
8452 +UNIT_TESTS = s2gTest
8453 +       
8454 +else
8455 +UNIT_TESTS =
8456 +
8457 +check-local:
8458 +       @echo ""
8459 +       @echo "**********************************************************"
8460 +       @echo "You must have cppunit 1.12.x or greater installed to run *"
8461 +       @echo "check target in unit-tests directory                     *"
8462 +       @echo "**********************************************************"
8463 +       @echo ""
8464 +endif
8465 +
8466 +s2gTest_SOURCES = s2gTest.cc
8467 +s2gTest_CPPFLAGS = $(AM_CPPFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) $(GDAL_CFLAGS)
8468 +s2gTest_LDADD = -ltest-types libswath2grid.la $(AM_LDADD)  $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS) $(GDAL_LDFLAGS) 
8469 +
8470 +if  LIBDAP
8471 +check-dap:
8472 +       @echo ""
8473 +       @echo "**********************************************************"
8474 +       @echo "USING DAP "
8475 +       @echo "DAP_CLIENT_CFLAGS:  " $(DAP_CLIENT_CFLAGS)
8476 +       @echo "DAP_SERVER_CFLAGS:  " $(DAP_SERVER_CFLAGS)
8477 +       @echo "DAP_CLIENT_LIBS:    " $(DAP_CLIENT_LIBS)
8478 +       @echo "DAP_SERVER_LIBS:    " $(DAP_SERVER_LIBS)
8479 +       @echo "**********************************************************"
8480 +       @echo ""
8481 +else
8482 +check-dap:
8483 +       @echo ""
8484 +       @echo "**********************************************************"
8485 +       @echo " Unable to locate DAP libraries!"
8486 +       @echo "**********************************************************"
8487 +       @echo ""
8488 +endif
8489 +
8490 +
8491 +if  GDAL_FOUND
8492 +check-gdal:
8493 +       @echo ""
8494 +       @echo "**********************************************************"
8495 +       @echo "Using gdal. "
8496 +       @echo "GDAL_CFLAGS:  " $(GDAL_CFLAGS)
8497 +       @echo "GDAL_LDFLAGS: " $(GDAL_LDFLAGS)
8498 +       @echo "**********************************************************"
8499 +       @echo ""
8500 +else
8501 +check-gdal:
8502 +       @echo ""
8503 +       @echo "**********************************************************"
8504 +       @echo "You must have gdal 12.15.12 or greater installed to run"
8505 +       @echo "check target in unit-tests directory                   "
8506 +       @echo "GDAL_VERSION: '$(GDAL_VERSION)'"
8507 +       @echo "prefix: '$(prefix)'"
8508 +       @echo "**********************************************************"
8509 +       @echo ""
8510 +endif
8511 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/84/8411727990dab1414d2bd0e9918fa8c2350fea4b.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/84/8411727990dab1414d2bd0e9918fa8c2350fea4b.svn-base
8512 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/84/8411727990dab1414d2bd0e9918fa8c2350fea4b.svn-base     1970-01-01 01:00:00.000000000 +0100
8513 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/84/8411727990dab1414d2bd0e9918fa8c2350fea4b.svn-base  2014-03-03 15:47:37.400232956 +0100
8514 @@ -0,0 +1,13 @@
8515 +<?xml version="1.0" encoding="UTF-8"?>
8516 +<request reqID ="some_unique_value" >
8517 +    <setContext name="dap_format">dap2</setContext>
8518 +    <setContext name="xdap_accept">3.3</setContext>
8519 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
8520 +    <define name="d">
8521 +          <container name="c">
8522 +              <constraint>swath2grid()</constraint>
8523 +          </container>
8524 +    </define>
8525 +    <get type="dods" definition="d"/>
8526 +</request>
8527 +
8528 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/84/84572441d00db760c377120e09ab68451d54d4a4.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/84/84572441d00db760c377120e09ab68451d54d4a4.svn-base
8529 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/84/84572441d00db760c377120e09ab68451d54d4a4.svn-base     1970-01-01 01:00:00.000000000 +0100
8530 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/84/84572441d00db760c377120e09ab68451d54d4a4.svn-base  2014-03-03 15:47:37.846899604 +0100
8531 @@ -0,0 +1,13 @@
8532 +<?xml version="1.0" encoding="UTF-8"?>
8533 +<request reqID ="some_unique_value" >
8534 +    <setContext name="dap_format">dap2</setContext>
8535 +    <setContext name="xdap_accept">3.3</setContext>
8536 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
8537 +    <define name="d">
8538 +          <container name="c">
8539 +              <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
8540 +          </container>
8541 +    </define>
8542 +    <get type="dods" definition="d"/>
8543 +</request>
8544 +
8545 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a1/a171586f7cd3757d03bb9b30306a4d2e0b053077.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/a1/a171586f7cd3757d03bb9b30306a4d2e0b053077.svn-base
8546 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a1/a171586f7cd3757d03bb9b30306a4d2e0b053077.svn-base     1970-01-01 01:00:00.000000000 +0100
8547 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/a1/a171586f7cd3757d03bb9b30306a4d2e0b053077.svn-base  2014-03-03 15:47:37.590232948 +0100
8548 @@ -0,0 +1,668 @@
8549 +
8550 +// -*- mode: c++; c-basic-offset:4 -*-
8551 +
8552 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
8553 +// Access Protocol.
8554 +
8555 +// Copyright (c) 2012 OPeNDAP, Inc.
8556 +// Author: James Gallagher <jgallagher@opendap.org>
8557 +//
8558 +// This library is free software; you can redistribute it and/or
8559 +// modify it under the terms of the GNU Lesser General Public
8560 +// License as published by the Free Software Foundation; either
8561 +// version 2.1 of the License, or (at your option) any later version.
8562 +//
8563 +// This library is distributed in the hope that it will be useful,
8564 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
8565 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
8566 +// Lesser General Public License for more details.
8567 +//
8568 +// You should have received a copy of the GNU Lesser General Public
8569 +// License along with this library; if not, write to the Free Software
8570 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
8571 +//
8572 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
8573 +
8574 +// Tests for the AISResources class.
8575 +
8576 +#include <cppunit/TextTestRunner.h>
8577 +#include <cppunit/extensions/TestFactoryRegistry.h>
8578 +#include <cppunit/extensions/HelperMacros.h>
8579 +
8580 +#define DODS_DEBUG
8581 +//#define DODS_DEBUG2
8582 +
8583 +#include "BaseType.h"
8584 +#include "Array.h"
8585 +#include "Grid.h"
8586 +
8587 +#include "reproj_functions.h"
8588 +
8589 +#include "test/TestTypeFactory.h"
8590 +
8591 +#include "util.h"
8592 +#include "debug.h"
8593 +
8594 +#define THREE_ARRAY_1_DDS "three_array_1.dds"
8595 +#define THREE_ARRAY_1_DAS "three_array_1.das"
8596 +
8597 +using namespace CppUnit;
8598 +using namespace libdap;
8599 +using namespace std;
8600 +
8601 +int test_variable_sleep_interval = 0;
8602 +
8603 +/**
8604 + * Splits the string on the passed char. Returns vector of substrings.
8605 + * TODO make this work on situations where multiple spaces doesn't hose the split()
8606 + */
8607 +static vector<string> &split(const string &s, char delim, vector<string> &elems) {
8608 +    stringstream ss(s);
8609 +    string item;
8610 +    while (getline(ss, item, delim)) {
8611 +        elems.push_back(item);
8612 +    }
8613 +    return elems;
8614 +}
8615 +
8616 +/**
8617 + * Splits the string on the passed char. Returns vector of substrings.
8618 + */
8619 +static vector<string> split(const string &s, char delim = ' ') {
8620 +    vector<string> elems;
8621 +    return split(s, delim, elems);
8622 +}
8623 +
8624 +class s2gTest:public TestFixture
8625 +{
8626 +private:
8627 +    DDS * dds;
8628 +    TestTypeFactory btf;
8629 +    ConstraintEvaluator ce;
8630 +public:
8631 +    s2gTest():dds(0)
8632 +    {}
8633 +    ~s2gTest()
8634 +    {}
8635 +
8636 +    void setUp()
8637 +    {
8638 +        try {
8639 +            dds = new DDS(&btf);
8640 +            string dds_file = /*(string)TEST_SRC_DIR + "/" +*/ THREE_ARRAY_1_DDS ;
8641 +            dds->parse(dds_file);
8642 +            DAS das;
8643 +            string das_file = /*(string)TEST_SRC_DIR + "/" +*/ THREE_ARRAY_1_DAS ;
8644 +            das.parse(das_file);
8645 +            dds->transfer_attributes(&das);
8646 +
8647 +            DBG(dds->print_xml(stderr, false, "noBlob"));
8648 +
8649 +            // Load values into the array variables
8650 +            Array & t = dynamic_cast < Array & >(*dds->var("t"));
8651 +            Array & lon = dynamic_cast < Array & >(*dds->var("lon"));
8652 +            Array & lat = dynamic_cast < Array & >(*dds->var("lat"));
8653 +
8654 +            dods_float64 t_vals[10][10];
8655 +            for (int i = 0; i < 10; ++i)
8656 +                for (int j = 0; j < 10; ++j)
8657 +                    t_vals[i][j] = j + (i * 10);
8658 +            t.set_value(&t_vals[0][0], 100);
8659 +            t.set_read_p(true);
8660 +
8661 +            // Read real lat/lon values from a Level 1B file ascii dump
8662 +            fstream input("AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz.ascii.txt", fstream::in);
8663 +            if (input.eof() || input.fail())
8664 +                throw Error("Could not open lat/lon data in SetUp.");
8665 +            // Read a line of text to get to the start of the data.
8666 +            string line;
8667 +            getline(input, line);
8668 +            if (input.eof() || input.fail())
8669 +                throw Error("Could not read lat/lon data in SetUp.");
8670 +
8671 +            dods_float64 lon_vals[10][10];
8672 +            for (int i = 0; i < 10; ++i) {
8673 +                getline(input, line);
8674 +                if (input.eof() || input.fail())
8675 +                    throw Error("Could not read lon data from row " + long_to_string(i) + " in SetUp.");
8676 +                vector<string> vals = split(line, ',');
8677 +                for (unsigned int j = 1; j < vals.size(); ++j) {
8678 +                    DBG2(cerr << "loading in lon value: " << vals[j] << "' " << atof(vals[j].c_str()) << endl;)
8679 +                    lon_vals[i][j-1] = atof(vals[j].c_str());
8680 +                }
8681 +            }
8682 +            lon.set_value(&lon_vals[0][0], 100);
8683 +            lon.set_read_p(true);
8684 +
8685 +            dods_float64 lat_vals[10][10];
8686 +            for (int i = 0; i < 10; ++i) {
8687 +                getline(input, line);
8688 +                if (input.eof() || input.fail())
8689 +                    throw Error("Could not read lat data from row " + long_to_string(i) + " in SetUp.");
8690 +                vector<string> vals = split(line, ',');
8691 +                for (unsigned int j = 1; j < vals.size(); ++j) {
8692 +                    DBG2(cerr << "loading in lat value: " << vals[j] << "' " << atof(vals[j].c_str()) << endl;)
8693 +                    lat_vals[i][j-1] = atof(vals[j].c_str());
8694 +                }
8695 +            }
8696 +            lat.set_value(&lat_vals[0][0], 100);
8697 +            lat.set_read_p(true);
8698 +        }
8699 +
8700 +        catch (Error & e) {
8701 +            cerr << "SetUp (Error): " << e.get_error_message() << endl;
8702 +            throw;
8703 +        }
8704 +        catch(std::exception &e) {
8705 +            cerr << "SetUp (std::exception): " << e.what() << endl;
8706 +            throw;
8707 +        }
8708 +    }
8709 +
8710 +    void tearDown()
8711 +    {
8712 +        delete dds; dds = 0;
8713 +    }
8714 +
8715 +    CPPUNIT_TEST_SUITE( s2gTest );
8716 +
8717 +    CPPUNIT_TEST(no_arguments_test);
8718 +    CPPUNIT_TEST(array_return_test);
8719 +    CPPUNIT_TEST(grid_return_test);
8720 +
8721 +    CPPUNIT_TEST_SUITE_END();
8722 +
8723 +    void no_arguments_test()
8724 +    {
8725 +        try {
8726 +            BaseType *btp = 0;
8727 +            function_swath2array(0, 0, *dds, &btp);
8728 +            CPPUNIT_ASSERT(true);
8729 +        }
8730 +        catch (Error &e) {
8731 +            DBG(cerr << e.get_error_message() << endl);
8732 +            CPPUNIT_ASSERT(!"no_arguments_test() should not have failed");
8733 +        }
8734 +    }
8735 +
8736 +    void array_return_test()
8737 +    {
8738 +        try {
8739 +            BaseType *argv[3];
8740 +            argv[0] = dds->var("t");
8741 +            argv[1] = dds->var("lon");
8742 +            argv[2] = dds->var("lat");
8743 +
8744 +            BaseType *btp = 0;
8745 +            function_swath2array(3, argv, *dds, &btp);
8746 +
8747 +            DBG(cerr << "btp->name(): " << btp->name() << endl);
8748 +            CPPUNIT_ASSERT(btp->name() == "t");
8749 +            CPPUNIT_ASSERT(btp->type() == dods_array_c);
8750 +
8751 +            // Extract data; I know it's 10x16 from debugging output
8752 +            dods_float64 values[10][16];
8753 +            Array *a = static_cast<Array*>(btp);
8754 +            a->value(&values[0][0]);
8755 +        }
8756 +        catch (Error &e) {
8757 +            DBG(cerr << e.get_error_message() << endl);
8758 +            CPPUNIT_FAIL("array_return_test");
8759 +        }
8760 +    }
8761 +
8762 +#if 0
8763 +    void one_argument_not_a_grid_test()
8764 +    {
8765 +        try {
8766 +            BaseType *argv[1];
8767 +            argv[0] = dds->var("lat");
8768 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this, although it is not a grid");
8769 +            BaseType *btp = 0;
8770 +            function_grid(1, argv, *dds, &btp);
8771 +            CPPUNIT_ASSERT(!"one_argument_not_a_grid_test() should have failed");
8772 +        }
8773 +        catch (Error &e) {
8774 +            DBG(cerr << e.get_error_message() << endl);
8775 +            CPPUNIT_ASSERT(true);
8776 +        }
8777 +    }
8778 +
8779 +    void map_not_in_grid_test()
8780 +    {
8781 +        try {
8782 +            BaseType *argv[2];
8783 +            argv[0] = dds->var("a");
8784 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8785 +            argv[1] = new Str("");
8786 +            string expression = "3<second<=7";
8787 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8788 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8789 +            BaseType *btp = 0;
8790 +            function_grid(2, argv, *dds, &btp);
8791 +            CPPUNIT_ASSERT(!"map_not_in_grid_test() should have failed");
8792 +        }
8793 +        catch (Error &e) {
8794 +            DBG(cerr << e.get_error_message() << endl);
8795 +            CPPUNIT_ASSERT(true);
8796 +        }
8797 +    }
8798 +
8799 +    void one_dim_grid_test()
8800 +    {
8801 +        try {
8802 +            BaseType *argv[2];
8803 +            argv[0] = dds->var("a");
8804 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8805 +            argv[1] = new Str("");
8806 +            string expression = "3<first<=7";
8807 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8808 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8809 +
8810 +            BaseType *btp = 0;
8811 +            function_grid(2, argv, *dds, &btp);
8812 +            Grid &g = dynamic_cast<Grid&>(*btp);
8813 +
8814 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
8815 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
8816 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 4);
8817 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 7);
8818 +        }
8819 +        catch (Error &e) {
8820 +            DBG(cerr << e.get_error_message() << endl);
8821 +            CPPUNIT_ASSERT(!"one_dim_grid_test() should have worked");
8822 +        }
8823 +    }
8824 +
8825 +    void one_dim_grid_two_expressions_test()
8826 +    {
8827 +        try {
8828 +            BaseType *argv[3];
8829 +            argv[0] = dds->var("a");
8830 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8831 +
8832 +            argv[1] = new Str("");
8833 +            string expression = "first>3";
8834 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8835 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8836 +
8837 +            argv[2] = new Str("");
8838 +            expression = "first<=7";
8839 +            dynamic_cast<Str*>(argv[2])->val2buf(&expression);
8840 +            dynamic_cast<Str*>(argv[2])->set_read_p(true);
8841 +
8842 +            //function_grid(3, argv, *dds);
8843 +            BaseType *btp = 0;
8844 +            function_grid(3, argv, *dds, &btp);
8845 +            Grid &g = dynamic_cast<Grid&>(*btp);
8846 +
8847 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(3, argv, *dds));
8848 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
8849 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
8850 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 4);
8851 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 7);
8852 +        }
8853 +        catch (Error &e) {
8854 +            DBG(cerr << e.get_error_message() << endl);
8855 +            CPPUNIT_ASSERT(!"one_dim_grid_two_expressions_test() should have worked");
8856 +        }
8857 +    }
8858 +
8859 +    void one_dim_grid_descending_test()
8860 +    {
8861 +        try {
8862 +            BaseType *argv[2];
8863 +            argv[0] = dds->var("b");
8864 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8865 +            argv[1] = new Str("");
8866 +            string expression = "3<first<=7";
8867 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8868 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8869 +
8870 +            BaseType *btp = 0;
8871 +            function_grid(2, argv, *dds, &btp);
8872 +            Grid &g = dynamic_cast<Grid&>(*btp);
8873 +
8874 +            //function_grid(2, argv, *dds);
8875 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(2, argv, *dds));
8876 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
8877 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
8878 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 2);
8879 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 5);
8880 +        }
8881 +        catch (Error &e) {
8882 +            DBG(cerr << e.get_error_message() << endl);
8883 +            CPPUNIT_ASSERT(!"one_dim_grid_test() should have worked");
8884 +        }
8885 +    }
8886 +
8887 +    void one_dim_grid_two_expressions_descending_test()
8888 +    {
8889 +        try {
8890 +            BaseType *argv[3];
8891 +            argv[0] = dds->var("b");
8892 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8893 +
8894 +            argv[1] = new Str("");
8895 +            string expression = "first>3";
8896 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8897 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8898 +
8899 +            argv[2] = new Str("");
8900 +            expression = "first<=7";
8901 +            dynamic_cast<Str*>(argv[2])->val2buf(&expression);
8902 +            dynamic_cast<Str*>(argv[2])->set_read_p(true);
8903 +
8904 +            BaseType *btp = 0;
8905 +            function_grid(3, argv, *dds, &btp);
8906 +            Grid &g = dynamic_cast<Grid&>(*btp);
8907 +
8908 +            //function_grid(3, argv, *dds);
8909 +            //Grid &g = dynamic_cast<Grid&>(*function_grid(3, argv, *dds));
8910 +            //Grid &g = dynamic_cast<Grid&>(*argv[0]);
8911 +            Array &m = dynamic_cast<Array&>(**g.map_begin());
8912 +            CPPUNIT_ASSERT(m.dimension_start(m.dim_begin(), true) == 2);
8913 +            CPPUNIT_ASSERT(m.dimension_stop(m.dim_begin(), true) == 5);
8914 +        }
8915 +        catch (Error &e) {
8916 +            DBG(cerr << e.get_error_message() << endl);
8917 +            CPPUNIT_ASSERT(!"one_dim_grid_two_expressions_test() should have worked");
8918 +        }
8919 +    }
8920 +
8921 +    void one_dim_grid_noninclusive_values_test()
8922 +    {
8923 +        try {
8924 +            BaseType *argv[2];
8925 +            argv[0] = dds->var("a");
8926 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8927 +            argv[1] = new Str("");
8928 +            string expression = "7<first<=3";
8929 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8930 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8931 +
8932 +            BaseType *btp = 0;
8933 +            function_grid(2, argv, *dds, &btp);
8934 +            //Grid &g = dynamic_cast<Grid&>(*btp);
8935 +
8936 +            // function_grid(2, argv, *dds);
8937 +
8938 +            CPPUNIT_ASSERT(!"one_dim_grid_noninclusive_values_test() should not have worked");
8939 +        }
8940 +        catch (Error &e) {
8941 +            DBG(cerr << e.get_error_message() << endl);
8942 +            CPPUNIT_ASSERT(true);
8943 +        }
8944 +    }
8945 +
8946 +    // grid() is not required to handle this case. This test is not used.
8947 +    void values_outside_map_range_test()
8948 +    {
8949 +        try {
8950 +            BaseType *argv[2];
8951 +            argv[0] = dds->var("a");
8952 +            CPPUNIT_ASSERT(argv[0] && "dds->var should find this");
8953 +            argv[1] = new Str("");
8954 +            string expression = "3<=first<20";
8955 +            dynamic_cast<Str*>(argv[1])->val2buf(&expression);
8956 +            dynamic_cast<Str*>(argv[1])->set_read_p(true);
8957 +
8958 +            BaseType *btp = 0;
8959 +            function_grid(2, argv, *dds, &btp);
8960 +            //Grid &g = dynamic_cast<Grid&>(*btp);
8961 +
8962 +            // function_grid(2, argv, *dds);
8963 +
8964 +            CPPUNIT_ASSERT(!"values_outside_map_range_test() should not have worked");
8965 +        }
8966 +        catch (Error &e) {
8967 +            DBG(cerr << e.get_error_message() << endl);
8968 +            CPPUNIT_ASSERT(true);
8969 +        }
8970 +    }
8971 +
8972 +    // linear_scale tests
8973 +    void linear_scale_args_test() {
8974 +        try {
8975 +            BaseType *btp = 0;
8976 +            function_linear_scale(0, 0, *dds, &btp);
8977 +            CPPUNIT_ASSERT(true);
8978 +        }
8979 +        catch (Error &e) {
8980 +            DBG(cerr << e.get_error_message() << endl);
8981 +            CPPUNIT_ASSERT(!"linear_scale_args_test: should not throw Error");
8982 +        }
8983 +    }
8984 +
8985 +    void linear_scale_array_test() {
8986 +        try {
8987 +            Array *a = dynamic_cast<Grid&>(*dds->var("a")).get_array();
8988 +            CPPUNIT_ASSERT(a);
8989 +            BaseType *argv[3];
8990 +            argv[0] = a;
8991 +            argv[1] = new Float64("");
8992 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);//m
8993 +            argv[2] = new Float64("");
8994 +            dynamic_cast<Float64*>(argv[2])->set_value(10);//b
8995 +            BaseType *scaled = 0;
8996 +            function_linear_scale(3, argv, *dds, &scaled);
8997 +            CPPUNIT_ASSERT(scaled->type() == dods_array_c
8998 +                           && scaled->var()->type() == dods_float64_c);
8999 +            double *values = extract_double_array(dynamic_cast<Array*>(scaled));
9000 +            CPPUNIT_ASSERT(values[0] == 10);
9001 +            CPPUNIT_ASSERT(values[1] == 10.1);
9002 +            CPPUNIT_ASSERT(values[9] == 10.9);
9003 +        }
9004 +        catch (Error &e) {
9005 +            DBG(cerr << e.get_error_message() << endl);
9006 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
9007 +        }
9008 +    }
9009 +
9010 +    void linear_scale_grid_test() {
9011 +        try {
9012 +            Grid *g = dynamic_cast<Grid*>(dds->var("a"));
9013 +            CPPUNIT_ASSERT(g);
9014 +            BaseType *argv[3];
9015 +            argv[0] = g;
9016 +            argv[1] = new Float64("");
9017 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);
9018 +            argv[2] = new Float64("");
9019 +            dynamic_cast<Float64*>(argv[2])->set_value(10);
9020 +            BaseType *scaled = 0;
9021 +            function_linear_scale(3, argv, *dds, &scaled);
9022 +            CPPUNIT_ASSERT(scaled->type() == dods_grid_c);
9023 +            Grid *g_s = dynamic_cast<Grid*>(scaled);
9024 +            CPPUNIT_ASSERT(g_s->get_array()->var()->type() == dods_float64_c);
9025 +            double *values = extract_double_array(g_s->get_array());
9026 +            CPPUNIT_ASSERT(values[0] == 10);
9027 +            CPPUNIT_ASSERT(values[1] == 10.1);
9028 +            CPPUNIT_ASSERT(values[9] == 10.9);
9029 +        }
9030 +        catch (Error &e) {
9031 +            DBG(cerr << e.get_error_message() << endl);
9032 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
9033 +        }
9034 +    }
9035 +
9036 +    void linear_scale_grid_attributes_test() {
9037 +        try {
9038 +            Grid *g = dynamic_cast<Grid*>(dds->var("a"));
9039 +            CPPUNIT_ASSERT(g);
9040 +            BaseType *argv[1];
9041 +            argv[0] = g;
9042 +            BaseType *scaled = 0;
9043 +            function_linear_scale(1, argv, *dds, &scaled);
9044 +            CPPUNIT_ASSERT(scaled->type() == dods_grid_c);
9045 +            Grid *g_s = dynamic_cast<Grid*>(scaled);
9046 +            CPPUNIT_ASSERT(g_s->get_array()->var()->type() == dods_float64_c);
9047 +            double *values = extract_double_array(g_s->get_array());
9048 +            CPPUNIT_ASSERT(values[0] == 10);
9049 +            CPPUNIT_ASSERT(values[1] == 10.1);
9050 +            CPPUNIT_ASSERT(values[9] == 10.9);
9051 +        }
9052 +        catch (Error &e) {
9053 +            DBG(cerr << e.get_error_message() << endl);
9054 +            CPPUNIT_ASSERT(!"Error in linear_scale_grid_test()");
9055 +        }
9056 +    }
9057 +
9058 +    // This tests the case where attributes are not found
9059 +    void linear_scale_grid_attributes_test2() {
9060 +        try {
9061 +            Grid *g = dynamic_cast<Grid*>(dds->var("b"));
9062 +            CPPUNIT_ASSERT(g);
9063 +            BaseType *argv[1];
9064 +            argv[0] = g;
9065 +            BaseType *btp = 0;
9066 +            function_linear_scale(1, argv, *dds, &btp);
9067 +            CPPUNIT_FAIL("Should not get here; no params passed and no attributes set for grid 'b'");
9068 +        }
9069 +        catch (Error &e) {
9070 +            DBG(cerr << e.get_error_message() << endl);
9071 +            CPPUNIT_ASSERT("Caught exception");
9072 +        }
9073 +    }
9074 +
9075 +    void linear_scale_scalar_test() {
9076 +        try {
9077 +            Int32 *i = new Int32("linear_scale_test_int32");
9078 +            CPPUNIT_ASSERT(i);
9079 +            i->set_value(1);
9080 +            BaseType *argv[3];
9081 +            argv[0] = i;
9082 +            argv[1] = new Float64("");
9083 +            dynamic_cast<Float64*>(argv[1])->set_value(0.1);//m
9084 +            argv[2] = new Float64("");
9085 +            dynamic_cast<Float64*>(argv[2])->set_value(10);//b
9086 +            BaseType *scaled = 0;
9087 +            function_linear_scale(3, argv, *dds, &scaled);
9088 +            CPPUNIT_ASSERT(scaled->type() == dods_float64_c);
9089 +
9090 +            CPPUNIT_ASSERT(dynamic_cast<Float64*>(scaled)->value() == 10.1);
9091 +        }
9092 +        catch (Error &e) {
9093 +            DBG(cerr << e.get_error_message() << endl);
9094 +            CPPUNIT_ASSERT(!"Error in linear_scale_scalar_test()");
9095 +        }
9096 +    }
9097 +
9098 +
9099 +    void function_dap_1_test() {
9100 +        try {
9101 +            Int32 *i = new Int32("function_dap_1_test_int32");
9102 +            CPPUNIT_ASSERT(i);
9103 +            i->set_value(2);
9104 +            BaseType *argv[1];
9105 +            argv[0] = i;
9106 +
9107 +            ConstraintEvaluator unused;
9108 +            function_dap(1, argv, *dds, unused);
9109 +
9110 +            CPPUNIT_ASSERT(dds->get_dap_major() == 2);
9111 +            CPPUNIT_ASSERT(dds->get_dap_minor() == 0);
9112 +        }
9113 +        catch (Error &e) {
9114 +            DBG(cerr << e.get_error_message() << endl);
9115 +            CPPUNIT_FAIL("Error in function_dap_1_test(): " + e.get_error_message());
9116 +        }
9117 +    }
9118 +
9119 +    void function_dap_2_test() {
9120 +        try {
9121 +            Float64 *d = new Float64("function_dap_1_test_float64");
9122 +            CPPUNIT_ASSERT(d);
9123 +            d->set_value(3.2);
9124 +            BaseType *argv[1];
9125 +            argv[0] = d;
9126 +
9127 +            ConstraintEvaluator unused;
9128 +            function_dap(1, argv, *dds, unused);
9129 +
9130 +            CPPUNIT_ASSERT(dds->get_dap_major() == 3);
9131 +            CPPUNIT_ASSERT(dds->get_dap_minor() == 2);
9132 +        }
9133 +        catch (Error &e) {
9134 +            DBG(cerr << e.get_error_message() << endl);
9135 +            CPPUNIT_FAIL("Error in function_dap_2_test(): " + e.get_error_message());
9136 +        }
9137 +    }
9138 +
9139 +    void function_dap_3_test() {
9140 +        try {
9141 +            cerr <<"In function_dap_3_test" << endl;
9142 +            ConstraintEvaluator unused;
9143 +            function_dap(0, 0, *dds, unused);
9144 +
9145 +            CPPUNIT_FAIL("Should have thrown an exception on no args");
9146 +                    }
9147 +        catch (Error &e) {
9148 +            DBG(cerr << e.get_error_message() << endl);
9149 +            CPPUNIT_ASSERT("Pass: Caught exception");
9150 +        }
9151 +    }
9152 +#endif
9153 +    void grid_return_test()
9154 +    {
9155 +        try {
9156 +            BaseType *argv[3];
9157 +            argv[0] = dds->var("t");
9158 +            argv[1] = dds->var("lon");
9159 +            argv[2] = dds->var("lat");
9160 +
9161 +            cerr << "Input values:" << endl;
9162 +            dods_float64 t_vals[10][10];
9163 +            Array *a = static_cast<Array*>(argv[0]);
9164 +            a->value(&t_vals[0][0]);
9165 +            for (int i = 0; i < 10; ++i) {
9166 +                for (int j = 0; j < 10; ++j) {
9167 +                    cerr << "t[" << i << "][" << j << "]: " <<  t_vals[i][j] << endl;
9168 +                }
9169 +            }
9170 +
9171 +            BaseType *btp = 0;
9172 +            function_swath2grid(3, argv, *dds, &btp);
9173 +
9174 +            DBG(cerr << "btp->name(): " << btp->name() << endl);
9175 +            CPPUNIT_ASSERT(btp->name() == "t");
9176 +            CPPUNIT_ASSERT(btp->type() == dods_grid_c);
9177 +
9178 +            // Extract data; I know it's 10x16 from debugging output
9179 +            dods_float64 values[10][16];
9180 +            Grid *g = static_cast<Grid*>(btp);
9181 +            g->get_array()->value(&values[0][0]);
9182 +
9183 +            Grid::Map_iter m = g->map_begin();
9184 +            dods_float64 lat[10];
9185 +            static_cast<Array*>(*m)->value(&lat[0]);
9186 +
9187 +            ++m;
9188 +            dods_float64 lon[16];
9189 +            static_cast<Array*>(*m)->value(&lon[0]);
9190 +
9191 +            cerr << "Output values:" << endl;
9192 +            for (int i = 0; i < 10; ++i) {
9193 +                for (int j = 0; j < 16; ++j) {
9194 +                    cerr << "t[" << i << "][" << j << "] == lon: " << lon[j] << ", lat: " << lat[i] << " val: " << values[i][j] << endl;
9195 +                }
9196 +            }
9197 +        }
9198 +        catch (Error &e) {
9199 +            DBG(cerr << e.get_error_message() << endl);
9200 +            CPPUNIT_FAIL("array_return_test");
9201 +        }
9202 +    }
9203 +};
9204 +
9205 +CPPUNIT_TEST_SUITE_REGISTRATION(s2gTest);
9206 +
9207 +int
9208 +main( int, char** )
9209 +{
9210 +    CppUnit::TextTestRunner runner;
9211 +    runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );
9212 +
9213 +    bool wasSuccessful = runner.run( "", false ) ;
9214 +
9215 +    return wasSuccessful ? 0 : 1;
9216 +}
9217 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a3/a3f498cd850e8312c27336b44b772bc06e45db56.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/a3/a3f498cd850e8312c27336b44b772bc06e45db56.svn-base
9218 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a3/a3f498cd850e8312c27336b44b772bc06e45db56.svn-base     1970-01-01 01:00:00.000000000 +0100
9219 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/a3/a3f498cd850e8312c27336b44b772bc06e45db56.svn-base  2014-03-03 15:47:37.810232939 +0100
9220 @@ -0,0 +1,10 @@
9221 +# three_array_1.das
9222 +#
9223 +# Created on: Dec 12, 2012
9224 +#     Author: jimg
9225 +
9226 +Attributes {
9227 +    t{}
9228 +    lon{}
9229 +    lat{}
9230 +}
9231 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a4/a48ca81df02968d388c1aff08bdb983200a5cb0f.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/a4/a48ca81df02968d388c1aff08bdb983200a5cb0f.svn-base
9232 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/a4/a48ca81df02968d388c1aff08bdb983200a5cb0f.svn-base     1970-01-01 01:00:00.000000000 +0100
9233 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/a4/a48ca81df02968d388c1aff08bdb983200a5cb0f.svn-base  2014-03-03 15:47:37.980232932 +0100
9234 @@ -0,0 +1,13 @@
9235 +<?xml version="1.0" encoding="UTF-8"?>
9236 +<request reqID ="some_unique_value" >
9237 +    <setContext name="dap_format">dap2</setContext>
9238 +    <setContext name="xdap_accept">3.3</setContext>
9239 +    <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
9240 +    <define name="d">
9241 +          <container name="c">
9242 +              <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
9243 +          </container>
9244 +    </define>
9245 +    <get type="das" definition="d"/>
9246 +</request>
9247 +
9248 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/bc/bceeadf67b7c887a5453ff7cc4e625483701f4e3.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/bc/bceeadf67b7c887a5453ff7cc4e625483701f4e3.svn-base
9249 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/bc/bceeadf67b7c887a5453ff7cc4e625483701f4e3.svn-base     1970-01-01 01:00:00.000000000 +0100
9250 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/bc/bceeadf67b7c887a5453ff7cc4e625483701f4e3.svn-base  2014-03-03 15:47:37.403566289 +0100
9251 @@ -0,0 +1,109 @@
9252 +
9253 +// -*- mode: c++; c-basic-offset:4 -*-
9254 +
9255 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
9256 +// Access Protocol.
9257 +
9258 +// Copyright (c) 2002,2003 OPeNDAP, Inc.
9259 +// Author: James Gallagher <jgallagher@opendap.org>
9260 +//
9261 +// This library is free software; you can redistribute it and/or
9262 +// modify it under the terms of the GNU Lesser General Public
9263 +// License as published by the Free Software Foundation; either
9264 +// version 2.1 of the License, or (at your option) any later version.
9265 +//
9266 +// This library is distributed in the hope that it will be useful,
9267 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
9268 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9269 +// Lesser General Public License for more details.
9270 +//
9271 +// You should have received a copy of the GNU Lesser General Public
9272 +// License along with this library; if not, write to the Free Software
9273 +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
9274 +//
9275 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
9276 +
9277 +// (c) COPYRIGHT URI/MIT 1999
9278 +// Please read the full copyright statement in the file COPYRIGHT_URI.
9279 +//
9280 +// Authors:
9281 +//      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
9282 +
9283 +// Declarations for CE functions.
9284 +//
9285 +// 1/15/99 jhrg
9286 +
9287 +#ifndef _reproj_functions_h
9288 +#define _reproj_functions_h
9289 +
9290 +#include "BESAbstractModule.h"
9291 +#include "ServerFunction.h"
9292 +#include "ServerFunctionsList.h"
9293 +
9294 +namespace libdap {
9295 +
9296 +void function_swath2array(int argc, BaseType * argv[], DDS &, BaseType **btpp);
9297 +void function_swath2grid(int argc, BaseType * argv[], DDS &, BaseType **btpp);
9298 +
9299 +
9300 +class SwathToGrid: public libdap::ServerFunction {
9301 +public:
9302 +    SwathToGrid()
9303 +    {
9304 +        setName("swath2grid");
9305 +        setDescriptionString("This function echos back it's arguments as DAP data.");
9306 +        setUsageString("swath2grid(dataArray, latitudeArray, longitudeArray)");
9307 +        setRole("http://services.opendap.org/dap4/server-side-function/swath2grid");
9308 +        setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2grid");
9309 +        setFunction(libdap::function_swath2grid);
9310 +        setVersion("1.0");
9311 +    }
9312 +    virtual ~SwathToGrid()
9313 +    {
9314 +    }
9315 +
9316 +};
9317 +
9318 +class SwathToArray: public libdap::ServerFunction {
9319 +public:
9320 +    SwathToArray()
9321 +    {
9322 +        setName("swath2array");
9323 +        setDescriptionString("This function echos back it's arguments as DAP data.");
9324 +        setUsageString("swath2array(dataArray, latitudeArray, longitudeArray)");
9325 +        setRole("http://services.opendap.org/dap4/server-side-function/swath2array");
9326 +        setDocUrl("http://docs.opendap.org/index.php/Server_Side_Processing_Functions#swath2array");
9327 +        setFunction(libdap::function_swath2array);
9328 +        setVersion("1.0");
9329 +    }
9330 +    virtual ~SwathToArray()
9331 +    {
9332 +    }
9333 +
9334 +};
9335 +
9336 +
9337 +class ReProjectionFunctions: public BESAbstractModule {
9338 +public:
9339 +    ReProjectionFunctions()
9340 +    {
9341 +        libdap::ServerFunctionsList::TheList()->add_function(new libdap::SwathToGrid());
9342 +
9343 +        libdap::ServerFunctionsList::TheList()->add_function(new libdap::SwathToArray());
9344 +
9345 +    }
9346 +    virtual ~ReProjectionFunctions()
9347 +    {
9348 +    }
9349 +    virtual void initialize(const string &modname);
9350 +    virtual void terminate(const string &modname);
9351 +
9352 +    virtual void dump(ostream &strm) const;
9353 +};
9354 +
9355 +
9356 +
9357 +
9358 +} // namespace libdap
9359 +
9360 +#endif // _reproj_functions_h
9361 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/bd/bd5bb3aeffa01d2e79bad1eba81402eb23ce33cd.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/bd/bd5bb3aeffa01d2e79bad1eba81402eb23ce33cd.svn-base
9362 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/bd/bd5bb3aeffa01d2e79bad1eba81402eb23ce33cd.svn-base     1970-01-01 01:00:00.000000000 +0100
9363 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/bd/bd5bb3aeffa01d2e79bad1eba81402eb23ce33cd.svn-base  2014-03-03 15:47:37.976899599 +0100
9364 @@ -0,0 +1,137 @@
9365 +/******************************************************************************
9366 + * $Id: BoundingBox.h 2011-07-19 16:24:00Z $
9367 + *
9368 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
9369 + *                      for Earth Observation: Open Source Reference Implementation
9370 + * Purpose:  BoundingBox class definition
9371 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
9372 + *
9373 + ******************************************************************************
9374 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
9375 + *
9376 + * Permission is hereby granted, free of charge, to any person obtaining a
9377 + * copy of this software and associated documentation files (the "Software"),
9378 + * to deal in the Software without restriction, including without limitation
9379 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9380 + * and/or sell copies of the Software, and to permit persons to whom the
9381 + * Software is furnished to do so, subject to the following conditions:
9382 + *
9383 + * The above copyright notice and this permission notice shall be included
9384 + * in all copies or substantial portions of the Software.
9385 + *
9386 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
9387 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9388 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
9389 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9390 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
9391 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
9392 + * DEALINGS IN THE SOFTWARE.
9393 + ****************************************************************************/
9394 +
9395 +#ifndef BOUNDINGBOX_H_
9396 +#define BOUNDINGBOX_H_
9397 +
9398 +#include <gdal.h>
9399 +#include <ogr_spatialref.h>
9400 +#include <limits>
9401 +#include <stdlib.h>
9402 +
9403 +using namespace std;
9404 +
9405 +/************************************************************************/
9406 +/* ==================================================================== */
9407 +/*                             My2DPoint                                */
9408 +/* ==================================================================== */
9409 +/************************************************************************/
9410 +
9411 +/**
9412 + * \class My2DPoint "BoundingBox.h"
9413 + *
9414 + * My2DPoint class is used to store the point coordinates.
9415 + */
9416 +
9417 +class My2DPoint
9418 +{
9419 +public:
9420 +       double mi_X;
9421 +       double mi_Y;
9422 +
9423 +       virtual ~My2DPoint();
9424 +
9425 +       My2DPoint()
9426 +       {
9427 +               mi_X = 0;
9428 +               mi_Y = 0;
9429 +       }
9430 +
9431 +       My2DPoint(const double& xx, const double& yy) :
9432 +               mi_X(xx), mi_Y(yy)
9433 +       {
9434 +       }
9435 +
9436 +       My2DPoint(const My2DPoint& p) :
9437 +               mi_X(p.mi_X), mi_Y(p.mi_Y)
9438 +       {
9439 +       }
9440 +
9441 +       My2DPoint& operator =(const My2DPoint& p)
9442 +       {
9443 +               mi_X = p.mi_X;
9444 +               mi_Y = p.mi_Y;
9445 +               return *this;
9446 +       }
9447 +};
9448 +
9449 +/************************************************************************/
9450 +/* ==================================================================== */
9451 +/*                             BoundingBox                              */
9452 +/* ==================================================================== */
9453 +/************************************************************************/
9454 +
9455 +/**
9456 + * \class BoundingBox "BoundingBox.h"
9457 + *
9458 + * BoundingBox class is used to transform bounding box between different
9459 + * Coordinate Reference System.
9460 + */
9461 +
9462 +class BoundingBox
9463 +{
9464 +public:
9465 +       My2DPoint mo_LowerLeftPT;
9466 +       My2DPoint mo_UpperRightPT;
9467 +       OGRSpatialReference mo_CRS;
9468 +
9469 +       BoundingBox(const My2DPoint& llpt, const My2DPoint& urpt, OGRSpatialReference& crs) :
9470 +               mo_LowerLeftPT(llpt), mo_UpperRightPT(urpt), mo_CRS(crs)
9471 +       {
9472 +
9473 +       }
9474 +
9475 +       BoundingBox(OGRSpatialReference& crs) :
9476 +               mo_LowerLeftPT(0,0), mo_UpperRightPT(0,0), mo_CRS(crs)
9477 +       {
9478 +
9479 +       }
9480 +       BoundingBox& operator =(const BoundingBox& box)
9481 +       {
9482 +               mo_LowerLeftPT = box.mo_LowerLeftPT;
9483 +               mo_UpperRightPT = box.mo_UpperRightPT;
9484 +               mo_CRS = box.mo_CRS;
9485 +               return *this;
9486 +       }
9487 +
9488 +       BoundingBox();
9489 +       virtual ~BoundingBox();
9490 +
9491 +       BoundingBox Transform(OGRSpatialReference&, int&);
9492 +       BoundingBox TransformWorkExtend(OGRSpatialReference&, int&);
9493 +       BoundingBox Transform(const double*);
9494 +};
9495 +
9496 +CPLErr CPL_DLL CPL_STDCALL bBox_transFormmate( OGRSpatialReference&,
9497 +                                                                                               OGRSpatialReference&,
9498 +                                                                                               My2DPoint& lowLeft,
9499 +                                                                                               My2DPoint& upRight);
9500 +
9501 +#endif /* BOUNDINGBOX_H_ */
9502 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/d2/d2f2e54b019cc687d4f25e9e0e840b3d0e0cdaec.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/d2/d2f2e54b019cc687d4f25e9e0e840b3d0e0cdaec.svn-base
9503 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/d2/d2f2e54b019cc687d4f25e9e0e840b3d0e0cdaec.svn-base     1970-01-01 01:00:00.000000000 +0100
9504 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/d2/d2f2e54b019cc687d4f25e9e0e840b3d0e0cdaec.svn-base  2014-03-03 15:47:37.846899604 +0100
9505 @@ -0,0 +1,48 @@
9506 +BES.ServerAdministrator=root@null.dev
9507 +
9508 +BES.User=user_name
9509 +BES.Group=group_name
9510 +
9511 +BES.LogName=./bes.log
9512 +BES.LogVerbose=no
9513 +
9514 +BES.modules=dap,cmd,nc,h4,fong,fonc
9515 +BES.module.dap=@libdir@/bes/libdap_module.so
9516 +BES.module.cmd=@libdir@/bes/libdap_xml_module.so
9517 +
9518 +BES.module.nc=@libdir@/bes/libnc_module.so
9519 +BES.module.h4=@libdir@/bes/libhdf4_module.so
9520 +
9521 +BES.module.fong=@libdir@/bes/libfong_module.so
9522 +BES.module.fonc=@libdir@/bes/libfonc_module.so
9523 +
9524 +BES.Catalog.catalog.RootDirectory=@abs_top_srcdir@
9525 +BES.Data.RootDirectory=/dev/null
9526 +
9527 +BES.Catalog.catalog.TypeMatch=nc:.*.nc(.bz2|.gz|.Z)?$;h4:.*.(hdf|HDF|eos)(.bz2|.gz|.Z)?$;
9528 +
9529 +BES.Catalog.catalog.Include=;
9530 +BES.Catalog.catalog.Exclude=^\..*;
9531 +
9532 +BES.FollowSymLinks=No
9533 +BES.Catalog.catalog.FollowSymLinks=No
9534 +
9535 +BES.ServerPort=10002
9536 +
9537 +BES.CacheDir=/tmp
9538 +BES.CachePrefix=bes_cache
9539 +BES.CacheSize=500
9540 +
9541 +BES.Container.Persistence=strict
9542 +
9543 +BES.Memory.GlobalArea.EmergencyPoolSize=1
9544 +BES.Memory.GlobalArea.MaximumHeapSize=20
9545 +BES.Memory.GlobalArea.Verbose=no
9546 +BES.Memory.GlobalArea.ControlHeap=no
9547 +
9548 +BES.ProcessManagerMethod=multiple
9549 +
9550 +BES.DefaultResponseMethod=POST
9551 +
9552 +FONg.TempDirectory=@abs_top_srcdir@/tests
9553 +
9554 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/d9/d934c25630e184bf0b7bcaf42ac44a390652631c.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/d9/d934c25630e184bf0b7bcaf42ac44a390652631c.svn-base
9555 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/d9/d934c25630e184bf0b7bcaf42ac44a390652631c.svn-base     1970-01-01 01:00:00.000000000 +0100
9556 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/d9/d934c25630e184bf0b7bcaf42ac44a390652631c.svn-base  2014-03-03 15:47:37.843566270 +0100
9557 @@ -0,0 +1,360 @@
9558 +/******************************************************************************
9559 + * $Id: BoundingBox.cpp 2011-07-19 16:24:00Z $
9560 + *
9561 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
9562 + *                      for Earth Observation: Open Source Reference Implementation
9563 + * Purpose:  BoundingBox class implementation, enable transform bounding box
9564 + *                      between different CRS
9565 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
9566 + *
9567 + ******************************************************************************
9568 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
9569 + *
9570 + * Permission is hereby granted, free of charge, to any person obtaining a
9571 + * copy of this software and associated documentation files (the "Software"),
9572 + * to deal in the Software without restriction, including without limitation
9573 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9574 + * and/or sell copies of the Software, and to permit persons to whom the
9575 + * Software is furnished to do so, subject to the following conditions:
9576 + *
9577 + * The above copyright notice and this permission notice shall be included
9578 + * in all copies or substantial portions of the Software.
9579 + *
9580 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
9581 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9582 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
9583 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9584 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
9585 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
9586 + * DEALINGS IN THE SOFTWARE.
9587 + ****************************************************************************/
9588 +
9589 +#include <vector>
9590 +#include <iostream>
9591 +
9592 +#include "BoundingBox.h"
9593 +#include "wcs_error.h"
9594 +
9595 +using namespace std;
9596 +
9597 +My2DPoint::~My2DPoint()
9598 +{
9599 +
9600 +}
9601 +
9602 +BoundingBox::BoundingBox()
9603 +{
9604 +
9605 +}
9606 +
9607 +BoundingBox::~BoundingBox()
9608 +{
9609 +
9610 +}
9611 +
9612 +BoundingBox BoundingBox::TransformWorkExtend(OGRSpatialReference &dstCRS, int &IsOK)
9613 +{
9614 +       if (mo_CRS.IsSame(&dstCRS))
9615 +       {
9616 +               IsOK = TRUE;
9617 +               return *this;
9618 +       }
9619 +
9620 +       OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&mo_CRS, &dstCRS);
9621 +       if (poCT == NULL)
9622 +       {
9623 +               IsOK = FALSE;
9624 +               return *this;
9625 +       }
9626 +
9627 +       double xdes = (mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
9628 +
9629 +       if (mo_CRS.IsGeographic()
9630 +                       && mo_UpperRightPT.mi_X < mo_LowerLeftPT.mi_X
9631 +                       && mo_LowerLeftPT.mi_X > 0 && mo_UpperRightPT.mi_X < 0)
9632 +       {
9633 +               xdes = (360 + mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
9634 +       }
9635 +
9636 +       vector<double> x;
9637 +       vector<double> y;
9638 +       //up and down edge
9639 +       for (double stepX = mo_LowerLeftPT.mi_X; stepX < mo_UpperRightPT.mi_X; stepX
9640 +                       += xdes)
9641 +       {
9642 +               x.push_back(stepX);
9643 +               y.push_back(mo_UpperRightPT.mi_Y);
9644 +               x.push_back(stepX);
9645 +               y.push_back(mo_LowerLeftPT.mi_Y);
9646 +       }
9647 +       x.push_back(mo_UpperRightPT.mi_X);
9648 +       y.push_back(mo_UpperRightPT.mi_Y);
9649 +       x.push_back(mo_UpperRightPT.mi_X);
9650 +       y.push_back(mo_LowerLeftPT.mi_Y);
9651 +
9652 +       double yMin = numeric_limits<double>::max();
9653 +       double yMax = numeric_limits<double>::min();
9654 +
9655 +       int k = 0;
9656 +       vector<int> bSuccess;
9657 +       vector<double> tmpX;
9658 +       vector<double> tmpY;
9659 +
9660 +       for (unsigned int i = 0; i < x.size(); i++)
9661 +       {
9662 +               tmpX.push_back(x[i]);
9663 +               tmpY.push_back(y[i]);
9664 +               bSuccess.push_back(0);
9665 +       }
9666 +
9667 +       poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
9668 +
9669 +       for (unsigned int n = 0; n < x.size(); n++)
9670 +       {
9671 +               if (bSuccess[n])
9672 +               {
9673 +                       ++k;
9674 +                       yMin = MIN(yMin,tmpY[n]);
9675 +                       yMax = MAX(yMax,tmpY[n]);
9676 +               }
9677 +       }
9678 +
9679 +       if (k < 80)
9680 +       {
9681 +               IsOK = FALSE;
9682 +               OCTDestroyCoordinateTransformation(poCT);
9683 +               return *this;
9684 +       }
9685 +
9686 +       //find xmin on left edge and xmax on right edge
9687 +       double xMin;
9688 +       double xMax;
9689 +
9690 +       double tmpPTX[2];
9691 +       double tmpPTY[2];
9692 +
9693 +       int isSucc[2];
9694 +
9695 +       tmpPTX[0] = mo_LowerLeftPT.mi_X;
9696 +       tmpPTX[1] = mo_LowerLeftPT.mi_X;
9697 +       tmpPTY[0] = mo_LowerLeftPT.mi_Y;
9698 +       tmpPTY[1] = mo_UpperRightPT.mi_Y;
9699 +
9700 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
9701 +       if (isSucc[0] && isSucc[1])
9702 +       {
9703 +               xMin = MIN(tmpPTX[0],tmpPTX[1]);
9704 +       }
9705 +       else
9706 +       {
9707 +               OCTDestroyCoordinateTransformation(poCT);
9708 +               IsOK = FALSE;
9709 +               return *this;
9710 +       }
9711 +
9712 +       tmpPTX[0] = mo_UpperRightPT.mi_X;
9713 +       tmpPTX[1] = mo_UpperRightPT.mi_X;
9714 +       tmpPTY[0] = mo_UpperRightPT.mi_Y;
9715 +       tmpPTY[1] = mo_LowerLeftPT.mi_Y;
9716 +
9717 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
9718 +       if (isSucc[0] && isSucc[1])
9719 +       {
9720 +               xMax = MAX(tmpPTX[0],tmpPTX[1]);
9721 +       }
9722 +       else
9723 +       {
9724 +               OCTDestroyCoordinateTransformation(poCT);
9725 +               IsOK = FALSE;
9726 +               return *this;
9727 +       }
9728 +
9729 +       BoundingBox bbox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
9730 +
9731 +       if (dstCRS.IsGeographic())
9732 +       {
9733 +               if (xMin > 180)
9734 +                       xMin = xMin - 360;
9735 +               if (xMax > 180)
9736 +                       xMax = xMax - 360;
9737 +
9738 +               if (xMin >= 180.)
9739 +                       xMin = 180.;
9740 +               if (xMin <= -180.)
9741 +                       xMin = -180.;
9742 +               if (xMax >= 180.)
9743 +                       xMax = 180.;
9744 +               if (xMax <= -180.)
9745 +                       xMax = -180.;
9746 +
9747 +               if (yMin < 0.)
9748 +                       yMin = 0.;
9749 +               if (yMax > 90.)
9750 +                       yMax = 90.;
9751 +       }
9752 +       OCTDestroyCoordinateTransformation(poCT);
9753 +       IsOK = TRUE;
9754 +       return BoundingBox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
9755 +}
9756 +
9757 +BoundingBox BoundingBox::Transform(const double GeoTransform[])
9758 +{
9759 +       My2DPoint llPt;
9760 +       My2DPoint urPt;
9761 +       llPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_LowerLeftPT.mi_X + GeoTransform[2] * mo_LowerLeftPT.mi_Y;
9762 +       llPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_LowerLeftPT.mi_X + GeoTransform[5] * mo_LowerLeftPT.mi_Y;
9763 +       urPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_UpperRightPT.mi_X + GeoTransform[2] * mo_UpperRightPT.mi_Y;
9764 +       urPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_UpperRightPT.mi_X + GeoTransform[5] * mo_UpperRightPT.mi_Y;
9765 +
9766 +       return BoundingBox(llPt,urPt,mo_CRS);
9767 +}
9768 +
9769 +/**
9770 + * Transform Coordinates of lowercorner_left and upcorner_right
9771 + * lowLeft, upRight.
9772 + * the return value has considered the case of image area crossing 180/-180 longitude line,
9773 + * so lowLeft.x maybe bigger than upRight.x
9774 + */
9775 +CPLErr CPL_STDCALL bBox_transFormmate(OGRSpatialReference& oSrcCRS,
9776 +               OGRSpatialReference& oDesCRS, My2DPoint& lowLeft, My2DPoint& upRight)
9777 +{
9778 +       if (oSrcCRS.IsSame(&oDesCRS))
9779 +               return CE_None;
9780 +
9781 +       OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&oSrcCRS, &oDesCRS);
9782 +       if (poCT == NULL)
9783 +       {
9784 +               SetWCS_ErrorLocator("bBox_transFormmate()");
9785 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create \"OGRCoordinateTransformation\"");
9786 +               return CE_Failure;
9787 +       }
9788 +
9789 +       double xdes = (upRight.mi_X - lowLeft.mi_X) / 100;
9790 +       if (oSrcCRS.IsGeographic() && upRight.mi_X < lowLeft.mi_X && lowLeft.mi_X > 0 && upRight.mi_X < 0)
9791 +       {
9792 +               xdes = (360 + upRight.mi_X - lowLeft.mi_X) / 100;
9793 +       }
9794 +
9795 +       vector<double> x, y;
9796 +       //up and down edge
9797 +       for (double stepX = lowLeft.mi_X; stepX < upRight.mi_X; stepX += xdes)
9798 +       {
9799 +               x.push_back(stepX);
9800 +               y.push_back(upRight.mi_Y);
9801 +               x.push_back(stepX);
9802 +               y.push_back(lowLeft.mi_Y);
9803 +       }
9804 +       x.push_back(upRight.mi_X);
9805 +       y.push_back(upRight.mi_Y);
9806 +       x.push_back(upRight.mi_X);
9807 +       y.push_back(lowLeft.mi_Y);
9808 +
9809 +       double yMin = numeric_limits<double>::max();
9810 +       double yMax = -numeric_limits<double>::max();
9811 +
9812 +       int k = 0;
9813 +       vector<int> bSuccess;
9814 +       vector<double> tmpX;
9815 +       vector<double> tmpY;
9816 +
9817 +       for (unsigned int i = 0; i < x.size(); i++)
9818 +       {
9819 +               tmpX.push_back(x[i]);
9820 +               tmpY.push_back(y[i]);
9821 +               bSuccess.push_back(0);
9822 +       }
9823 +
9824 +       poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
9825 +
9826 +       for (unsigned int n = 0; n < x.size(); n++)
9827 +       {
9828 +               if (bSuccess[n])
9829 +               {
9830 +                       ++k;
9831 +                       yMin = MIN(yMin,tmpY[n]);
9832 +                       yMax = MAX(yMax,tmpY[n]);
9833 +               }
9834 +       }
9835 +
9836 +       if (k < 80)
9837 +       {
9838 +               OCTDestroyCoordinateTransformation(poCT);
9839 +               SetWCS_ErrorLocator("bBox_transFormmate()");
9840 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
9841 +               return CE_Failure;
9842 +       }
9843 +
9844 +       double xMin;
9845 +       double xMax;
9846 +
9847 +       //find xmin on left edge and xmax on right edge
9848 +       double tmpPTX[2];
9849 +       double tmpPTY[2];
9850 +       int isOK[2];
9851 +
9852 +       tmpPTX[0] = lowLeft.mi_X;
9853 +       tmpPTX[1] = lowLeft.mi_X;
9854 +       tmpPTY[0] = upRight.mi_Y;
9855 +       tmpPTY[1] = lowLeft.mi_Y;
9856 +
9857 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
9858 +       if (isOK[0] && isOK[1])
9859 +       {
9860 +               xMin = MIN(tmpPTX[0],tmpPTX[1]);
9861 +       }
9862 +       else
9863 +       {
9864 +               OCTDestroyCoordinateTransformation(poCT);
9865 +               SetWCS_ErrorLocator("bBox_transFormmate()");
9866 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
9867 +               return CE_Failure;
9868 +       }
9869 +
9870 +       tmpPTX[0] = upRight.mi_X;
9871 +       tmpPTX[1] = upRight.mi_X;
9872 +       tmpPTY[0] = upRight.mi_Y;
9873 +       tmpPTY[1] = lowLeft.mi_Y;
9874 +
9875 +       poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
9876 +       if (isOK[0] && isOK[1])
9877 +       {
9878 +               xMax = MAX(tmpPTX[0],tmpPTX[1]);
9879 +       }
9880 +       else
9881 +       {
9882 +               SetWCS_ErrorLocator("bBox_transFormmate()");
9883 +               OCTDestroyCoordinateTransformation(poCT);
9884 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
9885 +               return CE_Failure;
9886 +       }
9887 +       
9888 +       lowLeft.mi_X = xMin;
9889 +       lowLeft.mi_Y = yMin;
9890 +       upRight.mi_X = xMax;
9891 +       upRight.mi_Y = yMax;
9892 +
9893 +       if (oDesCRS.IsGeographic())
9894 +       {
9895 +               if (xMin > 180)
9896 +                       lowLeft.mi_X = xMin - 360;
9897 +               if (xMax > 180)
9898 +                       upRight.mi_X = xMax - 360;
9899 +
9900 +               if (lowLeft.mi_X >= 180.)
9901 +                       lowLeft.mi_X = 180.;
9902 +               if (lowLeft.mi_X <= -180.)
9903 +                       lowLeft.mi_X = -180.;
9904 +               if (upRight.mi_X >= 180.)
9905 +                       upRight.mi_X = 180.;
9906 +               if (upRight.mi_X <= -180.)
9907 +                       upRight.mi_X = -180.;
9908 +
9909 +               if (lowLeft.mi_Y <= -90.)
9910 +                       lowLeft.mi_Y = -90.;
9911 +               if (upRight.mi_Y >= 90.)
9912 +                       upRight.mi_Y = 90.;
9913 +       }
9914 +       OCTDestroyCoordinateTransformation(poCT);
9915 +
9916 +       return CE_None;
9917 +}
9918 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/db/dbe4c7bb62ab52db2ffe9a04dcc82422b69d5bff.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/db/dbe4c7bb62ab52db2ffe9a04dcc82422b69d5bff.svn-base
9919 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/db/dbe4c7bb62ab52db2ffe9a04dcc82422b69d5bff.svn-base     1970-01-01 01:00:00.000000000 +0100
9920 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/db/dbe4c7bb62ab52db2ffe9a04dcc82422b69d5bff.svn-base  2014-03-03 15:47:37.980232932 +0100
9921 @@ -0,0 +1,124 @@
9922 +/******************************************************************************
9923 + * $Id: NC_GOES_Dataset.h 2011-07-19 16:24:00Z $
9924 + *
9925 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
9926 + *                      for Earth Observation: Open Source Reference Implementation
9927 + * Purpose:  NC_GOES_Dataset class definition
9928 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
9929 + *
9930 + ******************************************************************************
9931 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
9932 + *
9933 + * Permission is hereby granted, free of charge, to any person obtaining a
9934 + * copy of this software and associated documentation files (the "Software"),
9935 + * to deal in the Software without restriction, including without limitation
9936 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9937 + * and/or sell copies of the Software, and to permit persons to whom the
9938 + * Software is furnished to do so, subject to the following conditions:
9939 + *
9940 + * The above copyright notice and this permission notice shall be included
9941 + * in all copies or substantial portions of the Software.
9942 + *
9943 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
9944 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9945 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
9946 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9947 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
9948 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
9949 + * DEALINGS IN THE SOFTWARE.
9950 + ****************************************************************************/
9951 +
9952 +#ifndef NC_GOES_DATASET_H_
9953 +#define NC_GOES_DATASET_H_
9954 +
9955 +#include <string>
9956 +#include "AbstractDataset.h"
9957 +#include "wcsUtil.h"
9958 +
9959 +using namespace std;
9960 +
9961 +/************************************************************************/
9962 +/* ==================================================================== */
9963 +/*                           NC_GOES_Dataset                            */
9964 +/* ==================================================================== */
9965 +/************************************************************************/
9966 +
9967 +//! NC_GOES_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
9968 +
9969 +/**
9970 + * \class NC_GOES_Dataset "NC_GOES_Dataset.h"
9971 + *
9972 + * GOES satellites provide the kind of continuous monitoring necessary for
9973 + * intensive data analysis. They circle the Earth in a geosynchronous orbit,
9974 + * which means they orbit the equatorial plane of the Earth at a speed
9975 + * matching the Earth's rotation. This allows them to hover continuously
9976 + * over one position on the surface. The geosynchronous plane is about
9977 + * 35,800 km (22,300 miles) above the Earth, high enough to allow the
9978 + * satellites a full-disc view of the Earth. Because they stay above a
9979 + * fixed spot on the surface, they provide a constant vigil for the atmospheric
9980 + * "triggers" for severe weather conditions such as tornadoes, flash floods,
9981 + * hail storms, and hurricanes. When these conditions develop the GOES
9982 + * satellites are able to monitor storm development and track their movements.
9983 + *
9984 + * GOES satellite imagery is also used to estimate rainfall during
9985 + * the thunderstorms and hurricanes for flash flood warnings, as well
9986 + * as estimates snowfall accumulations and overall extent of snow cover.
9987 + * Such data help meteorologists issue winter storm warnings and spring
9988 + * snow melt advisories. Satellite sensors also detect ice fields and map
9989 + * the movements of sea and lake ice.
9990 + *
9991 + * For more inforamtion about NOAA GOES data, please access
9992 + * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
9993 + *
9994 + * NC_GOES_Dataset is a subclass of AbstractDataset, which is used to
9995 + * process GOES Imager and Sounder products.
9996 + */
9997 +
9998 +class NC_GOES_Dataset : public AbstractDataset
9999 +{
10000 +protected:
10001 +       string  m_ncLatDataSetName;
10002 +       string  m_ncLonDataSetName;
10003 +       string  m_ncCoverageIDName;
10004 +       int     mi_RectifiedImageXSize;
10005 +       int     mi_RectifiedImageYSize;
10006 +       int             mi_GoesSrcImageXSize;
10007 +       int             mi_GoesSrcImageYSize;
10008 +
10009 +       double  mb_LatLonBBox[4];
10010 +       double  mdSrcGeoMinX;
10011 +       double  mdSrcGeoMinY;
10012 +       double  mdSrcGeoMaxX;
10013 +       double  mdSrcGeoMaxY;
10014 +
10015 +       vector<GDAL_GCP>                m_gdalGCPs;
10016 +
10017 +public:
10018 +       CPLErr SetGCPGeoRef4VRTDataset(GDALDataset* );
10019 +       CPLErr SetGeoBBoxAndGCPs(GDALDataset* hSrcDS);
10020 +       CPLErr RectifyGOESDataSet();
10021 +       CPLErr setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue);
10022 +
10023 +       int isValidLatitude(const double &lat)
10024 +       {
10025 +               return (lat >= -90 && lat <= 90);
10026 +       }
10027 +       int isValidLongitude(const double &lon)
10028 +       {
10029 +               return (lon >= -180 && lon <= 180);
10030 +       }
10031 +
10032 +       virtual CPLErr SetGeoTransform();
10033 +       virtual CPLErr SetMetaDataList(GDALDataset* hSrcDS);
10034 +       virtual CPLErr SetNativeCRS();
10035 +       virtual CPLErr SetGDALDataset(const int isSimple=0);
10036 +       virtual CPLErr InitialDataset(const int isSimple=0);
10037 +       virtual CPLErr GetGeoMinMax(double geoMinMax[]);
10038 +
10039 +public:
10040 +       NC_GOES_Dataset();
10041 +       NC_GOES_Dataset(const string& id, vector<int>  &rBandList);
10042 +       virtual ~NC_GOES_Dataset();
10043 +};
10044 +
10045 +#endif /* NC_GOES_DATASET_H_ */
10046 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/ed/ed878e0243e84e5e05dc18b0ec24d13ce9146358.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/ed/ed878e0243e84e5e05dc18b0ec24d13ce9146358.svn-base
10047 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/ed/ed878e0243e84e5e05dc18b0ec24d13ce9146358.svn-base     1970-01-01 01:00:00.000000000 +0100
10048 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/ed/ed878e0243e84e5e05dc18b0ec24d13ce9146358.svn-base  2014-03-03 15:47:37.806899605 +0100
10049 @@ -0,0 +1,730 @@
10050 +
10051 +// -*- mode: c++; c-basic-offset:4 -*-
10052 +
10053 +// This file is part of libdap, A C++ implementation of the OPeNDAP Data
10054 +// Access Protocol.
10055 +
10056 +// Copyright (c) 2012 OPeNDAP, Inc.
10057 +// Author: James Gallagher <jgallagher@opendap.org>
10058 +//
10059 +// This library is free software; you can redistribute it and/or
10060 +// modify it under the terms of the GNU Lesser General Public
10061 +// License as published by the Free Software Foundation; either
10062 +// version 2.1 of the License, or (at your option) any later version.
10063 +//
10064 +// This library is distributed in the hope that it will be useful,
10065 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
10066 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10067 +// Lesser General Public License for more details.
10068 +//
10069 +// You should have received a copy of the GNU Lesser General Public
10070 +// License along with this library; if not, write to the Free Software
10071 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10072 +//
10073 +// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
10074 +
10075 +#include <cstdlib>
10076 +
10077 +#define DODS_DEBUG
10078 +
10079 +#include "DAP_Dataset.h"
10080 +
10081 +#include "Array.h"
10082 +#include "Grid.h"
10083 +#include "Float64.h"
10084 +
10085 +#include "ce_functions.h"
10086 +#include "util.h"
10087 +#include "debug.h"
10088 +
10089 +using namespace libdap;
10090 +using namespace std;
10091 +
10092 +#if 0
10093 +#define GOES_TIME_DEBUG FALSE
10094 +#endif
10095 +
10096 +namespace libdap {
10097 +
10098 +DAP_Dataset::DAP_Dataset()
10099 +{
10100 +}
10101 +
10102 +/************************************************************************/
10103 +/*                           ~DAP_Dataset()                             */
10104 +/************************************************************************/
10105 +
10106 +/**
10107 + * \brief Destroy an open DAP_Dataset object.
10108 + *
10109 + * This is the accepted method of closing a DAP_Dataset dataset and
10110 + * deallocating all resources associated with it.
10111 + */
10112 +
10113 +DAP_Dataset::~DAP_Dataset()
10114 +{
10115 +}
10116 +
10117 +/************************************************************************/
10118 +/*                           DAP_Dataset()                              */
10119 +/************************************************************************/
10120 +
10121 +/**
10122 + * \brief Create an DAP_Dataset object.
10123 + *
10124 + * This is the accepted method of creating a DAP_Dataset object and
10125 + * allocating all resources associated with it.
10126 + *
10127 + * @param id The coverage identifier.
10128 + *
10129 + * @param rBandList The field list selected for this coverage. For TRMM
10130 + * daily data, the user could specify multiple days range in request.
10131 + * Each day is seemed as one field.
10132 + *
10133 + * @return A DAP_Dataset object.
10134 + */
10135 +
10136 +DAP_Dataset::DAP_Dataset(const string& id, vector<int> &rBandList) :
10137 +        AbstractDataset(id, rBandList)
10138 +{
10139 +    md_MissingValue = 0;
10140 +    mb_GeoTransformSet = FALSE;
10141 +}
10142 +
10143 +/**
10144 + * @brief Initialize a DAP Dataset using Array objects already read.
10145 + *
10146 + *
10147 + */
10148 +
10149 +DAP_Dataset::DAP_Dataset(Array *src, Array *lat, Array *lon) :
10150 +        AbstractDataset(), m_src(src), m_lat(lat), m_lon(lon)
10151 +{
10152 +#if 1
10153 +    // TODO Remove these?
10154 +    DBG(cerr << "Registering GDAL drivers" << endl);
10155 +    GDALAllRegister();
10156 +    OGRRegisterAll();
10157 +#endif
10158 +
10159 +    CPLSetErrorHandler(CPLQuietErrorHandler);
10160 +
10161 +    // Read this from the 'missing_value' or '_FillValue' attributes
10162 +    string missing_value = m_src->get_attr_table().get_attr("missing_value");
10163 +    if (missing_value.empty())
10164 +        missing_value = m_src->get_attr_table().get_attr("_FillValue");
10165 +
10166 +    if (!missing_value.empty())
10167 +        md_MissingValue = atof(missing_value.c_str());
10168 +    else
10169 +        md_MissingValue = 0;
10170 +
10171 +    mb_GeoTransformSet = FALSE;
10172 +}
10173 +
10174 +/************************************************************************/
10175 +/*                           InitialDataset()                           */
10176 +/************************************************************************/
10177 +
10178 +/**
10179 + * \brief Initialize the GOES dataset with NetCDF format.
10180 +
10181 + * This method is the implementation for initializing a GOES dataset with NetCDF format.
10182 + * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
10183 + * will be called to initialize an GOES dataset.
10184 + *
10185 + * @note To use this, call this method and then access the GDALDataset that
10186 + * contains the reprojected array using maptr_DS.get().
10187 + *
10188 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
10189 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
10190 + *
10191 + * @return CE_None on success or CE_Failure on failure.
10192 + */
10193 +
10194 +CPLErr DAP_Dataset::InitialDataset(const int isSimple)
10195 +{
10196 +    DBG(cerr << "In InitialDataset" << endl);
10197 +
10198 +    // Might break that operation out so the remap is a separate call
10199 +    if (CE_None != SetNativeCRS() || CE_None != SetGeoTransform())
10200 +        throw Error("Could not set the dataset native CRS or the GeoTransform.");
10201 +
10202 +    DBG(cerr << "Before SetGDALDataset" << endl);
10203 +
10204 +    if (CE_None != SetGDALDataset(isSimple)) {
10205 +        GDALClose(maptr_DS.release());
10206 +        throw Error("Could not reproject the dataset.");
10207 +    }
10208 +
10209 +    return CE_None;
10210 +}
10211 +
10212 +/************************************************************************/
10213 +/*                            GetDAPArray()                            */
10214 +/************************************************************************/
10215 +
10216 +/**
10217 + * @brief Build a DAP Array from the GDALDataset
10218 + */
10219 +Array *DAP_Dataset::GetDAPArray()
10220 +{
10221 +    DBG(cerr << "In GetDAPArray" << endl);
10222 +    DBG(cerr << "maptr_DS: " << maptr_DS.get() << endl);
10223 +    DBG(cerr << "raster band count: " << maptr_DS->GetRasterCount() << endl);
10224 +
10225 +    // There should be just one band
10226 +    if (maptr_DS->GetRasterCount() != 1)
10227 +        throw Error("In function swath2grid(), expected a single raster band.");
10228 +
10229 +    // Get the x and y dimensions of the raster band
10230 +    int x = maptr_DS->GetRasterXSize();
10231 +    int y = maptr_DS->GetRasterYSize();
10232 +    GDALRasterBand *rb = maptr_DS->GetRasterBand(1);
10233 +    if (!rb)
10234 +        throw Error("In function swath2grid(), could not access the raster data.");
10235 +
10236 +    // Since the DAP_Dataset code works with all data values as doubles,
10237 +    // Assume the raster band has GDAL type GDT_Float64, but test anyway
10238 +    if (GDT_Float64 != rb->GetRasterDataType())
10239 +        throw Error("In function swath2grid(), expected raster data to be of type double.");
10240 +
10241 +    DBG(cerr << "Destination array will have dimensions: " << x << ", " << y << endl);
10242 +
10243 +    Array *a = new Array(m_src->name(), new Float64(m_src->name()));
10244 +
10245 +    // Make the result array have two dimensions
10246 +    Array::Dim_iter i = m_src->dim_begin();
10247 +
10248 +    a->append_dim(x, m_src->dimension_name(i));
10249 +    ++i;
10250 +
10251 +    if (i == m_src->dim_end())
10252 +        throw Error("In function swath2grid(), expected source array to have two dimensions (2).");
10253 +
10254 +    a->append_dim(y, m_src->dimension_name(i));
10255 +
10256 +    // Poke in the data values
10257 +    /* RasterIO (   GDALRWFlag  eRWFlag,
10258 +    int     nXOff,
10259 +    int     nYOff,
10260 +    int     nXSize,
10261 +    int     nYSize,
10262 +    void *  pData,
10263 +    int     nBufXSize,
10264 +    int     nBufYSize,
10265 +    GDALDataType    eBufType,
10266 +    int     nPixelSpace,
10267 +    int     nLineSpace
10268 +    ) */
10269 +    vector<double> data(x * y);
10270 +    rb->RasterIO(GF_Read, 0, 0, x, y, &data[0], x, y, GDT_Float64, 0, 0);
10271 +
10272 +    // NB: set_value() copies into new storage
10273 +    a->set_value(data, data.size());
10274 +
10275 +    // Now poke in some attributes
10276 +    // TODO Make these CF attributes
10277 +    string projection_info = maptr_DS->GetProjectionRef();
10278 +    string gcp_projection_info = maptr_DS->GetGCPProjection();
10279 +
10280 +    // This sets the instance variable that holds the geotransform coefs. These
10281 +    // are needed by the GetDAPGrid() method.
10282 +    if (CE_None != maptr_DS->GetGeoTransform (m_geo_transform_coef))
10283 +        throw Error("In function swath2grid(), could not access the geo transform data.");
10284 +
10285 +    DBG(cerr << "projection_info: " << projection_info << endl);
10286 +    DBG(cerr << "gcp_projection_info: " << gcp_projection_info << endl);
10287 +    DBG(cerr << "geo_transform coefs: " << double_to_string(m_geo_transform_coef[0]) << endl);
10288 +
10289 +    AttrTable &attr = a->get_attr_table();
10290 +    attr.append_attr("projection", "String", projection_info);
10291 +    attr.append_attr("gcp_projection", "String", gcp_projection_info);
10292 +    for (unsigned int i = 0; i < sizeof(m_geo_transform_coef); ++i) {
10293 +        attr.append_attr("geo_transform_coefs", "String", double_to_string(m_geo_transform_coef[i]));
10294 +    }
10295 +
10296 +    return a;
10297 +}
10298 +
10299 +/************************************************************************/
10300 +/*                            GetDAPGrid()                              */
10301 +/************************************************************************/
10302 +
10303 +/**
10304 + * @brief Build a DAP Grid from the GDALDataset
10305 + */
10306 +Grid *DAP_Dataset::GetDAPGrid()
10307 +{
10308 +    DBG(cerr << "In GetDAPGrid" << endl);
10309 +
10310 +    Array *a = GetDAPArray();
10311 +    Array::Dim_iter i = a->dim_begin();
10312 +    int lon_size = a->dimension_size(i);
10313 +    int lat_size = a->dimension_size(++i);
10314 +
10315 +    Grid *g = new Grid(a->name());
10316 +    g->add_var_nocopy(a, array);
10317 +
10318 +    // Add maps; assume lon, lat; only two dimensions
10319 +    Array *lon = new Array("longitude", new Float64("longitude"));
10320 +    lon->append_dim(lon_size);
10321 +
10322 +    vector<double> data(max(lon_size, lat_size)); // (re)use this for both lon and lat
10323 +
10324 +    // Compute values
10325 +    // u = a*x + b*y
10326 +    // v = c*x + d*y
10327 +    // u,v --> x,y --> lon,lat
10328 +    // The constants a, b, c, d are given by the 1, 2, 4, and 5 entries in the geotransform array.
10329 +
10330 +    if (m_geo_transform_coef[2] != 0)
10331 +       throw Error("The transformed data's Geographic projection should not be rotated.");
10332 +    for (int j = 0; j < lon_size; ++j) {
10333 +        data[j] = m_geo_transform_coef[1] * j + m_geo_transform_coef[0];
10334 +    }
10335 +
10336 +    // load (copy) values
10337 +    lon->set_value(&data[0], lon_size);
10338 +    // Set the map
10339 +    g->add_var_nocopy(lon, maps);
10340 +
10341 +    // Now do the latitude map
10342 +    Array *lat = new Array("latitude", new Float64("latitude"));
10343 +    lat->append_dim(lat_size);
10344 +
10345 +    if (m_geo_transform_coef[4] != 0)
10346 +       throw Error("The transformed data's Geographic projection should not be rotated.");
10347 +    for (int k = 0; k < lat_size; ++k) {
10348 +        data[k] = m_geo_transform_coef[5] * k + m_geo_transform_coef[3];
10349 +    }
10350 +
10351 +    lat->set_value(&data[0], lat_size);
10352 +    g->add_var_nocopy(lat, maps);
10353 +
10354 +    return g;
10355 +}
10356 +
10357 +/************************************************************************/
10358 +/*                            SetNativeCRS()                            */
10359 +/************************************************************************/
10360 +
10361 +/**
10362 + * \brief Set the Native CRS for a GOES dataset.
10363 + *
10364 + * The method will set the CRS for a GOES dataset as an native CRS.
10365 + *
10366 + * Since the original GOES data adopt satellite CRS to recored its value,
10367 + * like MODIS swath data, each data point has its corresponding latitude
10368 + * and longitude value, those coordinates could be fetched in another two fields.
10369 + *
10370 + * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
10371 + * both the latitude and longitude are existed.
10372 + *
10373 + * @return CE_None on success or CE_Failure on failure.
10374 + */
10375 +
10376 +CPLErr DAP_Dataset::SetNativeCRS()
10377 +{
10378 +    DBG(cerr << "In SetNativeCRS" << endl);
10379 +
10380 +    mo_NativeCRS.SetWellKnownGeogCS("WGS84");
10381 +
10382 +    return CE_None;
10383 +}
10384 +
10385 +/************************************************************************/
10386 +/*                           SetGeoTransform()                          */
10387 +/************************************************************************/
10388 +
10389 +/**
10390 + * \brief Set the affine GeoTransform matrix for a GOES data.
10391 + *
10392 + * The method will set a GeoTransform matrix for a GOES data
10393 + * by parsing the coordinates values existed in longitude and latitude field.
10394 + *
10395 + * The CRS for the bounding box is EPSG:4326.
10396 + *
10397 + * @return CE_None on success or CE_Failure on failure.
10398 + */
10399 +
10400 +CPLErr DAP_Dataset::SetGeoTransform()
10401 +{
10402 +    DBG(cerr << "In SetGeoTransform" << endl);
10403 +
10404 +    // TODO Look at this; is this correct
10405 +    // Assume the array is two dimensional
10406 +    Array::Dim_iter i = m_src->dim_begin();
10407 +#if 0
10408 +    // ORIGINAL code; maybe wrong
10409 +    int nXSize = m_src->dimension_size(i, true);
10410 +    int nYSize = m_src->dimension_size(i + 1, true);
10411 +#endif
10412 +    // Data are in row-major order, so the first dim is the Y-axis value
10413 +    int nYSize = m_src->dimension_size(i, true);
10414 +    int nXSize = m_src->dimension_size(i + 1, true);
10415 +
10416 +    mi_SrcImageXSize = nXSize;
10417 +    mi_SrcImageYSize = nYSize;
10418 +
10419 +    SetGeoBBoxAndGCPs(nXSize, nYSize);
10420 +
10421 +    double resX, resY;
10422 +    if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
10423 +        resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
10424 +    else
10425 +        resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
10426 +
10427 +    resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (nYSize - 1);
10428 +
10429 +    double res = MIN(resX, resY);
10430 +
10431 +    if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
10432 +        mi_RectifiedImageXSize = (int) ((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
10433 +    else
10434 +        mi_RectifiedImageXSize = (int) ((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
10435 +
10436 +    mi_RectifiedImageYSize = (int) fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
10437 +
10438 +    DBG(cerr << "Source image size: " << nXSize << ", " << nYSize << endl);
10439 +    DBG(cerr << "Rectified image size: " << mi_RectifiedImageXSize << ", " << mi_RectifiedImageYSize << endl);
10440 +
10441 +    md_Geotransform[0] = mdSrcGeoMinX;
10442 +    md_Geotransform[1] = res;
10443 +    md_Geotransform[2] = 0;
10444 +    md_Geotransform[3] = mdSrcGeoMaxY;
10445 +    md_Geotransform[4] = 0;
10446 +    md_Geotransform[5] = -res;
10447 +    mb_GeoTransformSet = TRUE;
10448 +
10449 +    return CE_None;
10450 +}
10451 +
10452 +/************************************************************************/
10453 +/*                         SetGeoBBoxAndGCPs()                          */
10454 +/************************************************************************/
10455 +
10456 +/**
10457 + * \brief Set the native geographical bounding box and GCP array for a GOES data.
10458 + *
10459 + * The method will set the native geographical bounding box
10460 + * by comparing the coordinates values existed in longitude and latitude field.
10461 + *
10462 + * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
10463 + *
10464 + * @return CE_None on success or CE_Failure on failure.
10465 + */
10466 +
10467 +void DAP_Dataset::SetGeoBBoxAndGCPs(int nXSize, int nYSize)
10468 +{
10469 +    DBG(cerr << "In SetGeoBBoxAndGCPs" << endl);
10470 +
10471 +    // reuse the Dim_iter for both lat and lon arrays
10472 +    Array::Dim_iter i = m_lat->dim_begin();
10473 +    int nLatXSize = m_lat->dimension_size(i, true);
10474 +    int nLatYSize = m_lat->dimension_size(i + 1, true);
10475 +    i = m_lon->dim_begin();
10476 +    int nLonXSize = m_lon->dimension_size(i, true);
10477 +    int nLonYSize = m_lon->dimension_size(i + 1, true);
10478 +
10479 +    if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
10480 +        throw Error("The size of latitude/longitude and data field does not match.");
10481 +
10482 +#if 0
10483 +    /*
10484 +     * Re-sample Standards:
10485 +     * Height | Width
10486 +     * (0, 500)                every other one pixel
10487 +     * [500, 1000)             every other two pixels
10488 +     * [1000,1500)             every other three pixels
10489 +     * [1500,2000)             every other four pixels
10490 +     * ... ...
10491 +     */
10492 +
10493 +    int xSpace = 1;
10494 +    int ySpace = 1;
10495 +    //setResampleStandard(poVDS, xSpace, ySpace);
10496 +
10497 +    // TODO understand how GMU picked this value.
10498 +    // xSpace and ySpace are the stride values for sampling in
10499 +    // the x and y dimensions.
10500 +    const int RESAMPLE_STANDARD = 500;
10501 +
10502 +    xSpace = int(nXSize / RESAMPLE_STANDARD) + 2;
10503 +    ySpace = int(nYSize / RESAMPLE_STANDARD) + 2;
10504 +#endif
10505 +
10506 +    m_lat->read();
10507 +    m_lon->read();
10508 +    double *dataLat = extract_double_array(m_lat);
10509 +    double *dataLon = extract_double_array(m_lon);
10510 +
10511 +    DBG(cerr << "Past lat/lon data read" << endl);
10512 +
10513 +    try {
10514 +
10515 +        mdSrcGeoMinX = 360;
10516 +        mdSrcGeoMaxX = -360;
10517 +        mdSrcGeoMinY = 90;
10518 +        mdSrcGeoMaxY = -90;
10519 +
10520 +        // Sample every other row and column
10521 +        int xSpace = 2;
10522 +        int ySpace = 2;
10523 +
10524 +        int nGCPs = 0;
10525 +        GDAL_GCP gdalCGP;
10526 +
10527 +        for (int iLine = 0; iLine < nYSize - ySpace; iLine += ySpace) {
10528 +            for (int iPixel = 0; iPixel < nXSize - xSpace; iPixel += xSpace) {
10529 +                double x = *(dataLon + (iLine * nYSize) + iPixel);
10530 +                double y = *(dataLat + (iLine * nYSize) + iPixel);
10531 +
10532 +                if (isValidLongitude(x) && isValidLatitude(y)) {
10533 +                    char pChr[64];
10534 +                    snprintf(pChr, 64, "%d", ++nGCPs);
10535 +                    GDALInitGCPs(1, &gdalCGP);
10536 +                    gdalCGP.pszId = strdup(pChr);
10537 +                    gdalCGP.pszInfo = strdup("");
10538 +                    gdalCGP.dfGCPLine = iLine;
10539 +                    gdalCGP.dfGCPPixel = iPixel;
10540 +                    gdalCGP.dfGCPX = x;
10541 +                    gdalCGP.dfGCPY = y;
10542 +
10543 +                    DBG2(cerr << "iLine, iPixel: " << iLine << ", " << iPixel << " --> x,y: " << x << ", " << y << endl);
10544 +
10545 +                    gdalCGP.dfGCPZ = 0;
10546 +                    m_gdalGCPs.push_back(gdalCGP);
10547 +
10548 +                    mdSrcGeoMinX = MIN(mdSrcGeoMinX, gdalCGP.dfGCPX);
10549 +                    mdSrcGeoMaxX = MAX(mdSrcGeoMaxX, gdalCGP.dfGCPX);
10550 +                    mdSrcGeoMinY = MIN(mdSrcGeoMinY, gdalCGP.dfGCPY);
10551 +                    mdSrcGeoMaxY = MAX(mdSrcGeoMaxY, gdalCGP.dfGCPY);
10552 +                }
10553 +            }
10554 +        }
10555 +    }
10556 +    catch (...) {
10557 +        delete[] dataLat;
10558 +        delete[] dataLon;
10559 +        throw;
10560 +    }
10561 +
10562 +    delete[] dataLat;
10563 +    delete[] dataLon;
10564 +
10565 +    DBG(cerr << "Leaving SetGeoBBoxAndGCPs" << endl);
10566 +}
10567 +
10568 +/************************************************************************/
10569 +/*                           SetGDALDataset()                           */
10570 +/************************************************************************/
10571 +
10572 +/**
10573 + * \brief Make a 'memory' dataset with one band
10574 + *
10575 + * @return CE_None on success or CE_Failure on failure.
10576 + */
10577 +
10578 +CPLErr DAP_Dataset::SetGDALDataset(const int isSimple)
10579 +{
10580 +    DBG(cerr << "In SetGDALDataset" << endl);
10581 +
10582 +    // NB: mi_RectifiedImageXSize & Y are set in SetGeoTransform()
10583 +    GDALDataType eBandType = GDT_Float64;
10584 +    // VRT, which was used in the original sample code, is not supported in this context, so I used MEM
10585 +    GDALDriverH poDriver = GDALGetDriverByName("MEM");
10586 +    if (!poDriver) {
10587 +        throw Error("Failed to get MEM driver (" + string(CPLGetLastErrorMsg()) + ").");
10588 +    }
10589 +
10590 +    GDALDataset* satDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
10591 +            1, eBandType, NULL);
10592 +    if (!satDataSet) {
10593 +        GDALClose(poDriver);
10594 +        throw Error("Failed to create MEM dataSet (" + string(CPLGetLastErrorMsg()) + ").");
10595 +    }
10596 +
10597 +    GDALRasterBand *poBand = satDataSet->GetRasterBand(1);
10598 +    poBand->SetNoDataValue(md_MissingValue);
10599 +
10600 +    m_src->read();
10601 +    double *data = extract_double_array(m_src);
10602 +    if (CE_None != poBand->RasterIO(GF_Write, 0, 0, mi_RectifiedImageXSize, mi_RectifiedImageYSize, data,
10603 +                    mi_SrcImageXSize, mi_SrcImageYSize, eBandType, 0, 0)) {
10604 +        GDALClose((GDALDatasetH) satDataSet);
10605 +        throw Error("Failed to set satellite data band to MEM DataSet (" + string(CPLGetLastErrorMsg()) + ").");
10606 +    }
10607 +    delete[] data;
10608 +
10609 +    //set GCPs for this VRTDataset
10610 +    if (CE_None != SetGCPGeoRef4VRTDataset(satDataSet)) {
10611 +        GDALClose((GDALDatasetH) satDataSet);
10612 +        throw Error("Could not georeference the virtual dataset (" + string(CPLGetLastErrorMsg()) + ").");
10613 +    }
10614 +
10615 +    DBG(cerr << "satDataSet: " << satDataSet << endl);
10616 +
10617 +    maptr_DS.reset(satDataSet);
10618 +
10619 +    if (isSimple)
10620 +        return CE_None;
10621 +
10622 +    return RectifyGOESDataSet();
10623 +}
10624 +
10625 +/************************************************************************/
10626 +/*                       SetGCPGeoRef4VRTDataset()                      */
10627 +/************************************************************************/
10628 +
10629 +/**
10630 + * \brief Set the GCP array for the VRT dataset.
10631 + *
10632 + * This method is used to set the GCP array to created VRT dataset based on GDAL
10633 + * method SetGCPs().
10634 + *
10635 + * @param poVDS The VRT dataset.
10636 + *
10637 + * @return CE_None on success or CE_Failure on failure.
10638 + */
10639 +
10640 +CPLErr DAP_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
10641 +{
10642 +    char* psTargetSRS;
10643 +    mo_NativeCRS.exportToWkt(&psTargetSRS);
10644 +
10645 +#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
10646 +    if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS)) {
10647 +        OGRFree(psTargetSRS);
10648 +        throw Error("Failed to set GCPs.");
10649 +    }
10650 +#else
10651 +    {
10652 +        if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
10653 +        {
10654 +            OGRFree( psTargetSRS );
10655 +            throw Error("Failed to set GCPs.");
10656 +        }
10657 +    }
10658 +#endif
10659 +
10660 +    OGRFree(psTargetSRS);
10661 +
10662 +    return CE_None;
10663 +}
10664 +#if 0
10665 +/************************************************************************/
10666 +/*                        SetMetaDataList()                             */
10667 +/************************************************************************/
10668 +
10669 +/**
10670 + * \brief Set the metadata list for this coverage.
10671 + *
10672 + * The method will set the metadata list for the coverage based on its
10673 + * corresponding GDALDataset object.
10674 + *
10675 + * @param hSrc the GDALDataset object corresponding to coverage.
10676 + *
10677 + * @return CE_None on success or CE_Failure on failure.
10678 + */
10679 +
10680 +CPLErr DAP_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
10681 +{
10682 +    // TODO Remove
10683 +#if 0
10684 +    mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
10685 +    mv_MetaDataList.push_back("unit=GVAR");
10686 +    mv_MetaDataList.push_back("FillValue=0");
10687 +    ms_FieldQuantityDef = "GVAR";
10688 +    ms_AllowRanges = "0 65535";
10689 +    ms_CoveragePlatform = "GOES-11";
10690 +    ms_CoverageInstrument = "GOES-11";
10691 +    ms_CoverageSensor = "Imager";
10692 +#endif
10693 +
10694 +    return CE_None;
10695 +}
10696 +#endif
10697 +/************************************************************************/
10698 +/*                          GetGeoMinMax()                              */
10699 +/************************************************************************/
10700 +
10701 +/**
10702 + * \brief Get the min/max coordinates of laitutude and longitude.
10703 + *
10704 + * The method will fetch the min/max coordinates of laitutude and longitude.
10705 + *
10706 + * @param geoMinMax an existing four double buffer into which the
10707 + * native geographical bounding box values will be placed.
10708 + *
10709 + * @return CE_None on success or CE_Failure on failure.
10710 + */
10711 +
10712 +CPLErr DAP_Dataset::GetGeoMinMax(double geoMinMax[])
10713 +{
10714 +    if (!mb_GeoTransformSet)
10715 +        return CE_Failure;
10716 +
10717 +    geoMinMax[0] = mdSrcGeoMinX;
10718 +    geoMinMax[2] = mdSrcGeoMinY;
10719 +    geoMinMax[1] = mdSrcGeoMaxX;
10720 +    geoMinMax[3] = mdSrcGeoMaxY;
10721 +
10722 +    return CE_None;
10723 +}
10724 +
10725 +/************************************************************************/
10726 +/*                          RectifyGOESDataSet()                        */
10727 +/************************************************************************/
10728 +
10729 +/**
10730 + * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
10731 + *
10732 + * The method will convert the GOES dataset from satellite CRS project to
10733 + * grid CRS based on GDAL API GDALReprojectImage;
10734 + *
10735 + * @return CE_None on success or CE_Failure on failure.
10736 + */
10737 +
10738 +CPLErr DAP_Dataset::RectifyGOESDataSet()
10739 +{
10740 +    DBG(cerr << "In RectifyGOESDataSet" << endl);
10741 +
10742 +    char *pszDstWKT;
10743 +    mo_NativeCRS.exportToWkt(&pszDstWKT);
10744 +
10745 +    GDALDriverH poDriver = GDALGetDriverByName("VRT"); // MEM
10746 +    GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
10747 +            maptr_DS->GetRasterCount(), maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
10748 +    if (NULL == rectDataSet) {
10749 +        GDALClose(poDriver);
10750 +        OGRFree(pszDstWKT);
10751 +        throw Error("Failed to create \"MEM\" dataSet.");
10752 +    }
10753 +
10754 +    rectDataSet->SetProjection(pszDstWKT);
10755 +    rectDataSet->SetGeoTransform(md_Geotransform);
10756 +
10757 +    DBG(cerr << "rectDataSet: " << rectDataSet << endl);
10758 +    DBG(cerr << "satDataSet: " << maptr_DS.get() << endl);
10759 +
10760 +    // FIXME Magic value of 0.125
10761 +    if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet, pszDstWKT,
10762 +            GRA_Lanczos /*GRA_NearestNeighbour*/, 0, 0.0/*0.125*/, NULL, NULL, NULL)) {
10763 +        GDALClose(rectDataSet);
10764 +        GDALClose(poDriver);
10765 +        OGRFree(pszDstWKT);
10766 +        throw Error("Failed to re-project satellite data from GCP CRS to geographical CRS.");
10767 +    }
10768 +
10769 +    OGRFree(pszDstWKT);
10770 +    GDALClose(maptr_DS.release());
10771 +
10772 +    maptr_DS.reset(rectDataSet);
10773 +
10774 +    DBG(cerr << "Leaving RectifyGOESDataSet" << endl);
10775 +
10776 +    return CE_None;
10777 +}
10778 +
10779 +} // namespace libdap
10780 diff -Nur bes-3.12.0/functions.orig/swath2grid/.svn/pristine/ee/eed03539b992d9d129c49278cfb7203c371bfd39.svn-base bes-3.12.0/functions/swath2grid/.svn/pristine/ee/eed03539b992d9d129c49278cfb7203c371bfd39.svn-base
10781 --- bes-3.12.0/functions.orig/swath2grid/.svn/pristine/ee/eed03539b992d9d129c49278cfb7203c371bfd39.svn-base     1970-01-01 01:00:00.000000000 +0100
10782 +++ bes-3.12.0/functions/swath2grid/.svn/pristine/ee/eed03539b992d9d129c49278cfb7203c371bfd39.svn-base  2014-03-03 15:47:37.976899599 +0100
10783 @@ -0,0 +1,625 @@
10784 +/******************************************************************************
10785 + * $Id: TRMM_Dataset.cpp 2011-07-19 16:24:00Z $
10786 + *
10787 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
10788 + *                      for Earth Observation: Open Source Reference Implementation
10789 + * Purpose:  NC_GOES_Dataset implementation for NOAA GOES data
10790 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
10791 + *
10792 + ******************************************************************************
10793 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
10794 + *
10795 + * Permission is hereby granted, free of charge, to any person obtaining a
10796 + * copy of this software and associated documentation files (the "Software"),
10797 + * to deal in the Software without restriction, including without limitation
10798 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10799 + * and/or sell copies of the Software, and to permit persons to whom the
10800 + * Software is furnished to do so, subject to the following conditions:
10801 + *
10802 + * The above copyright notice and this permission notice shall be included
10803 + * in all copies or substantial portions of the Software.
10804 + *
10805 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10806 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10807 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
10808 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10809 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
10810 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
10811 + * DEALINGS IN THE SOFTWARE.
10812 + ****************************************************************************/
10813 +
10814 +#include "NC_GOES_Dataset.h"
10815 +
10816 +using namespace std;
10817 +
10818 +#define GOES_TIME_DEBUG FALSE
10819 +
10820 +NC_GOES_Dataset::NC_GOES_Dataset()
10821 +{
10822 +}
10823 +
10824 +/************************************************************************/
10825 +/*                           ~NC_GOES_Dataset()                         */
10826 +/************************************************************************/
10827 +
10828 +/**
10829 + * \brief Destroy an open NC_GOES_Dataset object.
10830 + *
10831 + * This is the accepted method of closing a NC_GOES_Dataset dataset and
10832 + * deallocating all resources associated with it.
10833 + */
10834 +
10835 +NC_GOES_Dataset::~NC_GOES_Dataset()
10836 +{
10837 +}
10838 +
10839 +/************************************************************************/
10840 +/*                           NC_GOES_Dataset()                          */
10841 +/************************************************************************/
10842 +
10843 +/**
10844 + * \brief Create an NC_GOES_Dataset object.
10845 + *
10846 + * This is the accepted method of creating a NC_GOES_Dataset object and
10847 + * allocating all resources associated with it.
10848 + *
10849 + * @param id The coverage identifier.
10850 + *
10851 + * @param rBandList The field list selected for this coverage. For TRMM
10852 + * daily data, the user could specify multiple days range in request.
10853 + * Each day is seemed as one field.
10854 + *
10855 + * @return A NC_GOES_Dataset object.
10856 + */
10857 +
10858 +NC_GOES_Dataset::NC_GOES_Dataset(const string& id, vector<int> &rBandList) :
10859 +       AbstractDataset(id, rBandList)
10860 +{
10861 +       md_MissingValue = 0;
10862 +       mb_GeoTransformSet = FALSE;
10863 +}
10864 +
10865 +/************************************************************************/
10866 +/*                           InitialDataset()                           */
10867 +/************************************************************************/
10868 +
10869 +/**
10870 + * \brief Initialize the GOES dataset with NetCDF format.
10871 +
10872 + * This method is the implementation for initializing a GOES dataset with NetCDF format.
10873 + * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
10874 + * will be called to initialize an GOES dataset.
10875 + *
10876 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
10877 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
10878 + *
10879 + * @return CE_None on success or CE_Failure on failure.
10880 + */
10881 +
10882 +CPLErr NC_GOES_Dataset::InitialDataset(const int isSimple)
10883 +{
10884 +       vector<string> strSet;
10885 +       unsigned int n = CsvburstCpp(ms_CoverageID, strSet, ':');
10886 +       if (n != 4)
10887 +       {
10888 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
10889 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Incorrect coverage ID.");
10890 +               return CE_Failure;
10891 +       }
10892 +
10893 +       ms_DataTypeName = strSet[0] + ":" + strSet[1];
10894 +       ms_SrcFilename = StrTrims(strSet[2], " \'\"");
10895 +       ms_DatasetName = strSet[3];
10896 +
10897 +       m_ncLatDataSetName = "NETCDF:" + ms_SrcFilename + ":latitude";
10898 +       m_ncLonDataSetName = "NETCDF:" + ms_SrcFilename + ":longitude";
10899 +       m_ncCoverageIDName = strSet[1] + ":" + strSet[2] + ":" + strSet[3];
10900 +
10901 +       GDALDataset* pSrc = (GDALDataset*) GDALOpenShared(m_ncCoverageIDName.c_str(), GA_ReadOnly);
10902 +       if (pSrc == NULL)
10903 +       {
10904 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
10905 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open file \"%s\".", ms_SrcFilename.c_str());
10906 +               return CE_Failure;
10907 +       }
10908 +
10909 +       ms_NativeFormat = GDALGetDriverShortName(pSrc->GetDriver());
10910 +
10911 +       //setmetalist
10912 +       SetMetaDataList(pSrc);
10913 +
10914 +       //set noValue
10915 +       unsigned int nBandCount = pSrc->GetRasterCount();
10916 +       if (nBandCount < 1)
10917 +       {
10918 +               GDALClose(pSrc);
10919 +               SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
10920 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The GOES file does not contain any raster band.");
10921 +               return CE_Failure;
10922 +       }
10923 +
10924 +       maptr_DS.reset(pSrc);
10925 +
10926 +       //set moNativeCRS and mGeoTransform
10927 +       if (CE_None != SetNativeCRS() ||
10928 +               CE_None != SetGeoTransform() ||
10929 +               CE_None != SetGDALDataset(isSimple))
10930 +       {
10931 +               GDALClose(maptr_DS.release());
10932 +               return CE_Failure;
10933 +       }
10934 +
10935 +       return CE_None;
10936 +}
10937 +
10938 +/************************************************************************/
10939 +/*                            SetNativeCRS()                            */
10940 +/************************************************************************/
10941 +
10942 +/**
10943 + * \brief Set the Native CRS for a GOES dataset.
10944 + *
10945 + * The method will set the CRS for a GOES dataset as an native CRS.
10946 + *
10947 + * Since the original GOES data adopt satellite CRS to recored its value,
10948 + * like MODIS swath data, each data point has its corresponding latitude
10949 + * and longitude value, those coordinates could be fetched in another two fields.
10950 + *
10951 + * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
10952 + * both the latitude and longitude are existed.
10953 + *
10954 + * @return CE_None on success or CE_Failure on failure.
10955 + */
10956 +
10957 +CPLErr NC_GOES_Dataset::SetNativeCRS()
10958 +{
10959 +       if (CE_None == AbstractDataset::SetNativeCRS())
10960 +               return CE_None;
10961 +
10962 +       GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
10963 +       GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
10964 +
10965 +       if(hLatDS == NULL) {
10966 +               m_ncLatDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lat";
10967 +               hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
10968 +       }
10969 +
10970 +       if(hLonDS == NULL) {
10971 +               m_ncLonDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lon";
10972 +               hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
10973 +       }
10974 +
10975 +       if (hLatDS == NULL || hLonDS == NULL)
10976 +       {
10977 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetNativeCRS()");
10978 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open latitude/longitude sub-dataset.");
10979 +               return CE_Failure;
10980 +       }
10981 +
10982 +       mo_NativeCRS.SetWellKnownGeogCS("WGS84");
10983 +
10984 +       GDALClose(hLatDS);
10985 +       GDALClose(hLonDS);
10986 +
10987 +       return CE_None;
10988 +}
10989 +
10990 +/************************************************************************/
10991 +/*                           SetGeoTransform()                          */
10992 +/************************************************************************/
10993 +
10994 +/**
10995 + * \brief Set the affine GeoTransform matrix for a GOES data.
10996 + *
10997 + * The method will set a GeoTransform matrix for a GOES data
10998 + * by parsing the coordinates values existed in longitude and latitude field.
10999 + *
11000 + * The CRS for the bounding box is EPSG:4326.
11001 + *
11002 + * @return CE_None on success or CE_Failure on failure.
11003 + */
11004 +
11005 +CPLErr NC_GOES_Dataset::SetGeoTransform()
11006 +{
11007 +       if (CE_None == AbstractDataset::SetGeoTransform())
11008 +               return CE_None;
11009 +
11010 +       if (CE_None != SetGeoBBoxAndGCPs(maptr_DS.get()))
11011 +               return CE_Failure;
11012 +
11013 +       double resX, resY;
11014 +       if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
11015 +               resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
11016 +       else
11017 +               resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
11018 +
11019 +       resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (maptr_DS->GetRasterYSize() - 1);
11020 +
11021 +       double res = MIN(resX,resY);
11022 +
11023 +       if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
11024 +               mi_RectifiedImageXSize = (int)((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
11025 +       else
11026 +               mi_RectifiedImageXSize = (int)((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
11027 +
11028 +       mi_RectifiedImageYSize = (int)fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
11029 +
11030 +       md_Geotransform[0] = mdSrcGeoMinX;
11031 +       md_Geotransform[1] = res;
11032 +       md_Geotransform[2] = 0;
11033 +       md_Geotransform[3] = mdSrcGeoMaxY;
11034 +       md_Geotransform[4] = 0;
11035 +       md_Geotransform[5] = -res;
11036 +       mb_GeoTransformSet = TRUE;
11037 +
11038 +       return CE_None;
11039 +}
11040 +
11041 +CPLErr NC_GOES_Dataset::setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue)
11042 +{
11043 +       static int RESAMPLE_STANDARD = 500;
11044 +       int nXSize = hSrcDS->GetRasterXSize();
11045 +       int nYSize = hSrcDS->GetRasterYSize();
11046 +
11047 +       xRSValue = int(nXSize / RESAMPLE_STANDARD) + 2;
11048 +       yRSValue = int(nYSize / RESAMPLE_STANDARD) + 2;
11049 +
11050 +       return CE_None;
11051 +}
11052 +
11053 +/************************************************************************/
11054 +/*                         SetGeoBBoxAndGCPs()                          */
11055 +/************************************************************************/
11056 +
11057 +/**
11058 + * \brief Set the native geographical bounding box and GCP array for a GOES data.
11059 + *
11060 + * The method will set the native geographical bounding box
11061 + * by comparing the coordinates values existed in longitude and latitude field.
11062 + *
11063 + * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
11064 + *
11065 + * @return CE_None on success or CE_Failure on failure.
11066 + */
11067 +
11068 +CPLErr NC_GOES_Dataset::SetGeoBBoxAndGCPs(GDALDataset* poVDS)
11069 +{
11070 +       GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
11071 +       GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
11072 +
11073 +       int nXSize = poVDS->GetRasterXSize();
11074 +       int nYSize = poVDS->GetRasterYSize();
11075 +
11076 +       mi_GoesSrcImageXSize = nXSize;
11077 +       mi_GoesSrcImageYSize = nYSize;
11078 +
11079 +       int nLatXSize = hLatDS->GetRasterXSize();
11080 +       int nLatYSize = hLatDS->GetRasterYSize();
11081 +       int nLonXSize = hLonDS->GetRasterXSize();
11082 +       int nLonYSize = hLonDS->GetRasterYSize();
11083 +
11084 +       if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
11085 +       {
11086 +               GDALClose(hLatDS);
11087 +               GDALClose(hLonDS);
11088 +
11089 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGeoBBoxAndGCPs()");
11090 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The size of latitude/longitude and data field does not match.");
11091 +
11092 +               return CE_Failure;
11093 +       }
11094 +
11095 +       /*
11096 +       *       Re-sample Standards:
11097 +       *       Height | Width
11098 +       *       (0, 500)                every other one pixel
11099 +       *       [500, 1000)             every other two pixels
11100 +       *       [1000,1500)             every other three pixels
11101 +       *       [1500,2000)             every other four pixels
11102 +       *       ... ...
11103 +       */
11104 +
11105 +       int xSpace = 1;
11106 +       int ySpace = 1;
11107 +       setResampleStandard(poVDS, xSpace, ySpace);
11108 +
11109 +       int nGCPs = 0;
11110 +       GDAL_GCP gdalCGP;
11111 +
11112 +       GDALRasterBand *poBandLat = hLatDS->GetRasterBand(1);
11113 +       GDALRasterBand *poBandLon = hLonDS->GetRasterBand(1);
11114 +       GDALDataType eDT = poBandLat->GetRasterDataType();
11115 +       void *dataLat = NULL;
11116 +       void *dataLon = NULL;
11117 +
11118 +       mdSrcGeoMinX = 360;
11119 +       mdSrcGeoMaxX = -360;
11120 +       mdSrcGeoMinY = 90;
11121 +       mdSrcGeoMaxY = -90;
11122 +
11123 +       switch (eDT)
11124 +       {
11125 +       case GDT_Float32: //For GOES Imager and Sounder data
11126 +       {
11127 +               dataLat = (float *) CPLMalloc(nXSize * sizeof(float));
11128 +               dataLon = (float *) CPLMalloc(nXSize * sizeof(float));
11129 +
11130 +               for (int iLine = 0; iLine < nYSize; iLine += ySpace)
11131 +               {
11132 +                       if (iLine >= nYSize)
11133 +                               iLine = nYSize - 1;
11134 +
11135 +                       poBandLat->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLat, nXSize, 1, GDT_Float32, 0, 0);
11136 +                       poBandLon->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLon, nXSize, 1, GDT_Float32, 0, 0);
11137 +
11138 +                       for (int iPixel = 0; iPixel < nXSize; iPixel += xSpace)
11139 +                       {
11140 +                               if(iPixel >= nXSize)
11141 +                                       iPixel = nXSize - 1;
11142 +                               double x = *((float *) dataLon + iPixel);
11143 +                               double y = *((float *) dataLat + iPixel);
11144 +                               if (isValidLongitude(x) && isValidLatitude(y))
11145 +                               {
11146 +                                       char pChr[64];
11147 +                                       sprintf(pChr, "%d", ++nGCPs);
11148 +                                       GDALInitGCPs(1, &gdalCGP);
11149 +                                       gdalCGP.pszId = strdup(pChr);
11150 +                                       gdalCGP.pszInfo = strdup("");
11151 +                                       gdalCGP.dfGCPLine = iLine;
11152 +                                       gdalCGP.dfGCPPixel = iPixel;
11153 +                                       gdalCGP.dfGCPX = x;
11154 +                                       gdalCGP.dfGCPY = y;
11155 +                                       gdalCGP.dfGCPZ = 0;
11156 +                                       m_gdalGCPs.push_back(gdalCGP);
11157 +                                       mdSrcGeoMinX = MIN(mdSrcGeoMinX,gdalCGP.dfGCPX );
11158 +                                       mdSrcGeoMaxX = MAX(mdSrcGeoMaxX,gdalCGP.dfGCPX);
11159 +                                       mdSrcGeoMinY = MIN(mdSrcGeoMinY,gdalCGP.dfGCPY);
11160 +                                       mdSrcGeoMaxY = MAX(mdSrcGeoMaxY,gdalCGP.dfGCPY);
11161 +                               }
11162 +                       }
11163 +               }
11164 +
11165 +               VSIFree((float *) dataLat);
11166 +               VSIFree((float *) dataLon);
11167 +       }
11168 +               break;
11169 +
11170 +       default:
11171 +               break;
11172 +       }
11173 +
11174 +       GDALClose(hLatDS);
11175 +       GDALClose(hLonDS);
11176 +
11177 +       return CE_None;
11178 +}
11179 +
11180 +
11181 +/************************************************************************/
11182 +/*                           SetGDALDataset()                           */
11183 +/************************************************************************/
11184 +
11185 +/**
11186 + * \brief Set the GDALDataset object to GOES Imager and Sounder dataset.
11187 + *
11188 + * This method is used to set the GOES Imager and Sounder dataset based on GDAL
11189 + * class VRTDataset.
11190 + *
11191 + * @param isSimple the WCS request type.  When user executing a DescribeCoverage
11192 + * request, isSimple is set to 1, and for GetCoverage, is set to 0.
11193 + *
11194 + * @return CE_None on success or CE_Failure on failure.
11195 + */
11196 +
11197 +CPLErr NC_GOES_Dataset::SetGDALDataset(const int isSimple)
11198 +{
11199 +       for(int i = 1; i <= maptr_DS->GetRasterCount(); ++i)
11200 +               mv_BandList.push_back(i);
11201 +
11202 +       VRTDataset *poVDS = (VRTDataset *)VRTCreate(mi_RectifiedImageXSize, mi_RectifiedImageYSize);
11203 +       if (poVDS == NULL)
11204 +       {
11205 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGDALDataset()");
11206 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to create VRT DataSet.");
11207 +               return CE_Failure;
11208 +       }
11209 +
11210 +       VRTSourcedRasterBand *poVRTBand = NULL;
11211 +       GDALRasterBand *poSrcBand = NULL;
11212 +       GDALDataType eBandType;
11213 +       for (unsigned int i = 0; i < mv_BandList.size(); i++)
11214 +       {
11215 +               poSrcBand = maptr_DS->GetRasterBand(mv_BandList[i]);
11216 +               eBandType = poSrcBand->GetRasterDataType();
11217 +               poVDS->AddBand(eBandType, NULL);
11218 +               poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand(i + 1);
11219 +               poVRTBand->SetNoDataValue(md_MissingValue);
11220 +
11221 +               if (CE_None != poVRTBand->AddSimpleSource(poSrcBand, 0, 0,
11222 +                               mi_RectifiedImageXSize, mi_RectifiedImageYSize, 0, 0,
11223 +                               mi_RectifiedImageXSize, mi_RectifiedImageYSize, NULL, md_MissingValue))
11224 +               {
11225 +                       GDALClose((GDALDatasetH) poVDS);
11226 +                       SetWCS_ErrorLocator("NC_GOES_Dataset::setGDALDataset()");
11227 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Add Simple Source into VRT DataSet.");
11228 +                       return CE_Failure;
11229 +               }
11230 +       }
11231 +
11232 +       //set GCPs for this VRTDataset
11233 +       if (CE_None != SetGCPGeoRef4VRTDataset(poVDS))
11234 +       {
11235 +               GDALClose((GDALDatasetH) poVDS);
11236 +               return CE_Failure;
11237 +       }
11238 +
11239 +       GDALClose(maptr_DS.release());
11240 +       maptr_DS.reset(poVDS);
11241 +
11242 +       if (isSimple)
11243 +               return CE_None;
11244 +
11245 +       return RectifyGOESDataSet();
11246 +}
11247 +
11248 +/************************************************************************/
11249 +/*                       SetGCPGeoRef4VRTDataset()                      */
11250 +/************************************************************************/
11251 +
11252 +/**
11253 + * \brief Set the GCP array for the VRT dataset.
11254 + *
11255 + * This method is used to set the GCP array to created VRT dataset based on GDAL
11256 + * method SetGCPs().
11257 + *
11258 + * @param poVDS The VRT dataset.
11259 + *
11260 + * @return CE_None on success or CE_Failure on failure.
11261 + */
11262 +
11263 +CPLErr NC_GOES_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
11264 +{
11265 +       char* psTargetSRS;
11266 +       mo_NativeCRS.exportToWkt(&psTargetSRS);
11267 +
11268 +#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
11269 +       if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS))
11270 +       {
11271 +               OGRFree(psTargetSRS);
11272 +               SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
11273 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to set GCPs.");
11274 +
11275 +               return CE_Failure;
11276 +       }
11277 +#else
11278 +       {
11279 +               if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
11280 +               {
11281 +                       OGRFree( psTargetSRS );
11282 +                       SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
11283 +                       WCS_Error(CE_Failure,OGC_WCS_NoApplicableCode,"Failed to set GCPs.");
11284 +
11285 +                       return CE_Failure;
11286 +               }
11287 +       }
11288 +#endif
11289 +
11290 +       OGRFree(psTargetSRS);
11291 +
11292 +       return CE_None;
11293 +}
11294 +
11295 +/************************************************************************/
11296 +/*                        SetMetaDataList()                             */
11297 +/************************************************************************/
11298 +
11299 +/**
11300 + * \brief Set the metadata list for this coverage.
11301 + *
11302 + * The method will set the metadata list for the coverage based on its
11303 + * corresponding GDALDataset object.
11304 + *
11305 + * @param hSrc the GDALDataset object corresponding to coverage.
11306 + *
11307 + * @return CE_None on success or CE_Failure on failure.
11308 + */
11309 +
11310 +CPLErr NC_GOES_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
11311 +{
11312 +       mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
11313 +       mv_MetaDataList.push_back("unit=GVAR");
11314 +       mv_MetaDataList.push_back("FillValue=0");
11315 +       ms_FieldQuantityDef = "GVAR";
11316 +       ms_AllowRanges = "0 65535";
11317 +       ms_CoveragePlatform = "GOES-11";
11318 +       ms_CoverageInstrument = "GOES-11";
11319 +       ms_CoverageSensor = "Imager";
11320 +
11321 +       return CE_None;
11322 +}
11323 +
11324 +/************************************************************************/
11325 +/*                          GetGeoMinMax()                              */
11326 +/************************************************************************/
11327 +
11328 +/**
11329 + * \brief Get the min/max coordinates of laitutude and longitude.
11330 + *
11331 + * The method will fetch the min/max coordinates of laitutude and longitude.
11332 + *
11333 + * @param geoMinMax an existing four double buffer into which the
11334 + * native geographical bounding box values will be placed.
11335 + *
11336 + * @return CE_None on success or CE_Failure on failure.
11337 + */
11338 +
11339 +CPLErr NC_GOES_Dataset::GetGeoMinMax(double geoMinMax[])
11340 +{
11341 +       if (!mb_GeoTransformSet)
11342 +               return CE_Failure;
11343 +
11344 +       geoMinMax[0] = mdSrcGeoMinX;
11345 +       geoMinMax[2] = mdSrcGeoMinY;
11346 +       geoMinMax[1] = mdSrcGeoMaxX;
11347 +       geoMinMax[3] = mdSrcGeoMaxY;
11348 +
11349 +       return CE_None;
11350 +}
11351 +
11352 +/************************************************************************/
11353 +/*                          GetGeoMinMax()                              */
11354 +/************************************************************************/
11355 +
11356 +/**
11357 + * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
11358 + *
11359 + * The method will convert the GOES dataset from satellite CRS project to
11360 + * grid CRS based on GDAL API GDALReprojectImage;
11361 + *
11362 + * @return CE_None on success or CE_Failure on failure.
11363 + */
11364 +
11365 +CPLErr NC_GOES_Dataset::RectifyGOESDataSet()
11366 +{
11367 +       char *pszDstWKT;
11368 +       mo_NativeCRS.exportToWkt(&pszDstWKT);
11369 +
11370 +       GDALDriverH poDriver = GDALGetDriverByName("MEM");
11371 +       GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize,
11372 +                       mi_RectifiedImageYSize, maptr_DS->GetRasterCount(),
11373 +                       maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
11374 +       if (NULL == rectDataSet)
11375 +       {
11376 +               GDALClose(poDriver);
11377 +               OGRFree(pszDstWKT);
11378 +               SetWCS_ErrorLocator("AbstractDataset::rectifyDataSet()");
11379 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
11380 +                               "Failed to create \"MEM\" dataSet.");
11381 +
11382 +               return CE_Failure;
11383 +       }
11384 +
11385 +       rectDataSet->SetProjection(pszDstWKT);
11386 +       rectDataSet->SetGeoTransform(md_Geotransform);
11387 +
11388 +       if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet,
11389 +                       pszDstWKT, GRA_NearestNeighbour, 0, 0.125, NULL, NULL, NULL))
11390 +       {
11391 +               GDALClose(rectDataSet);
11392 +               GDALClose(poDriver);
11393 +               OGRFree(pszDstWKT);
11394 +               SetWCS_ErrorLocator("AbstractDataset::RectifyDataSet()");
11395 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
11396 +                               "Failed to re-project GOES data from satellite GCP CRS to geographical CRS.");
11397 +
11398 +               return CE_Failure;
11399 +       }
11400 +
11401 +       OGRFree(pszDstWKT);
11402 +       GDALClose(maptr_DS.release());
11403 +
11404 +       maptr_DS.reset(rectDataSet);
11405 +
11406 +       return CE_None;
11407 +}
11408 +
11409 Binarne pliki bes-3.12.0/functions.orig/swath2grid/.svn/wc.db i bes-3.12.0/functions/swath2grid/.svn/wc.db ró¿ni± siê
11410 diff -Nur bes-3.12.0/functions.orig/swath2grid/three_array_1.das bes-3.12.0/functions/swath2grid/three_array_1.das
11411 --- bes-3.12.0/functions.orig/swath2grid/three_array_1.das      1970-01-01 01:00:00.000000000 +0100
11412 +++ bes-3.12.0/functions/swath2grid/three_array_1.das   2014-03-03 15:47:38.046899595 +0100
11413 @@ -0,0 +1,10 @@
11414 +# three_array_1.das
11415 +#
11416 +# Created on: Dec 12, 2012
11417 +#     Author: jimg
11418 +
11419 +Attributes {
11420 +    t{}
11421 +    lon{}
11422 +    lat{}
11423 +}
11424 diff -Nur bes-3.12.0/functions.orig/swath2grid/three_array_1.dds bes-3.12.0/functions/swath2grid/three_array_1.dds
11425 --- bes-3.12.0/functions.orig/swath2grid/three_array_1.dds      1970-01-01 01:00:00.000000000 +0100
11426 +++ bes-3.12.0/functions/swath2grid/three_array_1.dds   2014-03-03 15:47:38.050232928 +0100
11427 @@ -0,0 +1,10 @@
11428 +# three_array_1.dds
11429 +#
11430 +# Created on: Dec 12, 2012
11431 +#     Author: jimg
11432 +
11433 +Dataset {
11434 +    Float64 t[10][10];
11435 +    Float64 lon[10][10];
11436 +    Float64 lat[10][10];
11437 +} three_array_1;
11438 diff -Nur bes-3.12.0/functions.orig/swath2grid/wcs_error.cpp bes-3.12.0/functions/swath2grid/wcs_error.cpp
11439 --- bes-3.12.0/functions.orig/swath2grid/wcs_error.cpp  1970-01-01 01:00:00.000000000 +0100
11440 +++ bes-3.12.0/functions/swath2grid/wcs_error.cpp       2014-03-03 15:47:38.046899595 +0100
11441 @@ -0,0 +1,116 @@
11442 +/******************************************************************************
11443 + * $Id: wcs_error.cpp 2011-07-19 16:24:00Z $
11444 + *
11445 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
11446 + *                      for Earth Observation: Open Source Reference Implementation
11447 + * Purpose:  WCS exception and error handler implementation, used to set
11448 + *                      the exception code and locator of WCS
11449 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
11450 + *
11451 + ******************************************************************************
11452 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
11453 + *
11454 + * Permission is hereby granted, free of charge, to any person obtaining a
11455 + * copy of this software and associated documentation files (the "Software"),
11456 + * to deal in the Software without restriction, including without limitation
11457 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11458 + * and/or sell copies of the Software, and to permit persons to whom the
11459 + * Software is furnished to do so, subject to the following conditions:
11460 + *
11461 + * The above copyright notice and this permission notice shall be included
11462 + * in all copies or substantial portions of the Software.
11463 + *
11464 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11465 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11466 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
11467 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11468 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
11469 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
11470 + * DEALINGS IN THE SOFTWARE.
11471 + ****************************************************************************/
11472 +
11473 +#include "wcs_error.h"
11474 +
11475 +static string WCS_ERROR_STRING="";
11476 +static string ERROR_LOCATOR="";
11477 +static string ExcptCodeText[] =
11478 +{
11479 +       "OperationNotSupported",
11480 +       "MissingParameterValue",
11481 +       "InvalidParameterValue",
11482 +       "VersionNegotiationFailed",
11483 +       "InvalidUpdateSequence",
11484 +       "OptionNotSupported",
11485 +       "NoApplicableCode",
11486 +       "NoSuchCoverage",
11487 +       "InvalidAxisLabel",
11488 +       "InvalidSubsetting"
11489 +};
11490 +
11491 +static int WCS_IsSoapMessage_Transform = 0;
11492 +
11493 +string CPL_STDCALL GetWCS_ErrorMsg()
11494 +{
11495 +       return WCS_ERROR_STRING;
11496 +}
11497 +
11498 +void CPL_STDCALL SetWCS_ErrorLocator(const char* loc)
11499 +{
11500 +       ERROR_LOCATOR = loc;
11501 +}
11502 +
11503 +void CPL_STDCALL WCS_ErrorHandler(CPLErr eErrClass,int err_no,const char *pszErrorMsg )
11504 +{
11505 +       WCS_ERROR_STRING.clear();
11506 +       string ExcCode;
11507 +
11508 +       if(err_no >= 300 && err_no <= 309)
11509 +               ExcCode = ExcptCodeText[err_no - 300];
11510 +       else
11511 +               ExcCode = ExcptCodeText[6];
11512 +
11513 +       if(WCS_IsSoapMessage_Transform)
11514 +       {
11515 +               WCS_ERROR_STRING  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11516 +               WCS_ERROR_STRING += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n";
11517 +               WCS_ERROR_STRING += "<soap:Body>\n";
11518 +               WCS_ERROR_STRING += "<ExceptionReport xmlns=\"http://www.opengis.net/ows\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
11519 +               WCS_ERROR_STRING += "xsi:schemaLocation=\"http://www.opengis.net/ows/owsCommon.xsd\" version=\"0.3.20\" language=\"en\">\n";
11520 +               WCS_ERROR_STRING += "   <Exception exceptionCode=\"";
11521 +               WCS_ERROR_STRING += ExcCode;
11522 +               WCS_ERROR_STRING += "\" locator=\"";
11523 +               WCS_ERROR_STRING += ERROR_LOCATOR;
11524 +               WCS_ERROR_STRING += "\">\n";
11525 +               WCS_ERROR_STRING += "           <ExceptionText>" + string(pszErrorMsg) + "</ExceptionText>\n";
11526 +               WCS_ERROR_STRING += "   </Exception>\n";
11527 +               WCS_ERROR_STRING += "</ExceptionReport>\n";
11528 +               WCS_ERROR_STRING += "/soap:Body>\n";
11529 +               WCS_ERROR_STRING += "/<soap:Envelope>\n";
11530 +       }
11531 +       else
11532 +       {
11533 +               WCS_ERROR_STRING  = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11534 +               WCS_ERROR_STRING += "<ExceptionReport xmlns=\"http://www.opengis.net/ows\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
11535 +               WCS_ERROR_STRING += "xsi:schemaLocation=\"http://www.opengis.net/ows/owsCommon.xsd\" version=\"0.3.20\" language=\"en\">\n";
11536 +               WCS_ERROR_STRING += "   <Exception exceptionCode=\"";
11537 +               WCS_ERROR_STRING += ExcCode;
11538 +               WCS_ERROR_STRING += "\" locator=\"";
11539 +               WCS_ERROR_STRING += ERROR_LOCATOR;
11540 +               WCS_ERROR_STRING += "\">\n";
11541 +               WCS_ERROR_STRING += "           <ExceptionText>" + string(pszErrorMsg) + "</ExceptionText>\n";
11542 +               WCS_ERROR_STRING += "   </Exception>\n";
11543 +               WCS_ERROR_STRING += "</ExceptionReport>\n";
11544 +       }
11545 +
11546 +       return;
11547 +}
11548 +
11549 +void WCST_SetSoapMsgTrns(int isSoap)
11550 +{
11551 +       WCS_IsSoapMessage_Transform = isSoap;
11552 +}
11553 +
11554 +int    WCST_GetSoapMsgTrns()
11555 +{
11556 +       return WCS_IsSoapMessage_Transform;
11557 +}
11558 diff -Nur bes-3.12.0/functions.orig/swath2grid/wcs_error.h bes-3.12.0/functions/swath2grid/wcs_error.h
11559 --- bes-3.12.0/functions.orig/swath2grid/wcs_error.h    1970-01-01 01:00:00.000000000 +0100
11560 +++ bes-3.12.0/functions/swath2grid/wcs_error.h 2014-03-03 15:47:38.046899595 +0100
11561 @@ -0,0 +1,81 @@
11562 +/******************************************************************************
11563 + * $Id: wcs_error.h 2011-07-19 16:24:00Z $
11564 + *
11565 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
11566 + *                      for Earth Observation: Open Source Reference Implementation
11567 + * Purpose:  WCS exception and error handler definition
11568 + * Author:   Yuanzheng Shao, yshao3@gmu.edu
11569 + *
11570 + ******************************************************************************
11571 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>
11572 + *
11573 + * Permission is hereby granted, free of charge, to any person obtaining a
11574 + * copy of this software and associated documentation files (the "Software"),
11575 + * to deal in the Software without restriction, including without limitation
11576 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11577 + * and/or sell copies of the Software, and to permit persons to whom the
11578 + * Software is furnished to do so, subject to the following conditions:
11579 + *
11580 + * The above copyright notice and this permission notice shall be included
11581 + * in all copies or substantial portions of the Software.
11582 + *
11583 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11584 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11585 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
11586 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
11587 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
11588 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
11589 + * DEALINGS IN THE SOFTWARE.
11590 + ****************************************************************************/
11591 +
11592 +/************************************************************************
11593 + WCS Exception Code
11594 +
11595 + See OGC Web Services Common Standard [OGC 06-121r9] for details
11596 + Table 27 â€” Standard exception codes and meanings
11597 +       OperationNotSupported
11598 +       MissingParameterValue
11599 +       InvalidParameterValue
11600 +       VersionNegotiationFailed
11601 +       InvalidUpdateSequence
11602 +       OptionNotSupported
11603 +       NoApplicableCode
11604 +
11605 + See OGC® WCS 2.0 Interface Standard - Core [09-110r3] for details
11606 + Table 18 - Exception codes for GetCoverage operation
11607 +        NoSuchCoverage
11608 +        InvalidAxisLabel
11609 +        InvalidSubsetting
11610 +
11611 +*************************************************************************/
11612 +
11613 +#ifndef WCS_ERROR_H_
11614 +#define WCS_ERROR_H_
11615 +
11616 +#include <cpl_error.h>
11617 +#include <string>
11618 +
11619 +using namespace std;
11620 +
11621 +#define OGC_WCS_OperationNotSupported                  300
11622 +#define OGC_WCS_MissingParameterValue                  301
11623 +#define OGC_WCS_InvalidParameterValue                  302
11624 +#define OGC_WCS_VersionNegotiationFailed       303
11625 +#define OGC_WCS_InvalidUpdateSequence          304
11626 +#define OGC_WCS_OptionNotSupported                     305
11627 +#define OGC_WCS_NoApplicableCode                       306
11628 +
11629 +#define OGC_WCS_NoSuchCoverage                         307
11630 +#define OGC_WCS_InvalidAxisLabel                       308
11631 +#define OGC_WCS_InvalidSubsetting                      309
11632 +
11633 +void CPL_DLL CPL_STDCALL WCS_Error(CPLErr, int, const char*, ...);
11634 +void CPL_DLL CPL_STDCALL SetWCS_ErrorLocator(const char* loc);
11635 +void CPL_DLL CPL_STDCALL WCS_ErrorHandler(CPLErr, int, const char*);
11636 +string CPL_DLL CPL_STDCALL GetWCS_ErrorMsg();
11637 +
11638 +int    WCST_GetSoapMsgTrns();
11639 +void WCST_SetSoapMsgTrns(int);
11640 +
11641 +#define WCS_Error  CPLError
11642 +#endif /* WCS_ERROR_H_ */
11643 diff -Nur bes-3.12.0/functions.orig/swath2grid/wcsUtil.cpp bes-3.12.0/functions/swath2grid/wcsUtil.cpp
11644 --- bes-3.12.0/functions.orig/swath2grid/wcsUtil.cpp    1970-01-01 01:00:00.000000000 +0100
11645 +++ bes-3.12.0/functions/swath2grid/wcsUtil.cpp 2014-03-03 15:47:38.056899595 +0100
11646 @@ -0,0 +1,1278 @@
11647 +/******************************************************************************\r
11648 + * $Id: wcsUtil.cpp 2011-07-19 16:24:00Z $\r
11649 + *\r
11650 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)\r
11651 + *                      for Earth Observation: Open Source Reference Implementation\r
11652 + * Purpose:  WCS Utility Function implementation\r
11653 + * Author:   Yuanzheng Shao, yshao3@gmu.edu\r
11654 + *\r
11655 + ******************************************************************************\r
11656 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>\r
11657 + *\r
11658 + * Permission is hereby granted, free of charge, to any person obtaining a\r
11659 + * copy of this software and associated documentation files (the "Software"),\r
11660 + * to deal in the Software without restriction, including without limitation\r
11661 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
11662 + * and/or sell copies of the Software, and to permit persons to whom the\r
11663 + * Software is furnished to do so, subject to the following conditions:\r
11664 + *\r
11665 + * The above copyright notice and this permission notice shall be included\r
11666 + * in all copies or substantial portions of the Software.\r
11667 + *\r
11668 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
11669 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
11670 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
11671 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
11672 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
11673 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
11674 + * DEALINGS IN THE SOFTWARE.\r
11675 + ****************************************************************************/\r
11676 +\r
11677 +#include <unistd.h>\r
11678 +#include <dirent.h>\r
11679 +#include <sys/stat.h>\r
11680 +#include <stdexcept>\r
11681 +#include <uuid/uuid.h>\r
11682 +#include "wcsUtil.h"\r
11683 +//#include "mfhdf.h"\r
11684 +\r
11685 +/************************************************************************/\r
11686 +/*                          GetUUID()                                   */\r
11687 +/************************************************************************/\r
11688 +\r
11689 +/**\r
11690 + * \brief Used to get UUID string.\r
11691 + *\r
11692 + * This method will return a UUID, such as: cd32eb56-412c-11e0-9cce-67750f871b94\r
11693 + *\r
11694 + * @return A generated UUID string.\r
11695 + */\r
11696 +\r
11697 +string CPL_STDCALL GetUUID()\r
11698 +{\r
11699 +       uuid_t uuid;\r
11700 +       uuid_generate(uuid);\r
11701 +       char uuidstr[36];\r
11702 +       uuid_unparse(uuid, uuidstr);\r
11703 +       return uuidstr;\r
11704 +}\r
11705 +\r
11706 +/************************************************************************/\r
11707 +/*                          SPrintArray()                               */\r
11708 +/************************************************************************/\r
11709 +\r
11710 +/**\r
11711 + * \brief Print a string based on coverage realted parameters.\r
11712 + *\r
11713 + * This method will return a UUID, such as: cd32eb56-412c-11e0-9cce-67750f871b94\r
11714 + *\r
11715 + * @return A generated UUID string.\r
11716 + */\r
11717 +\r
11718 +string CPL_STDCALL SPrintArray(GDALDataType eDataType, const void *paDataArray, int nValues, const char *pszDelimiter)\r
11719 +{\r
11720 +       char *pszString, *pszField;\r
11721 +       int i, iFieldSize, iStringSize;\r
11722 +\r
11723 +       iFieldSize = 32 + strlen(pszDelimiter);\r
11724 +       pszField = (char *) CPLMalloc(iFieldSize + 1);\r
11725 +       iStringSize = nValues * iFieldSize + 1;\r
11726 +       pszString = (char *) CPLMalloc(iStringSize);\r
11727 +       memset(pszString, 0, iStringSize);\r
11728 +       for (i = 0; i < nValues; i++)\r
11729 +       {\r
11730 +               switch (eDataType)\r
11731 +               {\r
11732 +               case GDT_Byte:\r
11733 +                       sprintf(pszField, "%d%s", ((GByte *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11734 +                       break;\r
11735 +               case GDT_UInt16:\r
11736 +                       sprintf(pszField, "%u%s", ((GUInt16 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11737 +                       break;\r
11738 +               case GDT_Int16:\r
11739 +               default:\r
11740 +                       sprintf(pszField, "%d%s", ((GInt16 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11741 +                       break;\r
11742 +               case GDT_UInt32:\r
11743 +                       sprintf(pszField, "%u%s", ((GUInt32 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11744 +                       break;\r
11745 +               case GDT_Int32:\r
11746 +                       sprintf(pszField, "%d%s", ((GInt32 *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11747 +                       break;\r
11748 +               case GDT_Float32:\r
11749 +                       sprintf(pszField, "%.7g%s", ((float *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11750 +                       break;\r
11751 +               case GDT_Float64:\r
11752 +                       sprintf(pszField, "%.15g%s", ((double *) paDataArray)[i], (i < nValues - 1) ? pszDelimiter : "");\r
11753 +                       break;\r
11754 +               }\r
11755 +               strcat(pszString, pszField);\r
11756 +       }\r
11757 +\r
11758 +       CPLFree(pszField);\r
11759 +\r
11760 +       return string(pszString);\r
11761 +}\r
11762 +\r
11763 +/************************************************************************/\r
11764 +/*                          StrTrimHead()                               */\r
11765 +/************************************************************************/\r
11766 +\r
11767 +/**\r
11768 + * \brief Trim s string's head.\r
11769 + *\r
11770 + * This method will trim a string's head, remove the sapce and line break\r
11771 + * in the head of a string.\r
11772 + *\r
11773 + * @param str The string to be processed.\r
11774 + *\r
11775 + * @return A head-trimmed string.\r
11776 + */\r
11777 +\r
11778 +string CPL_STDCALL StrTrimHead(const string &str)\r
11779 +{\r
11780 +       string::size_type p = 0;\r
11781 +       /* leading space? */\r
11782 +       while ((p < str.size()) && (str[p] == ' ' || str[p] == '\t' || str[p] == 13 || str[p] == 10))\r
11783 +               p++;\r
11784 +       if (p >= str.size())\r
11785 +               return "";\r
11786 +       else\r
11787 +               return str.substr(p);\r
11788 +}\r
11789 +\r
11790 +/************************************************************************/\r
11791 +/*                          StrTrimTail()                               */\r
11792 +/************************************************************************/\r
11793 +\r
11794 +/**\r
11795 + * \brief Trim s string's tail.\r
11796 + *\r
11797 + * This method will trim a string's tail, remove the sapce and line break\r
11798 + * in the tail of a string.\r
11799 + *\r
11800 + * @param str The string to be processed.\r
11801 + *\r
11802 + * @return A tail-trimmed string.\r
11803 + */\r
11804 +\r
11805 +string CPL_STDCALL StrTrimTail(const string &str)\r
11806 +{\r
11807 +       string::size_type p = str.size() - 1;\r
11808 +       while (p >= 0 && (str[p] == ' ' || str[p] == '\t' || str[p] == 13 || str[p] == 10))\r
11809 +               p--;\r
11810 +       if (p < 0)\r
11811 +               return "";\r
11812 +       else\r
11813 +               return str.substr(0, p + 1);\r
11814 +}\r
11815 +\r
11816 +/************************************************************************/\r
11817 +/*                          StrTrim()                                   */\r
11818 +/************************************************************************/\r
11819 +\r
11820 +/**\r
11821 + * \brief Trim s string's head and tail.\r
11822 + *\r
11823 + * This method will trim a string's head and tail, remove the sapce and\r
11824 + * line break in both the head and end of a string.\r
11825 + *\r
11826 + * @param str The string to be processed.\r
11827 + *\r
11828 + * @return A trimmed string.\r
11829 + */\r
11830 +\r
11831 +string CPL_STDCALL StrTrim(const string &str)\r
11832 +{\r
11833 +       string s = StrTrimTail(str);\r
11834 +       return StrTrimHead(s);\r
11835 +}\r
11836 +\r
11837 +/************************************************************************/\r
11838 +/*                          StrTrims()                                  */\r
11839 +/************************************************************************/\r
11840 +\r
11841 +/**\r
11842 + * \brief Trim s string's head and tail based on delimiter string.\r
11843 + *\r
11844 + * This method will trim a string's head and tail based on delimiter\r
11845 + * string, and return the trimmed string.\r
11846 + *\r
11847 + * @param srcStr The string to be processed.\r
11848 + *\r
11849 + * @param tok The delimiter string used to trim the string.\r
11850 + *\r
11851 + * @return A trimmed string.\r
11852 + */\r
11853 +\r
11854 +string CPL_STDCALL StrTrims(const string& srcStr, const char* tok)\r
11855 +{\r
11856 +       if (srcStr.empty())\r
11857 +               return srcStr;\r
11858 +\r
11859 +       string::size_type beginIdx, endIdx;\r
11860 +       beginIdx = srcStr.find_first_not_of(tok);\r
11861 +       endIdx = srcStr.find_last_not_of(tok);\r
11862 +\r
11863 +       if (beginIdx != string::npos && endIdx != string::npos)\r
11864 +               return srcStr.substr(beginIdx, endIdx - beginIdx + 1);\r
11865 +       else\r
11866 +               return "";\r
11867 +}\r
11868 +\r
11869 +/************************************************************************/\r
11870 +/*                          Strslip()                                   */\r
11871 +/************************************************************************/\r
11872 +\r
11873 +/**\r
11874 + * \brief Slice a string and split it into an array.\r
11875 + *\r
11876 + * This method will slice a string based on left and right delimiter, and then\r
11877 + * split the slipped part into an array.\r
11878 + *\r
11879 + * @param str The string to be processed, such as "longitude[15.5,23.5]"\r
11880 + *\r
11881 + * @param arrStr The two dimension array to place the sliced results.\r
11882 + *\r
11883 + * @param leftdlm The left delimiter used to slip the string, such as '['.\r
11884 + *\r
11885 + * @param rightdlm The right delimiter used to slip the string, such as ']'.\r
11886 + */\r
11887 +\r
11888 +void CPL_STDCALL Strslip(const char* str, const char* arrStr[], const char leftdlm, const char rightdlm)\r
11889 +{\r
11890 +       char* pdest1 = 0;\r
11891 +       char* pdest2 = 0;\r
11892 +\r
11893 +       arrStr[0] = str;\r
11894 +       pdest1 = (char*)strchr(str, leftdlm);\r
11895 +       if (!pdest1)\r
11896 +       {\r
11897 +               arrStr[1] = str;\r
11898 +               return;\r
11899 +       }\r
11900 +\r
11901 +       pdest2 = (char*)strrchr(str, rightdlm);\r
11902 +       if (!pdest2)\r
11903 +               return;\r
11904 +\r
11905 +       arrStr[1] = pdest1 + 1;\r
11906 +       *pdest1 = '\0';\r
11907 +       *pdest2 = '\0';\r
11908 +\r
11909 +       return;\r
11910 +}\r
11911 +\r
11912 +/************************************************************************/\r
11913 +/*                          CsvburstComplexCpp()                        */\r
11914 +/************************************************************************/\r
11915 +\r
11916 +/**\r
11917 + * \brief Slice a string based on single or multiple delimiter(s), and\r
11918 + * then store the results to array.\r
11919 + *\r
11920 + * This method will slice a string based on specified delimiter(s), and then\r
11921 + * place the sliced string parts to a array.\r
11922 + *\r
11923 + * @param line The string to be processed.\r
11924 + *\r
11925 + * @param strSet The array to place the sliced results.\r
11926 + *\r
11927 + * @param tok The delimiter string used to slice the string.\r
11928 + *\r
11929 + * @return The size of the sliced parts.\r
11930 + */\r
11931 +\r
11932 +int CPL_STDCALL CsvburstComplexCpp(const string& line, vector<string> &strSet, const char *tok)\r
11933 +{\r
11934 +       if (line.empty() || line == "")\r
11935 +               return 0;\r
11936 +\r
11937 +       strSet.clear();\r
11938 +       string::size_type firstPos, idx;\r
11939 +\r
11940 +       firstPos = idx = 0;\r
11941 +       idx = line.find_first_of(tok, firstPos);\r
11942 +\r
11943 +       while (idx != string::npos)\r
11944 +       {\r
11945 +               string tmpStr = StrTrim(line.substr(firstPos, (idx - firstPos)));\r
11946 +               if (!tmpStr.empty() && tmpStr != "")\r
11947 +                       strSet.push_back(tmpStr);\r
11948 +\r
11949 +               firstPos = idx + 1;\r
11950 +               if (firstPos == string::npos)\r
11951 +                       break;\r
11952 +               idx = line.find_first_of(tok, firstPos);\r
11953 +       }\r
11954 +\r
11955 +       if (firstPos != string::npos)\r
11956 +       {\r
11957 +               strSet.push_back(StrTrim(line.substr(firstPos)));\r
11958 +       }\r
11959 +\r
11960 +       return strSet.size();\r
11961 +}\r
11962 +\r
11963 +/************************************************************************/\r
11964 +/*                          CsvburstCpp()                               */\r
11965 +/************************************************************************/\r
11966 +\r
11967 +/**\r
11968 + * \brief Slice a string based on single delimiter, and then store the results to array.\r
11969 + *\r
11970 + * This method will slice a string based on specified single delimiter, and then\r
11971 + * place the sliced string parts to a array.\r
11972 + *\r
11973 + * @param line The string to be processed, such as "12,34,56".\r
11974 + *\r
11975 + * @param strSet The array to place the sliced results.\r
11976 + *\r
11977 + * @param tok The delimiter character used to slice the string, such as ','.\r
11978 + *\r
11979 + * @return The size of the sliced parts.\r
11980 + */\r
11981 +\r
11982 +int CPL_STDCALL CsvburstCpp(const string& line, vector<string> &strSet, const char tok)\r
11983 +{\r
11984 +       if (line.empty() || line == "")\r
11985 +               return 0;\r
11986 +\r
11987 +       strSet.clear();\r
11988 +       string::size_type firstPos, idx;\r
11989 +       string::size_type panfuPos;\r
11990 +       panfuPos = 0;\r
11991 +       firstPos = idx = 0;\r
11992 +\r
11993 +       idx = line.find_first_of(tok, firstPos);\r
11994 +\r
11995 +       while (idx != string::npos)\r
11996 +       {\r
11997 +               if(line[idx-2] == '\"' || line[idx-2] == '\'')//Add By Yuanzheng Shao\r
11998 +               {\r
11999 +                       firstPos = idx + 1;\r
12000 +                       if (firstPos == string::npos)\r
12001 +                               break;\r
12002 +                       panfuPos = idx-2;\r
12003 +                       idx = line.find_first_of(tok, firstPos);\r
12004 +\r
12005 +                       string tmpStr = StrTrim(line.substr(panfuPos, (idx - panfuPos)));\r
12006 +                       if (!tmpStr.empty() && tmpStr != "")\r
12007 +                               strSet.push_back(tmpStr);\r
12008 +\r
12009 +                       firstPos = idx + 1;\r
12010 +                       idx = line.find_first_of(tok, firstPos);\r
12011 +               }\r
12012 +               else\r
12013 +               {\r
12014 +                       string tmpStr = StrTrim(line.substr(firstPos, (idx - firstPos)));\r
12015 +                       if (!tmpStr.empty() && tmpStr != "")\r
12016 +                               strSet.push_back(tmpStr);\r
12017 +\r
12018 +                       firstPos = idx + 1;\r
12019 +                       if (firstPos == string::npos)\r
12020 +                               break;\r
12021 +                       idx = line.find_first_of(tok, firstPos);\r
12022 +               }\r
12023 +       }\r
12024 +\r
12025 +       if (firstPos != string::npos)\r
12026 +       {\r
12027 +               strSet.push_back(StrTrim(line.substr(firstPos)));\r
12028 +       }\r
12029 +\r
12030 +       return strSet.size();\r
12031 +}\r
12032 +\r
12033 +/************************************************************************/\r
12034 +/*                          Find_Compare_SubStr()                       */\r
12035 +/************************************************************************/\r
12036 +\r
12037 +/**\r
12038 + * \brief Find the substring in a string.\r
12039 + *\r
12040 + * This method will find a substring in a string.\r
12041 + *\r
12042 + * @param line The string to be processed.\r
12043 + *\r
12044 + * @param sub The substring to be compared.\r
12045 + *\r
12046 + * @return TRUE if find the substring, otherwise FALSE.\r
12047 + */\r
12048 +\r
12049 +int CPL_STDCALL Find_Compare_SubStr(string line, string sub)\r
12050 +{\r
12051 +       if (line.empty() || line == "" || sub.empty() || sub == "")\r
12052 +               return 0;\r
12053 +\r
12054 +       for (unsigned int i = 0; i < line.size(); ++i)\r
12055 +       {\r
12056 +               line[i] = (char) toupper((char) line[i]);\r
12057 +       }\r
12058 +       for (unsigned int j = 0; j < sub.size(); ++j)\r
12059 +       {\r
12060 +               sub[j] = (char) toupper((char) sub[j]);\r
12061 +       }\r
12062 +\r
12063 +       if (string::npos == line.find(sub))\r
12064 +               return 0;\r
12065 +       else\r
12066 +               return 1;\r
12067 +}\r
12068 +\r
12069 +/************************************************************************/\r
12070 +/*                          GetFileNameList()                           */\r
12071 +/************************************************************************/\r
12072 +\r
12073 +/**\r
12074 + * \brief Fetch the file name list under the specified directory.\r
12075 + *\r
12076 + * This method will fetch the file name list under the specified directory,\r
12077 + * and store the results to a array.\r
12078 + *\r
12079 + * @param dir The directory name.\r
12080 + *\r
12081 + * @param strList The array used to place the results.\r
12082 + *\r
12083 + * @return CE_None on success or CE_Failure on failure.\r
12084 + */\r
12085 +\r
12086 +CPLErr CPL_STDCALL GetFileNameList(char* dir, vector<string> &strList)\r
12087 +{\r
12088 +       char pwdBuf[256];\r
12089 +       char *pwd=getcwd (pwdBuf, 256);\r
12090 +       DIR *dp;\r
12091 +       struct dirent *entry;\r
12092 +       struct stat statbuf;\r
12093 +       if ((dp = opendir(dir)) == NULL)\r
12094 +       {\r
12095 +               SetWCS_ErrorLocator("getFileNameList()");\r
12096 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Open Director %s", dir);\r
12097 +               return CE_Failure;\r
12098 +       }\r
12099 +\r
12100 +       if (dir[strlen(dir) - 1] == '/')\r
12101 +               dir[strlen(dir) - 1] = '\0';\r
12102 +\r
12103 +       chdir(dir);\r
12104 +\r
12105 +       while ((entry = readdir(dp)) != NULL)\r
12106 +       {\r
12107 +               lstat(entry->d_name, &statbuf);\r
12108 +               if (S_ISDIR(statbuf.st_mode))\r
12109 +               {\r
12110 +                       /* Found a directory, but ignore . and .. */\r
12111 +                       if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)\r
12112 +                               continue;\r
12113 +                       /* Recurse at a new indent level */\r
12114 +                       string subdir = dir;\r
12115 +                       subdir = subdir + "/" + entry->d_name;\r
12116 +                       GetFileNameList((char*)subdir.c_str(), strList);\r
12117 +               }\r
12118 +               else if (S_ISREG(statbuf.st_mode))\r
12119 +               {\r
12120 +                       string fname = getcwd(NULL, 0);\r
12121 +                       fname = fname + "/" + entry->d_name;\r
12122 +                       strList.push_back(fname);\r
12123 +               }\r
12124 +       }\r
12125 +       chdir(pwd);\r
12126 +       closedir(dp);\r
12127 +\r
12128 +       return CE_None;\r
12129 +}\r
12130 +\r
12131 +/************************************************************************/\r
12132 +/*                             Julian2Date()                            */\r
12133 +/************************************************************************/\r
12134 +\r
12135 +/**\r
12136 + * \brief Convert the Julian days to date string.\r
12137 + *\r
12138 + * This method will convert the days of year to its date string (YYYY-MM-DD);\r
12139 + *\r
12140 + * @param year The year of days.\r
12141 + *\r
12142 + * @param days The Julian days.\r
12143 + *\r
12144 + * @return The date string.\r
12145 + */\r
12146 +\r
12147 +string Julian2Date(int year, int days)\r
12148 +{\r
12149 +       bool leapyear = ((year%4==0 && year%100!=0) || year%400==0) ? true : false;\r
12150 +       int month, day;\r
12151 +\r
12152 +       int leapArr[24] = {1, 31, 32, 60, 61, 91, 92, 121, 122, 152, 153, 182, 183, 213, 214, 244,\r
12153 +               245, 274, 275, 305, 306, 335, 336, 366};\r
12154 +       int unLeArr[24] = {1, 31, 32, 59, 60, 90, 91, 120, 121, 151, 152, 181, 182, 212, 213, 243,\r
12155 +               244, 273, 274, 304, 305, 334, 335, 365};\r
12156 +\r
12157 +       if(leapyear) {\r
12158 +               for (int i = 0; i < 24; i += 2) {\r
12159 +                       if(days >= leapArr[i] && days <= leapArr[i+1]) {\r
12160 +                               month = int(i/2) + 1;\r
12161 +                               day = days - leapArr[i] + 1;\r
12162 +                               break;\r
12163 +                       }\r
12164 +               }\r
12165 +       } else {\r
12166 +               for (int i=0; i < 24; i += 2) {\r
12167 +                       if(days >= unLeArr[i] && days <= unLeArr[i+1]) {\r
12168 +                               month = int(i/2) + 1;\r
12169 +                               day = days - unLeArr[i] + 1;\r
12170 +                               break;\r
12171 +                       }\r
12172 +               }\r
12173 +       }\r
12174 +\r
12175 +       string monthStr = month<10 ? "0" + convertToString(month) : convertToString(month);\r
12176 +       string dayStr = day<10 ? "0" + convertToString(day) : convertToString(day);\r
12177 +\r
12178 +       return convertToString(year) + "-" + monthStr + "-" + dayStr;\r
12179 +}\r
12180 +\r
12181 +/************************************************************************/\r
12182 +/*                          GetTRMMBandList()                           */\r
12183 +/************************************************************************/\r
12184 +\r
12185 +/**\r
12186 + * \brief Fetch the day's list for TRMM data based on the range of date/time.\r
12187 + *\r
12188 + * This method will find day's list for TRMM data based on specified date/time\r
12189 + * range, and store the results to a array.\r
12190 + *\r
12191 + * @param start The start date/time.\r
12192 + *\r
12193 + * @param end The end date/time.\r
12194 + *\r
12195 + * @param bandList The array used to place the results.\r
12196 + *\r
12197 + * @return CE_None on success or CE_Failure on failure.\r
12198 + */\r
12199 +\r
12200 +CPLErr CPL_STDCALL GetTRMMBandList(string start, string end, std::vector<int> &bandList)\r
12201 +{\r
12202 +       //calculate 2000-06-01's days, start's days, end's days\r
12203 +       if(EQUAL(start.c_str(), "") && EQUAL(end.c_str(), ""))\r
12204 +               return CE_None;\r
12205 +\r
12206 +       string june1str = start.substr(0, 4) + "-06-01";\r
12207 +       long int june1sec = ConvertDateTimeToSeconds(june1str);\r
12208 +       long int startsec = 0, endsec = 0;\r
12209 +\r
12210 +       if(!EQUAL(start.c_str(), ""))\r
12211 +               startsec = ConvertDateTimeToSeconds(start);\r
12212 +       if(!EQUAL(end.c_str(), ""))\r
12213 +               endsec = ConvertDateTimeToSeconds(end);\r
12214 +\r
12215 +       int sdays = (int)(startsec - june1sec)/(24*3600) + 1;\r
12216 +       int edays = (int)(endsec - june1sec)/(24*3600) + 1;\r
12217 +\r
12218 +       sdays = (sdays < 0) ? 0 : sdays;\r
12219 +       edays = (edays < 0) ? sdays : edays;\r
12220 +\r
12221 +       for(int i = sdays; i <= edays; i++)\r
12222 +               bandList.push_back(i);\r
12223 +\r
12224 +       return CE_None;\r
12225 +}\r
12226 +\r
12227 +\r
12228 +/************************************************************************/\r
12229 +/*                          GetTimeString()                             */\r
12230 +/************************************************************************/\r
12231 +\r
12232 +/**\r
12233 + * \brief Fetch the current system time to a string.\r
12234 + *\r
12235 + * This method will get the current system time, and convert it to a string.\r
12236 + * The return date/time has two formats:\r
12237 + *             1: YYYYMMDDHHMMSS\r
12238 + *             2: YYYY-MM-DDTHH:MM:SSZ\r
12239 + *\r
12240 + * @param code The return string's format.\r
12241 + *\r
12242 + * @return The string corresponding to current system time.\r
12243 + */\r
12244 +\r
12245 +string GetTimeString(int code)\r
12246 +{\r
12247 +       struct tm* ptime;\r
12248 +       time_t now;\r
12249 +       time(&now);\r
12250 +       ptime = localtime(&now);\r
12251 +       int year = ptime->tm_year + 1900;\r
12252 +       int month = ptime->tm_mon + 1;\r
12253 +       int day = ptime->tm_mday;\r
12254 +       int hour = ptime->tm_hour;\r
12255 +       int minute = ptime->tm_min;\r
12256 +       int second = ptime->tm_sec;\r
12257 +       string ye, mo, da, ho, mi, se;\r
12258 +       ye = convertToString(year);\r
12259 +       mo = (month < 10) ? "0" + convertToString(month) : convertToString(month);\r
12260 +       da = (day < 10) ? "0" + convertToString(day) : convertToString(day);\r
12261 +       ho = (hour < 10)        ? "0" + convertToString(hour) : convertToString(hour);\r
12262 +       mi = (minute < 10)      ? "0" + convertToString(minute) : convertToString(minute);\r
12263 +       se = (second < 10)      ? "0" + convertToString(second) : convertToString(second);\r
12264 +\r
12265 +       string timestring;\r
12266 +       if(code == 1)\r
12267 +       {\r
12268 +               string part1 = ye + mo + da;\r
12269 +               string part2 = ho + mi + se;\r
12270 +               timestring = part1.append(part2);\r
12271 +       }\r
12272 +       else if(code == 2)\r
12273 +       {\r
12274 +               string part1 = ye + "-" + mo + "-" + da + "T";\r
12275 +               string part2 = ho + ":" + mi + ":" + se + "Z";\r
12276 +               timestring = part1.append(part2);\r
12277 +       }\r
12278 +\r
12279 +       return timestring;\r
12280 +}\r
12281 +\r
12282 +/************************************************************************/\r
12283 +/*                          MakeTempFile()                              */\r
12284 +/************************************************************************/\r
12285 +\r
12286 +/**\r
12287 + * \brief Generate a temporary file path.\r
12288 + *\r
12289 + * This method will generate a path for temporary file or output file,\r
12290 + * which is based on coverage identifier.\r
12291 + *\r
12292 + * @param dir The directory of the temporary file.\r
12293 + *\r
12294 + * @param covID The coverage identifier.\r
12295 + *\r
12296 + * @param suffix The suffix of the file format.\r
12297 + *\r
12298 + * @return The full path of the temporary file.\r
12299 + */\r
12300 +\r
12301 +string MakeTempFile(string dir, string covID, string suffix)\r
12302 +{\r
12303 +       string sOutFileName;\r
12304 +\r
12305 +       if (!dir.empty() && dir != "")\r
12306 +       {\r
12307 +               if (dir[dir.length() - 1] != '/')\r
12308 +               {\r
12309 +                       dir += "/";\r
12310 +               }\r
12311 +       }\r
12312 +       if (!suffix.empty() && suffix != "")\r
12313 +       {\r
12314 +               if (suffix[0] != '.')\r
12315 +                       suffix = "." + suffix;\r
12316 +       }\r
12317 +\r
12318 +       if(covID == "")\r
12319 +       {\r
12320 +               sOutFileName = dir + GetUUID() + suffix;\r
12321 +       }\r
12322 +       else if (EQUALN(covID.c_str(),"HDF4_EOS:EOS_SWATH:",19) ||\r
12323 +               EQUALN(covID.c_str(),"HDF4_EOS:EOS_GRID:",18) ||\r
12324 +               EQUALN(covID.c_str(),"HDF5:",5))\r
12325 +       {\r
12326 +               vector<string> strSet;\r
12327 +               int n = CsvburstCpp(covID, strSet, ':');\r
12328 +               if(n == 5){//Terra&Aqua\r
12329 +                       string srcFilePath = StrTrims(strSet[2], "\'\"");\r
12330 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
12331 +                       string datasetname = StrTrims(strSet[4], "\'\"");\r
12332 +                       datasetname = StrReplace(datasetname, " ", "_");\r
12333 +                       sOutFileName = dir + srcFileName + "." + datasetname + "." + GetTimeString(1) + suffix;\r
12334 +               }else if(n == 3) {//Aura\r
12335 +                       string srcFilePath = StrTrims(strSet[1], "\'\"");\r
12336 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
12337 +                       string datasetname = StrTrims(strSet[2], "\'\"");\r
12338 +                       datasetname = StrReplace(datasetname, "//", "");\r
12339 +                       datasetname = StrReplace(datasetname, "/", "_");\r
12340 +                       datasetname = StrReplace(datasetname, " ", "");\r
12341 +                       sOutFileName = dir + srcFileName + "." + datasetname + "." + GetTimeString(1) + suffix;\r
12342 +               }else\r
12343 +                       sOutFileName = dir + GetUUID() + suffix;\r
12344 +       }else if(EQUALN( covID.c_str(), "GOES:NetCDF:",12))\r
12345 +       {\r
12346 +               vector<string> strSet;\r
12347 +               int n = CsvburstCpp(covID, strSet, ':');\r
12348 +               if(n == 4){\r
12349 +                       string srcFilePath = StrTrims(strSet[2], " \'\"");\r
12350 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
12351 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
12352 +               }else\r
12353 +                       sOutFileName = dir + GetUUID() + suffix;\r
12354 +       }\r
12355 +       else if(EQUALN(covID.c_str(),"GEOTIFF:",8))\r
12356 +       {\r
12357 +               vector<string> strSet;\r
12358 +               int n = CsvburstCpp(covID, strSet, ':');\r
12359 +               if(n == 3){\r
12360 +                       string srcFilePath = StrTrims(strSet[1], " \'\"");\r
12361 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
12362 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
12363 +               }else\r
12364 +                       sOutFileName = dir + GetUUID() + suffix;\r
12365 +       }\r
12366 +       else if(EQUALN(covID.c_str(),"TRMM:",5))\r
12367 +       {\r
12368 +               vector<string> strSet;\r
12369 +               int n = CsvburstCpp(covID, strSet, ':');\r
12370 +               if(n == 3){\r
12371 +                       string srcFilePath = StrTrims(strSet[1], " \'\"");\r
12372 +                       string srcFileName = string(CPLGetBasename(srcFilePath.c_str()));\r
12373 +                       sOutFileName = dir + srcFileName + "." + GetTimeString(1) + suffix;\r
12374 +               }else\r
12375 +                       sOutFileName = dir + GetUUID() + suffix;\r
12376 +       }\r
12377 +       else\r
12378 +               sOutFileName = dir + GetUUID() + suffix;\r
12379 +\r
12380 +       return sOutFileName;\r
12381 +}\r
12382 +\r
12383 +/************************************************************************/\r
12384 +/*                          StringList()                                */\r
12385 +/************************************************************************/\r
12386 +\r
12387 +/**\r
12388 + * \brief Constructor for StringList.\r
12389 + */\r
12390 +\r
12391 +StringList::StringList(const string& sstrings, const char delimiter)\r
12392 +{\r
12393 +       string str = sstrings + delimiter;\r
12394 +       string::size_type np, op = 0;\r
12395 +       while ((op < str.size())\r
12396 +                       && ((np = str.find(delimiter, op)) != string::npos))\r
12397 +       {\r
12398 +               add(str.substr(op, np - op));\r
12399 +               op = ++np;\r
12400 +       }\r
12401 +}\r
12402 +\r
12403 +// -----------------------------------------------------------------------\r
12404 +// string list constructor\r
12405 +// -----------------------------------------------------------------------\r
12406 +StringList::StringList(const string& sstrings, const string& delimiters)\r
12407 +{\r
12408 +       string str = sstrings + delimiters;\r
12409 +       string::size_type np, op = 0;\r
12410 +       while ((op < str.size()) && ((np = str.find(delimiters, op))\r
12411 +                       != string::npos))\r
12412 +       {\r
12413 +               add(str.substr(op, np - op));\r
12414 +               op = np + delimiters.length();\r
12415 +       }\r
12416 +}\r
12417 +\r
12418 +// -----------------------------------------------------------------------\r
12419 +// string list -- append\r
12420 +// -----------------------------------------------------------------------\r
12421 +void StringList::append(StringList & s)\r
12422 +{\r
12423 +       for (int i = 0; i < s.size(); i++)\r
12424 +               add(s[i]);\r
12425 +}\r
12426 +\r
12427 +// -----------------------------------------------------------------------\r
12428 +// string list -- append with delimiter\r
12429 +// -----------------------------------------------------------------------\r
12430 +void StringList::append(const string sstrings, const char delimiter)\r
12431 +{\r
12432 +       StringList n(sstrings, delimiter);\r
12433 +       append(n);\r
12434 +}\r
12435 +\r
12436 +// -----------------------------------------------------------------------\r
12437 +// string list -- append with delimiters\r
12438 +// -----------------------------------------------------------------------\r
12439 +void StringList::append(const string sstrings, const string& delimiters)\r
12440 +{\r
12441 +       StringList n(sstrings, delimiters);\r
12442 +       append(n);\r
12443 +}\r
12444 +\r
12445 +// -----------------------------------------------------------------------\r
12446 +// string list -- return the index for query string\r
12447 +// -----------------------------------------------------------------------\r
12448 +int StringList::indexof(string qstr)\r
12449 +{\r
12450 +       for (int i = 0; i < size(); i++)\r
12451 +       {\r
12452 +               if (strings[i] == qstr)\r
12453 +                       return i;\r
12454 +       }\r
12455 +       return -1;\r
12456 +}\r
12457 +\r
12458 +/************************************************************************/\r
12459 +/*                          KVP()                                       */\r
12460 +/************************************************************************/\r
12461 +\r
12462 +/**\r
12463 + * \brief Constructor for KVP.\r
12464 + *\r
12465 + * @param namevaluepair The key-value pair.\r
12466 + */\r
12467 +\r
12468 +KVP::KVP(string namevaluepair)\r
12469 +{\r
12470 +       StringList ss(namevaluepair, '=');\r
12471 +       if (ss.size() == 2)\r
12472 +       {\r
12473 +               name = StrTrim(ss[0]);\r
12474 +               value = StrTrim(ss[1]);\r
12475 +       }\r
12476 +       else\r
12477 +       {\r
12478 +               name = namevaluepair;\r
12479 +               value = "";\r
12480 +       }\r
12481 +}\r
12482 +\r
12483 +/************************************************************************/\r
12484 +/*                          CFGReader()                                 */\r
12485 +/************************************************************************/\r
12486 +\r
12487 +/**\r
12488 + * \brief Constructor for CFGReader.\r
12489 + *\r
12490 + * This method is used to load the configuration file for WCS. Each configuration\r
12491 + * item looks like a key-value pair, CFGReader() will read the file to memory and\r
12492 + * store the parameters to a KVP array.\r
12493 + *\r
12494 + * @param configfilename The full path of the configuration file.\r
12495 + */\r
12496 +\r
12497 +CFGReader::CFGReader(const string &configfilename)\r
12498 +{\r
12499 +       ifstream cfgfile(configfilename.c_str());\r
12500 +       if (!cfgfile)\r
12501 +       {\r
12502 +               SetWCS_ErrorLocator("CFGReader");\r
12503 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open configure file.");\r
12504 +               throw runtime_error("");\r
12505 +       }\r
12506 +\r
12507 +       char line[MAX_LINE_LEN];\r
12508 +       while (!cfgfile.eof())\r
12509 +       {\r
12510 +               cfgfile.getline(line, MAX_LINE_LEN - 1, '\n');\r
12511 +               if (!cfgfile.fail())\r
12512 +               {\r
12513 +                       if (line[0] != '#')\r
12514 +                       {\r
12515 +                               KVP kvp(line);\r
12516 +                               kvps.push_back(kvp);\r
12517 +                       }\r
12518 +               }\r
12519 +       }\r
12520 +\r
12521 +       cfgfile.close();\r
12522 +}\r
12523 +\r
12524 +/************************************************************************/\r
12525 +/*                          getValue()                                  */\r
12526 +/************************************************************************/\r
12527 +\r
12528 +/**\r
12529 + * \brief Fetch a configured item's value.\r
12530 + *\r
12531 + * This method is used to fetch a items value from a configuration file.\r
12532 + *\r
12533 + * @param keyname The item's name.\r
12534 + *\r
12535 + * @return The result string.\r
12536 + */\r
12537 +\r
12538 +string CFGReader::getValue(const string &keyname)\r
12539 +{\r
12540 +       for (int i = 0; i < size(); i++)\r
12541 +       {\r
12542 +               if (EQUAL(kvps[i].name.c_str(), keyname.c_str()))\r
12543 +                       return kvps[i].value;\r
12544 +       }\r
12545 +\r
12546 +       return "";\r
12547 +}\r
12548 +\r
12549 +/************************************************************************/\r
12550 +/*                          getValue()                                  */\r
12551 +/************************************************************************/\r
12552 +\r
12553 +/**\r
12554 + * \brief Fetch a configured item's value, with default value.\r
12555 + *\r
12556 + * This method is used to fetch a items value from a configuration file,\r
12557 + * if not found, use the default value.\r
12558 + *\r
12559 + * @param keyname The item's name.\r
12560 + *\r
12561 + * @param defaultvalue The item's default value.\r
12562 + *\r
12563 + * @return The result string.\r
12564 + */\r
12565 +\r
12566 +string CFGReader::getValue(const string &keyname, const string &defaultvalue)\r
12567 +{\r
12568 +       string ret = getValue(keyname);\r
12569 +       if (ret.empty() || ret == "")\r
12570 +               return defaultvalue;\r
12571 +       else\r
12572 +               return ret;\r
12573 +}\r
12574 +\r
12575 +/************************************************************************/\r
12576 +/*                          Run()                                       */\r
12577 +/************************************************************************/\r
12578 +\r
12579 +/**\r
12580 + * \brief The entry point for CGI program.\r
12581 + *\r
12582 + * This method is used to fetch CGI parameters. Supports both HTTP GET\r
12583 + * and POST method. POST content could be KVPs and XML string, and GET\r
12584 + * content must be KVPs.\r
12585 + *\r
12586 + * @return CE_None on success or CE_Failure on failure.\r
12587 + */\r
12588 +\r
12589 +CPLErr WCSCGI::Run()\r
12590 +{\r
12591 +       /* get request parameters*/\r
12592 +       char *gm = getenv("REQUEST_METHOD");\r
12593 +       if (NULL == gm)\r
12594 +       {\r
12595 +               SetWCS_ErrorLocator("WCSCGI::Run()");\r
12596 +               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Get \"REQUEST_METHOD\" Environment variable.");\r
12597 +               return CE_Failure;\r
12598 +       }\r
12599 +\r
12600 +       if (EQUAL(gm, "POST"))\r
12601 +               me_CGIMethod = HTTP_XML_POST;\r
12602 +       else if (EQUAL(gm, "GET"))\r
12603 +               me_CGIMethod = HTTP_GET;\r
12604 +       else\r
12605 +               me_CGIMethod = UN_KNOWN;\r
12606 +\r
12607 +       switch (me_CGIMethod)\r
12608 +       {\r
12609 +               case HTTP_XML_POST:\r
12610 +               {\r
12611 +                       char* aString = getenv("CONTENT_LENGTH");\r
12612 +                       if (NULL == aString || aString[0] == '\0')\r
12613 +                       {\r
12614 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Get \"CONTENT_LENGTH\" Environment variable.");\r
12615 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
12616 +                               return CE_Failure;\r
12617 +                       }\r
12618 +\r
12619 +                       unsigned int cLength = atoi(aString);\r
12620 +\r
12621 +                       string cString;\r
12622 +                       cString.resize(cLength + 1);\r
12623 +\r
12624 +                       if (cLength != fread((char*) cString.c_str(), 1, cLength, stdin))\r
12625 +                       {\r
12626 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
12627 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Read POST Data Stream from Internet.");\r
12628 +                               return CE_Failure;\r
12629 +                       }\r
12630 +\r
12631 +                       cString = StrReplace(cString, "&amps;", "%26");\r
12632 +                       cString = StrReplace(cString, "&amp;", "%26");\r
12633 +\r
12634 +                       string tmpStr = CPLUnescapeString(cString.c_str(), NULL, CPLES_URL);\r
12635 +                       ms_CGIContent = CPLUnescapeString((char*) tmpStr.c_str(), NULL, CPLES_XML);\r
12636 +\r
12637 +                       string::size_type beginIdx, endIdx;\r
12638 +\r
12639 +                       beginIdx = ms_CGIContent.find("<?");\r
12640 +                       endIdx = ms_CGIContent.rfind(">");\r
12641 +                       //The post contents could be KVPs\r
12642 +                       if (beginIdx != string::npos && endIdx != string::npos)\r
12643 +                               ms_CGIContent = ms_CGIContent.substr(beginIdx, endIdx - beginIdx + 1);\r
12644 +               }\r
12645 +                       break;\r
12646 +               case HTTP_GET:\r
12647 +               {\r
12648 +                       string tmpStr = getenv("QUERY_STRING");\r
12649 +                       tmpStr = StrReplace(tmpStr, "&amps;", "%26");\r
12650 +                       tmpStr = StrReplace(tmpStr, "&amp;", "%26");\r
12651 +                       if (tmpStr.empty() || tmpStr == "")\r
12652 +                       {\r
12653 +                               SetWCS_ErrorLocator("WCSCGI::Run()");\r
12654 +                               WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "No \"QUERY_STRING\" Content.");\r
12655 +                               return CE_Failure;\r
12656 +                       }\r
12657 +\r
12658 +                       ms_CGIContent = CPLUnescapeString((char*) tmpStr.c_str(), NULL, CPLES_URL);\r
12659 +               }\r
12660 +                       break;\r
12661 +               default:\r
12662 +               {\r
12663 +                       SetWCS_ErrorLocator("WCSCGI::Run()");\r
12664 +                       WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Unkown \"REQUEST_METHOD\".");\r
12665 +                       return CE_Failure;\r
12666 +               }\r
12667 +       }\r
12668 +\r
12669 +       return CE_None;\r
12670 +}\r
12671 +\r
12672 +// -----------------------------------------------------------------------\r
12673 +// KVPsReader constructor\r
12674 +// -----------------------------------------------------------------------\r
12675 +KVPsReader::KVPsReader(const string& urlStr, const char &tok)\r
12676 +{\r
12677 +       StringList strLit(urlStr, tok);\r
12678 +\r
12679 +       for (int i = 0; i < strLit.size(); ++i)\r
12680 +       {\r
12681 +               KVP kvp(StrTrim(strLit[i]));\r
12682 +               m_kvps.push_back(kvp);\r
12683 +       }\r
12684 +}\r
12685 +\r
12686 +// -----------------------------------------------------------------------\r
12687 +// KVPsReader get value function\r
12688 +// -----------------------------------------------------------------------\r
12689 +string KVPsReader::getValue(const string &keyname)\r
12690 +{\r
12691 +       for (unsigned int i = 0; i < m_kvps.size(); i++)\r
12692 +       {\r
12693 +               if (EQUAL(m_kvps[i].name.c_str() , keyname.c_str()))\r
12694 +                       return m_kvps[i].value;\r
12695 +       }\r
12696 +       return "";\r
12697 +}\r
12698 +\r
12699 +\r
12700 +vector<string> KVPsReader::getValues(const string &keyname)\r
12701 +{\r
12702 +       vector<string> valuesList;\r
12703 +       for (unsigned int i = 0; i < m_kvps.size(); i++)\r
12704 +       {\r
12705 +               if (EQUAL(m_kvps[i].name.c_str() , keyname.c_str()))\r
12706 +                       valuesList.push_back(m_kvps[i].value);\r
12707 +       }\r
12708 +       return valuesList;\r
12709 +}\r
12710 +\r
12711 +// -----------------------------------------------------------------------\r
12712 +// KVPsReader get value function, with default value\r
12713 +// -----------------------------------------------------------------------\r
12714 +string KVPsReader::getValue(const string &keyname, const string &defaultvalue)\r
12715 +{\r
12716 +       string ret = getValue(keyname);\r
12717 +       if (ret.empty() || ret == "")\r
12718 +               return defaultvalue;\r
12719 +       else\r
12720 +               return ret;\r
12721 +}\r
12722 +\r
12723 +/************************************************************************/\r
12724 +/*                          StrReplace()                                */\r
12725 +/************************************************************************/\r
12726 +\r
12727 +/**\r
12728 + * \brief Replace a string.\r
12729 + *\r
12730 + * This method is used to replace a string with specified substring.\r
12731 + *\r
12732 + * @param str The string needs to be processed.\r
12733 + *\r
12734 + * @param oldSubStr The substring needs to be replaced.\r
12735 + *\r
12736 + * @param newStr The string will replace the oldSubStr.\r
12737 + *\r
12738 + * @return The processed string.\r
12739 + */\r
12740 +\r
12741 +string CPL_STDCALL StrReplace(string& str, const string oldSubStr, const string newStr)\r
12742 +{\r
12743 +       while(true)\r
12744 +       {\r
12745 +               string::size_type pos(0);\r
12746 +               if( ( pos = str.find(oldSubStr) ) != string::npos )\r
12747 +               {\r
12748 +                       str.replace( pos, oldSubStr.length(), newStr );\r
12749 +               }else {\r
12750 +                       break;\r
12751 +               }\r
12752 +       }\r
12753 +       return str;\r
12754 +}\r
12755 +\r
12756 +/************************************************************************/\r
12757 +/*                          GetSingleValue()                            */\r
12758 +/************************************************************************/\r
12759 +\r
12760 +/**\r
12761 + * \brief Get a single value from a special KVP part.\r
12762 + *\r
12763 + * This method is used to get value from a special KVP part.\r
12764 + *\r
12765 + * @param subsetstr The string needs to be processed, such as "subset=Long(11)".\r
12766 + *\r
12767 + * @return The processed string, such as "11".\r
12768 + */\r
12769 +\r
12770 +string CPL_STDCALL GetSingleValue(const string& subsetstr)\r
12771 +{\r
12772 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
12773 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
12774 +\r
12775 +       return StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 -1));\r
12776 +}\r
12777 +\r
12778 +/************************************************************************/\r
12779 +/*                          GetSubSetLatLon()                           */\r
12780 +/************************************************************************/\r
12781 +\r
12782 +/**\r
12783 + * \brief Get a subset spatial extent in WCS 2.0 request.\r
12784 + *\r
12785 + * This method is used to get values of spatial extent and place the values\r
12786 + * in an array, and return the CRS code for the coordinates of the extent.\r
12787 + *\r
12788 + * @param subsetstr The string needs to be processed,\r
12789 + * such as "subset=Lat,http://www.opengis.net/def/crs/EPSG/0/4326(32,47)".\r
12790 + *\r
12791 + * @param subsetvalue The array to place the spatial extent values.\r
12792 + *\r
12793 + * @return The processed string, such as "EPSG:4326".\r
12794 + */\r
12795 +\r
12796 +string CPL_STDCALL GetSubSetLatLon(const string& subsetstr, vector<double> &subsetvalue)\r
12797 +{\r
12798 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
12799 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
12800 +\r
12801 +       string value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 -1));\r
12802 +       vector<string> tmpV;\r
12803 +       CsvburstCpp(value, tmpV, ',');\r
12804 +\r
12805 +       for(unsigned int i = 0; i < tmpV.size(); i++)\r
12806 +       {\r
12807 +               double curD;\r
12808 +               convertFromString(curD, tmpV.at(i));\r
12809 +               subsetvalue.push_back(curD);\r
12810 +       }\r
12811 +\r
12812 +       string subsetProj;\r
12813 +       idx1 = subsetstr.find(',');\r
12814 +       idx2 = subsetstr.find('(');\r
12815 +       if(idx1 > idx2) \r
12816 +       {\r
12817 +               subsetProj = "EPSG:4326";\r
12818 +       }\r
12819 +       else\r
12820 +       {\r
12821 +               value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 - 1));\r
12822 +               if(value.find("http") != string::npos)\r
12823 +               {\r
12824 +                       string::size_type idx3 = value.find_last_of('/');\r
12825 +                       subsetProj = "EPSG:" + value.substr(idx3 + 1);\r
12826 +               }\r
12827 +               else\r
12828 +               {\r
12829 +                       subsetProj = value;\r
12830 +               }\r
12831 +\r
12832 +       }\r
12833 +\r
12834 +       return subsetProj;\r
12835 +}\r
12836 +\r
12837 +//subset=phenomenonTime("2006-08-01","2006-08-22T09:22:00Z")&\r
12838 +//subset=phenomenonTime("2006-08-01")&\r
12839 +void CPL_STDCALL GetSubSetTime(const string& subsetstr, vector<string> &subsetvalue)\r
12840 +{\r
12841 +       string::size_type idx1 = subsetstr.find_last_of('(');\r
12842 +       string::size_type idx2 = subsetstr.find_last_of(')');\r
12843 +       string value = StrTrim(subsetstr.substr(idx1 + 1, idx2 - idx1 - 1));\r
12844 +       string valueN = StrReplace(value, "\"", "");\r
12845 +       CsvburstCpp(valueN, subsetvalue, ',');\r
12846 +}\r
12847 +\r
12848 +//time type 1: 2006-08-22T09:22:00Z\r
12849 +//time type 1: 2006-08-01\r
12850 +int CPL_STDCALL CompareDateTime_GreaterThan(string time1, string time2)\r
12851 +{\r
12852 +       time_t retval1 = 0;\r
12853 +       time_t retval2 = 0;\r
12854 +\r
12855 +       struct tm storage1 = {0,0,0,0,0,0,0,0,0};\r
12856 +       struct tm storage2 = {0,0,0,0,0,0,0,0,0};\r
12857 +\r
12858 +       char *p1 = NULL;\r
12859 +       char *p2 = NULL;\r
12860 +\r
12861 +       if(time1.find("T") != string::npos && time1.find("Z") != string::npos)\r
12862 +               p1 =    (char *)strptime(time1.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage1);\r
12863 +       else\r
12864 +               p1 = (char *)strptime(time1.c_str(), "%Y-%m-%d", &storage1);\r
12865 +\r
12866 +       if(time2.find("T") != string::npos && time2.find("Z") != string::npos)\r
12867 +               p2 =    (char *)strptime(time2.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage2);\r
12868 +       else\r
12869 +               p2 = (char *)strptime(time2.c_str(), "%Y-%m-%d", &storage2);\r
12870 +\r
12871 +       retval1 = mktime(&storage1);\r
12872 +       retval2 = mktime(&storage2);\r
12873 +\r
12874 +       if(retval1 == retval2)\r
12875 +               return 0;\r
12876 +       else if(retval1 > retval2)\r
12877 +               return 1;\r
12878 +       else\r
12879 +               return -1;\r
12880 +\r
12881 +}\r
12882 +\r
12883 +int CPL_STDCALL        ConvertDateTimeToSeconds(string datetime)\r
12884 +{\r
12885 +       time_t retval1 = 0;\r
12886 +       struct tm storage1 = {0,0,0,0,0,0,0,0,0};\r
12887 +       char *p1 = NULL;\r
12888 +\r
12889 +       if(datetime.find("T") != string::npos && datetime.find("Z") != string::npos)\r
12890 +               p1 =    (char *)strptime(datetime.c_str(), "%Y-%m-%dT%H:%M:%SZ", &storage1);\r
12891 +       else\r
12892 +               p1 = (char *)strptime(datetime.c_str(), "%Y-%m-%d", &storage1);\r
12893 +\r
12894 +       retval1 = mktime(&storage1);\r
12895 +\r
12896 +       return retval1;\r
12897 +}\r
12898 +\r
12899 +// -----------------------------------------------------------------------\r
12900 +// Find lower-left and upper-right corner point coordinate\r
12901 +// -----------------------------------------------------------------------\r
12902 +void CPL_STDCALL GetCornerPoints(const GDAL_GCP* &pGCPList, const int &nGCPs, My2DPoint& lowLeft, My2DPoint& upRight)\r
12903 +{\r
12904 +        double xLeft = (numeric_limits<double>::max)();\r
12905 +        double xRight = -xLeft;\r
12906 +        double yLower = (numeric_limits<double>::max)();\r
12907 +        double yUpper = -yLower;\r
12908 +\r
12909 +        for (int j = 0; j < nGCPs; j++)\r
12910 +        {\r
12911 +                yUpper = MAX(yUpper,pGCPList[j].dfGCPY);\r
12912 +                yLower = MIN(yLower,pGCPList[j].dfGCPY);\r
12913 +                if(pGCPList[j].dfGCPX != -999)//test MOD021KM.A2000065.1900.005.2008235220315.hdf, error GCP X value (-999)\r
12914 +                        xLeft = MIN(xLeft,pGCPList[j].dfGCPX);\r
12915 +                xRight = MAX(xRight,pGCPList[j].dfGCPX);\r
12916 +        }\r
12917 +\r
12918 +        lowLeft.mi_X = xLeft;\r
12919 +        lowLeft.mi_Y = yLower;\r
12920 +        upRight.mi_X = xRight;\r
12921 +        upRight.mi_Y = yUpper;\r
12922 +\r
12923 +        return;\r
12924 +}\r
12925 diff -Nur bes-3.12.0/functions.orig/swath2grid/wcsUtil.h bes-3.12.0/functions/swath2grid/wcsUtil.h
12926 --- bes-3.12.0/functions.orig/swath2grid/wcsUtil.h      1970-01-01 01:00:00.000000000 +0100
12927 +++ bes-3.12.0/functions/swath2grid/wcsUtil.h   2014-03-03 15:47:38.043566262 +0100
12928 @@ -0,0 +1,381 @@
12929 +/******************************************************************************\r
12930 + * $Id: wcsUtil.h 2011-07-19 16:24:00Z $\r
12931 + *\r
12932 + * Project:  The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)\r
12933 + *                      for Earth Observation: Open Source Reference Implementation\r
12934 + * Purpose:  WCS Utility Function definition\r
12935 + * Author:   Yuanzheng Shao, yshao3@gmu.edu\r
12936 + *\r
12937 + ******************************************************************************\r
12938 + * Copyright (c) 2011, Liping Di <ldi@gmu.edu>, Yuanzheng Shao <yshao3@gmu.edu>\r
12939 + *\r
12940 + * Permission is hereby granted, free of charge, to any person obtaining a\r
12941 + * copy of this software and associated documentation files (the "Software"),\r
12942 + * to deal in the Software without restriction, including without limitation\r
12943 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
12944 + * and/or sell copies of the Software, and to permit persons to whom the\r
12945 + * Software is furnished to do so, subject to the following conditions:\r
12946 + *\r
12947 + * The above copyright notice and this permission notice shall be included\r
12948 + * in all copies or substantial portions of the Software.\r
12949 + *\r
12950 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
12951 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
12952 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
12953 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
12954 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
12955 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
12956 + * DEALINGS IN THE SOFTWARE.\r
12957 + ****************************************************************************/\r
12958 +\r
12959 +#ifndef WCSUTIL_H_\r
12960 +#define WCSUTIL_H_\r
12961 +\r
12962 +#include <iostream>\r
12963 +#include <fstream>\r
12964 +#include <sstream>\r
12965 +#include <vector>\r
12966 +#include <stdlib.h>\r
12967 +#include <time.h>\r
12968 +\r
12969 +#include <cpl_string.h>\r
12970 +#include "wcs_error.h"\r
12971 +#include "BoundingBox.h"\r
12972 +\r
12973 +using namespace std;\r
12974 +\r
12975 +#ifndef EQUAL\r
12976 +#if defined(WIN32) || defined(WIN32CE)\r
12977 +#  define EQUALN(a,b,n)           (strnicmp(a,b,n)==0)\r
12978 +#  define EQUAL(a,b)              (stricmp(a,b)==0)\r
12979 +#else\r
12980 +#  define EQUALN(a,b,n)           (strncasecmp(a,b,n)==0)\r
12981 +#  define EQUAL(a,b)              (strcasecmp(a,b)==0)\r
12982 +#endif\r
12983 +#endif\r
12984 +\r
12985 +#ifndef TRUE\r
12986 +#define TRUE 1\r
12987 +#endif\r
12988 +#ifndef FALSE\r
12989 +#define FALSE 0\r
12990 +#endif\r
12991 +\r
12992 +#ifndef NULL\r
12993 +#define NULL 0\r
12994 +#endif\r
12995 +\r
12996 +#ifdef WINDOWS\r
12997 +#define DELIMITER "\\"\r
12998 +#else\r
12999 +#define DELIMITER "/"\r
13000 +#endif\r
13001 +\r
13002 +const int SHORT_NAME_LEN = 128;\r
13003 +const int MAX_NAME_LEN = 512;\r
13004 +const int MAX_LIST_LEN = 1024;\r
13005 +const int MAX_LINE_LEN = 65536;\r
13006 +\r
13007 +\r
13008 +// -----------------------------------------------------------------------\r
13009 +// CGI (Common Gateway Interface) related class and functions\r
13010 +// -----------------------------------------------------------------------\r
13011 +enum CGI_METHOD_FLAG\r
13012 +{\r
13013 +       UN_KNOWN, HTTP_GET, HTTP_XML_POST\r
13014 +};\r
13015 +\r
13016 +/************************************************************************/\r
13017 +/* ==================================================================== */\r
13018 +/*                             WCSCGI                                   */\r
13019 +/* ==================================================================== */\r
13020 +/************************************************************************/\r
13021 +\r
13022 +/**\r
13023 + * \class WCSCGI "wcsUtil.h"\r
13024 + *\r
13025 + * WCSCGI class is used to acquire WCS request, both GET and POST method\r
13026 + * are supported.\r
13027 + */\r
13028 +\r
13029 +class WCSCGI\r
13030 +{\r
13031 +private:\r
13032 +       string ms_CGIContent;\r
13033 +       CGI_METHOD_FLAG me_CGIMethod;\r
13034 +\r
13035 +public:\r
13036 +       WCSCGI()\r
13037 +       {\r
13038 +               me_CGIMethod = UN_KNOWN;\r
13039 +       }\r
13040 +\r
13041 +       CPLErr Run();\r
13042 +\r
13043 +       string GetRqstContent()\r
13044 +       {\r
13045 +               return ms_CGIContent;\r
13046 +       }\r
13047 +\r
13048 +       CGI_METHOD_FLAG GetCGImethod()\r
13049 +       {\r
13050 +               return me_CGIMethod;\r
13051 +       }\r
13052 +};\r
13053 +\r
13054 +/************************************************************************/\r
13055 +/* ==================================================================== */\r
13056 +/*                             StringList                               */\r
13057 +/* ==================================================================== */\r
13058 +/************************************************************************/\r
13059 +\r
13060 +class StringList\r
13061 +{\r
13062 +private:\r
13063 +       vector<string> strings;\r
13064 +\r
13065 +public:\r
13066 +       StringList(const string& sstrings, const char delimiter);\r
13067 +       StringList(const string& sstrings, const string& delimiters);\r
13068 +       StringList(){ }\r
13069 +\r
13070 +       int indexof(string qstr);\r
13071 +\r
13072 +       void add(string newstr)\r
13073 +       {\r
13074 +               strings.push_back(newstr);\r
13075 +       }\r
13076 +\r
13077 +       void clear()\r
13078 +       {\r
13079 +               strings.clear();\r
13080 +       }\r
13081 +\r
13082 +       int size()\r
13083 +       {\r
13084 +               return strings.size();\r
13085 +       }\r
13086 +\r
13087 +       string& operator [](int index)\r
13088 +       {\r
13089 +               return strings[index];\r
13090 +       }\r
13091 +\r
13092 +       void append(StringList & s);\r
13093 +       void append(const string sstrings, const char delimiter);\r
13094 +       void append(const string sstrings, const string& delimiters);\r
13095 +\r
13096 +       string toString()\r
13097 +       {\r
13098 +               string s = "";\r
13099 +               for (int i = 0; i < size(); i++)\r
13100 +                       s += strings[i];\r
13101 +               return s;\r
13102 +       }\r
13103 +\r
13104 +       string toString(const char delimiter)\r
13105 +       {\r
13106 +               string s = "";\r
13107 +               for (int i = 0; i < size(); i++)\r
13108 +                       s += strings[i] + delimiter;\r
13109 +               return s;\r
13110 +       }\r
13111 +\r
13112 +       string toString(const string& delimiters)\r
13113 +       {\r
13114 +               string s = "";\r
13115 +               for (int i = 0; i < size(); i++)\r
13116 +                       s += strings[i] + delimiters;\r
13117 +               return s;\r
13118 +       }\r
13119 +};\r
13120 +\r
13121 +class S2C\r
13122 +{\r
13123 +\r
13124 +private:\r
13125 +       char buf[MAX_LINE_LEN];\r
13126 +\r
13127 +public:\r
13128 +       S2C(string s)\r
13129 +       {\r
13130 +               s.copy(buf, string::npos);\r
13131 +               buf[s.size()] = 0;\r
13132 +       }\r
13133 +\r
13134 +       char * c_str()\r
13135 +       {\r
13136 +               return buf;\r
13137 +       }\r
13138 +\r
13139 +};\r
13140 +\r
13141 +/************************************************************************/\r
13142 +/* ==================================================================== */\r
13143 +/*                             KVP                                      */\r
13144 +/* ==================================================================== */\r
13145 +/************************************************************************/\r
13146 +\r
13147 +class KVP\r
13148 +{\r
13149 +public:\r
13150 +       string name, value;\r
13151 +\r
13152 +       KVP& operator =(const KVP &id)\r
13153 +       {\r
13154 +               name = id.name;\r
13155 +               value = id.value;\r
13156 +               return *this;\r
13157 +       }\r
13158 +\r
13159 +       KVP& operator =(const KVP *pid)\r
13160 +       {\r
13161 +               name = pid->name;\r
13162 +               value = pid->value;\r
13163 +               return *this;\r
13164 +       }\r
13165 +\r
13166 +       KVP(string n, string v) :\r
13167 +               name(n), value(v)\r
13168 +       {\r
13169 +       }\r
13170 +\r
13171 +       KVP(string namevaluepair);\r
13172 +};\r
13173 +\r
13174 +\r
13175 +/************************************************************************/\r
13176 +/* ==================================================================== */\r
13177 +/*                             KVPsReader                               */\r
13178 +/* ==================================================================== */\r
13179 +/************************************************************************/\r
13180 +\r
13181 +class KVPsReader\r
13182 +{\r
13183 +protected:\r
13184 +       vector<KVP> m_kvps;\r
13185 +\r
13186 +public:\r
13187 +       KVPsReader()\r
13188 +       {\r
13189 +       }\r
13190 +\r
13191 +       ~KVPsReader()\r
13192 +       {\r
13193 +       }\r
13194 +\r
13195 +       KVPsReader(const string& urlStr, const char &tok);\r
13196 +\r
13197 +       KVP& operator [](const int index)\r
13198 +       {\r
13199 +               return m_kvps[index];\r
13200 +       }\r
13201 +\r
13202 +       int size()\r
13203 +       {\r
13204 +               return m_kvps.size();\r
13205 +       }\r
13206 +\r
13207 +       string getValue(const string &keyname);\r
13208 +       string getValue(const string &keyname, const string &defaultvalue);\r
13209 +       vector<string> getValues(const string &keyname);\r
13210 +};\r
13211 +\r
13212 +/************************************************************************/\r
13213 +/* ==================================================================== */\r
13214 +/*                             CFGReader                                */\r
13215 +/* ==================================================================== */\r
13216 +/************************************************************************/\r
13217 +class CFGReader\r
13218 +{\r
13219 +protected:\r
13220 +       vector<KVP> kvps;\r
13221 +\r
13222 +public:\r
13223 +       CFGReader(const string &configfilename);\r
13224 +\r
13225 +       KVP& operator [](const int index)\r
13226 +       {\r
13227 +               return kvps[index];\r
13228 +       }\r
13229 +\r
13230 +       int size()\r
13231 +       {\r
13232 +               return kvps.size();\r
13233 +       }\r
13234 +\r
13235 +       string getValue(const string &keyname);\r
13236 +       string getValue(const string &keyname, const string &defaultvalue);\r
13237 +};\r
13238 +\r
13239 +\r
13240 +// -----------------------------------------------------------------------\r
13241 +// Extra Template Functions\r
13242 +//             Exchange()                              --- used to exchange values\r
13243 +//             convertToString()               --- convert value to string\r
13244 +//             convertFromString               --- convert string to values\r
13245 +// -----------------------------------------------------------------------\r
13246 +template<class T>\r
13247 +static void Exchange(T & a, T & b)\r
13248 +{\r
13249 +       T t;\r
13250 +       t = a;\r
13251 +       a = b;\r
13252 +       b = t;\r
13253 +}\r
13254 +\r
13255 +template <class T>\r
13256 +static string convertToString(T &value)\r
13257 +{\r
13258 +       stringstream ss;\r
13259 +       ss<<value;\r
13260 +       string rtnstr = ss.str();\r
13261 +       return rtnstr;\r
13262 +}\r
13263 +\r
13264 +template <class T>\r
13265 +static void convertFromString(T &value, const string& s)\r
13266 +{\r
13267 +       stringstream ss(s);\r
13268 +       ss>>value;\r
13269 +}\r
13270 +\r
13271 +\r
13272 +// -----------------------------------------------------------------------\r
13273 +// Extra Utility Functions\r
13274 +// -----------------------------------------------------------------------\r
13275 +CPL_C_START\r
13276 +\r
13277 +// String Operation Related\r
13278 +int CPL_DLL CPL_STDCALL                CsvburstCpp(const std::string& line, std::vector<std::string>  &strSet, const char tok);\r
13279 +int CPL_DLL CPL_STDCALL                CsvburstComplexCpp(const string& line, vector<string> &strSet, const char* tok);\r
13280 +int CPL_DLL CPL_STDCALL                Find_Compare_SubStr(string line, string sub);\r
13281 +void CPL_DLL CPL_STDCALL               Strslip(const char* str, const char* arrStr[], const char leftdlm, const char rightdlm);\r
13282 +string CPL_DLL CPL_STDCALL             StrReplace(string& str, const string oldSubStr, const string newStr);\r
13283 +string CPL_DLL CPL_STDCALL             SPrintArray(GDALDataType eDataType, const void *paDataArray, int nValues, const char *pszDelimiter);\r
13284 +string CPL_DLL CPL_STDCALL             StrTrimHead(const string &str);\r
13285 +string CPL_DLL CPL_STDCALL             StrTrimTail(const string &str);\r
13286 +string CPL_DLL CPL_STDCALL             StrTrims(const std::string&, const char*);\r
13287 +string CPL_DLL CPL_STDCALL             StrTrim(const string &str);\r
13288 +\r
13289 +// Date Time Operation Related\r
13290 +int CPL_DLL CPL_STDCALL                CompareDateTime_GreaterThan(string time1, string time2);\r
13291 +int CPL_DLL CPL_STDCALL                ConvertDateTimeToSeconds(string datetime);\r
13292 +string CPL_DLL CPL_STDCALL             GetTimeString(int code);\r
13293 +\r
13294 +// Directory Operation Related\r
13295 +CPLErr CPL_DLL CPL_STDCALL             GetFileNameList(char* dir, std::vector<string> &strList);\r
13296 +string CPL_DLL CPL_STDCALL             MakeTempFile(string dir, string covID, string suffix);\r
13297 +string CPL_DLL CPL_STDCALL             GetUUID();\r
13298 +\r
13299 +// Request Parser Operation\r
13300 +void CPL_DLL CPL_STDCALL               GetSubSetTime(const string& subsetstr, vector<string> &subsetvalue);\r
13301 +string CPL_DLL CPL_STDCALL             GetSubSetLatLon(const string& subsetstr, vector<double> &subsetvalue);\r
13302 +string CPL_DLL CPL_STDCALL             GetSingleValue(const string& subsetstr);\r
13303 +\r
13304 +CPLErr CPL_DLL CPL_STDCALL             GetTRMMBandList(string start, string end, std::vector<int> &bandList);\r
13305 +void CPL_DLL CPL_STDCALL               GetCornerPoints(const GDAL_GCP* &pGCPList, const int &nGCPs, My2DPoint& lowLeft, My2DPoint& upRight);\r
13306 +\r
13307 +CPL_C_END\r
13308 +\r
13309 +#endif /*WCSUTIL_H_*/\r
This page took 1.10116 seconds and 3 git commands to generate.