File failed to load: https://isis.astrogeology.usgs.gov/6.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
ShapeModelFactory.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 
8 #include "ShapeModelFactory.h"
9 
10 #include <string>
11 
12 #include "BulletShapeModel.h"
13 #include "BulletTargetShape.h"
14 #include "Cube.h"
15 #include "DemShape.h"
16 #include "EllipsoidShape.h"
17 #include "EmbreeShapeModel.h"
18 #include "EmbreeTargetManager.h"
19 #include "EquatorialCylindricalShape.h"
20 #include "FileName.h"
21 #include "IException.h"
22 #include "IString.h"
23 #include "NaifDskShape.h"
24 #include "NaifStatus.h"
25 #include "PlaneShape.h"
26 #include "Projection.h"
27 #include "Preference.h"
28 #include "Pvl.h"
29 #include "PvlFlatMap.h"
30 #include "PvlGroup.h"
31 #include "PvlKeyword.h"
32 #include "Target.h"
33 
34 using namespace std;
35 
36 namespace Isis {
42  ShapeModelFactory::ShapeModelFactory() {
43  }
44 
45 
47  ShapeModelFactory::~ShapeModelFactory() {
48  }
49 
50 
63  ShapeModel *ShapeModelFactory::create(Target *target, Pvl &pvl) {
64 
65  // get kernels and instrument Pvl groups
66  PvlGroup &kernelsPvlGroup = pvl.findGroup("Kernels", Pvl::Traverse);
67 
68  // Get user preferences to determine preferred model
69  PvlFlatMap parameters(kernelsPvlGroup);
70  if ( Preference::Preferences().hasGroup("ShapeModel") ) {
71  parameters.merge(PvlFlatMap(Preference::Preferences().findGroup("ShapeModel")));
72  }
73 
74  // Do we need a sky shape model, member variable, or neither? For now treat sky as ellipsoid
75  bool skyTarget = target->isSky();
76 
77  // Determine if target is a plane??? target name has rings in it?
78  // Another keyword in label to indicate plane? What about lander/rovers?
79  // bool planeTarget = false;
80 
81  // shape model file name
82  QString shapeModelFilenames = "";
83 
84  // TODO: We differentiate between "Elevation" and "Shape" models on the
85  // labels, but we assign either one to the shapeModelFilename. Do we
86  // need a shapeModelFilename AND an elevationModelFilename?
87  // is this historical? Interchangeable?
88  if (skyTarget) {
89  // Sky targets are ellipsoid shapes
90  }
91  else if (kernelsPvlGroup.hasKeyword("ElevationModel") &&
92  !kernelsPvlGroup["ElevationModel"].isNull()) {
93  shapeModelFilenames = (QString) kernelsPvlGroup["ElevationModel"];
94  }
95  else if (kernelsPvlGroup.hasKeyword("ShapeModel") &&
96  !kernelsPvlGroup["ShapeModel"].isNull()) {
97  shapeModelFilenames = (QString) kernelsPvlGroup["ShapeModel"];
98  }
99 
100  // Create shape model
101  ShapeModel *shapeModel = NULL;
102 
103  // TODO: If there is no shape model filename, the shape model type defaults to an
104  // ellipsoid (should it?).
105 
106  // This exception will be thrown at the end of this method if no shape model is constructed.
107  // More specific exceptions will be appended before throwing this error.
108  IException finalError(IException::Programmer,
109  "Unable to create a shape model from given target and pvl.",
110  _FILEINFO_);
111 
112  if (shapeModelFilenames == "") {
113  // No file name given. If EllipsoidShape throws an error or returns null, the following
114  // exception will be appended to the finalError.
115  QString msg = "Unable to construct an Ellipsoid shape model.";
116 
117  try {
118  shapeModel = new EllipsoidShape(target);
119  }
120  catch (IException &e) {
121  // No file name given and ellipsoid fails. Append e to new exception
122  // with above message. Append this to finalError and throw.
123  finalError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
124  throw finalError;
125  }
126  // in case no error was thrown, but constructor returned NULL
127  finalError.append(IException(IException::Unknown, msg, _FILEINFO_));
128  }
129  else if (shapeModelFilenames == "RingPlane") {
130  // No file name given, RingPlane indicated. If PlaneShape throws an error or returns
131  // null, the following exception will be appended to the finalError.
132  QString msg = "Unable to construct a RingPlane shape model.";
133 
134  try {
135  shapeModel = new PlaneShape(target, pvl);
136  }
137  catch (IException &e) {
138  // No file name given, RingPlane specified. Append a message to the finalError and throw it.
139  finalError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
140  throw finalError;
141  }
142  // in case no error was thrown, but constructor returned NULL
143  finalError.append(IException(IException::Unknown, msg, _FILEINFO_));
144  }
145  else { // assume shape model given is a Bullet, Embree, NAIF DSK or DEM cube file name
146 
147  QString preferred = parameters.get("RayTraceEngine", "None").toLower();
148  QString onerror = parameters.get("OnError", "Continue").toLower();
149  double tolerance = toDouble(parameters.get("Tolerance", toString(DBL_MAX)));
150 
151  // A file error message will be appened to the finalError, if no shape model is constructed.
152  QString fileErrorMsg = "Invalid shape model file ["
153  + shapeModelFilenames + "] in Kernels group.";
154  IException fileError(IException::Io, fileErrorMsg, _FILEINFO_);
155 
156  //-------------- Check for bullet engine first -------------------------------//
157  if ( "bullet" == preferred ) {
158  // Check to see of ISIS cube DEMs get a pass
159  FileName v_shapefile(shapeModelFilenames);
160  QString ext = v_shapefile.extension().toLower();
161  // Cubes are not supported at this time.
162 
163  try {
164  BulletTargetShape *bullet = BulletTargetShape::load(shapeModelFilenames);
165  if ( 0 == bullet ) {
166 
167  // Bullet failed to load the kernel...test failure conditions
168  if ("cub" == ext) {
169  onerror = "fail"; // This is fatal no matter the condition
170  QString mess = "Bullet could not initialize ISIS Cube DEM";
171  throw IException(IException::Unknown, mess, _FILEINFO_);
172  }
173 
174  // Always throw an error in this case
175  QString b_msg = "Bullet could not initialize DEM!";
176  throw IException(IException::Unknown, b_msg, _FILEINFO_);
177  }
178  else {
179 
180  // Allocate the real shape model
181  BulletShapeModel *b_model = new BulletShapeModel(bullet, target, pvl);
182  b_model->setTolerance(tolerance);
183 
184  // Do this here, otherwise default behavior will ensue from here on out
185  kernelsPvlGroup.addKeyword(PvlKeyword("RayTraceEngine", preferred), PvlContainer::Replace);
186  kernelsPvlGroup.addKeyword(PvlKeyword("OnError", onerror), PvlContainer::Replace);
187  kernelsPvlGroup.addKeyword(PvlKeyword("Tolerance", toString(tolerance)),
188  PvlContainer::Replace);
189 
190  return ( b_model );
191  }
192  } catch (IException &ie) {
193  fileError.append(ie);
194  QString mess = "Unable to create preferred BulletShapeModel";
195  fileError.append(IException(IException::Unknown, mess, _FILEINFO_));
196  if ("fail" == onerror) throw fileError;
197  }
198 
199  // Don't have ShapeModel yet - invoke pre-exising behavior (2017-03-23)
200  }
201 
202  //-------------- Check for Embree engine -------------------------------//
203  if ( "embree" == preferred ) {
204 
205  // Check to see of ISIS cube DEMs get a pass
206  FileName v_shapefile(shapeModelFilenames);
207  QString ext = v_shapefile.extension().toLower();
208  // Cubes are not supported at this time
209 
210  try {
211 
212  // Allocate the shape model
213  EmbreeTargetManager *targetManager = EmbreeTargetManager::getInstance();
214  EmbreeShapeModel *embreeModel = new EmbreeShapeModel(target, shapeModelFilenames,
215  targetManager);
216  embreeModel->setTolerance(tolerance);
217 
218  // Do this here, otherwise default behavior will ensue from here on out
219  kernelsPvlGroup.addKeyword(PvlKeyword("RayTraceEngine", preferred), PvlContainer::Replace);
220  kernelsPvlGroup.addKeyword(PvlKeyword("OnError", onerror), PvlContainer::Replace);
221  kernelsPvlGroup.addKeyword(PvlKeyword("Tolerance", toString(tolerance)),
222  PvlContainer::Replace);
223 
224  return ( embreeModel );
225 
226  } catch (IException &ie) {
227  fileError.append(ie);
228  QString mess = "Unable to create preferred EmbreeShapeModel";
229  fileError.append(IException(IException::Unknown, mess, _FILEINFO_));
230  if ("fail" == onerror) throw fileError;
231  }
232  }
233 
234  //-------------- Is the shape model a NAIF DSK? ------------------------------//
235 
236  // If NaifDskShape throws an error or returns null and DEM construction is
237  // unsuccessful, the following exception will be appended to the fileError.
238  QString msg = "The given shape model file is not a valid NAIF DSK file. "
239  "Unable to construct a NAIF DSK shape model.";
240  IException dskError(IException::Unknown, msg, _FILEINFO_);
241 
242  try {
243  // try to create a NaifDskShape object
244  shapeModel = new NaifDskShape(target, pvl);
245  }
246  catch (IException &e) {
247  // append a message to the fileError, but don't throw it.
248  // We will make sure it's not a DEM before throwing the error.
249  dskError.append(e);
250  }
251 
252  if (shapeModel == NULL) {
253 
254  // in case no error was thrown, but constructor returned NULL
255  fileError.append(dskError);
256 
257  //-------------- Is the shape model an ISIS DEM? ------------------------------//
258  // TODO Deal with stacks -- this could be a list of DEMs
259  Isis::Cube* shapeModelCube = new Isis::Cube;
260  try {
261  // first, try to open the shape model file as an Isis cube
262  shapeModelCube->open(FileName(shapeModelFilenames).expanded(), "r" );
263  }
264  catch (IException &e) {
265  // The file is neither a valid DSK nor an ISIS cube. Append a message and throw the error.
266  QString msg = "The given shape model file is not a valid ISIS DEM. "
267  "Unable to open as an ISIS cube.";
268  fileError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
269  finalError.append(fileError);
270  throw finalError;
271  }
272 
273  Projection *projection = NULL;
274  try {
275  // get projection of shape model cube
276  projection = shapeModelCube->projection();
277  }
278  catch (IException &e) {
279  // The file is neither a valid DSK nor a valid ISIS DEM. Append message and throw the error.
280  QString msg = "The given shape model file is not a valid ISIS DEM cube. "
281  "It is not map-projected.";
282  fileError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
283  finalError.append(fileError);
284  throw finalError;
285  }
286 
287  if (projection->IsEquatorialCylindrical()) {
288  // If the EquatorialCylindricalShape constructor throws an error or returns null, the
289  // following exception will be appended to the fileError. (Later added to the finalError)
290  QString msg = "Unable to construct a DEM shape model from the given "
291  "EquatorialCylindrical projected ISIS cube.";
292 
293  try {
294  shapeModel = new EquatorialCylindricalShape(target, pvl);
295  }
296  catch (IException &e) {
297  // The file is an equatorial cylindrical ISIS cube. Append fileError and throw.
298  fileError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
299  finalError.append(fileError);
300  throw finalError;
301  }
302  // in case no error was thrown, but constructor returned NULL
303  fileError.append(IException(IException::Unknown, msg, _FILEINFO_));
304  }
305  else {
306  // If the DemShape constructor throws an error or returns null, the following
307  // exception will be appended to the fileError. (Later added to the finalError)
308  QString msg = "Unable to construct a DEM shape model "
309  "from the given projected ISIS cube file.";
310 
311  try {
312  shapeModel = new DemShape(target, pvl);
313  }
314  catch (IException &e) {
315  // The file is projected ISIS cube (assumed to be DEM). Append fileError and throw.
316  fileError.append(IException(e, IException::Unknown, msg, _FILEINFO_));
317  finalError.append(fileError);
318  throw finalError;
319  }
320  // in case no error was thrown, but constructor returned NULL
321  fileError.append(IException(IException::Unknown, msg, _FILEINFO_));
322  }
323 
324  delete shapeModelCube;
325 
326  }
327 
328  // in case no error was thrown, but DSK, Equatorial, or DEM constructor returned NULL
329  finalError.append(fileError);
330  }
331 
332  // TODO Add Naif DSK shape and stack?
333 
334  if (shapeModel == NULL) {
335  throw finalError;
336  }
337 
338  return shapeModel;
339  }
340 } // end namespace isis
Isis::PvlObject::findGroup
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:129
Isis::NaifDskShape
Provides support for NAIF's Digital Shape Kernel (DSK)
Definition: NaifDskShape.h:42
Isis::PvlKeyword
A single keyword-value pair.
Definition: PvlKeyword.h:82
Isis::Target::isSky
bool isSky() const
Return if our target is the sky.
Definition: Target.cpp:190
Isis::PvlFlatMap
Provides a flat map of PvlKeywords.
Definition: PvlFlatMap.h:218
Isis::PvlContainer::addKeyword
void addKeyword(const PvlKeyword &keyword, const InsertMode mode=Append)
Add a keyword to the container.
Definition: PvlContainer.cpp:202
Isis::FileName
File name manipulation and expansion.
Definition: FileName.h:100
Isis::EmbreeShapeModel
General purpose Embree ray tracing model.
Definition: EmbreeShapeModel.h:37
Isis::PvlContainer::hasKeyword
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
Definition: PvlContainer.cpp:159
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::EllipsoidShape
Define shapes and provide utilities for ISIS targets.
Definition: EllipsoidShape.h:46
Isis::IException::append
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
Definition: IException.cpp:409
Isis::BulletShapeModel::setTolerance
void setTolerance(const double &tolerance)
Sets the occlusion tolerance.
Definition: BulletShapeModel.cpp:177
Isis::PvlFlatMap::merge
int merge(const PvlFlatMap &other)
Adds the keywords from another PvlFlatMap.
Definition: PvlFlatMap.cpp:680
Isis::Projection::IsEquatorialCylindrical
virtual bool IsEquatorialCylindrical()
This method returns true if the projection is equatorial cylindrical.
Definition: Projection.cpp:222
Isis::EmbreeTargetManager
Class for managing the construction and destruction of EmbreeTargetShapes.
Definition: EmbreeTargetManager.h:37
Isis::PvlGroup
Contains multiple PvlContainers.
Definition: PvlGroup.h:41
Isis::EquatorialCylindricalShape
Define shapes and provide utilities for shapes stored as ISIS EquatorialCylindrical map.
Definition: EquatorialCylindricalShape.h:39
Isis::PvlFlatMap::get
QString get(const QString &key, const int &index=0) const
Gets the value of a keyword in the PvlFlatMap.
Definition: PvlFlatMap.cpp:576
Isis::Cube
IO Handler for Isis Cubes.
Definition: Cube.h:167
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::DemShape
Define shapes and provide utilities for targets stored as ISIS maps.
Definition: DemShape.h:52
Isis::FileName::extension
QString extension() const
Returns the last extension of the file name.
Definition: FileName.cpp:178
Isis::toDouble
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:149
std
Namespace for the standard library.
Isis::ShapeModel
Define shapes and provide utilities for Isis targets.
Definition: ShapeModel.h:62
Isis::BulletTargetShape
Bullet Target Shape for planetary bodies.
Definition: BulletTargetShape.h:33
Isis::EmbreeShapeModel::setTolerance
void setTolerance(const double &tolerance)
Set the tolerance used when checking if the stored surface point is visible.
Definition: EmbreeShapeModel.cpp:745
Isis::BulletShapeModel
Shape model that uses the Bullet library to perform ray tracing.
Definition: BulletShapeModel.h:35
Isis::Projection
Base class for Map Projections.
Definition: Projection.h:155
Isis::Cube::open
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:627
Isis::Target
This class is used to create and store valid Isis targets.
Definition: Target.h:63
Isis::Cube::projection
Projection * projection()
Definition: Cube.cpp:1794
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::PlaneShape
Define plane shape model.
Definition: PlaneShape.h:44

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the USGS Astrogeology Discussion Board
To report a bug, or suggest a feature go to: ISIS Github
File Modified: 07/13/2023 15:17:17