(09:03:49) ACSpike: I tried to glean drawing a circle from conic-4 (I think) I'm either missing the drawing of the circle in the rest of the code, or it is just so short and simple that I don't get it (09:08:03) ACSpike: heh, oh "Define here various primatives, such as line, line segment, circle, bezier path etc." (09:18:29) njh: don't look at that (09:18:37) njh: that's done in a hacky way (09:19:09) njh: ok, lets plan what your program will do (09:19:23) njh: I'm thinking an 'on canvas' editor for gears (09:20:13) njh: the biggest problem is that you have lumpy parameters (for example number of teeth is a whole number) (09:20:54) ACSpike: lets start smaller (09:21:00) njh: ok (09:21:09) njh: howabout just drawing a circle (09:21:11) ACSpike: I need an entry point into the world of 2geom (09:21:31) ACSpike: can I get an svg path for a circle? (09:21:35) njh: well, what I was going to suggest was just making circles with handles (09:21:44) ACSpike: ie, no gtk gui stuff (09:21:47) njh: hehe, I still haven't done circles :) (09:21:52) njh: but you can use cairo (09:21:58) ACSpike: well (09:22:02) njh: cairo_arc (09:22:03) ACSpike: what can I get? (09:22:27) njh: lets make a program that just draws a single circle (09:23:00) ACSpike: ok. back in a bit (09:31:15) njh: ok (09:31:22) njh: I've committed a starting point for you (09:31:23) ACSpike: ok, I get it. 2geom doesn't do svg (09:31:29) ACSpike: it does beziers (09:31:37) ACSpike: and draws them on a cairo surface (09:32:27) njh: at this point, yeah (09:32:38) njh: actually, it doesn't even draw them :) (09:32:54) njh: that's done by path-cairo, which is demidetached :) (09:33:22) njh: so gear.cpp is a starting point for you (09:33:51) njh: one issue is that I haven't done elliptical arcs in Paths yet (09:34:04) njh: so we're going to not even use paths at this point (09:34:34) njh: just attempt to make a circle using sbasis rather than calling cairo_arc (09:35:03) verbalshadow [verbalshadow@gristle.org/Laptop] entered the room. (09:35:17) ACSpike: oy (09:35:19) njh: so a circle is parameterised by with t going form 0 to 2*pi (09:35:27) ACSpike: right (09:35:41) njh: does gear compile and run on your computer? (09:36:35) ACSpike: did you commit it? (09:39:27) njh: I spose I should add before commiting (09:39:37) njh: done (09:39:57) njh: ok, your second step will be to add two handles (09:48:04) njh: feel free to ask if you are stuck (09:48:50) ACSpike: oh, boy (09:49:04) ACSpike: so we have a handle for radius (09:50:01) Botty: the most elegant way to do this convex stuff would be to have a circular iterator (09:50:16) Botty: i suppose modulus works (09:51:32) njh: it does (09:51:55) njh: ACSpike: the longest journey starts with a single step (09:52:11) ACSpike: or a single grep (09:52:24) njh: I prefer emacs isearch (09:52:35) njh: so, does it compile? (09:52:39) ACSpike: ya (09:52:41) ACSpike: and runs (09:52:48) njh: and have yuo worked out how to add a handle (09:52:59) ACSpike: pushback (09:53:05) njh: yep (09:53:11) njh: just increase the loop (09:53:27) njh: generates random handles (09:53:51) njh: anyway, have you got two extra handles? (09:54:00) ACSpike: no (09:54:01) njh: please tell me when you have something working (09:54:16) ACSpike: I'm trying to grok the single handle (09:54:33) njh: just assume that handles can be moved anyway (09:54:40) njh: how they work is a bit fiddly (09:54:49) ACSpike: and raise kids :-) (09:54:51) njh: but all they are is a Geom::Point (09:57:54) njh: no (09:58:05) njh: how do I do that? (10:01:44) ACSpike: yes (10:05:04) ACSpike: norm ~ magnatude ~ distance? (10:06:07) njh: norms are like distance, yes (10:06:31) njh: but not just 'as the crow flies' distance (10:06:51) njh: another norm would be how long it takes you to get between places (10:07:17) njh: 2geom provides a few norms: L2 and Linfinity (10:07:28) njh: L2 = eucliean, as the crow flies distance (10:07:34) ACSpike: L1, L2 and infinity (10:07:47) ACSpike: l1 equals as the taxi drives (10:07:50) njh: Linfinity = maximum distance in x or y (10:07:56) njh: yeah l1 is taxi (10:08:07) Botty: (X+Y) (10:08:11) ACSpike: linfinity is x or y? (10:08:14) njh: no, |X| + |Y| (10:08:23) Botty: good point... (10:08:25) njh: Linfinity = max(|X|, |Y|) (10:08:30) ACSpike: right (10:08:34) ACSpike: interesting (10:08:40) ACSpike: thanks (12:02:59) ACSpike: what should I do with these two random handles? (12:03:19) ACSpike: pressure angle and number of teeth is what's needed (12:06:18) njh: lets start with a line (12:06:49) ACSpike: like constrain the movement of the handles? (12:06:52) njh: ok, SBasis functions map [0,1] to a value (12:06:57) njh: no, just darwing a line segment (12:07:20) ACSpike: each handle makes one endpoint? (12:07:21) njh: so we want to construct a function that maps [0,1] onto a line from handle 1 to handle 2 (12:08:14) njh: do you have two new handles? (12:09:35) ACSpike: yes (12:09:59) njh: ok, so we're going to make a pair of sbasis functions, one for x, one for y (12:10:10) njh: to do this we need a multidim_sbasis<2> (12:10:18) njh: (one day I'll work out better names :) (12:10:28) ACSpike: which means, a second degree sbasis? (12:10:47) njh: multidim_sbasis<2> B; (12:10:56) ACSpike: this is global? (12:10:57) njh: it means a function which maps [0,1] onto a point (12:11:03) njh: no, put it in expose (12:11:07) njh: everything goes in expose (12:20:09) njh: anyway, so you have a function that maps [0,1] onto a point (12:20:08) ACSpike: I'm about to look for the definition of multidim_sbasis (12:20:15) njh: don't (12:20:23) njh: it's complicated and not necessary (12:20:27) ACSpike: ok (12:20:36) ACSpike: leaps with faith (12:21:21) njh: so we need to define what the functions are for X and Y (12:21:36) njh: just like a point, these are B[X] and B[Y] (12:21:47) ACSpike: ah (12:21:55) ACSpike: X and Y are defined somewhere? (12:22:00) njh: yeah, in point I think (12:22:06) njh: but I'm lazy and use 0 and 1 (12:22:12) ACSpike: ah, good (12:23:33) njh: Now the simplest function maps [0,1] onto a constant value (12:23:53) njh: we could do this with B[0] = handles[1][0]; (12:23:59) ACSpike: so all values between 0 and 1 are the same (12:24:03) njh: and similarly B[1] = handles[1][1]; (12:24:07) njh: yep (12:24:11) njh: that would define a point (12:24:32) njh: (I'm not sure that would compile, due to missing code) (12:24:48) njh: I usually do everything in parallel like this: (12:24:55) njh: for(int im = 0; dim < 2; dim++) (12:25:04) njh: B[dim] = handles[1][dim]; (12:25:25) njh: remember that handles[0] is the point on the gear we did already (12:25:51) njh: we're going to draw a line somewhere (12:25:57) njh: (you have to draw a line somewhere!) (12:26:27) njh: to do this we want to map [0,1] to points between handles[1] and handles[2] (12:27:06) njh: for technical(and not very good) reasons this means using BezOrds (12:27:11) ACSpike: pause for reflection (12:27:11) njh: like this: (12:27:30) njh: B[dim] = BezOrd(handles[1][dim], handles[2][dim]); (12:27:41) ACSpike: what are BezOrds? (12:27:50) njh: so try adding that code into expose (12:28:07) njh: BezOrd(a,b) maps 0,1 onto [a,b] (12:29:48) njh: the reason for BezOrds is they are the fundamental unit for all the maths (12:30:08) ACSpike: what does BezOrd mean though? (12:30:10) njh: just like points are the fundamental units for graphics (12:30:14) njh: Bezier Ordinal (12:30:16) ACSpike: I need to attach the idea to the name (12:30:27) njh: you can think of them as linear bezier segments (12:30:46) njh: add another poit and you have a quadratic, another, cubic (12:31:08) njh: a two point bezier is a line segment (12:31:13) Botty: so its like a parametric thing? (12:31:19) njh: Botty: correct (12:31:30) njh: parametric here means maps from [0,1] to a point (12:31:37) njh: (12:31:38) ACSpike: sbasis is all parametric vector squishyness (12:31:50) njh: yes, most computer graphics is parametric (12:31:59) ACSpike: and squishy (12:32:06) njh: sometimes (12:32:11) njh: sometimes it is all angular (12:39:28) ACSpike: do I need to draw the bezord out? (12:39:39) njh: draw it out? (12:39:41) njh: to the canvas? (12:40:08) njh: no, here is some boilerplate to draw a md_sb to the canvas (12:40:25) njh: void draw_cb(cairo_t *cr, multidim_sbasis<2> const &B) { Geom::PathBuilder pb; subpath_from_sbasis(pb, B, 0.1); cairo_path(cr, pb.peek()); } (12:40:37) njh: add that to gear (12:41:02) njh: perhaps change the name to draw_md_sb or something (12:41:11) njh: then to draw B, just use: (12:41:19) njh: draw_md_sb(cr, B); (12:41:26) njh: (cr is the cairo canvas) (12:41:38) njh: so paste what you have so far (12:41:50) njh: (I mean just your lines, not the whole file!) (12:46:12) ACSpike: random points are in the same spot on every execution? (12:46:31) njh: correct (12:46:36) ACSpike: neat (12:46:48) njh: that's just rand() (12:47:11) ACSpike: wow, the line. it moves. (12:47:16) njh: if you want different positions you start the random number generator in a different spot, using say the current time (12:47:28) njh: can you commit your changes? (12:49:09) ACSpike: yes (12:49:11) ACSpike: done (12:50:24) njh: ok, so we have a single line :) (12:50:35) ACSpike: and a single circle (12:50:46) njh: now the nice thing about lines in this form is we can perform arithmetic on them (12:50:46) ACSpike: but I don't know why we have a line (12:50:54) ACSpike: ok (12:52:14) njh: ok, so now you have some experience with lines, we're going to try to make an arc (12:52:30) njh: remember that a circle is just (12:52:35) ACSpike: why would I perform arithmetic on a line? (12:52:51) njh: because all geometry is arithmetic (12:53:31) njh: so we're going to use two built in functions, sin and cos to make an arc from 0 to 1 radian (12:53:52) njh: SBasis sin(double a0, double a1, int k); SBasis cos(double a0, double a1, int k) (12:54:15) njh: these two functions take a range of angles (a0, a1) and a parameter k (12:54:23) njh: k is the accuracy (12:54:30) njh: for now lets just use k = 2 (12:55:23) njh: so lets make B[0] = BezOrd(centre[0]) + 100*cos(0,1,2); (12:55:29) njh: and similarly Y (12:55:44) ***njh has never tried this before, it might not work :) (12:56:10) ACSpike: I realize you are taking really small really slow steps (12:56:21) ACSpike: but I'm loosing a lot of it (12:56:35) njh: that should make an arc centred at the centre with a radius 100 (12:56:55) njh: perhaps we could convert this conversation into a tutorial when we're finished (12:57:01) ACSpike: do I replace the line? (12:57:06) njh: yeah (12:57:07) ACSpike: make a new arc? (12:57:09) ACSpike: ok (12:57:19) njh: just comment out the line if you like (12:57:25) njh: or you can overwrite it (12:58:02) ACSpike: compiling (13:00:05) ACSpike: http://rafb.net/paste/results/ZXudDC19.html (13:01:26) ACSpike: misplaced parens? (13:02:00) njh: no, missing defn (13:02:03) njh: try (13:02:16) njh: SBasis(BezOrd(centre[0])) + 100*cos(0,1,2); (13:02:40) njh: might be due to std::cos actually (13:02:48) njh: sin and cos are slightly crap (13:03:00) njh: ah, I've got an idea (13:05:37) njh: yep, looks like it will work (13:07:02) ACSpike: indeed it does (13:07:08) ACSpike: now I can draw arcs (13:07:29) ACSpike: ok (13:07:48) ACSpike: at this point I'm gonna copy the backlogs and go to bed (13:08:07) njh: ok! (13:08:09) njh: worked it out (13:08:21) ACSpike: worked what? (13:08:26) njh: I know all this sounds pedestrian (13:08:46) ACSpike: you mean this tutorial? (13:09:03) njh: but perhaps what you aren't realising is that when you write cos(0,1,2) you aren't just computing cos at a single point (13:09:10) ACSpike: right (13:09:12) njh: you are computing cos everywhere at the same time (13:09:16) ACSpike: it the whole sweep (13:09:19) njh: yep (13:09:23) ACSpike: I see that (13:09:31) ACSpike: but I don't "get" it at all :-) (13:09:38) njh: if you run conic-3 you'll see that it converts to beziers automagically (13:09:52) njh: well, do you understand how std::cos(t) works? (13:10:11) ACSpike: I don't even understand the question (13:10:31) njh: well, you wrote cos(x) in your gear program (13:10:36) njh: do you understand how it works? (13:10:38) ACSpike: my math is really rusty (13:10:46) njh: right, yet you managed to draw gears (13:11:02) njh: my point is that understanding how something works isn't entirely necessary to use it (13:11:05) ACSpike: I don't know the definition of the function, but I know the triangle soh cah toa thing (13:11:11) njh: yep (13:11:32) njh: I use floating point all the time. I know exactly how it works,because I once implemented my own version (13:11:41) njh: but 99.9999% of programmers don't (13:11:52) ACSpike: I read the spec once (13:11:53) njh: the same should be true of this new stuff (13:12:13) ACSpike: but I want to grok it because I want to help (13:12:19) njh: you should be able to make an involute without any more than a rough idea of how it works (13:12:29) Botty: I just remember that sin is Y (intuitively opposite), cos is X (intuitively adjacent), and tan is Y / X (13:12:32) njh: I think you will grok it, once you've got the hang of playing withit (13:12:49) njh: we'll get some nice circular arcs going (13:13:01) njh: maybe you can try and come up with a nice interface for circulat arcs (13:13:04) ACSpike: I think right now I could draw all the arcs from the gear (13:13:14) njh: yep, I think so too (13:13:26) njh: and you would get bezier curves at the end, rather than line segments (13:13:36) njh: and I think it would be a lot faster as well (13:13:40) ACSpike: right (13:13:44) njh: (actually, in this case, I doubt it metters :) (13:14:04) ACSpike: curveto or arcto? (13:14:19) njh: curveto, I'm afraid (13:14:31) njh: I would like to pick the best choice, but I haven't worked out how yet (13:14:56) ACSpike: so if I want to draw the involute I need to map that function in there somehow (13:15:04) njh: but you can't represent involutes with arcs anyway (13:15:07) njh: yeah (13:15:13) ACSpike: ah hah (13:15:15) njh: that is basically all there is to it (13:15:24) ACSpike: so this is crazy function plotting (13:15:38) njh: you should theoretically be able to just change the type of your equation to SBasis and use the old code (13:15:57) njh: the only reason you can't do that is because I haven't written all the operator*(,) type functions :) (13:16:19) njh: even more cool is you can compute the derivatives in the same way. that is something you simply can't do with point plotting (13:16:50) njh: for example, if you want the tangent to a bezier path, B, just write derivative(B) (13:17:10) njh: something I played with last night was trying to find the points of maximum and minimum curvature on paths (13:17:14) njh: ('corners') (13:17:29) njh: so I computed the curvature, took the derivative and found where that = 0 (13:17:44) njh: SBasis curvature(multidim_sbasis<2> & B) { multidim_sbasis<2> dB = derivative(B); multidim_sbasis<2> ddB = derivative(dB); SBasis n = multiply(dB[0], ddB[1]) - multiply(dB[1], ddB[0]); SBasis den = multiply(dB[0], dB[0]) + multiply(dB[1], dB[1]); den = multiply(den, den); return divide(multiply(n, sqrt(den, 4)), den, 6); } (13:17:54) njh: that is pretty much the definition off wikipedia (13:18:16) njh: std::vector r = roots(derivative(curvature(B))); (13:18:42) njh: gives r, a list of t values with maximum or minimum curvature