Я хочу внести свой ответ в C# на основе ответа Марсело Кантоса, поскольку алгоритм работает очень хорошо. Я написал программу для расчета центроида лазерного луча, спроецированного на матрицу ПЗС. После того, как центроид найден, линия угла направления рисуется, и мне нужна стрелка, указывающая в этом направлении. Поскольку угол вычисляется, стрелка должна будет следовать за углом в любом направлении.
Этот код дает вам гибкость изменения размера головы стрелка, как показано на фотографии.
Сначала вам понадобится векторная структура со всеми необходимыми перегрузками операторов.
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);
}
}
Затем вы можете использовать один и тот же код, заданный Марсела Песню, но я сделал длину и half_width переменной стрелки головы, так что вы можете определить, что при вызове функции.
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 является вторым вектором местоположением (стрелка глава).
Я рисую стрелку, сохраняя значения вектора в точках для функции graphics.DrawPolygon() в System.Drawings.Код показан ниже:
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);
Чтобы уточнить - это конец линии в середине точки основания наконечника стрелки или на наконечнике наконечника стрелки? – Chowlett
Это наконечник наконечника стрелки –