1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-25 17:42:46 +02:00

rebuild + sections up to 14

This commit is contained in:
Pomax
2016-01-02 10:05:27 -08:00
parent 15523da391
commit c8ebcf29b9
31 changed files with 3079 additions and 94 deletions

View File

@@ -0,0 +1,145 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
var PointVectors = React.createClass({
statics: {
title: "Tangents and normals"
},
setupQuadratic: function(api) {
var curve = api.getDefaultQuadratic();
api.setCurve(curve);
},
setupCubic: function(api) {
var curve = api.getDefaultCubic();
api.setCurve(curve);
},
draw: function(api, curve) {
api.reset();
api.drawSkeleton(curve);
api.drawCurve(curve);
var i,t,p,tg,n,td=0.25,nd=20;
for(i=0; i<=10; i++) {
t = i/10.0;
p = curve.get(t);
tg = curve.derivative(t);
n = curve.normal(t);
api.setColor("blue");
api.drawLine(p, {x:p.x+tg.x*td, y:p.y+tg.y*td});
api.setColor("red");
api.drawLine(p, {x:p.x+n.x*nd, y:p.y+n.y*nd});
api.setColor("black");
api.drawCircle(p,3);
}
},
render: function() {
return (
<section>
<SectionHeader {...this.props}>{ PointVectors.title }</SectionHeader>
<p>If you want to move objects along a curve, or "away from" a curve, the two vectors you're most interested
in are the tangent vector and normal vector for curve points. These are actually really easy to find. For
moving, and orienting, along a curve we use the tangent, which indicates the direction travel at specific
points, and is literally just the first derivative of our curve:</p>
<p>\[
\left \{ \begin{matrix}
tangent_x(t) = B'_x(t) \\
tangent_y(t) = B'_y(t)
\end{matrix} \right. \]</p>
<p>This gives us the directional vector we want. We can normalize it to give us uniform directional vectors
(having a length of 1.0) at each point, and then do whatever it is we want to do based on those directions:</p>
<p>\[
d = || tangent(t) || = \sqrt{B'_x(t)^2 + B'_y(t)^2}
\]</p>
<p>\[
\left \{ \begin{matrix}
\hat{x}(t) = || tangent_x(t) ||
=\frac{tangent_x(t)}{ || tangent(t) || }
= \frac{B'_x(t)}{d} \\
\hat{y}(t) = || tangent_y(t) ||
= \frac{tangent_y(t)}{ || tangent(t) || }
= \frac{B'_y(t)}{d}
\end{matrix} \right. \]</p>
<p>The tangent is very useful for moving along a line, but what if we want to move away from the curve instead,
perpendicular to the curve at some point <i>t</i>? In that case we want the "normal" vector. This vector runs
at a right angle to the direction of the curve, and is typically of length 1.0, so all we have to do is rotate
the normalized directional vector and we're done:</p>
<p>\[
\left \{ \begin{array}{l}
normal_x(t) = \hat{x}(t) \cdot \cos{\frac{\pi}{2}} - \hat{y}(t) \cdot \sin{\frac{\pi}{2}} = - \hat{y}(t) \\
normal_y(t) = \underset{quarter\ circle\ rotation} {\underbrace{ \hat{x}(t) \cdot \sin{\frac{\pi}{2}} + \hat{y}(t) \cdot \cos{\frac{\pi}{2}} }} = \hat{x}(t)
\end{array} \right. \]</p>
<div className="note">
<p>Rotating coordinates is actually very easy, if you know the rule for it. You might find
it explained as "applying a <a href="https://en.wikipedia.org/wiki/Rotation_matrix">rotation matrix</a>",
which is what we'll look at here, too. Essentially, the idea is to take the circles over
which we can rotate, and simply "sliding the coordinates" over those circles by the desired
angle. If we want a quarter circle turn, we take the coordinate, slide it along the cirle
by a quarter turn, and done.</p>
<p>To turn any point <i>(x,y)</i> into a rotated point <i>(x',y')</i> (over 0,0) by
some angle φ, we apply this nicely easy computation:</p>
<p>\[\begin{array}{l}
x' = x \cdot \cos(\phi) - y \cdot \sin(\phi) \\
y' = x \cdot \sin(\phi) + y \cdot \cos(\phi)
\end{array}\]</p>
<p>Which is the "long" version of the following matrix transformation:</p>
<p>\[
\begin{bmatrix}
x' \\ y'
\end{bmatrix}
=
\begin{bmatrix}
\cos(\phi) & -\sin(\phi) \\
\sin(\phi) & \cos(\phi)
\end{bmatrix}
\begin{bmatrix}
x \\ y
\end{bmatrix}
\]</p>
<p>And that's all we need to rotate any coordinate. Note that for quarter, half
and three quarter turns these functions become even easier, since <i>sin</i> and
<i>cos</i> for these angles are, respectively: 0 and 1, -1 and 0, and 0 and -1.</p>
<p>But <strong><em>why</em></strong> does this work? Why this matrix multiplication?
<a href="http://en.wikipedia.org/wiki/Rotation_matrix#Decomposition_into_shears">wikipedia</a>
(Technically, Thomas Herter and Klaus Lott) tells us that a rotation matrix can be
treated as a sequence of three (elementary) shear operations. When we combine this into
a single matrix operation (because all matrix multiplications can be collapsed), we get
the matrix that you see above.
<a href="http://datagenetics.com/blog/august32013/index.html">DataGenetics</a> have an
excellent article about this very thing: it's really quite cool, and I strongly recommend
taking a quick break from this primer to read that article.</p>
</div>
<p>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.</p>
<div className="figure">
<Graphic preset="simple" title="Quadratic Bézier tangents and normals" inline={true} setup={this.setupQuadratic} draw={this.draw}/>
<Graphic preset="simple" title="Cubic Bézier tangents and normals" inline={true} setup={this.setupCubic} draw={this.draw}/>
</div>
</section>
);
}
});
module.exports = PointVectors;