TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
2 / 5
40.0%
Branches:
0 / 4
0.0%
Functions:
1 / 2, 1 excl
50.0%

mesh/io/icq.h
Line Branch Exec Source
1 /// @file
2 /// @brief Gaskell's implicitly connected quadrilateral (ICQ) shape models: reading, writing and
3 /// triangulating them.
4 #pragma once
5
6 #include "terraingen/mesh/mesh.h"
7 #include "terraingen/util/radial_shape.h"
8
9 #include <cstddef>
10 #include <filesystem>
11 #include <vector>
12
13 namespace terraingen {
14
15 /// A shape model in Gaskell's implicitly connected quadrilateral (ICQ) format, in metres: the
16 /// vertices v(I, J, F) labelled as grid points on the six faces of a cube, I and J from 0 to Q and
17 /// F from 1 to 6, the faces centred on +z, -y, -x, +y, +x and -z. Vertices on the cube's edges and
18 /// corners are stored once per face, as in the files. Format: R. W. Gaskell, "The Implicitly
19 /// Connected Quadrilateral Format", NASA PDS Small Bodies Node,
20 /// https://sbnarchive.psi.edu/pds3/dawn/fc/DWNCSPC_4_01/DOCUMENT/ICQMODEL.ASC
21 struct IcqModel {
22 ✗ std::size_t q = 0; ///< Q, the vertex grid's intervals per face edge.
23 ✗ std::vector<Vec3d> vertices; ///< 6 (Q + 1)^2 vertices in file order: F, then J, then I.
24
25 /// The index in `vertices` of v(`i`, `j`, `face`), with `face` from 1 to 6.
26 77415 std::size_t Index(std::size_t i, std::size_t j, std::size_t face) const {
27 77415 return ((face - 1) * (q + 1) + j) * (q + 1) + i;
28 }
29
30
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ bool operator==(const IcqModel&) const = default;
31 };
32
33 /// Whether `path` ends in .icq, in any case.
34 bool IsIcqPath(const std::filesystem::path& path);
35
36 /// The unit direction of label (`i`, `j`, `face`) of a cube with `q` intervals per edge, at
37 /// equiangular coordinates, with the faces oriented as in Gaskell's models: on face 1 (+z) I runs
38 /// along +x and J along -y; on faces 2 to 5 (-y, -x, +y, +x) J runs along -z; on face 6 (-z) I runs
39 /// along +x and J along +y. Labels the format shares between faces get the same direction exactly.
40 /// @throws std::invalid_argument unless `q` > 0, `i` and `j` <= `q` and 1 <= `face` <= 6.
41 Vec3d IcqDirection(std::size_t q, std::size_t i, std::size_t j, std::size_t face);
42
43 /// Reads an ICQ file: Q on the first line, then 6 (Q + 1)^2 lines of x, y and z (extra columns,
44 /// such as albedo, are ignored).
45 /// @param metresPerUnit Metres per file unit; Gaskell's models are in kilometres.
46 /// @throws std::runtime_error if the file cannot be read, or holds a bad Q, too few vertices or a
47 /// value that is not a finite number.
48 IcqModel ReadIcq(const std::filesystem::path& path, double metresPerUnit = 1000.0);
49
50 /// Writes `model` as an ICQ file.
51 /// @param metresPerUnit Metres per file unit; Gaskell's models are in kilometres.
52 /// @throws std::invalid_argument for a Q of 0, a vertex count other than 6 (Q + 1)^2 or a vertex
53 /// that is not finite.
54 /// @throws std::runtime_error if the file cannot be written.
55 void WriteIcq(const std::filesystem::path& path, const IcqModel& model,
56 double metresPerUnit = 1000.0);
57
58 /// The model as 12 Q^2 triangles over its 6 Q^2 + 2 distinct vertices, as Gaskell converts it:
59 /// each shared edge and corner vertex taken from one face, each quadrilateral split along its
60 /// shorter diagonal, triangles wound outward.
61 /// @throws std::invalid_argument as `WriteIcq`.
62 TriangleMesh IcqToMesh(const IcqModel& model);
63
64 /// The model as a radial shape of the same Q: each vertex's distance from the origin when every
65 /// vertex lies along its label's `IcqDirection`, as in the ICQ files TerrainGen writes; otherwise,
66 /// as in Gaskell's models, whose vertices are relaxed off those directions, the model resampled
67 /// along rays from the origin (`ShapeModelFromMesh` of `IcqToMesh`).
68 /// @throws std::invalid_argument as `WriteIcq`.
69 /// @throws std::runtime_error as `ShapeModelFromMesh`.
70 RadialShape ToRadialShape(const IcqModel& model);
71
72 /// The shape as an ICQ model: each label at its direction times its radius.
73 IcqModel ToIcq(const RadialShape& shape);
74
75 } // namespace terraingen
76