mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-31 03:59:58 +02:00
this rename is absolutely stupid
This commit is contained in:
10
docs/chapters/tightbounds/content.en-GB.md
Normal file
10
docs/chapters/tightbounds/content.en-GB.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Tight bounding boxes
|
||||
|
||||
With our knowledge of bounding boxes, and curve alignment, We can now form the "tight" bounding box for curves. We first align our curve, recording the translation we performed, "T", and the rotation angle we used, "R". We then determine the aligned curve's normal bounding box. Once we have that, we can map that bounding box back to our original curve by rotating it by -R, and then translating it by -T.
|
||||
|
||||
We now have nice tight bounding boxes for our curves:
|
||||
|
||||
<graphics-element title="Aligning a quadratic curve" src="./quadratic.js"></graphics-element>
|
||||
<graphics-element title="Aligning a cubic curve" src="./cubic.js"></graphics-element>
|
||||
|
||||
These are, strictly speaking, not necessarily the tightest possible bounding boxes. It is possible to compute the optimal bounding box by determining which spanning lines we need to effect a minimal box area, but because of the parametric nature of Bézier curves this is actually a rather costly operation, and the gain in bounding precision is often not worth it.
|
79
docs/chapters/tightbounds/cubic.js
Normal file
79
docs/chapters/tightbounds/cubic.js
Normal file
@@ -0,0 +1,79 @@
|
||||
setup() {
|
||||
const curve = this.curve = Bezier.defaultCubic(this);
|
||||
curve.points[2].x = 210;
|
||||
setMovable(curve.points);
|
||||
}
|
||||
|
||||
draw() {
|
||||
const curve = this.curve;
|
||||
|
||||
clear();
|
||||
curve.drawSkeleton();
|
||||
curve.drawCurve();
|
||||
curve.drawPoints();
|
||||
|
||||
let translated = this.translatePoints(curve.points);
|
||||
let rotated = this.rotatePoints(translated);
|
||||
let rtcurve = new Bezier(this, rotated);
|
||||
let extrema = rtcurve.extrema();
|
||||
|
||||
let minx = Number.MAX_SAFE_INTEGER,
|
||||
miny = minx,
|
||||
maxx = Number.MIN_SAFE_INTEGER,
|
||||
maxy = maxx;
|
||||
|
||||
setStroke(`red`);
|
||||
|
||||
[0, ...extrema.x, ...extrema.y, 1].forEach(t => {
|
||||
let p = curve.get(t);
|
||||
let rtp = rtcurve.get(t);
|
||||
if (rtp.x < minx) minx = rtp.x;
|
||||
if (rtp.x > maxx) maxx = rtp.x;
|
||||
if (rtp.y < miny) miny = rtp.y;
|
||||
if (rtp.y > maxy) maxy = rtp.y;
|
||||
if (t > 0 && t< 1) circle(p.x, p.y, 3);
|
||||
});
|
||||
|
||||
noFill();
|
||||
setStroke(`#0F0`);
|
||||
|
||||
let tx = curve.points[0].x;
|
||||
let ty = curve.points[0].y;
|
||||
let a = rotated[0].a;
|
||||
|
||||
start();
|
||||
vertex(tx + minx * cos(a) - miny * sin(a), ty + minx * sin(a) + miny * cos(a));
|
||||
vertex(tx + maxx * cos(a) - miny * sin(a), ty + maxx * sin(a) + miny * cos(a));
|
||||
vertex(tx + maxx * cos(a) - maxy * sin(a), ty + maxx * sin(a) + maxy * cos(a));
|
||||
vertex(tx + minx * cos(a) - maxy * sin(a), ty + minx * sin(a) + maxy * cos(a));
|
||||
end(true);
|
||||
}
|
||||
|
||||
translatePoints(points) {
|
||||
// translate to (0,0)
|
||||
let m = points[0];
|
||||
return points.map(v => {
|
||||
return {
|
||||
x: v.x - m.x,
|
||||
y: v.y - m.y
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
rotatePoints(points) {
|
||||
// rotate so that last point is (...,0)
|
||||
let dx = points[3].x;
|
||||
let dy = points[3].y;
|
||||
let a = atan2(dy, dx);
|
||||
return points.map(v => {
|
||||
return {
|
||||
a: a,
|
||||
x: v.x * cos(-a) - v.y * sin(-a),
|
||||
y: v.x * sin(-a) + v.y * cos(-a)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onMouseMove() {
|
||||
redraw();
|
||||
}
|
78
docs/chapters/tightbounds/quadratic.js
Normal file
78
docs/chapters/tightbounds/quadratic.js
Normal file
@@ -0,0 +1,78 @@
|
||||
setup() {
|
||||
this.curve = Bezier.defaultQuadratic(this);
|
||||
setMovable(this.curve.points);
|
||||
}
|
||||
|
||||
draw() {
|
||||
const curve = this.curve;
|
||||
|
||||
clear();
|
||||
curve.drawSkeleton();
|
||||
curve.drawCurve();
|
||||
curve.drawPoints();
|
||||
|
||||
let translated = this.translatePoints(curve.points);
|
||||
let rotated = this.rotatePoints(translated);
|
||||
let rtcurve = new Bezier(this, rotated);
|
||||
let extrema = rtcurve.extrema();
|
||||
|
||||
let minx = Number.MAX_SAFE_INTEGER,
|
||||
miny = minx,
|
||||
maxx = Number.MIN_SAFE_INTEGER,
|
||||
maxy = maxx;
|
||||
|
||||
setStroke(`red`);
|
||||
|
||||
[0, ...extrema.x, ...extrema.y, 1].forEach(t => {
|
||||
let p = curve.get(t);
|
||||
let rtp = rtcurve.get(t);
|
||||
if (rtp.x < minx) minx = rtp.x;
|
||||
if (rtp.x > maxx) maxx = rtp.x;
|
||||
if (rtp.y < miny) miny = rtp.y;
|
||||
if (rtp.y > maxy) maxy = rtp.y;
|
||||
if (t > 0 && t< 1) circle(p.x, p.y, 3);
|
||||
});
|
||||
|
||||
noFill();
|
||||
setStroke(`#0F0`);
|
||||
|
||||
let tx = curve.points[0].x;
|
||||
let ty = curve.points[0].y;
|
||||
let a = rotated[0].a;
|
||||
|
||||
start();
|
||||
vertex(tx + minx * cos(a) - miny * sin(a), ty + minx * sin(a) + miny * cos(a));
|
||||
vertex(tx + maxx * cos(a) - miny * sin(a), ty + maxx * sin(a) + miny * cos(a));
|
||||
vertex(tx + maxx * cos(a) - maxy * sin(a), ty + maxx * sin(a) + maxy * cos(a));
|
||||
vertex(tx + minx * cos(a) - maxy * sin(a), ty + minx * sin(a) + maxy * cos(a));
|
||||
end(true);
|
||||
}
|
||||
|
||||
translatePoints(points) {
|
||||
// translate to (0,0)
|
||||
let m = points[0];
|
||||
return points.map(v => {
|
||||
return {
|
||||
x: v.x - m.x,
|
||||
y: v.y - m.y
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
rotatePoints(points) {
|
||||
// rotate so that last point is (...,0)
|
||||
let dx = points[2].x;
|
||||
let dy = points[2].y;
|
||||
let a = atan2(dy, dx);
|
||||
return points.map(v => {
|
||||
return {
|
||||
a: a,
|
||||
x: v.x * cos(-a) - v.y * sin(-a),
|
||||
y: v.x * sin(-a) + v.y * cos(-a)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onMouseMove() {
|
||||
redraw();
|
||||
}
|
Reference in New Issue
Block a user