РЕШЕНО: см. мой ответ.
Я пытаюсь найти точку, которая находится внутри дуги, поэтому, когда происходит заливка, она случайно не заполняет область за пределами дуги. Пока абсолютное значение расстояния между двумя углами: начало и конец; меньше, чем PI, это работает (есть пара крайних случаев, когда нарисованные линии настолько близки, что выбранная точка является частью этих линий, но это для другого дня...).
Проблема, с которой я сталкиваюсь, заключается в том, что когда абсолютное значение расстояния между начальным и конечным углами больше, чем PI, затопление происходит на внешней стороне дуги, а не на внутренней. Один из многих примеров: если дуга начинается в 0 и заканчивается в 3PI/2, абсолютное значение расстояния равно 3PI/2, заполнение происходит между углами, как если бы абсолютное значение расстояния было PI/2, и заполняет весь экран. кроме дуги в форме pacman.
РЕДАКТИРОВАТЬ:
Чтобы не было путаницы, вот определение дуги по аллегро (и вообще по тригонометрии):
void arc(BITMAP *bmp, int x, y, фиксированный ang1, ang2, int r, int color);
Рисует дугу окружности [минус начальная/конечная стороны или центральная точка] с центром [так в оригинале] x, y и радиусом r в направлении против часовой стрелки [так в оригинале], начиная с угла a1 и заканчивая, когда он достигает a2....Ноль находится справа от центральной [так в оригинале] точки, и большие значения вращаются оттуда против часовой стрелки [так в оригинале].
Квадратные скобки - это мое обозначение.
Я уже позаботился о переходе от аллегро (глупого) использования 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);
}
}
}
}