mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-01-18 22:18:00 +01:00
added <Graphic/> protection + extended converted to markdown
This commit is contained in:
parent
b47a94d23d
commit
badb1ebed3
28
components/sections/extended/content.en-GB.md
Normal file
28
components/sections/extended/content.en-GB.md
Normal file
@ -0,0 +1,28 @@
|
||||
# The Bézier interval [0,1]
|
||||
|
||||
Now that we know the mathematics behind Bézier curves, there's one curious thing that you may have noticed: they always run from `t=0` to `t=1`. Why that particular interval?
|
||||
|
||||
It all has to do with how we run from "the start" of our curve to "the end" of our curve. If we have a value that is a mixture of two other values, then the general formula for this is:
|
||||
|
||||
\[
|
||||
mixture = a \cdot value_1 + b \cdot value_2
|
||||
\]
|
||||
|
||||
The obvious start and end values here need to be `a=1, b=0`, so that the mixed value is 100% value 1, and 0% value 2, and `a=0, b=1`, so that the mixed value is 0% value 1 and 100% value 2. Additionally, we don't want "a" and "b" to be independent: if they are, then we could just pick whatever values we like, and end up with a mixed value that is, for example, 100% value 1 **and** 100% value 2. In principle that's fine, but for Bézier curves we always want mixed values *between* the start and end point, so we need to make sure we can never set "a" and "b" to some values that lead to a mix value that sums to more than 100%. And that's easy:
|
||||
|
||||
\[
|
||||
m = a \cdot value_1 + (1 - a) \cdot value_2
|
||||
\]
|
||||
|
||||
With this we can guarantee that we never sum above 100%. By restricting `a` to values in the interval [0,1], we will always be somewhere between our two values (inclusively), and we will always sum to a 100% mix.
|
||||
|
||||
But... what if we use this form, used in the assumption that we will only ever use values between 0 and 1, and instead use values outside of that interval? Do things go horribly wrong? Well... not really, but we get to "see more".
|
||||
|
||||
In the case of Bézier curves, extending the interval simply makes our curve "keep going". Bézier curves are simply segments on some polynomial curve, so if we pick a wider interval we simply get to see more of the curve. So what do they look like?
|
||||
|
||||
The following two graphics show you Bézier curves rendered "the usual way", as well as the curves they "lie on" if we were to extend the `t` values much further. As you can see, there's a lot more "shape" hidden in the rest of the curve, and we can model those parts by moving the curve points around.
|
||||
|
||||
<Graphic preset="simple" title="Quadratic infinite interval Bézier curve" setup={this.setupQuadratic} draw={this.draw} />
|
||||
<Graphic preset="simple" title="Cubic infinite interval Bézier curve" setup={this.setupCubic} draw={this.draw} />
|
||||
|
||||
In fact, there are curves used in graphics design and computer modelling that do the opposite of Bézier curves, where rather than fixing the interval, and giving you free coordinates, they fix the coordinates, but give you freedom over the interval. A great example of this is the ["Spiro" curve](http://levien.com/phd/phd.html), which is a curve based on part of a [Cornu Spiral, also known as Euler's Spiral](https://en.wikipedia.org/wiki/Euler_spiral). It's a very aesthetically pleasing curve and you'll find it in quite a few graphics packages like [FontForge](https://fontforge.github.io) and [Inkscape](https://inkscape.org), having even been used in font design (such as for the Inconsolata font).
|
@ -1,11 +1,13 @@
|
||||
var React = require("react");
|
||||
var Graphic = require("../../Graphic.jsx");
|
||||
var SectionHeader = require("../../SectionHeader.jsx");
|
||||
|
||||
var Locale = require("../../../lib/locale");
|
||||
var locale = new Locale("en-GB");
|
||||
var page = "extended";
|
||||
|
||||
var Explanation = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
title: "The Bézier interval [0,1]"
|
||||
title: locale.getTitle(page)
|
||||
};
|
||||
},
|
||||
|
||||
@ -44,61 +46,7 @@ var Explanation = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<section>
|
||||
<SectionHeader {...this.props} />
|
||||
|
||||
<p>Now that we know the mathematics behind Bézier curves, there's one curious thing that you may have
|
||||
noticed: they always run from <i>t=0</i> to <i>t=1</i>. Why that particular interval?</p>
|
||||
|
||||
<p>It all has to do with how we run from "the start" of our curve to "the end" of our curve. If we have
|
||||
a value that is a mixture of two other values, then the general formula for this is:</p>
|
||||
|
||||
<p>\[
|
||||
mixture = a \cdot value_1 + b \cdot value_2
|
||||
\]</p>
|
||||
|
||||
<p>The obvious start and end values here need to be <i>a=1, b=0</i>, so that the mixed value is 100%
|
||||
value 1, and 0% value 2, and <i>a=0, b=1</i>, so that the mixed value is 0% value 1 and 100% value 2.
|
||||
Additionally, we don't want "a" and "b" to be independent: if they are, then we could just pick
|
||||
whatever values we like, and end up with a mixed value that is, for example, 100% value
|
||||
1 <strong>and</strong> 100% value 2. In principle that's fine, but for Bézier curves we always
|
||||
want mixed values <em>between</em> the start and end point, so we need to make sure we can
|
||||
never set "a" and "b" to some values that lead to a mix value that sums to more than 100%. And
|
||||
that's easy:</p>
|
||||
|
||||
<p>\[
|
||||
m = a \cdot value_1 + (1 - a) \cdot value_2
|
||||
\]</p>
|
||||
|
||||
<p>With this we can guarantee that we never sum above 100%. By restricting <i>a</i> to values
|
||||
in the interval [0,1], we will always be somewhere between our two values (inclusively), and
|
||||
we will always sum to a 100% mix.</p>
|
||||
|
||||
<p>But... what if we use this form, used in the assumption that we will only ever use values
|
||||
between 0 and 1, and instead use values outside of that interval? Do things go horribly wrong?
|
||||
Well... not really, but we get to "see more".</p>
|
||||
|
||||
<p>In the case of Bézier curves, extending the interval simply makes our curve "keep going".
|
||||
Bézier curves are simply segments on some polynomial curve, so if we pick a wider interval
|
||||
we simply get to see more of the curve. So what do they look like?</p>
|
||||
|
||||
<p>The following two graphics show you Bézier curves rendered "the usual way", as well as the curves
|
||||
they "lie on" if we were to extend the <i>t</i> values much further. As you can see, there's a lot
|
||||
more "shape" hidden in the rest of the curve, and we can model those parts by moving the curve
|
||||
points around.</p>
|
||||
|
||||
<Graphic preset="simple" title="Quadratic infinite interval Bézier curve" setup={this.setupQuadratic} draw={this.draw} />
|
||||
<Graphic preset="simple" title="Cubic infinite interval Bézier curve" setup={this.setupCubic} draw={this.draw} />
|
||||
|
||||
<p>In fact, there are curves used in graphics design and computer modelling that do the opposite
|
||||
of Bézier curves, where rather than fixing the interval, and giving you free coordinates, they fix
|
||||
the coordinates, but give you freedom over the interval. A great example of this is the <a href="http://levien.com/phd/phd.html">"Spiro"
|
||||
curve</a>, which is a curve based on part of a <a href="https://en.wikipedia.org/wiki/Euler_spiral">Cornu Spiral, also
|
||||
known as Euler's Spiral</a>. It's a very aesthetically pleasing curve and you'll find it in
|
||||
quite a few graphics packages
|
||||
like <a href="https://fontforge.github.io">FontForge</a> and <a href="https://inkscape.org">Inkscape</a>, having
|
||||
even been used in font design (such as for the Inconsolata font).</p>
|
||||
</section>
|
||||
<section>{ locale.getContent(page, this) }</section>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -63,7 +63,6 @@ Given \left (
|
||||
|
||||
<p>So let's look at that in action: the following graphic is interactive in that you can use your up and down arrow keys to increase or decrease the interpolation ratio, to see what happens. We start with three points, which gives us two lines. Linear interpolation over those lines gives use two points, between which we can again perform linear interpolation, yielding a single point. And that point —and all points we can form in this way for all ratios taken together— form our Bézier curve:</p>
|
||||
<Graphic title="Linear Interpolation leading to Bézier curves" setup={handler.setup} draw={handler.draw} onKeyDown={handler.onKeyDown}/>
|
||||
|
||||
<p>And that brings us to the complicated maths: calculus.</p>
|
||||
<p>While it doesn't look like that's what we've just done, we actually just drew a quadratic curve, in steps, rather than in a single go. One of the fascinating parts about Bézier curves is that they can both be described in terms of polynomial functions, as well as in terms of very simple interpolations of interpolations of [...]. That, in turn, means we can look at what these curves can do based on both "real maths" (by examining the functions, their derivatives, and all that stuff), as well as by looking at the "mechanical" composition (which tells us that a curve will never extend beyond the points we used to construct it, for instance)</p>
|
||||
<p>So let's start looking at Bézier curves a bit more in depth. Their mathematical expressions, the properties we can derive from those, and the various things we can do to, and with, Bézier curves.</p>
|
||||
@ -111,7 +110,6 @@ Given \left (
|
||||
<p>There we go. <i>x</i>/<i>y</i> coordinates, linked through some mystery value <i>t</i>.</p>
|
||||
<p>So, parametric curves don't define a <i>y</i> coordinate in terms of an <i>x</i> coordinate, like normal functions do, but they instead link the values to a "control" variable. If we vary the value of <i>t</i>, then with every change we get <strong>two</strong> values, which we can use as (<i>x</i>,<i>y</i>) coordinates in a graph. The above set of functions, for instance, generates points on a circle: We can range <i>t</i> from negative to positive infinity, and the resulting (<i>x</i>,<i>y</i>) coordinates will always lie on a circle with radius 1 around the origin (0,0). If we plot it for <i>t</i> from 0 to 5, we get this (use your up and down arrow keys to change the plot end value):</p>
|
||||
<Graphic preset="empty" title="A (partial) circle: x=sin(t), y=cos(t)" static={true} setup={handler.setup} draw={handler.draw} onKeyDown={handler.props.onKeyDown}/>
|
||||
|
||||
<p>Bézier curves are (one in many classes of) parametric functions, and are characterised by using the same base function for all its dimensions. Unlike the above example, where the <i>x</i> and <i>y</i> values use different functions (one uses a sine, the other a cosine), Bézier curves use the "binomial polynomial" for both <i>x</i> and <i>y</i>. So what are binomial polynomials?</p>
|
||||
<p>You may remember polynomials from high school, where they're those sums that look like:</p>
|
||||
|
||||
@ -265,7 +263,6 @@ function Bezier(3,t):
|
||||
|
||||
<p>Which gives us the curve we saw at the top of the article:</p>
|
||||
<Graphic preset="simple" title="Our cubic Bézier curve" setup={handler.drawCubic} draw={handler.drawCurve}/>
|
||||
|
||||
<p>What else can we do with Bézier curves? Quite a lot, actually. The rest of this article covers a multitude of possible operations and algorithms that we can apply, and the tasks they achieve.</p>
|
||||
|
||||
<div className="howtocode">
|
||||
@ -302,8 +299,29 @@ function Bezier(3,t,w[]):
|
||||
|
||||
},
|
||||
"extended": {
|
||||
"title": "Unknown title (extended)",
|
||||
"title": "The Bézier interval [0,1]",
|
||||
"getContent": function(handler) { return <section>
|
||||
<SectionHeader name="extended" title="The Bézier interval [0,1]" number="5"/>
|
||||
<p>Now that we know the mathematics behind Bézier curves, there's one curious thing that you may have noticed: they always run from <code>t=0</code> to <code>t=1</code>. Why that particular interval?</p>
|
||||
<p>It all has to do with how we run from "the start" of our curve to "the end" of our curve. If we have a value that is a mixture of two other values, then the general formula for this is:</p>
|
||||
|
||||
\[
|
||||
mixture = a \cdot value_1 + b \cdot value_2
|
||||
\]
|
||||
|
||||
<p>The obvious start and end values here need to be <code>a=1, b=0</code>, so that the mixed value is 100% value 1, and 0% value 2, and <code>a=0, b=1</code>, so that the mixed value is 0% value 1 and 100% value 2. Additionally, we don't want "a" and "b" to be independent: if they are, then we could just pick whatever values we like, and end up with a mixed value that is, for example, 100% value 1 <strong>and</strong> 100% value 2. In principle that's fine, but for Bézier curves we always want mixed values <em>between</em> the start and end point, so we need to make sure we can never set "a" and "b" to some values that lead to a mix value that sums to more than 100%. And that's easy:</p>
|
||||
|
||||
\[
|
||||
m = a \cdot value_1 + (1 - a) \cdot value_2
|
||||
\]
|
||||
|
||||
<p>With this we can guarantee that we never sum above 100%. By restricting <code>a</code> to values in the interval [0,1], we will always be somewhere between our two values (inclusively), and we will always sum to a 100% mix.</p>
|
||||
<p>But... what if we use this form, used in the assumption that we will only ever use values between 0 and 1, and instead use values outside of that interval? Do things go horribly wrong? Well... not really, but we get to "see more".</p>
|
||||
<p>In the case of Bézier curves, extending the interval simply makes our curve "keep going". Bézier curves are simply segments on some polynomial curve, so if we pick a wider interval we simply get to see more of the curve. So what do they look like?</p>
|
||||
<p>The following two graphics show you Bézier curves rendered "the usual way", as well as the curves they "lie on" if we were to extend the <code>t</code> values much further. As you can see, there's a lot more "shape" hidden in the rest of the curve, and we can model those parts by moving the curve points around.</p>
|
||||
<Graphic preset="simple" title="Quadratic infinite interval Bézier curve" setup={handler.setupQuadratic} draw={handler.draw} />
|
||||
<Graphic preset="simple" title="Cubic infinite interval Bézier curve" setup={handler.setupCubic} draw={handler.draw} />
|
||||
<p>In fact, there are curves used in graphics design and computer modelling that do the opposite of Bézier curves, where rather than fixing the interval, and giving you free coordinates, they fix the coordinates, but give you freedom over the interval. A great example of this is the <a href="http://levien.com/phd/phd.html">"Spiro" curve</a>, which is a curve based on part of a <a href="https://en.wikipedia.org/wiki/Euler_spiral">Cornu Spiral, also known as Euler's Spiral</a>. It's a very aesthetically pleasing curve and you'll find it in quite a few graphics packages like <a href="https://fontforge.github.io">FontForge</a> and <a href="https://inkscape.org">Inkscape</a>, having even been used in font design (such as for the Inconsolata font).</p>
|
||||
</section>; }
|
||||
|
||||
},
|
||||
|
@ -15,7 +15,40 @@ Module.prototype.require = function() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function chunkGraphicJSX(data, chunks, chunkMore) {
|
||||
var p = 0,
|
||||
next = chunkMore ? chunkMore[0] : false,
|
||||
otherChunkers = chunkMore ? chunkMore.slice(1) : false,
|
||||
gfxTag = '<Graphic',
|
||||
gfxEnd = '/>';
|
||||
|
||||
while (p !== -1) {
|
||||
// Let's check a LaTeX block
|
||||
let gfx = data.indexOf(gfxTag, p);
|
||||
if (gfx === -1) {
|
||||
// No <Graphic/> block found: we're done here. Parse the remaining
|
||||
// data for whatever else might be in there.
|
||||
performChunking(data.substring(p), chunks, next, otherChunkers);
|
||||
break;
|
||||
}
|
||||
|
||||
// First parse the non-<Graphic/> data for whatever else might be in there.
|
||||
performChunking(data.substring(p, gfx), chunks, next, otherChunkers);
|
||||
|
||||
// Then capture the <Graphic/> block and mark it as "don't convert"
|
||||
let eol = data.indexOf(gfxEnd, gfx) + gfxEnd.length;
|
||||
chunks.push({ convert: false, type: "gfx", s:gfx, e:eol, data: data.substring(gfx, eol) });
|
||||
p = eol;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function chunkDivs(data, chunks, chunkMore) {
|
||||
var p = 0,
|
||||
next = chunkMore ? chunkMore[0] : false,
|
||||
@ -108,7 +141,7 @@ function performChunking(data, chunks, chunker, moreChunkers) {
|
||||
*/
|
||||
function chunk(data) {
|
||||
var chunks = [];
|
||||
performChunking(data, chunks, chunkLatex, [chunkDivs]);
|
||||
performChunking(data, chunks, chunkLatex, [chunkDivs, chunkGraphicJSX]);
|
||||
return chunks;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user