/* This was originally my head.typ file from 3rd semester of calculus. * But I stripped all the math formatting stuff. * */ #import calc #let norm-vec2(A) = calc.sqrt(A.at(0) * A.at(0) + A.at(1) * A.at(1)) #let rotate-vec2(V, angle) = ( calc.cos(angle) * V.at(0) + calc.sin(angle) * V.at(1), -calc.sin(angle) * V.at(0) + calc.cos(angle) * V.at(1) ) #let rotate-vec2-90deg(V) = (V.at(1), -V.at(0)) #let mul-vec2-scal(A, b) = (A.at(0) * b, A.at(1) * b) #let add-vec2(A, B) = (A.at(0) + B.at(0), A.at(1) + B.at(1)) #let sub-vec2(A, B) = (A.at(0) - B.at(0), A.at(1) - B.at(1)) #let make-length-vec2(fv) = mul-vec2-scal(fv, 1pt) #let draw-something(cnt) = place(top + left, dx: 0pt, dy: 0pt, cnt) #let draw-line(start, end, stroke: black) = draw-something( line(start: make-length-vec2(start), end: make-length-vec2(end), stroke: stroke)) #let draw-arrow-head(start, end, arm-sz: 4.5, stroke: black) = { let d = sub-vec2(start, end) let L = norm-vec2(d) let arrow_angle = calc.pi * 3/16 let a1 = rotate-vec2(d, -arrow_angle) let a2 = rotate-vec2(d, arrow_angle) if (L > arm-sz){ a1 = mul-vec2-scal(a1, arm-sz/L) a2 = mul-vec2-scal(a2, arm-sz/L) } let tg_end = make-length-vec2(end) let tg_a1 = make-length-vec2(a1) let tg_a2 = make-length-vec2(a2) show line: draw-something line(start: add-vec2(tg_end, tg_a1), end: tg_end, stroke: stroke) line(start: add-vec2(tg_end, tg_a2), end: tg_end, stroke: stroke) } #let draw-arrow(start, end, stroke: black) = { let tg_start = make-length-vec2(start) let tg_end = make-length-vec2(end) show line: draw-something line(start: tg_start, end:tg_end, stroke: stroke) draw-arrow-head(start, end, stroke: stroke) } #let draw-content(pos, cnt) = place(top + left, dx: pos.at(0) * 1pt, dy: pos.at(1) * 1pt, cnt) #let linp(A1, B1, A2, B2, x) = (x - A1) * (B2 - A2) / (B1 - A1) + A2 #let CSCpos2pac(csc, pan_dim, pos) = ( linp(csc.X_at_left, csc.X_at_right, 0, pan_dim.at(0), pos.at(0)), linp(csc.Y_at_bottom, csc.Y_at_top, pan_dim.at(1), 0, pos.at(1)) ) #let draw-coordinate-system(csc, pan_dim, Ox_marks: (), Oy_marks: (), x_name: $x$, y_name: $y$) = { let pac_y_of_Ox = linp(csc.Y_at_top, csc.Y_at_bottom, 0, pan_dim.at(1), 0) let Ox_enters_pac = (0, pac_y_of_Ox) let Ox_leaves_pac = (pan_dim.at(0), pac_y_of_Ox) let pac_x_of_Oy = linp(csc.X_at_left, csc.X_at_right, 0, pan_dim.at(0), 0) let Oy_enters_pac = (pac_x_of_Oy, pan_dim.at(1)) let Oy_leaves_pac = (pac_x_of_Oy, 0) draw-arrow(Ox_enters_pac, Ox_leaves_pac) draw-arrow(Oy_enters_pac, Oy_leaves_pac) let funny_offset_Ox = (-5, 2) let funny_offset_Oy = (3, -6) for (val, cnt) in Ox_marks { let pan_pac = CSCpos2pac(csc, pan_dim, (val, 0)) draw-line(add-vec2(pan_pac, (0, 2)), add-vec2(pan_pac, (0, -2))) draw-content(add-vec2(pan_pac, funny_offset_Ox), cnt) } for (val, cnt) in Oy_marks { let pan_pac = CSCpos2pac(csc, pan_dim, (0, val)) draw-line(add-vec2(pan_pac, (2, 0)), add-vec2(pan_pac, (-2, 0))) draw-content(add-vec2(pan_pac, funny_offset_Oy), cnt) } draw-content(add-vec2(Ox_leaves_pac, funny_offset_Ox), x_name) draw-content(add-vec2(Oy_leaves_pac, funny_offset_Oy), y_name) } #let fix-csc(csc, pan_dim) = { let X_at_left = csc.at("X_at_left", default: none) let X_at_right = csc.at("X_at_right", default: none) let Y_at_bottom = csc.at("Y_at_bottom", default: none) let Y_at_top = csc.at("Y_at_top", default: none) let goodX = X_at_left != none and X_at_right != none let goodY = Y_at_bottom != none and Y_at_top != none if ((not goodX) and (not goodY)){ panic("This is wrong") } if (goodX and goodY) { } else if (goodX){ let yd = (X_at_right - X_at_left) * pan_dim.at(1) / pan_dim.at(0) if (Y_at_bottom != none){ csc.Y_at_top = Y_at_bottom + yd } else if (Y_at_top != none){ csc.Y_at_bottom = Y_at_top - yd } else { csc.Y_at_bottom = -yd/2 csc.Y_at_top = yd/2 } } else if (goodY){ let xd = (Y_at_top - Y_at_bottom) * pan_dim.at(0) / pan_dim.at(1) if (X_at_left != none){ csc.X_at_right = X_at_left + xd } else if (A_at_right != none){ csc.X_at_left = X_at_right - xd } else { csc.X_at_left = -xd/2 csc.X_at_right = xd/2 } } return csc } // csc is linear coordinate system configurration for display on panel #let plot-function-nocheck(csc, pan_dim, func, stroke: black+1pt) = { let points = range(0, calc.floor(pan_dim.at(0)) + 1).map((x_pac) => { let x = linp(0, pan_dim.at(0), csc.X_at_left, csc.X_at_right, x_pac) let y = func(x) let y_pac = linp(csc.Y_at_bottom, csc.Y_at_top, pan_dim.at(1), 0, y) (x_pac * 1pt, y_pac * 1pt) }) draw-something(path(stroke: stroke, ..points)) } #let plot-path-nocheck(csc, pan_dim, ..points, stroke: black) = { draw-something(path(stroke: stroke, ..(points).pos().map(point => make-length-vec2(CSCpos2pac(csc, pan_dim, point))))) } #let plot-closed-figure-nocheck(csc, pan_dim, ..points, stroke: black, fill: none) = { draw-something(path(stroke: stroke, fill: fill, closed: true, ..(points).pos().map(point => make-length-vec2(CSCpos2pac(csc, pan_dim, point))))) } #let ensureTypeRelative(x) = { if type(x) == relative { return x } else if type(x) == ratio { return x + 0pt } else if type(x) == length { return x + 0% } panic("Not supported") } #let drawing-rectangle(ab_width, ab_height, drawing_function, stroke: none) = context { let rl_width = ensureTypeRelative(ab_width) let rl_height = ensureTypeRelative(ab_height) layout(size => { let dim = ( (rl_width.ratio * size.width + rl_width.length.to-absolute()).pt(), (rl_height.ratio * size.height + rl_height.length.to-absolute()).pt() ) rect(width: rl_width, height: rl_height, inset: 0pt, stroke: stroke, drawing_function(dim)) }) }