アルゴリズムが非常にうまく機能するため、Marcelo Cantos の回答に基づいて C# で回答を提供したいと思います。CCDアレイに投影されたレーザービームの重心を計算するプログラムを書きました。重心が見つかった後、方向角度線が描かれ、その方向を指す矢印の頭が必要です。角度が計算されるため、矢印の先端はいずれかの方向の角度に従う必要があります。
このコードを使用すると、図に示すように矢印のサイズを柔軟に変更できます。
まず、必要なすべての演算子をオーバーロードした vector 構造体が必要です。
private struct vec
{
public float x;
public float y;
public vec(float x, float y)
{
this.x = x;
this.y = y;
}
public static vec operator -(vec v1, vec v2)
{
return new vec(v1.x - v2.x, v1.y - v2.y);
}
public static vec operator +(vec v1, vec v2)
{
return new vec(v1.x + v2.x, v1.y + v2.y);
}
public static vec operator /(vec v1, float number)
{
return new vec(v1.x / number, v1.y / number);
}
public static vec operator *(vec v1, float number)
{
return new vec(v1.x * number, v1.y * number);
}
public static vec operator *(float number, vec v1)
{
return new vec(v1.x * number, v1.y * number);
}
public float length()
{
double distance;
distance = (this.x * this.x) + (this.y * this.y);
return (float)Math.Sqrt(distance);
}
}
次に、Marcelo Cantos によって提供された同じコードを使用できますが、関数を呼び出すときに定義できるように、矢頭変数の長さと半幅を作成しました。
private void arrowhead(float length, float half_width,
vec A, vec B, ref vec v1, ref vec v2)
{
float h = length * (float)Math.Sqrt(3);
float w = half_width;
vec U = (B - A) / (B - A).length();
vec V = new vec(-U.y, U.x);
v1 = B - h * U + w * V;
v2 = B - h * U - w * V;
}
これで、次のように関数を呼び出すことができます:
vec leftArrowHead = new vec();
vec rightArrowHead = new vec();
arrowhead(20, 10, new vec(circle_center_x, circle_center_y),
new vec(x_centroid_pixel, y_centroid_pixel),
ref leftArrowHead, ref rightArrowHead);
私のコードでは、円の中心が最初のベクトル位置 (矢尻) であり、centroid_pixel が 2 番目のベクトル位置 (矢頭) です。
System.Drawings の graphics.DrawPolygon() 関数のポイントにベクトル値を格納して、矢印の頭を描画します。コードを以下に示します。
Point[] ppts = new Point[3];
ppts[0] = new Point((int)leftArrowHead.x, (int)leftArrowHead.y);
ppts[1] = new Point(x_cm_pixel,y_cm_pixel);
ppts[2] = new Point((int)rightArrowHead.x, (int)rightArrowHead.y);
g2.DrawPolygon(p, ppts);