1 : /******************************************************************************
2 : * $Id: gtmtracklayer.cpp 21684 2011-02-11 22:14:01Z warmerdam $
3 : *
4 : * Project: GTM Driver
5 : * Purpose: Implementation of GTMTrackLayer 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 :
32 :
33 10 : GTMTrackLayer::GTMTrackLayer( const char* pszName,
34 : OGRSpatialReference* poSRSIn,
35 : int bWriterIn,
36 10 : OGRGTMDataSource* poDSIn )
37 : {
38 10 : poCT = NULL;
39 :
40 : /* We are implementing just WGS84, although GTM supports other datum
41 : formats. */
42 10 : 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 2 : poSRS = NULL;
74 : }
75 :
76 10 : poDS = poDSIn;
77 :
78 10 : nNextFID = 0;
79 10 : nTotalFCount = poDS->getNTracks();
80 :
81 10 : poFeatureDefn = new OGRFeatureDefn( pszName );
82 10 : poFeatureDefn->Reference();
83 10 : poFeatureDefn->SetGeomType ( wkbLineString );
84 :
85 : /* We implement just name, type, and color for tracks, if others
86 : needed feel free to append more parameters and implement the
87 : code */
88 10 : OGRFieldDefn oFieldName( "name", OFTString );
89 10 : poFeatureDefn->AddFieldDefn( &oFieldName );
90 :
91 10 : OGRFieldDefn oFieldTrackType( "type", OFTInteger );
92 10 : poFeatureDefn->AddFieldDefn( &oFieldTrackType );
93 :
94 10 : OGRFieldDefn oFieldColor( "color", OFTInteger );
95 10 : poFeatureDefn->AddFieldDefn( &oFieldColor );
96 :
97 10 : this->pszName = CPLStrdup(pszName);
98 10 : }
99 :
100 10 : GTMTrackLayer::~GTMTrackLayer()
101 : {
102 : /* poDS, poSRS, poCT, pszName, and poFeatureDefn are released on
103 : parent class*/
104 10 : }
105 :
106 :
107 : /************************************************************************/
108 : /* WriteFeatureAttributes() */
109 : /************************************************************************/
110 8 : void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
111 : {
112 8 : void* pBuffer = NULL;
113 8 : char* psztrackname = NULL;
114 8 : int type = 1;
115 8 : unsigned int color = 0;
116 32 : for (int i = 0; i < poFeatureDefn->GetFieldCount(); ++i)
117 : {
118 24 : OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
119 24 : if( poFeature->IsFieldSet( i ) )
120 : {
121 24 : const char* pszName = poFieldDefn->GetNameRef();
122 : /* track name */
123 24 : if (strncmp(pszName, "name", 4) == 0)
124 : {
125 8 : psztrackname = CPLStrdup( poFeature->GetFieldAsString( i ) );
126 : }
127 : /* track type */
128 16 : else if (strncmp(pszName, "type", 4) == 0)
129 : {
130 8 : type = poFeature->GetFieldAsInteger( i );
131 : // Check if it is a valid type
132 8 : if (type < 1 || type > 30)
133 0 : type = 1;
134 : }
135 : /* track color */
136 8 : else if (strncmp(pszName, "color", 5) == 0)
137 : {
138 8 : color = (unsigned int) poFeature->GetFieldAsInteger( i );
139 8 : if (color > 0xFFFFFF)
140 0 : color = 0xFFFFFFF;
141 : }
142 : }
143 : }
144 :
145 8 : if (psztrackname == NULL)
146 0 : psztrackname = CPLStrdup( "" );
147 :
148 8 : int trackNameLength = 0;
149 8 : if (psztrackname != NULL)
150 8 : trackNameLength = strlen(psztrackname);
151 :
152 8 : int bufferSize = 14 + trackNameLength;
153 8 : pBuffer = CPLMalloc(bufferSize);
154 8 : void* pBufferAux = pBuffer;
155 : /* Write track string name size to buffer */
156 8 : appendUShort(pBufferAux, (unsigned short) trackNameLength);
157 8 : pBufferAux = (char*)pBufferAux + 2;
158 :
159 : /* Write track name */
160 8 : strncpy((char*)pBufferAux, psztrackname, trackNameLength);
161 8 : pBufferAux = (char*)pBufferAux + trackNameLength;
162 :
163 : /* Write track type */
164 8 : appendUChar(pBufferAux, (unsigned char) type);
165 8 : pBufferAux = (char*)pBufferAux + 1;
166 :
167 : /* Write track color */
168 8 : appendInt(pBufferAux, color);
169 8 : pBufferAux = (char*)pBufferAux + 4;
170 :
171 : /* Write track scale */
172 8 : appendFloat(pBufferAux, 0);
173 8 : pBufferAux = (char*)pBufferAux + 4;
174 :
175 : /* Write track label */
176 8 : appendUChar(pBufferAux, 0);
177 8 : pBufferAux = (char*)pBufferAux + 1;
178 :
179 : /* Write track layer */
180 8 : appendUShort(pBufferAux, 0);
181 :
182 8 : VSIFWriteL(pBuffer, bufferSize, 1, poDS->getTmpTracksFP());
183 8 : poDS->incNumTracks();
184 :
185 8 : if (psztrackname != NULL)
186 8 : CPLFree(psztrackname);
187 8 : CPLFree(pBuffer);
188 8 : }
189 :
190 : /************************************************************************/
191 : /* WriteTrackpoint() */
192 : /************************************************************************/
193 30 : inline void GTMTrackLayer::WriteTrackpoint( double lat, double lon, float altitude, bool start )
194 : {
195 30 : void* pBuffer = CPLMalloc(25);
196 30 : void* pBufferAux = pBuffer;
197 : //latitude
198 30 : appendDouble(pBufferAux, lat);
199 30 : pBufferAux = (char*)pBufferAux + 8;
200 : //longitude
201 30 : appendDouble(pBufferAux, lon);
202 30 : pBufferAux = (char*)pBufferAux + 8;
203 : //date
204 30 : appendInt(pBufferAux, 0);
205 30 : pBufferAux = (char*)pBufferAux + 4;
206 : //start
207 30 : appendUChar(pBufferAux, start);
208 30 : pBufferAux = (char*)pBufferAux + 1;
209 : //altitude
210 30 : appendFloat(pBufferAux, altitude);
211 30 : VSIFWriteL(pBuffer, 25, 1, poDS->getTmpTrackpointsFP());
212 30 : poDS->incNumTrackpoints();
213 30 : CPLFree(pBuffer);
214 30 : }
215 :
216 :
217 : /************************************************************************/
218 : /* CreateFeature() */
219 : /************************************************************************/
220 6 : OGRErr GTMTrackLayer::CreateFeature (OGRFeature *poFeature)
221 : {
222 6 : VSILFILE* fpTmpTrackpoints = poDS->getTmpTrackpointsFP();
223 6 : if (fpTmpTrackpoints == NULL)
224 0 : return CE_Failure;
225 :
226 6 : VSILFILE* fpTmpTracks = poDS->getTmpTracksFP();
227 6 : if (fpTmpTracks == NULL)
228 0 : return CE_Failure;
229 :
230 6 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
231 6 : if ( poGeom == NULL )
232 : {
233 : CPLError( CE_Failure, CPLE_AppDefined,
234 0 : "Features without geometry not supported by GTM writer in track layer." );
235 0 : return OGRERR_FAILURE;
236 : }
237 :
238 6 : if (NULL != poCT)
239 : {
240 0 : poGeom = poGeom->clone();
241 0 : poGeom->transform( poCT );
242 : }
243 :
244 6 : switch( poGeom->getGeometryType() )
245 : {
246 : case wkbLineString:
247 : case wkbLineString25D:
248 : {
249 4 : WriteFeatureAttributes(poFeature);
250 4 : OGRLineString* line = (OGRLineString*)poGeom;
251 20 : for(int i = 0; i < line->getNumPoints(); ++i)
252 : {
253 16 : double lat = line->getY(i);
254 16 : double lon = line->getX(i);
255 16 : float altitude = 0;
256 16 : CheckAndFixCoordinatesValidity(lat, lon);
257 16 : poDS->checkBounds((float)lat, (float)lon);
258 16 : if (line->getGeometryType() == wkbLineString25D)
259 0 : altitude = (float)line->getZ(i);
260 16 : WriteTrackpoint( lat, lon, altitude, i==0 );
261 : }
262 4 : break;
263 : }
264 :
265 : case wkbMultiLineString:
266 : case wkbMultiLineString25D:
267 : {
268 2 : int nGeometries = ((OGRGeometryCollection*)poGeom)->getNumGeometries ();
269 6 : for(int j = 0; j < nGeometries; ++j)
270 : {
271 4 : WriteFeatureAttributes(poFeature);
272 4 : OGRLineString* line = (OGRLineString*) ( ((OGRGeometryCollection*)poGeom)->getGeometryRef(j) );
273 4 : int n = (line) ? line->getNumPoints() : 0;
274 18 : for(int i = 0; i < n; ++i)
275 : {
276 14 : double lat = line->getY(i);
277 14 : double lon = line->getX(i);
278 14 : float altitude = 0;
279 14 : CheckAndFixCoordinatesValidity(lat, lon);
280 14 : if (line->getGeometryType() == wkbLineString25D)
281 0 : altitude = (float) line->getZ(i);
282 14 : WriteTrackpoint( lat, lon, altitude, i==0 );
283 : }
284 : }
285 2 : break;
286 : }
287 :
288 : default:
289 : {
290 : CPLError( CE_Failure, CPLE_NotSupported,
291 : "Geometry type of `%s' not supported for 'track' element.\n",
292 0 : OGRGeometryTypeToName(poGeom->getGeometryType()) );
293 0 : if (NULL != poCT)
294 0 : delete poGeom;
295 0 : return OGRERR_FAILURE;
296 : }
297 : }
298 :
299 6 : if (NULL != poCT)
300 0 : delete poGeom;
301 :
302 6 : return OGRERR_NONE;
303 : }
304 :
305 :
306 14 : OGRFeature* GTMTrackLayer::GetNextFeature()
307 : {
308 14 : if (bError)
309 0 : return NULL;
310 :
311 28 : while (poDS->hasNextTrack())
312 : {
313 14 : Track* poTrack = poDS->fetchNextTrack();
314 14 : if (poTrack == NULL)
315 : {
316 : CPLError(CE_Failure, CPLE_AppDefined,
317 0 : "Could not read track. File probably corrupted");
318 0 : bError = TRUE;
319 0 : return NULL;
320 : }
321 14 : OGRFeature* poFeature = new OGRFeature( poFeatureDefn );
322 28 : OGRLineString* lineString = new OGRLineString ();
323 :
324 74 : for (int i = 0; i < poTrack->getNumPoints(); ++i)
325 : {
326 60 : const TrackPoint* psTrackPoint = poTrack->getPoint(i);
327 : lineString->addPoint(psTrackPoint->x,
328 60 : psTrackPoint->y);
329 : }
330 14 : if (poSRS)
331 14 : lineString->assignSpatialReference(poSRS);
332 14 : poFeature->SetField( NAME, poTrack->getName());
333 14 : poFeature->SetField( TYPE, poTrack->getType());
334 14 : poFeature->SetField( COLOR, poTrack->getColor());
335 14 : poFeature->SetFID( nNextFID++ );
336 14 : delete poTrack;
337 :
338 14 : poFeature->SetGeometryDirectly(lineString);
339 14 : if( (m_poFilterGeom == NULL
340 : || FilterGeometry( poFeature->GetGeometryRef() ) )
341 : && (m_poAttrQuery == NULL
342 : || m_poAttrQuery->Evaluate( poFeature )) )
343 14 : return poFeature;
344 :
345 0 : delete poFeature;
346 : }
347 0 : return NULL;
348 : }
349 :
350 4 : int GTMTrackLayer::GetFeatureCount(int bForce)
351 : {
352 4 : if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
353 4 : return poDS->getNTracks();
354 :
355 0 : return OGRLayer::GetFeatureCount(bForce);
356 : }
357 :
358 :
359 0 : void GTMTrackLayer::ResetReading()
360 : {
361 0 : nNextFID = 0;
362 0 : poDS->rewindTrack();
363 4029 : }
364 :
|