1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  Implements OGRGmtDataSource class.
5  * Author:   Frank Warmerdam, warmerdam@pobox.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "cpl_conv.h"
30 #include "cpl_string.h"
31 #include "ogr_gmt.h"
32 
33 CPL_CVSID("$Id: ogrgmtdatasource.cpp 8e5eeb35bf76390e3134a4ea7076dab7d478ea0e 2018-11-14 22:55:13 +0100 Even Rouault $")
34 
35 /************************************************************************/
36 /*                          OGRGmtDataSource()                          */
37 /************************************************************************/
38 
OGRGmtDataSource()39 OGRGmtDataSource::OGRGmtDataSource() :
40     papoLayers(nullptr),
41     nLayers(0),
42     pszName(nullptr),
43     bUpdate(false)
44 {}
45 
46 /************************************************************************/
47 /*                         ~OGRGmtDataSource()                          */
48 /************************************************************************/
49 
~OGRGmtDataSource()50 OGRGmtDataSource::~OGRGmtDataSource()
51 
52 {
53     for( int i = 0; i < nLayers; i++ )
54         delete papoLayers[i];
55     CPLFree( papoLayers );
56     CPLFree( pszName );
57 }
58 
59 /************************************************************************/
60 /*                                Open()                                */
61 /************************************************************************/
62 
Open(const char * pszFilename,int bUpdateIn)63 int OGRGmtDataSource::Open( const char *pszFilename, int bUpdateIn )
64 
65 {
66     bUpdate = CPL_TO_BOOL( bUpdateIn );
67 
68     OGRGmtLayer *poLayer = new OGRGmtLayer( pszFilename, bUpdate );
69     if( !poLayer->bValidFile )
70     {
71         delete poLayer;
72         return FALSE;
73     }
74 
75     papoLayers = static_cast<OGRGmtLayer **>( CPLRealloc( papoLayers,
76                                         (nLayers + 1) *sizeof(OGRGmtLayer*)) );
77     papoLayers[nLayers] = poLayer;
78     nLayers ++;
79 
80     CPLFree (pszName);
81     pszName = CPLStrdup( pszFilename );
82 
83     return TRUE;
84 }
85 
86 /************************************************************************/
87 /*                               Create()                               */
88 /*                                                                      */
89 /*      Create a new datasource.  This does not really do anything      */
90 /*      currently but save the name.                                    */
91 /************************************************************************/
92 
Create(const char * pszDSName,char **)93 int OGRGmtDataSource::Create( const char *pszDSName, char ** /* papszOptions */)
94 
95 {
96     pszName = CPLStrdup( pszDSName );
97 
98     return TRUE;
99 }
100 
101 /************************************************************************/
102 /*                           ICreateLayer()                             */
103 /************************************************************************/
104 
105 OGRLayer *
ICreateLayer(const char * pszLayerName,OGRSpatialReference * poSRS,OGRwkbGeometryType eType,CPL_UNUSED char ** papszOptions)106 OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
107                                 OGRSpatialReference *poSRS,
108                                 OGRwkbGeometryType eType,
109                                 CPL_UNUSED char ** papszOptions )
110 {
111     if( nLayers != 0 )
112         return nullptr;
113 
114 /* -------------------------------------------------------------------- */
115 /*      Establish the geometry type.  Note this logic                   */
116 /* -------------------------------------------------------------------- */
117     const char *pszGeom = nullptr;
118 
119     switch( wkbFlatten(eType) )
120     {
121       case wkbPoint:
122         pszGeom = " @GPOINT";
123         break;
124       case wkbLineString:
125         pszGeom = " @GLINESTRING";
126         break;
127       case wkbPolygon:
128         pszGeom = " @GPOLYGON";
129         break;
130       case wkbMultiPoint:
131         pszGeom = " @GMULTIPOINT";
132         break;
133       case wkbMultiLineString:
134         pszGeom = " @GMULTILINESTRING";
135         break;
136       case wkbMultiPolygon:
137         pszGeom = " @GMULTIPOLYGON";
138         break;
139       default:
140         pszGeom = "";
141         break;
142     }
143 
144 /* -------------------------------------------------------------------- */
145 /*      If this is the first layer for this datasource, and if the      */
146 /*      datasource name ends in .gmt we will override the provided      */
147 /*      layer name with the name from the gmt.                          */
148 /* -------------------------------------------------------------------- */
149     CPLString osPath = CPLGetPath( pszName );
150     CPLString osFilename;
151 
152     if( EQUAL(CPLGetExtension(pszName),"gmt") )
153         osFilename = pszName;
154     else
155         osFilename = CPLFormFilename( osPath, pszLayerName, "gmt" );
156 
157 /* -------------------------------------------------------------------- */
158 /*      Open the file.                                                  */
159 /* -------------------------------------------------------------------- */
160     VSILFILE *fp = VSIFOpenL( osFilename, "w" );
161     if( fp == nullptr )
162     {
163         CPLError( CE_Failure, CPLE_OpenFailed,
164                   "open(%s) failed: %s",
165                   osFilename.c_str(), VSIStrerror(errno) );
166         return nullptr;
167     }
168 
169 /* -------------------------------------------------------------------- */
170 /*      Write out header.                                               */
171 /* -------------------------------------------------------------------- */
172     VSIFPrintfL( fp, "# @VGMT1.0%s\n", pszGeom );
173     VSIFPrintfL( fp, "# REGION_STUB                                      "
174                  "                       \n" );
175 
176 /* -------------------------------------------------------------------- */
177 /*      Write the projection, if possible.                              */
178 /* -------------------------------------------------------------------- */
179     if( poSRS != nullptr )
180     {
181         if( poSRS->GetAuthorityName(nullptr)
182             && EQUAL(poSRS->GetAuthorityName(nullptr),"EPSG") )
183         {
184             VSIFPrintfL( fp, "# @Je%s\n",
185                          poSRS->GetAuthorityCode(nullptr) );
186         }
187 
188         char *pszValue = nullptr;
189         if( poSRS->exportToProj4( &pszValue ) == OGRERR_NONE )
190         {
191             VSIFPrintfL( fp, "# @Jp\"%s\"\n", pszValue );
192         }
193         CPLFree( pszValue );
194         pszValue = nullptr;
195 
196         if( poSRS->exportToWkt( &pszValue ) == OGRERR_NONE )
197         {
198             char *pszEscapedWkt = CPLEscapeString( pszValue, -1,
199                                                    CPLES_BackslashQuotable );
200 
201             VSIFPrintfL( fp, "# @Jw\"%s\"\n", pszEscapedWkt );
202             CPLFree( pszEscapedWkt );
203         }
204         CPLFree( pszValue );
205     }
206 
207 /* -------------------------------------------------------------------- */
208 /*      Finish header and close.                                        */
209 /* -------------------------------------------------------------------- */
210     VSIFCloseL( fp );
211 
212 /* -------------------------------------------------------------------- */
213 /*      Return open layer handle.                                       */
214 /* -------------------------------------------------------------------- */
215     if( Open( osFilename, TRUE ) )
216         return papoLayers[nLayers-1];
217 
218     return nullptr;
219 }
220 
221 /************************************************************************/
222 /*                           TestCapability()                           */
223 /************************************************************************/
224 
TestCapability(const char * pszCap)225 int OGRGmtDataSource::TestCapability( const char * pszCap )
226 
227 {
228     if( EQUAL(pszCap,ODsCCreateLayer) )
229         return TRUE;
230 
231     return FALSE;
232 }
233 
234 /************************************************************************/
235 /*                              GetLayer()                              */
236 /************************************************************************/
237 
GetLayer(int iLayer)238 OGRLayer *OGRGmtDataSource::GetLayer( int iLayer )
239 
240 {
241     if( iLayer < 0 || iLayer >= nLayers )
242         return nullptr;
243 
244     return papoLayers[iLayer];
245 }
246