diff --git a/docs/blog/2020-08-28.md b/docs/blog/2020-08-28.md new file mode 100644 index 00000000..def2a0ad --- /dev/null +++ b/docs/blog/2020-08-28.md @@ -0,0 +1,7 @@ +# Rewriting the tech stack + +- started in 2011 as simple webpage with some Processing.js +- complete rewrite to React in 2016 +- web's caught up, and there is no reason to keep things React. This content should work even without JS. + + diff --git a/docs/chapters/intersections/content.en-GB.md b/docs/chapters/intersections/content.en-GB.md index a9c36710..7c6418ad 100644 --- a/docs/chapters/intersections/content.en-GB.md +++ b/docs/chapters/intersections/content.en-GB.md @@ -10,7 +10,7 @@ If we have two line segments with two coordinates each, segments A-B and C-D, we The following graphic implements this intersection detection, showing a red point for an intersection on the lines our segments lie on (thus being a virtual intersection point), and a green point for an intersection that lies on both segments (being a real intersection point). - +
@@ -44,7 +44,9 @@ lli = function(line1, line2): Curve/line intersection is more work, but we've already seen the techniques we need to use in order to perform it: first we translate/rotate both the line and curve together, in such a way that the line coincides with the x-axis. This will position the curve in a way that makes it cross the line at points where its y-function is zero. By doing this, the problem of finding intersections between a curve and a line has now become the problem of performing root finding on our translated/rotated curve, as we already covered in the section on finding extremities. - - +
+ + +
Curve/curve intersection, however, is more complicated. Since we have no straight line to align to, we can't simply align one of the curves and be left with a simple procedure. Instead, we'll need to apply two techniques we've met before: de Casteljau's algorithm, and curve splitting. diff --git a/docs/chapters/intersections/curve-line.js b/docs/chapters/intersections/curve-line.js new file mode 100644 index 00000000..d81095ac --- /dev/null +++ b/docs/chapters/intersections/curve-line.js @@ -0,0 +1,53 @@ +const utils = Bezier.getUtils(); + +let Point = Vector, curve, line; + +setup() { + const type = this.parameters.type ?? `quadratic`; + if (type === `quadratic`) { + curve = Bezier.defaultQuadratic(this); + line = [new Point(15,250), new Point(220,20)]; + } else { + curve = Bezier.defaultCubic(this); + line = [new Point(25,260), new Point(240,55)]; + } + setMovable(curve.points, line); +} + +draw() { + clear(); + + curve.drawSkeleton(); + curve.drawCurve(); + curve.drawPoints(); + + this.drawLine(...line); + + const [p1, p2] = line; + const aligned = utils.align(curve.points, {p1,p2}); + const nB = new Bezier(this, aligned); + const roots = utils.roots(nB.points); + const coords = roots.map(t => curve.get(t)); + + if (roots.length) { + roots.forEach((t,i) => { + var p = coords[i]; + setColor(`magenta`); + circle(p.x, p.y, 3); + setColor(`black`); + text(`t = ${t.toFixed(2)}`, p.x + 5, p.y + 10); + }); + + setFill(`black`); + const cval = coords.map(p => `(${p.x|0},${p.y|0})`).join(`, `); + text(`Intersection${roots.length>=1?`s`:``} at ${cval}`, this.width/2, 15, CENTER); + } +} + +drawLine(p1, p2) { + setStroke(`black`); + line(p1.x, p1.y, p2.x, p2.y); + setStroke( randomColor() ); + circle(p1.x, p1.y, 3); + circle(p2.x, p2.y, 3); +} diff --git a/docs/chapters/intersections/handler.js b/docs/chapters/intersections/handler.js deleted file mode 100644 index cd46de09..00000000 --- a/docs/chapters/intersections/handler.js +++ /dev/null @@ -1,75 +0,0 @@ -var min = Math.min, max = Math.max; - -module.exports = { - setupLines: function(api) { - var curve1 = new api.Bezier([50,50,150,110]); - var curve2 = new api.Bezier([50,250,170,170]); - api.setCurve(curve1, curve2); - }, - - drawLineIntersection: function(api, curves) { - api.reset(); - - var lli = api.utils.lli4; - var p = lli( - curves[0].points[0], - curves[0].points[1], - curves[1].points[0], - curves[1].points[1] - ); - - var mark = 0; - curves.forEach(curve => { - api.drawSkeleton(curve); - api.setColor("black"); - if (p) { - var pts = curve.points, - mx = min(pts[0].x, pts[1].x), - my = min(pts[0].y, pts[1].y), - Mx = max(pts[0].x, pts[1].x), - My = max(pts[0].y, pts[1].y); - if (mx <= p.x && my <= p.y && Mx >= p.x && My >= p.y) { - api.setColor("#00FF00"); - mark++; - } - } - api.drawCurve(curve); - }); - - if (p) { - api.setColor(mark < 2 ? "red" : "#00FF00"); - api.drawCircle(p, 3); - } - }, - - setupQuadratic: function(api) { - var curve1 = api.getDefaultQuadratic(); - var curve2 = new api.Bezier([15,250,220,20]); - api.setCurve(curve1, curve2); - }, - - setupCubic: function(api) { - var curve1 = new api.Bezier([100,240, 30,60, 210,230, 160,30]); - var curve2 = new api.Bezier([25,260, 230,20]); - api.setCurve(curve1, curve2); - }, - - draw: function(api, curves) { - api.reset(); - curves.forEach(curve => { - api.drawSkeleton(curve); - api.drawCurve(curve); - }); - - var utils = api.utils; - var line = { p1: curves[1].points[0], p2: curves[1].points[1] }; - var acpts = utils.align(curves[0].points, line); - var nB = new api.Bezier(acpts); - var roots = utils.roots(nB.points); - roots.forEach(t => { - var p = curves[0].get(t); - api.drawCircle(p, 3); - api.text("t = " + t, {x: p.x + 5, y: p.y + 10}); - }); - } -}; diff --git a/docs/chapters/intersections/line-line.js b/docs/chapters/intersections/line-line.js new file mode 100644 index 00000000..eb022550 --- /dev/null +++ b/docs/chapters/intersections/line-line.js @@ -0,0 +1,61 @@ +let Point = Vector, points = []; + +setup() { + points.push(new Point(50,50)); + points.push(new Point(150,110)); + points.push(new Point(50,250)); + points.push(new Point(170,170)); + setMovable(points); +} + +draw() { + clear(); + const [p1, p2, p3, p4] = points; + + setStroke(`black`); + this.drawLine(p1,p2); + this.drawLine(p3,p4); + + const p = this.lli( + p1.x, p1.y, + p2.x, p2.y, + p3.x, p3.y, + p4.x, p4.y + ); + + if (p) { + if (this.onLine(p, p1, p2) && this.onLine(p, p3, p4)) { + setColor(`lime`); + circle(p.x, p.y, 3); + setFill(`black`); + text(`Intersection at (${p.x|0}, ${p.y|0})`, this.width/2, 15, CENTER); + } else { + setColor(`red`); + circle(p.x, p.y, 3); + } + } +} + +drawLine(p1, p2) { + setColor(`black`); + line(p1.x, p1.y, p2.x, p2.y); + setStroke( randomColor() ); + circle(p1.x, p1.y, 2); + circle(p2.x, p2.y, 2); +} + +lli(x1, y1, x2, y2, x3, y3, x4, y4) { + const nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4), + ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4), + d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); + if (d == 0) return; + return { x: nx / d, y: ny / d }; +} + +onLine(p, p1, p2) { + const mx = min(p1.x, p2.x), + my = min(p1.y, p2.y), + Mx = max(p1.x, p2.x), + My = max(p1.y, p2.y); + return (mx <= p.x && my <= p.y && Mx >= p.x && My >= p.y); +} diff --git a/docs/images/chapters/intersections/594c2df534a1736c03cd3a96ff4a9913.png b/docs/images/chapters/intersections/594c2df534a1736c03cd3a96ff4a9913.png new file mode 100644 index 00000000..04b94995 Binary files /dev/null and b/docs/images/chapters/intersections/594c2df534a1736c03cd3a96ff4a9913.png differ diff --git a/docs/images/chapters/intersections/61876a2bd727df377619c5ad34ce86be.png b/docs/images/chapters/intersections/61876a2bd727df377619c5ad34ce86be.png new file mode 100644 index 00000000..52e23505 Binary files /dev/null and b/docs/images/chapters/intersections/61876a2bd727df377619c5ad34ce86be.png differ diff --git a/docs/images/chapters/intersections/dc26a6063dadc31d242f1c1c8f38bb5e.png b/docs/images/chapters/intersections/dc26a6063dadc31d242f1c1c8f38bb5e.png new file mode 100644 index 00000000..7b2c8a1b Binary files /dev/null and b/docs/images/chapters/intersections/dc26a6063dadc31d242f1c1c8f38bb5e.png differ diff --git a/docs/index.html b/docs/index.html index 4d1edebc..5d0779d9 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1474,7 +1474,11 @@ y = curve.get(t).y

Line-line intersections

If we have two line segments with two coordinates each, segments A-B and C-D, we can find the intersection of the lines these segments are an intervals on by linear algebra, using the procedure outlined in this top coder article. Of course, we need to make sure that the intersection isn't just on the lines our line segments lie on, but actually on our line segments themselves. So after we find the intersection, we need to verify that it lies without the bounds of our original line segments.

The following graphic implements this intersection detection, showing a red point for an intersection on the lines our segments lie on (thus being a virtual intersection point), and a green point for an intersection that lies on both segments (being a real intersection point).

- + + + + Scripts are disabled. Showing fallback image. +
@@ -1501,8 +1505,18 @@ lli = function(line1, line2):

What about curve-line intersections?

Curve/line intersection is more work, but we've already seen the techniques we need to use in order to perform it: first we translate/rotate both the line and curve together, in such a way that the line coincides with the x-axis. This will position the curve in a way that makes it cross the line at points where its y-function is zero. By doing this, the problem of finding intersections between a curve and a line has now become the problem of performing root finding on our translated/rotated curve, as we already covered in the section on finding extremities.

- - +
+ + + + Scripts are disabled. Showing fallback image. + + + + + Scripts are disabled. Showing fallback image. + +

Curve/curve intersection, however, is more complicated. Since we have no straight line to align to, we can't simply align one of the curves and be left with a simple procedure. Instead, we'll need to apply two techniques we've met before: de Casteljau's algorithm, and curve splitting.

diff --git a/docs/ja-JP/index.html b/docs/ja-JP/index.html index 8eb2e3f5..802f7d61 100644 --- a/docs/ja-JP/index.html +++ b/docs/ja-JP/index.html @@ -1471,7 +1471,11 @@ y = curve.get(t).y

Line-line intersections

If we have two line segments with two coordinates each, segments A-B and C-D, we can find the intersection of the lines these segments are an intervals on by linear algebra, using the procedure outlined in this top coder article. Of course, we need to make sure that the intersection isn't just on the lines our line segments lie on, but actually on our line segments themselves. So after we find the intersection, we need to verify that it lies without the bounds of our original line segments.

The following graphic implements this intersection detection, showing a red point for an intersection on the lines our segments lie on (thus being a virtual intersection point), and a green point for an intersection that lies on both segments (being a real intersection point).

- + + + + Scripts are disabled. Showing fallback image. +
@@ -1498,8 +1502,18 @@ lli = function(line1, line2):

What about curve-line intersections?

Curve/line intersection is more work, but we've already seen the techniques we need to use in order to perform it: first we translate/rotate both the line and curve together, in such a way that the line coincides with the x-axis. This will position the curve in a way that makes it cross the line at points where its y-function is zero. By doing this, the problem of finding intersections between a curve and a line has now become the problem of performing root finding on our translated/rotated curve, as we already covered in the section on finding extremities.

- - +
+ + + + Scripts are disabled. Showing fallback image. + + + + + Scripts are disabled. Showing fallback image. + +

Curve/curve intersection, however, is more complicated. Since we have no straight line to align to, we can't simply align one of the curves and be left with a simple procedure. Instead, we'll need to apply two techniques we've met before: de Casteljau's algorithm, and curve splitting.

diff --git a/docs/js/custom-element/api/graphics-api.js b/docs/js/custom-element/api/graphics-api.js index 928ccea7..55ea7b39 100644 --- a/docs/js/custom-element/api/graphics-api.js +++ b/docs/js/custom-element/api/graphics-api.js @@ -128,8 +128,8 @@ class GraphicsAPI extends BaseAPI { if (points) this.setMovable(points); } - setMovable(points) { - points.forEach((p) => this.movable.push(p)); + setMovable(...allpoints) { + allpoints.forEach((points) => points.forEach((p) => this.movable.push(p))); } /** @@ -318,6 +318,22 @@ class GraphicsAPI extends BaseAPI { this.setStroke(false); } + /** + * stroke + fill + */ + setColor(color) { + this.setFill(color); + this.setStroke(color); + } + + /** + * no stroke/fill + */ + noColor() { + this.noFill(); + this.noStroke(); + } + /** * Set a text stroke/color */ diff --git a/docs/zh-CN/index.html b/docs/zh-CN/index.html index 76206b78..aaf9ff09 100644 --- a/docs/zh-CN/index.html +++ b/docs/zh-CN/index.html @@ -1465,7 +1465,11 @@ y = curve.get(t).y

Line-line intersections

If we have two line segments with two coordinates each, segments A-B and C-D, we can find the intersection of the lines these segments are an intervals on by linear algebra, using the procedure outlined in this top coder article. Of course, we need to make sure that the intersection isn't just on the lines our line segments lie on, but actually on our line segments themselves. So after we find the intersection, we need to verify that it lies without the bounds of our original line segments.

The following graphic implements this intersection detection, showing a red point for an intersection on the lines our segments lie on (thus being a virtual intersection point), and a green point for an intersection that lies on both segments (being a real intersection point).

- + + + + Scripts are disabled. Showing fallback image. +
@@ -1492,8 +1496,18 @@ lli = function(line1, line2):

What about curve-line intersections?

Curve/line intersection is more work, but we've already seen the techniques we need to use in order to perform it: first we translate/rotate both the line and curve together, in such a way that the line coincides with the x-axis. This will position the curve in a way that makes it cross the line at points where its y-function is zero. By doing this, the problem of finding intersections between a curve and a line has now become the problem of performing root finding on our translated/rotated curve, as we already covered in the section on finding extremities.

- - +
+ + + + Scripts are disabled. Showing fallback image. + + + + + Scripts are disabled. Showing fallback image. + +

Curve/curve intersection, however, is more complicated. Since we have no straight line to align to, we can't simply align one of the curves and be left with a simple procedure. Instead, we'll need to apply two techniques we've met before: de Casteljau's algorithm, and curve splitting.

diff --git a/src/build/markdown/preprocess-graphics-element.js b/src/build/markdown/preprocess-graphics-element.js index ceec89b0..600e2abe 100644 --- a/src/build/markdown/preprocess-graphics-element.js +++ b/src/build/markdown/preprocess-graphics-element.js @@ -57,6 +57,12 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) { /width="([^"]+)"\s+height="([^"]+)"\s+src="([^"]+)"\s*([^>]*)>/ ); + if (!terms) { + throw new Error( + `Bad markup for while parsing:\n${updated}` + ); + } + const [original, width, height, _, remainder] = terms; let src = terms[3];