3
\$\begingroup\$

I am trying to calculate the reflection of a laser within a polygon. My current calculations are probably quite long-winded because I'm building on line intersection and other functions. The problem is that I'm using a point (x,y) with velocity(x,y) and trying to calculate where the point is after each reflection off a line - this is a problem because when the point reflects within very small corners I can't seem to calculate the final location and velocity of the laser point.

Is there a well known algorithm for calculating laser reflection in 2D within polygons?

Note: I would post my code but as stated above it's extremely long ATM.

My general logic is:

Call method with particle {x,y,velocity={x,y}}
Begin loop
  Check for intersections
  If no intersections then exit
  Get closest intersection to particle
  Update particle location, direction and velocity
End loop
Refresh particle velocity (to maintain speed)
Return particle

I was hoping there something a bit more concise for this (basic?) math problem.

\$\endgroup\$
  • \$\begingroup\$ What is the problem within small corners? Do you run into rounding errors? \$\endgroup\$ – Fault Jun 23 '14 at 9:32
  • \$\begingroup\$ I can't come up with an algorithm that can handle the multiple bounces within a tight space. I would like to know if there is an industry standard for this as it's beating me right now and it must have been solved many times before. \$\endgroup\$ – Matt W Jun 23 '14 at 9:38
  • \$\begingroup\$ You might be able to solve the small corner problem by giving your algorithm a maximum number of bounces before giving up. \$\endgroup\$ – Nicolas Louis Guillemot Jun 23 '14 at 9:56
  • \$\begingroup\$ It doesn't get that far. I'd really like to know if there is a piece of code to do this available, as I can't find any. \$\endgroup\$ – Matt W Jun 23 '14 at 10:09
2
\$\begingroup\$

One approach to simplifying this is to spawn new lasers instead of trying to work out reflection points on single beams.

E.g.

enter image description here

Here the red laser shot is moving out of the rectangle, and we detect this by testing intersection on each boundary of our rectangle. Since we have detected that it's moving out (And therefore hit a reflective surface) we place a new laser beam at a point that intersects with the reflective surface and the red laser. We place it such that the correct amount of laser is discarded outside the boundary.

For clarity in the diagram, our new reflection is green.

Immediately, we test the new laser for intersection on the other boundaries and if it too intersects we spawn a third (Blue in our example) and so on until we have no intersections with new boundaries.

In this way we can support multiple reflections on single updates.

To render, clip all lasers to the boundary object and discard forever any which have moved completely outside.

I'd imagine that a variant of this approach could be figured out for solid beams and not the 'shot' type blaster lasers described here.

A demo of a game that does this exact thing is here.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thank you - you've actually made me realise that I was probably going about this the hard way (though my pseudo-code above isn't very complex.) I'm going to rewrite with a closure to check the current location/intersections and have an outer loop to test for current positions, etc. \$\endgroup\$ – Matt W Jun 23 '14 at 12:45
0
\$\begingroup\$

I had a similar problem in some other code I wrote. Didn't find a pre-written algorithm with my (admittedly quick) search. This was in python, so this might not be too helpful for you.

Firstly, I stored my line to test as a point and an angle. This made a lot of the calculations easier, and let me put the math library to good use.

My intersection test function returned a point, though in your case it would also need to return another angle. In the case of multiple reflections the following pattern may be useful:

getNextLine(line, polygon, n = maxReflections)
   if n = 0: return line #Max number of tests reached
   next = intersection(line, polygon)
   if next = None:
       return line
   else:
       return getNextLine(next, n-1)

In this case intersection would be your ready-made intersection finder. (I assumed it returns None if there is no intersection)

One thing to watch out, that got me, is that you can end up with multiple intersections and need to make sure you pick the closest.

Without knowing more about your application I can't really say much more, hope this helps.

\$\endgroup\$
  • \$\begingroup\$ I've tried working the logic in a single loop and keeping track of the laser 'particle' within the loop, but I think the variables got too complex to maintain. I'm going to try an 'until false' loop and use a closure function to check the particle intersections. \$\endgroup\$ – Matt W Jun 23 '14 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.