PageRenderTime 48ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/gdal-1.9.1-fedora/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp

#
C++ | 421 lines | 263 code | 67 blank | 91 comment | 28 complexity | ba25fff9acb365984b3567af070a029d MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0
  1. /******************************************************************************
  2. * $Id: ogr_xplane_awy_reader.cpp
  3. *
  4. * Project: X-Plane awy.dat file reader
  5. * Purpose: Implements OGRXPlaneAwyReader class
  6. * Author: Even Rouault, even dot rouault at mines dash paris dot org
  7. *
  8. ******************************************************************************
  9. * Copyright (c) 2008, Even Rouault
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a
  12. * copy of this software and associated documentation files (the "Software"),
  13. * to deal in the Software without restriction, including without limitation
  14. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. * and/or sell copies of the Software, and to permit persons to whom the
  16. * Software is furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included
  19. * in all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27. * DEALINGS IN THE SOFTWARE.
  28. ****************************************************************************/
  29. #include "ogr_xplane_awy_reader.h"
  30. CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
  31. /************************************************************************/
  32. /* OGRXPlaneCreateAwyFileReader */
  33. /************************************************************************/
  34. OGRXPlaneReader* OGRXPlaneCreateAwyFileReader( OGRXPlaneDataSource* poDataSource )
  35. {
  36. OGRXPlaneReader* poReader = new OGRXPlaneAwyReader(poDataSource);
  37. return poReader;
  38. }
  39. /************************************************************************/
  40. /* OGRXPlaneAwyReader() */
  41. /************************************************************************/
  42. OGRXPlaneAwyReader::OGRXPlaneAwyReader()
  43. {
  44. poAirwaySegmentLayer = NULL;
  45. poAirwayIntersectionLayer = NULL;
  46. }
  47. /************************************************************************/
  48. /* OGRXPlaneAwyReader() */
  49. /************************************************************************/
  50. OGRXPlaneAwyReader::OGRXPlaneAwyReader( OGRXPlaneDataSource* poDataSource )
  51. {
  52. poAirwaySegmentLayer = new OGRXPlaneAirwaySegmentLayer();
  53. poAirwayIntersectionLayer = new OGRXPlaneAirwayIntersectionLayer();
  54. poDataSource->RegisterLayer(poAirwaySegmentLayer);
  55. poDataSource->RegisterLayer(poAirwayIntersectionLayer);
  56. }
  57. /************************************************************************/
  58. /* CloneForLayer() */
  59. /************************************************************************/
  60. OGRXPlaneReader* OGRXPlaneAwyReader::CloneForLayer(OGRXPlaneLayer* poLayer)
  61. {
  62. OGRXPlaneAwyReader* poReader = new OGRXPlaneAwyReader();
  63. poReader->poInterestLayer = poLayer;
  64. SET_IF_INTEREST_LAYER(poAirwaySegmentLayer);
  65. SET_IF_INTEREST_LAYER(poAirwayIntersectionLayer);
  66. if (pszFilename)
  67. {
  68. poReader->pszFilename = CPLStrdup(pszFilename);
  69. poReader->fp = VSIFOpenL( pszFilename, "rt" );
  70. }
  71. return poReader;
  72. }
  73. /************************************************************************/
  74. /* IsRecognizedVersion() */
  75. /************************************************************************/
  76. int OGRXPlaneAwyReader::IsRecognizedVersion( const char* pszVersionString)
  77. {
  78. return EQUALN(pszVersionString, "640 Version", 11);
  79. }
  80. /************************************************************************/
  81. /* Read() */
  82. /************************************************************************/
  83. void OGRXPlaneAwyReader::Read()
  84. {
  85. const char* pszLine;
  86. while((pszLine = CPLReadLineL(fp)) != NULL)
  87. {
  88. papszTokens = CSLTokenizeString(pszLine);
  89. nTokens = CSLCount(papszTokens);
  90. nLineNumber ++;
  91. if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
  92. {
  93. CSLDestroy(papszTokens);
  94. papszTokens = NULL;
  95. bEOF = TRUE;
  96. return;
  97. }
  98. else if (nTokens == 0 || assertMinCol(10) == FALSE)
  99. {
  100. CSLDestroy(papszTokens);
  101. papszTokens = NULL;
  102. continue;
  103. }
  104. ParseRecord();
  105. CSLDestroy(papszTokens);
  106. papszTokens = NULL;
  107. if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
  108. return;
  109. }
  110. papszTokens = NULL;
  111. bEOF = TRUE;
  112. }
  113. /************************************************************************/
  114. /* ParseRecord() */
  115. /************************************************************************/
  116. void OGRXPlaneAwyReader::ParseRecord()
  117. {
  118. const char* pszFirstPointName;
  119. const char* pszSecondPointName;
  120. const char* pszAirwaySegmentName;
  121. double dfLat1, dfLon1;
  122. double dfLat2, dfLon2;
  123. int bIsHigh;
  124. int nBaseFL, nTopFL;
  125. pszFirstPointName = papszTokens[0];
  126. RET_IF_FAIL(readLatLon(&dfLat1, &dfLon1, 1));
  127. pszSecondPointName = papszTokens[3];
  128. RET_IF_FAIL(readLatLon(&dfLat2, &dfLon2, 4));
  129. bIsHigh = atoi(papszTokens[6]) == 2;
  130. nBaseFL = atoi(papszTokens[7]);
  131. nTopFL = atoi(papszTokens[8]);
  132. pszAirwaySegmentName = papszTokens[9];
  133. if (poAirwayIntersectionLayer)
  134. {
  135. poAirwayIntersectionLayer->AddFeature(pszFirstPointName, dfLat1, dfLon1);
  136. poAirwayIntersectionLayer->AddFeature(pszSecondPointName, dfLat2, dfLon2);
  137. }
  138. if (poAirwaySegmentLayer)
  139. {
  140. /*
  141. poAirwaySegmentLayer->AddFeature(pszAirwaySegmentName,
  142. pszFirstPointName,
  143. pszSecondPointName,
  144. dfLat1, dfLon1, dfLat2, dfLon2,
  145. bIsHigh, nBaseFL, nTopFL);
  146. */
  147. if (strchr(pszAirwaySegmentName, '-'))
  148. {
  149. char** papszSegmentNames = CSLTokenizeString2( pszAirwaySegmentName, "-", CSLT_HONOURSTRINGS );
  150. int i = 0;
  151. while(papszSegmentNames[i])
  152. {
  153. poAirwaySegmentLayer->AddFeature(papszSegmentNames[i],
  154. pszFirstPointName,
  155. pszSecondPointName,
  156. dfLat1, dfLon1, dfLat2, dfLon2,
  157. bIsHigh, nBaseFL, nTopFL);
  158. i++;
  159. }
  160. CSLDestroy(papszSegmentNames);
  161. }
  162. else
  163. {
  164. poAirwaySegmentLayer->AddFeature(pszAirwaySegmentName,
  165. pszFirstPointName,
  166. pszSecondPointName,
  167. dfLat1, dfLon1, dfLat2, dfLon2,
  168. bIsHigh, nBaseFL, nTopFL);
  169. }
  170. }
  171. }
  172. /************************************************************************/
  173. /* OGRXPlaneAirwaySegmentLayer() */
  174. /************************************************************************/
  175. OGRXPlaneAirwaySegmentLayer::OGRXPlaneAirwaySegmentLayer() : OGRXPlaneLayer("AirwaySegment")
  176. {
  177. poFeatureDefn->SetGeomType( wkbLineString );
  178. OGRFieldDefn oFieldSegmentName("segment_name", OFTString );
  179. poFeatureDefn->AddFieldDefn( &oFieldSegmentName );
  180. OGRFieldDefn oFieldPoint1Name("point1_name", OFTString );
  181. poFeatureDefn->AddFieldDefn( &oFieldPoint1Name );
  182. OGRFieldDefn oFieldPoint2Name("point2_name", OFTString );
  183. poFeatureDefn->AddFieldDefn( &oFieldPoint2Name );
  184. OGRFieldDefn oFieldIsHigh("is_high", OFTInteger );
  185. oFieldIsHigh.SetWidth( 1 );
  186. poFeatureDefn->AddFieldDefn( &oFieldIsHigh );
  187. OGRFieldDefn oFieldBase("base_FL", OFTInteger );
  188. oFieldBase.SetWidth( 3 );
  189. poFeatureDefn->AddFieldDefn( &oFieldBase );
  190. OGRFieldDefn oFieldTop("top_FL", OFTInteger );
  191. oFieldTop.SetWidth( 3 );
  192. poFeatureDefn->AddFieldDefn( &oFieldTop );
  193. }
  194. /************************************************************************/
  195. /* AddFeature() */
  196. /************************************************************************/
  197. OGRFeature*
  198. OGRXPlaneAirwaySegmentLayer::AddFeature(const char* pszAirwaySegmentName,
  199. const char* pszFirstPointName,
  200. const char* pszSecondPointName,
  201. double dfLat1,
  202. double dfLon1,
  203. double dfLat2,
  204. double dfLon2,
  205. int bIsHigh,
  206. int nBaseFL,
  207. int nTopFL)
  208. {
  209. int nCount = 0;
  210. OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
  211. if (fabs(dfLon1 - dfLon2) < 270)
  212. {
  213. OGRLineString* lineString = new OGRLineString();
  214. lineString->addPoint(dfLon1, dfLat1);
  215. lineString->addPoint(dfLon2, dfLat2);
  216. poFeature->SetGeometryDirectly( lineString );
  217. }
  218. else
  219. {
  220. /* Crossing antemeridian */
  221. OGRMultiLineString* multiLineString = new OGRMultiLineString();
  222. OGRLineString* lineString1 = new OGRLineString();
  223. OGRLineString* lineString2 = new OGRLineString();
  224. double dfLatInt;
  225. lineString1->addPoint(dfLon1, dfLat1);
  226. if (dfLon1 < dfLon2)
  227. {
  228. dfLatInt = dfLat1 + (dfLat2 - dfLat1) * (-180 - dfLon1) / ((dfLon2 - 360) - dfLon1);
  229. lineString1->addPoint(-180, dfLatInt);
  230. lineString2->addPoint(180, dfLatInt);
  231. }
  232. else
  233. {
  234. dfLatInt = dfLat1 + (dfLat2 - dfLat1) * (180 - dfLon1) / ((dfLon2 + 360) - dfLon1);
  235. lineString1->addPoint(180, dfLatInt);
  236. lineString2->addPoint(-180, dfLatInt);
  237. }
  238. lineString2->addPoint(dfLon2, dfLat2);
  239. multiLineString->addGeometryDirectly( lineString1 );
  240. multiLineString->addGeometryDirectly( lineString2 );
  241. poFeature->SetGeometryDirectly( multiLineString );
  242. }
  243. poFeature->SetField( nCount++, pszAirwaySegmentName );
  244. poFeature->SetField( nCount++, pszFirstPointName );
  245. poFeature->SetField( nCount++, pszSecondPointName );
  246. poFeature->SetField( nCount++, bIsHigh );
  247. poFeature->SetField( nCount++, nBaseFL );
  248. poFeature->SetField( nCount++, nTopFL );
  249. RegisterFeature(poFeature);
  250. return poFeature;
  251. }
  252. /************************************************************************/
  253. /* EqualAirwayIntersectionFeature */
  254. /************************************************************************/
  255. static int EqualAirwayIntersectionFeatureFunc(const void* _feature1, const void* _feature2)
  256. {
  257. OGRFeature* feature1 = (OGRFeature*)_feature1;
  258. OGRFeature* feature2 = (OGRFeature*)_feature2;
  259. if (strcmp(feature1->GetFieldAsString(0), feature2->GetFieldAsString(0)) == 0)
  260. {
  261. OGRPoint* point1 = (OGRPoint*) feature1->GetGeometryRef();
  262. OGRPoint* point2 = (OGRPoint*) feature2->GetGeometryRef();
  263. return (point1->getX() == point2->getX() && point1->getY() == point2->getY());
  264. }
  265. return FALSE;
  266. }
  267. /************************************************************************/
  268. /* OGRXPlaneAirwayHashDouble() */
  269. /************************************************************************/
  270. static unsigned long OGRXPlaneAirwayHashDouble(const double& dfVal)
  271. {
  272. /* To make a long story short, we must copy the double into */
  273. /* an array in order to respect C strict-aliasing rule */
  274. /* We can't directly cast into an unsigned int* */
  275. /* See #2521 for the longer version */
  276. unsigned int anValue[2];
  277. memcpy(anValue, &dfVal, sizeof(double));
  278. return anValue[0] ^ anValue[1];
  279. }
  280. /************************************************************************/
  281. /* HashAirwayIntersectionFeatureFunc */
  282. /************************************************************************/
  283. static unsigned long HashAirwayIntersectionFeatureFunc(const void* _feature)
  284. {
  285. OGRFeature* feature = (OGRFeature*)_feature;
  286. OGRPoint* point = (OGRPoint*) feature->GetGeometryRef();
  287. unsigned long hash = CPLHashSetHashStr((unsigned char*)feature->GetFieldAsString(0));
  288. const double x = point->getX();
  289. const double y = point->getY();
  290. return hash ^ OGRXPlaneAirwayHashDouble(x) ^ OGRXPlaneAirwayHashDouble(y);
  291. }
  292. /************************************************************************/
  293. /* FreeAirwayIntersectionFeatureFunc */
  294. /************************************************************************/
  295. static void FreeAirwayIntersectionFeatureFunc(void* _feature)
  296. {
  297. delete (OGRFeature*)_feature;
  298. }
  299. /************************************************************************/
  300. /* OGRXPlaneAirwayIntersectionLayer() */
  301. /************************************************************************/
  302. OGRXPlaneAirwayIntersectionLayer::OGRXPlaneAirwayIntersectionLayer() : OGRXPlaneLayer("AirwayIntersection")
  303. {
  304. poFeatureDefn->SetGeomType( wkbPoint );
  305. OGRFieldDefn oFieldName("name", OFTString );
  306. poFeatureDefn->AddFieldDefn( &oFieldName );
  307. poSet = CPLHashSetNew(HashAirwayIntersectionFeatureFunc,
  308. EqualAirwayIntersectionFeatureFunc,
  309. FreeAirwayIntersectionFeatureFunc);
  310. }
  311. /************************************************************************/
  312. /* ~OGRXPlaneAirwayIntersectionLayer() */
  313. /************************************************************************/
  314. OGRXPlaneAirwayIntersectionLayer::~OGRXPlaneAirwayIntersectionLayer()
  315. {
  316. CPLHashSetDestroy(poSet);
  317. }
  318. /************************************************************************/
  319. /* AddFeature() */
  320. /************************************************************************/
  321. OGRFeature*
  322. OGRXPlaneAirwayIntersectionLayer::AddFeature(const char* pszIntersectionName,
  323. double dfLat,
  324. double dfLon)
  325. {
  326. OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
  327. poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
  328. poFeature->SetField( 0, pszIntersectionName );
  329. if (CPLHashSetLookup(poSet, poFeature) == NULL)
  330. {
  331. CPLHashSetInsert(poSet, poFeature->Clone());
  332. RegisterFeature(poFeature);
  333. return poFeature;
  334. }
  335. else
  336. {
  337. delete poFeature;
  338. return NULL;
  339. }
  340. }
  341. /************************************************************************/
  342. /* ResetReading() */
  343. /************************************************************************/
  344. void OGRXPlaneAirwayIntersectionLayer::ResetReading()
  345. {
  346. if (poReader)
  347. {
  348. CPLHashSetDestroy(poSet);
  349. poSet = CPLHashSetNew(HashAirwayIntersectionFeatureFunc,
  350. EqualAirwayIntersectionFeatureFunc,
  351. FreeAirwayIntersectionFeatureFunc);
  352. }
  353. OGRXPlaneLayer::ResetReading();
  354. }