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