E57Header.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #ifndef CC_E57_HEADER_HEADER
  2. #define CC_E57_HEADER_HEADER
  3. #include <cstdint>
  4. //! Point prototype (structure use to interrogate if standardized fields are available)
  5. /** Taken from "E57 Simple API" by Stan Coleby
  6. **/
  7. class PointStandardizedFieldsAvailable
  8. {
  9. public:
  10. bool cartesianXField = false; //!< Indicates that the PointRecord cartesianX field is active
  11. bool cartesianYField = false; //!< Indicates that the PointRecord cartesianY field is active
  12. bool cartesianZField = false; //!< Indicates that the PointRecord cartesianZ field is active
  13. bool cartesianInvalidStateField = false; //!< Indicates that the PointRecord cartesianInvalidState field is active
  14. bool sphericalRangeField = false; //!< Indicates that the PointRecord sphericalRange field is active
  15. bool sphericalAzimuthField = false; //!< Indicates that the PointRecord sphericalAzimuth field is active
  16. bool sphericalElevationField = false; //!< Indicates that the PointRecord sphericalElevation field is active
  17. bool sphericalInvalidStateField = false; //!< Indicates that the PointRecord sphericalInvalidState field is active
  18. double pointRangeMinimum = 0.0; //!< Indicates that the PointRecord cartesian and range fields should be configured with this minimum value -E57_FLOAT_MAX or -E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a minimum range value.
  19. double pointRangeMaximum = 0.0; //!< Indicates that the PointRecord cartesian and range fields should be configured with this maximum value E57_FLOAT_MAX or E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a maximum range value.
  20. double pointRangeScaledInteger = 0.0; //!< Indicates that the PointRecord cartesain and range fields should be configured as a ScaledIntegerNode with this scale setting. If 0. then use FloatNode.
  21. bool normXField = false; //!< Indicates that the PointRecord normalX field is active
  22. bool normYField = false; //!< Indicates that the PointRecord normalY field is active
  23. bool normZField = false; //!< Indicates that the PointRecord normalZ field is active
  24. double normRangeMinimum = 0.0; //!< Indicates that the PointRecord normal and range fields should be configured with this minimum value -E57_FLOAT_MAX or -E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a minimum range value.
  25. double normRangeMaximum = 0.0; //!< Indicates that the PointRecord normal and range fields should be configured with this maximum value E57_FLOAT_MAX or E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a maximum range value.
  26. double normRangeScaledInteger = 0.0; //!< Indicates that the PointRecord normal and range fields should be configured as a ScaledIntegerNode with this scale setting. If 0. then use FloatNode.
  27. double angleMinimum = 0.0; //!< Indicates that the PointRecord angle fields should be configured with this minimum value -E57_FLOAT_MAX or -E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a minimum angle value.
  28. double angleMaximum = 0.0; //!< Indicates that the PointRecord angle fields should be configured with this maximum value E57_FLOAT_MAX or E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a maximum angle value.
  29. double angleScaledInteger = 0.0; //!< Indicates that the PointRecord angle fields should be configured as a ScaledIntegerNode with this scale setting. If 0. then use FloatNode.
  30. bool rowIndexField = false; //!< Indicates that the PointRecord rowIndex field is active
  31. uint32_t rowIndexMaximum = 0; //!< Indicates that the PointRecord index fields should be configured with this maximum value where the minimum will be set to 0.
  32. bool columnIndexField = false; //!< Indicates that the PointRecord columnIndex field is active
  33. uint32_t columnIndexMaximum = 0; //!< Indicates that the PointRecord index fields should be configured with this maximum value where the minimum will be set to 0.
  34. bool returnIndexField = false; //!< Indicates that the PointRecord returnIndex field is active
  35. bool returnCountField = false; //!< Indicates that the PointRecord returnCount field is active
  36. uint8_t returnMaximum = 0.0; //!< Indicates that the PointRecord return fields should be configured with this maximum value where the minimum will be set to 0.
  37. bool timeStampField = false; //!< Indicates that the PointRecord timeStamp field is active
  38. bool isTimeStampInvalidField = false; //!< Indicates that the PointRecord isTimeStampInvalid field is active
  39. double timeMaximum = 0.0; //!< Indicates that the PointRecord timeStamp fields should be configured with this maximum value. like E57_UINT32_MAX, E57_FLOAT_MAX or E57_DOUBLE_MAX
  40. bool intensityField = false; //!< Indicates that the PointRecord intensity field is active
  41. bool isIntensityInvalidField = false; //!< Indicates that the PointRecord isIntensityInvalid field is active
  42. double intensityScaledInteger = 0.0; //!< Indicates that the PointRecord intensity fields should be configured as a ScaledIntegerNode with this setting. If 0. then use FloatNode, if -1. use IntegerNode
  43. bool colorRedField = false; //!< indicates that the PointRecord colorRed field is active
  44. bool colorGreenField = false; //!< indicates that the PointRecord colorGreen field is active
  45. bool colorBlueField = false; //!< indicates that the PointRecord colorBlue field is active
  46. bool isColorInvalidField = false; //!< Indicates that the PointRecord isColorInvalid field is active
  47. };
  48. //! Specifies the limits for the value of signal intensity that a sensor is capable of producing
  49. /** From "E57 Simple API" by Stan Coleby
  50. **/
  51. class IntensityLimits
  52. {
  53. public:
  54. double intensityMinimum = 0.0; //!< The minimum producible intensity value. Unit is unspecified.
  55. double intensityMaximum = 0.0; //!< The maximum producible intensity value. Unit is unspecified.
  56. };
  57. //! Secifies the limits for the value of red, green, and blue color that a sensor is capable of producing.
  58. /** From "E57 Simple API" by Stan Coleby
  59. **/
  60. class ColorLimits
  61. {
  62. public:
  63. double colorRedMinimum = 0.0; //!< The minimum producible red color value. Unit is unspecified.
  64. double colorRedMaximum = 0.0; //!< The maximum producible red color value. Unit is unspecified.
  65. double colorGreenMinimum = 0.0; //!< The minimum producible green color value. Unit is unspecified.
  66. double colorGreenMaximum = 0.0; //!< The maximum producible green color value. Unit is unspecified.
  67. double colorBlueMinimum = 0.0; //!< The minimum producible blue color value. Unit is unspecified.
  68. double colorBlueMaximum = 0.0; //!< The maximum producible blue color value. Unit is unspecified.
  69. };
  70. //! E57 scan useful header information (minimal set for CloudCompare only ;)
  71. struct E57ScanHeader
  72. {
  73. IntensityLimits intensityLimits; //!< The limits for the value of signal intensity that the sensor is capable of producing.
  74. ColorLimits colorLimits; //!< The limits for the value of red, green, and blue color that the sensor is capable of producing.
  75. PointStandardizedFieldsAvailable pointFields; //!< This defines the active fields used in the WritePoints function.
  76. };
  77. struct E57NodeDesc
  78. {
  79. QString type;
  80. QString content;
  81. };
  82. struct E57NodeMap : QMap<QString, E57NodeDesc>
  83. {
  84. QStringList toStringList() const
  85. {
  86. QStringList stringList;
  87. for (auto it = begin(); it != end(); ++it)
  88. {
  89. stringList << it.key() + "=" + it.value().type + "=" + it.value().content;
  90. }
  91. return stringList;
  92. }
  93. static void FromStringList(E57NodeMap& stringMap, const QStringList& stringList)
  94. {
  95. stringMap.clear();
  96. for (const QString& string : stringList)
  97. {
  98. QStringList tokens = string.split("=", Qt::KeepEmptyParts);
  99. if (tokens.size() == 3)
  100. {
  101. stringMap.insert(tokens[0], { tokens[1], tokens[2] });
  102. }
  103. else
  104. {
  105. ccLog::Warning("[E57NodeMap] Unexpected string: " + string);
  106. }
  107. }
  108. }
  109. };
  110. //! Identifies the representation for the image data
  111. /** From "E57 Simple API" by Stan Coleby
  112. **/
  113. enum Image2DProjection
  114. {
  115. E57_NO_PROJECTION = 0, //!< No representation for the image data is present
  116. E57_VISUAL = 1, //!< VisualReferenceRepresentation for the image data
  117. E57_PINHOLE = 2, //!< PinholeRepresentation for the image data
  118. E57_SPHERICAL = 3, //!< SphericalRepresentation for the image data
  119. E57_CYLINDRICAL = 4 //!< CylindricalRepresentation for the image data
  120. };
  121. //! Identifies the format representation for the image data
  122. /** From "E57 Simple API" by Stan Coleby
  123. **/
  124. enum Image2DType
  125. {
  126. E57_NO_IMAGE = 0, //!< No image data
  127. E57_JPEG_IMAGE = 1, //!< JPEG format image data.
  128. E57_PNG_IMAGE = 2, //!< PNG format image data.
  129. E57_PNG_IMAGE_MASK = 3 //!< PNG format image mask.
  130. };
  131. //! Interface for E57 camera representation
  132. class CameraRepresentation
  133. {
  134. public:
  135. virtual ~CameraRepresentation() = default;
  136. virtual Image2DProjection getType() { return E57_NO_PROJECTION; }
  137. virtual const char* getName() const { return {}; }
  138. virtual QStringList toStringList() const { return {}; }
  139. virtual bool fromStringList(const QStringList& stringList) { return true; }
  140. };
  141. //! Structure that stores an image that is to be used only as a visual reference.
  142. /** From "E57 Simple API" by Stan Coleby
  143. **/
  144. class VisualReferenceRepresentation : public CameraRepresentation
  145. {
  146. public:
  147. Image2DProjection getType() override { return E57_VISUAL; }
  148. static const char* GetName() { return "visualReferenceRepresentation"; }
  149. const char* getName() const override { return GetName(); }
  150. Image2DType imageType = E57_NO_IMAGE; //!< image type.
  151. int64_t imageSize = 0; //!< size of image data in BlobNode.
  152. int64_t imageMaskSize = 0; //!< size of image mask data in BlobNode (if any).
  153. int32_t imageWidth = 0; //!< image width (in pixels). Shall be positive
  154. int32_t imageHeight = 0; //!< image height (in pixels). Shall be positive
  155. QStringList toStringList() const override
  156. {
  157. QStringList stringList;
  158. stringList << "type=" + QString(getName());
  159. stringList << "imageWidth=" + QString::number(imageWidth);
  160. stringList << "imageHeight=" + QString::number(imageHeight);
  161. return stringList;
  162. }
  163. static bool InitDoubleFromStringList(const QString& key, const QStringList& stringList, double& destValue)
  164. {
  165. for (const QString& string : stringList)
  166. {
  167. if (string.startsWith(key))
  168. {
  169. QString valueStr = string.mid(key.length() + 1); // +1 to account for the '=' character
  170. bool ok = false;
  171. destValue = valueStr.toDouble(&ok);
  172. return ok;
  173. }
  174. }
  175. return false;
  176. }
  177. static bool InitInt32FromStringList(const QString& key, const QStringList& stringList, int32_t& destValue)
  178. {
  179. for (const QString& string : stringList)
  180. {
  181. if (string.startsWith(key))
  182. {
  183. QString valueStr = string.mid(key.length() + 1); // +1 to account for the '=' character
  184. bool ok = false;
  185. destValue = valueStr.toInt(&ok);
  186. return ok;
  187. }
  188. }
  189. return false;
  190. }
  191. bool fromStringList(const QStringList& stringList) override
  192. {
  193. // mandatory fields
  194. return ( InitInt32FromStringList("imageWidth", stringList, imageWidth)
  195. && InitInt32FromStringList("imageHeight", stringList, imageHeight) );
  196. }
  197. };
  198. //! Structure that stores an image that is mapped from 3D using a spherical projection model
  199. /** From "E57 Simple API" by Stan Coleby
  200. **/
  201. class SphericalRepresentation : public VisualReferenceRepresentation
  202. {
  203. public:
  204. Image2DProjection getType() override { return E57_SPHERICAL; }
  205. static const char* GetName() { return "sphericalRepresentation"; }
  206. const char* getName() const override { return GetName(); }
  207. QStringList toStringList() const override
  208. {
  209. QStringList stringList = VisualReferenceRepresentation::toStringList();
  210. stringList << "pixelWidth=" + QString::number(pixelWidth, 'f', 12);
  211. stringList << "pixelHeight=" + QString::number(pixelHeight, 'f', 12);
  212. return stringList;
  213. }
  214. bool fromStringList(const QStringList& stringList) override
  215. {
  216. if (!VisualReferenceRepresentation::fromStringList(stringList))
  217. {
  218. return false;
  219. }
  220. // mandatory fields
  221. return ( InitDoubleFromStringList("pixelWidth", stringList, pixelWidth)
  222. && InitDoubleFromStringList("pixelHeight", stringList, pixelHeight) );
  223. }
  224. double pixelWidth = 0; //!< The width of a pixel in the image (in radians). Shall be positive
  225. double pixelHeight = 0; //!< The height of a pixel in the image (in radians). Shall be positive.
  226. };
  227. //! Structure that stores an image that is mapped from 3D using the pinhole camera projection model.
  228. /** From "E57 Simple API" by Stan Coleby
  229. **/
  230. class PinholeRepresentation : public SphericalRepresentation
  231. {
  232. public:
  233. Image2DProjection getType() override { return E57_PINHOLE; }
  234. static const char* GetName() { return "pinholeRepresentation"; }
  235. const char* getName() const override { return GetName(); }
  236. QStringList toStringList() const override
  237. {
  238. QStringList stringList = SphericalRepresentation::toStringList();
  239. stringList << "focalLength=" + QString::number(focalLength, 'f', 12);
  240. stringList << "principalPointX=" + QString::number(principalPointX, 'f', 12);
  241. stringList << "principalPointY=" + QString::number(principalPointY, 'f', 12);
  242. return stringList;
  243. }
  244. bool fromStringList(const QStringList& stringList) override
  245. {
  246. if (!SphericalRepresentation::fromStringList(stringList))
  247. {
  248. return false;
  249. }
  250. // mandatory fields
  251. return ( InitDoubleFromStringList("focalLength", stringList, focalLength)
  252. && InitDoubleFromStringList("principalPointX", stringList, principalPointX)
  253. && InitDoubleFromStringList("principalPointY", stringList, principalPointY) );
  254. }
  255. double focalLength = 0; //!< The camera's focal length (in meters). Shall be positive
  256. double principalPointX = 0; //!< The X coordinate in the image of the principal point, (in pixels). The principal point is the intersection of the z axis of the camera coordinate frame with the image plane.
  257. double principalPointY = 0; //!< The Y coordinate in the image of the principal point (in pixels).
  258. };
  259. //!Structure that stores an image that is mapped from 3D using a cylindrical projection model.
  260. /** From "E57 Simple API" by Stan Coleby
  261. **/
  262. class CylindricalRepresentation : public SphericalRepresentation
  263. {
  264. public:
  265. Image2DProjection getType() override { return E57_CYLINDRICAL; }
  266. static const char* GetName() { return "cylindricalRepresentation"; }
  267. const char* getName() const override { return GetName(); }
  268. QStringList toStringList() const override
  269. {
  270. QStringList stringList = SphericalRepresentation::toStringList();
  271. stringList << "radius=" + QString::number(radius, 'f', 12);
  272. stringList << "principalPointY=" + QString::number(principalPointY, 'f', 12);
  273. return stringList;
  274. }
  275. bool fromStringList(const QStringList& stringList) override
  276. {
  277. if (!SphericalRepresentation::fromStringList(stringList))
  278. {
  279. return false;
  280. }
  281. // mandatory fields
  282. return ( InitDoubleFromStringList("radius", stringList, radius)
  283. && InitDoubleFromStringList("principalPointY", stringList, principalPointY) );
  284. }
  285. double radius = 0; //!< The closest distance from the cylindrical image surface to the center of projection (that is, the radius of the cylinder) (in meters). Shall be non-negative
  286. double principalPointY = 0; //!< The Y coordinate in the image of the principal point (in pixels). This is the intersection of the z = 0 plane with the image
  287. };
  288. #endif