17 */ |
17 */ |
18 |
18 |
19 #include "miscallenous.h" |
19 #include "miscallenous.h" |
20 #include "linetypes/modelobject.h" |
20 #include "linetypes/modelobject.h" |
21 #include "lddocument.h" |
21 #include "lddocument.h" |
22 |
|
23 void Vertex::transform(const Matrix& matrix, const Vertex& pos) |
|
24 { |
|
25 double x2 = (matrix(0, 0) * x) + (matrix(0, 1) * y) + (matrix(0, 2) * z) + pos.x; |
|
26 double y2 = (matrix(1, 0) * x) + (matrix(1, 1) * y) + (matrix(1, 2) * z) + pos.y; |
|
27 double z2 = (matrix(2, 0) * x) + (matrix(2, 1) * y) + (matrix(2, 2) * z) + pos.z; |
|
28 this->x = x2; |
|
29 this->y = y2; |
|
30 this->z = z2; |
|
31 } |
|
32 |
|
33 void Vertex::apply(ApplyFunction func) |
|
34 { |
|
35 func(X, this->x); |
|
36 func(Y, this->y); |
|
37 func(Z, this->z); |
|
38 } |
|
39 |
|
40 void Vertex::apply(ApplyConstFunction func) const |
|
41 { |
|
42 func(X, this->x); |
|
43 func(Y, this->y); |
|
44 func(Z, this->z); |
|
45 } |
|
46 |
|
47 double& Vertex::operator[](Axis axis) |
|
48 { |
|
49 switch (axis) |
|
50 { |
|
51 case X: |
|
52 return this->x; |
|
53 |
|
54 case Y: |
|
55 return this->y; |
|
56 |
|
57 case Z: |
|
58 return this->z; |
|
59 |
|
60 default: |
|
61 return ::sink<double>(); |
|
62 } |
|
63 } |
|
64 |
|
65 double Vertex::operator[] (Axis axis) const |
|
66 { |
|
67 switch (axis) |
|
68 { |
|
69 case X: |
|
70 return this->x; |
|
71 |
|
72 case Y: |
|
73 return this->y; |
|
74 |
|
75 case Z: |
|
76 return this->z; |
|
77 |
|
78 default: |
|
79 return 0.0; |
|
80 } |
|
81 } |
|
82 |
|
83 void Vertex::setCoordinate (Axis axis, qreal value) |
|
84 { |
|
85 (*this)[axis] = value; |
|
86 } |
|
87 |
|
88 QString Vertex::toString (bool mangled) const |
|
89 { |
|
90 if (mangled) |
|
91 return ::format("(%1, %2, %3)", this->x, this->y, this->z); |
|
92 else |
|
93 return ::format("%1 %2 %3", this->x, this->y, this->z); |
|
94 } |
|
95 |
|
96 Vertex Vertex::operator* (qreal scalar) const |
|
97 { |
|
98 return {this->x * scalar, this->y * scalar, this->z * scalar}; |
|
99 } |
|
100 |
|
101 Vertex& Vertex::operator+=(const QVector3D& other) |
|
102 { |
|
103 this->x += other.x(); |
|
104 this->y += other.y(); |
|
105 this->z += other.z(); |
|
106 return *this; |
|
107 } |
|
108 |
|
109 Vertex Vertex::operator+(const QVector3D& other) const |
|
110 { |
|
111 Vertex result (*this); |
|
112 result += other; |
|
113 return result; |
|
114 } |
|
115 |
|
116 QVector3D Vertex::toVector() const |
|
117 { |
|
118 return { |
|
119 static_cast<float>(this->x), |
|
120 static_cast<float>(this->y), |
|
121 static_cast<float>(this->z) |
|
122 }; |
|
123 } |
|
124 |
|
125 Vertex Vertex::operator- (const QVector3D& vector) const |
|
126 { |
|
127 Vertex result = *this; |
|
128 result -= vector; |
|
129 return result; |
|
130 } |
|
131 |
|
132 Vertex& Vertex::operator-= (const QVector3D& vector) |
|
133 { |
|
134 this->x -= vector.x(); |
|
135 this->y -= vector.y(); |
|
136 this->z -= vector.z(); |
|
137 return *this; |
|
138 } |
|
139 |
|
140 QVector3D Vertex::operator- (const Vertex& other) const |
|
141 { |
|
142 return { |
|
143 static_cast<float>(this->x - other.x), |
|
144 static_cast<float>(this->y - other.y), |
|
145 static_cast<float>(this->z - other.z) |
|
146 }; |
|
147 } |
|
148 |
|
149 Vertex& Vertex::operator*= (qreal scalar) |
|
150 { |
|
151 x *= scalar; |
|
152 y *= scalar; |
|
153 z *= scalar; |
|
154 return *this; |
|
155 } |
|
156 |
|
157 bool Vertex::operator==(const Vertex& other) const |
|
158 { |
|
159 return this->x == other.x and this->y == other.y and this->z == other.z; |
|
160 } |
|
161 |
|
162 bool Vertex::operator!=(const Vertex& other) const |
|
163 { |
|
164 return not (*this == other); |
|
165 } |
|
166 |
|
167 bool Vertex::operator< (const Vertex& other) const |
|
168 { |
|
169 if (not qFuzzyCompare(this->x, other.x)) |
|
170 return this->x < other.x; |
|
171 else if (not qFuzzyCompare(this->y, other.y)) |
|
172 return this->y < other.y; |
|
173 else |
|
174 return this->z < other.z; |
|
175 } |
|
176 |
|
177 /* |
|
178 * Transforms this vertex with a tranformation matrix and returns the result. |
|
179 */ |
|
180 Vertex Vertex::transformed(const GLRotationMatrix& matrix) const |
|
181 { |
|
182 return { |
|
183 matrix(0, 0) * this->x |
|
184 + matrix(0, 1) * this->y |
|
185 + matrix(0, 2) * this->z, |
|
186 matrix(1, 0) * this->x |
|
187 + matrix(1, 1) * this->y |
|
188 + matrix(1, 2) * this->z, |
|
189 matrix(2, 0) * this->x |
|
190 + matrix(2, 1) * this->y |
|
191 + matrix(2, 2) * this->z, |
|
192 }; |
|
193 } |
|
194 |
|
195 QDataStream& operator<<(QDataStream& out, const Vertex& vertex) |
|
196 { |
|
197 return out << vertex.x << vertex.y << vertex.z; |
|
198 } |
|
199 |
|
200 QDataStream& operator>>(QDataStream& in, Vertex& vertex) |
|
201 { |
|
202 return in >> vertex.x >> vertex.y >> vertex.z; |
|
203 } |
|
204 |
|
205 // ============================================================================= |
|
206 // |
|
207 BoundingBox::BoundingBox() |
|
208 { |
|
209 reset(); |
|
210 } |
|
211 |
|
212 // ============================================================================= |
|
213 // |
|
214 BoundingBox& BoundingBox::operator<< (const Vertex& v) |
|
215 { |
|
216 calcVertex (v); |
|
217 return *this; |
|
218 } |
|
219 |
|
220 // ============================================================================= |
|
221 // |
|
222 void BoundingBox::calcVertex (const Vertex& vertex) |
|
223 { |
|
224 m_vertex0.x = qMin(vertex.x, m_vertex0.x); |
|
225 m_vertex0.y = qMin(vertex.y, m_vertex0.y); |
|
226 m_vertex0.z = qMin(vertex.z, m_vertex0.z); |
|
227 m_vertex1.x = qMax(vertex.x, m_vertex1.x); |
|
228 m_vertex1.y = qMax(vertex.y, m_vertex1.y); |
|
229 m_vertex1.z = qMax(vertex.z, m_vertex1.z); |
|
230 m_isEmpty = false; |
|
231 } |
|
232 |
|
233 // ============================================================================= |
|
234 // |
|
235 // Clears the bounding box |
|
236 // |
|
237 void BoundingBox::reset() |
|
238 { |
|
239 m_vertex0 = {10000.0, 10000.0, 10000.0}; |
|
240 m_vertex1 = {-10000.0, -10000.0, -10000.0}; |
|
241 m_isEmpty = true; |
|
242 } |
|
243 |
|
244 // ============================================================================= |
|
245 // |
|
246 // Returns the length of the bounding box on the longest measure. |
|
247 // |
|
248 double BoundingBox::longestMeasurement() const |
|
249 { |
|
250 double xscale = m_vertex0.x - m_vertex1.x; |
|
251 double yscale = m_vertex0.y - m_vertex1.y; |
|
252 double zscale = m_vertex0.z - m_vertex1.z; |
|
253 double size = qMax(xscale, qMax(yscale, zscale)); |
|
254 return qMax(qAbs(size / 2.0), 1.0); |
|
255 } |
|
256 |
|
257 // ============================================================================= |
|
258 // |
|
259 // Yields the center of the bounding box. |
|
260 // |
|
261 Vertex BoundingBox::center() const |
|
262 { |
|
263 return { |
|
264 (m_vertex0.x + m_vertex1.x) / 2, |
|
265 (m_vertex0.y + m_vertex1.y) / 2, |
|
266 (m_vertex0.z + m_vertex1.z) / 2 |
|
267 }; |
|
268 } |
|
269 |
|
270 bool BoundingBox::isEmpty() const |
|
271 { |
|
272 return m_isEmpty; |
|
273 } |
|
274 |
|
275 const Vertex& BoundingBox::vertex0() const |
|
276 { |
|
277 return m_vertex0; |
|
278 } |
|
279 |
|
280 const Vertex& BoundingBox::vertex1() const |
|
281 { |
|
282 return m_vertex1; |
|
283 } |
|
284 |
22 |
285 // http://stackoverflow.com/a/18204188/3629665 |
23 // http://stackoverflow.com/a/18204188/3629665 |
286 template<typename T> |
24 template<typename T> |
287 inline int rotl10(T x) |
25 inline int rotl10(T x) |
288 { |
26 { |