1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-22 16:23:12 +02:00

intersections

This commit is contained in:
Pomax
2020-08-29 08:40:36 -07:00
parent 4e34774afb
commit bdc7c4228d
13 changed files with 201 additions and 89 deletions

7
docs/blog/2020-08-28.md Normal file
View 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.

View File

@@ -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). 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"> <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. 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}/> <div class="figure">
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/> <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. 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.

View 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);
}

View File

@@ -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});
});
}
};

View 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

View File

@@ -1474,7 +1474,11 @@ y = curve.get(t).y</code></pre>
<h3>Line-line intersections</h3> <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>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> <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"> <div class="howtocode">
@@ -1501,8 +1505,18 @@ lli = function(line1, line2):
<h3>What about curve-line intersections?</h3> <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> <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}/> <div class="figure">
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/> <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> <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>

View File

@@ -1471,7 +1471,11 @@ y = curve.get(t).y</code></pre>
<h3>Line-line intersections</h3> <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>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> <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"> <div class="howtocode">
@@ -1498,8 +1502,18 @@ lli = function(line1, line2):
<h3>What about curve-line intersections?</h3> <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> <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}/> <div class="figure">
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/> <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> <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>

View File

@@ -128,8 +128,8 @@ class GraphicsAPI extends BaseAPI {
if (points) this.setMovable(points); if (points) this.setMovable(points);
} }
setMovable(points) { setMovable(...allpoints) {
points.forEach((p) => this.movable.push(p)); allpoints.forEach((points) => points.forEach((p) => this.movable.push(p)));
} }
/** /**
@@ -318,6 +318,22 @@ class GraphicsAPI extends BaseAPI {
this.setStroke(false); 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 * Set a text stroke/color
*/ */

View File

@@ -1465,7 +1465,11 @@ y = curve.get(t).y</code></pre>
<h3>Line-line intersections</h3> <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>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> <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"> <div class="howtocode">
@@ -1492,8 +1496,18 @@ lli = function(line1, line2):
<h3>What about curve-line intersections?</h3> <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> <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}/> <div class="figure">
<Graphic title="Cubic curve/line intersections" setup={this.setupCubic} draw={this.draw}/> <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> <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>

View File

@@ -57,6 +57,12 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) {
/width="([^"]+)"\s+height="([^"]+)"\s+src="([^"]+)"\s*([^>]*)>/ /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; const [original, width, height, _, remainder] = terms;
let src = terms[3]; let src = terms[3];