PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/otbossim/src/ossim/projection/ossimAdjMapModel.cpp

https://github.com/paniwani/OTB
C++ | 417 lines | 261 code | 53 blank | 103 comment | 17 complexity | a37c82ea3bd2ec228a6ac1225ea2d6a4 MD5 | raw file
  1. //----------------------------------------------------------------------------
  2. // Copyright (c) 2005, Oscar Kramer, all rights reserved.
  3. //
  4. // License: LGPL
  5. //
  6. // See LICENSE.txt file in the top level directory for more details.
  7. //
  8. // Author: Oscar Kramer
  9. //
  10. // Description:
  11. //
  12. // Special "sensor model" that provides a conventional map projection but
  13. // with additional capability for adjusting the map x,y coordinates with
  14. // offset, scale, and rotation transform. Funtions to control notifications,
  15. // information and error output.
  16. //
  17. //----------------------------------------------------------------------------
  18. // $Id: ossimAdjMapModel.cpp 15766 2009-10-20 12:37:09Z gpotts $
  19. #include <cstdlib> /* for atof */
  20. #include <ossim/projection/ossimAdjMapModel.h>
  21. #include <ossim/projection/ossimMapProjection.h>
  22. #include <ossim/base/ossimKeywordNames.h>
  23. #include <ossim/projection/ossimMapProjectionFactory.h>
  24. #include <ossim/elevation/ossimElevManager.h>
  25. // Geometry File Keywords:
  26. static const char* PARAMETER_KEYWORDS[] = {"map_offset_x",
  27. "map_offset_y",
  28. "map_rotation",
  29. "map_scale_x",
  30. "map_scale_y"};
  31. static const char* MAP_PROJ_FILE_KW = "map_proj_filename";
  32. RTTI_DEF1(ossimAdjMapModel, "ossimAdjMapModel", ossimSensorModel);
  33. //----------------------------------------------------------------------------
  34. //! Constructs to uninitialized state (needed by factory).
  35. //----------------------------------------------------------------------------
  36. ossimAdjMapModel::ossimAdjMapModel()
  37. :
  38. ossimSensorModel(),
  39. theAdjParams(NUM_ADJ_PARAMS),
  40. theMapProjection(),
  41. theCosTheta(0.0),
  42. theSinTheta(0.0)
  43. {
  44. theImageSize = ossimIpt(0,0);
  45. initAdjustableParameters();
  46. theErrorStatus++;
  47. }
  48. //----------------------------------------------------------------------------
  49. //! Constructs with map projection and image rectangle size.
  50. //----------------------------------------------------------------------------
  51. ossimAdjMapModel::ossimAdjMapModel(ossimMapProjection* map_proj,
  52. const ossimIpt& image_size)
  53. :
  54. ossimSensorModel(),
  55. theAdjParams(NUM_ADJ_PARAMS),
  56. theMapProjection(map_proj),
  57. theCosTheta(0.0),
  58. theSinTheta(0.0)
  59. {
  60. initializeFromMap();
  61. theImageSize = image_size;
  62. initAdjustableParameters();
  63. }
  64. //----------------------------------------------------------------------------
  65. //! Copy constructor
  66. //----------------------------------------------------------------------------
  67. ossimAdjMapModel::ossimAdjMapModel(const ossimAdjMapModel& copy_this)
  68. :
  69. ossimSensorModel(copy_this),
  70. theAdjParams(NUM_ADJ_PARAMS),
  71. theMapProjection(copy_this.theMapProjection),
  72. theCosTheta(0.0),
  73. theSinTheta(0.0)
  74. {
  75. theAdjParams = copy_this.theAdjParams;
  76. }
  77. //----------------------------------------------------------------------------
  78. //! Constructs from Geom KWL
  79. //----------------------------------------------------------------------------
  80. ossimAdjMapModel::ossimAdjMapModel(const ossimKeywordlist& kwl,
  81. const char* prefix)
  82. :
  83. ossimSensorModel(kwl),
  84. theAdjParams(NUM_ADJ_PARAMS),
  85. theMapProjection(),
  86. theCosTheta(0.0),
  87. theSinTheta(0.0)
  88. {
  89. initAdjustableParameters();
  90. loadState(kwl, prefix);
  91. }
  92. //----------------------------------------------------------------------------
  93. //! Constructs from Geom KWL
  94. //----------------------------------------------------------------------------
  95. ossimAdjMapModel::ossimAdjMapModel(const ossimFilename& kwl_filename)
  96. :
  97. ossimSensorModel(),
  98. theAdjParams(NUM_ADJ_PARAMS),
  99. theMapProjection(),
  100. theCosTheta(0.0),
  101. theSinTheta(0.0)
  102. {
  103. initAdjustableParameters();
  104. ossimKeywordlist kwl (kwl_filename);
  105. loadState(kwl);
  106. }
  107. //----------------------------------------------------------------------------
  108. //! Initializes base class data members after map model established. Returns TRUE if all's well.
  109. //----------------------------------------------------------------------------
  110. bool ossimAdjMapModel::initializeFromMap()
  111. {
  112. if (!theMapProjection)
  113. {
  114. theErrorStatus++;
  115. return false;
  116. }
  117. theSensorID = "AdjMapModel";
  118. theGSD = theMapProjection->getMetersPerPixel();
  119. theMeanGSD = 0.5*(theGSD.x + theGSD.y);
  120. theRefGndPt = theMapProjection->origin();
  121. return true;
  122. }
  123. //----------------------------------------------------------------------------
  124. //! Destructor
  125. //----------------------------------------------------------------------------
  126. ossimAdjMapModel::~ossimAdjMapModel()
  127. {
  128. theAdjParams.CleanUp();
  129. }
  130. //----------------------------------------------------------------------------
  131. //! Initializes adjustable parameters to their default values.
  132. //! Overrides ossimAdjustableParameterInterface virtual method.
  133. //----------------------------------------------------------------------------
  134. void ossimAdjMapModel::initAdjustableParameters()
  135. {
  136. // Initialize this adjustment as the initial geometry "adjustment":
  137. removeAllAdjustments();
  138. newAdjustment(NUM_ADJ_PARAMS);
  139. setAdjustmentDescription("Initial Geometry");
  140. // Initialize each adjustable parameter for this initial:
  141. setAdjustableParameter (OFFSET_X, 0.0, 1.0);
  142. setParameterDescription(OFFSET_X, "map_offset_x");
  143. setParameterCenter (OFFSET_X, 0.0);
  144. setAdjustableParameter (OFFSET_Y, 0.0, 1.0);
  145. setParameterDescription(OFFSET_Y, "map_offset_y");
  146. setParameterCenter (OFFSET_Y, 0.0);
  147. setAdjustableParameter (ROTATION, 0.0, 1.0);
  148. setParameterDescription(ROTATION, "map_rotation");
  149. setParameterCenter (ROTATION, 0.0);
  150. setAdjustableParameter (SCALE_X, 0.0, 1.0);
  151. setParameterDescription(SCALE_X, "map_scale_x");
  152. setParameterCenter (SCALE_X, 1.0);
  153. setAdjustableParameter (SCALE_Y, 0.0, 1.0);
  154. setParameterDescription(SCALE_Y, "map_scale_y");
  155. setParameterCenter (SCALE_Y, 1.0);
  156. updateModel();
  157. }
  158. //----------------------------------------------------------------------------
  159. //! Following a change to the adjustable parameter set, this virtual is called
  160. //! to permit instances to compute derived quantities after parameter change.
  161. //----------------------------------------------------------------------------
  162. void ossimAdjMapModel::updateModel()
  163. {
  164. for (int i=0; i<NUM_ADJ_PARAMS; i++)
  165. theAdjParams[i] = computeParameterOffset(i);
  166. theCosTheta = ossim::cosd(theAdjParams[ROTATION]);
  167. theSinTheta = ossim::sind(theAdjParams[ROTATION]);
  168. }
  169. //----------------------------------------------------------------------------
  170. //! Overrides base class pure virtual.
  171. //----------------------------------------------------------------------------
  172. void ossimAdjMapModel::lineSampleHeightToWorld(const ossimDpt& image_point,
  173. const double& heightEllipsoid,
  174. ossimGpt& worldPoint) const
  175. {
  176. // Just call other transform method
  177. // Check for bad map projection pointer:
  178. if (!theMapProjection)
  179. {
  180. worldPoint = ossimGpt(ossim::nan(), ossim::nan(), ossim::nan());
  181. return;
  182. }
  183. // Adjust image point by transform:
  184. double x = theAdjParams[SCALE_X]*(image_point.x - theAdjParams[OFFSET_X]);
  185. double y = theAdjParams[SCALE_Y]*(image_point.y - theAdjParams[OFFSET_Y]);
  186. ossimDpt adjusted_point(x*theCosTheta + y*theSinTheta,
  187. y*theCosTheta - x*theSinTheta);
  188. // Obtain ground point given adjusted image point:
  189. theMapProjection->lineSampleHeightToWorld(adjusted_point,
  190. heightEllipsoid,
  191. worldPoint);
  192. worldPoint.height(heightEllipsoid);
  193. }
  194. //----------------------------------------------------------------------------
  195. //! Overrides base class virtual.
  196. //----------------------------------------------------------------------------
  197. void ossimAdjMapModel::lineSampleToWorld(const ossimDpt& image_point,
  198. ossimGpt& worldPoint) const
  199. {
  200. lineSampleHeightToWorld(image_point, 0.0, worldPoint);
  201. if (!worldPoint.hasNans())
  202. {
  203. // worldPoint.height(theElevation->getHeightAboveEllipsoid(worldPoint));
  204. }
  205. }
  206. //----------------------------------------------------------------------------
  207. //! Rigorous inverse transform implented, overrides base-class' iterative
  208. //! solution.
  209. //----------------------------------------------------------------------------
  210. void ossimAdjMapModel::worldToLineSample(const ossimGpt& world_point,
  211. ossimDpt& image_point) const
  212. {
  213. // Check for bad map projection pointer:
  214. if (!theMapProjection)
  215. {
  216. image_point = ossimDpt(ossim::nan(), ossim::nan());
  217. return;
  218. }
  219. // Obtain non-adjusted image point given ground point:
  220. ossimDpt p1;
  221. theMapProjection->worldToLineSample(world_point, p1);
  222. // Adjust image point by transform:
  223. ossimDpt p2 (p1.x*theCosTheta - p1.y*theSinTheta,
  224. p1.y*theCosTheta + p1.x*theSinTheta);
  225. image_point.x = p2.x/theAdjParams[SCALE_X] + theAdjParams[OFFSET_X];
  226. image_point.y = p2.y/theAdjParams[SCALE_Y] + theAdjParams[OFFSET_Y];
  227. }
  228. //----------------------------------------------------------------------------
  229. //! Fulfills ossimObject base-class pure virtuals. Saves geometry
  230. //! KWL files. Returns true if successful.
  231. //----------------------------------------------------------------------------
  232. bool ossimAdjMapModel::saveState(ossimKeywordlist& kwl, const char* prefix) const
  233. {
  234. kwl.add(prefix, ossimKeywordNames::TYPE_KW, "ossimAdjMapModel");
  235. // Hand off to base class for common stuff:
  236. ossimSensorModel::saveState(kwl, prefix);
  237. // Save off data members:
  238. for (int i=0; i<NUM_ADJ_PARAMS; i++)
  239. kwl.add(prefix, PARAMETER_KEYWORDS[i], theAdjParams[i]);
  240. // Save off map projection info:
  241. if (theMapProjection.valid())
  242. {
  243. theMapProjection->saveState(kwl, prefix);
  244. }
  245. return true;
  246. }
  247. //----------------------------------------------------------------------------
  248. //! Fulfills ossimObject base-class pure virtuals. Loads geometry
  249. //! KWL files. Returns true if successful.
  250. //----------------------------------------------------------------------------
  251. bool ossimAdjMapModel::loadState(const ossimKeywordlist& kwl, const char* prefix)
  252. {
  253. static const ossimString MODULE ("ossimAdjMapModel::loadState() -- ");
  254. bool success = true;
  255. const char* value_str;
  256. double value;
  257. ossimString error_msg (MODULE+"Error encountered reading keyword: ");
  258. try
  259. {
  260. // Verify correct model type:
  261. value_str = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
  262. if ((!value_str) || (strcmp(value_str, TYPE_NAME(this))))
  263. {
  264. throw (error_msg + ossimKeywordNames::TYPE_KW);
  265. }
  266. //---
  267. // Instantiate the map projection via the factory if one has not been
  268. // initialized yet:
  269. //---
  270. if (!theMapProjection)
  271. {
  272. // should find the map projection filename in the KWL:
  273. value_str = kwl.find(prefix, MAP_PROJ_FILE_KW);
  274. if (!value_str)
  275. {
  276. throw (error_msg + MAP_PROJ_FILE_KW);
  277. }
  278. theMapProjection = PTR_CAST(ossimMapProjection,
  279. ossimMapProjectionFactory::instance()->createProjection(ossimKeywordlist(value_str)));
  280. if (!theMapProjection)
  281. {
  282. throw "Error encountered instantiating map ";
  283. }
  284. }
  285. // Everything OK so far, just load in the adjustable parameters. This involves modifying the
  286. // center value of the bsae class adjustable parameter:
  287. for (int i=0; i<NUM_ADJ_PARAMS; i++)
  288. {
  289. value_str = kwl.find(prefix, PARAMETER_KEYWORDS[i]);
  290. if (!value_str)
  291. {
  292. throw (error_msg + PARAMETER_KEYWORDS[i]).chars();
  293. }
  294. value = atof(value_str);
  295. setParameterCenter(i, value);
  296. }
  297. }
  298. catch (const char* /*message*/)
  299. {
  300. theErrorStatus++;
  301. success = false;
  302. }
  303. //---
  304. // updateModel() reads the base class adjustable parameters and initializes
  305. // theAdjParams
  306. // with the unnormalized, biased (to the "center" set above) quantities
  307. // used in the projection:
  308. //---
  309. if (success)
  310. {
  311. initializeFromMap();
  312. updateModel();
  313. }
  314. return success;
  315. }
  316. //----------------------------------------------------------------------------
  317. //! Writes a template of geom keywords processed by loadState and saveState to
  318. //! output stream.
  319. //----------------------------------------------------------------------------
  320. void ossimAdjMapModel::writeGeomTemplate(ostream& os)
  321. {
  322. os <<
  323. "//*****************************************************************\n"
  324. "// Template for Adjustable Map Model keywordlist\n"
  325. "//*****************************************************************\n"
  326. << ossimKeywordNames::TYPE_KW << ": " << "ossimFcsiModel" << endl;
  327. ossimSensorModel::writeGeomTemplate(os);
  328. os << "//***\n"
  329. << "// Derived-class AdjMapModel Keywords:\n"
  330. << "//***\n"
  331. << PARAMETER_KEYWORDS[OFFSET_X] << ": <east offset meters>\n"
  332. << PARAMETER_KEYWORDS[OFFSET_Y] << ": <north offset meters>\n"
  333. << PARAMETER_KEYWORDS[ROTATION] << ": <degrees CW>\n"
  334. << PARAMETER_KEYWORDS[SCALE_X] << ": <ratio>\n"
  335. << PARAMETER_KEYWORDS[SCALE_Y] << ": <ratio>\n"
  336. << endl;
  337. return;
  338. }
  339. //----------------------------------------------------------------------------
  340. //! Extends base-class implementation. Dumps contents of object to ostream.
  341. //----------------------------------------------------------------------------
  342. std::ostream& ossimAdjMapModel::print(std::ostream& out) const
  343. {
  344. ossimSensorModel::print(out);
  345. for (int i=0; i<NUM_ADJ_PARAMS; i++)
  346. out << PARAMETER_KEYWORDS[i] << ": " << theAdjParams[i] << endl;
  347. out << endl;
  348. return out;
  349. }
  350. //----------------------------------------------------------------------------
  351. //! Fetches the GSD from the internal map projection.
  352. //----------------------------------------------------------------------------
  353. ossimDpt ossimAdjMapModel::getMetersPerPixel () const
  354. {
  355. if (theMapProjection.valid())
  356. {
  357. return theMapProjection->getMetersPerPixel();
  358. }
  359. return ossimDpt(0,0);
  360. }
  361. ossimObject* ossimAdjMapModel::dup() const
  362. {
  363. return new ossimAdjMapModel(*this);
  364. }