当前位置: 首页> 房产> 家装 > 华为手机网络推广方案_传奇公益服_朋友圈推广平台_今日新闻十大头条内容

华为手机网络推广方案_传奇公益服_朋友圈推广平台_今日新闻十大头条内容

时间:2025/9/7 22:45:22来源:https://blog.csdn.net/graypigen1990/article/details/142730210 浏览次数:0次
华为手机网络推广方案_传奇公益服_朋友圈推广平台_今日新闻十大头条内容

概述

Vector2是GDSCript中表示二维向量的类型,你会发现无论在任何编程语言中,只要你想很好的实现2D绘图以及几何和物理相关,Vector2是你必须要实现的一个类。我之前学C++时就写过一个C++的版本。

本篇就介绍我自己在JavaScript中定义的Vector2类型。它将是我接下来基于Canvas和SVG进行绘图的类的基础类型。

定义Vector2类型

在这里插入图片描述

// =======================================================
// Vector2
// 自定义类,Javascript版本的2D向量类型
// 巽星石
// 2024年10月6日13:18:59
// 2024年10月6日17:19:54
// 2D向量类型
// =======================================================
class Vector2{/*==================== 构造函数 ====================*/ constructor(x,y){ // 构造函数this.x = xthis.y = y}/*==================== 静态方法 ====================*/static ZERO(){return new Vector2(0,0);}static LEFT(){return new Vector2(-1,0);}static RIGHT(){return new Vector2(1,0);}static UP(){return new Vector2(0,-1);}static DOWN(){return new Vector2(0,1);}static ONE(){return new Vector2(1,1);}static ROTATED(deg){ //返回与X轴夹角为deg度的单位向量var vec = this.RIGHT();vec.rotated(deg);return vec;}static pVector2(ang,len){ // 返回极坐标点if(typeof(ang) == "number" && typeof(len) == "number"){return this.ROTATED(ang).times(len);}}static rad_to_deg(rad){ // 弧度转角度return rad * (180.0 / Math.PI) ;}static deg_to_rad(deg){ // 角度转弧度return deg * (Math.PI / 180.0) ;}static sin(deg){  //修正后的正弦函数const PI2 = Math.PI * 2    //2πlet ang_rad = Vector2.deg_to_rad(deg);  //转为弧度let yu = Math.abs(ang_rad % PI2)        //所有正负180度或360度 + 任意圈数的sin值设为0return (yu != Math.PI && yu != 0) ? Math.sin(ang_rad) : 0}static cos(deg){  //修正后的余弦函数const PI2 = Math.PI * 2    //2πlet ang_rad = Vector2.deg_to_rad(deg);  //转为弧度let yu = Math.abs(ang_rad % PI2)        //所有正负90度 + 任意圈数的cos值设为0return (yu != Math.PI/2) ? Math.cos(ang_rad) : 0}/*==================== 方法 ====================*/ distance_to(b){  // 返回到b点的距离if(b.constructor.name == "Vector2"){const dx = this.x - b.x;const dy = this.y - b.y;return Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2))}}direction_to(b){  // 返回到b点的方向if(b.constructor.name == "Vector2"){let vec = b.minus(this);  // AB向量 = B - Areturn vec.normalized();}}length(){ //返回向量的长度const o = new Vector2(0,0); //坐标系原点return this.distance_to(o)}normalized(){ // 获取归一化向量return this.divide(this.length());}/*==================== 角度相关 ====================*/ angle(){ // 与X轴夹角(角度)return Vector2.rad_to_deg(Math.asin(this.normalized().y));}angle_to(b){ // 到b向量的夹角(角度)if(b.constructor.name == "Vector2"){return b.angle() - this.angle();}}rotated(deg){ // 旋转向量const r  = this.length();const ang = this.angle();var ang_rad = deg + ang;this.x = r * Vector2.cos(ang_rad);this.y = r * Vector2.sin(ang_rad);}/*==================== 运算 ====================*/plus(b){ //加法switch (typeof(b)) {case "object":if(b.constructor.name == "Vector2"){return new Vector2(this.x + b.x,this.y + b.y)}break;default:break;}}minus(b){ //减法switch (typeof(b)) {case "object":if(b.constructor.name == "Vector2"){return new Vector2(this.x - b.x,this.y - b.y)}break;default:break;}}times(b){ //乘法switch (typeof(b)) {case "number":return new Vector2(this.x * b,this.y * b)break;case "object":if(b.constructor.name == "Vector2"){return new Vector2(this.x * b.x,this.y * b.y)}break;default:break;}}divide(b){ //除法switch (typeof(b)) {case "number":return new Vector2(this.x/b,this.y/b)break;case "object":if(b.constructor.name == "Vector2"){return new Vector2(this.x / b.x,this.y / b.y)}break;default:break;}}
}

在网页中使用Vector2类型

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="1.js"></script>
</head>
<body></body>
<script>var a = new Vector2(100,100);console.log(a);
</script>
</html>

运行效果:

向量的长度

向量的长度是指到坐标系原点(0,0)的距离。

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.length());
console.log(b.length());

两点间距离

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.distance_to(b));

到点B的方向向量

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.direction_to(b));

归一化向量

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.normalized());

四则运算

加法

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.plus(b));

减法

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.minus(b));

乘法

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.times(b));   # 乘以一个Vector2
console.log(a.times(2));   # 乘以一个标量

除法

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.divide(b));   # 除以一个Vector2
console.log(a.divide(2));   # 除以一个标量

求角度

我们知道$ \sin \theta = \frac{y}{r} ,其中 r = 1 ,则 ,其中r = 1,则 ,其中r=1,则 \sin \theta = y ,则 ,则 ,则 \theta = \arcsin (y) $。

也就是我们要求一个向量与X轴的夹角θ,只需要求其归一化向量的y坐标的反正弦函数即可。

angle(){ // 与X轴夹角(角度)return this.rad_to_deg(Math.asin(this.normalized().y));
}

与X轴正方向的夹角

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.angle());
console.log(b.angle());

到B向量的夹角

var a = new Vector2(100,100);
var b = new Vector2(200,100);
console.log(a.angle_to(b));
console.log(b.angle_to(a));

向量旋转

var a = new Vector2(100,100);
console.log(a.length());
a.rotated(45)
console.log(a);
console.log(a.length());

常用单位向量和极坐标点

仿照GDSCript中的Vector2,设计了一些静态方法用于获取一些常用的单位向量。

static ZERO(){return new Vector2(0,0);
}
static LEFT(){return new Vector2(-1,0);
}
static RIGHT(){return new Vector2(1,0);
}
static UP(){return new Vector2(0,-1);
}
static DOWN(){return new Vector2(0,1);
}
static ONE(){return new Vector2(1,1);
}
static ROTATED(deg){ //返回与X轴夹角为deg度的单位向量var vec = this.RIGHT();vec.rotated(deg);return vec;
}
static pVector2(ang,len){ // 返回极坐标点if(typeof(ang) == "number" && typeof(len) == "number"){return this.ROTATED(ang).times(len);}
}

ROTATED()是我自己原创的,可以快速的获取与X轴夹角为deg度的单位向量。

pVector2()返回与X轴夹角为deg度,长度为len的向量。

var a = Vector2.pVector2(-90,100)
console.log(a)

角度与弧度互转

static rad_to_deg(rad){ // 弧度转角度return rad * (180.0 / Math.PI) ;
}static deg_to_rad(deg){ // 角度转弧度return deg * (Math.PI / 180.0) ;
}

修正后的正弦和余弦函数

Math.sin(Math.PI * n)Math.sin(Math.PI * 2 * n)以及Math.cos((Math.PI / 2) * n)返回的都不是0,而是一个极小数。这对极坐标和向量旋转来说是没法用的,所以自己在Vector2类型中定义了cos()sin(),并做了一些修正。

static sin(deg){  //修正后的正弦函数const PI2 = Math.PI * 2    //2πlet ang_rad = Vector2.deg_to_rad(deg);  //转为弧度let yu = Math.abs(ang_rad % PI2)        //所有正负180度或360度 + 任意圈数的sin值设为0return (yu != Math.PI && yu != 0) ? Math.sin(ang_rad) : 0
}static cos(deg){  //修正后的余弦函数const PI2 = Math.PI * 2    //2πlet ang_rad = Vector2.deg_to_rad(deg);  //转为弧度let yu = Math.abs(ang_rad % PI2)        //所有正负90度 + 任意圈数的cos值设为0return (yu != Math.PI/2) ? Math.cos(ang_rad) : 0
}

在HTML5 Canvas中使用

在HTML中定义canvas标签:

<body><canvas id="canvas01" width="300" height="300"></canvas>
</body>

使用Vector2定义点并进行绘制:

// 获取canvas和上下文对象
let canvas = document.getElementById("canvas01");
let ctx = canvas.getContext('2d');// 定义两点
let p1 = Vector2.ZERO()
let p2 = Vector2.pVector2(45,100)// 绘制
ctx.beginPath()
ctx.strokeStyle = "red"; //轮廓颜色
ctx.lineWidth = 2;       //轮廓线宽
// 绘制直线
ctx.moveTo(p1.x,p1.y);
ctx.lineTo(p2.x,p2.y);
ctx.stroke();

为了方便查看画布,定义如下CSS样式:

body{background-color: #444;
}
canvas{background-color: #fff;
}

绘制效果:

总结

本文基于JavaScript编写了Vector2类型,基本实现与GDSCript内置Vector2类型相同的效果。

点积、叉积等内容后续将逐步实现和添加。

关键字:华为手机网络推广方案_传奇公益服_朋友圈推广平台_今日新闻十大头条内容

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: