У меня есть программа моделирования лучей, которая находит пересечения луча и краев многоугольника. В моем фрагменте кода ниже у меня есть луч и край в виде y = mx + b линии. Я определил квадрат по его вершинам ((50, 50), (50, 70), (70, 70), (70, 50))
и направил лучи к каждой вершине, и моя программа вычислила пересечение с каждой вершиной, кроме (70, 70)
и (70, 50)
. В последнем случае луч, казалось, «проскользнул» через эту вершину и пересек линию, проходящую через точки (50, 50)
и (50, 70)
в неожиданной точке (49.99999999999999 16.666666666666643)
. Чтобы уточнить, вот все пересечения, обнаруженные моей программой:
(50.0, 50.00000000000001) # Ray was cast towards (50, 50)
(50.0, 70.0) # Ray was cast towards (50, 70)
(50.0, 50.00000000000001) # Ray was cast towards (70, 70). Also unexpected
(49.99999999999999, 16.666666666666643) # Ray was cast towards (70, 50) Unexpected intersection value
В моем файле objects.py:
from math import atan, pi
class Ray:
def __init__(self, origin, direction):
self.origin = origin
self.direction = direction # radians
self.endpoint = None
self.hit = False
def set_endpoint(self, point):
self.endpoint = point
def set_hit(self):
self.hit = True
class Line:
def __init__(self, endpoint1, endpoint2):
self.p1 = endpoint1
self.p2 = endpoint2
def direction(self):
delta_x = self.p2[0] - self.p1[0]
delta_y = self.p2[1] - self.p1[1]
if delta_x == 0: # Undefined slope
if delta_y > 0:
return pi / 2
else:
return 3 * pi / 2
else:
return atan(delta_y / delta_x)
class Polygon:
def __init__(self, vertices):
self.vertices = vertices
def edges(self):
edges = []
for i in range(len(self.vertices)):
# We mod the endpoint point of the line by the amount of vertices
# since we want the endpoint of our last edge to be the first vertex
edges.append(Line(self.vertices[i], self.vertices[(i + 1) % len(self.vertices)]))
return edges
И в моем файле caster.py:
from ART import objects
from math import tan
class ShadowCaster:
def __init__(self, source, polygons):
self.source = source
self.polygons = polygons
self.rays = []
print(self.polygons)
def cast_rays(self):
for polygon in self.polygons:
for vertex in polygon.vertices:
direction_to_vertex = objects.Line(self.source, vertex).direction()
ray = objects.Ray(self.source, direction_to_vertex)
self.rays.append(ray)
def process_endpoints(self):
for ray in self.rays:
for polygon in self.polygons:
for edge in polygon.edges():
# We are given the endpoints and direction of both the ray and the edge. Find intersection.
# We want to obtain the general form y = mx + b for the ray and edge.
# Given: y, m, x; solve for b
# b = y - mx
if not ray.hit:
ray_x = ray.origin[0]
ray_y = ray.origin[1]
ray_m = tan(ray.direction)
ray_b = ray_y - ray_m * ray_x
edge_x = edge.p1[0] # Using either p1 or p2 is fine since the line passes through both.
edge_y = edge.p1[1]
edge_m = tan(edge.direction())
edge_b = edge_y - edge_m * edge_x
# General case
# {y = ax + b
# {y = cx + d
#
# => ax + b = cx + d
# => x(a - c) = d - b
# => x = (d - b) / (a - c) therefore y = a((d - b) / (a - c)) + b
intersect_x = (edge_b - ray_b) / (ray_m - edge_m)
intersect_y = ray_m * intersect_x + ray_b
print(intersect_x, intersect_y)
ray.set_endpoint((intersect_x, intersect_y))
ray.set_hit()
l oop, который я запускаю:
caster = engine.ShadowCaster(origin=(100, 100), polygons=[objects.Polygon(((50, 50), (50, 70), (70, 70), (70, 50)))])
while 1:
caster.cast_rays()
caster.process_endpoints()
Есть предложения о том, что я мог сделать неправильно?