Houdini Labs VEXの説明書

# はじめに
### 概要
SideFXLabs19.5.519で追加されたLabs VEXについて少し深堀していこうと思う。
※本検証は2023/02/18時点で追加されている関数です。

### 環境
Houdini19.5
SideFXLabs19.5.519

# そもそもLabs VEXってなに？
Labs VEXは新しいノードやVEX関数が追加されたわけではなく、SideFXLabsのインストールディレクトリ内にあるvex/includeに追加された、```sidefxlabs_data.h``` ```sidefxlabs_math.h```のことである。
ベクトル演算、データの並べ替え、変換などに便利なヘルパー関数が追加されているそうです。
使い方はAttributeWrangle SOPで以下のように記述すると使えるようになる。
```C##:vex
#include <sidefxlabs_math.h>
#include <sidefxlabs_data.h>

```
include分の詳しい挙動に関しては以下を参照してください。
[【Houdini】vexのinclude文の挙動@harayoki](https://qiita.com/harayoki/items/e934586035aa3a0f603a)
[VEX言語リファレンス](https://www.sidefx.com/ja/docs/houdini/vex/lang.html)

# Labs VEXの関数一覧
Labs VEXはsidefxlabs_data.hに3種、sidefxlabs_math.hに19種の系22種の関数が用意されている。(2023/02/12現在)

```C##:sidefxlabs_data.h
labs_ftoa
labs_binary_search
labs_append_unique
```
```C##:sidefxlabs_math.h
labs_triarea
labs_planenormal
labs_istotheright
labs_isabove
labs_pointplanedist
labs_pointplaneproj
labs_pointlinedist
labs_pointlineproj
labs_pointsegmentdist
labs_pointsegmentproj
labs_isoutsidetri
labs_pointtriedgedist
labs_pointtriedgeproj
labs_pointtridist
labs_pointtriproj
labs_anglebetween
labs_rotatevector
labs_rotatevector2d
labs_getnoncollinear
```
この関数たちを1つずつ検証していきます。

## sidefxlabs_data.h
### labs_ftoa
float からStringに変換する関数
```C#:labs_ftoa
string labs_ftoa(number <float>)
string labs_ftoa(numer <float>, size <int>)
```
**number** : 変換したい数値
**size** : 小数点以下の桁数

ちなみにこちらはデフォルトだとエラーが出ます。(2023/02/18現在)
sidefxlabs_data.hファイルを書き換える必要があるため推奨しません。
<details><summary>修正方法</summary>

関数の順番を入れ替えることで使用可能になる
```C#: old(default)
string labs_ftoa(const float f)
{
    return labs_ftoa(f, 3);
}
string labs_ftoa(const float f; const int decimal_places)
{
    return sprintf("%.*g", decimal_places + 1, f);
}
```

```C#:new
string labs_ftoa(const float f; const int decimal_places)
{
    return sprintf("%.*g", decimal_places + 1, f);
}

string labs_ftoa(const float f)
{
    return labs_ftoa(f, 3);
}
```
</details>

### labs_binary_search
バイナリサーチを行う関数。
```C#:labs_binary_search
float labs_binary_search(array[] <int/float>, target <int/float>,  &success <int>)
int labs_binary_search(array[] <string>, target <string>, &success <int>)
```
**array[]** : 探索元の配列
**target** : 検索したい値 (失敗時は-1)
**&success** : 検索成功か否かの値を返す(1 or 0)

```&success```は返り値のため、変数を入れます。

### labs_append_unique
配列に値が存在しない場合のみ値を追加できる関数。ある場合はスキップ。
```C#:labs_append_unique
void labs_append_unique(array[] <type[]>, value <type>)
void labs_append_unique(str <string>, value <string>)
```
**array[]** : 追加元の配列
**value** : 追加したい値 
**str** : 追加元の文字列
int/float/vector2/vector/vector4/string配列対応

## sidefxlabs_math.h
### labs_triarea
Primitive(三角形)の面積を求める関数。
```C#:labs_triarea
float labs_triarea(geohandle <int>, prim_num <int>)
float labs_triarea(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>)

float labs_triarea(a <vector>, b <vector>, c <vector>)
```

### labs_planenormal
Primitive(三角形)の法線を求める関数。
```C#:labs_planenormal
vector labs_planenormal(geohandle <int>, prim_num <int>, is_normalize <int>)
vector labs_planenormal(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, is_normalize <int>)

vector labs_planenormal(a <vector>, b <vector>, c <vector>, is_normalize <int>)
```
**is_normalize** : 返り値を正規化するか否か。
左手の法則 (Houdini のデフォルトの面巻き順序) を使用します。
正規化されていない場合、出力ベクトルの大きさは入力三角形の面積になります。

### labs_istotheright
任意点が特定の位置より右側にあるかを判定する関数。
```C#:labs_istotheright
int labs_istotheright(pivot <vector>, forward <vector>, up <vector>, pos <vector>)
```
**forward** : 前方ベクトル 
**up** : 上向きベクトル

### labs_isabove
任意点が面(三角形)より上(normal方向)にあるかを判定する関数。
```C#:labs_isabove
int labs_isabove(geohandle <int>, prim_num <int>, pos <vector>)
int labs_isabove(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>)

int labs_isabove(plane_pos <vector>, plane_normal <vector>, pos <vector>)
int labs_isabove(a <vector>, b <vector>, c <vector>, pos <vector>)
```

### labs_pointplanedist
ポイントからと無限平面までの距離を求める関数。
```C#:labs_pointplanedist
float labs_pointplanedist(geohandle <int>, prim_num <int>, pos <vector>)
float labs_pointplanedist(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>)

float labs_pointplanedist(plane_pos <vector>, plane_normal <vector>, pos <vector>)
float labs_pointplanedist(a <vector>, b <vector>, c <vector>, pos <vector>)
```
ポイントa/b/cまたはpt0/pt1/pt2の3点から構成される面が計算される。

### labs_pointplaneproj
ポイントから無限平面までの距離と最近接点を求める関数。
```C#:labs_pointplaneproj
float labs_pointplaneproj(geohandle <int>, prim_num <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointplaneproj(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>, &nearest_pos <vector>)

float labs_pointplaneproj(plane_pos <vector>, plane_unit_normal <vector>, pos <vector>, &nearest_pos <vector>)
float labs_pointplaneproj(a <vector>, b <vector>, c <vector>, pos <vector>, &nearest_pos <vector>)
```
```&nearest_pos```は返り値のため、変数を入れます。

### labs_pointlinedist
ポイントからと無限直線までの距離を求める関数。
```C#:labs_pointlinedist
float labs_pointlinedist(geohandle <int>, prim_num <int>, pos <vector>)
float labs_pointlinedist(geohandle <int>, pt0 <int>, pt1 <int>, pos <vector>)
float labs_pointlinedist(line_pos <vector>, line_direction <vector>, pos <vector>)
```
これは、外積 (三角面積) アプローチよりも正確です。

### labs_pointlineproj
ポイントから無限直線までの距離と最近接点を求める関数。
```C#:labs_pointlineproj
float labs_pointlineproj(geohandle <int>, prim_num <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointlineproj(geohandle <int>, pt0 <int>, pt1 <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointlineproj(line_pos <vector>, line_direction <vector>, pos <vector>, &nearest_pos <vector>)
```
```&nearest_pos```は返り値のため、変数を入れます。

### labs_pointsegmentdist
ポイントから無限直線までの距離を求める関数。
```C#:labs_pointsegmentdist
float labs_pointsegmentdist(geohandle <int>, prim_num <int>, pos <vector>)
float labs_pointsegmentdist(geohandle <int>, pt0 <int>, pt1 <int>, pos <vector>)
float labs_pointsegmentdist(a <vector>, b <vector>, pos <vector>)
```

### labs_pointsegmentproj
ポイントから無限直線までの距離と最近接点を求める関数。
```C#:labs_pointsegmentproj
float labs_pointsegmentproj(geohandle <int>, prim_num <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointsegmentproj(geohandle <int>, pt0 <int>, pt1 <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointsegmentproj(a <vector>, b <vector>, pos <vector>, &nearest_pos <vector>)
```
```&nearest_pos```は返り値のため、変数を入れます。

### labs_isoutsidetri
ポイントが三角面内にあるかを判定する関数。
```C#:labs_isoutsidetri
int labs_isoutsidetri(geohandle <int>, prim_num <int>, pos <vector>)
int labs_isoutsidetri(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>)
int labs_isoutsidetri(a <vector>, b <vector>, c <vector>, pos <vector>)
```
三角面の内側の場合は-1、辺上なら0、外側なら1を返す。

### labs_pointtriedgedist
ポイントが三角形の辺までの距離を求める関数。
```C#:labs_pointtriedgedist
float labs_pointtriedgedist(geohandle <int>, prim_num <int>, pos <vector>)
float labs_pointtriedgedist(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>)
float labs_pointtriedgedist(a <vector>, b <vector>, c <vector>, pos <vector>)
```
三角面の内側の場合は負、外側なら正の値を返す。

### labs_pointtriedgeproj
ポイントが三角形の辺までの距離と最近接点を求める関数。
```C#:labs_pointtriedgeproj
float labs_pointtriedgeproj(geohandle <int>, prim_num <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointtriedgeproj(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointtriedgeproj(a <vector>, b <vector>, c <vector>, pos <vector>, &nearest_pos <vector>)
```
```&nearest_pos```は返り値のため、変数を入れます。
三角面の内側の場合は負、外側なら正の値を返す。

### labs_pointtridist
ポイントが三角形の面（無限平面）までの距離を求める関数。
```C#:labs_pointtridist
float labs_pointtridist(geohandle <int>, prim_num <int>, pos <vector>)
float labs_pointtridist(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>)
float labs_pointtridist(a <vector>, b <vector>, c <vector>, pos <vector>)
```

### labs_pointtriproj
ポイントが三角形の面（無限平面）までの距離と最近接点を求める関数。
```C#:labs_pointtriproj
float labs_pointtriproj(geohandle <int>, prim_num <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointtriproj(geohandle <int>, pt0 <int>, pt1 <int>, pt2 <int>, pos <vector>, &nearest_pos <vector>)
float labs_pointtriproj(a <vector>, b <vector>, c <vector>, pos <vector>, &nearest_pos <vector>)
```
```&nearest_pos```は返り値のため、変数を入れます。

### labs_anglebetween
2辺の間の角度を求める関数。
```C#:labs_anglebetween
float labs_anglebetween(a <vector>, b <vector>, is_degrees <int>)
```
**is_degree** : 返り値がDegreeなら1を、Radianなら0を設定する。

### labs_rotatevector
ベクトルを回転する関数。
```C#:labs_rotatevector
vector labs_rotatevector(v <vector>, angle <float>, axis <vector>, is_degrees <int>)
vector labs_rotatevector(v <vector>, a <vector>, b <vector>)
```
**is_degree** : angleの値がDegreeなら1を、Radianなら0を設定する。
aからbまで回転する量だけvを回転させる。

### labs_rotatevector2d
2Dベクトルを回転する関数。
```C#:labs_rotatevector2d
vector2 labs_rotatevector2d(v <vector2>, angle <float>, is_degrees <int>)
vector2 labs_rotatevector2d(v <vector2>, a <vector2>, b <vector2>)
```
**is_degree** : angleの値がDegreeなら1を、Radianなら0を設定する。
aからbまで回転する量だけvを回転させる。

### labs_getnoncollinear
非コリニアベクトルを求める関数。
```C#:labs_getnoncollinear
vector labs_getnoncollinear(v <vector>)
```
｛Z,X,-Y｝のベクトルを返す。


# おわりに
基本的にはヘルパー関数なので、シンプルな関数が多い印象ですね。微妙に使える部分も多いのかな...？
もっと関数の種類が増えるといいですね。

それでは、しゃーした～。