PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/spatialreference_test.cpp

https://github.com/libLAS/libLAS-1.6
C++ | 323 lines | 215 code | 78 blank | 30 comment | 0 complexity | 5d5865ff731707ad7ae3a23dd27b56e3 MD5 | raw file
  1. // $Id: lasspatialreference_test.cpp 1102 2009-03-16 14:57:12Z hobu $
  2. //
  3. // (C) Copyright Mateusz Loskot 2008, mateusz@loskot.net
  4. // Distributed under the BSD License
  5. // (See accompanying file LICENSE.txt or copy at
  6. // http://www.opensource.org/licenses/bsd-license.php)
  7. //
  8. #include <liblas/liblas.hpp>
  9. #include <tut/tut.hpp>
  10. #include <string>
  11. #include <stdexcept>
  12. #include "common.hpp"
  13. #include "liblas_test.hpp"
  14. namespace tut
  15. {
  16. struct lasspatialreference_data
  17. {
  18. liblas::SpatialReference m_default;
  19. std::string utm17_filename;
  20. std::string utm15_filename;
  21. lasspatialreference_data()
  22. : utm17_filename(g_test_data_path + "//srs.las")
  23. , utm15_filename(g_test_data_path + "//1.2_3.las")
  24. {}
  25. };
  26. typedef test_group<lasspatialreference_data> tg;
  27. typedef tg::object to;
  28. tg test_group_lasspatialreference("liblas::SpatialReference");
  29. // Test default constructor
  30. template<>
  31. template<>
  32. void to::test<1>()
  33. {
  34. ensure_equals(m_default.GetProj4(), "");
  35. ensure_equals(m_default.GetWKT(), "");
  36. }
  37. #ifdef HAVE_GDAL
  38. // Test fetching SRS from an existing file
  39. template<>
  40. template<>
  41. void to::test<2>()
  42. {
  43. std::ifstream ifs;
  44. ifs.open(utm17_filename.c_str(), std::ios::in | std::ios::binary);
  45. liblas::Reader reader(ifs);
  46. liblas::Header const& header = reader.GetHeader();
  47. liblas::SpatialReference const& ref = header.GetSRS();
  48. const char* wkt_c = "PROJCS[\"WGS 84 / UTM zone 17N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-81],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"32617\"]]";
  49. ensure_equals("WKT comparison", ref.GetWKT(), wkt_c );
  50. const char* proj4_c = "+proj=utm +zone=17 +datum=WGS84 +units=m +no_defs ";
  51. ensure_equals("Proj.4 comparison", ref.GetProj4(), proj4_c);
  52. }
  53. // Test round-tripping proj.4 string
  54. template<>
  55. template<>
  56. void to::test<3>()
  57. {
  58. liblas::SpatialReference ref;
  59. const char* proj4_c = "+proj=utm +zone=15 +datum=WGS84 +units=m +no_defs ";
  60. ref.SetProj4(proj4_c);
  61. ensure_equals("Proj.4 comparison", ref.GetProj4(), proj4_c);
  62. }
  63. // Test setting EPSG:4326 from User string
  64. template<>
  65. template<>
  66. void to::test<4>()
  67. {
  68. liblas::SpatialReference ref;
  69. const char* code = "EPSG:4326";
  70. const char* proj4_c = "+proj=longlat +datum=WGS84 +no_defs ";
  71. const char* wkt_c = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
  72. ref.SetFromUserInput(code);
  73. ensure_equals("Proj.4 comparison", ref.GetProj4(), proj4_c);
  74. ensure_equals("WKT comparison", ref.GetWKT(), wkt_c );
  75. }
  76. // Test reprojecting UTM 15 to DD with a filter
  77. template<>
  78. template<>
  79. void to::test<5>()
  80. {
  81. std::ifstream ifs;
  82. ifs.open(utm15_filename.c_str(), std::ios::in | std::ios::binary);
  83. liblas::Reader reader(ifs);
  84. liblas::Header const& header = reader.GetHeader();
  85. liblas::SpatialReference const& in_ref = header.GetSRS();
  86. const char* utm15_wkt = "PROJCS[\"NAD83 / UTM zone 15N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.2572221010002,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-93],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"26915\"]]";
  87. ensure_equals("Input WKT comparison", in_ref.GetWKT(), utm15_wkt);
  88. const char* epsg4326_wkt = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]";
  89. liblas::SpatialReference out_ref;
  90. out_ref.SetWKT(epsg4326_wkt);
  91. ensure_equals("Output WKT comparison", out_ref.GetWKT(), epsg4326_wkt);
  92. liblas::HeaderPtr out_hdr = liblas::HeaderPtr(new liblas::Header(header));
  93. out_hdr->SetScale(0.00000001, 0.00000001, 0.01);
  94. out_hdr->SetOffset(0,0,0);
  95. liblas::TransformPtr srs_transform = liblas::TransformPtr(new liblas::ReprojectionTransform(in_ref, out_ref, out_hdr));
  96. std::vector<liblas::TransformPtr> transforms;
  97. transforms.push_back(srs_transform);
  98. reader.ReadPointAt(0);
  99. liblas::Point unprojected_point = reader.GetPoint();
  100. ensure_distance("unprojected_point.GetX()",
  101. unprojected_point.GetX(),
  102. double(470692.44),
  103. 0.01);
  104. ensure_distance("unprojected_point.GetY()",
  105. unprojected_point.GetY(),
  106. double(4602888.90),
  107. 0.01);
  108. reader.SetTransforms(transforms);
  109. // This should throw an out of range exception because the given scale/offset
  110. // combination is not sufficient to store the data.
  111. try
  112. {
  113. reader.ReadPointAt(0);
  114. ensure("std::domain_error was not thrown", false);
  115. }
  116. catch (std::domain_error const& e)
  117. {
  118. ensure(e.what(), true);
  119. }
  120. out_hdr->SetScale(0.0000001, 0.0000001, 0.01);
  121. out_hdr->SetOffset(0,0,0);
  122. srs_transform = liblas::TransformPtr(new liblas::ReprojectionTransform(in_ref, out_ref, out_hdr));
  123. transforms.clear();
  124. transforms.push_back(srs_transform);
  125. reader.SetTransforms(transforms);
  126. reader.Reset();
  127. reader.ReadPointAt(0);
  128. liblas::Point const& projected_point = reader.GetPoint();
  129. ensure_distance("projected_point.GetX()",
  130. projected_point.GetX(),
  131. double(-93.35156259),
  132. 0.0000001);
  133. ensure_distance("projected_point.GetY()",
  134. projected_point.GetY(),
  135. double(41.57714839),
  136. 0.000001);
  137. }
  138. // Test VLR sizes from setting SRS
  139. template<>
  140. template<>
  141. void to::test<6>()
  142. {
  143. liblas::SpatialReference ref;
  144. const char* code = "EPSG:4326";
  145. ref.SetFromUserInput(code);
  146. std::vector<liblas::VariableRecord> const& vlrs = ref.GetVLRs();
  147. ensure_equals("VLR count", vlrs.size(), boost::uint32_t(4));
  148. ensure_equals("First record size", vlrs[0].GetRecordLength(), boost::uint32_t(64));
  149. }
  150. // Test incorporation of vertical datum information into WKT string and
  151. // into GeoTIFF VLRs.
  152. template<>
  153. template<>
  154. void to::test<7>()
  155. {
  156. liblas::SpatialReference ref;
  157. const char* wkt_c = "COMPD_CS[\"WGS 84 + VERT_CS\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],VERT_CS[\"NAVD88 height\",VERT_DATUM[\"North American Vertical Datum 1988\",2005,AUTHORITY[\"EPSG\",\"5103\"],EXTENSION[\"PROJ4_GRIDS\",\"g2003conus.gtx\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Up\",UP],AUTHORITY[\"EPSG\",\"5703\"]]]";
  158. const char* exp_gtiff = "Geotiff_Information:\n Version: 1\n Key_Revision: 1.0\n Tagged_Information:\n End_Of_Tags.\n Keyed_Information:\n GTRasterTypeGeoKey (Short,1): RasterPixelIsArea\n GTModelTypeGeoKey (Short,1): ModelTypeGeographic\n GeogAngularUnitsGeoKey (Short,1): Angular_Degree\n GeogCitationGeoKey (Ascii,7): \"WGS 84\"\n GeographicTypeGeoKey (Short,1): GCS_WGS_84\n GeogInvFlatteningGeoKey (Double,1): 298.257223563 \n GeogSemiMajorAxisGeoKey (Double,1): 6378137 \n VerticalCitationGeoKey (Ascii,14): \"NAVD88 height\"\n VerticalCSTypeGeoKey (Short,1): Unknown-5703\n VerticalDatumGeoKey (Short,1): Unknown-5103\n VerticalUnitsGeoKey (Short,1): Linear_Meter\n End_Of_Keys.\n End_Of_Geotiff.\n";
  159. ref.SetFromUserInput(wkt_c);
  160. ensure_equals("WKT comparison", ref.GetWKT(liblas::SpatialReference::eCompoundOK), wkt_c );
  161. std::vector<liblas::VariableRecord> const& vlrs = ref.GetVLRs();
  162. ensure_equals("VLR count", vlrs.size(), boost::uint32_t(4));
  163. ensure_equals("First record size", vlrs[0].GetRecordLength(), boost::uint32_t(96));
  164. liblas::property_tree::ptree tree = ref.GetPTree();
  165. std::string gtiff = tree.get<std::string>("gtiff");
  166. ensure_equals("GeoTIFF Tags", gtiff, exp_gtiff );
  167. // Now try stripping away the WKT VLR and see that we get the GeoTIFF
  168. // derived version instead.
  169. ref.ClearVLRs( liblas::SpatialReference::eOGRWKT );
  170. wkt_c = "COMPD_CS[\"unknown\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]],VERT_CS[\"NAVD88 height\",VERT_DATUM[\"North American Vertical Datum 1988\",2005,AUTHORITY[\"EPSG\",\"5103\"],EXTENSION[\"PROJ4_GRIDS\",\"g2003conus.gtx,g2003alaska.gtx,g2003h01.gtx,g2003p01.gtx\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Up\",UP],AUTHORITY[\"EPSG\",\"5703\"]]]";
  171. ensure_equals("non OGR WKT comparison", ref.GetWKT(liblas::SpatialReference::eCompoundOK), wkt_c );
  172. }
  173. // Try writing a compound coordinate system to file and ensure we get back
  174. // WKT with the geoidgrids (from the WKT VLR).
  175. template<>
  176. template<>
  177. void to::test<8>()
  178. {
  179. std::string tmpfile_(g_test_data_path + "//tmp_srs.las");
  180. liblas::SpatialReference ref, result_ref;
  181. const char* wkt_c = "COMPD_CS[\"WGS 84 + VERT_CS\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],VERT_CS[\"NAVD88 height\",VERT_DATUM[\"North American Vertical Datum 1988\",2005,AUTHORITY[\"EPSG\",\"5103\"],EXTENSION[\"PROJ4_GRIDS\",\"g2003conus.gtx,g2003alaska.gtx,g2003h01.gtx,g2003p01.gtx\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Up\",UP],AUTHORITY[\"EPSG\",\"5703\"]]]";
  182. ref.SetFromUserInput( wkt_c );
  183. // Write a very simple file with our SRS and one point.
  184. {
  185. std::ofstream ofs;
  186. ofs.open(tmpfile_.c_str(), std::ios::out | std::ios::binary);
  187. liblas::Header header;
  188. header.SetSRS( ref );
  189. liblas::Writer writer(ofs, header);
  190. liblas::Point point;
  191. point.SetCoordinates( -117, 33, 100 );
  192. writer.WritePoint( point );
  193. }
  194. // Reopen and check contents.
  195. {
  196. std::ifstream ifs;
  197. ifs.open( tmpfile_.c_str(), std::ios::in | std::ios::binary );
  198. liblas::Reader reader(ifs);
  199. liblas::Header const& header = reader.GetHeader();
  200. result_ref = header.GetSRS();
  201. }
  202. ensure_equals("WKT comparison", ref.GetWKT(liblas::SpatialReference::eCompoundOK), wkt_c );
  203. // Cleanup
  204. std::remove(tmpfile_.c_str());
  205. }
  206. // Try writing only the WKT VLR to a file, and see if the resulting
  207. // file still works ok.
  208. template<>
  209. template<>
  210. void to::test<9>()
  211. {
  212. std::string tmpfile_(g_test_data_path + "//tmp_srs_9.las");
  213. liblas::SpatialReference ref, result_ref;
  214. ref.SetFromUserInput( "EPSG:4326" );
  215. ref.ClearVLRs( liblas::SpatialReference::eGeoTIFF );
  216. // Write a very simple file with our SRS and one point.
  217. {
  218. std::ofstream ofs;
  219. ofs.open(tmpfile_.c_str(), std::ios::out | std::ios::binary);
  220. liblas::Header header;
  221. header.SetSRS( ref );
  222. liblas::Writer writer(ofs, header);
  223. liblas::Point point;
  224. point.SetCoordinates( -117, 33, 100 );
  225. writer.WritePoint( point );
  226. }
  227. // Reopen and check contents.
  228. {
  229. std::ifstream ifs;
  230. ifs.open( tmpfile_.c_str(), std::ios::in | std::ios::binary );
  231. liblas::Reader reader(ifs);
  232. liblas::Header const& header = reader.GetHeader();
  233. result_ref = header.GetSRS();
  234. }
  235. std::vector<liblas::VariableRecord> const& vlrs = ref.GetVLRs();
  236. ensure_equals("VLR count", vlrs.size(), boost::uint32_t(1));
  237. liblas::property_tree::ptree tree = ref.GetPTree();
  238. std::string gtiff = tree.get<std::string>("gtiff");
  239. // there should be no geotiff definition.
  240. ensure_equals("GeoTIFF Tags", gtiff, "" );
  241. // Cleanup
  242. std::remove(tmpfile_.c_str());
  243. }
  244. #endif
  245. }