首页 > 编程语言 >【每日GIS算法】(1)二维矢量的运算

【每日GIS算法】(1)二维矢量的运算

时间:2024-01-25 18:35:07浏览次数:42  
标签:Vector2d return 矢量 scalar v2 二维 new GIS

二维向量的基础运算主要有以下几种

  • 矢量的加法
  • 矢量的减法
  • 矢量的乘法
  • 矢量的除法
  • 矢量的模
  • 矢量的点乘
  • 矢量的叉乘
  • 矢量的归一化

针对不同的场景,我们为二维矢量类提供对应的实例方法,但是由于这些实例方法会修改对象内部的数值,因此还提供对应的静态方法,在不改变原来的向量的情况下,返回一个新的向量。

1. 矢量的加法

二维向量的加法可以定义为将两个二维向量对应位置的数值相加。

add(v: Vector2d) : Vector2d{
  this.x += v.x;
  this.y += v.y;
  return this;
}

static addVector(v1: Vector2d, v2: Vector2d) {
  return new Vector2d(v1.x + v2.x, v1.y + v2.y);
}

为了方便使用,我们提供一个矢量与标量的加法函数,矢量的每一项都加上对应的标量值。

addScalar(scalar: number) : Vector2d {
  this.x += scalar;
  this.y += scalar;
  return this;
}

static addScalarVector(v: Vector2d, scalar: number) : Vector2d {
  return new Vector2d(v.x + scalar, v.y + scalar);
}

2. 矢量的减法

同理,矢量的减法就是对应的位置相减,同样我们提供了一个与标量的减法方法。

sub(v: Vector2d) : Vector2d {
  this.x -= v.x;
  this.y -= v.y;
  return this;
}

static subVector(v1: Vector2d, v2: Vector2d) : Vector2d {
  return new Vector2d(v1.x - v2.x, v1.y - v2.y);
}

subScalar(scalar: number) : Vector2d {
  this.x -= scalar;
  this.y -= scalar;
  return this;
}

static subScalarVector(v: Vector2d, scalar: number) : Vector2d {
  return new Vector2d(v.x - scalar, v.y - scalar);
}

3. 矢量的乘法

矢量的乘法有很多种,我们针对以后可能需要,提供三种不同的乘法方法,第一种是将两个矢量对应位置的数值相乘,第二种是矢量点乘,第三种是将两个矢量叉乘,

矢量对应位置的数值相乘

此处我们同样支持了与标量的乘法,将矢量的每一项都乘以对应的标量值。

multiplyByComponent(v: Vector2d): Vector2d {
  this.x *= v.x;
  this.y *= v.y;
  return this;
}

static multiplyByComponentVector(v1: Vector2d, v2: Vector2d): Vector2d {
  return new Vector2d(v1.x * v2.x, v1.y * v2.y);
}

multiplyByScalar(scalar: number) : Vector2d {
  this.x *= scalar;
  this.y *= scalar;
  return this;
}

static multiplyByScalarVector(v: Vector2d, scalar: number): Vector2d {
  return new Vector2d(v.x * scalar, v.y * scalar);
}

矢量点乘

矢量点乘的意义可以看作为其中一个矢量向另一个矢量上进行投影,投影矢量的长度与另一个矢量的长度的成绩,其结果是一个标量,其公式为:
$$
\vec{v} \cdot \vec{w} = |\vec{v}| \times |\vec{w}| \times \cos\theta
$$
数学结果表达式可以表示为
$$
\vec{v} \cdot \vec{w} = v_x \times w_x + v_y \times w_y
$$

dot(v: Vector2d) : number {
  return this.x * v.x + this.y * v.y;
}

矢量叉乘

在三维空间中,两个三维矢量的叉乘的结果也是一个三维矢量,这个三维矢量的方向垂直于相乘的两个三维矢量组成的平面,矢量的长度为$|\vec{v}|\times |\vec{w}|\times\sin\theta$,其中,$\theta$为两个矢量组成的平面的夹角,夹角的方向符合右手螺旋定则。

但是在二维空间中,两个二维矢量的叉乘的结果是一个标量,其公式为:
$$
\vec{v} \times \vec{w} = v_x \times w_y - v_y \times w_x
$$

实际上二维空间的矢量的叉乘可以看作三维空间中,$z$轴都为0,起点为原点的两个三维向量的叉乘结果,其结果一定是一个垂直于$XY$平面,起点为原点,即位于$Z$轴上的一个三维向量。由于其$XY$值都是0,我们就不考虑了,只考虑$Z$轴的值即可。

cross(v: Vector2d) : number {
  return this.x * v.y - this.y * v.x;
}

针对二维矢量叉乘的结果的符号,我们可以用来判断一条折线段的拐向。假设一条折线段有三个点p0p1p2,我们定义X轴正方向为右向,X轴负方向为左向,那么点从p1点拐到p2点,这个折线段是向左拐了还是向右拐了。我们可以通过$(p_2-p_0)\times(p_1-p_0)$的结果来判断,如果结果为正,则向左拐,如果结果为负,则向右拐,如果为0,则说明三点共线。这个结论在后续一些操作中会用到。

矢量除法

矢量的除法我们同样定义了对应位置的除法操作,以及对一个标量的除法操作,同时定义了对应的静态方法,用于返回新向量。

在这里注意的是,由于0不能做除数,所以我们需要判断一下,如果除数为0,则抛出一个错误。当然,如果你不想抛出错误,而是想返回一个默认值,那么你可以自己实现一个默认值的返回方法。

divide(v: Vector2d): Vector2d {
  if (v.x === 0 || v.y === 0) {
    throw new Error("Cannot divide by zero");
  }

  this.x /= v.x;
  this.y /= v.y;
  return this;
}

static divideVector(v1: Vector2d, v2: Vector2d): Vector2d {
  if (v2.x === 0 || v2.y === 0) {
    throw new Error("Cannot divide by zero");
  }
  return new Vector2d(v1.x / v2.x, v1.y / v2.y);
}

divideByScalar(scalar: number) : Vector2d {
  if (scalar === 0) {
    throw new Error("Cannot divide by scalar 0");
  }
  this.x /= scalar;
  this.y /= scalar;
  return this;
}

static divideByScalarVector(v: Vector2d, scalar: number): Vector2d {
  if (scalar === 0) {
    throw new Error("Cannot divide by scalar 0");
  }
  return new Vector2d(v.x / scalar, v.y / scalar);
}

矢量的模

矢量的模就是矢量的长度。一个二维矢量的模可以用勾股定理来计算,即$|v|=\sqrt{v_x2+v_y2}$

length() : number {
  return Math.sqrt(this.x * this.x + this.y * this.y);
}

矢量的标准化

矢量的标准化就是将矢量的模变为1,即将矢量的方向不变,而将模变为1。一个二维矢量的标准化可以用矢量的模除以原模来计算,即$v'=v/|v|$

normalize() : Vector2d {
  const length = this.length();
  this.x /= length;
  this.y /= length;
  return this;
}

其他操作

除以上操作之外,我们定义几个内部静态变量,分别是$XY$轴上的单位向量以及零向量。

static readonly UNIT_X = new Vector2d(1, 0); // 单位向量x
static readonly UNIT_Y = new Vector2d(0, 1); // 单位向量y
static readonly ZERO = new Vector2d(0, 0); // 零向量

还有更多的向量操作,如旋转等,等以后我们需要的时候再创建。

标签:Vector2d,return,矢量,scalar,v2,二维,new,GIS
From: https://www.cnblogs.com/masakulayou/p/17987868

相关文章

  • Registry&Harbor私有仓库构建
    一、介绍Harbor是一个用于存储Docker镜像的企业级Registry服务。Registry是Dcoker官方的一个私有仓库镜像,可以将本地的镜像打标签进行标记然后push到以Registry起的容器的私有仓库中。企业可以根据自己的需求,使用Dokcerfile生成自己的镜像,并推到私有仓库中,这样可以大大提高拉取......
  • 微信小程序之条形码和二维码
    整个示例目录:index.wxml代码: <view class="container page">  <view class="panel">    <view class="header">    </view>    <view class="barcode">      <view class="barnum">......
  • npm ERR! request to https://registry.npm.taobao.org/axios failed, reason: certif
    前言一直使用npmbuild没问题的,突然出现报错:npmWARNinstallUsageofthe`--dev`optionisdeprecated.Use`--only=dev`instead.npmERR!codeCERT_HAS_EXPIREDnpmERR!errnoCERT_HAS_EXPIREDnpmERR!requesttohttps://registry.npm.taobao.org/axiosfailed,......
  • request to https://registry.npm.taobao.org/vue-loader failed!
    npminstall报错:requestto https://registry.npm.taobao.org/vue-loader failed,reason:getaddrinfoENOTFOUNDregistry.npm.taobao.org解决:https://jingyan.baidu.com/article/acf728fd99b16ff8e510a301.html查看镜像源:npmgetregistryhttps://registry.npmjs.org/国......
  • QGIS的安装和开发
    osgeo4w-setup离线安装包资源不大,便于安装。 界面安装后,如控件开发报错:进入C:\ProgramFiles\QGIS3.28.10\bin下执行bat后,下载相应安装包,注意网络 建立的控件等工程文件首先可对应与系统文件夹里: 前者是目标新建目录,后者是原有目录。工程文件: Plugins->需要安装bu......
  • Python 生成二维码的几种方式、生成条形码
    一:#生成地维码importqrcodeimportmatplotlib.pyplotaspltfrombarcode.writerimportImageWriter创建QRCode对象qr=qrcode.QRCode(version=1,error_correction=qrcode.constants.ERROR_CORRECT_L,box_size=10,border=4)设置二维码的数据data="Hello,world!"......
  • 二维动态规划+子集和
    题目:查看代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;constintN=1e3+7;constllmod=1e5+7;intn,s;intdp[N][N],a[N];intmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;for(in......
  • Matlab-pcolor绘制二维色温图并修改温度条颜色
    figure(3)pcolor(time,yData',data1.ConVel')shadinginterp;colorbar;color_1=[0,0,1];color_2=[1,1,1];color_3=[1,0,0];num12=45;num23=25;R_mat=[linspace(color_1(1),color_2(1),num12),linspace(color_2(1),color_3(1),num23)];G_mat=[linspace(col......
  • 动态规划--摆花(二维dp)
    #include<iostream>usingnamespacestd;//dp[i][j]表示第i种花位置,第j个位置为止longlongintdp[120][120];longlonginta[160];intmain(){intn,m;cin>>n>>m;//n种花m盆for(inti=1;i<=n;i++){cin>>a[i];}dp[0][0]=1;for(inti=1;i<=n;......
  • iReport使用zxing二维码模板设置方式
    1.首先需要给软件配置引用包core和javase;工具-选项-iReport-ClassPath, 2.然后组件就直接使用Image的,选文件时直接取消就行;3.重点:设置属性ImageExpression:com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(newcom.google.zxing.qrcode.QRCodeWriter(......