Rev 2211 | Go to most recent revision | 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) { |
||
144 | points_array::iterator vter = ++vertices.begin (), lter = ++left_tangents.begin (), rter = ++right_tangents.begin (); |
||
145 | vector<curve>::iterator cter = curv.begin (); |
||
146 | for (int i = 0, j = last_vertex; i < j; ++i, ++vter, ++lter, ++rter, ++cter) { |
||
147 | point<float>& vi = vertices[i]; |
||
148 | point<float>& vi1 = vertices[i + 1]; |
||
149 | if ((x >= vi.x) && (x <= vi1.x)) { |
||
1605 | jag | 150 | /*float ltx, lty; unit_vector (ltx, lty, x, y, vi.x, vi.y); |
964 | jag | 151 | float rtx, rty; unit_vector (rtx, rty, x, y, vi1.x, vi1.y); |
1605 | jag | 152 | point<float> v (x, y), lt (x + tx * ltx, y + ty * lty), rt (x + tx * rtx, y + ty * rty);*/ |
153 | point<float> v (x, y); |
||
964 | jag | 154 | vertices.insert (vter, v); |
155 | last_vertex = num_vertices++; |
||
1605 | jag | 156 | left_tangents.insert (lter, v); |
157 | right_tangents.insert (rter, v); |
||
158 | /*left_tangents.insert (lter, lt); |
||
159 | right_tangents.insert (rter, rt);*/ |
||
2197 | jag | 160 | (*cter).eval = 1; |
964 | jag | 161 | curv.insert (cter, curve()); |
2195 | jag | 162 | ++ncurvs; |
964 | jag | 163 | return 1; |
164 | } |
||
165 | } |
||
166 | return 0; |
||
167 | } |
||
168 | |||
169 | int multi_curve::remove (int i) { |
||
170 | // remove ith vertex and its tangents |
||
171 | if (num_vertices < 3) return 0; |
||
172 | erase_id (vertices, i); |
||
173 | erase_id (left_tangents, i); |
||
174 | erase_id (right_tangents, i); |
||
2195 | jag | 175 | if (i == ncurvs) { |
964 | jag | 176 | int j = i - 1; |
177 | erase_id (curv, j); |
||
178 | } else { |
||
179 | erase_id (curv, i); |
||
2197 | jag | 180 | if (--i > -1) curv[i].eval = 1; else curv[0].eval = 1; |
964 | jag | 181 | } |
182 | --num_vertices; |
||
2195 | jag | 183 | --ncurvs; |
964 | jag | 184 | last_vertex = num_vertices - 1; |
185 | return 1; |
||
186 | } |
||
187 | |||
188 | void multi_curve::set_limit (float d) { |
||
189 | limit = d; |
||
190 | require_eval (); |
||
191 | } |
||
192 | |||
193 | void multi_curve::require_eval () { |
||
2197 | jag | 194 | for (int i = 0; i < ncurvs; ++i) curv[i].eval = 1; |
964 | jag | 195 | } |
196 | |||
197 | void multi_curve::set_color () { |
||
198 | static const float base = 0.1f; |
||
199 | static rnd<float> rd (base, 1.0f - base); |
||
200 | r = rd (); g = rd (); b = rd (); |
||
201 | calc_tangent_color (); |
||
202 | } |
||
203 | |||
204 | void multi_curve::set_color (float rr, float gg, float bb) { |
||
205 | r = rr; |
||
206 | g = gg; |
||
207 | b = bb; |
||
208 | calc_tangent_color (); |
||
209 | } |
||
210 | |||
211 | void multi_curve::calc_tangent_color () { |
||
212 | static const float factor = 0.5; |
||
213 | rt = factor * r; |
||
214 | gt = factor * g; |
||
215 | bt = factor * b; |
||
216 | } |
||
217 | |||
218 | void multi_curve::evaluate () { |
||
219 | int nevals = 0; |
||
2195 | jag | 220 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 221 | curve& crv = curv[i]; |
2197 | jag | 222 | if (crv.eval) { |
964 | jag | 223 | int j = i + 1; |
224 | point<float>& v0 = vertices[i]; |
||
225 | point<float>& v1 = vertices[j]; |
||
226 | point<float>& rt0 = right_tangents[i]; |
||
227 | point<float>& lt1 = left_tangents[j]; |
||
228 | crv.vertex (0, v0.x, v0.y); |
||
229 | crv.vertex (1, v1.x, v1.y); |
||
230 | crv.tangent (0, rt0.x, rt0.y); |
||
231 | crv.tangent (1, lt1.x, lt1.y); |
||
232 | crv.set_limit (limit); |
||
2191 | jag | 233 | crv.evaluate (shapeform); |
964 | jag | 234 | ++nevals; |
235 | } |
||
236 | } |
||
237 | |||
238 | if (nevals) { |
||
239 | if (shapeform) { |
||
240 | float total_length = 0.0f; |
||
241 | float now_length = 0.0f; |
||
2195 | jag | 242 | for (int i = 0; i < ncurvs; ++i) total_length += curv[i].length; |
243 | for (int i = 0; i < ncurvs; ++i) curv[i].normalise_length (now_length, total_length); |
||
964 | jag | 244 | check_shapeform (); |
245 | } |
||
246 | } |
||
247 | } |
||
248 | |||
249 | void multi_curve::check_shapeform () { |
||
2195 | jag | 250 | for (int i = 0, j = 1, k = ncurvs - 1; i < k; ++i, ++j) { |
964 | jag | 251 | curve& crvi = curv[i]; |
252 | curve& crvj = curv[j]; |
||
253 | vector<crvpt>& dptsi = crvi.dpts; |
||
254 | vector<crvpt>& dptsj = crvj.dpts; |
||
255 | int last = dptsi.size () - 1; |
||
256 | crvpt& dl = dptsi[last]; |
||
257 | crvpt& d0 = dptsj[0]; |
||
258 | d0.x = dl.x; |
||
259 | d0.y = dl.y; |
||
260 | } |
||
261 | } |
||
262 | |||
263 | void multi_curve::calc_bbox (box<float>& b) { |
||
2195 | jag | 264 | if (ncurvs) { |
964 | jag | 265 | int num_points = curv[0].vpts.size (); |
266 | if (num_points) { |
||
267 | const vector<crvpt>& vpts = curv[0].vpts; |
||
268 | b.left = b.right = vpts[0].x; |
||
269 | b.bottom = b.top = vpts[0].y; |
||
2195 | jag | 270 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 271 | const vector <crvpt>& vpts = curv[i].vpts; |
272 | num_points = vpts.size (); |
||
273 | for (int j = 0; j < num_points; ++j) { |
||
274 | const crvpt& p = vpts[j]; |
||
275 | if (p.x < b.left) b.left = p.x; else if (p.x > b.right) b.right = p.x; |
||
276 | if (p.y < b.bottom) b.bottom = p.y; else if (p.y > b.top) b.top = p.y; |
||
277 | } |
||
278 | } |
||
279 | } |
||
280 | } |
||
281 | b.calc (); |
||
282 | } |
||
283 | |||
284 | |||
285 | void multi_curve::load (const string& filename) { |
||
286 | ifstream file ((user_data_dir + filename).c_str (), ios::in); |
||
287 | if (!file) { |
||
288 | dlog << "!!! failed to load curve from: " << filename << " !!!" << endl; |
||
289 | return; |
||
290 | } |
||
291 | load (file); |
||
292 | dlog << "+++ loaded curve from: " << filename << " +++" << endl; |
||
293 | } |
||
294 | |||
295 | void multi_curve::load (ifstream& file) { |
||
296 | |||
297 | clear (); |
||
298 | |||
299 | string ignore; |
||
300 | |||
301 | file >> ignore >> name; |
||
302 | |||
303 | int nvertices; |
||
304 | file >> ignore >> nvertices; |
||
305 | |||
306 | for (int i = 0; i < nvertices; ++i) { |
||
307 | |||
308 | float x, y; |
||
2208 | jag | 309 | int p; |
310 | file >> ignore >> x >> y >> p; |
||
311 | add_vertex (x, y, p); |
||
312 | file >> ignore >> x >> y >> p; |
||
313 | add_left_tangent (x, y, p); |
||
314 | file >> ignore >> x >> y >> p; |
||
315 | add_right_tangent (x, y, p); |
||
964 | jag | 316 | |
317 | } |
||
318 | |||
319 | file >> ignore >> limit; |
||
320 | |||
321 | float ir, ig, ib; file >> ignore >> ir >> ig >> ib; |
||
322 | set_color (ir, ig, ib); |
||
323 | |||
324 | file >> ignore >> shapeform; |
||
1947 | jag | 325 | setcentroid (shapeform); |
964 | jag | 326 | |
327 | point<float>& lt0 = left_tangents[0]; |
||
328 | point<float>& v0 = vertices[0]; |
||
329 | int last = nvertices - 1; |
||
330 | point<float>& rtl = right_tangents[last]; |
||
331 | point<float>& vl = vertices[last]; |
||
332 | lt0.x = v0.x; lt0.y = v0.y; |
||
333 | rtl.x = vl.x; rtl.y = vl.y; |
||
334 | |||
335 | evaluate (); |
||
336 | |||
337 | } |
||
338 | |||
339 | void multi_curve::save (const string& filename) { |
||
340 | ofstream file ((user_data_dir + filename).c_str (), ios::out); |
||
341 | if (!file) { |
||
342 | dlog << "!!! failed writing curve to: " << filename << endl; |
||
343 | return; |
||
344 | } |
||
345 | save (file); |
||
346 | dlog << "+++ saved curve into: " << filename << " +++" << endl; |
||
347 | } |
||
348 | |||
349 | void multi_curve::save (ofstream& file) { |
||
350 | string ignore; |
||
351 | if (name == "") name = "nameless"; |
||
352 | file << "name " << name << eol; |
||
353 | file << "num_vertices " << num_vertices << eol; |
||
354 | for (int i = 0; i < num_vertices; ++i) { |
||
2208 | jag | 355 | pointinfo<float>& v = vertices[i]; |
356 | pointinfo<float>& lt = left_tangents[i]; |
||
357 | pointinfo<float>& rt = right_tangents[i]; |
||
2211 | jag | 358 | file << "v" << i << spc << v.x << spc << v.y << spc << v.pin << eol; |
359 | file << "lt" << i << spc << lt.x << spc << lt.y << spc << lt.pin << eol; |
||
360 | file << "rt" << i << spc << rt.x << spc << rt.y << spc << rt.pin << eol; |
||
964 | jag | 361 | } |
362 | file << "limit " << limit << eol; |
||
363 | file << "color " << r << spc << g << spc << b << eol; |
||
364 | file << "shapeform " << shapeform << eol; |
||
365 | } |
||
366 | |||
367 | void create_polyline (multi_curve& crv, const points_array& pts) { |
||
368 | int npts = pts.size (); |
||
369 | if (npts < 2) return; |
||
370 | crv.clear (0); |
||
371 | for (int i = 0; i < npts; ++i) { |
||
372 | float xi = pts[i].x, yi = pts[i].y; |
||
373 | crv.add_vertex (xi, yi); |
||
374 | crv.add_left_tangent (xi, yi); |
||
375 | crv.add_right_tangent (xi, yi); |
||
376 | } |
||
377 | crv.evaluate (); |
||
378 | } |
||
379 | |||
380 | void convert2_polyline (multi_curve& crv) { |
||
381 | for (int i = 0, j = crv.num_vertices; i < j; ++i) { |
||
382 | point<float>& v = crv.vertices[i]; |
||
383 | crv.set_left_tangent (i, v.x, v.y); |
||
384 | crv.set_right_tangent (i, v.x, v.y); |
||
385 | } |
||
386 | crv.evaluate (); |
||
387 | } |
||
388 | |||
389 | void convert2_catmull_rom (multi_curve& crv, float tangent_size) { |
||
390 | |||
391 | int npts = crv.num_vertices; |
||
392 | |||
393 | if (npts < 2) return; |
||
394 | |||
395 | int last = npts - 1; |
||
396 | point<float>& p0 = crv.vertices[0]; |
||
397 | point<float>& p1 = crv.vertices[1]; |
||
398 | point<float>& pl = crv.vertices[last]; |
||
399 | point<float>& pl1 = crv.vertices[last-1]; |
||
400 | |||
401 | // set tangents for 1st vertex |
||
402 | float dx, dy; direction (dx, dy, p0.x, p0.y, p1.x, p1.y); |
||
403 | float tx = tangent_size * dx, ty = tangent_size * dy; |
||
404 | crv.set_left_tangent (0, p0.x - tx, p0.y - ty); |
||
405 | crv.set_right_tangent (0, p0.x + tx, p0.y + ty); |
||
406 | |||
407 | // set tangents for last vertex |
||
408 | direction (dx, dy, pl.x, pl.y, pl1.x, pl1.y); |
||
409 | tx = tangent_size * dx; ty = tangent_size * dy; |
||
410 | crv.set_left_tangent (last, pl.x + tx, pl.y + ty); |
||
411 | crv.set_right_tangent (last, pl.x - tx, pl.y - ty); |
||
412 | |||
413 | // set left, right tangent for inbetween vertices |
||
414 | for (int i = 1; i < last; ++i) { |
||
415 | int l = i - 1, r = i + 1; |
||
416 | point<float>& pi = crv.vertices[i]; |
||
417 | point<float>& pl = crv.vertices[l]; |
||
418 | point<float>& pr = crv.vertices[r]; |
||
419 | direction (dx, dy, pl.x, pl.y, pr.x, pr.y); |
||
420 | crv.set_left_tangent (i, pi.x - tangent_size * dx, pi.y - tangent_size * dy); |
||
421 | crv.set_right_tangent (i, pi.x + tangent_size * dx, pi.y + tangent_size * dy); |
||
422 | } |
||
423 | |||
424 | crv.evaluate (); |
||
425 | |||
426 | } |
||
427 | |||
428 | multi_curve* check_list (multi_curve** lst, int n, const string& name) { |
||
429 | for (int m = 0; m < n; ++m) if (lst[m]->name == name) return lst[m]; |
||
430 | return 0; |
||
431 | } |
||
432 | |||
433 | vector<crvpt>& multi_curve::get_profile_points (int i) { |
||
434 | if (shapeform) return curv[i].dpts; else return curv[i].vpts; |
||
435 | } |
||
436 | |||
1947 | jag | 437 | void multi_curve::setcentroid (int shapeform) { |
438 | static const float CX [] = {0.0f, 0.5f}; |
||
2178 | jag | 439 | cen.x = CX [shapeform]; |
440 | cen.y = 0.0f; |
||
1947 | jag | 441 | } |
442 | |||
964 | jag | 443 | void multi_curve::set_shapeform (int what) { |
444 | shapeform = what; |
||
1947 | jag | 445 | setcentroid (shapeform); |
1107 | jag | 446 | require_eval (); |
447 | evaluate (); |
||
964 | jag | 448 | } |
449 | |||
1947 | jag | 450 | void multi_curve::rotate (float angle) { |
2185 | jag | 451 | for (int i = 1; i < num_vertices; ++i) { |
2184 | jag | 452 | pointinfo<float>& lt = left_tangents[i]; |
2185 | jag | 453 | if (lt.pin == 0) lt.rotate (cen, angle); |
454 | } |
||
455 | for (int i = 0; i < last_vertex; ++i) { |
||
2184 | jag | 456 | pointinfo<float>& rt = right_tangents[i]; |
2181 | jag | 457 | if (rt.pin == 0) rt.rotate (cen, angle); |
964 | jag | 458 | } |
2187 | jag | 459 | for (int i = 0; i < num_vertices; ++i) { |
460 | pointinfo<float>& vi = vertices[i]; |
||
461 | if (vi.pin == 0) vi.rotate (cen, angle); |
||
462 | } |
||
463 | |||
464 | point<float>& v0 = vertices[0]; |
||
465 | point<float>& lt0 = left_tangents[0]; |
||
466 | lt0 = v0; |
||
467 | |||
468 | point<float>& vl = vertices[last_vertex]; |
||
469 | point<float>& rtl = right_tangents[last_vertex]; |
||
470 | rtl = vl; |
||
471 | |||
964 | jag | 472 | require_eval (); |
473 | evaluate (); |
||
2187 | jag | 474 | |
964 | jag | 475 | } |
476 | |||
477 | void multi_curve::scale (float sx, float sy) { |
||
478 | for (int i = 0; i < num_vertices; ++i) { |
||
479 | point<float>& vi = vertices[i]; |
||
480 | point<float>& lt = left_tangents[i]; |
||
481 | point<float>& rt = right_tangents[i]; |
||
2178 | jag | 482 | vi.scale (cen, sx, sy); |
483 | lt.scale (cen, sx, sy); |
||
484 | rt.scale (cen, sx, sy); |
||
964 | jag | 485 | } |
486 | require_eval (); |
||
487 | evaluate (); |
||
488 | } |
||
489 | |||
490 | void multi_curve::get_xy (double d, float& x, float& y) { |
||
2195 | jag | 491 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 492 | curve& c = curv[i]; |
493 | vector<crvpt>& vpts = c.vpts; |
||
494 | vector<crvpt>& dpts = c.dpts; |
||
495 | for (int m = 0, n = dpts.size () - 1; m < n; ++m) { |
||
496 | crvpt& dm = dpts[m]; |
||
497 | crvpt& dn = dpts[m+1]; |
||
498 | crvpt& vm = vpts[m]; |
||
499 | crvpt& vn = vpts[m+1]; |
||
500 | if (d >= dm.x && d <= dn.x) { |
||
501 | float amt = (d - dm.x) / (dn.x - dm.x); |
||
502 | x = vm.x + amt * (vn.x - vm.x); |
||
503 | y = vm.y + amt * (vn.y - vm.y); |
||
504 | return; |
||
505 | } |
||
506 | } |
||
507 | } |
||
508 | } |
||
509 | |||
510 | int multi_curve::get_total_points () { |
||
511 | int total = 0; |
||
2195 | jag | 512 | for (int i = 0; i < ncurvs; ++i) { |
964 | jag | 513 | vector<crvpt>& vpts = curv[i].vpts; |
2133 | jag | 514 | int ni = vpts.size () - 1; |
515 | total = total + ni; |
||
964 | jag | 516 | } |
2133 | jag | 517 | ++total; |
964 | jag | 518 | return total; |
519 | } |
||
520 | |||
2133 | jag | 521 | int multi_curve::get_total_points (vector<int>& crvs) { |
2195 | jag | 522 | int j = ncurvs, j_1 = j - 1; |
2133 | jag | 523 | crvs.reserve (j); |
524 | int total = 0; |
||
525 | for (int i = 0; i < j; ++i) { |
||
526 | vector<crvpt>& vpts = curv[i].vpts; |
||
527 | int ni = vpts.size () - 1; |
||
528 | crvs[i] = ni; |
||
529 | total = total + ni; |
||
530 | } |
||
531 | ++crvs[j_1]; |
||
532 | ++total; |
||
533 | |||
534 | return total; |
||
535 | } |
||
536 | |||
2158 | jag | 537 | int multi_curve::get_profile_points (vector<crvpt>& profile) { |
2133 | jag | 538 | vector<int> crvs; |
539 | int n = get_total_points (crvs); |
||
540 | profile.reserve (n); |
||
541 | profile.clear (); |
||
2195 | jag | 542 | for (int i = 0, k = 0; i < ncurvs; ++i) { |
964 | jag | 543 | vector<crvpt>& vpts = curv[i].vpts; |
2133 | jag | 544 | for (int p = 0; p < crvs[i]; ++p) profile[k++] = vpts[p]; |
964 | jag | 545 | } |
2158 | jag | 546 | return n; |
964 | jag | 547 | } |
548 | |||
2120 | jag | 549 | double multi_curve::get_tangent_mag (int i, points_array& pa) { |
550 | point<float>& v = vertices[i]; |
||
551 | point<float>& t = pa[i]; |
||
552 | return magnitude (v.x, v.y, t.x, t.y); |
||
553 | } |
||
554 | |||
555 | double multi_curve::get_left_tangent_mag (int i) { |
||
556 | return get_tangent_mag (i, left_tangents); |
||
557 | } |
||
558 | |||
559 | |||
560 | double multi_curve::get_right_tangent_mag (int i) { |
||
561 | return get_tangent_mag (i, right_tangents); |
||
562 | } |
||
2133 | jag | 563 | |
2189 | jag | 564 | void multi_curve::move (float dx, float dy) { |
565 | for (int i = 0; i < num_vertices; ++i) { |
||
566 | pointinfo<float>& p = vertices [i]; |
||
567 | set_vertex (i, p.x + dx, p.y + dy); |
||
2199 | jag | 568 | /*if (p.carry == 0) { |
2189 | jag | 569 | pointinfo<float>& l = left_tangents [i]; |
2198 | jag | 570 | if (l.pin == 0) set_left_tangent (i, l.x + dx, l.y + dy); |
2189 | jag | 571 | pointinfo<float>& r = right_tangents [i]; |
2198 | jag | 572 | if (r.pin == 0) set_right_tangent (i, r.x + dx, r.y + dy); |
2199 | jag | 573 | //}*/ |
2189 | jag | 574 | } |
575 | require_eval (); |
||
576 | evaluate (); |
||
577 | } |
||
578 | |||
2133 | jag | 579 | extern void make_good_name (string& name); |
580 | |||
581 | void multi_curve::set_name (const string& _name) { |
||
582 | name = _name; |
||
583 | make_good_name (name); |
||
584 | } |
||
585 | |||
2178 | jag | 586 | void scale (point<float>& p, point<float>& c, float sx, float sy) { |
587 | float px = sx * (p.x - c.x), py = sy * (p.y - c.y); |
||
588 | p.x = c.x + px; |
||
589 | p.y = c.y + py; |
||
590 | } |