Rev 2302 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
964 | jag | 1 | /* |
2 | * multi_curve.cc |
||
2302 | jag | 3 | * DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath |
1713 | jag | 4 | * DIN Is Noise is released under GNU Public License 2.0 |
1479 | jag | 5 | * For more information, please visit https://dinisnoise.org/ |
964 | jag | 6 | */ |
7 | |||
8 | |||
9 | #include "multi_curve.h" |
||
10 | #include "vector2d.h" |
||
11 | #include "container.h" |
||
12 | #include "random.h" |
||
13 | #include "log.h" |
||
14 | #include <iostream> |
||
15 | |||
16 | extern string user_data_dir; |
||
1695 | jag | 17 | static const char eol = '\n'; |
964 | jag | 18 | |
19 | multi_curve::multi_curve (const string& filename) { |
||
20 | load (filename); |
||
21 | } |
||
22 | |||
23 | multi_curve::multi_curve () { |
||
24 | clear (); |
||
25 | } |
||
26 | |||
27 | void multi_curve::clear (int all) { |
||
28 | |||
29 | if (all) { |
||
30 | name = "nameless"; |
||
31 | set_color (1, 1, 1); |
||
32 | } |
||
33 | |||
34 | vertices.clear (); |
||
35 | num_vertices = 0; |
||
36 | last_vertex = -1; |
||
37 | |||
38 | left_tangents.clear (); |
||
39 | right_tangents.clear (); |
||
40 | |||
41 | curv.clear (); |
||
42 | |||
43 | limit = 0.001f; |
||
44 | |||
45 | shapeform = 0; |
||
1943 | jag | 46 | |
964 | jag | 47 | } |
48 | |||
49 | // |
||
2189 | jag | 50 | // must call following 3 funcs together with add_vertex called first |
964 | jag | 51 | // to correctly add curve |
52 | // |
||
2208 | jag | 53 | void multi_curve::add_vertex (float x, float y, int p) { |
964 | jag | 54 | last_vertex = num_vertices++; |
2208 | jag | 55 | vertices.push_back (pointinfo<float> (x, y, p)); |
2195 | jag | 56 | if (num_vertices > 1) { |
57 | curv.push_back (curve()); |
||
58 | ncurvs = curv.size (); |
||
59 | } |
||
964 | jag | 60 | } |
61 | |||
2208 | jag | 62 | void multi_curve::add_left_tangent (float x, float y, int p) { |
63 | left_tangents.push_back (pointinfo<float> (x, y, p)); |
||
964 | jag | 64 | } |
65 | |||
2208 | jag | 66 | void multi_curve::add_right_tangent (float x, float y, int p) { |
67 | right_tangents.push_back (pointinfo<float> (x, y, p)); |
||
964 | jag | 68 | } |
69 | |||
70 | void multi_curve::get_vertex (int i, float& x, float& y) { |
||
2208 | jag | 71 | pointinfo<float>& v = vertices[i]; |
964 | jag | 72 | x = v.x; |
73 | y = v.y; |
||
74 | } |
||
75 | |||
2184 | jag | 76 | int multi_curve::set_vertex (int i, float x, float y) { |
2195 | jag | 77 | |
2184 | jag | 78 | pointinfo<float>& v = vertices[i]; |
2195 | jag | 79 | |
964 | jag | 80 | if ((v.x != x) || (v.y != y)) { |
2195 | jag | 81 | |
2208 | jag | 82 | pointinfo<float>& lt = left_tangents[i]; |
83 | if (lt.pin == 0) { |
||
84 | float dlx, dly; |
||
85 | dlx = lt.x - v.x; |
||
86 | dly = lt.y - v.y; |
||
87 | lt.x = x + dlx; lt.y = y + dly; |
||
88 | } |
||
89 | pointinfo<float>& rt = right_tangents[i]; |
||
90 | if (rt.pin == 0) { |
||
91 | float drx, dry; |
||
92 | drx = rt.x - v.x; dry = rt.y - v.y; |
||
93 | rt.x = x + drx; rt.y = y + dry; |
||
94 | } |
||
2195 | jag | 95 | |
964 | jag | 96 | v.x = x; |
97 | v.y = y; |
||
2195 | jag | 98 | |
2197 | jag | 99 | if (i < ncurvs) curv[i].eval = 1; |
100 | int i_1 = i - 1; if (i_1 > -1) curv[i_1].eval = 1; |
||
2195 | jag | 101 | |
964 | jag | 102 | return 1; |
2195 | jag | 103 | |
964 | jag | 104 | } else return 0; |
2208 | jag | 105 | |
964 | jag | 106 | } |
107 | |||
108 | int multi_curve::set_left_tangent (int i, float x, float y) { |
||
109 | point<float>& lt = left_tangents [i]; |
||
110 | if ((lt.x != x) || (lt.y != y)) { |
||
111 | lt.x = x; |
||
112 | lt.y = y; |
||
113 | int j = i - 1; |
||
2197 | jag | 114 | if (j > -1) curv[j].eval = 1; |
964 | jag | 115 | return 1; |
116 | } |
||
117 | return 0; |
||
118 | } |
||
119 | |||
120 | int multi_curve::set_right_tangent (int i, float x, float y) { |
||
121 | point<float>& rt = right_tangents[i]; |
||
122 | if ((rt.x != x) || (rt.y != y)) { |
||
123 | rt.x = x; |
||
124 | rt.y = y; |
||
2197 | jag | 125 | if (i < ncurvs) curv[i].eval = 1; |
964 | jag | 126 | return 1; |
127 | } |
||
128 | return 0; |
||
129 | } |
||
130 | |||
131 | void multi_curve::get_left_tangent (int i, float& x, float& y) { |
||
132 | point<float>& lt = left_tangents [i]; |
||
133 | x = lt.x; |
||
134 | y = lt.y; |
||
135 | } |
||
136 | |||
137 | void multi_curve::get_right_tangent (int i, float& x, float& y) { |
||
138 | point<float>& rt = right_tangents[i]; |
||
139 | x = rt.x; |
||
140 | y = rt.y; |
||
141 | } |
||
142 | |||
143 | int multi_curve::insert (float x, float y, float tx, float ty) { |
||
2311 | jag | 144 | |
145 | point<float>& vl = vertices[last_vertex]; |
||
146 | if (x > vl.x) { // append |
||
147 | add_vertex (x, y); |
||
148 | add_left_tangent (x, y); |
||
149 | add_right_tangent (x, y); |
||
150 | evaluate (); |
||
151 | return 1; |
||
152 | } |
||
153 | |||
154 | // insert |
||
155 | // |
||
156 | |||
157 | points_array::iterator \ |
||
158 | vter = ++vertices.begin (), \ |
||
159 | lter = ++left_tangents.begin (), \ |
||
160 | rter = ++right_tangents.begin (); |
||
161 | |||
964 | jag | 162 | vector<curve>::iterator cter = curv.begin (); |
2311 | jag | 163 | for (int i = 0, k = last_vertex; i < k; ++i, ++vter, ++lter, ++rter, ++cter) { |
964 | jag | 164 | point<float>& vi = vertices[i]; |
2311 | jag | 165 | point<float>& vj = vertices[i + 1]; |
166 | if ((x >= vi.x) && (x <= vj.x)) { |
||
1605 | jag | 167 | point<float> v (x, y); |
964 | jag | 168 | vertices.insert (vter, v); |
169 | last_vertex = num_vertices++; |
||
1605 | jag | 170 | left_tangents.insert (lter, v); |
171 | right_tangents.insert (rter, v); |
||
2197 | jag | 172 | (*cter).eval = 1; |
964 | jag | 173 | curv.insert (cter, curve()); |
2195 | jag | 174 | ++ncurvs; |
964 | jag | 175 | return 1; |
176 | } |
||
177 | } |
||
2311 | jag | 178 | |
964 | jag | 179 | return 0; |
180 | } |
||
181 | |||
182 | int multi_curve::remove (int i) { |
||
183 | // remove ith vertex and its tangents |
||
184 | if (num_vertices < 3) return 0; |
||
185 | erase_id (vertices, i); |
||
186 | erase_id (left_tangents, i); |
||
187 | erase_id (right_tangents, i); |
||
2195 | jag | 188 | if (i == ncurvs) { |
964 | jag | 189 | int j = i - 1; |
190 | erase_id (curv, j); |
||
191 | } else { |
||
192 | erase_id (curv, i); |
||
2197 | jag | 193 | if (--i > -1) curv[i].eval = 1; else curv[0].eval = 1; |
964 | jag | 194 | } |
195 | --num_vertices; |
||
2195 | jag | 196 | --ncurvs; |
964 | jag | 197 | last_vertex = num_vertices - 1; |
198 | return 1; |
||
199 | } |
||
200 | |||
201 | void multi_curve::set_limit (float d) { |
||
202 | limit = d; |
||
203 | require_eval (); |
||
204 | } |
||
205 | |||
206 | void multi_curve::require_eval () { |
||
2197 | jag | 207 | for (int i = 0; i < ncurvs; ++i) curv[i].eval = 1; |
964 | jag | 208 | } |
209 | |||
210 | void multi_curve::set_color () { |
||
211 | static const float base = 0.1f; |
||
212 | static rnd<float> rd (base, 1.0f - base); |
||
213 | r = rd (); g = rd (); b = rd (); |
||
214 | calc_tangent_color (); |
||
215 | } |
||
216 | |||
217 | void multi_curve::set_color (float rr, float gg, float bb) { |
||
218 | r = rr; |
||
219 | g = gg; |
||
220 | b = bb; |
||
221 | calc_tangent_color (); |
||
222 | } |
||
223 | |||
224 | void multi_curve::calc_tangent_color () { |
||
225 | static const float factor = 0.5; |
||
226 | rt = factor * r; |
||
227 | gt = factor * g; |
||
228 | bt = factor * b; |
||
229 | } |
||
230 | |||
231 | void multi_curve::evaluate () { |
||
232 | int nevals = 0; |
||
2195 | jag | 233 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 234 | curve& crv = curv[i]; |
2197 | jag | 235 | if (crv.eval) { |
964 | jag | 236 | int j = i + 1; |
237 | point<float>& v0 = vertices[i]; |
||
238 | point<float>& v1 = vertices[j]; |
||
239 | point<float>& rt0 = right_tangents[i]; |
||
240 | point<float>& lt1 = left_tangents[j]; |
||
241 | crv.vertex (0, v0.x, v0.y); |
||
242 | crv.vertex (1, v1.x, v1.y); |
||
243 | crv.tangent (0, rt0.x, rt0.y); |
||
244 | crv.tangent (1, lt1.x, lt1.y); |
||
245 | crv.set_limit (limit); |
||
2191 | jag | 246 | crv.evaluate (shapeform); |
964 | jag | 247 | ++nevals; |
248 | } |
||
249 | } |
||
250 | |||
251 | if (nevals) { |
||
252 | if (shapeform) { |
||
253 | float total_length = 0.0f; |
||
254 | float now_length = 0.0f; |
||
2195 | jag | 255 | for (int i = 0; i < ncurvs; ++i) total_length += curv[i].length; |
256 | for (int i = 0; i < ncurvs; ++i) curv[i].normalise_length (now_length, total_length); |
||
964 | jag | 257 | check_shapeform (); |
258 | } |
||
259 | } |
||
260 | } |
||
261 | |||
262 | void multi_curve::check_shapeform () { |
||
2195 | jag | 263 | for (int i = 0, j = 1, k = ncurvs - 1; i < k; ++i, ++j) { |
964 | jag | 264 | curve& crvi = curv[i]; |
265 | curve& crvj = curv[j]; |
||
266 | vector<crvpt>& dptsi = crvi.dpts; |
||
267 | vector<crvpt>& dptsj = crvj.dpts; |
||
268 | int last = dptsi.size () - 1; |
||
269 | crvpt& dl = dptsi[last]; |
||
270 | crvpt& d0 = dptsj[0]; |
||
271 | d0.x = dl.x; |
||
272 | d0.y = dl.y; |
||
273 | } |
||
274 | } |
||
275 | |||
276 | void multi_curve::calc_bbox (box<float>& b) { |
||
2195 | jag | 277 | if (ncurvs) { |
964 | jag | 278 | int num_points = curv[0].vpts.size (); |
279 | if (num_points) { |
||
280 | const vector<crvpt>& vpts = curv[0].vpts; |
||
281 | b.left = b.right = vpts[0].x; |
||
282 | b.bottom = b.top = vpts[0].y; |
||
2195 | jag | 283 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 284 | const vector <crvpt>& vpts = curv[i].vpts; |
285 | num_points = vpts.size (); |
||
286 | for (int j = 0; j < num_points; ++j) { |
||
287 | const crvpt& p = vpts[j]; |
||
288 | if (p.x < b.left) b.left = p.x; else if (p.x > b.right) b.right = p.x; |
||
289 | if (p.y < b.bottom) b.bottom = p.y; else if (p.y > b.top) b.top = p.y; |
||
290 | } |
||
291 | } |
||
292 | } |
||
293 | } |
||
294 | b.calc (); |
||
295 | } |
||
296 | |||
297 | |||
298 | void multi_curve::load (const string& filename) { |
||
299 | ifstream file ((user_data_dir + filename).c_str (), ios::in); |
||
300 | if (!file) { |
||
301 | dlog << "!!! failed to load curve from: " << filename << " !!!" << endl; |
||
302 | return; |
||
303 | } |
||
304 | load (file); |
||
305 | dlog << "+++ loaded curve from: " << filename << " +++" << endl; |
||
306 | } |
||
307 | |||
308 | void multi_curve::load (ifstream& file) { |
||
309 | |||
310 | clear (); |
||
311 | |||
312 | string ignore; |
||
313 | |||
314 | file >> ignore >> name; |
||
315 | |||
316 | int nvertices; |
||
317 | file >> ignore >> nvertices; |
||
318 | |||
319 | for (int i = 0; i < nvertices; ++i) { |
||
320 | |||
321 | float x, y; |
||
2208 | jag | 322 | int p; |
323 | file >> ignore >> x >> y >> p; |
||
324 | add_vertex (x, y, p); |
||
325 | file >> ignore >> x >> y >> p; |
||
326 | add_left_tangent (x, y, p); |
||
327 | file >> ignore >> x >> y >> p; |
||
328 | add_right_tangent (x, y, p); |
||
964 | jag | 329 | |
330 | } |
||
331 | |||
332 | file >> ignore >> limit; |
||
333 | |||
334 | float ir, ig, ib; file >> ignore >> ir >> ig >> ib; |
||
335 | set_color (ir, ig, ib); |
||
336 | |||
337 | file >> ignore >> shapeform; |
||
1947 | jag | 338 | setcentroid (shapeform); |
964 | jag | 339 | |
340 | point<float>& lt0 = left_tangents[0]; |
||
341 | point<float>& v0 = vertices[0]; |
||
342 | int last = nvertices - 1; |
||
343 | point<float>& rtl = right_tangents[last]; |
||
344 | point<float>& vl = vertices[last]; |
||
345 | lt0.x = v0.x; lt0.y = v0.y; |
||
346 | rtl.x = vl.x; rtl.y = vl.y; |
||
347 | |||
348 | evaluate (); |
||
349 | |||
350 | } |
||
351 | |||
352 | void multi_curve::save (const string& filename) { |
||
353 | ofstream file ((user_data_dir + filename).c_str (), ios::out); |
||
354 | if (!file) { |
||
355 | dlog << "!!! failed writing curve to: " << filename << endl; |
||
356 | return; |
||
357 | } |
||
358 | save (file); |
||
359 | dlog << "+++ saved curve into: " << filename << " +++" << endl; |
||
360 | } |
||
361 | |||
362 | void multi_curve::save (ofstream& file) { |
||
363 | string ignore; |
||
364 | if (name == "") name = "nameless"; |
||
365 | file << "name " << name << eol; |
||
366 | file << "num_vertices " << num_vertices << eol; |
||
367 | for (int i = 0; i < num_vertices; ++i) { |
||
2208 | jag | 368 | pointinfo<float>& v = vertices[i]; |
369 | pointinfo<float>& lt = left_tangents[i]; |
||
370 | pointinfo<float>& rt = right_tangents[i]; |
||
2211 | jag | 371 | file << "v" << i << spc << v.x << spc << v.y << spc << v.pin << eol; |
372 | file << "lt" << i << spc << lt.x << spc << lt.y << spc << lt.pin << eol; |
||
373 | file << "rt" << i << spc << rt.x << spc << rt.y << spc << rt.pin << eol; |
||
964 | jag | 374 | } |
375 | file << "limit " << limit << eol; |
||
376 | file << "color " << r << spc << g << spc << b << eol; |
||
377 | file << "shapeform " << shapeform << eol; |
||
378 | } |
||
379 | |||
380 | void create_polyline (multi_curve& crv, const points_array& pts) { |
||
381 | int npts = pts.size (); |
||
382 | if (npts < 2) return; |
||
383 | crv.clear (0); |
||
384 | for (int i = 0; i < npts; ++i) { |
||
385 | float xi = pts[i].x, yi = pts[i].y; |
||
386 | crv.add_vertex (xi, yi); |
||
387 | crv.add_left_tangent (xi, yi); |
||
388 | crv.add_right_tangent (xi, yi); |
||
389 | } |
||
390 | crv.evaluate (); |
||
391 | } |
||
392 | |||
393 | void convert2_polyline (multi_curve& crv) { |
||
394 | for (int i = 0, j = crv.num_vertices; i < j; ++i) { |
||
395 | point<float>& v = crv.vertices[i]; |
||
396 | crv.set_left_tangent (i, v.x, v.y); |
||
397 | crv.set_right_tangent (i, v.x, v.y); |
||
398 | } |
||
399 | crv.evaluate (); |
||
400 | } |
||
401 | |||
402 | void convert2_catmull_rom (multi_curve& crv, float tangent_size) { |
||
403 | |||
404 | int npts = crv.num_vertices; |
||
405 | |||
406 | if (npts < 2) return; |
||
407 | |||
408 | int last = npts - 1; |
||
409 | point<float>& p0 = crv.vertices[0]; |
||
410 | point<float>& p1 = crv.vertices[1]; |
||
411 | point<float>& pl = crv.vertices[last]; |
||
412 | point<float>& pl1 = crv.vertices[last-1]; |
||
413 | |||
414 | // set tangents for 1st vertex |
||
415 | float dx, dy; direction (dx, dy, p0.x, p0.y, p1.x, p1.y); |
||
416 | float tx = tangent_size * dx, ty = tangent_size * dy; |
||
417 | crv.set_left_tangent (0, p0.x - tx, p0.y - ty); |
||
418 | crv.set_right_tangent (0, p0.x + tx, p0.y + ty); |
||
419 | |||
420 | // set tangents for last vertex |
||
421 | direction (dx, dy, pl.x, pl.y, pl1.x, pl1.y); |
||
422 | tx = tangent_size * dx; ty = tangent_size * dy; |
||
423 | crv.set_left_tangent (last, pl.x + tx, pl.y + ty); |
||
424 | crv.set_right_tangent (last, pl.x - tx, pl.y - ty); |
||
425 | |||
426 | // set left, right tangent for inbetween vertices |
||
427 | for (int i = 1; i < last; ++i) { |
||
428 | int l = i - 1, r = i + 1; |
||
429 | point<float>& pi = crv.vertices[i]; |
||
430 | point<float>& pl = crv.vertices[l]; |
||
431 | point<float>& pr = crv.vertices[r]; |
||
432 | direction (dx, dy, pl.x, pl.y, pr.x, pr.y); |
||
433 | crv.set_left_tangent (i, pi.x - tangent_size * dx, pi.y - tangent_size * dy); |
||
434 | crv.set_right_tangent (i, pi.x + tangent_size * dx, pi.y + tangent_size * dy); |
||
435 | } |
||
436 | |||
437 | crv.evaluate (); |
||
438 | |||
439 | } |
||
440 | |||
441 | multi_curve* check_list (multi_curve** lst, int n, const string& name) { |
||
442 | for (int m = 0; m < n; ++m) if (lst[m]->name == name) return lst[m]; |
||
443 | return 0; |
||
444 | } |
||
445 | |||
446 | vector<crvpt>& multi_curve::get_profile_points (int i) { |
||
447 | if (shapeform) return curv[i].dpts; else return curv[i].vpts; |
||
448 | } |
||
449 | |||
1947 | jag | 450 | void multi_curve::setcentroid (int shapeform) { |
451 | static const float CX [] = {0.0f, 0.5f}; |
||
2178 | jag | 452 | cen.x = CX [shapeform]; |
453 | cen.y = 0.0f; |
||
1947 | jag | 454 | } |
455 | |||
964 | jag | 456 | void multi_curve::set_shapeform (int what) { |
457 | shapeform = what; |
||
1947 | jag | 458 | setcentroid (shapeform); |
1107 | jag | 459 | require_eval (); |
460 | evaluate (); |
||
964 | jag | 461 | } |
462 | |||
1947 | jag | 463 | void multi_curve::rotate (float angle) { |
2185 | jag | 464 | for (int i = 1; i < num_vertices; ++i) { |
2184 | jag | 465 | pointinfo<float>& lt = left_tangents[i]; |
2185 | jag | 466 | if (lt.pin == 0) lt.rotate (cen, angle); |
467 | } |
||
468 | for (int i = 0; i < last_vertex; ++i) { |
||
2184 | jag | 469 | pointinfo<float>& rt = right_tangents[i]; |
2181 | jag | 470 | if (rt.pin == 0) rt.rotate (cen, angle); |
964 | jag | 471 | } |
2187 | jag | 472 | for (int i = 0; i < num_vertices; ++i) { |
473 | pointinfo<float>& vi = vertices[i]; |
||
474 | if (vi.pin == 0) vi.rotate (cen, angle); |
||
475 | } |
||
476 | |||
477 | point<float>& v0 = vertices[0]; |
||
478 | point<float>& lt0 = left_tangents[0]; |
||
479 | lt0 = v0; |
||
480 | |||
481 | point<float>& vl = vertices[last_vertex]; |
||
482 | point<float>& rtl = right_tangents[last_vertex]; |
||
483 | rtl = vl; |
||
484 | |||
964 | jag | 485 | require_eval (); |
486 | evaluate (); |
||
2187 | jag | 487 | |
964 | jag | 488 | } |
489 | |||
490 | void multi_curve::scale (float sx, float sy) { |
||
491 | for (int i = 0; i < num_vertices; ++i) { |
||
492 | point<float>& vi = vertices[i]; |
||
493 | point<float>& lt = left_tangents[i]; |
||
494 | point<float>& rt = right_tangents[i]; |
||
2178 | jag | 495 | vi.scale (cen, sx, sy); |
496 | lt.scale (cen, sx, sy); |
||
497 | rt.scale (cen, sx, sy); |
||
964 | jag | 498 | } |
499 | require_eval (); |
||
500 | evaluate (); |
||
501 | } |
||
502 | |||
503 | void multi_curve::get_xy (double d, float& x, float& y) { |
||
2195 | jag | 504 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 505 | curve& c = curv[i]; |
506 | vector<crvpt>& vpts = c.vpts; |
||
507 | vector<crvpt>& dpts = c.dpts; |
||
508 | for (int m = 0, n = dpts.size () - 1; m < n; ++m) { |
||
509 | crvpt& dm = dpts[m]; |
||
510 | crvpt& dn = dpts[m+1]; |
||
511 | crvpt& vm = vpts[m]; |
||
512 | crvpt& vn = vpts[m+1]; |
||
513 | if (d >= dm.x && d <= dn.x) { |
||
514 | float amt = (d - dm.x) / (dn.x - dm.x); |
||
515 | x = vm.x + amt * (vn.x - vm.x); |
||
516 | y = vm.y + amt * (vn.y - vm.y); |
||
517 | return; |
||
518 | } |
||
519 | } |
||
520 | } |
||
521 | } |
||
522 | |||
523 | int multi_curve::get_total_points () { |
||
524 | int total = 0; |
||
2195 | jag | 525 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 526 | vector<crvpt>& vpts = curv[i].vpts; |
2133 | jag | 527 | int ni = vpts.size () - 1; |
528 | total = total + ni; |
||
964 | jag | 529 | } |
2133 | jag | 530 | ++total; |
964 | jag | 531 | return total; |
532 | } |
||
533 | |||
2133 | jag | 534 | int multi_curve::get_total_points (vector<int>& crvs) { |
2195 | jag | 535 | int j = ncurvs, j_1 = j - 1; |
2133 | jag | 536 | crvs.reserve (j); |
537 | int total = 0; |
||
538 | for (int i = 0; i < j; ++i) { |
||
539 | vector<crvpt>& vpts = curv[i].vpts; |
||
540 | int ni = vpts.size () - 1; |
||
541 | crvs[i] = ni; |
||
542 | total = total + ni; |
||
543 | } |
||
544 | ++crvs[j_1]; |
||
545 | ++total; |
||
546 | |||
547 | return total; |
||
548 | } |
||
549 | |||
2158 | jag | 550 | int multi_curve::get_profile_points (vector<crvpt>& profile) { |
2133 | jag | 551 | vector<int> crvs; |
552 | int n = get_total_points (crvs); |
||
553 | profile.reserve (n); |
||
554 | profile.clear (); |
||
2195 | jag | 555 | for (int i = 0, k = 0; i < ncurvs; ++i) { |
964 | jag | 556 | vector<crvpt>& vpts = curv[i].vpts; |
2133 | jag | 557 | for (int p = 0; p < crvs[i]; ++p) profile[k++] = vpts[p]; |
964 | jag | 558 | } |
2158 | jag | 559 | return n; |
964 | jag | 560 | } |
561 | |||
2120 | jag | 562 | double multi_curve::get_tangent_mag (int i, points_array& pa) { |
563 | point<float>& v = vertices[i]; |
||
564 | point<float>& t = pa[i]; |
||
565 | return magnitude (v.x, v.y, t.x, t.y); |
||
566 | } |
||
567 | |||
568 | double multi_curve::get_left_tangent_mag (int i) { |
||
569 | return get_tangent_mag (i, left_tangents); |
||
570 | } |
||
571 | |||
572 | |||
573 | double multi_curve::get_right_tangent_mag (int i) { |
||
574 | return get_tangent_mag (i, right_tangents); |
||
575 | } |
||
2133 | jag | 576 | |
2189 | jag | 577 | void multi_curve::move (float dx, float dy) { |
578 | for (int i = 0; i < num_vertices; ++i) { |
||
579 | pointinfo<float>& p = vertices [i]; |
||
580 | set_vertex (i, p.x + dx, p.y + dy); |
||
2199 | jag | 581 | /*if (p.carry == 0) { |
2189 | jag | 582 | pointinfo<float>& l = left_tangents [i]; |
2198 | jag | 583 | if (l.pin == 0) set_left_tangent (i, l.x + dx, l.y + dy); |
2189 | jag | 584 | pointinfo<float>& r = right_tangents [i]; |
2198 | jag | 585 | if (r.pin == 0) set_right_tangent (i, r.x + dx, r.y + dy); |
2199 | jag | 586 | //}*/ |
2189 | jag | 587 | } |
588 | require_eval (); |
||
589 | evaluate (); |
||
590 | } |
||
591 | |||
2133 | jag | 592 | extern void make_good_name (string& name); |
593 | |||
594 | void multi_curve::set_name (const string& _name) { |
||
595 | name = _name; |
||
596 | make_good_name (name); |
||
597 | } |
||
598 | |||
2178 | jag | 599 | void scale (point<float>& p, point<float>& c, float sx, float sy) { |
600 | float px = sx * (p.x - c.x), py = sy * (p.y - c.y); |
||
601 | p.x = c.x + px; |
||
602 | p.y = c.y + py; |
||
603 | } |