已解决:请参阅我的答案。
我试图找到一个位于弧内部的点,因此当发生洪水填充时,它不会意外填充弧外的区域。只要两个角之间距离的绝对值:start和end;小于 PI 这有效(有几个极端的边缘情况,其中绘制的线非常接近,以至于选择的点是这些线的一部分,但那是不同的一天......)。
我遇到的问题是,当开始角和结束角之间的距离的绝对值大于 PI 时,洪水发生在弧的外部而不是内部。许多例子之一是:如果弧从 0 开始并以 3PI/2 结束,则距离的绝对值为 3PI/2,泛光发生在角度之间,就好像绝对值距离为 PI/2 并泛滥整个屏幕除了吃豆人形的弧线。
编辑:
为避免混淆,这里是根据 allegro(以及一般的三角学)定义的弧:
void arc(BITMAP *bmp, int x, y, fixed ang1, ang2, int r, int color);
以逆时针 [sic] 方向绘制圆弧 [减去初始/终止边或中心点],中心 [sic] x, y 和半径 r,从角度 a1 开始,在到达 a2 时结束......零位于中心 [sic] 点的右侧,较大的值从那里逆时针旋转 [sic]。
方括号是我的符号。
我已经处理了从 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);
}
}
}
}