-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathVectorVisual.cppm
More file actions
108 lines (88 loc) · 3.86 KB
/
Copy pathVectorVisual.cppm
File metadata and controls
108 lines (88 loc) · 3.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
module;
/*!
* \file Declares VectorVisual to visualize a vector.
*/
#include <cstdint>
#include <array>
export module mplot.vectorvisual;
import sm.vec;
import mplot.visualmodel;
import mplot.colourmap;
export namespace mplot
{
//! How should the visualized vector go? Does it start at the origin? If so, it goes 'from'
//! the origin; FromOrigin. Does it instead sit on top of the origin (OnOrigin)?
//! Alternatively, it could go 'to' the origin; ToOrigin.
enum class VectorGoes
{
FromOrigin,
ToOrigin,
OnOrigin
};
//! A class to visualize a single vector
template <typename Flt, std::int32_t ndim, std::int32_t glver = mplot::gl::version_4_1>
class VectorVisual : public VisualModel<glver>
{
static_assert (ndim > 0 && ndim <= 3, "1, 2 or 3 dimensions please.");
public:
VectorVisual(const sm::vec<float> _offset) { this->viewmatrix.translate (_offset); }
//! Do the computations to initialize the vertices that will represent the Quivers.
void initializeVertices()
{
sm::vec<float> start, end, origin = {0,0,0};
// Convert thevec into a 3D vec
sm::vec<float> threevec = {0,0,0};
if constexpr (ndim == 1) {
threevec[0] = static_cast<float>(thevec[0]);
} else if constexpr (ndim == 2) {
threevec[0] = static_cast<float>(thevec[0]);
threevec[1] = static_cast<float>(thevec[1]);
} else {
threevec = thevec.as_float();
}
// Shift threevec to sit on origin if necessary
if (this->vgoes == VectorGoes::FromOrigin) {
start = origin;
end = threevec * this->scale_factor;
} else if (this->vgoes == VectorGoes::ToOrigin) {
end = origin;
start = threevec * this->scale_factor;
} else { // OnOrigin
sm::vec<float> halfvec = threevec * this->scale_factor * 0.5f;
start = origin - halfvec;
end = origin + halfvec ;
}
sm::vec<float> colourvec = threevec;
colourvec.renormalize();
mplot::ColourMap<float> cm (mplot::ColourMapType::HSV);
std::array<float, 3> clr = cm.convert (colourvec[0], colourvec[1]);
if (fixed_colour == true) { clr = single_colour; }
// The right way to draw an arrow.
sm::vec<float> arrow_line = end - start;
float len = arrow_line.length();
sm::vec<float> cone_start = arrow_line.shorten (len * arrowhead_prop);
cone_start += start;
this->computeTube (start, cone_start, clr, clr, thickness * this->scale_factor, shapesides);
float conelen = (arrow_line - cone_start).length();
if (arrow_line.length() > conelen) {
this->computeCone (cone_start, end, 0.0f, clr, thickness * this->scale_factor * 2.0f, shapesides);
}
}
// The vector to vis
sm::vec<Flt, ndim> thevec;
//! An enumerated type to say whether we draw from, on or to the origin
VectorGoes vgoes = VectorGoes::OnOrigin;
// How many sides to an arrow/cone/sphere? Increase for smoother arrow
// objects. Decrease to ease the load on your CPU and GPU. 12 is a reasonable
// compromise. You can set this before calling finalize().
std::int32_t shapesides = 12;
// Arrow thickness for the vector
float thickness = 0.1f;
// What proportion of the arrow length should the arrowhead length be?
float arrowhead_prop = 0.25f;
// How much to lienarly scale the size of the vector
float scale_factor = 1.0f;
bool fixed_colour = false;
std::array<float, 3> single_colour = mplot::colour::black;
};
} // namespace mplot