Здравствуйте.
Вот например, есть луч и есть отрезок. Тырим в интернете формулы, находим градус отражённого луча и говорим, что это мы сами сделали.
Но вот проблема. На всех четырёх скриншотах луч отражается туда же, откуда был послан. Значит, угол должен быть 90 градусов (или PI / 2
радиан). На первых трёх скриншотах так и есть. А на последнем выдаёт 270 градусов.
Line MakeLine(double x1, double y1, double x2, double y2)
{
Line resLine;
resLine.pt1 = Vec2{ x1, y1 };
resLine.pt2 = Vec2{ x2, y2 };
Vec2 direction = VectorNormalize(VectorDirection(resLine.pt1, resLine.pt2));
resLine.angle = VectorsAngle(resLine.pt1, resLine.pt1 + direction);
resLine.normal = VectorNormal(direction);
return resLine;
}
case WM_MOUSEMOVE:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
if (canDrag)
{
Vec2 tmpPos = Vec2{ (double)x, (double)y };
if (!PointInCircle(ray.origin, tmpPos, circle.radius))
circle.position = tmpPos;
}
else
{
ray.direction = VectorNormalize(Vec2{ (double)x, (double)y } - ray.origin);
ray.angle = VectorsAngle(ray.origin, ray.origin + ray.direction);
}
InvalidateRect(hMainWindow, nullptr, false);
break;
}
Vec2 GetReflectedDirection(Ray ray, Line line)
{
return ray.direction - (line.normal * VectorsProductDot(line.normal, ray.direction) * 2.0);
}
Ray GetReflectedRay(Ray ray, Line line, Vec2 intersectionPoint)
{
Ray resRay;
resRay.origin = intersectionPoint;
resRay.direction = VectorNormalize(GetReflectedDirection(ray, line));
resRay.angle = VectorsAngle(resRay.origin, resRay.origin + resRay.direction);
return resRay;
}
Vec2 GetReflectedDirection(Ray ray, Circle circle, Vec2 intersectionPoint)
{
Vec2 normal = VectorNormalize(intersectionPoint - circle.position);
return ray.direction - (normal * VectorsProductDot(normal, ray.direction) * 2.0);
}
Ray GetReflectedRay(Ray ray, Circle circle, Vec2 intersectionPoint)
{
Ray resRay;
resRay.origin = intersectionPoint;
resRay.direction = VectorNormalize(GetReflectedDirection(ray, circle, intersectionPoint));;
resRay.angle = VectorsAngle(resRay.origin, resRay.origin + resRay.direction);
return resRay;
}
std::vector<Vec2> points = GetIntersectionPoints(ray, circle);
if (points.size() > 0)
{
double len = VectorsDistance(ray.origin, points[0]);
DrawRay(dcMem, ray, len);
SelectObject(dcMem, (HBRUSH)GetStockObject(WHITE_BRUSH));
DrawCircle(dcMem, (int)points[0].x, (int)points[0].y, 5);
Ray reflectedRay = GetReflectedRay(ray, circle, points[0]);
DrawRay(dcMem, reflectedRay, 3000.0);
Vec2 normal = VectorNormalize(points[0] - circle.position);
Vec2 normal90 = VectorNormal(normal);
Vec2 pt1 = points[0] + normal90 * 100;
Vec2 pt2 = points[0] - normal90 * 100;
Line line = MakeLine(pt1.x, pt1.y, pt2.x, pt2.y);
DrawLine(dcMem, line);
std::cout << "Line angle: " << RadToDeg(line.angle) << std::endl;
std::cout << "Ray angle: " << RadToDeg(reflectedRay.angle) << std::endl;
reflectedRay = GetReflectedRay(ray, line, points[0]);
double intersectionAngle = fabs(line.angle - reflectedRay.angle);
std::cout << "Intersected in [" << points[0].x << " " << points[0].y << "] " <<
RadToDeg(intersectionAngle) << " degrees" << std::endl;
}
else
{
DrawRay(dcMem, ray, 3000.0);
}
Как поправить код, чтобы со всех сторон под прямым углом выдавало 90?
Знаю один ламерский способ. Проверять, чтобы всегда было line.pt1 < line.pt2
. Но, по-моему, это не правильно с математической точки зрения.