mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-09-02 12:54:23 +02:00
pointvectors
This commit is contained in:
@@ -73,6 +73,6 @@ treated as a sequence of three (elementary) shear operations. When we combine th
|
|||||||
The following two graphics show the tangent and normal along a quadratic and cubic curve, with the direction vector coloured blue, and the normal vector coloured red (the markers are spaced out evenly as *t*-intervals, not spaced equidistant).
|
The following two graphics show the tangent and normal along a quadratic and cubic curve, with the direction vector coloured blue, and the normal vector coloured red (the markers are spaced out evenly as *t*-intervals, not spaced equidistant).
|
||||||
|
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<Graphic title="Quadratic Bézier tangents and normals" inline={true} setup={this.setupQuadratic} draw={this.draw}/>
|
<graphics-element title="Quadratic Bézier tangents and normals" src="./quadratic.js"></graphics-element>
|
||||||
<Graphic title="Cubic Bézier tangents and normals" inline={true} setup={this.setupCubic} draw={this.draw}/>
|
<graphics-element title="Cubic Bézier tangents and normals" src="./cubic.js"></graphics-element>
|
||||||
</div>
|
</div>
|
||||||
|
67
chapters/pointvectors/cubic.js
Normal file
67
chapters/pointvectors/cubic.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
setup() {
|
||||||
|
this.curve = Bezier.defaultCubic(this);
|
||||||
|
setMovable(this.curve.points);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
clear();
|
||||||
|
const curve = this.curve;
|
||||||
|
curve.drawSkeleton();
|
||||||
|
const pts = curve.points;
|
||||||
|
const f = 15;
|
||||||
|
|
||||||
|
for(let i=0; i<=10; i++) {
|
||||||
|
let t = i/10.0;
|
||||||
|
let p = curve.get(t);
|
||||||
|
let d = this.getDerivative(t, pts);
|
||||||
|
|
||||||
|
let m = sqrt(d.x*d.x + d.y*d.y);
|
||||||
|
d = { x: d.x/m, y: d.y/m };
|
||||||
|
let n = this.getNormal(t, d);
|
||||||
|
|
||||||
|
setStroke(`blue`);
|
||||||
|
line(p.x, p.y, p.x + d.x*f, p.y + d.y*f);
|
||||||
|
|
||||||
|
setStroke(`red`);
|
||||||
|
line(p.x, p.y, p.x + n.x*f, p.y + n.y*f);
|
||||||
|
|
||||||
|
setStroke(`purple`);
|
||||||
|
line(p.x, p.y, p.x - n.x*f, p.y - n.y*f);
|
||||||
|
|
||||||
|
setStroke(`black`);
|
||||||
|
circle(p.x, p.y, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
curve.drawPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDerivative(t, points) {
|
||||||
|
let mt = (1 - t), a = mt*mt, b = mt*t, c = t*t, d = [
|
||||||
|
{
|
||||||
|
x: 3 * (points[1].x - points[0].x),
|
||||||
|
y: 3 * (points[1].y - points[0].y)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 3 * (points[2].x - points[1].x),
|
||||||
|
y: 3 * (points[2].y - points[1].y)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 3 * (points[3].x - points[2].x),
|
||||||
|
y: 3 * (points[3].y - points[2].y)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: a * d[0].x + b * d[1].x + c * d[2].x,
|
||||||
|
y: a * d[0].y + b * d[1].y + c * d[2].y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getNormal(t, d) {
|
||||||
|
const q = sqrt(d.x * d.x + d.y * d.y);
|
||||||
|
return { x: -d.y / q, y: d.x / q };
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseMove() {
|
||||||
|
redraw();
|
||||||
|
}
|
63
chapters/pointvectors/quadratic.js
Normal file
63
chapters/pointvectors/quadratic.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
setup() {
|
||||||
|
this.curve = Bezier.defaultQuadratic(this);
|
||||||
|
setMovable(this.curve.points);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
clear();
|
||||||
|
const curve = this.curve;
|
||||||
|
curve.drawSkeleton();
|
||||||
|
const pts = curve.points;
|
||||||
|
const f = 15;
|
||||||
|
|
||||||
|
for(let i=0; i<=10; i++) {
|
||||||
|
let t = i/10.0;
|
||||||
|
let p = curve.get(t);
|
||||||
|
let d = this.getDerivative(t, pts);
|
||||||
|
|
||||||
|
let m = sqrt(d.x*d.x + d.y*d.y);
|
||||||
|
d = { x: d.x/m, y: d.y/m };
|
||||||
|
let n = this.getNormal(t, d);
|
||||||
|
|
||||||
|
setStroke(`blue`);
|
||||||
|
line(p.x, p.y, p.x + d.x*f, p.y + d.y*f);
|
||||||
|
|
||||||
|
setStroke(`red`);
|
||||||
|
line(p.x, p.y, p.x + n.x*f, p.y + n.y*f);
|
||||||
|
|
||||||
|
setStroke(`purple`);
|
||||||
|
line(p.x, p.y, p.x - n.x*f, p.y - n.y*f);
|
||||||
|
|
||||||
|
setStroke(`black`);
|
||||||
|
circle(p.x, p.y, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
curve.drawPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDerivative(t, points) {
|
||||||
|
let mt = (1 - t), d = [
|
||||||
|
{
|
||||||
|
x: 2 * (points[1].x - points[0].x),
|
||||||
|
y: 2 * (points[1].y - points[0].y)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: 2 * (points[2].x - points[1].x),
|
||||||
|
y: 2 * (points[2].y - points[1].y)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: mt * d[0].x + t * d[1].x,
|
||||||
|
y: mt * d[0].y + t * d[1].y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getNormal(t, d) {
|
||||||
|
const q = sqrt(d.x * d.x + d.y * d.y);
|
||||||
|
return { x: -d.y / q, y: d.x / q };
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseMove() {
|
||||||
|
redraw();
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
40
index.html
40
index.html
@@ -2586,18 +2586,38 @@ function drawCurve(points[], t):
|
|||||||
evenly as <em>t</em>-intervals, not spaced equidistant).
|
evenly as <em>t</em>-intervals, not spaced equidistant).
|
||||||
</p>
|
</p>
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<Graphic
|
<graphics-element
|
||||||
title="Quadratic Bézier tangents and normals"
|
title="Quadratic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupQuadratic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/quadratic.js"
|
||||||
/>
|
>
|
||||||
<Graphic
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\3158c82ea512f70ec17d4a1ce2e7c7b2.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
|
<graphics-element
|
||||||
title="Cubic Bézier tangents and normals"
|
title="Cubic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupCubic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/cubic.js"
|
||||||
/>
|
>
|
||||||
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\05a1ee3b81a4838292814a7097b4cf50.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="pointvectors3d">
|
<section id="pointvectors3d">
|
||||||
|
@@ -2180,18 +2180,38 @@ function drawCurve(points[], t):
|
|||||||
evenly as <em>t</em>-intervals, not spaced equidistant).
|
evenly as <em>t</em>-intervals, not spaced equidistant).
|
||||||
</p>
|
</p>
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<Graphic
|
<graphics-element
|
||||||
title="Quadratic Bézier tangents and normals"
|
title="Quadratic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupQuadratic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/quadratic.js"
|
||||||
/>
|
>
|
||||||
<Graphic
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\3158c82ea512f70ec17d4a1ce2e7c7b2.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
|
<graphics-element
|
||||||
title="Cubic Bézier tangents and normals"
|
title="Cubic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupCubic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/cubic.js"
|
||||||
/>
|
>
|
||||||
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\05a1ee3b81a4838292814a7097b4cf50.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="pointvectors3d">
|
<section id="pointvectors3d">
|
||||||
|
@@ -200,7 +200,7 @@ class BaseAPI {
|
|||||||
*/
|
*/
|
||||||
setup() {
|
setup() {
|
||||||
// console.log(`setup`);
|
// console.log(`setup`);
|
||||||
this.moveable = [];
|
this.movable = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -72,8 +72,8 @@ class GraphicsAPI extends BaseAPI {
|
|||||||
? TOUCH_PRECISION_ZONE
|
? TOUCH_PRECISION_ZONE
|
||||||
: MOUSE_PRECISION_ZONE;
|
: MOUSE_PRECISION_ZONE;
|
||||||
|
|
||||||
for (let i = 0, e = this.moveable.length, p, d; i < e; i++) {
|
for (let i = 0, e = this.movable.length, p, d; i < e; i++) {
|
||||||
p = this.moveable[i];
|
p = this.movable[i];
|
||||||
d = new Vector(p).dist(this.cursor);
|
d = new Vector(p).dist(this.cursor);
|
||||||
if (d <= cdist) {
|
if (d <= cdist) {
|
||||||
this.currentPoint = p;
|
this.currentPoint = p;
|
||||||
@@ -88,8 +88,8 @@ class GraphicsAPI extends BaseAPI {
|
|||||||
this.currentPoint.x = this.cursor.x;
|
this.currentPoint.x = this.cursor.x;
|
||||||
this.currentPoint.y = this.cursor.y;
|
this.currentPoint.y = this.cursor.y;
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0, e = this.moveable.length, p; i < e; i++) {
|
for (let i = 0, e = this.movable.length, p; i < e; i++) {
|
||||||
p = this.moveable[i];
|
p = this.movable[i];
|
||||||
if (new Vector(p).dist(this.cursor) <= 5) {
|
if (new Vector(p).dist(this.cursor) <= 5) {
|
||||||
this.setCursor(this.HAND);
|
this.setCursor(this.HAND);
|
||||||
return; // NOTE: this is a return, not a break.
|
return; // NOTE: this is a return, not a break.
|
||||||
@@ -105,12 +105,12 @@ class GraphicsAPI extends BaseAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetMovable(points) {
|
resetMovable(points) {
|
||||||
this.moveable.splice(0, this.moveable.length);
|
this.movable.splice(0, this.movable.length);
|
||||||
if (points) this.setMovable(points);
|
if (points) this.setMovable(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMovable(points) {
|
setMovable(points) {
|
||||||
points.forEach((p) => this.moveable.push(p));
|
points.forEach((p) => this.movable.push(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -10,7 +10,9 @@ const __root = path.join(__dirname, `..`, `..`, `..`);
|
|||||||
/**
|
/**
|
||||||
* ...docs go here...
|
* ...docs go here...
|
||||||
*/
|
*/
|
||||||
async function generateFallbackImage(src, width, height) {
|
async function generateFallbackImage(localeStrings, src, width, height) {
|
||||||
|
const locale = localeStrings.getCurrentLocale();
|
||||||
|
|
||||||
// Get the sketch code
|
// Get the sketch code
|
||||||
const sourcePath = path.join(__root, src);
|
const sourcePath = path.join(__root, src);
|
||||||
let code;
|
let code;
|
||||||
@@ -23,6 +25,9 @@ async function generateFallbackImage(src, width, height) {
|
|||||||
|
|
||||||
// Do we need to even generate a file here?
|
// Do we need to even generate a file here?
|
||||||
const hash = createHash(`md5`).update(code).digest(`hex`);
|
const hash = createHash(`md5`).update(code).digest(`hex`);
|
||||||
|
|
||||||
|
if (locale !== localeStrings.getDefaultLocale()) return hash;
|
||||||
|
|
||||||
const destPath = path.dirname(path.join(__root, `images`, src));
|
const destPath = path.dirname(path.join(__root, `images`, src));
|
||||||
const filename = path.join(destPath, `${hash}.png`);
|
const filename = path.join(destPath, `${hash}.png`);
|
||||||
if (fs.existsSync(filename)) return hash;
|
if (fs.existsSync(filename)) return hash;
|
||||||
@@ -50,7 +55,7 @@ async function generateFallbackImage(src, width, height) {
|
|||||||
|
|
||||||
fs.ensureDirSync(path.dirname(filename));
|
fs.ensureDirSync(path.dirname(filename));
|
||||||
fs.writeFileSync(filename, imageData);
|
fs.writeFileSync(filename, imageData);
|
||||||
console.log(`Generated fallback image for ${src}`);
|
console.log(`Generated fallback image for ${src} (${locale})`);
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,12 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) {
|
|||||||
src = src.replace(`./`, `./chapters/${chapter}/`);
|
src = src.replace(`./`, `./chapters/${chapter}/`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let imageHash = await generateFallbackImage(src, width, height); // ← this is super fancy functionality.
|
let imageHash = await generateFallbackImage(
|
||||||
|
localeStrings,
|
||||||
|
src,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
); // ← this is super fancy functionality.
|
||||||
let imgUrl = path.join(
|
let imgUrl = path.join(
|
||||||
path.dirname(src.replace(`./`, `./images/`)),
|
path.dirname(src.replace(`./`, `./images/`)),
|
||||||
`${imageHash}.png`
|
`${imageHash}.png`
|
||||||
|
@@ -2190,18 +2190,38 @@ function drawCurve(points[], t):
|
|||||||
evenly as <em>t</em>-intervals, not spaced equidistant).
|
evenly as <em>t</em>-intervals, not spaced equidistant).
|
||||||
</p>
|
</p>
|
||||||
<div class="figure">
|
<div class="figure">
|
||||||
<Graphic
|
<graphics-element
|
||||||
title="Quadratic Bézier tangents and normals"
|
title="Quadratic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupQuadratic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/quadratic.js"
|
||||||
/>
|
>
|
||||||
<Graphic
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\3158c82ea512f70ec17d4a1ce2e7c7b2.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
|
<graphics-element
|
||||||
title="Cubic Bézier tangents and normals"
|
title="Cubic Bézier tangents and normals"
|
||||||
inline="{true}"
|
width="275"
|
||||||
setup="{this.setupCubic}"
|
height="275"
|
||||||
draw="{this.draw}"
|
src="./chapters/pointvectors/cubic.js"
|
||||||
/>
|
>
|
||||||
|
<fallback-image>
|
||||||
|
<img
|
||||||
|
width="275px"
|
||||||
|
height="275px"
|
||||||
|
src="images\chapters\pointvectors\05a1ee3b81a4838292814a7097b4cf50.png"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
Scripts are disabled. Showing fallback image.
|
||||||
|
</fallback-image></graphics-element
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="pointvectors3d">
|
<section id="pointvectors3d">
|
||||||
|
Reference in New Issue
Block a user