找到一个位于扇区内部的点
Finding a point that is interior to a sector
已解决:请参阅我的答案。
我试图找到一个弧内部的点,这样当发生溢流时,它就不会意外地填充弧外的区域。只要两个角度之间的距离的绝对值:起点和终点;小于PI,这是可行的(有几个极端的边缘情况,绘制的线非常接近,以至于拾取的点是这些线的一部分,但这是另一天的情况…)。
我遇到的问题是,当起点角和终点角之间的距离的绝对值大于PI时,洪水发生在弧的外部,而不是内部。其中一个例子是:如果弧从0开始,到3PI/2结束,距离的绝对值为3PI/2,则在角度之间发生洪水,就像绝对值距离为PI/2一样,并洪水淹没除太平洋人形弧之外的整个屏幕。
编辑:
为了避免混淆,以下是根据快板(以及一般的三角法)对弧的定义:
空心弧(BITMAP*bmp,int x,y,固定的ang1,ang2,int r,int color);
在逆时针方向,从角度a1开始,到达到a2…零在中心点的右边,更大值从此处逆时针旋转。
方括号是我的符号。
我已经处理好了从allegro(愚蠢的)使用fixed integers
到正确的radian
值的转换。
结束编辑
void Arc::Draw(BITMAP* dest, int color, bool filled, bool showCenter, bool showSides) {
if(showSides || filled) {
Line initial(GetX(), GetY(), GetZ(), GetStartPoint().GetX(), GetStartPoint().GetY(), GetZ(), false);
initial.SetColor(color);
Line terminal(GetX(), GetY(), GetZ(), GetEndPoint().GetX(), GetEndPoint().GetY(), GetZ(), false);
terminal.SetColor(color);
initial.Draw(dest, initial.GetColor(), false);
terminal.Draw(dest, terminal.GetColor(), false);
} else if(showCenter) {
putpixel(dest, GetX(), GetY(), color);
}
//Draw arc first to prevent flood overflow.
arc(dest, GetX(), GetY(), AngleConverter::RadianToFixed(_startAngle), AngleConverter::RadianToFixed(_endAngle), _radius, color);
if(filled) {
double distance = std::fabs(this->_endAngle - this->_startAngle);
if(distance < a2de::A2DE_PI) {
Line displace(GetStartPoint(), GetEndPoint(), false);
Point displacePoint(displace.GetCenter());
floodfill(dest, displacePoint.GetX(), displacePoint.GetY(), color);
} else if(distance > a2de::A2DE_PI) {
Line displace(GetStartPoint(), GetEndPoint(), false);
Vector2D center_of_displacement(displace.GetCenter());
Vector2D center_point(this->_center);
Vector2D direction_of_center(center_of_displacement - center_point);
double angle = std::atan2(direction_of_center.GetY(), direction_of_center.GetX());
Vector2D flood_point = center_point - direction_of_center;
flood_point += angle;
double x = flood_point.GetX() > 0.0 ? std::ceilf(flood_point.GetX()) : std::floorf(flood_point.GetX());
double y = flood_point.GetY() > 0.0 ? std::ceilf(flood_point.GetY()) : std::floorf(flood_point.GetY());
floodfill(dest, x, y, color);
} else {
if(_startAngle == 0.0 || _endAngle == a2de::A2DE_2PI) {
floodfill(dest, GetX(), GetY() - 1, color);
} else if(_endAngle == 0.0 || _startAngle == a2de::A2DE_PI) {
floodfill(dest, GetX(), GetY() + 1, color);
}
}
}
}
首先,关于您的"sic"注释。圆心通常也被称为弧的中心,逆时针是最常见的约定。正如x轴向右,y轴向上,角度从正x轴开始。
要确定点x,y是否在极坐标(r,eta)定义的区域内,只需将点x_point,y_point转换为极坐标
r_point=sqrt((x_point-x_circle)^2 + (y_point-y_circle)^2 )
eta_point=atan2((y_point-y_circle) , (y_point-x_circle))
使用atan2,那么你不需要考虑符号和pi翻转等。在c++中atan2和atan2有什么区别?
Now, is the radious within the 'sector' ?
if (r_point<r_sector) ...
如果是这种情况,那么值得一看角度部分:从eta_point和扇区的角度大小中减去星形角度
eta_point_new = eta_point - ang1
ang2_new = ang2 - ang1
现在,ang2_new是扇区在旋转方向上的大小,eta_point_new是点的距离。如果ang2_new为负,则意味着扇区越过了角坐标的边界,因此需要向其添加2pi。然后:
if (eta_point_new < ang2_new)
... then the point is inside...
很抱歉,我没有时间测试它,也没有时间用合适的C++编写它,你喜欢怎么做就怎么做。
正旋转方向为逆时针方向。我给出的是伪代码,而不是真正的C++代码。
要确定旋转角度,请从结束角度减去开始角度。不要取绝对值。归一化到区间[0,2π)。
rot_angle = end_angle - start_angle;
while (rot_angle < 0)
rot_angle += TWO_PI;
现在我们需要在弧的中心和起点之间取一个点,并将其绕中心旋转我们刚刚发现的总旋转角度的一半:
start_point = rotate (point (center.x+r, center.y), center, start_angle);
interior_point = rotate (midpoint (center, start_point), center, rot_angle/2);
将点pt
绕原点o
旋转角度theta
:
point rotate (point pt, point o, double theta)
{
return point(cos(theta) * (pt.x-o.x) - sin(theta) * (pt.y-o.y) + o.x,
sin(theta) * (pt.x-o.x) + cos(theta) * (pt.y-o.y) + o.y);
}
完整性:
point midpoint (point p1, point p2)
{
return point((p1.x+p2.x)/2, (p1.y+p2.y)/2);
}
已解决:
1) 计算圆心:
double e = GetEndAngle();
double s = GetStartAngle();
double d = e - s;
double arc_center_x = 0.0;
double arc_center_y = 0.0;
double offset = 0.0;
if(d < 0.0) {
offset = PI;
}
arc_center_x = (GetPosition().GetX() + std::cos(((s + e) / 2.0) + offset) * GetRadius());
arc_center_y = (GetPosition().GetY() + -std::sin(((s + e) / 2.0) + offset) * GetRadius());
_center = Vector2D(x, y);
2) 计算从该中心到扇区位置的直线:
Line l(arc_center_x, arc_center_y, p_x, p_y);
3) 获取始终位于扇区角度内部的线的中点:
double x = l.GetCenter().GetX();
double y = l.GetCenter().GetY();
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- "constinit"和"constexpr"之间的真正区别是什么?
- ((int) a) 和 (int(a)) 之间的区别是什么?
- 如何完全删除窗口的非工作区?
- 在Visual Studio Code(.json配置)中设置相对于工作区路径的c / c ++项目的包含路径
- 如何使用ATA命令读取磁盘的特定扇区
- 获得有关硬盘扇区中原始数据更改的通知-文件更改通知
- 如何以编程方式使用 MBR 和 USB 闪存扇区
- 写入文件的原始磁盘扇区
- 找到一个位于扇区内部的点
- 如何使用 SDL 2 和 C++ 绘制椭圆的填充扇区
- CFile将如何处理坏扇区
- 原始读取带有 fstream 的引导扇区
- C++将数据写入随机HDD扇区
- 使用哪个小部件将硬盘扇区显示为十六进制
- 在Linux上用c++读取硬盘扇区
- ReadFile FILE_FLAG_NO_BUFFERING如何读取两个扇区之间的数据
- 写入文件失败,错误码为87,每个扇区磁盘4096字节
- DeviceIoControl返回意外的物理扇区大小
- 如何在CD或DVD上获得扇区的准确位置和角度(数据位置测量)