寻找箭头帽的坐标

时间:2014-10-08 08:01:33

标签: c++ math geometry

我必须画一个箭头。我有一个头点和一个尾点现在我需要画一个三角形的箭头帽。一个长度大小为5的三角形。如何找到三角形终点的坐标。有一点是我们的角度为45.so如果我们可以将矢量旋转45来获得它。 `int x1 = arrowStart.X;     int y1 = arrowStart.Y;     int x2 = arrowend.X;     int y2 = arrowend.Y;

PointF arrowPoint=arrowend;

double arrowlength=sqrt(pow(x1-x2,2)+pow(y1-y2,2));

int ArrowMultiplier=1;
double arrowangle=atan2(y1-y2,x1-x2);

double pointx,pointy; 
if(x1>x2)
{
    pointx=x1 - (cos(arrowangle) * (arrowlength-3 * ArrowMultiplier ));
}
else
{
    pointx = cos(arrowangle) * (arrowlength-3 * ArrowMultiplier ) + x1;
}

if (y1 > y2)
{
    pointy = y1 - (sin(arrowangle) * (arrowlength -3 * ArrowMultiplier));
}
else
{
    pointy = (sin(arrowangle) * (arrowlength-3 * ArrowMultiplier )) + y1;
}

PointF arrowPointBack(pointx,pointy);
double angleB = atan2((3 * ArrowMultiplier), (arrowlength - (3 * ArrowMultiplier)));

 double angleC = (3.14) * (90 - (arrowangle * (180 /3.14)) - (angleB * (180 / 3.14))) / 180;


 double secondaryLength = (3 * ArrowMultiplier)/sin(angleB);

  if (x1 > x2)
{
    pointx = x1 - (sin(angleC) * secondaryLength);
}
else
{
    pointx = (sin(angleC) * secondaryLength) + x1;
}

if (y1 > y2)
{
    pointy = y1 - (cos(angleC) * secondaryLength);
}
else
{
    pointy = (cos(angleC) * secondaryLength) + y1;
}

PointF arrowPointLeft((float)pointx, (float)pointy);
 angleC = arrowangle - angleB;

if (x1 > x2)
{
    pointx = x1 - (cos(angleC) * secondaryLength);
}
else
{
    pointx = (cos(angleC) * secondaryLength) +x1;
}

if (y1 > y2)
{
    pointy =y1 - (sin(angleC) * secondaryLength);
}
else
{
    pointy = (sin(angleC) * secondaryLength) + y1;
}

PointF arrowPointRight((float)pointx,(float)pointy);
PointF arrowPoints[4];
arrowPoints[0] = arrowPoint;
arrowPoints[1] = arrowPointLeft;
//arrowPoints[2] = arrowPointBack;
arrowPoints[2] = arrowPointRight;
arrowPoints[3] = arrowPoint;

`

1 个答案:

答案 0 :(得分:1)

是的,我想我应该为你分解一下:

首先,您需要计算箭头所在的角度。这可以通过反正切函数来实现:

atan(diff_y, diff_x)

其中diff_y和diff_x是两个端点的x和y值之间的差异。

然后,您可以将箭头所需的角度添加到此角度,并使用sincos来计算第一个的xy值箭头的额外点。

new_x = head_x - 5 * cos (angle + pi/4)
new_y = head_y + 5 * sin (angle + pi/4)

对于另一点,你也这样做,但减去角度的差异。

new_x = head_x - 5 * cos (angle - pi/4)
new_y = head_y + 5 * sin (angle - pi/4)

然后你拥有所需的所有要点。

我这样做是为了好玩(起诉我,我很无聊)并想出了这个:

#include <math.h>
#include <iostream>

const double arrow_head_length = 3;
const double PI = 3.14159265;
const double arrow_head_angle = PI/6;

//returns the angle between two points, with coordinate1 describing the centre of the circle, with the angle progressing clockwise
double angle_between_points( std::pair<double,double> coordinate1,  std::pair<double,double> coordinate2)
{
  return atan2(coordinate2.second - coordinate1.second, coordinate1.first - coordinate2.first);
}

//calculate the position of a new point [displacement] away from an original point at an angle of [angle]
std::pair<double,double> displacement_angle_offset(std::pair<double,double> coordinate_base, double displacement, double angle)
{
    return std::make_pair
    (
        coordinate_base.first  - displacement * cos(angle),
        coordinate_base.second + displacement * sin(angle)
    );
}

int main()
{
  std::pair<double,double> arrow_tail( 0, 0);
  std::pair<double,double> arrow_head( 15,-15);

  //find the angle of the arrow
  double angle = angle_between_points(arrow_head, arrow_tail);

  //calculate the new positions
  std::pair<double,double> head_point_1 = displacement_angle_offset(arrow_head, arrow_head_length, angle + arrow_head_angle);
  std::pair<double,double> head_point_2 = displacement_angle_offset(arrow_head, arrow_head_length, angle - arrow_head_angle);

  //output the points in order: tail->head->point1->point2->head so if you follow them it draws the arrow
  std::cout << arrow_tail.first   << ',' << arrow_tail.second   << '\n'
            << arrow_head.first   << ',' << arrow_head.second   << '\n'
            << head_point_1.first << ',' << head_point_1.second << '\n'
            << head_point_2.first << ',' << head_point_2.second << '\n'
            << arrow_head.first   << ',' << arrow_head.second   << std::endl;
}

输出可以保存为.csv并加载到excel中,例如,您可以使用它来绘制将形成箭头形状的连接散点图。

如果这是作业,那么在你做任何事情之前,确保你确切知道它是如何工作的。这包括了解诸如以下问题的答案:

  • 在计算角度时,为什么代码会point2_y-point1_ypoint1_x-point2_x
  • 角度0的方向是什么?
  • 为什么角度增加顺时针而不是逆时针?
  • 当只需要4个点时,为什么有5个输出?
  • 代码中PI/6的重要性是什么?它不是== 45度。为什么这个角度更好?

另请注意,此问题和答案现在会在Google搜索中弹出。

工作示例:http://ideone.com/D4IwOy

您可以将输出粘贴到任何图表工具(such as this one)或保存为.csv并在选择的Excel /电子表格中打开,并绘制散点图以查看箭头坐标。请注意,它(令人讨厌)不会使xy比例保持相等,因此会像这样拉伸箭头:

3,7
24,15
21.0381,15.4768
22.1061,12.6734
24,15