1 : /******************************************************************************
2 : * $Id: gtmwaypointlayer.cpp 17637 2009-09-12 23:22:00Z 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 5 : GTMWaypointLayer::GTMWaypointLayer( const char* pszName,
34 : OGRSpatialReference* poSRSIn,
35 : int bWriterIn,
36 5 : OGRGTMDataSource* poDSIn )
37 : {
38 5 : poCT = NULL;
39 :
40 : /* We are implementing just WGS84, although GTM supports other datum
41 : formats. */
42 5 : if( poSRSIn != NULL )
43 : {
44 3 : poSRS = new OGRSpatialReference(NULL);
45 3 : poSRS->SetWellKnownGeogCS( "WGS84" );
46 3 : 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 2 : poSRS = NULL;
74 : }
75 :
76 5 : poDS = poDSIn;
77 :
78 5 : nNextFID = 0;
79 5 : nTotalFCount = poDS->getNWpts();
80 :
81 5 : poFeatureDefn = new OGRFeatureDefn( pszName );
82 5 : poFeatureDefn->Reference();
83 5 : poFeatureDefn->SetGeomType ( wkbPoint );
84 :
85 : /* We implement just name, comment, and icon, if others needed feel
86 : free to append more parameters */
87 5 : OGRFieldDefn oFieldName( "name", OFTString );
88 5 : poFeatureDefn->AddFieldDefn( &oFieldName );
89 :
90 5 : OGRFieldDefn oFieldComment( "comment", OFTString );
91 5 : poFeatureDefn->AddFieldDefn( &oFieldComment );
92 :
93 5 : OGRFieldDefn oFieldIcon( "icon", OFTInteger );
94 5 : poFeatureDefn->AddFieldDefn( &oFieldIcon );
95 :
96 5 : OGRFieldDefn oFieldTime( "time", OFTDateTime );
97 5 : poFeatureDefn->AddFieldDefn( &oFieldTime );
98 :
99 5 : this->pszName = CPLStrdup(pszName);
100 5 : }
101 :
102 10 : GTMWaypointLayer::~GTMWaypointLayer()
103 : {
104 :
105 10 : }
106 :
107 :
108 : /************************************************************************/
109 : /* WriteFeatureAttributes() */
110 : /************************************************************************/
111 3 : void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float altitude )
112 : {
113 3 : void* pBuffer = NULL;
114 3 : void* pBufferAux = NULL;
115 3 : char psNameField[] = " ";
116 3 : char* pszcomment = NULL;
117 3 : int icon = 48;
118 3 : int date = 0;
119 15 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); ++i)
120 : {
121 12 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
122 12 : if( poFeature->IsFieldSet( i ) )
123 : {
124 9 : const char* pszName = poFieldDefn->GetNameRef();
125 : /* Waypoint name */
126 9 : if (strncmp(pszName, "name", 4) == 0)
127 : {
128 3 : strncpy (psNameField, poFeature->GetFieldAsString( i ), 10);
129 3 : CPLStrlcat (psNameField, " ", sizeof(psNameField));
130 : }
131 : /* Waypoint comment */
132 6 : else if (strncmp(pszName, "comment", 7) == 0)
133 : {
134 3 : pszcomment = CPLStrdup( poFeature->GetFieldAsString( i ) );
135 : }
136 : /* Waypoint icon */
137 3 : else if (strncmp(pszName, "icon", 4) == 0)
138 : {
139 2 : icon = poFeature->GetFieldAsInteger( i );
140 : // Check if it is a valid icon
141 2 : if (icon < 1 || icon > 220)
142 0 : icon = 48;
143 : }
144 : /* Waypoint date */
145 1 : else if (EQUAL(pszName, "time"))
146 : {
147 : struct tm brokendowndate;
148 : int year, month, day, hour, min, sec, TZFlag;
149 1 : if (poFeature->GetFieldAsDateTime( i, &year, &month, &day, &hour, &min, &sec, &TZFlag))
150 : {
151 1 : brokendowndate.tm_year = year - 1900;
152 1 : brokendowndate.tm_mon = month - 1;
153 1 : brokendowndate.tm_mday = day;
154 1 : brokendowndate.tm_hour = hour;
155 1 : brokendowndate.tm_min = min;
156 1 : brokendowndate.tm_sec = sec;
157 1 : GIntBig unixTime = CPLYMDHMSToUnixTime(&brokendowndate);
158 1 : if (TZFlag != 0)
159 0 : unixTime -= (TZFlag - 100) * 15;
160 1 : 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 1 : date = (int)(unixTime - GTM_EPOCH);
169 : }
170 : }
171 : }
172 : }
173 : }
174 :
175 3 : if (pszcomment == NULL)
176 0 : pszcomment = CPLStrdup( "" );
177 :
178 3 : int commentLength = 0;
179 3 : if (pszcomment != NULL)
180 3 : commentLength = strlen(pszcomment);
181 :
182 3 : int bufferSize = 27 + commentLength;
183 3 : pBuffer = CPLMalloc(bufferSize);
184 3 : pBufferAux = pBuffer;
185 : /* Write waypoint name to buffer */
186 3 : strncpy((char*)pBufferAux, psNameField, 10);
187 :
188 : /* Write waypoint string comment size to buffer */
189 3 : pBufferAux = (char*)pBuffer+10;
190 3 : appendUShort(pBufferAux, commentLength);
191 :
192 : /* Write waypoint string comment to buffer */
193 3 : strncpy((char*)pBuffer+12, pszcomment, commentLength);
194 :
195 : /* Write icon to buffer */
196 3 : pBufferAux = (char*)pBuffer+12+commentLength;
197 3 : appendUShort(pBufferAux, icon);
198 :
199 : /* Write dslp to buffer */
200 3 : pBufferAux = (char*)pBufferAux + 2;
201 3 : appendUChar(pBufferAux, 3);
202 :
203 : /* Date */
204 3 : pBufferAux = (char*)pBufferAux + 1;
205 3 : appendInt(pBufferAux, date);
206 :
207 : /* wrot */
208 3 : pBufferAux = (char*)pBufferAux + 4;
209 3 : appendUShort(pBufferAux, 0);
210 :
211 : /* walt */
212 3 : pBufferAux = (char*)pBufferAux + 2;
213 3 : appendFloat(pBufferAux, altitude);
214 :
215 : /* wlayer */
216 3 : pBufferAux = (char*)pBufferAux + 4;
217 3 : appendUShort(pBufferAux, 0);
218 :
219 3 : VSIFWriteL(pBuffer, bufferSize, 1, poDS->getOutputFP());
220 3 : poDS->incNumWaypoints();
221 :
222 3 : if (pszcomment != NULL)
223 3 : CPLFree(pszcomment);
224 3 : CPLFree(pBuffer);
225 3 : }
226 :
227 : /************************************************************************/
228 : /* CreateFeature() */
229 : /************************************************************************/
230 3 : OGRErr GTMWaypointLayer::CreateFeature (OGRFeature *poFeature)
231 : {
232 3 : FILE* fp = poDS->getOutputFP();
233 3 : if (fp == NULL)
234 0 : return CE_Failure;
235 :
236 3 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
237 3 : 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 3 : if (NULL != poCT)
245 : {
246 0 : poGeom = poGeom->clone();
247 0 : poGeom->transform( poCT );
248 : }
249 :
250 :
251 3 : switch( poGeom->getGeometryType() )
252 : {
253 : case wkbPoint:
254 : case wkbPoint25D:
255 : {
256 3 : OGRPoint* point = (OGRPoint*)poGeom;
257 3 : double lat = point->getY();
258 3 : double lon = point->getX();
259 3 : CheckAndFixCoordinatesValidity(lat, lon);
260 3 : poDS->checkBounds((float)lat, (float)lon);
261 3 : writeDouble(fp, lat);
262 3 : writeDouble(fp, lon);
263 3 : float altitude = 0.0;
264 3 : if (poGeom->getGeometryType() == wkbPoint25D)
265 1 : altitude = (float) point->getZ();
266 :
267 3 : 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 3 : if (NULL != poCT)
281 0 : delete poGeom;
282 :
283 3 : return OGRERR_NONE;
284 :
285 : }
286 :
287 6 : OGRFeature* GTMWaypointLayer::GetNextFeature()
288 : {
289 6 : if (bError)
290 0 : return NULL;
291 :
292 12 : while (poDS->hasNextWaypoint())
293 : {
294 6 : Waypoint* poWaypoint = poDS->fetchNextWaypoint();
295 6 : 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 6 : OGRFeature* poFeature = new OGRFeature( poFeatureDefn );
304 6 : double altitude = poWaypoint->getAltitude();
305 6 : if (altitude == 0.0)
306 : poFeature->SetGeometryDirectly(new OGRPoint
307 : (poWaypoint->getLongitude(),
308 5 : poWaypoint->getLatitude()));
309 : else
310 : poFeature->SetGeometryDirectly(new OGRPoint
311 : (poWaypoint->getLongitude(),
312 : poWaypoint->getLatitude(),
313 1 : altitude));
314 :
315 6 : if (poSRS)
316 6 : poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
317 6 : poFeature->SetField( NAME, poWaypoint->getName());
318 6 : poFeature->SetField( COMMENT, poWaypoint->getComment());
319 6 : poFeature->SetField( ICON, poWaypoint->getIcon());
320 :
321 6 : GIntBig wptdate = poWaypoint->getDate();
322 6 : if (wptdate != 0)
323 : {
324 : struct tm brokendownTime;
325 3 : 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 3 : brokendownTime.tm_sec);
333 : }
334 :
335 6 : poFeature->SetFID( nNextFID++ );
336 6 : delete poWaypoint;
337 6 : if( (m_poFilterGeom == NULL
338 : || FilterGeometry( poFeature->GetGeometryRef() ) )
339 : && (m_poAttrQuery == NULL
340 : || m_poAttrQuery->Evaluate( poFeature )) )
341 6 : return poFeature;
342 :
343 0 : delete poFeature;
344 : }
345 0 : return NULL;
346 : }
347 :
348 2 : int GTMWaypointLayer::GetFeatureCount(int bForce)
349 : {
350 2 : if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
351 2 : 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 1140 : }
|