1
0

C++でベクトル演算のライブラリを作りました。

Last updated at Posted at 2024-03-02

初めに

 自分がベクトル関連の競プロの問題やってるときにライブラリ探したのですが、見つからなかったので作りました。間違い等見つかったらご指摘いただけると幸いです。

コード

vec2d.cpp
struct vec2d{
  double x,y;
  vec2d operator+(vec2d other)const{
    vec2d ret;
    ret.x=x+other.x;
    ret.y=y+other.y;
    return ret;
  } 
  vec2d operator-(vec2d other)const{
    vec2d ret;
    ret.x=x-other.x;
    ret.y=y-other.y;
    return ret;
  }
  double operator*(vec2d other)const{
    double ret;
    ret=x*other.x+y*other.y;
    return ret;
  }
  template <typename T>
  vec2d operator*(T other)const{
    vec2d ret;
    ret.x=x*other,ret.y=y*other;
    return ret;
  }
  double abs()const{
    return sqrt(x*x+y*y);
  }
  double Abs()const{
    return x*x+y*y;
  }
  vec2d normalize()const{
    vec2d v,ret;
    v={x,y};
    double siz = v.abs();
    ret.x=x/siz;
    ret.y=y/siz;
    return ret;
  }
};

使い方

 この構造体を張り付けた後、vec2d で型を宣言します。
vec2d は内部にxyを持ちます。
また、加算減算内積定数倍大きさ単位ベクトル化、に対応しています。

できる事 宣言方法 返り値 注意事項
x成分にアクセス vec2d a.x double
y成分にアクセス vec2d a.y double
加算 vec2d a + vec2d b vec2d
減算 vec2d a + vec2d b vec2d
内積 vec2d a * vec2d b double
定数倍 vec2d a * T b vec2d 順序は、絶対にvec2d が先になるようにしてください。また、Tは任意の型ですが、doubleが望ましいです。それ以外は動作確認をしておりません
大きさ vec2d a.abs() double sqrtを挟む分計算量は大きいです。tleに注意してください
大きさ二乗 vec2d a.Abs() double absと比べて計算量は少ないので、単純な大きさ比較をしたいときに使用してください
単位ベクトル化 vec2d a.normalize() vec2d 単位ベクトルを返すだけであることに注意してください。aを単位ベクトル化したい場合、a=a.normalize()と記述してください

比較演算子
比較演算子については実装しておりません。なぜなら状況においてベクトルの何を比較したいかは異なると考えたからです。比較演算はご自身で実装するか、逐一計算する、例えば単純な大きさ比較だったらAbs関数を使う、等してください。

使用例

example_1_code.cpp
//includeは割愛します
//struct vec2d を貼ってください
int main(){
  //この二つのベクトルを利用して例を示します。
  vec2d a={1,4}, b={5,1};
  
  vec2d v;
  v=a+b;
  cout << "加算" << "  " << v.x << " " << v.y << endl;
  
  v=a-b;
  cout << "減算" << "  " << v.x << " " << v.y << endl;
  
  double naiseki = a*b;
  cout << "内積" << "  " << naiseki << endl;
  
  v = a*2;
  //2*aとするとエラーを吐いてしまうので注意してください
  cout << "定数倍" << "  " << v.x << " " << v.y << endl;
  
  double siz = a.abs();
  cout << "ベクトルの大きさ" << "  " << siz << endl;
  
  double siz_2 = a.Abs();
  cout << "ベクトルの大きさの二乗" << "  " << siz_2 << endl;
  
  v = a.normalize();
  cout << "単位ベクトル" << " " << v.x << " " << v.y << endl;
}

出力

example_1_out.cpp
加算  6.0000000000000 5.0000000000000
減算  -4.0000000000000 3.0000000000000
内積  9.0000000000000
定数倍  2.0000000000000 8.0000000000000
ベクトルの大きさ  4.1231056256177
ベクトルの大きさの二乗  17.0000000000000
単位ベクトル 0.2425356250363 0.9701425001453

これらを活用した関数

 struct vec2d を貼った後にこの関数も貼ってご活用ください。

夾角

inc.cpp
double inc(vec2d a,vec2d b){
 double cs = (a*b)/a.abs()/b.abs();
 return acos(cs);
}

 二つのベクトルを引数としてとることで、夾角(二つのベクトルの間の角の大きさ)をdouble型で返します。ラジアンです。csにcosを持つので途中でcsを出力させることでcosを得ることも可能です。

偏角

dec.cpp
double dec(vec2d a){
  vec2d v = a.normalize();
  if(a.y>=0){
    double rad = acos(v.x);
    return rad;
  }
  else {
    double rad = acos(v.x)+acos(-1);
    return rad;
  }
}

ベクトルの偏角(x軸を軸と見た時のベクトルの角度)を返します。ラジアンです。これで偏角ソートもはかどります。

終わりに

誤字脱字、コードの間違いなどあったら非常に申し訳ありません。気づきましたら是非お知らせください。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0