src/miscallenous.cpp

branch
projects
changeset 935
8d98ee0dc917
parent 931
85080f7a1c20
child 941
f895379d7fab
equal deleted inserted replaced
930:ab77deb851fa 935:8d98ee0dc917
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2015 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <math.h>
20 #include <locale.h>
21 #include <QColor>
22 #include "main.h"
23 #include "miscallenous.h"
24 #include "mainWindow.h"
25 #include "dialogs.h"
26 #include "ldDocument.h"
27 #include "ui_rotpoint.h"
28
29 // Prime number table.
30 static const int PrimeNumbers[] =
31 {
32 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
33 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
34 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
35 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
36 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
37 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
38 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
39 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
40 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
41 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
42 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
43 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
44 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
45 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
46 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
47 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
48 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
49 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
50 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
51 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
52 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
53 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
54 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
55 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
56 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
57 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
58 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
59 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
60 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
61 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
62 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
63 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
64 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
65 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
66 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
67 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
68 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
69 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
70 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
71 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
72 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
73 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
74 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
75 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
76 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
77 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
78 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
79 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
80 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
81 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
82 };
83
84 static const long E10[] =
85 {
86 1l,
87 10l,
88 100l,
89 1000l,
90 10000l,
91 100000l,
92 1000000l,
93 10000000l,
94 100000000l,
95 1000000000l,
96 };
97
98 // =============================================================================
99 //
100 // Grid stuff
101 //
102 CFGENTRY (Int, Grid, Grid::Medium)
103 CFGENTRY (Float, GridCoarseCoordinateSnap, 5.0f)
104 CFGENTRY (Float, GridCoarseAngleSnap, 45.0f)
105 CFGENTRY (Float, GridMediumCoordinateSnap, 1.0f)
106 CFGENTRY (Float, GridMediumAngleSnap, 22.5f)
107 CFGENTRY (Float, GridFineCoordinateSnap, 0.1f)
108 CFGENTRY (Float, GridFineAngleSnap, 7.5f)
109 CFGENTRY (Int, RotationPointType, 0)
110 CFGENTRY (Vertex, CustomRotationPoint, Origin)
111
112 const GridData Grids[3] =
113 {
114 { "Coarse", &cfg::GridCoarseCoordinateSnap, &cfg::GridCoarseAngleSnap },
115 { "Medium", &cfg::GridMediumCoordinateSnap, &cfg::GridMediumAngleSnap },
116 { "Fine", &cfg::GridFineCoordinateSnap, &cfg::GridFineAngleSnap },
117 };
118
119 // =============================================================================
120 //
121 // Snap the given coordinate value on the current grid's given axis.
122 //
123 double Grid::Snap (double value, const Grid::Config type)
124 {
125 double snapvalue = (type == Coordinate) ? *CurrentGrid().coordinateSnap : *CurrentGrid().angleSnap;
126 double mult = floor (Abs<double> (value / snapvalue));
127 double out = mult * snapvalue;
128
129 if (Abs (value) - (mult * snapvalue) > snapvalue / 2)
130 out += snapvalue;
131
132 if (value < 0)
133 out = -out;
134
135 return out;
136 }
137
138 // =============================================================================
139 //
140 void Simplify (int& numer, int& denom)
141 {
142 bool repeat;
143
144 do
145 {
146 repeat = false;
147
148 for (int x = 0; x < countof (PrimeNumbers); x++)
149 {
150 int const prime = PrimeNumbers[x];
151
152 if (numer < prime and denom < prime)
153 break;
154
155 if ((numer % prime == 0) and (denom % prime == 0))
156 {
157 numer /= prime;
158 denom /= prime;
159 repeat = true;
160 break;
161 }
162 }
163 } while (repeat);
164 }
165
166 // =============================================================================
167 //
168 Vertex GetRotationPoint (const LDObjectList& objs)
169 {
170 switch (RotationPoint (cfg::RotationPointType))
171 {
172 case RotationPoint::ObjectOrigin:
173 {
174 LDBoundingBox box;
175
176 // Calculate center vertex
177 for (LDObjectPtr obj : objs)
178 {
179 if (obj->hasMatrix())
180 box << obj.dynamicCast<LDMatrixObject>()->position();
181 else
182 box << obj;
183 }
184
185 return box.center();
186 }
187
188 case RotationPoint::WorldOrigin:
189 return Origin;
190
191 case RotationPoint::CustomPoint:
192 return cfg::CustomRotationPoint;
193
194 case RotationPoint::NumValues: break;
195 }
196
197 return Vertex();
198 }
199
200 // =============================================================================
201 //
202 void ConfigureRotationPoint()
203 {
204 QDialog* dlg = new QDialog;
205 Ui::RotPointUI ui;
206 ui.setupUi (dlg);
207
208 switch (RotationPoint (cfg::RotationPointType))
209 {
210 case RotationPoint::ObjectOrigin:
211 ui.objectPoint->setChecked (true);
212 break;
213
214 case RotationPoint::WorldOrigin:
215 ui.worldPoint->setChecked (true);
216 break;
217
218 case RotationPoint::CustomPoint:
219 ui.customPoint->setChecked (true);
220 break;
221
222 case RotationPoint::NumValues: break;
223 }
224
225 ui.customX->setValue (cfg::CustomRotationPoint.x());
226 ui.customY->setValue (cfg::CustomRotationPoint.y());
227 ui.customZ->setValue (cfg::CustomRotationPoint.z());
228
229 if (not dlg->exec())
230 return;
231
232 cfg::RotationPointType = int (
233 (ui.objectPoint->isChecked()) ? RotationPoint::ObjectOrigin :
234 (ui.worldPoint->isChecked()) ? RotationPoint::WorldOrigin :
235 RotationPoint::CustomPoint);
236
237 cfg::CustomRotationPoint.setX (ui.customX->value());
238 cfg::CustomRotationPoint.setY (ui.customY->value());
239 cfg::CustomRotationPoint.setZ (ui.customZ->value());
240 }
241
242 // =============================================================================
243 //
244 QString Join (QList<StringFormatArg> vals, QString delim)
245 {
246 QStringList list;
247
248 for (const StringFormatArg& arg : vals)
249 list << arg.text();
250
251 return list.join (delim);
252 }
253
254 // =============================================================================
255 //
256 void RoundToDecimals (double& a, int decimals)
257 {
258 assert (decimals >= 0 and decimals < countof (E10));
259 a = round (a * E10[decimals]) / E10[decimals];
260 }
261
262 // =============================================================================
263 //
264 void ApplyToMatrix (Matrix& a, ApplyToMatrixFunction func)
265 {
266 for (int i = 0; i < 9; ++i)
267 func (i, a[i]);
268 }
269
270 // =============================================================================
271 //
272 void ApplyToMatrix (const Matrix& a, ApplyToMatrixConstFunction func)
273 {
274 for (int i = 0; i < 9; ++i)
275 func (i, a[i]);
276 }
277
278 // =============================================================================
279 //
280 double GetCoordinateOf (const Vertex& a, Axis ax)
281 {
282 switch (ax)
283 {
284 case X: return a.x();
285 case Y: return a.y();
286 case Z: return a.z();
287 }
288
289 assert (false);
290 return 0.0;
291 }
292
293
294 // =============================================================================
295 //
296 QString MakePrettyFileSize (qint64 size)
297 {
298 if (size < 1024LL)
299 return QString::number (size) + " bytes";
300 else if (size < (1024LL * 1024LL))
301 return QString::number (double (size) / 1024LL, 'f', 1) + " Kb";
302 else if (size < (1024LL * 1024LL * 1024LL))
303 return QString::number (double (size) / (1024LL * 1024LL), 'f', 1) + " Mb";
304 else
305 return QString::number (double (size) / (1024LL * 1024LL * 1024LL), 'f', 1) + " Gb";
306 }

mercurial