http://GameProgrammer.Com

Programming

GP Mailing List
     Thread Index
     Date Index

ATXGPSIG List
     Thread Index
     Date Index

Google
>

Home

Wise2Food



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GP: Flipping a point across a line: The answer



Hi all,

I'm brand-new to this list and so far I've seen a lot of excellent
information on where to start, sources of info etc. Thanks for
everything
so far.

Anyway, sorry to bring this one back up after it seems to have been left
to lie for a while but I've just read this and think there are a few
things worth pointing out about the answers given so far.

Eudoxus3 wrote:
> 
> ...
> 
> // declare variables to use, integers are Ok.
> declare A, B, C, D, E, Y, M, ZZ, P
> ...
> // so, from here we want to get `D`, which will also have x and y values...
> // this bit calculates where a line from C to A,B at a right angle will
> // intersect...
> Y = (B.y - A.y) / (B.x - A.x)

The basic algorithm everyone has used is correct, but there are a few
problems with it - (above) what if B.x == A.x? Especially if you're
using
integer display-coords? I saw another mail involving tan(), cos() etc 
which has a related problem - arctan(what?) == 90 degrees?

A more reliable approach for doing this type of operation (this sort of
stuff is what I do for a living) is to use a parameterised definition
of a line instead of the implicit 'y = mx + c' form. You can avoid a lot
of infinite and undefined results that way.

Start off defining your line as L(t) = A + tD where A is a point on the
line and D = B - A. Your line is then parameterised by t from 0 (A) to
1 (B). Alternatively (I prefer this one), make D a unit vector and
remember
B's parameter which is also the length of the line-segment.

Next, orthogonally project C onto the line to get the point I. It's
worth
noting that this projection & reflection are through the *unbounded*
line
through A & B. The (vector) equation for the projection is:

I = A + [(C - A).D'] D' // '.' is the scalar/dot product here

where D' is the *unit* direction of the line

finally,

Cm = C + 2(I-C).

This method also works in 3d as well without change.

The only thing you have to watch is when defining the unit direction D'.
If you're calculating it on the fly from the two endpoints A & B by
dividing (B-A) by its length, watch for a divide-by-zero when B and A
are
the same point. A simple resolution check is needed along the lines of:

DL = length_of(D)
if DL < "resolution"
	// There *is* no line in this case, only a point
	D'.x = 0
	D'.y = 0
	...
else
	D'.x = D.x/DL
	D'.y = D.y/DL
	...
endif

Note that are no more divides, sqrt() or trig functions after this -
everything is relatively fast additions & multiplications from here on
in.

The 2d pseudo code for the reflection would then look vaguely like
(there
are a lot of intermediate variables here that can be eliminated):

CA.x = C.x - A.x
CA.y = C.y - A.y

// Project C onto the line to get I (calculate D' as above)
PD = CA.x * D'.x + CA.y * D'.y // the 'distance' along the line from A
I.x = A.x + PD * D'.x
I.y = A.y + PD * D'.y

// Then get Cm
IC.x = I.x - C.x
IC.y = I.y - C.y

Cm.x = C.x + 2*IC.x
Cm.y = C.y + 2*IC.y

Hope all this helps!

Kev

-----------------------------------------------------------------------
Kevin Shea						D-Cubed Ltd.
Software Engineer					Cambridge
Tel:	+44 1223 722632					CB6 2XD
Email:	kev@d-cubed.co.uk				United Kingdom

The opinions expressed here are my own and in no way represent the
opinions of my employer etc etc
-----------------------------------------------------------------------
=================================================================
To SUBSCRIBE or UNSUBSCRIBE please visit
http://gameprogrammer.com/mailinglist.html