数学篇07 # 如何用向量和参数方程描述曲线?

Posted 凯小默

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数学篇07 # 如何用向量和参数方程描述曲线?相关的知识,希望对你有一定的参考价值。

说明

【跟月影学可视化】学习笔记。

如何用向量描述曲线?

用向量绘制折线的方法来绘制正多边形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>如何用向量描述曲线</title>
    <style>
        canvas 
            border: 1px dashed salmon;
        
    </style>
</head>
<body>
    <canvas width="512" height="512"></canvas>
    <script type="module">
        import  Vector2D  from './common/lib/vector2d.js';

        const canvas = document.querySelector('canvas');
        const ctx = canvas.getContext('2d');
        const width, height = canvas;
        ctx.translate(0.5 * width, 0.5 * height);
        ctx.scale(1, -1);
        /**
         * 边数 edges
         * 起点 x, y
         * 一条边的长度 step
         * */
        function regularShape(edges = 3, x, y, step) 
            const ret = [];
            const delta = Math.PI * (1 - (edges - 2) / edges);
            let p = new Vector2D(x, y);
            const dir = new Vector2D(step, 0);
            ret.push(p);
            for(let i = 0; i < edges; i++) 
                p = p.copy().add(dir.rotate(delta));
                ret.push(p);
            
            return ret;
        
        function draw(points, strokeStyle = 'salmon', fillStyle = null) 
            ctx.strokeStyle = strokeStyle;
            ctx.beginPath();
            ctx.moveTo(...points[0]);
            for(let i = 1; i < points.length; i++) 
                ctx.lineTo(...points[i]);
            
            ctx.closePath();
            if(fillStyle) 
                ctx.fillStyle = fillStyle;
                ctx.fill();
            
            ctx.stroke();
        

        draw(regularShape(3, 128, 128, 100));  // 绘制三角形
        draw(regularShape(6, -64, 128, 50));  // 绘制六边形
        draw(regularShape(11, -64, -64, 30));  // 绘制十一边形
        draw(regularShape(60, 128, -64, 6));  // 绘制六十边形
    </script>
</body>
</html>

如何用参数方程描述曲线?

1. 画圆

圆可以用一组参数方程来定义。定义了一个圆心在(x0,y0),半径为 r 的圆。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>画圆</title>
    <style>
        canvas 
            border: 1px dashed salmon;
        
    </style>
</head>
<body>
    <canvas width="512" height="512"></canvas>
    <script>
        const canvas = document.querySelector('canvas');
        const ctx = canvas.getContext('2d');
        const width, height = canvas;
        ctx.translate(0.5 * width, 0.5 * height);
        ctx.scale(1, -1);

        
        const TAU_SEGMENTS = 60;
        const TAU = Math.PI * 2;
        function arc(x0, y0, radius, startAng = 0, endAng = Math.PI * 2) 
            const ang = Math.min(TAU, endAng - startAng);
            const ret = ang === TAU ? [] : [[x0, y0]];
            const segments = Math.round(TAU_SEGMENTS * ang / TAU);
            for(let i = 0; i <= segments; i++) 
                const x = x0 + radius * Math.cos(startAng + ang * i / segments);
                const y = y0 + radius * Math.sin(startAng + ang * i / segments);
                ret.push([x, y]);
            
            return ret;
        

        function draw(points, strokeStyle = 'salmon', fillStyle = null) 
            ctx.strokeStyle = strokeStyle;
            ctx.beginPath();
            ctx.moveTo(...points[0]);
            for(let i = 1; i < points.length; i++) 
                ctx.lineTo(...points[i]);
            
            ctx.closePath();
            if(fillStyle) 
                ctx.fillStyle = fillStyle;
                ctx.fill();
            
            ctx.stroke();
        

        draw(arc(0, 0, 100));
    </script>
</body>
</html>

2. 画圆锥曲线

椭圆

a、b 分别是椭圆的长轴和短轴,当 a = b = r 时,这个方程是就圆的方程式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>椭圆</title>
    <style>
        canvas 
            border: 1px dashed salmon;
        
    </style>
</head>
<body>
    <canvas width="512" height="512"></canvas>
    <script>
        const canvas = document.querySelector('canvas');
        const ctx = canvas.getContext('2d');
        const width, height = canvas;
        ctx.translate(0.5 * width, 0.5 * height);
        ctx.scale(1, -1);

        
        const TAU_SEGMENTS = 60;
        const TAU = Math.PI * 2;
        
        function ellipse(x0, y0, radiusX, radiusY, startAng = 0, endAng = Math.PI * 2) 
            const ang = Math.min(TAU, endAng - startAng);
            const ret = ang === TAU ? [] : [[x0, y0]];
            const segments = Math.round(TAU_SEGMENTS * ang / TAU);
            for(let i = 0; i <= segments; i++) 
                const x = x0 + radiusX * Math.cos(startAng + ang * i / segments);
                const y = y0 + radiusY * Math.sin(startAng + ang * i / segments);
                ret.push([x, y]);
            
            return ret;
        

        function draw(points, strokeStyle = 'salmon', fillStyle = null) 
            ctx.strokeStyle = strokeStyle;
            ctx.beginPath();
            ctx.moveTo(...points[0]);
            for(let i = 1; i < points.length; i++) 
                ctx.lineTo(...points[i]);
            
            ctx.closePath();
            if(fillStyle) 
                ctx.fillStyle = fillStyle;
                ctx.fill();
            
            ctx.stroke();
        

        draw(ellipse(0, 0, 100, 50));
    </script>
</body>
</html>

抛物线

抛物线的参数方程。其中 p 是常数,为焦点到准线的距离。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>抛物线</title>
    <style>
        canvas 
            border: 1px dashed salmon;
        
    </style>
</head>
<body>
    <canvas width="512" height="512"></canvas>
    <script>
        const canvas = document.querySelector('canvas');
        const ctx = canvas.getContext('2d');
        const width, height = canvas;
        ctx.translate(0.5 * width, 0.5 * height);
        ctx.scale(1, -1);
        
        const LINE_SEGMENTS = 60;
        function parabola(x0, y0, p, min, max) 
            const ret = [];
            for(let i = 0; i <= LINE_SEGMENTS; i++) 
                const s = i / 60;
                const t = min * (1 - s) + max * s;
                const x = x0 + 2 * p * t ** 2;
                const y = y0 + 2 * p * t;
                ret.push([x, y]);
            
            return ret;
        

        function draw(points, strokeStyle = 'salmon', fillStyle = null) 
            ctx.strokeStyle = strokeStyle;
            ctx.beginPath();
            ctx.moveTo(...points[0]);
            for(let i = 1; i < points.length; i++) 
                ctx.lineTo(...points[i]);
            
            ctx.closePath();
            if(fillStyle) 
                ctx.fillStyle = fillStyle;
                ctx.fill();
            
            ctx.stroke();
        

        draw(parabola(0, 0, 5.5, -10, 10));
    </script>
</body>
</html>

3. 画其他常见曲线

在 lib 下面新建一个 parametric.js 文件,封装一个更简单的 javascript 参数方程绘图模块。

// 根据点来绘制图形
function draw(
    points,
    context,
    以上是关于数学篇07 # 如何用向量和参数方程描述曲线?的主要内容,如果未能解决你的问题,请参考以下文章

数学篇05 # 如何用向量和坐标系描述点和线段?

如何用向量表示圆

数学篇09 # 如何用仿射变换对几何图形进行坐标变换?

如何用spss制作二次曲线趋势方程?

JavaScript动画实例:李萨如曲线

如何用MATLAB画机器人手臂一个关节的速度曲线