randFromArray([2, 4, 5, 8]) randRange(1, T_DENOM - 1) T_NUMER / T_DENOM fractionReduce(T_NUMER, T_DENOM) floor(8 / T_DENOM)
randRange(-DELTA, DELTA) * T_DENOM randRange(-DELTA, DELTA) * T_DENOM (atan2(DYA, DXA) + PI) % PI
randRange(-DELTA, DELTA) * T_DENOM randRange(-DELTA, DELTA) * T_DENOM (atan2(DYC, DXC) + PI) % PI
randRangeNonZero(-9 - min(0, min(DXA, DXC)), 9 - max(0, max(DXA, DXC))) randRangeNonZero(-9 - min(0, min(DYA, DYC)), 9 - max(0, max(DYA, DYC))) BX + DXA BY + DYA BX + DXC BY + DYC round(AX * (1 - T) + BX * T) round(AY * (1 - T) + BY * T) round(BX * (1 - T) + CX * T) round(BY * (1 - T) + CY * T) QX * (1 - T) + RX * T QY * (1 - T) + RY * T fractionReduce(QX * (T_DENOM - T_NUMER) + RX * T_NUMER, T_DENOM) fractionReduce(QY * (T_DENOM - T_NUMER) + RY * T_NUMER, T_DENOM)

A parabola is created with a string construction from the control points, `A`, `B` and `C`.

What is the coordinate of a point, `P`, if it is `T_FRACTION` of the way along the parabola, from `A` to `C`?

graphInit({ range: 10, scale: 20, tickStep: 1, labelStep: 1, unityLabels: false, labelFormat: function( s ) { return "\\small{" + s + "}"; }, axisArrows: "<->", }); style({ stroke: BLUE, fill: BLUE, strokeWidth: 1.5 }); line([AX, AY], [BX, BY]); line([CX, CY], [BX, BY]); // Construct parabola var points = []; var resolution = 40; for (var i = 0; i <= resolution; i++) { var t = i / resolution; var s = 1 - t; var x = s * s * AX + 2 * s * t * BX + t * t * CX; var y = s * s * AY + 2 * s * t * BY + t * t * CY; points.push([x, y]); } style({ stroke: GREEN, fill: null, strokeWidth: 3 }); path(points); style({ stroke: BLUE, fill: BLUE, color: BLUE, strokeWidth: 1.5 }); circle([AX, AY], 0.15); circle([BX, BY], 0.15); circle([CX, CY], 0.15); var A = [AX, AY]; var B = [BX, BY]; var C = [CX, CY]; var labelA = kvector.normalize(kvector.subtract(A, B)); var labelC = kvector.normalize(kvector.subtract(C, B)); var labelB = kvector.negate(kvector.normalize(kvector.add(labelA, labelC))); label(kvector.add(A, labelA), "A"); label(kvector.add(B, labelB), "B"); label(kvector.add(C, labelC), "C");

`P = (` PX, PY `)`

First find a point, `\pink{Q}`, `T_FRACTION` of the way along `\blue{\overline{AB}}`.

`\pink{Q} = \left(1 - T_FRACTION\right)\blue{A} + \left(T_FRACTION\right)\blue{B}`

`\begin{eqnarray} \pink{Q_x} &=& \left(fractionReduce(T_DENOM - T_NUMER, T_DENOM)\right)\blue{A_x} + \left(T_FRACTION\right)\blue{B_x} \\ &=& \left(fractionReduce(T_DENOM - T_NUMER, T_DENOM)\right)\blue{negParens(AX)} + \left(T_FRACTION\right)\blue{negParens(BX)} \\ &=& fractionReduce((T_DENOM - T_NUMER) * AX, T_DENOM) + fractionReduce(T_NUMER * BX, T_DENOM) = \pink{QX} \end{eqnarray}`

`\begin{eqnarray} \pink{Q_y} &=& \left(fractionReduce(T_DENOM - T_NUMER, T_DENOM)\right)\blue{A_y} + \left(T_FRACTION\right)\blue{B_y} \\ &=& \left(fractionReduce(T_DENOM - T_NUMER, T_DENOM)\right)\blue{negParens(AY)} + \left(T_FRACTION\right)\blue{negParens(BY)} \\ &=& fractionReduce((T_DENOM - T_NUMER) * AY, T_DENOM) + fractionReduce(T_NUMER * BY, T_DENOM) = \pink{QY} \end{eqnarray}`

So `\pink{Q}` is at `(\pink{QX}, \pink{QY})`.

graph.R = [RX, RY]; graph.Q = [QX, QY]; graph.RQ = kvector.normalize(kvector.subtract(graph.R, graph.Q)); style({ stroke: PINK, fill: PINK, color: PINK, strokeWidth: 1.5 }); circle(graph.Q, 0.15); label(kvector.subtract(graph.Q, graph.RQ), "Q");

Find a point, `\pink{R}`, `T_FRACTION` of the way along `\blue{\overline{BC}}`, using the same method.

`\pink{R} = \left(1 - T_FRACTION\right)\blue{B} + \left(T_FRACTION\right)\blue{C}`

`\pink{R}` is at `(\pink{RX}, \pink{RY})`.

circle(graph.R, 0.15); label(kvector.add(graph.R, graph.RQ), "R");

`\green{P}` is `T_FRACTION` of the way along `\pink{\overline{QR}}`.

line([QX, QY], [RX, RY], { stroke: PINK });

`\green{P} = \left(1 - T_FRACTION\right)\pink{Q} + \left(T_FRACTION\right)\pink{R}`

`\green{P}` is at `\left(\green{PX_FRACTION}, \green{PY_FRACTION}\right)`.

style({ stroke: GREEN, fill: GREEN, color: GREEN }); circle([PX, PY], 0.15); label(kvector.add([PX, PY], kvector.rotateDeg(graph.RQ, 90)), "P");