mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-22 16:23:12 +02:00
intersections
This commit is contained in:
7
docs/blog/2020-08-28.md
Normal file
7
docs/blog/2020-08-28.md
Normal file
@@ -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.
|
||||
|
||||
|
@@ -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).
|
||||
|
||||
<Graphic title="Line/line intersections" setup={this.setupLines} draw={this.drawLineIntersection} />
|
||||
<graphics-element title="Line/line intersections" src="./line-line.js"></graphics-element>
|
||||
|
||||
<div class="howtocode">
|
||||
|
||||
@@ -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.
|
||||
|
||||
<Graphic title="Quadratic curve/line intersections" setup={this.setupQuadratic} draw={this.draw}/>
|
||||
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/>
|
||||
<div class="figure">
|
||||
<graphics-element title="Quadratic curve/line intersections" src="./curve-line.js" data-type="quadratic"></graphics-element>
|
||||
<graphics-element title="Cubic curve/line intersections" src="./curve-line.js" data-type="cubic"></graphics-element>
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
53
docs/chapters/intersections/curve-line.js
Normal file
53
docs/chapters/intersections/curve-line.js
Normal file
@@ -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);
|
||||
}
|
@@ -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});
|
||||
});
|
||||
}
|
||||
};
|
61
docs/chapters/intersections/line-line.js
Normal file
61
docs/chapters/intersections/line-line.js
Normal file
@@ -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);
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@@ -1474,7 +1474,11 @@ y = curve.get(t).y</code></pre>
|
||||
<h3>Line-line intersections</h3>
|
||||
<p>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 <a href="http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2#line_line_intersection">top coder</a> 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.</p>
|
||||
<p>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).</p>
|
||||
<Graphic title="Line/line intersections" setup={this.setupLines} draw={this.drawLineIntersection} />
|
||||
<graphics-element title="Line/line intersections" width="275" height="275" src="./chapters/intersections/line-line.js" >
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\61876a2bd727df377619c5ad34ce86be.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
|
||||
<div class="howtocode">
|
||||
|
||||
@@ -1501,8 +1505,18 @@ lli = function(line1, line2):
|
||||
|
||||
<h3>What about curve-line intersections?</h3>
|
||||
<p>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.</p>
|
||||
<Graphic title="Quadratic curve/line intersections" setup={this.setupQuadratic} draw={this.draw}/>
|
||||
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/>
|
||||
<div class="figure">
|
||||
<graphics-element title="Quadratic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="quadratic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\594c2df534a1736c03cd3a96ff4a9913.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
<graphics-element title="Cubic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="cubic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\dc26a6063dadc31d242f1c1c8f38bb5e.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
@@ -1471,7 +1471,11 @@ y = curve.get(t).y</code></pre>
|
||||
<h3>Line-line intersections</h3>
|
||||
<p>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 <a href="http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2#line_line_intersection">top coder</a> 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.</p>
|
||||
<p>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).</p>
|
||||
<Graphic title="Line/line intersections" setup={this.setupLines} draw={this.drawLineIntersection} />
|
||||
<graphics-element title="Line/line intersections" width="275" height="275" src="./chapters/intersections/line-line.js" >
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\61876a2bd727df377619c5ad34ce86be.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
|
||||
<div class="howtocode">
|
||||
|
||||
@@ -1498,8 +1502,18 @@ lli = function(line1, line2):
|
||||
|
||||
<h3>What about curve-line intersections?</h3>
|
||||
<p>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.</p>
|
||||
<Graphic title="Quadratic curve/line intersections" setup={this.setupQuadratic} draw={this.draw}/>
|
||||
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/>
|
||||
<div class="figure">
|
||||
<graphics-element title="Quadratic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="quadratic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\594c2df534a1736c03cd3a96ff4a9913.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
<graphics-element title="Cubic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="cubic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\dc26a6063dadc31d242f1c1c8f38bb5e.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -1465,7 +1465,11 @@ y = curve.get(t).y</code></pre>
|
||||
<h3>Line-line intersections</h3>
|
||||
<p>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 <a href="http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2#line_line_intersection">top coder</a> 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.</p>
|
||||
<p>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).</p>
|
||||
<Graphic title="Line/line intersections" setup={this.setupLines} draw={this.drawLineIntersection} />
|
||||
<graphics-element title="Line/line intersections" width="275" height="275" src="./chapters/intersections/line-line.js" >
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\61876a2bd727df377619c5ad34ce86be.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
|
||||
<div class="howtocode">
|
||||
|
||||
@@ -1492,8 +1496,18 @@ lli = function(line1, line2):
|
||||
|
||||
<h3>What about curve-line intersections?</h3>
|
||||
<p>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.</p>
|
||||
<Graphic title="Quadratic curve/line intersections" setup={this.setupQuadratic} draw={this.draw}/>
|
||||
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/>
|
||||
<div class="figure">
|
||||
<graphics-element title="Quadratic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="quadratic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\594c2df534a1736c03cd3a96ff4a9913.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
<graphics-element title="Cubic curve/line intersections" width="275" height="275" src="./chapters/intersections/curve-line.js" data-type="cubic">
|
||||
<fallback-image>
|
||||
<img width="275px" height="275px" src="images\chapters\intersections\dc26a6063dadc31d242f1c1c8f38bb5e.png" loading="lazy">
|
||||
Scripts are disabled. Showing fallback image.
|
||||
</fallback-image></graphics-element>
|
||||
</div>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
|
@@ -57,6 +57,12 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) {
|
||||
/width="([^"]+)"\s+height="([^"]+)"\s+src="([^"]+)"\s*([^>]*)>/
|
||||
);
|
||||
|
||||
if (!terms) {
|
||||
throw new Error(
|
||||
`Bad markup for <graphics-element> while parsing:\n${updated}`
|
||||
);
|
||||
}
|
||||
|
||||
const [original, width, height, _, remainder] = terms;
|
||||
|
||||
let src = terms[3];
|
||||
|
Reference in New Issue
Block a user