1 : /******************************************************************************
2 : * $Id: gtmwaypointlayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
3 : *
4 : * Project: GTM Driver
5 : * Purpose: Implementation of gtmwaypoint class.
6 : * Author: Leonardo de Paula Rosa Piga; http://lampiao.lsc.ic.unicamp.br/~piga
7 : *
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009, Leonardo de Paula Rosa Piga
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 : #include "ogr_gtm.h"
31 : #include "cpl_time.h"
32 :
33 14 : GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
34 : OGRSpatialReference* poSRSIn,
35 : int bWriterIn,
36 14 : OGRGTMDataSource* poDSIn )
37 : {
38 14 : poCT = NULL;
39 :
40 : /* We are implementing just WGS84, although GTM supports other datum
41 : formats. */
42 14 : if( poSRSIn != NULL )
43 : {
44 8 : poSRS = new OGRSpatialReference(NULL);
45 8 : poSRS->SetWellKnownGeogCS( "WGS84" );
46 8 : if (!poSRS->IsSame(poSRSIn))
47 : {
48 0 : poCT = OGRCreateCoordinateTransformation( poSRSIn, poSRS );
49 0 : if( poCT == NULL && poDSIn->isFirstCTError() )
50 : {
51 : /* If we can't create a transformation, issue a warning - but
52 : continue the transformation*/
53 0 : char *pszWKT = NULL;
54 :
55 0 : poSRSIn->exportToPrettyWkt( &pszWKT, FALSE );
56 :
57 : CPLError( CE_Warning, CPLE_AppDefined,
58 : "Failed to create coordinate transformation between the\n"
59 : "input coordinate system and WGS84. This may be because they\n"
60 : "are not transformable, or because projection services\n"
61 : "(PROJ.4 DLL/.so) could not be loaded.\n"
62 : "This message will not be issued any more. \n"
63 : "\nSource:\n%s\n",
64 0 : pszWKT );
65 :
66 0 : CPLFree( pszWKT );
67 0 : poDSIn->issuedFirstCTError();
68 : }
69 : }
70 : }
71 : else
72 : {
73 6 : poSRS = NULL;
74 : }
75 :
76 14 : poDS = poDSIn;
77 :
78 14 : nNextFID = 0;
79 14 : nTotalFCount = poDS->getNWpts();
80 :
81 14 : poFeatureDefn = new OGRFeatureDefn( pszName );
82 14 : poFeatureDefn->Reference();
83 14 : poFeatureDefn->SetGeomType ( wkbPoint );
84 :
85 : /* We implement just name, comment, and icon, if others needed feel
86 : free to append more parameters */
87 14 : OGRFieldDefn oFieldName( "name", OFTString );
88 14 : poFeatureDefn->AddFieldDefn( &oFieldName );
89 :
90 14 : OGRFieldDefn oFieldComment( "comment", OFTString );
91 14 : poFeatureDefn->AddFieldDefn( &oFieldComment );
92 :
93 14 : OGRFieldDefn oFieldIcon( "icon", OFTInteger );
94 14 : poFeatureDefn->AddFieldDefn( &oFieldIcon );
95 :
96 14 : OGRFieldDefn oFieldTime( "time", OFTDateTime );
97 14 : poFeatureDefn->AddFieldDefn( &oFieldTime );
98 :
99 14 : this->pszName = CPLStrdup(pszName);
100 14 : }
101 :
102 14 : GTMWaypointLayer::~GTMWaypointLayer()
103 : {
104 :
105 14 : }
106 :
107 :
108 : /************************************************************************/
109 : /* WriteFeatureAttributes() */
110 : /************************************************************************/
111 8 : void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float altitude )
112 : {
113 8 : void* pBuffer = NULL;
114 8 : void* pBufferAux = NULL;
115 8 : char psNameField[] = " ";
116 8 : char* pszcomment = NULL;
117 8 : int icon = 48;
118 8 : int date = 0;
119 40 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); ++i)
120 : {
121 32 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
122 32 : if( poFeature->IsFieldSet( i ) )
123 : {
124 22 : const char* pszName = poFieldDefn->GetNameRef();
125 : /* Waypoint name */
126 22 : if (strncmp(pszName, "name", 4) == 0)
127 : {
128 8 : strncpy (psNameField, poFeature->GetFieldAsString( i ), 10);
129 8 : CPLStrlcat (psNameField, " ", sizeof(psNameField));
130 : }
131 : /* Waypoint comment */
132 14 : else if (strncmp(pszName, "comment", 7) == 0)
133 : {
134 8 : pszcomment = CPLStrdup( poFeature->GetFieldAsString( i ) );
135 : }
136 : /* Waypoint icon */
137 6 : else if (strncmp(pszName, "icon", 4) == 0)
138 : {
139 4 : icon = poFeature->GetFieldAsInteger( i );
140 : // Check if it is a valid icon
141 4 : if (icon < 1 || icon > 220)
142 0 : icon = 48;
143 : }
144 : /* Waypoint date */
145 2 : else if (EQUAL(pszName, "time"))
146 : {
147 : struct tm brokendowndate;
148 : int year, month, day, hour, min, sec, TZFlag;
149 2 : if (poFeature->GetFieldAsDateTime( i, &year, &month, &day, &hour, &min, &sec, &TZFlag))
150 : {
151 2 : brokendowndate.tm_year = year - 1900;
152 2 : brokendowndate.tm_mon = month - 1;
153 2 : brokendowndate.tm_mday = day;
154 2 : brokendowndate.tm_hour = hour;
155 2 : brokendowndate.tm_min = min;
156 2 : brokendowndate.tm_sec = sec;
157 2 : GIntBig unixTime = CPLYMDHMSToUnixTime(&brokendowndate);
158 2 : if (TZFlag != 0)
159 0 : unixTime -= (TZFlag - 100) * 15;
160 2 : if (unixTime <= GTM_EPOCH || (unixTime - GTM_EPOCH) != (int)(unixTime - GTM_EPOCH))
161 : {
162 : CPLError(CE_Warning, CPLE_AppDefined,
163 : "%04d/%02d/%02d %02d:%02d:%02d is not a valid datetime for GTM",
164 0 : year, month, day, hour, min, sec);
165 : }
166 : else
167 : {
168 2 : date = (int)(unixTime - GTM_EPOCH);
169 : }
170 : }
171 : }
172 : }
173 : }
174 :
175 8 : if (pszcomment == NULL)
176 0 : pszcomment = CPLStrdup( "" );
177 :
178 8 : int commentLength = 0;
179 8 : if (pszcomment != NULL)
180 8 : commentLength = strlen(pszcomment);
181 :
182 8 : int bufferSize = 27 + commentLength;
183 8 : pBuffer = CPLMalloc(bufferSize);
184 8 : pBufferAux = pBuffer;
185 : /* Write waypoint name to buffer */
186 8 : strncpy((char*)pBufferAux, psNameField, 10);
187 :
188 : /* Write waypoint string comment size to buffer */
189 8 : pBufferAux = (char*)pBuffer+10;
190 8 : appendUShort(pBufferAux, (unsigned short) commentLength);
191 :
192 : /* Write waypoint string comment to buffer */
193 8 : strncpy((char*)pBuffer+12, pszcomment, commentLength);
194 :
195 : /* Write icon to buffer */
196 8 : pBufferAux = (char*)pBuffer+12+commentLength;
197 8 : appendUShort(pBufferAux, (unsigned short) icon);
198 :
199 : /* Write dslp to buffer */
200 8 : pBufferAux = (char*)pBufferAux + 2;
201 8 : appendUChar(pBufferAux, 3);
202 :
203 : /* Date */
204 8 : pBufferAux = (char*)pBufferAux + 1;
205 8 : appendInt(pBufferAux, date);
206 :
207 : /* wrot */
208 8 : pBufferAux = (char*)pBufferAux + 4;
209 8 : appendUShort(pBufferAux, 0);
210 :
211 : /* walt */
212 8 : pBufferAux = (char*)pBufferAux + 2;
213 8 : appendFloat(pBufferAux, altitude);
214 :
215 : /* wlayer */
216 8 : pBufferAux = (char*)pBufferAux + 4;
217 8 : appendUShort(pBufferAux, 0);
218 :
219 8 : VSIFWriteL(pBuffer, bufferSize, 1, poDS->getOutputFP());
220 8 : poDS->incNumWaypoints();
221 :
222 8 : if (pszcomment != NULL)
223 8 : CPLFree(pszcomment);
224 8 : CPLFree(pBuffer);
225 8 : }
226 :
227 : /************************************************************************/
228 : /* CreateFeature() */
229 : /************************************************************************/
230 8 : OGRErr GTMWaypointLayer::CreateFeature (OGRFeature *poFeature)
231 : {
232 8 : VSILFILE* fp = poDS->getOutputFP();
233 8 : if (fp == NULL)
234 0 : return CE_Failure;
235 :
236 8 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
237 8 : if ( poGeom == NULL )
238 : {
239 : CPLError( CE_Failure, CPLE_AppDefined,
240 0 : "Features without geometry not supported by GTM writer in waypoints layer." );
241 0 : return OGRERR_FAILURE;
242 : }
243 :
244 8 : if (NULL != poCT)
245 : {
246 0 : poGeom = poGeom->clone();
247 0 : poGeom->transform( poCT );
248 : }
249 :
250 :
251 8 : switch( poGeom->getGeometryType() )
252 : {
253 : case wkbPoint:
254 : case wkbPoint25D:
255 : {
256 8 : OGRPoint* point = (OGRPoint*)poGeom;
257 8 : double lat = point->getY();
258 8 : double lon = point->getX();
259 8 : CheckAndFixCoordinatesValidity(lat, lon);
260 8 : poDS->checkBounds((float)lat, (float)lon);
261 8 : writeDouble(fp, lat);
262 8 : writeDouble(fp, lon);
263 8 : float altitude = 0.0;
264 8 : if (poGeom->getGeometryType() == wkbPoint25D)
265 2 : altitude = (float) point->getZ();
266 :
267 8 : WriteFeatureAttributes(poFeature, altitude);
268 : break;
269 : }
270 :
271 : default:
272 : {
273 : CPLError( CE_Failure, CPLE_NotSupported,
274 : "Geometry type of `%s' not supported for 'waypoint' element.\n",
275 0 : OGRGeometryTypeToName(poGeom->getGeometryType()) );
276 0 : return OGRERR_FAILURE;
277 : }
278 : }
279 :
280 8 : if (NULL != poCT)
281 0 : delete poGeom;
282 :
283 8 : return OGRERR_NONE;
284 :
285 : }
286 :
287 14 : OGRFeature* GTMWaypointLayer::GetNextFeature()
288 : {
289 14 : if (bError)
290 0 : return NULL;
291 :
292 28 : while (poDS->hasNextWaypoint())
293 : {
294 14 : Waypoint* poWaypoint = poDS->fetchNextWaypoint();
295 14 : if (poWaypoint == NULL)
296 : {
297 : CPLError(CE_Failure, CPLE_AppDefined,
298 0 : "Could not read waypoint. File probably corrupted");
299 0 : bError = TRUE;
300 0 : return NULL;
301 : }
302 :
303 14 : OGRFeature* poFeature = new OGRFeature( poFeatureDefn );
304 14 : double altitude = poWaypoint->getAltitude();
305 14 : if (altitude == 0.0)
306 : poFeature->SetGeometryDirectly(new OGRPoint
307 : (poWaypoint->getLongitude(),
308 12 : poWaypoint->getLatitude()));
309 : else
310 : poFeature->SetGeometryDirectly(new OGRPoint
311 : (poWaypoint->getLongitude(),
312 : poWaypoint->getLatitude(),
313 2 : altitude));
314 :
315 14 : if (poSRS)
316 14 : poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
317 14 : poFeature->SetField( NAME, poWaypoint->getName());
318 14 : poFeature->SetField( COMMENT, poWaypoint->getComment());
319 14 : poFeature->SetField( ICON, poWaypoint->getIcon());
320 :
321 14 : GIntBig wptdate = poWaypoint->getDate();
322 14 : if (wptdate != 0)
323 : {
324 : struct tm brokendownTime;
325 6 : CPLUnixTimeToYMDHMS(wptdate, &brokendownTime);
326 : poFeature->SetField( DATE,
327 : brokendownTime.tm_year + 1900,
328 : brokendownTime.tm_mon + 1,
329 : brokendownTime.tm_mday,
330 : brokendownTime.tm_hour,
331 : brokendownTime.tm_min,
332 6 : brokendownTime.tm_sec);
333 : }
334 :
335 14 : poFeature->SetFID( nNextFID++ );
336 14 : delete poWaypoint;
337 14 : if( (m_poFilterGeom == NULL
338 : || FilterGeometry( poFeature->GetGeometryRef() ) )
339 : && (m_poAttrQuery == NULL
340 : || m_poAttrQuery->Evaluate( poFeature )) )
341 14 : return poFeature;
342 :
343 0 : delete poFeature;
344 : }
345 0 : return NULL;
346 : }
347 :
348 4 : int GTMWaypointLayer::GetFeatureCount(int bForce)
349 : {
350 4 : if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
351 4 : return poDS->getNWpts();
352 :
353 0 : return OGRLayer::GetFeatureCount(bForce);
354 : }
355 :
356 0 : void GTMWaypointLayer::ResetReading()
357 : {
358 0 : nNextFID = 0;
359 0 : poDS->rewindWaypoint();
360 4029 : }
|