[packages/bes] - new - missing patch contains some missing gdal-related code taken from svn - gdal patch fixes gdal
qboosh
qboosh at pld-linux.org
Mon Mar 3 19:20:09 CET 2014
commit 118a05b799ef1e4150cfaa28047050c19da22e85
Author: Jakub Bogusz <qboosh at pld-linux.org>
Date: Mon Mar 3 19:22:40 2014 +0100
- new
- missing patch contains some missing gdal-related code taken from svn
- gdal patch fixes gdal detection and build
bes-gdal.patch | 21 +
bes-missing.patch | 13309 ++++++++++++++++++++++++++++++++++++++++++++++++++++
bes.spec | 230 +
3 files changed, 13560 insertions(+)
---
diff --git a/bes.spec b/bes.spec
new file mode 100644
index 0000000..d92cdcf
--- /dev/null
+++ b/bes.spec
@@ -0,0 +1,230 @@
+Summary: OPeNDAP Back End Server software framework
+Summary(pl.UTF-8): Szkielet OPeNDAP Back End Server (serwera backendu OPeNDAP)
+Name: bes
+Version: 3.12.0
+Release: 1
+License: LGPL v2.1+
+Group: Libraries
+Source0: http://www.opendap.org/pub/source/%{name}-%{version}.tar.gz
+# Source0-md5: 624d7665bd8f756089b58df50e389f45
+Patch0: %{name}-missing.patch
+Patch1: %{name}-gdal.patch
+URL: http://opendap.org/
+BuildRequires: autoconf >= 2.61
+BuildRequires: automake >= 1:1.10
+BuildRequires: bison
+BuildRequires: bzip2-devel
+%{?with_tests:BuildRequires: cppunit-devel >= 1.12.0}
+BuildRequires: gdal-devel >= 1.10.0
+BuildRequires: libdap-devel >= 3.12.0
+BuildRequires: libstdc++-devel
+BuildRequires: libtool >= 2:1.5
+BuildRequires: libwrap-devel
+BuildRequires: libxml2-devel >= 1:2.6.16
+BuildRequires: openssl-devel
+BuildRequires: pkgconfig
+BuildRequires: readline-devel
+BuildRequires: sed >= 4.0
+BuildRequires: zlib-devel
+Requires(pre): /bin/id
+Requires(pre): /usr/bin/getgid
+Requires(pre): /usr/sbin/groupadd
+Requires(pre): /usr/sbin/useradd
+Requires(postun): /usr/sbin/groupdel
+Requires(postun): /usr/sbin/userdel
+Requires: libxml2 >= 1:2.6.16
+Requires: %{name}-libs = %{version}-%{release}
+Provides: group(bes)
+Provides: user(bes)
+BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+BES is a high-performance back-end server software framework for
+OPeNDAP that allows data providers more flexibility in providing end
+users views of their data. The current OPeNDAP data objects (DAS, DDS,
+and DataDDS) are still supported, but now data providers can add new
+data views, provide new functionality, and new features to their end
+users through the BES modular design. Providers can add new data
+handlers, new data objects/views, the ability to define views with
+constraints and aggregation, the ability to add reporting mechanisms,
+initialization hooks, and more.
+
+%description -l pl.UTF-8
+BES to szkielet wysoko wydajnego serwera backendu dla OPeNDAP,
+pozwalający na większą elastyczność dostarczycieli danych (providers)
+w udostępnianiu widoków danych dla użytkowników końcowych. Obecne
+obiekty danych OPeNDAP (DAS, DDS i DataDDS) są nadal obsługiwane, ale
+teraz dostarczyciele danych mogą dodawać nowe widoki danych, zapewniać
+nową funkcjonalność oraz nowe możliwości dla użytkowników końcowych
+poprzez modularną budowę BES. Dostarczyciele mogą dodawać nowe
+procedury obsługujące (handlers), nowe obiekty/widoki danych,
+możliwość definiowania widoków z ograniczeniami i agregacją, możliwość
+dodawania mechanizmów raportujących, uchwytów inicjujących itd.
+
+%package libs
+Summary: Shared OPeNDAP Back End Server libraries
+Summary(pl.UTF-8): Biblioteki współdzielone serwera backendu OPeNDAP
+Group: Libraries
+Requires: libdap >= 3.12.0
+
+%description libs
+Shared OPeNDAP Back End Server libraries.
+
+%description libs -l pl.UTF-8
+Biblioteki współdzielone serwera backendu OPeNDAP.
+
+%package devel
+Summary: Header files for OPeNDAP Back End Server libraries
+Summary(pl.UTF-8): Pliki nagłówkowe bibliotek serwera backendu OPeNDAP
+Group: Development/Libraries
+Requires: %{name}-libs = %{version}-%{release}
+Requires: bzip2-devel
+Requires: libstdc++-devel
+Requires: openssl-devel
+Requires: zlib-devel
+
+%description devel
+Header files for OPeNDAP Back End Server libraries.
+
+%description devel -l pl.UTF-8
+Pliki nagłówkowe bibliotek serwera backendu OPeNDAP.
+
+%package static
+Summary: Static OPeNDAP Back End Server libraries
+Summary(pl.UTF-8): Statyczne biblioteki serwera backendu OPeNDAP
+Group: Development/Libraries
+Requires: %{name}-devel = %{version}-%{release}
+
+%description static
+Static OPeNDAP Back End Server libraries.
+
+%description static -l pl.UTF-8
+Statyczne biblioteki serwera backendu OPeNDAP.
+
+%prep
+%setup -q
+%patch0 -p1
+%patch1 -p1
+
+%{__sed} -i \
+ -e 's:=/tmp:=/var/cache/bes:' \
+ -e 's:=.*/bes\.log:=/var/log/bes/bes.log:' \
+ -e 's:=.*/lib/bes:=%{_libdir}/bes:' \
+ -e 's:=.*/share/bes:=%{_datadir}/bes:' \
+ -e 's:=.*/share/hyrax:=%{_datadir}/hyrax:' \
+ -e 's:=/full/path/to/serverside/certificate/file.pem:=/etc/pki/bes/cacerts/file.pem:' \
+ -e 's:=/full/path/to/serverside/key/file.pem:=/etc/pki/bes/public/file.pem:' \
+ -e 's:=/full/path/to/clientside/certificate/file.pem:=/etc/pki/bes/cacerts/file.pem:' \
+ -e 's:=/full/path/to/clientside/key/file.pem:=/etc/pki/bes/public/file.pem:' \
+ -e 's:=user_name:=bes:' \
+ -e 's:=group_name:=bes:' \
+ dispatch/bes/bes.conf
+
+%build
+%{__libtoolize}
+%{__aclocal} -I conf
+%{__autoconf}
+%{__autoheader}
+%{__automake}
+%configure \
+ --with-libwrap
+%{__make}
+
+%{?with_tests:%{__make} check}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d $RPM_BUILD_ROOT{/etc/rc.d/init.d,/etc/pki/bes/{cacerts,public}} \
+ $RPM_BUILD_ROOT{/var/cache/bes,/var/log/bes}
+
+%{__make} install \
+ DESTDIR=$RPM_BUILD_ROOT
+
+%{__mv} $RPM_BUILD_ROOT%{_bindir}/besd $RPM_BUILD_ROOT/etc/rc.d/init.d
+
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/bes/*.{la,a}
+# obsoleted by pkg-config
+%{__rm} $RPM_BUILD_ROOT%{_libdir}/libbes*.la
+
+install -d $RPM_BUILD_ROOT%{systemdtmpfilesdir}
+cat >$RPM_BUILD_ROOT%{systemdtmpfilesdir}/bes.conf <<EOF
+d /var/run/bes 0775 bes bes -
+EOF
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%pre
+%groupadd -g 307 bes
+%useradd -u 307 -d /var/cache/bes -g bes -s /bin/false -c "BES daemon" bes
+
+%postun
+if [ "$1" = "0" ]; then
+ %userremove bes
+ %groupremove bes
+fi
+
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+
+%files
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/bescmdln
+%attr(755,root,root) %{_bindir}/besctl
+%attr(755,root,root) %{_bindir}/besdaemon
+%attr(755,root,root) %{_bindir}/beslistener
+%attr(755,root,root) %{_bindir}/besregtest
+%attr(755,root,root) %{_bindir}/besstandalone
+%attr(755,root,root) %{_bindir}/hyraxctl
+%dir %{_sysconfdir}/bes/modules
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/bes/modules/dap.conf
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/bes/modules/functions.conf
+%dir /etc/pki/bes
+%dir /etc/pki/bes/cacerts
+%dir /etc/pki/bes/public
+%attr(754,root,root) /etc/rc.d/init.d/besd
+%attr(775,bes,bes) %dir /var/cache/bes
+%attr(775,bes,bes) %dir /var/log/bes
+%attr(775,bes,bes) %dir /var/run/bes
+%{systemdtmpfilesdir}/bes.conf
+
+%files libs
+%defattr(644,root,root,755)
+%doc NEWS README*
+%attr(755,root,root) %{_libdir}/libbes_dispatch.so.*.*.*
+%attr(755,root,root) %ghost %{_libdir}/libbes_dispatch.so.8
+%attr(755,root,root) %{_libdir}/libbes_ppt.so.*.*.*
+%attr(755,root,root) %ghost %{_libdir}/libbes_ppt.so.4
+%attr(755,root,root) %{_libdir}/libbes_xml_command.so.*.*.*
+%attr(755,root,root) %ghost %{_libdir}/libbes_xml_command.so.1
+%dir %{_libdir}/bes
+%attr(755,root,root) %{_libdir}/bes/libdap_module.so
+%attr(755,root,root) %{_libdir}/bes/libdap_xml_module.so
+%attr(755,root,root) %{_libdir}/bes/libdapreader_module.so
+%attr(755,root,root) %{_libdir}/bes/libfunctions_module.so
+%dir %{_sysconfdir}/bes
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/bes/bes.conf
+%dir %{_datadir}/bes
+%{_datadir}/bes/bes_help.*
+%{_datadir}/bes/dap_help.*
+
+%files devel
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/bes-config
+%attr(755,root,root) %{_bindir}/bes-config-pkgconfig
+%attr(755,root,root) %{_bindir}/besCreateModule
+%attr(755,root,root) %{_libdir}/libbes_dispatch.so
+%attr(755,root,root) %{_libdir}/libbes_ppt.so
+%attr(755,root,root) %{_libdir}/libbes_xml_command.so
+%{_includedir}/bes
+%{_pkgconfigdir}/bes_dispatch.pc
+%{_pkgconfigdir}/bes_ppt.pc
+%{_pkgconfigdir}/bes_xml_command.pc
+%{_aclocaldir}/bes.m4
+%{_datadir}/bes/templates
+
+%files static
+%defattr(644,root,root,755)
+%{_libdir}/libbes_dispatch.a
+%{_libdir}/libbes_ppt.a
+%{_libdir}/libbes_xml_command.a
diff --git a/bes-gdal.patch b/bes-gdal.patch
new file mode 100644
index 0000000..0160393
--- /dev/null
+++ b/bes-gdal.patch
@@ -0,0 +1,21 @@
+--- bes-3.12.0/conf/ax_lib_gdal.m4.orig 2013-09-12 00:22:22.000000000 +0200
++++ bes-3.12.0/conf/ax_lib_gdal.m4 2014-03-03 15:25:45.416954681 +0100
+@@ -83,7 +83,7 @@
+ dnl
+
+ gdal_version_req=ifelse([$1], [], [], [$1])
+- if test "$found_gdal" = "yes" -a -n "$gdal_version_req"; then
++ if test "$found_gdal" != "no" -a -n "$gdal_version_req"; then
+
+ AC_MSG_CHECKING([if GDAL version is >= $gdal_version_req])
+
+--- bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp.orig 2014-03-03 15:50:13.366893077 +0100
++++ bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp 2014-03-03 16:41:14.653431275 +0100
+@@ -33,7 +33,6 @@
+ #include "Grid.h"
+ #include "Float64.h"
+
+-#include "ce_functions.h"
+ #include "util.h"
+ #include "debug.h"
+
diff --git a/bes-missing.patch b/bes-missing.patch
new file mode 100644
index 0000000..74aa6b3
--- /dev/null
+++ b/bes-missing.patch
@@ -0,0 +1,13309 @@
+diff -Nur bes-3.12.0/functions.orig/swath2grid/AbstractDataset.cpp bes-3.12.0/functions/swath2grid/AbstractDataset.cpp
+--- bes-3.12.0/functions.orig/swath2grid/AbstractDataset.cpp 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/AbstractDataset.cpp 2014-03-03 15:47:38.046899595 +0100
+@@ -0,0 +1,1238 @@
++/******************************************************************************
++ * $Id: AbstractDataset.cpp 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: AbstractDataset implementation for providing an abstract data
++ * model for multiple data source.
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#include "AbstractDataset.h"
++
++/************************************************************************/
++/* ==================================================================== */
++/* AbstractDataset */
++/* ==================================================================== */
++/************************************************************************/
++
++/**
++ * \class AbstractDataset "AbstractDataset.h"
++ *
++ * An abstract dataset encapsulating one or more raster bands, which is
++ * based on GDALDataset, and add the support to metadata model: ISO 19115
++ * and 1SO 19115 (2). A series of Fetch functions are provided for the
++ * implementation of Web Coverage Service.
++ *
++ * Use WCSTCreateDataset() to create a AbstractDataset for a named coverage
++ * identifier and band list.
++ */
++
++/************************************************************************/
++/* AbstractDataset() */
++/************************************************************************/
++AbstractDataset::AbstractDataset()
++{
++}
++
++/************************************************************************/
++/* AbstractDataset() */
++/************************************************************************/
++
++/**
++ * \brief Constructor of an AbstractDataset.
++ *
++ * This is the accepted method of opening an abstract dataset and allocating
++ * all resources associated with it.
++ */
++
++AbstractDataset::AbstractDataset(const string& id, vector<int> &rBandList) :
++ ms_CoverageID(id), mv_BandList(rBandList)
++{
++}
++
++/************************************************************************/
++/* ~AbstractDataset() */
++/************************************************************************/
++
++/**
++ * \brief Destroy an open AbstractDataset object.
++ *
++ * This is the accepted method of closing a AbstractDataset dataset and
++ * deallocating all resources associated with it.
++ */
++
++AbstractDataset::~AbstractDataset()
++{
++ if (maptr_DS.get())
++ GDALClose(maptr_DS.release());
++}
++
++/************************************************************************/
++/* InitialDataset() */
++/************************************************************************/
++
++/**
++ * \brief Initialize the data set.
++ *
++ * This is the virtual function for initializing abstract dataste. The
++ * subclasses of AbstarctDataset will call SetNativeCRS(), SetGeoTransform()
++ * and SetGDALDataset() to initialize an abstarct dataset.
++ *
++ * @param isSimple The WCS request type. When user executing a DescribeCoverage
++ * request, isSimple is set to 1, and for GetCoverage, is set to 0.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr AbstractDataset::InitialDataset(const int isSimple)
++{
++ return CE_Failure;
++}
++
++/************************************************************************/
++/* GetGDALDataset() */
++/************************************************************************/
++
++/**
++ * \brief Get the GDALDataset object from AbstarctDataset.
++ *
++ * An AbstarctDataset encapsulating one GDALDataset. GetGDALDataset()
++ * returns a GDALDatset object, which is used to fetch its information
++ * through GDAL APIs.
++ *
++ * @return GDALDatset object.
++ */
++
++GDALDataset* AbstractDataset::GetGDALDataset()
++{
++ return maptr_DS.get();
++}
++
++/************************************************************************/
++/* SetGDALDataset() */
++/************************************************************************/
++
++/**
++ * \brief Set the GDALDataset object to AbstarctDataset.
++ *
++ * This is the virtual function for setting the abstract dataset by
++ * calling GDAL functions.
++ *
++ * @param isSimple the WCS request type. When user executing a DescribeCoverage
++ * request, isSimple is set to 1, and for GetCoverage, is set to 0.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr AbstractDataset::SetGDALDataset(const int isSimple)
++{
++ return CE_Failure;
++}
++
++/************************************************************************/
++/* GetNativeCRS() */
++/************************************************************************/
++
++/**
++ * \brief Get the Native CRS of an AbstarctDataset.
++ *
++ * The method will return the CRS obejct, which is an OGRSpatialReference
++ * object.
++ *
++ * @return an OGRSpatialReference object corresponding the native CRS of
++ * coverage.
++ */
++
++const OGRSpatialReference& AbstractDataset::GetNativeCRS()
++{
++ return mo_NativeCRS;
++}
++
++/************************************************************************/
++/* SetNativeCRS() */
++/************************************************************************/
++
++/**
++ * \brief Set the Native CRS for an AbstarctDataset.
++ *
++ * The method will set the CRS for an AbstractDataset as an native CRS. For
++ * some served coverage, GDAL could not tell its native CRS, this method
++ * should be called to set its native CRS.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr AbstractDataset::SetNativeCRS()
++{
++ char* wktStr = (char*) maptr_DS->GetProjectionRef();
++
++ if (wktStr && OGRERR_NONE == mo_NativeCRS.importFromWkt(&wktStr))
++ return CE_None;
++
++ return CE_Failure;
++}
++
++/************************************************************************/
++/* SetGeoTransform() */
++/************************************************************************/
++
++/**
++ * \brief Set the affine GeoTransform matrix for a coverage.
++ *
++ * The method will set a GeoTransform matrix for a coverage. The method
++ * GetGeoTransform of GDAL library will be called to get the matrix.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr AbstractDataset::SetGeoTransform()
++{
++ if (CE_None != maptr_DS->GetGeoTransform(md_Geotransform))
++ return CE_Failure;
++
++ //Is the returned matrix correct? check the resolution values;
++ if(md_Geotransform[2] == 0 && md_Geotransform[5] == 0)
++ return CE_Failure;
++
++ mb_GeoTransformSet = TRUE;
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* GetGeoTransform() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the affine transformation coefficients.
++ *
++ * Fetches the coefficients for transforming between pixel/line (P,L) raster
++ * space, and projection coordinates (Xp,Yp) space.
++ *
++ * \code
++ * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
++ * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
++ * \endcode
++ *
++ * In a north up image, padfTransform[1] is the pixel width, and
++ * padfTransform[5] is the pixel height. The upper left corner of the
++ * upper left pixel is at position (padfTransform[0],padfTransform[3]).
++ *
++ * The default transform is (0,1,0,0,0,1) and should be returned even when
++ * a CE_Failure error is returned, such as for formats that don't support
++ * transformation to projection coordinates.
++ *
++ * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
++ * OGC Grid Coverages pixel/line to projection transformation schemes.
++ * Eventually this method will be depreciated in favour of a more general
++ * scheme.
++ *
++ * @param geoTrans an existing six double buffer into which the
++ * transformation will be placed.
++ *
++ * @return TRUE on success or FALSE on failure.
++ */
++
++int AbstractDataset::GetGeoTransform(double geoTrans[])
++{
++ if (!mb_GeoTransformSet)//Geo-Transform not setup in each data driver, then set default.
++ {
++ geoTrans[0]=0.0;
++ geoTrans[0]=1.0;
++ geoTrans[0]=0.0;
++ geoTrans[0]=0.0;
++ geoTrans[0]=0.0;
++ geoTrans[0]=1.0;
++ return FALSE;
++ }
++
++ memcpy(geoTrans, md_Geotransform, sizeof(double) * 6);
++
++ return TRUE;
++}
++
++/************************************************************************/
++/* GetCoverageID() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the identifier of a coverage.
++ *
++ * The method will return the coverage identifier related to the abstarct
++ * dataset. As to TRMM data, the coverage identifier likes:
++ * TRMM:/Volumes/RAIDL1/GeoData/TRMM/TRMM_3B42_daily.2000.hdf:Daily
++ *
++ * As to MODIS data, the coverage identifier likes:
++ * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MOD15A2/2007/MYD15A2.A2007241.h12v09.005.2007256053902.hdf":MOD_Grid_MOD15A2:Lai_1km
++ *
++ * @return the string of coverage identifier.
++ */
++
++string AbstractDataset::GetCoverageID()
++{
++ return ms_CoverageID;
++}
++
++/************************************************************************/
++/* GetResourceFileName() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the resource file name of a coverage.
++ *
++ * The method will return the full path corresponding the file contained
++ * coverage.
++ *
++ * @return the string of resource file path.
++ */
++
++string AbstractDataset::GetResourceFileName()
++{
++ return ms_SrcFilename;
++}
++
++/************************************************************************/
++/* GetDatasetName() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the dataset name of a coverage.
++ *
++ * The method will return the data set name corresponding the file contained
++ * coverage. For example, MOD09GQ data has the coverage identifier as following;
++ * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
++ *
++ * sur_refl_b01_1 is seemed as the dataset name.
++ *
++ * @return the string of dataset name.
++ */
++
++string AbstractDataset::GetDatasetName()
++{
++ return ms_DatasetName;
++}
++
++/************************************************************************/
++/* GetDataTypeName() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the dataset type name of a coverage.
++ *
++ * The method will return the data set name corresponding the file contained
++ * coverage. For example, MOD09GQ data has the coverage identifier as following;
++ * HDF4_EOS:EOS_GRID:"/Volumes/RAIDL1/GeoData/MODISData/MOD09GQ/MOD09GQ.A2010001.h12v05.005.2010007003100.hdf":MODIS_Grid_2D:sur_refl_b01_1
++ *
++ * MODIS_Grid_2D is seemed as the dataset type name.
++ *
++ * @return the string of dataset type name.
++ */
++
++string AbstractDataset::GetDataTypeName()
++{
++ return ms_DataTypeName;
++}
++
++/************************************************************************/
++/* GetDataTypeName() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the dataset description of a coverage.
++ *
++ * The method will build a description for the coverage. The coverage
++ * extent, dataset name, dataset type name will be contained in the
++ * description,
++ *
++ * @return the string of dataset description.
++ */
++
++string AbstractDataset::GetDatasetDescription()
++{
++ //[15x2030x1354] Band JPEG2000 (16-bit unsigned integer)
++ string rtnBuf;
++ int aiDimSizes[3];
++ int nBandCount = maptr_DS->GetRasterCount();
++ string pszString;
++ if (nBandCount > 1)
++ {
++ aiDimSizes[0] = nBandCount;
++ aiDimSizes[1] = GetImageYSize();
++ aiDimSizes[2] = GetImageXSize();
++ pszString = SPrintArray(GDT_UInt32, aiDimSizes, 3, "x");
++ }
++ else
++ {
++ aiDimSizes[0] = GetImageYSize();
++ aiDimSizes[1] = GetImageXSize();
++ pszString = SPrintArray(GDT_UInt32, aiDimSizes, 2, "x");
++ }
++
++ rtnBuf = "[" + pszString + "] " + ms_DatasetName + " " + ms_DataTypeName + " (" +
++ GDALGetDataTypeName(maptr_DS->GetRasterBand(1)->GetRasterDataType()) + ")";
++
++ return rtnBuf;
++}
++
++/************************************************************************/
++/* GetNativeFormat() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the native format of a coverage.
++ *
++ * The method will return the native format of a coverage. GDAL API
++ * GDALGetDriverShortName() will be called to generate the format.
++ *
++ * @return the string of dataset native format, in forms of GDAL Formats
++ * Code. See http://gdal.org/formats_list.html for details.
++ */
++
++string AbstractDataset::GetNativeFormat()
++{
++ return ms_NativeFormat;
++}
++
++/************************************************************************/
++/* IsbGeoTransformSet() */
++/************************************************************************/
++
++/**
++ * \brief Determine whether set the affine geoTransform for a coverage.
++ *
++ * The method will return the status of the affine GeoTransform matrix.
++ *
++ * @return TRUE if set already or FALSE on failure..
++ */
++
++int AbstractDataset::IsbGeoTransformSet()
++{
++ return mb_GeoTransformSet;
++}
++
++/************************************************************************/
++/* GetNativeBBox() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the bounding box of a coverage under the native CRS.
++ *
++ * The method will fetch the bounding box of the coverage under native CRS.
++ * The sequence of values stored in array is: xmin, xmax, ymin, ymax
++ *
++ * @param bBox an existing four double buffer into which the
++ * native bounding box values will be placed.
++ */
++
++void AbstractDataset::GetNativeBBox(double bBox[])
++{
++ if (mb_GeoTransformSet)
++ {
++ bBox[0] = md_Geotransform[0];
++ bBox[1] = bBox[0] + GetImageXSize() * md_Geotransform[1];
++ bBox[3] = md_Geotransform[3];
++ bBox[2] = bBox[3] + GetImageYSize() * md_Geotransform[5];
++ }
++ else
++ {
++ bBox[0] = 0;
++ bBox[1] = maptr_DS->GetRasterXSize() - 1;
++ bBox[2] = 0;
++ bBox[3] = maptr_DS->GetRasterYSize() - 1;
++ }
++}
++
++/************************************************************************/
++/* GetGeoMinMax() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the bounding box of a coverage under EPSG:4326.
++ *
++ * The method will fetch the bounding box of the coverage under EPSG:4326
++ * CRS. The sequence of values stored in array is: xmin, xmax, ymin, ymax
++ *
++ * @param bBox an existing four double buffer into which the geographic
++ * bounding box values will be placed.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr AbstractDataset::GetGeoMinMax(double geoMinMax[])
++{
++ if (!mb_GeoTransformSet)
++ {
++ SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to get Geo-BoundingBox coordinates");
++ return CE_Failure;
++ }
++
++ geoMinMax[0] = md_Geotransform[0];
++ geoMinMax[1] = geoMinMax[0] + GetImageXSize() * md_Geotransform[1];
++ geoMinMax[3] = md_Geotransform[3];
++ geoMinMax[2] = geoMinMax[3] + GetImageYSize() * md_Geotransform[5];
++
++
++ if (mo_NativeCRS.IsGeographic() || Find_Compare_SubStr(ms_DataTypeName, "MODIS"))//for modis data
++ {
++ geoMinMax[0] = (geoMinMax[0] >= -180.0) ? geoMinMax[0] : -180.0;
++ geoMinMax[1] = (geoMinMax[1] <= 180.0) ? geoMinMax[1] : 180.0;
++ geoMinMax[2] = (geoMinMax[2] >= -90.0) ? geoMinMax[2] : -90.0;
++ geoMinMax[3] = (geoMinMax[3] <= 90.0) ? geoMinMax[3] : 90.0;
++ return CE_None;
++ }
++
++ OGRSpatialReference oGeoSRS;
++ oGeoSRS.CopyGeogCSFrom(&mo_NativeCRS);
++
++ My2DPoint llPt(geoMinMax[0], geoMinMax[2]);
++ My2DPoint urPt(geoMinMax[1], geoMinMax[3]);
++ if (CE_None != bBox_transFormmate(mo_NativeCRS, oGeoSRS, llPt, urPt))
++ {
++ SetWCS_ErrorLocator("AbstractDataset::getGeoMinMax()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to transform bounding box coordinates to geographic coordinates.");
++ return CE_Failure;
++ }
++
++ geoMinMax[0] = llPt.mi_X;
++ geoMinMax[1] = urPt.mi_X;
++ geoMinMax[2] = llPt.mi_Y;
++ geoMinMax[3] = urPt.mi_Y;
++
++ return CE_None;
++}
++
++
++/************************************************************************/
++/* GetImageXSize() */
++/************************************************************************/
++
++/**
++ * \brief Fetch coverage width in pixels.
++ *
++ * The method will return the width of coverage in pixels. GDAL API
++ * GetRasterXSize() will be called to generate the width value.
++ *
++ * @return the width in pixels of raster bands in this coverage.
++ */
++
++int AbstractDataset::GetImageXSize()
++{
++ return maptr_DS->GetRasterXSize();
++}
++
++/************************************************************************/
++/* GetImageYSize() */
++/************************************************************************/
++
++/**
++ * \brief Fetch coverage height in pixels.
++ *
++ * The method will return the height of coverage in pixels. GDAL API
++ * GetRasterYSize() will be called to generate the height value.
++ *
++ * @return the height in pixels of raster bands in this coverage.
++ */
++int AbstractDataset::GetImageYSize()
++{
++ return maptr_DS->GetRasterYSize();
++}
++
++/************************************************************************/
++/* GetCoverageBeginTime() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the begin date/time of a coverage.
++ *
++ * The method will return the begin date/time of a coverage. For MODIS data,
++ * each granule will cover a range of time; for TRMM data, the daily data
++ * will cover a whole day, and monthly data will cover a whole month.
++ *
++ * @return the string of begin date/time corresponding to the coverage.
++ */
++
++string AbstractDataset::GetCoverageBeginTime()
++{
++ return ms_CoverageBeginTime;
++}
++
++/************************************************************************/
++/* GetCoverageBeginTime() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the end date/time of a coverage.
++ *
++ * The method will return the end date/time of a coverage. For MODIS data,
++ * each granule will cover a range of time; for TRMM data, the daily data
++ * will cover a whole day, and monthly data will cover a whole month.
++ *
++ * @return the string of end date/time corresponding to the coverage.
++ */
++
++string AbstractDataset::GetCoverageEndTime()
++{
++ return ms_CoverageEndTime;
++}
++
++/************************************************************************/
++/* getCoverageSubType() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the coverage type.
++ *
++ * The method will return the type of the coverage, such as
++ * "ReferenceableDataset" and "RectifiedDataset".
++ *
++ * @return the string of coverage type.
++ */
++
++string AbstractDataset::GetCoverageSubType()
++{
++ return ms_CoverageSubType;
++}
++
++/************************************************************************/
++/* getFieldQuantityDef() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the field units of a coverage.
++ *
++ * The method will return the field units of coverage. For example to
++ * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, units equals
++ * to reflectance.
++ *
++ * @return the string of coverage field units.
++ */
++
++string AbstractDataset::GetFieldQuantityDef()
++{
++ return ms_FieldQuantityDef;
++}
++
++/************************************************************************/
++/* GetAllowValues() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the allow values of a coverage.
++ *
++ * The method will return the valid range of a coverage. For example to
++ * MOD09GQ(collection name) sur_refl_b01_1(dataset name) data, valid_range
++ * equals to (-100, 16000).
++ *
++ * @return the string of valid range of a coverage, in the forms of "min, max".
++ */
++
++string AbstractDataset::GetAllowValues()
++{
++ return ms_AllowRanges;
++}
++
++/************************************************************************/
++/* GetISO19115Metadata() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the coverage metadata which is compliant to ISO 19115:2003
++ * - GeoGraphic information -- Metadata; and ISO 19115(2):2009 - GeoGraphic
++ * information -- Metadata -- Part 2.
++ *
++ * The method will return the metadata of a coverage based on ISO 19115
++ * and ISO 19115(2).
++ *
++ * ISO 19115:2003 defines the schema required for
++ * describing geographic information and services. It provides information
++ * about the identification, the extent, the quality, the spatial and temporal
++ * schema, spatial reference, and distribution of digital geographic data.
++ *
++ * ISO 19115-2:2009 extends the existing geographic metadata standard by
++ * defining the schema required for describing imagery and gridded data.
++ * It provides information about the properties of the measuring equipment
++ * used to acquire the data, the geometry of the measuring process employed
++ * by the equipment, and the production process used to digitize the raw data.
++ * This extension deals with metadata needed to describe the derivation of
++ * geographic information from raw data, including the properties of the
++ * measuring system, and the numerical methods and computational procedures
++ * used in the derivation. The metadata required to address coverage data in
++ * general is addressed sufficiently in the general part of ISO 19115.
++ *
++ * @return the string of metadata of a coverage.
++ */
++
++string AbstractDataset::GetISO19115Metadata()
++{
++ return ms_ISO19115Metadata;
++}
++
++/************************************************************************/
++/* GetCoverageArchiveTime() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the archive date/time of this dataset.
++ *
++ * The method will return the archive date/time of dataset (granule).
++ *
++ * @return The string of archive date/time.
++ */
++
++string AbstractDataset::GetCoverageArchiveTime()
++{
++ return ms_CoverageArchiveTime;
++}
++
++/************************************************************************/
++/* GetCoveragePlatform() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the platform name of this dataset.
++ *
++ * The method will return the platform name of dataset (granule).
++ *
++ * @return The string of platform name.
++ */
++
++string AbstractDataset::GetCoveragePlatform()
++{
++ return ms_CoveragePlatform;
++}
++
++/************************************************************************/
++/* GetCoverageInstrument() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the instrument name of this dataset.
++ *
++ * The method will return the instrument name of dataset (granule).
++ *
++ * @return The string of instrument name.
++ */
++
++string AbstractDataset::GetCoverageInstrument()
++{
++ return ms_CoverageInstrument;
++}
++
++/************************************************************************/
++/* GetCoverageInstrument() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the sensor name of this dataset.
++ *
++ * The method will return the sensor name of dataset (granule).
++ *
++ * @return The string of sensor name.
++ */
++
++string AbstractDataset::GetCoverageSensor()
++{
++ return ms_CoverageSensor;
++}
++
++/************************************************************************/
++/* GetImageBandCount() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the number of raster bands on this dataset.
++ *
++ * The method will return the number of raster bands on this dataset. GDAL
++ * API GetRasterCount() will be called to get the count number.
++ *
++ * @return the number of raster bands on this dataset.
++ */
++
++int AbstractDataset::GetImageBandCount()
++{
++ return maptr_DS->GetRasterCount();
++}
++
++/************************************************************************/
++/* getMissingValue() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the filled value (missing value) of a coverage.
++ *
++ * The method will return the filled value of a coverage.
++ *
++ * @return the value of filled value of a coverage.
++ */
++
++const double& AbstractDataset::GetMissingValue()
++{
++ return md_MissingValue;
++}
++
++/************************************************************************/
++/* GetProjectionRef() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the native projection reference of a coverage.
++ *
++ * The method will return the the native projection reference of a coverage.
++ *
++ * @return the string of the native projection reference of a coverage.
++ */
++
++string AbstractDataset::GetProjectionRef()
++{
++ char* pszProjection = NULL;
++ mo_NativeCRS.exportToWkt(&pszProjection);
++ string tmpStr = pszProjection;
++ CPLFree(pszProjection);
++
++ return tmpStr;
++}
++
++/************************************************************************/
++/* SetMetaDataList() */
++/************************************************************************/
++
++/**
++ * \brief Set the metadata list for this coverage based on dataset object.
++ *
++ * The method will set the metadata list for the coverage based on its
++ * corresponding GDALDataset object. Will be implemented in the subclasses
++ * of AbstractDataset.
++ *
++ * @param hSrc the GDALDataset object corresponding to coverage.
++ *
++ * @return CE_Failure.
++ */
++
++CPLErr AbstractDataset::SetMetaDataList(GDALDataset* hSrc)
++{
++ return CE_Failure;
++}
++
++/************************************************************************/
++/* GetMetaDataList() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the metadata list for this coverage.
++ *
++ * The method will return the metadata list for the coverage.
++ *
++ * @return the list of metadate.
++ */
++
++vector<string> AbstractDataset::GetMetaDataList()
++{
++ return mv_MetaDataList;
++}
++
++/************************************************************************/
++/* GetBandList() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the contained band list of request coverage.
++ *
++ * The method will return the contained band list of request coverage.
++ *
++ * @return the band array.
++ */
++
++vector<int> AbstractDataset::GetBandList()
++{
++ return mv_BandList;
++}
++
++/************************************************************************/
++/* getNativeCRS_URN() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the native CRS code of coverage.
++ *
++ * The method will return the native CRS code of coverage.
++ *
++ * @return the string of the URN for native CRS of coverage.
++ */
++
++string AbstractDataset::GetNativeCRS_URN()
++{
++ string urn;
++
++ if (mo_NativeCRS.IsProjected())
++ {
++ const char* nativeAuthorityName =
++ mo_NativeCRS.GetAuthorityName("PROJCS");
++ const char* nativeAuthorityCode =
++ mo_NativeCRS.GetAuthorityCode("PROJCS");
++
++ urn = "urn:ogc:def:crs:";
++
++ if (nativeAuthorityName && (EQUAL(nativeAuthorityName,"EPSG")
++ || EQUAL(nativeAuthorityName,"OGP")
++ || EQUAL(nativeAuthorityName,"OGC")))
++ urn += (string) nativeAuthorityName + (string) ":6.3:";
++ else
++ urn += "CSISS:0.0:";
++
++ if (nativeAuthorityCode)
++ urn += (string) nativeAuthorityCode;
++ else
++ urn += "80000000";
++ }
++ else if (mo_NativeCRS.IsGeographic())
++ {
++ const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
++ const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
++
++ urn = "urn:ogc:def:crs:";
++ if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
++ || EQUAL(geoAuthorityName,"OGP")
++ || EQUAL(geoAuthorityName,"OGC")))
++ urn += (string) geoAuthorityName + (string) ":6.3:";
++ else
++ urn += "CSISS:0.0:";
++
++ if (geoAuthorityCode)
++ urn += (string) geoAuthorityCode;
++ else
++ urn += "70000000";
++ }
++ else
++ urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
++
++ return urn;
++}
++
++/************************************************************************/
++/* GetGeoCRS_URN() */
++/************************************************************************/
++
++/**
++ * \brief Fetch the Geographic CRS code of coverage.
++ *
++ * The method will return the Geographic CRS code of coverage.
++ *
++ * @return the URN for Geographic CRS of coverage.
++ */
++
++string AbstractDataset::GetGeoCRS_URN()
++{
++ string urn;
++
++ if (mo_NativeCRS.IsProjected() || mo_NativeCRS.IsGeographic())
++ {
++ const char* geoAuthorityName = mo_NativeCRS.GetAuthorityName("GEOGCS");
++ const char* geoAuthorityCode = mo_NativeCRS.GetAuthorityCode("GEOGCS");
++
++ urn = "urn:ogc:def:crs:";
++ if (geoAuthorityName && (EQUAL(geoAuthorityName,"EPSG")
++ || EQUAL(geoAuthorityName,"OGP")
++ || EQUAL(geoAuthorityName,"OGC")))
++ urn += (string) geoAuthorityName + (string) ":6.3:";
++ else
++ urn += "CSISS:0.0:";
++
++ if (geoAuthorityCode)
++ urn += (string) geoAuthorityCode;
++ else
++ urn += "70000000";
++
++ }
++ else
++ urn = "urn:ogc:def:crs:OGC:0.0:imageCRS";
++
++ return urn;
++}
++
++/************************************************************************/
++/* IsCrossingIDL() */
++/************************************************************************/
++
++/**
++ * \brief Determine whether the extend of coverage cross the International
++ * Date Line (IDL).
++ *
++ * The method will return the status of whether the extend of coverage
++ * cross the International Date Line (IDL).
++ *
++ * @return the TRUE of the coverage extent cross the IDL, otherwise FALSE.
++ */
++
++int AbstractDataset::IsCrossingIDL()
++{
++ double bboxArray[4];
++ GetNativeBBox(bboxArray);
++
++ OGRSpatialReference latlonSRS;
++ latlonSRS.SetWellKnownGeogCS("WGS84");
++ My2DPoint llPtex(bboxArray[0], bboxArray[2]);
++ My2DPoint urPtex(bboxArray[1], bboxArray[3]);
++ bBox_transFormmate(mo_NativeCRS, latlonSRS, llPtex, urPtex);
++
++ int bCrossCenter = false;
++ if(urPtex.mi_X < 0 && llPtex.mi_X > 0)
++ bCrossCenter = true;
++
++ return bCrossCenter;
++}
++
++/************************************************************************/
++/* GetSuggestedWarpResolution() */
++/************************************************************************/
++
++/**
++ * \brief Get the suggested warp option, method 1.
++ *
++ * @return CE_Failure if an error occurs, otherwise CE_None.
++ */
++
++CPLErr AbstractDataset::GetSuggestedWarpResolution( OGRSpatialReference& dstCRS,
++ double adfDstGeoTransform[],
++ int &nPixels,
++ int &nLines)
++{
++ if (!dstCRS.IsProjected() && !dstCRS.IsGeographic())
++ {
++ adfDstGeoTransform[0] = 0;
++ adfDstGeoTransform[1] = 1;
++ adfDstGeoTransform[2] = 0;
++ adfDstGeoTransform[3] = 0;
++ adfDstGeoTransform[4] = 0;
++ adfDstGeoTransform[5] = 1;
++
++ nPixels = GetImageXSize();
++ nLines = GetImageYSize();
++
++ }
++ else if (dstCRS.IsSame(&mo_NativeCRS))
++ {
++ memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
++ nPixels = GetImageXSize();
++ nLines = GetImageYSize();
++ }
++ else
++ {
++ char *pszDstWKT;
++ dstCRS.exportToWkt(&pszDstWKT);
++ char *pszSrcWKT;
++ mo_NativeCRS.exportToWkt(&pszSrcWKT);
++
++ void *hTransformArg = GDALCreateGenImgProjTransformer(maptr_DS.get(),
++ (const char*) pszSrcWKT, NULL, (const char*) pszDstWKT, TRUE, 1000.0, 0);
++ OGRFree(pszDstWKT);
++ OGRFree(pszSrcWKT);
++ if (hTransformArg == NULL)
++ {
++ SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create GDAL GenImgProjTransformer.");
++
++ return CE_Failure;
++ }
++ /* -------------------------------------------------------------------- */
++ /* Get approximate output definition. */
++ /* -------------------------------------------------------------------- */
++ if (GDALSuggestedWarpOutput(maptr_DS.get(), GDALGenImgProjTransform,
++ hTransformArg, adfDstGeoTransform, &nPixels, &nLines) != CE_None)
++ {
++ SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Computing Output Resolution.");
++
++ return CE_Failure;
++ }
++
++ GDALDestroyGenImgProjTransformer(hTransformArg);
++ }
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* GetSuggestedWarpResolution2() */
++/************************************************************************/
++
++/**
++ * \brief Get the suggested warp option, method 2.
++ *
++ * @return CE_Failure if an error occurs, otherwise CE_None.
++ */
++
++CPLErr AbstractDataset::GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS,
++ double adfDstGeoTransform[],
++ int &nPixels,
++ int &nLines)
++{
++ if (dstCRS.IsLocal())
++ {
++ adfDstGeoTransform[0] = 0;
++ adfDstGeoTransform[1] = 1;
++ adfDstGeoTransform[2] = 0;
++ adfDstGeoTransform[3] = 0;
++ adfDstGeoTransform[4] = 0;
++ adfDstGeoTransform[5] = 1;
++
++ nPixels = GetImageXSize();
++ nLines = GetImageYSize();
++ }
++ else if (dstCRS.IsSame(&mo_NativeCRS))
++ {
++ memcpy(adfDstGeoTransform, md_Geotransform, sizeof(double) * 6);
++ nPixels = GetImageXSize();
++ nLines = GetImageYSize();
++ }
++ else
++ {
++ double bboxArray[4];
++ GetNativeBBox(bboxArray);
++
++ My2DPoint llPt(bboxArray[0], bboxArray[2]);
++ My2DPoint urPt(bboxArray[1], bboxArray[3]);
++ if (CE_None != bBox_transFormmate(mo_NativeCRS, dstCRS, llPt, urPt))
++ {
++ SetWCS_ErrorLocator("AbstractDataset::GetSuggestedWarpResolution2()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform bounding box Coordinate.");
++ return CE_Failure;
++ }
++
++ double xRes, yRes;
++ if(IsCrossingIDL())
++ {
++ yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
++ xRes = fabs((llPt.mi_X - urPt.mi_X) / GetImageXSize());
++ nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
++ nPixels = fabs((llPt.mi_X - urPt.mi_X) / xRes + 0.5);
++ }else
++ {
++ xRes = (urPt.mi_X - llPt.mi_X) / GetImageXSize();
++ yRes = (urPt.mi_Y - llPt.mi_Y) / GetImageYSize();
++ nPixels = (urPt.mi_X - llPt.mi_X) / xRes + 0.5;
++ nLines = (urPt.mi_Y - llPt.mi_Y) / yRes + 0.5;
++ }
++
++ xRes = MIN(xRes,yRes);
++ yRes = MIN(xRes,yRes);
++
++ adfDstGeoTransform[0] = llPt.mi_X;
++ adfDstGeoTransform[1] = xRes;
++ adfDstGeoTransform[2] = 0;
++ adfDstGeoTransform[3] = urPt.mi_Y;
++ adfDstGeoTransform[4] = 0;
++ adfDstGeoTransform[5] = -yRes;
++ }
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* DatasetWarper() */
++/************************************************************************/
++
++/**
++ * Wrap the dataset to a GDALDataset object based on input parameters.
++ *
++ * @return the warpped GDALDataset object.
++ */
++/************************************************************************/
++/* DatasetWarper() */
++/************************************************************************/
++
++/**
++ * \brief Wrap the dataset to a GDALDataset object based on input parameters.
++ *
++ * @return GDALDatset object.
++ */
++
++GDALDataset* AbstractDataset::DatasetWarper(int& IsRefDS,
++ OGRSpatialReference& dstCRS,
++ int& iDstRasterXsize,
++ int& iDstRasterYsize,
++ double pDstGeoTransform[],
++ GDALResampleAlg eResampleAlg)
++{
++ OGRSpatialReference locCRS=dstCRS;
++ if (dstCRS.IsLocal())
++ locCRS=mo_NativeCRS;
++
++ if((mo_NativeCRS.IsSame(&locCRS) &&
++ iDstRasterXsize == maptr_DS->GetRasterXSize() &&
++ iDstRasterYsize == maptr_DS->GetRasterYSize())&&
++ CPLIsEqual(md_Geotransform[0],pDstGeoTransform[0])&&
++ CPLIsEqual(md_Geotransform[1],pDstGeoTransform[1])&&
++ CPLIsEqual(md_Geotransform[3],pDstGeoTransform[3])&&
++ CPLIsEqual(md_Geotransform[5],pDstGeoTransform[5]))
++ {
++ IsRefDS = TRUE;
++ return maptr_DS.get();
++ }
++
++ char *sDstCRS_WKT;
++ locCRS.exportToWkt(&sDstCRS_WKT);
++
++ /* Create a memory data-set for re-projection */
++ GDALDriverH poDriver = GDALGetDriverByName("MEM");
++
++ int nBand = maptr_DS->GetRasterCount();
++ GDALDataset* hMemDS = (GDALDataset*) GDALCreate(poDriver, "", iDstRasterXsize,
++ iDstRasterYsize, nBand, GDALGetRasterDataType(maptr_DS->GetRasterBand(1)), NULL);
++ if (NULL == hMemDS)
++ {
++ GDALClose(poDriver);
++ OGRFree(sDstCRS_WKT);
++ return NULL;
++ }
++
++ hMemDS->SetProjection(sDstCRS_WKT);
++ hMemDS->SetGeoTransform(pDstGeoTransform);
++
++ for (int i = 1; i <= nBand; i++)
++ {
++ hMemDS->GetRasterBand(i)->SetNoDataValue(md_MissingValue);
++ }
++
++ /* -------------------------------------------------------------------- */
++ /* Perform the re-projection. */
++ /* -------------------------------------------------------------------- */
++ char *srcWKT;
++ mo_NativeCRS.exportToWkt(&srcWKT);
++ if (CE_None != GDALReprojectImage(maptr_DS.get(), srcWKT, hMemDS,
++ sDstCRS_WKT, eResampleAlg, 0, 0.125, NULL, NULL, NULL))
++ {
++ GDALClose(poDriver);
++ GDALClose(GDALDatasetH(hMemDS));
++ OGRFree(sDstCRS_WKT);
++ OGRFree(srcWKT);
++ return NULL;
++ }
++ IsRefDS = FALSE;
++ OGRFree(sDstCRS_WKT);
++ OGRFree(srcWKT);
++
++ return hMemDS;
++}
+diff -Nur bes-3.12.0/functions.orig/swath2grid/AbstractDataset.h bes-3.12.0/functions/swath2grid/AbstractDataset.h
+--- bes-3.12.0/functions.orig/swath2grid/AbstractDataset.h 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/AbstractDataset.h 2014-03-03 15:47:38.050232928 +0100
+@@ -0,0 +1,150 @@
++/******************************************************************************
++ * $Id: AbstractDataset.h 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: AbstractDataset class definition
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#ifndef ABSTRACTDATASET_H_
++#define ABSTRACTDATASET_H_
++
++#include <vector>
++#include <memory>
++
++#include <gdal.h>
++#include <gdal_priv.h>
++#include <gdalwarper.h>
++#include <ogrsf_frmts.h>
++#include <ogr_spatialref.h>
++#include <cpl_conv.h>
++#include <cpl_minixml.h>
++#include <vrtdataset.h>
++
++#include "wcsUtil.h"
++
++using namespace std;
++
++/* ******************************************************************** */
++/* AbstractDataset */
++/* ******************************************************************** */
++
++//! Abstract dataset model definition. Based on GDAL dataset model.
++class AbstractDataset {
++
++protected:
++ auto_ptr<GDALDataset> maptr_DS;
++
++ // Coverage Information Related
++ string ms_CoverageID;
++ string ms_CoverageBeginTime;
++ string ms_CoverageEndTime;
++ string ms_CoverageSubType;
++ string ms_CoverageArchiveTime;
++ string ms_CoveragePlatform;
++ string ms_CoverageInstrument;
++ string ms_CoverageSensor;
++ string ms_SrcFilename;
++ string ms_DatasetName;
++ string ms_DataTypeName;
++ string ms_NativeFormat;
++ string ms_FieldQuantityDef;
++ string ms_AllowRanges;
++ string ms_ISO19115Metadata;
++
++ vector<int> mv_BandList;
++ vector<string> mv_MetaDataList;
++
++ double md_Geotransform[6];
++ double md_GeoMinMax[4]; // Order: xmin, xmax, ymin, ymax
++ double md_MissingValue;
++
++ int mb_GeoTransformSet;
++ int mb_IsVirtualDS;
++
++ OGRSpatialReference mo_NativeCRS;
++
++protected:
++ AbstractDataset();
++ virtual CPLErr SetNativeCRS();
++ virtual CPLErr SetGeoTransform();
++ virtual CPLErr SetGDALDataset(const int isSimple = 0);
++ virtual CPLErr SetMetaDataList(GDALDataset*);
++
++public:
++ AbstractDataset(const string&, vector<int> &);
++ virtual ~AbstractDataset();
++
++ GDALDataset* GetGDALDataset();
++
++ // Virtual Functions Definition
++ virtual CPLErr InitialDataset(const int isSimple = 0);
++
++ // Fetch Function Related
++ const OGRSpatialReference& GetNativeCRS();
++ const double& GetMissingValue();
++ int GetGeoTransform(double geoTrans[]);
++ vector<string> GetMetaDataList();
++ vector<int> GetBandList();
++ void GetNativeBBox(double bBox[]);
++ CPLErr GetGeoMinMax(double geoMinMax[]);
++
++ int GetImageBandCount();
++ int GetImageXSize();
++ int GetImageYSize();
++ string GetResourceFileName();
++ string GetDatasetName();
++ string GetDataTypeName();
++ string GetNativeFormat();
++ string GetCoverageID();
++ string GetDatasetDescription();
++ string GetNativeCRS_URN();
++ string GetGeoCRS_URN();
++ string GetProjectionRef();
++ string GetCoverageBeginTime();
++ string GetCoverageEndTime();
++ string GetCoverageSubType();
++ string GetFieldQuantityDef();
++ string GetAllowValues();
++ string GetISO19115Metadata();
++ string GetCoverageArchiveTime();
++ string GetCoveragePlatform();
++ string GetCoverageInstrument();
++ string GetCoverageSensor();
++
++ // Fetch Variables Status Related
++ int IsbGeoTransformSet();
++ int IsCrossingIDL();
++
++ CPLErr GetSuggestedWarpResolution(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
++ int &nLines);
++ CPLErr GetSuggestedWarpResolution2(OGRSpatialReference& dstCRS, double adfDstGeoTransform[], int &nPixels,
++ int &nLines);
++
++ GDALDataset* DatasetWarper(int& IsRefDS, OGRSpatialReference& dstCRS, int& iDstRasterXsize, int& iDstRasterYsize,
++ double pDstGeoTransform[], GDALResampleAlg eResampleAlg = GRA_NearestNeighbour);
++};
++
++#endif /*ABSTRACTDATASET_H_*/
+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
+--- bes-3.12.0/functions.orig/swath2grid/airs.nc.0.data.bescmd 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/airs.nc.0.data.bescmd 2014-03-03 15:47:38.050232928 +0100
+@@ -0,0 +1,13 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<request reqID ="some_unique_value" >
++ <setContext name="dap_format">dap2</setContext>
++ <setContext name="xdap_accept">3.3</setContext>
++ <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
++ <define name="d">
++ <container name="c">
++ <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
++ </container>
++ </define>
++ <get type="dods" definition="d"/>
++</request>
++
+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
+--- bes-3.12.0/functions.orig/swath2grid/airs.nc.0.ddx.bescmd 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/airs.nc.0.ddx.bescmd 2014-03-03 15:47:38.053566262 +0100
+@@ -0,0 +1,13 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<request reqID ="some_unique_value" >
++ <setContext name="dap_format">dap2</setContext>
++ <setContext name="xdap_accept">3.3</setContext>
++ <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
++ <define name="d">
++ <container name="c">
++ <constraint>swath2grid(topog,Latitude,Longitude)</constraint>
++ </container>
++ </define>
++ <get type="das" definition="d"/>
++</request>
++
+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
+--- bes-3.12.0/functions.orig/swath2grid/airs.nc.1.err.bescmd 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/airs.nc.1.err.bescmd 2014-03-03 15:47:38.043566262 +0100
+@@ -0,0 +1,13 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<request reqID ="some_unique_value" >
++ <setContext name="dap_format">dap2</setContext>
++ <setContext name="xdap_accept">3.3</setContext>
++ <setContainer name="c" space="catalog">/data/nc/OWS_9_Data/AIRS_570672/AIRS_AQUA_L1B_BRIGHTNESS_20101026_1617.nc.gz</setContainer>
++ <define name="d">
++ <container name="c">
++ <constraint>swath2grid()</constraint>
++ </container>
++ </define>
++ <get type="dods" definition="d"/>
++</request>
++
+diff -Nur bes-3.12.0/functions.orig/swath2grid/bes.conf.in bes-3.12.0/functions/swath2grid/bes.conf.in
+--- bes-3.12.0/functions.orig/swath2grid/bes.conf.in 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/bes.conf.in 2014-03-03 15:47:38.050232928 +0100
+@@ -0,0 +1,48 @@
++BES.ServerAdministrator=root at null.dev
++
++BES.User=user_name
++BES.Group=group_name
++
++BES.LogName=./bes.log
++BES.LogVerbose=no
++
++BES.modules=dap,cmd,nc,h4,fong,fonc
++BES.module.dap=@libdir@/bes/libdap_module.so
++BES.module.cmd=@libdir@/bes/libdap_xml_module.so
++
++BES.module.nc=@libdir@/bes/libnc_module.so
++BES.module.h4=@libdir@/bes/libhdf4_module.so
++
++BES.module.fong=@libdir@/bes/libfong_module.so
++BES.module.fonc=@libdir@/bes/libfonc_module.so
++
++BES.Catalog.catalog.RootDirectory=@abs_top_srcdir@
++BES.Data.RootDirectory=/dev/null
++
++BES.Catalog.catalog.TypeMatch=nc:.*.nc(.bz2|.gz|.Z)?$;h4:.*.(hdf|HDF|eos)(.bz2|.gz|.Z)?$;
++
++BES.Catalog.catalog.Include=;
++BES.Catalog.catalog.Exclude=^\..*;
++
++BES.FollowSymLinks=No
++BES.Catalog.catalog.FollowSymLinks=No
++
++BES.ServerPort=10002
++
++BES.CacheDir=/tmp
++BES.CachePrefix=bes_cache
++BES.CacheSize=500
++
++BES.Container.Persistence=strict
++
++BES.Memory.GlobalArea.EmergencyPoolSize=1
++BES.Memory.GlobalArea.MaximumHeapSize=20
++BES.Memory.GlobalArea.Verbose=no
++BES.Memory.GlobalArea.ControlHeap=no
++
++BES.ProcessManagerMethod=multiple
++
++BES.DefaultResponseMethod=POST
++
++FONg.TempDirectory=@abs_top_srcdir@/tests
++
+diff -Nur bes-3.12.0/functions.orig/swath2grid/BoundingBox.cpp bes-3.12.0/functions/swath2grid/BoundingBox.cpp
+--- bes-3.12.0/functions.orig/swath2grid/BoundingBox.cpp 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/BoundingBox.cpp 2014-03-03 15:47:38.050232928 +0100
+@@ -0,0 +1,360 @@
++/******************************************************************************
++ * $Id: BoundingBox.cpp 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: BoundingBox class implementation, enable transform bounding box
++ * between different CRS
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#include <vector>
++#include <iostream>
++
++#include "BoundingBox.h"
++#include "wcs_error.h"
++
++using namespace std;
++
++My2DPoint::~My2DPoint()
++{
++
++}
++
++BoundingBox::BoundingBox()
++{
++
++}
++
++BoundingBox::~BoundingBox()
++{
++
++}
++
++BoundingBox BoundingBox::TransformWorkExtend(OGRSpatialReference &dstCRS, int &IsOK)
++{
++ if (mo_CRS.IsSame(&dstCRS))
++ {
++ IsOK = TRUE;
++ return *this;
++ }
++
++ OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&mo_CRS, &dstCRS);
++ if (poCT == NULL)
++ {
++ IsOK = FALSE;
++ return *this;
++ }
++
++ double xdes = (mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
++
++ if (mo_CRS.IsGeographic()
++ && mo_UpperRightPT.mi_X < mo_LowerLeftPT.mi_X
++ && mo_LowerLeftPT.mi_X > 0 && mo_UpperRightPT.mi_X < 0)
++ {
++ xdes = (360 + mo_UpperRightPT.mi_X - mo_LowerLeftPT.mi_X) / 100;
++ }
++
++ vector<double> x;
++ vector<double> y;
++ //up and down edge
++ for (double stepX = mo_LowerLeftPT.mi_X; stepX < mo_UpperRightPT.mi_X; stepX
++ += xdes)
++ {
++ x.push_back(stepX);
++ y.push_back(mo_UpperRightPT.mi_Y);
++ x.push_back(stepX);
++ y.push_back(mo_LowerLeftPT.mi_Y);
++ }
++ x.push_back(mo_UpperRightPT.mi_X);
++ y.push_back(mo_UpperRightPT.mi_Y);
++ x.push_back(mo_UpperRightPT.mi_X);
++ y.push_back(mo_LowerLeftPT.mi_Y);
++
++ double yMin = numeric_limits<double>::max();
++ double yMax = numeric_limits<double>::min();
++
++ int k = 0;
++ vector<int> bSuccess;
++ vector<double> tmpX;
++ vector<double> tmpY;
++
++ for (unsigned int i = 0; i < x.size(); i++)
++ {
++ tmpX.push_back(x[i]);
++ tmpY.push_back(y[i]);
++ bSuccess.push_back(0);
++ }
++
++ poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
++
++ for (unsigned int n = 0; n < x.size(); n++)
++ {
++ if (bSuccess[n])
++ {
++ ++k;
++ yMin = MIN(yMin,tmpY[n]);
++ yMax = MAX(yMax,tmpY[n]);
++ }
++ }
++
++ if (k < 80)
++ {
++ IsOK = FALSE;
++ OCTDestroyCoordinateTransformation(poCT);
++ return *this;
++ }
++
++ //find xmin on left edge and xmax on right edge
++ double xMin;
++ double xMax;
++
++ double tmpPTX[2];
++ double tmpPTY[2];
++
++ int isSucc[2];
++
++ tmpPTX[0] = mo_LowerLeftPT.mi_X;
++ tmpPTX[1] = mo_LowerLeftPT.mi_X;
++ tmpPTY[0] = mo_LowerLeftPT.mi_Y;
++ tmpPTY[1] = mo_UpperRightPT.mi_Y;
++
++ poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
++ if (isSucc[0] && isSucc[1])
++ {
++ xMin = MIN(tmpPTX[0],tmpPTX[1]);
++ }
++ else
++ {
++ OCTDestroyCoordinateTransformation(poCT);
++ IsOK = FALSE;
++ return *this;
++ }
++
++ tmpPTX[0] = mo_UpperRightPT.mi_X;
++ tmpPTX[1] = mo_UpperRightPT.mi_X;
++ tmpPTY[0] = mo_UpperRightPT.mi_Y;
++ tmpPTY[1] = mo_LowerLeftPT.mi_Y;
++
++ poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isSucc);
++ if (isSucc[0] && isSucc[1])
++ {
++ xMax = MAX(tmpPTX[0],tmpPTX[1]);
++ }
++ else
++ {
++ OCTDestroyCoordinateTransformation(poCT);
++ IsOK = FALSE;
++ return *this;
++ }
++
++ BoundingBox bbox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
++
++ if (dstCRS.IsGeographic())
++ {
++ if (xMin > 180)
++ xMin = xMin - 360;
++ if (xMax > 180)
++ xMax = xMax - 360;
++
++ if (xMin >= 180.)
++ xMin = 180.;
++ if (xMin <= -180.)
++ xMin = -180.;
++ if (xMax >= 180.)
++ xMax = 180.;
++ if (xMax <= -180.)
++ xMax = -180.;
++
++ if (yMin < 0.)
++ yMin = 0.;
++ if (yMax > 90.)
++ yMax = 90.;
++ }
++ OCTDestroyCoordinateTransformation(poCT);
++ IsOK = TRUE;
++ return BoundingBox(My2DPoint(xMin, yMin), My2DPoint(xMax, yMax), dstCRS);
++}
++
++BoundingBox BoundingBox::Transform(const double GeoTransform[])
++{
++ My2DPoint llPt;
++ My2DPoint urPt;
++ llPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_LowerLeftPT.mi_X + GeoTransform[2] * mo_LowerLeftPT.mi_Y;
++ llPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_LowerLeftPT.mi_X + GeoTransform[5] * mo_LowerLeftPT.mi_Y;
++ urPt.mi_X = GeoTransform[0] + GeoTransform[1] * mo_UpperRightPT.mi_X + GeoTransform[2] * mo_UpperRightPT.mi_Y;
++ urPt.mi_Y = GeoTransform[3] + GeoTransform[4] * mo_UpperRightPT.mi_X + GeoTransform[5] * mo_UpperRightPT.mi_Y;
++
++ return BoundingBox(llPt,urPt,mo_CRS);
++}
++
++/**
++ * Transform Coordinates of lowercorner_left and upcorner_right
++ * lowLeft, upRight.
++ * the return value has considered the case of image area crossing 180/-180 longitude line,
++ * so lowLeft.x maybe bigger than upRight.x
++ */
++CPLErr CPL_STDCALL bBox_transFormmate(OGRSpatialReference& oSrcCRS,
++ OGRSpatialReference& oDesCRS, My2DPoint& lowLeft, My2DPoint& upRight)
++{
++ if (oSrcCRS.IsSame(&oDesCRS))
++ return CE_None;
++
++ OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation(&oSrcCRS, &oDesCRS);
++ if (poCT == NULL)
++ {
++ SetWCS_ErrorLocator("bBox_transFormmate()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Create \"OGRCoordinateTransformation\"");
++ return CE_Failure;
++ }
++
++ double xdes = (upRight.mi_X - lowLeft.mi_X) / 100;
++ if (oSrcCRS.IsGeographic() && upRight.mi_X < lowLeft.mi_X && lowLeft.mi_X > 0 && upRight.mi_X < 0)
++ {
++ xdes = (360 + upRight.mi_X - lowLeft.mi_X) / 100;
++ }
++
++ vector<double> x, y;
++ //up and down edge
++ for (double stepX = lowLeft.mi_X; stepX < upRight.mi_X; stepX += xdes)
++ {
++ x.push_back(stepX);
++ y.push_back(upRight.mi_Y);
++ x.push_back(stepX);
++ y.push_back(lowLeft.mi_Y);
++ }
++ x.push_back(upRight.mi_X);
++ y.push_back(upRight.mi_Y);
++ x.push_back(upRight.mi_X);
++ y.push_back(lowLeft.mi_Y);
++
++ double yMin = numeric_limits<double>::max();
++ double yMax = -numeric_limits<double>::max();
++
++ int k = 0;
++ vector<int> bSuccess;
++ vector<double> tmpX;
++ vector<double> tmpY;
++
++ for (unsigned int i = 0; i < x.size(); i++)
++ {
++ tmpX.push_back(x[i]);
++ tmpY.push_back(y[i]);
++ bSuccess.push_back(0);
++ }
++
++ poCT->TransformEx(x.size(), &tmpX[0], &tmpY[0], NULL, &bSuccess[0]);
++
++ for (unsigned int n = 0; n < x.size(); n++)
++ {
++ if (bSuccess[n])
++ {
++ ++k;
++ yMin = MIN(yMin,tmpY[n]);
++ yMax = MAX(yMax,tmpY[n]);
++ }
++ }
++
++ if (k < 80)
++ {
++ OCTDestroyCoordinateTransformation(poCT);
++ SetWCS_ErrorLocator("bBox_transFormmate()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
++ return CE_Failure;
++ }
++
++ double xMin;
++ double xMax;
++
++ //find xmin on left edge and xmax on right edge
++ double tmpPTX[2];
++ double tmpPTY[2];
++ int isOK[2];
++
++ tmpPTX[0] = lowLeft.mi_X;
++ tmpPTX[1] = lowLeft.mi_X;
++ tmpPTY[0] = upRight.mi_Y;
++ tmpPTY[1] = lowLeft.mi_Y;
++
++ poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
++ if (isOK[0] && isOK[1])
++ {
++ xMin = MIN(tmpPTX[0],tmpPTX[1]);
++ }
++ else
++ {
++ OCTDestroyCoordinateTransformation(poCT);
++ SetWCS_ErrorLocator("bBox_transFormmate()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
++ return CE_Failure;
++ }
++
++ tmpPTX[0] = upRight.mi_X;
++ tmpPTX[1] = upRight.mi_X;
++ tmpPTY[0] = upRight.mi_Y;
++ tmpPTY[1] = lowLeft.mi_Y;
++
++ poCT->TransformEx(2, tmpPTX, tmpPTY, NULL, isOK);
++ if (isOK[0] && isOK[1])
++ {
++ xMax = MAX(tmpPTX[0],tmpPTX[1]);
++ }
++ else
++ {
++ SetWCS_ErrorLocator("bBox_transFormmate()");
++ OCTDestroyCoordinateTransformation(poCT);
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Transform Coordinates");
++ return CE_Failure;
++ }
++
++ lowLeft.mi_X = xMin;
++ lowLeft.mi_Y = yMin;
++ upRight.mi_X = xMax;
++ upRight.mi_Y = yMax;
++
++ if (oDesCRS.IsGeographic())
++ {
++ if (xMin > 180)
++ lowLeft.mi_X = xMin - 360;
++ if (xMax > 180)
++ upRight.mi_X = xMax - 360;
++
++ if (lowLeft.mi_X >= 180.)
++ lowLeft.mi_X = 180.;
++ if (lowLeft.mi_X <= -180.)
++ lowLeft.mi_X = -180.;
++ if (upRight.mi_X >= 180.)
++ upRight.mi_X = 180.;
++ if (upRight.mi_X <= -180.)
++ upRight.mi_X = -180.;
++
++ if (lowLeft.mi_Y <= -90.)
++ lowLeft.mi_Y = -90.;
++ if (upRight.mi_Y >= 90.)
++ upRight.mi_Y = 90.;
++ }
++ OCTDestroyCoordinateTransformation(poCT);
++
++ return CE_None;
++}
+diff -Nur bes-3.12.0/functions.orig/swath2grid/BoundingBox.h bes-3.12.0/functions/swath2grid/BoundingBox.h
+--- bes-3.12.0/functions.orig/swath2grid/BoundingBox.h 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/BoundingBox.h 2014-03-03 15:47:38.053566262 +0100
+@@ -0,0 +1,137 @@
++/******************************************************************************
++ * $Id: BoundingBox.h 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: BoundingBox class definition
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#ifndef BOUNDINGBOX_H_
++#define BOUNDINGBOX_H_
++
++#include <gdal.h>
++#include <ogr_spatialref.h>
++#include <limits>
++#include <stdlib.h>
++
++using namespace std;
++
++/************************************************************************/
++/* ==================================================================== */
++/* My2DPoint */
++/* ==================================================================== */
++/************************************************************************/
++
++/**
++ * \class My2DPoint "BoundingBox.h"
++ *
++ * My2DPoint class is used to store the point coordinates.
++ */
++
++class My2DPoint
++{
++public:
++ double mi_X;
++ double mi_Y;
++
++ virtual ~My2DPoint();
++
++ My2DPoint()
++ {
++ mi_X = 0;
++ mi_Y = 0;
++ }
++
++ My2DPoint(const double& xx, const double& yy) :
++ mi_X(xx), mi_Y(yy)
++ {
++ }
++
++ My2DPoint(const My2DPoint& p) :
++ mi_X(p.mi_X), mi_Y(p.mi_Y)
++ {
++ }
++
++ My2DPoint& operator =(const My2DPoint& p)
++ {
++ mi_X = p.mi_X;
++ mi_Y = p.mi_Y;
++ return *this;
++ }
++};
++
++/************************************************************************/
++/* ==================================================================== */
++/* BoundingBox */
++/* ==================================================================== */
++/************************************************************************/
++
++/**
++ * \class BoundingBox "BoundingBox.h"
++ *
++ * BoundingBox class is used to transform bounding box between different
++ * Coordinate Reference System.
++ */
++
++class BoundingBox
++{
++public:
++ My2DPoint mo_LowerLeftPT;
++ My2DPoint mo_UpperRightPT;
++ OGRSpatialReference mo_CRS;
++
++ BoundingBox(const My2DPoint& llpt, const My2DPoint& urpt, OGRSpatialReference& crs) :
++ mo_LowerLeftPT(llpt), mo_UpperRightPT(urpt), mo_CRS(crs)
++ {
++
++ }
++
++ BoundingBox(OGRSpatialReference& crs) :
++ mo_LowerLeftPT(0,0), mo_UpperRightPT(0,0), mo_CRS(crs)
++ {
++
++ }
++ BoundingBox& operator =(const BoundingBox& box)
++ {
++ mo_LowerLeftPT = box.mo_LowerLeftPT;
++ mo_UpperRightPT = box.mo_UpperRightPT;
++ mo_CRS = box.mo_CRS;
++ return *this;
++ }
++
++ BoundingBox();
++ virtual ~BoundingBox();
++
++ BoundingBox Transform(OGRSpatialReference&, int&);
++ BoundingBox TransformWorkExtend(OGRSpatialReference&, int&);
++ BoundingBox Transform(const double*);
++};
++
++CPLErr CPL_DLL CPL_STDCALL bBox_transFormmate( OGRSpatialReference&,
++ OGRSpatialReference&,
++ My2DPoint& lowLeft,
++ My2DPoint& upRight);
++
++#endif /* BOUNDINGBOX_H_ */
+diff -Nur bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.cpp bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp
+--- bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.cpp 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/DAP_Dataset.cpp 2014-03-03 15:47:38.046899595 +0100
+@@ -0,0 +1,730 @@
++
++// -*- mode: c++; c-basic-offset:4 -*-
++
++// This file is part of libdap, A C++ implementation of the OPeNDAP Data
++// Access Protocol.
++
++// Copyright (c) 2012 OPeNDAP, Inc.
++// Author: James Gallagher <jgallagher at opendap.org>
++//
++// This library is free software; you can redistribute it and/or
++// modify it under the terms of the GNU Lesser General Public
++// License as published by the Free Software Foundation; either
++// version 2.1 of the License, or (at your option) any later version.
++//
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++// Lesser General Public License for more details.
++//
++// You should have received a copy of the GNU Lesser General Public
++// License along with this library; if not, write to the Free Software
++// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++//
++// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
++
++#include <cstdlib>
++
++#define DODS_DEBUG
++
++#include "DAP_Dataset.h"
++
++#include "Array.h"
++#include "Grid.h"
++#include "Float64.h"
++
++#include "ce_functions.h"
++#include "util.h"
++#include "debug.h"
++
++using namespace libdap;
++using namespace std;
++
++#if 0
++#define GOES_TIME_DEBUG FALSE
++#endif
++
++namespace libdap {
++
++DAP_Dataset::DAP_Dataset()
++{
++}
++
++/************************************************************************/
++/* ~DAP_Dataset() */
++/************************************************************************/
++
++/**
++ * \brief Destroy an open DAP_Dataset object.
++ *
++ * This is the accepted method of closing a DAP_Dataset dataset and
++ * deallocating all resources associated with it.
++ */
++
++DAP_Dataset::~DAP_Dataset()
++{
++}
++
++/************************************************************************/
++/* DAP_Dataset() */
++/************************************************************************/
++
++/**
++ * \brief Create an DAP_Dataset object.
++ *
++ * This is the accepted method of creating a DAP_Dataset object and
++ * allocating all resources associated with it.
++ *
++ * @param id The coverage identifier.
++ *
++ * @param rBandList The field list selected for this coverage. For TRMM
++ * daily data, the user could specify multiple days range in request.
++ * Each day is seemed as one field.
++ *
++ * @return A DAP_Dataset object.
++ */
++
++DAP_Dataset::DAP_Dataset(const string& id, vector<int> &rBandList) :
++ AbstractDataset(id, rBandList)
++{
++ md_MissingValue = 0;
++ mb_GeoTransformSet = FALSE;
++}
++
++/**
++ * @brief Initialize a DAP Dataset using Array objects already read.
++ *
++ *
++ */
++
++DAP_Dataset::DAP_Dataset(Array *src, Array *lat, Array *lon) :
++ AbstractDataset(), m_src(src), m_lat(lat), m_lon(lon)
++{
++#if 1
++ // TODO Remove these?
++ DBG(cerr << "Registering GDAL drivers" << endl);
++ GDALAllRegister();
++ OGRRegisterAll();
++#endif
++
++ CPLSetErrorHandler(CPLQuietErrorHandler);
++
++ // Read this from the 'missing_value' or '_FillValue' attributes
++ string missing_value = m_src->get_attr_table().get_attr("missing_value");
++ if (missing_value.empty())
++ missing_value = m_src->get_attr_table().get_attr("_FillValue");
++
++ if (!missing_value.empty())
++ md_MissingValue = atof(missing_value.c_str());
++ else
++ md_MissingValue = 0;
++
++ mb_GeoTransformSet = FALSE;
++}
++
++/************************************************************************/
++/* InitialDataset() */
++/************************************************************************/
++
++/**
++ * \brief Initialize the GOES dataset with NetCDF format.
++
++ * This method is the implementation for initializing a GOES dataset with NetCDF format.
++ * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
++ * will be called to initialize an GOES dataset.
++ *
++ * @note To use this, call this method and then access the GDALDataset that
++ * contains the reprojected array using maptr_DS.get().
++ *
++ * @param isSimple the WCS request type. When user executing a DescribeCoverage
++ * request, isSimple is set to 1, and for GetCoverage, is set to 0.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::InitialDataset(const int isSimple)
++{
++ DBG(cerr << "In InitialDataset" << endl);
++
++ // Might break that operation out so the remap is a separate call
++ if (CE_None != SetNativeCRS() || CE_None != SetGeoTransform())
++ throw Error("Could not set the dataset native CRS or the GeoTransform.");
++
++ DBG(cerr << "Before SetGDALDataset" << endl);
++
++ if (CE_None != SetGDALDataset(isSimple)) {
++ GDALClose(maptr_DS.release());
++ throw Error("Could not reproject the dataset.");
++ }
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* GetDAPArray() */
++/************************************************************************/
++
++/**
++ * @brief Build a DAP Array from the GDALDataset
++ */
++Array *DAP_Dataset::GetDAPArray()
++{
++ DBG(cerr << "In GetDAPArray" << endl);
++ DBG(cerr << "maptr_DS: " << maptr_DS.get() << endl);
++ DBG(cerr << "raster band count: " << maptr_DS->GetRasterCount() << endl);
++
++ // There should be just one band
++ if (maptr_DS->GetRasterCount() != 1)
++ throw Error("In function swath2grid(), expected a single raster band.");
++
++ // Get the x and y dimensions of the raster band
++ int x = maptr_DS->GetRasterXSize();
++ int y = maptr_DS->GetRasterYSize();
++ GDALRasterBand *rb = maptr_DS->GetRasterBand(1);
++ if (!rb)
++ throw Error("In function swath2grid(), could not access the raster data.");
++
++ // Since the DAP_Dataset code works with all data values as doubles,
++ // Assume the raster band has GDAL type GDT_Float64, but test anyway
++ if (GDT_Float64 != rb->GetRasterDataType())
++ throw Error("In function swath2grid(), expected raster data to be of type double.");
++
++ DBG(cerr << "Destination array will have dimensions: " << x << ", " << y << endl);
++
++ Array *a = new Array(m_src->name(), new Float64(m_src->name()));
++
++ // Make the result array have two dimensions
++ Array::Dim_iter i = m_src->dim_begin();
++
++ a->append_dim(x, m_src->dimension_name(i));
++ ++i;
++
++ if (i == m_src->dim_end())
++ throw Error("In function swath2grid(), expected source array to have two dimensions (2).");
++
++ a->append_dim(y, m_src->dimension_name(i));
++
++ // Poke in the data values
++ /* RasterIO ( GDALRWFlag eRWFlag,
++ int nXOff,
++ int nYOff,
++ int nXSize,
++ int nYSize,
++ void * pData,
++ int nBufXSize,
++ int nBufYSize,
++ GDALDataType eBufType,
++ int nPixelSpace,
++ int nLineSpace
++ ) */
++ vector<double> data(x * y);
++ rb->RasterIO(GF_Read, 0, 0, x, y, &data[0], x, y, GDT_Float64, 0, 0);
++
++ // NB: set_value() copies into new storage
++ a->set_value(data, data.size());
++
++ // Now poke in some attributes
++ // TODO Make these CF attributes
++ string projection_info = maptr_DS->GetProjectionRef();
++ string gcp_projection_info = maptr_DS->GetGCPProjection();
++
++ // This sets the instance variable that holds the geotransform coefs. These
++ // are needed by the GetDAPGrid() method.
++ if (CE_None != maptr_DS->GetGeoTransform (m_geo_transform_coef))
++ throw Error("In function swath2grid(), could not access the geo transform data.");
++
++ DBG(cerr << "projection_info: " << projection_info << endl);
++ DBG(cerr << "gcp_projection_info: " << gcp_projection_info << endl);
++ DBG(cerr << "geo_transform coefs: " << double_to_string(m_geo_transform_coef[0]) << endl);
++
++ AttrTable &attr = a->get_attr_table();
++ attr.append_attr("projection", "String", projection_info);
++ attr.append_attr("gcp_projection", "String", gcp_projection_info);
++ for (unsigned int i = 0; i < sizeof(m_geo_transform_coef); ++i) {
++ attr.append_attr("geo_transform_coefs", "String", double_to_string(m_geo_transform_coef[i]));
++ }
++
++ return a;
++}
++
++/************************************************************************/
++/* GetDAPGrid() */
++/************************************************************************/
++
++/**
++ * @brief Build a DAP Grid from the GDALDataset
++ */
++Grid *DAP_Dataset::GetDAPGrid()
++{
++ DBG(cerr << "In GetDAPGrid" << endl);
++
++ Array *a = GetDAPArray();
++ Array::Dim_iter i = a->dim_begin();
++ int lon_size = a->dimension_size(i);
++ int lat_size = a->dimension_size(++i);
++
++ Grid *g = new Grid(a->name());
++ g->add_var_nocopy(a, array);
++
++ // Add maps; assume lon, lat; only two dimensions
++ Array *lon = new Array("longitude", new Float64("longitude"));
++ lon->append_dim(lon_size);
++
++ vector<double> data(max(lon_size, lat_size)); // (re)use this for both lon and lat
++
++ // Compute values
++ // u = a*x + b*y
++ // v = c*x + d*y
++ // u,v --> x,y --> lon,lat
++ // The constants a, b, c, d are given by the 1, 2, 4, and 5 entries in the geotransform array.
++
++ if (m_geo_transform_coef[2] != 0)
++ throw Error("The transformed data's Geographic projection should not be rotated.");
++ for (int j = 0; j < lon_size; ++j) {
++ data[j] = m_geo_transform_coef[1] * j + m_geo_transform_coef[0];
++ }
++
++ // load (copy) values
++ lon->set_value(&data[0], lon_size);
++ // Set the map
++ g->add_var_nocopy(lon, maps);
++
++ // Now do the latitude map
++ Array *lat = new Array("latitude", new Float64("latitude"));
++ lat->append_dim(lat_size);
++
++ if (m_geo_transform_coef[4] != 0)
++ throw Error("The transformed data's Geographic projection should not be rotated.");
++ for (int k = 0; k < lat_size; ++k) {
++ data[k] = m_geo_transform_coef[5] * k + m_geo_transform_coef[3];
++ }
++
++ lat->set_value(&data[0], lat_size);
++ g->add_var_nocopy(lat, maps);
++
++ return g;
++}
++
++/************************************************************************/
++/* SetNativeCRS() */
++/************************************************************************/
++
++/**
++ * \brief Set the Native CRS for a GOES dataset.
++ *
++ * The method will set the CRS for a GOES dataset as an native CRS.
++ *
++ * Since the original GOES data adopt satellite CRS to recored its value,
++ * like MODIS swath data, each data point has its corresponding latitude
++ * and longitude value, those coordinates could be fetched in another two fields.
++ *
++ * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
++ * both the latitude and longitude are existed.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::SetNativeCRS()
++{
++ DBG(cerr << "In SetNativeCRS" << endl);
++
++ mo_NativeCRS.SetWellKnownGeogCS("WGS84");
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetGeoTransform() */
++/************************************************************************/
++
++/**
++ * \brief Set the affine GeoTransform matrix for a GOES data.
++ *
++ * The method will set a GeoTransform matrix for a GOES data
++ * by parsing the coordinates values existed in longitude and latitude field.
++ *
++ * The CRS for the bounding box is EPSG:4326.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::SetGeoTransform()
++{
++ DBG(cerr << "In SetGeoTransform" << endl);
++
++ // TODO Look at this; is this correct
++ // Assume the array is two dimensional
++ Array::Dim_iter i = m_src->dim_begin();
++#if 0
++ // ORIGINAL code; maybe wrong
++ int nXSize = m_src->dimension_size(i, true);
++ int nYSize = m_src->dimension_size(i + 1, true);
++#endif
++ // Data are in row-major order, so the first dim is the Y-axis value
++ int nYSize = m_src->dimension_size(i, true);
++ int nXSize = m_src->dimension_size(i + 1, true);
++
++ mi_SrcImageXSize = nXSize;
++ mi_SrcImageYSize = nYSize;
++
++ SetGeoBBoxAndGCPs(nXSize, nYSize);
++
++ double resX, resY;
++ if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
++ resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
++ else
++ resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (nXSize - 1);
++
++ resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (nYSize - 1);
++
++ double res = MIN(resX, resY);
++
++ if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
++ mi_RectifiedImageXSize = (int) ((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
++ else
++ mi_RectifiedImageXSize = (int) ((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
++
++ mi_RectifiedImageYSize = (int) fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
++
++ DBG(cerr << "Source image size: " << nXSize << ", " << nYSize << endl);
++ DBG(cerr << "Rectified image size: " << mi_RectifiedImageXSize << ", " << mi_RectifiedImageYSize << endl);
++
++ md_Geotransform[0] = mdSrcGeoMinX;
++ md_Geotransform[1] = res;
++ md_Geotransform[2] = 0;
++ md_Geotransform[3] = mdSrcGeoMaxY;
++ md_Geotransform[4] = 0;
++ md_Geotransform[5] = -res;
++ mb_GeoTransformSet = TRUE;
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetGeoBBoxAndGCPs() */
++/************************************************************************/
++
++/**
++ * \brief Set the native geographical bounding box and GCP array for a GOES data.
++ *
++ * The method will set the native geographical bounding box
++ * by comparing the coordinates values existed in longitude and latitude field.
++ *
++ * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++void DAP_Dataset::SetGeoBBoxAndGCPs(int nXSize, int nYSize)
++{
++ DBG(cerr << "In SetGeoBBoxAndGCPs" << endl);
++
++ // reuse the Dim_iter for both lat and lon arrays
++ Array::Dim_iter i = m_lat->dim_begin();
++ int nLatXSize = m_lat->dimension_size(i, true);
++ int nLatYSize = m_lat->dimension_size(i + 1, true);
++ i = m_lon->dim_begin();
++ int nLonXSize = m_lon->dimension_size(i, true);
++ int nLonYSize = m_lon->dimension_size(i + 1, true);
++
++ if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
++ throw Error("The size of latitude/longitude and data field does not match.");
++
++#if 0
++ /*
++ * Re-sample Standards:
++ * Height | Width
++ * (0, 500) every other one pixel
++ * [500, 1000) every other two pixels
++ * [1000,1500) every other three pixels
++ * [1500,2000) every other four pixels
++ * ... ...
++ */
++
++ int xSpace = 1;
++ int ySpace = 1;
++ //setResampleStandard(poVDS, xSpace, ySpace);
++
++ // TODO understand how GMU picked this value.
++ // xSpace and ySpace are the stride values for sampling in
++ // the x and y dimensions.
++ const int RESAMPLE_STANDARD = 500;
++
++ xSpace = int(nXSize / RESAMPLE_STANDARD) + 2;
++ ySpace = int(nYSize / RESAMPLE_STANDARD) + 2;
++#endif
++
++ m_lat->read();
++ m_lon->read();
++ double *dataLat = extract_double_array(m_lat);
++ double *dataLon = extract_double_array(m_lon);
++
++ DBG(cerr << "Past lat/lon data read" << endl);
++
++ try {
++
++ mdSrcGeoMinX = 360;
++ mdSrcGeoMaxX = -360;
++ mdSrcGeoMinY = 90;
++ mdSrcGeoMaxY = -90;
++
++ // Sample every other row and column
++ int xSpace = 2;
++ int ySpace = 2;
++
++ int nGCPs = 0;
++ GDAL_GCP gdalCGP;
++
++ for (int iLine = 0; iLine < nYSize - ySpace; iLine += ySpace) {
++ for (int iPixel = 0; iPixel < nXSize - xSpace; iPixel += xSpace) {
++ double x = *(dataLon + (iLine * nYSize) + iPixel);
++ double y = *(dataLat + (iLine * nYSize) + iPixel);
++
++ if (isValidLongitude(x) && isValidLatitude(y)) {
++ char pChr[64];
++ snprintf(pChr, 64, "%d", ++nGCPs);
++ GDALInitGCPs(1, &gdalCGP);
++ gdalCGP.pszId = strdup(pChr);
++ gdalCGP.pszInfo = strdup("");
++ gdalCGP.dfGCPLine = iLine;
++ gdalCGP.dfGCPPixel = iPixel;
++ gdalCGP.dfGCPX = x;
++ gdalCGP.dfGCPY = y;
++
++ DBG2(cerr << "iLine, iPixel: " << iLine << ", " << iPixel << " --> x,y: " << x << ", " << y << endl);
++
++ gdalCGP.dfGCPZ = 0;
++ m_gdalGCPs.push_back(gdalCGP);
++
++ mdSrcGeoMinX = MIN(mdSrcGeoMinX, gdalCGP.dfGCPX);
++ mdSrcGeoMaxX = MAX(mdSrcGeoMaxX, gdalCGP.dfGCPX);
++ mdSrcGeoMinY = MIN(mdSrcGeoMinY, gdalCGP.dfGCPY);
++ mdSrcGeoMaxY = MAX(mdSrcGeoMaxY, gdalCGP.dfGCPY);
++ }
++ }
++ }
++ }
++ catch (...) {
++ delete[] dataLat;
++ delete[] dataLon;
++ throw;
++ }
++
++ delete[] dataLat;
++ delete[] dataLon;
++
++ DBG(cerr << "Leaving SetGeoBBoxAndGCPs" << endl);
++}
++
++/************************************************************************/
++/* SetGDALDataset() */
++/************************************************************************/
++
++/**
++ * \brief Make a 'memory' dataset with one band
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::SetGDALDataset(const int isSimple)
++{
++ DBG(cerr << "In SetGDALDataset" << endl);
++
++ // NB: mi_RectifiedImageXSize & Y are set in SetGeoTransform()
++ GDALDataType eBandType = GDT_Float64;
++ // VRT, which was used in the original sample code, is not supported in this context, so I used MEM
++ GDALDriverH poDriver = GDALGetDriverByName("MEM");
++ if (!poDriver) {
++ throw Error("Failed to get MEM driver (" + string(CPLGetLastErrorMsg()) + ").");
++ }
++
++ GDALDataset* satDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
++ 1, eBandType, NULL);
++ if (!satDataSet) {
++ GDALClose(poDriver);
++ throw Error("Failed to create MEM dataSet (" + string(CPLGetLastErrorMsg()) + ").");
++ }
++
++ GDALRasterBand *poBand = satDataSet->GetRasterBand(1);
++ poBand->SetNoDataValue(md_MissingValue);
++
++ m_src->read();
++ double *data = extract_double_array(m_src);
++ if (CE_None != poBand->RasterIO(GF_Write, 0, 0, mi_RectifiedImageXSize, mi_RectifiedImageYSize, data,
++ mi_SrcImageXSize, mi_SrcImageYSize, eBandType, 0, 0)) {
++ GDALClose((GDALDatasetH) satDataSet);
++ throw Error("Failed to set satellite data band to MEM DataSet (" + string(CPLGetLastErrorMsg()) + ").");
++ }
++ delete[] data;
++
++ //set GCPs for this VRTDataset
++ if (CE_None != SetGCPGeoRef4VRTDataset(satDataSet)) {
++ GDALClose((GDALDatasetH) satDataSet);
++ throw Error("Could not georeference the virtual dataset (" + string(CPLGetLastErrorMsg()) + ").");
++ }
++
++ DBG(cerr << "satDataSet: " << satDataSet << endl);
++
++ maptr_DS.reset(satDataSet);
++
++ if (isSimple)
++ return CE_None;
++
++ return RectifyGOESDataSet();
++}
++
++/************************************************************************/
++/* SetGCPGeoRef4VRTDataset() */
++/************************************************************************/
++
++/**
++ * \brief Set the GCP array for the VRT dataset.
++ *
++ * This method is used to set the GCP array to created VRT dataset based on GDAL
++ * method SetGCPs().
++ *
++ * @param poVDS The VRT dataset.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
++{
++ char* psTargetSRS;
++ mo_NativeCRS.exportToWkt(&psTargetSRS);
++
++#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
++ if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS)) {
++ OGRFree(psTargetSRS);
++ throw Error("Failed to set GCPs.");
++ }
++#else
++ {
++ if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
++ {
++ OGRFree( psTargetSRS );
++ throw Error("Failed to set GCPs.");
++ }
++ }
++#endif
++
++ OGRFree(psTargetSRS);
++
++ return CE_None;
++}
++#if 0
++/************************************************************************/
++/* SetMetaDataList() */
++/************************************************************************/
++
++/**
++ * \brief Set the metadata list for this coverage.
++ *
++ * The method will set the metadata list for the coverage based on its
++ * corresponding GDALDataset object.
++ *
++ * @param hSrc the GDALDataset object corresponding to coverage.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
++{
++ // TODO Remove
++#if 0
++ mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
++ mv_MetaDataList.push_back("unit=GVAR");
++ mv_MetaDataList.push_back("FillValue=0");
++ ms_FieldQuantityDef = "GVAR";
++ ms_AllowRanges = "0 65535";
++ ms_CoveragePlatform = "GOES-11";
++ ms_CoverageInstrument = "GOES-11";
++ ms_CoverageSensor = "Imager";
++#endif
++
++ return CE_None;
++}
++#endif
++/************************************************************************/
++/* GetGeoMinMax() */
++/************************************************************************/
++
++/**
++ * \brief Get the min/max coordinates of laitutude and longitude.
++ *
++ * The method will fetch the min/max coordinates of laitutude and longitude.
++ *
++ * @param geoMinMax an existing four double buffer into which the
++ * native geographical bounding box values will be placed.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::GetGeoMinMax(double geoMinMax[])
++{
++ if (!mb_GeoTransformSet)
++ return CE_Failure;
++
++ geoMinMax[0] = mdSrcGeoMinX;
++ geoMinMax[2] = mdSrcGeoMinY;
++ geoMinMax[1] = mdSrcGeoMaxX;
++ geoMinMax[3] = mdSrcGeoMaxY;
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* RectifyGOESDataSet() */
++/************************************************************************/
++
++/**
++ * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
++ *
++ * The method will convert the GOES dataset from satellite CRS project to
++ * grid CRS based on GDAL API GDALReprojectImage;
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr DAP_Dataset::RectifyGOESDataSet()
++{
++ DBG(cerr << "In RectifyGOESDataSet" << endl);
++
++ char *pszDstWKT;
++ mo_NativeCRS.exportToWkt(&pszDstWKT);
++
++ GDALDriverH poDriver = GDALGetDriverByName("VRT"); // MEM
++ GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize, mi_RectifiedImageYSize,
++ maptr_DS->GetRasterCount(), maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
++ if (NULL == rectDataSet) {
++ GDALClose(poDriver);
++ OGRFree(pszDstWKT);
++ throw Error("Failed to create \"MEM\" dataSet.");
++ }
++
++ rectDataSet->SetProjection(pszDstWKT);
++ rectDataSet->SetGeoTransform(md_Geotransform);
++
++ DBG(cerr << "rectDataSet: " << rectDataSet << endl);
++ DBG(cerr << "satDataSet: " << maptr_DS.get() << endl);
++
++ // FIXME Magic value of 0.125
++ if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet, pszDstWKT,
++ GRA_Lanczos /*GRA_NearestNeighbour*/, 0, 0.0/*0.125*/, NULL, NULL, NULL)) {
++ GDALClose(rectDataSet);
++ GDALClose(poDriver);
++ OGRFree(pszDstWKT);
++ throw Error("Failed to re-project satellite data from GCP CRS to geographical CRS.");
++ }
++
++ OGRFree(pszDstWKT);
++ GDALClose(maptr_DS.release());
++
++ maptr_DS.reset(rectDataSet);
++
++ DBG(cerr << "Leaving RectifyGOESDataSet" << endl);
++
++ return CE_None;
++}
++
++} // namespace libdap
+diff -Nur bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.h bes-3.12.0/functions/swath2grid/DAP_Dataset.h
+--- bes-3.12.0/functions.orig/swath2grid/DAP_Dataset.h 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/DAP_Dataset.h 2014-03-03 15:47:38.050232928 +0100
+@@ -0,0 +1,142 @@
++
++// -*- mode: c++; c-basic-offset:4 -*-
++
++// This file is part of libdap, A C++ implementation of the OPeNDAP Data
++// Access Protocol.
++
++// Copyright (c) 2012 OPeNDAP, Inc.
++// Author: James Gallagher <jgallagher at opendap.org>
++//
++// This library is free software; you can redistribute it and/or
++// modify it under the terms of the GNU Lesser General Public
++// License as published by the Free Software Foundation; either
++// version 2.1 of the License, or (at your option) any later version.
++//
++// This library is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++// Lesser General Public License for more details.
++//
++// You should have received a copy of the GNU Lesser General Public
++// License along with this library; if not, write to the Free Software
++// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++//
++// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
++
++#ifndef DAP_DATASET_H_
++#define DAP_DATASET_H_
++
++#include <string>
++#include "AbstractDataset.h"
++#include "wcsUtil.h"
++
++using namespace std;
++
++namespace libdap {
++
++class Array;
++class Grid;
++
++/************************************************************************/
++/* ==================================================================== */
++/* DAP_Dataset */
++/* ==================================================================== */
++/************************************************************************/
++
++//! DAP_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
++/**
++ * \class DAP_Dataset "DAP_Dataset.h"
++ *
++ * GOES satellites provide the kind of continuous monitoring necessary for
++ * intensive data analysis. They circle the Earth in a geosynchronous orbit,
++ * which means they orbit the equatorial plane of the Earth at a speed
++ * matching the Earth's rotation. This allows them to hover continuously
++ * over one position on the surface. The geosynchronous plane is about
++ * 35,800 km (22,300 miles) above the Earth, high enough to allow the
++ * satellites a full-disc view of the Earth. Because they stay above a
++ * fixed spot on the surface, they provide a constant vigil for the atmospheric
++ * "triggers" for severe weather conditions such as tornadoes, flash floods,
++ * hail storms, and hurricanes. When these conditions develop the GOES
++ * satellites are able to monitor storm development and track their movements.
++ *
++ * GOES satellite imagery is also used to estimate rainfall during
++ * the thunderstorms and hurricanes for flash flood warnings, as well
++ * as estimates snowfall accumulations and overall extent of snow cover.
++ * Such data help meteorologists issue winter storm warnings and spring
++ * snow melt advisories. Satellite sensors also detect ice fields and map
++ * the movements of sea and lake ice.
++ *
++ * For more inforamtion about NOAA GOES data, please access
++ * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
++ *
++ * DAP_Dataset is a subclass of AbstractDataset, which is used to
++ * process GOES Imager and Sounder products.
++ */
++
++class DAP_Dataset : public AbstractDataset {
++protected:
++ string m_ncLatDataSetName;
++ string m_ncLonDataSetName;
++ string m_ncCoverageIDName;
++
++ // Instead of using names and opening files with GDAL,
++ // store pointers to Arrays read by the underlying DAP
++ // server constraint evaluator.
++ Array *m_src;
++ Array *m_lat;
++ Array *m_lon;
++
++ int mi_RectifiedImageXSize;
++ int mi_RectifiedImageYSize;
++ int mi_SrcImageXSize;
++ int mi_SrcImageYSize;
++
++ double mb_LatLonBBox[4];
++ double mdSrcGeoMinX;
++ double mdSrcGeoMinY;
++ double mdSrcGeoMaxX;
++ double mdSrcGeoMaxY;
++
++ // This is not set until GetDAPArray() is called.
++ double m_geo_transform_coef[6];
++
++ vector<GDAL_GCP> m_gdalGCPs;
++
++public:
++ CPLErr SetGCPGeoRef4VRTDataset(GDALDataset*);
++ void SetGeoBBoxAndGCPs(int xSize, int ySize);
++ CPLErr RectifyGOESDataSet();
++ CPLErr setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue);
++
++ int isValidLatitude(const double &lat)
++ {
++ return (lat >= -90 && lat <= 90);
++ }
++ int isValidLongitude(const double &lon)
++ {
++ return (lon >= -180 && lon <= 180);
++ }
++
++ virtual CPLErr SetGeoTransform();
++#if 0
++ virtual CPLErr SetMetaDataList(GDALDataset* hSrcDS); //TODO Remove
++#endif
++ virtual CPLErr SetNativeCRS();
++ virtual CPLErr SetGDALDataset(const int isSimple = 0);
++ virtual CPLErr InitialDataset(const int isSimple = 0);
++ virtual CPLErr GetGeoMinMax(double geoMinMax[]);
++
++public:
++ DAP_Dataset();
++ DAP_Dataset(const string& id, vector<int> &rBandList);
++
++ // Added jhrg 11/23/12
++ DAP_Dataset(Array *src, Array *lat, Array *lon);
++ Array *GetDAPArray();
++ Grid *GetDAPGrid();
++
++ virtual ~DAP_Dataset();
++};
++
++} // namespace libdap
++#endif /* DAP_DATASET_H_ */
+diff -Nur bes-3.12.0/functions.orig/swath2grid/Makefile.am bes-3.12.0/functions/swath2grid/Makefile.am
+--- bes-3.12.0/functions.orig/swath2grid/Makefile.am 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/Makefile.am 2014-03-03 15:47:38.056899595 +0100
+@@ -0,0 +1,106 @@
++
++# Build libswath2grid, part of libdap.
++
++AUTOMAKE_OPTIONS = foreign
++
++AM_CPPFLAGS = -I$(top_srcdir)/GNU -I$(top_srcdir) -I$(top_srcdir)/tests -I$(top_srcdir)/dispatch $(XML2_CFLAGS) $(CURL_CFLAGS)
++AM_LDADD =
++
++if CPPUNIT
++AM_CPPFLAGS += $(CPPUNIT_CFLAGS)
++AM_LDADD += $(CPPUNIT_LIBS)
++endif
++
++# These are not used by automake but are often useful for certain types of
++# debugging. The best way to use these is to run configure as:
++# export CXXFLAGS='...'; ./configure --disable-shared
++# the --disable-shared is not required, but it seems to help with debuggers.
++CXXFLAGS_DEBUG = -g3 -O0 -Wall -W -Wcast-align -Werror
++TEST_COV_FLAGS = -ftest-coverage -fprofile-arcs
++
++# SUBDIRS =
++# DIST_SUBDIRS =
++
++# This determines what gets built by make check
++check_PROGRAMS = $(UNIT_TESTS)
++
++# This determines what gets run by 'make check.'
++# Now (12/20/12) this fails; don't run until it works.
++# TESTS = $(UNIT_TESTS)
++
++
++noinst_LTLIBRARIES = libswath2grid.la
++
++libswath2grid_la_SOURCES = $(SRCS) $(HDRS)
++libswath2grid_la_CPPFLAGS = $(GDAL_CFLAGS) $(XML2_CFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) -I$(top_srcdir)/dispatch
++libswath2grid_la_LDFLAGS =
++libswath2grid_la_LIBADD = $(GDAL_LDFLAGS) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS)
++
++SRCS = AbstractDataset.cpp wcs_error.cpp \
++BoundingBox.cpp wcsUtil.cpp DAP_Dataset.cpp reproj_functions.cc
++
++# NC_GOES_Dataset.cpp NC_GOES_Dataset.h
++
++HDRS = AbstractDataset.h wcs_error.h \
++BoundingBox.h wcsUtil.h DAP_Dataset.h reproj_functions.h
++
++if CPPUNIT
++UNIT_TESTS = s2gTest
++
++else
++UNIT_TESTS =
++
++check-local:
++ @echo ""
++ @echo "**********************************************************"
++ @echo "You must have cppunit 1.12.x or greater installed to run *"
++ @echo "check target in unit-tests directory *"
++ @echo "**********************************************************"
++ @echo ""
++endif
++
++s2gTest_SOURCES = s2gTest.cc
++s2gTest_CPPFLAGS = $(AM_CPPFLAGS) $(DAP_SERVER_CFLAGS) $(DAP_CLIENT_CFLAGS) $(GDAL_CFLAGS)
++s2gTest_LDADD = -ltest-types libswath2grid.la $(AM_LDADD) $(DAP_SERVER_LIBS) $(DAP_CLIENT_LIBS) $(GDAL_LDFLAGS)
++
++if LIBDAP
++check-dap:
++ @echo ""
++ @echo "**********************************************************"
++ @echo "USING DAP "
++ @echo "DAP_CLIENT_CFLAGS: " $(DAP_CLIENT_CFLAGS)
++ @echo "DAP_SERVER_CFLAGS: " $(DAP_SERVER_CFLAGS)
++ @echo "DAP_CLIENT_LIBS: " $(DAP_CLIENT_LIBS)
++ @echo "DAP_SERVER_LIBS: " $(DAP_SERVER_LIBS)
++ @echo "**********************************************************"
++ @echo ""
++else
++check-dap:
++ @echo ""
++ @echo "**********************************************************"
++ @echo " Unable to locate DAP libraries!"
++ @echo "**********************************************************"
++ @echo ""
++endif
++
++
++if GDAL_FOUND
++check-gdal:
++ @echo ""
++ @echo "**********************************************************"
++ @echo "Using gdal. "
++ @echo "GDAL_CFLAGS: " $(GDAL_CFLAGS)
++ @echo "GDAL_LDFLAGS: " $(GDAL_LDFLAGS)
++ @echo "**********************************************************"
++ @echo ""
++else
++check-gdal:
++ @echo ""
++ @echo "**********************************************************"
++ @echo "You must have gdal 12.15.12 or greater installed to run"
++ @echo "check target in unit-tests directory "
++ @echo "GDAL_VERSION: '$(GDAL_VERSION)'"
++ @echo "prefix: '$(prefix)'"
++ @echo "**********************************************************"
++ @echo ""
++endif
+diff -Nur bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.cpp bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.cpp
+--- bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.cpp 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.cpp 2014-03-03 15:47:38.053566262 +0100
+@@ -0,0 +1,625 @@
++/******************************************************************************
++ * $Id: TRMM_Dataset.cpp 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: NC_GOES_Dataset implementation for NOAA GOES data
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#include "NC_GOES_Dataset.h"
++
++using namespace std;
++
++#define GOES_TIME_DEBUG FALSE
++
++NC_GOES_Dataset::NC_GOES_Dataset()
++{
++}
++
++/************************************************************************/
++/* ~NC_GOES_Dataset() */
++/************************************************************************/
++
++/**
++ * \brief Destroy an open NC_GOES_Dataset object.
++ *
++ * This is the accepted method of closing a NC_GOES_Dataset dataset and
++ * deallocating all resources associated with it.
++ */
++
++NC_GOES_Dataset::~NC_GOES_Dataset()
++{
++}
++
++/************************************************************************/
++/* NC_GOES_Dataset() */
++/************************************************************************/
++
++/**
++ * \brief Create an NC_GOES_Dataset object.
++ *
++ * This is the accepted method of creating a NC_GOES_Dataset object and
++ * allocating all resources associated with it.
++ *
++ * @param id The coverage identifier.
++ *
++ * @param rBandList The field list selected for this coverage. For TRMM
++ * daily data, the user could specify multiple days range in request.
++ * Each day is seemed as one field.
++ *
++ * @return A NC_GOES_Dataset object.
++ */
++
++NC_GOES_Dataset::NC_GOES_Dataset(const string& id, vector<int> &rBandList) :
++ AbstractDataset(id, rBandList)
++{
++ md_MissingValue = 0;
++ mb_GeoTransformSet = FALSE;
++}
++
++/************************************************************************/
++/* InitialDataset() */
++/************************************************************************/
++
++/**
++ * \brief Initialize the GOES dataset with NetCDF format.
++
++ * This method is the implementation for initializing a GOES dataset with NetCDF format.
++ * Within this method, SetNativeCRS(), SetGeoTransform() and SetGDALDataset()
++ * will be called to initialize an GOES dataset.
++ *
++ * @param isSimple the WCS request type. When user executing a DescribeCoverage
++ * request, isSimple is set to 1, and for GetCoverage, is set to 0.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::InitialDataset(const int isSimple)
++{
++ vector<string> strSet;
++ unsigned int n = CsvburstCpp(ms_CoverageID, strSet, ':');
++ if (n != 4)
++ {
++ SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Incorrect coverage ID.");
++ return CE_Failure;
++ }
++
++ ms_DataTypeName = strSet[0] + ":" + strSet[1];
++ ms_SrcFilename = StrTrims(strSet[2], " \'\"");
++ ms_DatasetName = strSet[3];
++
++ m_ncLatDataSetName = "NETCDF:" + ms_SrcFilename + ":latitude";
++ m_ncLonDataSetName = "NETCDF:" + ms_SrcFilename + ":longitude";
++ m_ncCoverageIDName = strSet[1] + ":" + strSet[2] + ":" + strSet[3];
++
++ GDALDataset* pSrc = (GDALDataset*) GDALOpenShared(m_ncCoverageIDName.c_str(), GA_ReadOnly);
++ if (pSrc == NULL)
++ {
++ SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open file \"%s\".", ms_SrcFilename.c_str());
++ return CE_Failure;
++ }
++
++ ms_NativeFormat = GDALGetDriverShortName(pSrc->GetDriver());
++
++ //setmetalist
++ SetMetaDataList(pSrc);
++
++ //set noValue
++ unsigned int nBandCount = pSrc->GetRasterCount();
++ if (nBandCount < 1)
++ {
++ GDALClose(pSrc);
++ SetWCS_ErrorLocator("NC_GOES_Dataset::InitialDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The GOES file does not contain any raster band.");
++ return CE_Failure;
++ }
++
++ maptr_DS.reset(pSrc);
++
++ //set moNativeCRS and mGeoTransform
++ if (CE_None != SetNativeCRS() ||
++ CE_None != SetGeoTransform() ||
++ CE_None != SetGDALDataset(isSimple))
++ {
++ GDALClose(maptr_DS.release());
++ return CE_Failure;
++ }
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetNativeCRS() */
++/************************************************************************/
++
++/**
++ * \brief Set the Native CRS for a GOES dataset.
++ *
++ * The method will set the CRS for a GOES dataset as an native CRS.
++ *
++ * Since the original GOES data adopt satellite CRS to recored its value,
++ * like MODIS swath data, each data point has its corresponding latitude
++ * and longitude value, those coordinates could be fetched in another two fields.
++ *
++ * The native CRS for GOES Imager and Sounder data is assigned to EPSG:4326 if
++ * both the latitude and longitude are existed.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetNativeCRS()
++{
++ if (CE_None == AbstractDataset::SetNativeCRS())
++ return CE_None;
++
++ GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
++ GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
++
++ if(hLatDS == NULL) {
++ m_ncLatDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lat";
++ hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
++ }
++
++ if(hLonDS == NULL) {
++ m_ncLonDataSetName = "NETCDF:\"" + ms_SrcFilename + "\":lon";
++ hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
++ }
++
++ if (hLatDS == NULL || hLonDS == NULL)
++ {
++ SetWCS_ErrorLocator("NC_GOES_Dataset::SetNativeCRS()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to open latitude/longitude sub-dataset.");
++ return CE_Failure;
++ }
++
++ mo_NativeCRS.SetWellKnownGeogCS("WGS84");
++
++ GDALClose(hLatDS);
++ GDALClose(hLonDS);
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetGeoTransform() */
++/************************************************************************/
++
++/**
++ * \brief Set the affine GeoTransform matrix for a GOES data.
++ *
++ * The method will set a GeoTransform matrix for a GOES data
++ * by parsing the coordinates values existed in longitude and latitude field.
++ *
++ * The CRS for the bounding box is EPSG:4326.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetGeoTransform()
++{
++ if (CE_None == AbstractDataset::SetGeoTransform())
++ return CE_None;
++
++ if (CE_None != SetGeoBBoxAndGCPs(maptr_DS.get()))
++ return CE_Failure;
++
++ double resX, resY;
++ if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
++ resX = (360 + mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
++ else
++ resX = (mdSrcGeoMaxX - mdSrcGeoMinX) / (maptr_DS->GetRasterXSize() - 1);
++
++ resY = (mdSrcGeoMaxY - mdSrcGeoMinY) / (maptr_DS->GetRasterYSize() - 1);
++
++ double res = MIN(resX,resY);
++
++ if (mdSrcGeoMinX > mdSrcGeoMaxX && mdSrcGeoMinX > 0 && mdSrcGeoMaxX < 0)
++ mi_RectifiedImageXSize = (int)((360 + mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
++ else
++ mi_RectifiedImageXSize = (int)((mdSrcGeoMaxX - mdSrcGeoMinX) / res) + 1;
++
++ mi_RectifiedImageYSize = (int)fabs((mdSrcGeoMaxY - mdSrcGeoMinY) / res) + 1;
++
++ md_Geotransform[0] = mdSrcGeoMinX;
++ md_Geotransform[1] = res;
++ md_Geotransform[2] = 0;
++ md_Geotransform[3] = mdSrcGeoMaxY;
++ md_Geotransform[4] = 0;
++ md_Geotransform[5] = -res;
++ mb_GeoTransformSet = TRUE;
++
++ return CE_None;
++}
++
++CPLErr NC_GOES_Dataset::setResampleStandard(GDALDataset* hSrcDS, int& xRSValue, int& yRSValue)
++{
++ static int RESAMPLE_STANDARD = 500;
++ int nXSize = hSrcDS->GetRasterXSize();
++ int nYSize = hSrcDS->GetRasterYSize();
++
++ xRSValue = int(nXSize / RESAMPLE_STANDARD) + 2;
++ yRSValue = int(nYSize / RESAMPLE_STANDARD) + 2;
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetGeoBBoxAndGCPs() */
++/************************************************************************/
++
++/**
++ * \brief Set the native geographical bounding box and GCP array for a GOES data.
++ *
++ * The method will set the native geographical bounding box
++ * by comparing the coordinates values existed in longitude and latitude field.
++ *
++ * @param poVDS The GDAL dataset returned by calling GDALOpen() method.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetGeoBBoxAndGCPs(GDALDataset* poVDS)
++{
++ GDALDataset* hLatDS = (GDALDataset*) GDALOpen(m_ncLatDataSetName.c_str(), GA_ReadOnly);
++ GDALDataset* hLonDS = (GDALDataset*) GDALOpen(m_ncLonDataSetName.c_str(), GA_ReadOnly);
++
++ int nXSize = poVDS->GetRasterXSize();
++ int nYSize = poVDS->GetRasterYSize();
++
++ mi_GoesSrcImageXSize = nXSize;
++ mi_GoesSrcImageYSize = nYSize;
++
++ int nLatXSize = hLatDS->GetRasterXSize();
++ int nLatYSize = hLatDS->GetRasterYSize();
++ int nLonXSize = hLonDS->GetRasterXSize();
++ int nLonYSize = hLonDS->GetRasterYSize();
++
++ if (nXSize != nLatXSize || nLatXSize != nLonXSize || nYSize != nLatYSize || nLatYSize != nLonYSize)
++ {
++ GDALClose(hLatDS);
++ GDALClose(hLonDS);
++
++ SetWCS_ErrorLocator("NC_GOES_Dataset::SetGeoBBoxAndGCPs()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "The size of latitude/longitude and data field does not match.");
++
++ return CE_Failure;
++ }
++
++ /*
++ * Re-sample Standards:
++ * Height | Width
++ * (0, 500) every other one pixel
++ * [500, 1000) every other two pixels
++ * [1000,1500) every other three pixels
++ * [1500,2000) every other four pixels
++ * ... ...
++ */
++
++ int xSpace = 1;
++ int ySpace = 1;
++ setResampleStandard(poVDS, xSpace, ySpace);
++
++ int nGCPs = 0;
++ GDAL_GCP gdalCGP;
++
++ GDALRasterBand *poBandLat = hLatDS->GetRasterBand(1);
++ GDALRasterBand *poBandLon = hLonDS->GetRasterBand(1);
++ GDALDataType eDT = poBandLat->GetRasterDataType();
++ void *dataLat = NULL;
++ void *dataLon = NULL;
++
++ mdSrcGeoMinX = 360;
++ mdSrcGeoMaxX = -360;
++ mdSrcGeoMinY = 90;
++ mdSrcGeoMaxY = -90;
++
++ switch (eDT)
++ {
++ case GDT_Float32: //For GOES Imager and Sounder data
++ {
++ dataLat = (float *) CPLMalloc(nXSize * sizeof(float));
++ dataLon = (float *) CPLMalloc(nXSize * sizeof(float));
++
++ for (int iLine = 0; iLine < nYSize; iLine += ySpace)
++ {
++ if (iLine >= nYSize)
++ iLine = nYSize - 1;
++
++ poBandLat->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLat, nXSize, 1, GDT_Float32, 0, 0);
++ poBandLon->RasterIO(GF_Read, 0, iLine, nXSize, 1, dataLon, nXSize, 1, GDT_Float32, 0, 0);
++
++ for (int iPixel = 0; iPixel < nXSize; iPixel += xSpace)
++ {
++ if(iPixel >= nXSize)
++ iPixel = nXSize - 1;
++ double x = *((float *) dataLon + iPixel);
++ double y = *((float *) dataLat + iPixel);
++ if (isValidLongitude(x) && isValidLatitude(y))
++ {
++ char pChr[64];
++ sprintf(pChr, "%d", ++nGCPs);
++ GDALInitGCPs(1, &gdalCGP);
++ gdalCGP.pszId = strdup(pChr);
++ gdalCGP.pszInfo = strdup("");
++ gdalCGP.dfGCPLine = iLine;
++ gdalCGP.dfGCPPixel = iPixel;
++ gdalCGP.dfGCPX = x;
++ gdalCGP.dfGCPY = y;
++ gdalCGP.dfGCPZ = 0;
++ m_gdalGCPs.push_back(gdalCGP);
++ mdSrcGeoMinX = MIN(mdSrcGeoMinX,gdalCGP.dfGCPX );
++ mdSrcGeoMaxX = MAX(mdSrcGeoMaxX,gdalCGP.dfGCPX);
++ mdSrcGeoMinY = MIN(mdSrcGeoMinY,gdalCGP.dfGCPY);
++ mdSrcGeoMaxY = MAX(mdSrcGeoMaxY,gdalCGP.dfGCPY);
++ }
++ }
++ }
++
++ VSIFree((float *) dataLat);
++ VSIFree((float *) dataLon);
++ }
++ break;
++
++ default:
++ break;
++ }
++
++ GDALClose(hLatDS);
++ GDALClose(hLonDS);
++
++ return CE_None;
++}
++
++
++/************************************************************************/
++/* SetGDALDataset() */
++/************************************************************************/
++
++/**
++ * \brief Set the GDALDataset object to GOES Imager and Sounder dataset.
++ *
++ * This method is used to set the GOES Imager and Sounder dataset based on GDAL
++ * class VRTDataset.
++ *
++ * @param isSimple the WCS request type. When user executing a DescribeCoverage
++ * request, isSimple is set to 1, and for GetCoverage, is set to 0.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetGDALDataset(const int isSimple)
++{
++ for(int i = 1; i <= maptr_DS->GetRasterCount(); ++i)
++ mv_BandList.push_back(i);
++
++ VRTDataset *poVDS = (VRTDataset *)VRTCreate(mi_RectifiedImageXSize, mi_RectifiedImageYSize);
++ if (poVDS == NULL)
++ {
++ SetWCS_ErrorLocator("NC_GOES_Dataset::SetGDALDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to create VRT DataSet.");
++ return CE_Failure;
++ }
++
++ VRTSourcedRasterBand *poVRTBand = NULL;
++ GDALRasterBand *poSrcBand = NULL;
++ GDALDataType eBandType;
++ for (unsigned int i = 0; i < mv_BandList.size(); i++)
++ {
++ poSrcBand = maptr_DS->GetRasterBand(mv_BandList[i]);
++ eBandType = poSrcBand->GetRasterDataType();
++ poVDS->AddBand(eBandType, NULL);
++ poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand(i + 1);
++ poVRTBand->SetNoDataValue(md_MissingValue);
++
++ if (CE_None != poVRTBand->AddSimpleSource(poSrcBand, 0, 0,
++ mi_RectifiedImageXSize, mi_RectifiedImageYSize, 0, 0,
++ mi_RectifiedImageXSize, mi_RectifiedImageYSize, NULL, md_MissingValue))
++ {
++ GDALClose((GDALDatasetH) poVDS);
++ SetWCS_ErrorLocator("NC_GOES_Dataset::setGDALDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to Add Simple Source into VRT DataSet.");
++ return CE_Failure;
++ }
++ }
++
++ //set GCPs for this VRTDataset
++ if (CE_None != SetGCPGeoRef4VRTDataset(poVDS))
++ {
++ GDALClose((GDALDatasetH) poVDS);
++ return CE_Failure;
++ }
++
++ GDALClose(maptr_DS.release());
++ maptr_DS.reset(poVDS);
++
++ if (isSimple)
++ return CE_None;
++
++ return RectifyGOESDataSet();
++}
++
++/************************************************************************/
++/* SetGCPGeoRef4VRTDataset() */
++/************************************************************************/
++
++/**
++ * \brief Set the GCP array for the VRT dataset.
++ *
++ * This method is used to set the GCP array to created VRT dataset based on GDAL
++ * method SetGCPs().
++ *
++ * @param poVDS The VRT dataset.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetGCPGeoRef4VRTDataset(GDALDataset* poVDS)
++{
++ char* psTargetSRS;
++ mo_NativeCRS.exportToWkt(&psTargetSRS);
++
++#if (__GNUC__ >=4 && __GNUC_MINOR__ > 1)
++ if (CE_None != poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*) (m_gdalGCPs.data()), psTargetSRS))
++ {
++ OGRFree(psTargetSRS);
++ SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode, "Failed to set GCPs.");
++
++ return CE_Failure;
++ }
++#else
++ {
++ if(CE_None!=poVDS->SetGCPs(m_gdalGCPs.size(), (GDAL_GCP*)&m_gdalGCPs[0], psTargetSRS))
++ {
++ OGRFree( psTargetSRS );
++ SetWCS_ErrorLocator("NC_GOES_Dataset::SetGCPGeoRef4VRTDataset()");
++ WCS_Error(CE_Failure,OGC_WCS_NoApplicableCode,"Failed to set GCPs.");
++
++ return CE_Failure;
++ }
++ }
++#endif
++
++ OGRFree(psTargetSRS);
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* SetMetaDataList() */
++/************************************************************************/
++
++/**
++ * \brief Set the metadata list for this coverage.
++ *
++ * The method will set the metadata list for the coverage based on its
++ * corresponding GDALDataset object.
++ *
++ * @param hSrc the GDALDataset object corresponding to coverage.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::SetMetaDataList(GDALDataset* hSrcDS)
++{
++ mv_MetaDataList.push_back("Product_Description=The data was created by GMU WCS from NOAA GOES satellite data.");
++ mv_MetaDataList.push_back("unit=GVAR");
++ mv_MetaDataList.push_back("FillValue=0");
++ ms_FieldQuantityDef = "GVAR";
++ ms_AllowRanges = "0 65535";
++ ms_CoveragePlatform = "GOES-11";
++ ms_CoverageInstrument = "GOES-11";
++ ms_CoverageSensor = "Imager";
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* GetGeoMinMax() */
++/************************************************************************/
++
++/**
++ * \brief Get the min/max coordinates of laitutude and longitude.
++ *
++ * The method will fetch the min/max coordinates of laitutude and longitude.
++ *
++ * @param geoMinMax an existing four double buffer into which the
++ * native geographical bounding box values will be placed.
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::GetGeoMinMax(double geoMinMax[])
++{
++ if (!mb_GeoTransformSet)
++ return CE_Failure;
++
++ geoMinMax[0] = mdSrcGeoMinX;
++ geoMinMax[2] = mdSrcGeoMinY;
++ geoMinMax[1] = mdSrcGeoMaxX;
++ geoMinMax[3] = mdSrcGeoMaxY;
++
++ return CE_None;
++}
++
++/************************************************************************/
++/* GetGeoMinMax() */
++/************************************************************************/
++
++/**
++ * \brief Convert the GOES dataset from satellite CRS project to grid CRS.
++ *
++ * The method will convert the GOES dataset from satellite CRS project to
++ * grid CRS based on GDAL API GDALReprojectImage;
++ *
++ * @return CE_None on success or CE_Failure on failure.
++ */
++
++CPLErr NC_GOES_Dataset::RectifyGOESDataSet()
++{
++ char *pszDstWKT;
++ mo_NativeCRS.exportToWkt(&pszDstWKT);
++
++ GDALDriverH poDriver = GDALGetDriverByName("MEM");
++ GDALDataset* rectDataSet = (GDALDataset*) GDALCreate(poDriver, "", mi_RectifiedImageXSize,
++ mi_RectifiedImageYSize, maptr_DS->GetRasterCount(),
++ maptr_DS->GetRasterBand(1)->GetRasterDataType(), NULL);
++ if (NULL == rectDataSet)
++ {
++ GDALClose(poDriver);
++ OGRFree(pszDstWKT);
++ SetWCS_ErrorLocator("AbstractDataset::rectifyDataSet()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
++ "Failed to create \"MEM\" dataSet.");
++
++ return CE_Failure;
++ }
++
++ rectDataSet->SetProjection(pszDstWKT);
++ rectDataSet->SetGeoTransform(md_Geotransform);
++
++ if (CE_None != GDALReprojectImage(maptr_DS.get(), NULL, rectDataSet,
++ pszDstWKT, GRA_NearestNeighbour, 0, 0.125, NULL, NULL, NULL))
++ {
++ GDALClose(rectDataSet);
++ GDALClose(poDriver);
++ OGRFree(pszDstWKT);
++ SetWCS_ErrorLocator("AbstractDataset::RectifyDataSet()");
++ WCS_Error(CE_Failure, OGC_WCS_NoApplicableCode,
++ "Failed to re-project GOES data from satellite GCP CRS to geographical CRS.");
++
++ return CE_Failure;
++ }
++
++ OGRFree(pszDstWKT);
++ GDALClose(maptr_DS.release());
++
++ maptr_DS.reset(rectDataSet);
++
++ return CE_None;
++}
++
+diff -Nur bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.h bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.h
+--- bes-3.12.0/functions.orig/swath2grid/NC_GOES_Dataset.h 1970-01-01 01:00:00.000000000 +0100
++++ bes-3.12.0/functions/swath2grid/NC_GOES_Dataset.h 2014-03-03 15:47:38.053566262 +0100
+@@ -0,0 +1,124 @@
++/******************************************************************************
++ * $Id: NC_GOES_Dataset.h 2011-07-19 16:24:00Z $
++ *
++ * Project: The Open Geospatial Consortium (OGC) Web Coverage Service (WCS)
++ * for Earth Observation: Open Source Reference Implementation
++ * Purpose: NC_GOES_Dataset class definition
++ * Author: Yuanzheng Shao, yshao3 at gmu.edu
++ *
++ ******************************************************************************
++ * Copyright (c) 2011, Liping Di <ldi at gmu.edu>, Yuanzheng Shao <yshao3 at gmu.edu>
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ ****************************************************************************/
++
++#ifndef NC_GOES_DATASET_H_
++#define NC_GOES_DATASET_H_
++
++#include <string>
++#include "AbstractDataset.h"
++#include "wcsUtil.h"
++
++using namespace std;
++
++/************************************************************************/
++/* ==================================================================== */
++/* NC_GOES_Dataset */
++/* ==================================================================== */
++/************************************************************************/
++
++//! NC_GOES_Dataset is a subclass of AbstractDataset, used to process NOAA GOES data.
++
++/**
++ * \class NC_GOES_Dataset "NC_GOES_Dataset.h"
++ *
++ * GOES satellites provide the kind of continuous monitoring necessary for
++ * intensive data analysis. They circle the Earth in a geosynchronous orbit,
++ * which means they orbit the equatorial plane of the Earth at a speed
++ * matching the Earth's rotation. This allows them to hover continuously
++ * over one position on the surface. The geosynchronous plane is about
++ * 35,800 km (22,300 miles) above the Earth, high enough to allow the
++ * satellites a full-disc view of the Earth. Because they stay above a
++ * fixed spot on the surface, they provide a constant vigil for the atmospheric
++ * "triggers" for severe weather conditions such as tornadoes, flash floods,
++ * hail storms, and hurricanes. When these conditions develop the GOES
++ * satellites are able to monitor storm development and track their movements.
++ *
++ * GOES satellite imagery is also used to estimate rainfall during
++ * the thunderstorms and hurricanes for flash flood warnings, as well
++ * as estimates snowfall accumulations and overall extent of snow cover.
++ * Such data help meteorologists issue winter storm warnings and spring
++ * snow melt advisories. Satellite sensors also detect ice fields and map
++ * the movements of sea and lake ice.
++ *
++ * For more inforamtion about NOAA GOES data, please access
++ * <a href=http://www.oso.noaa.gov/GOES/>http://www.oso.noaa.gov/GOES/</a>
++ *
++ * NC_GOES_Dataset is a subclass of AbstractDataset, which is used to
++ * process GOES Imager and Sounder products.
++ */
++
++class NC_GOES_Dataset : public AbstractDataset
<Skipped 9604 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/bes.git/commitdiff/118a05b799ef1e4150cfaa28047050c19da22e85
More information about the pld-cvs-commit
mailing list