# [JASS]IsPointInRect -check code pl0x

Status
Not open for further replies.

#### Maker

Level 37
I am making a spell request that has a moving laser beam. I need to check to know when it collides with units. So I check whether the unit is inside a rectangle like this:

Here's the code:

JASS:
``````library PointInRect

// Returns a boolean that tells whether the point is inside a rectangle.
// (px , py) = Point to check
// (cx , cy) = lower left corner of the rect
// (ax , ay) = upper left corner
// (bx , by) = lower right corner
function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean
// Vector from lower left corner to point
local real v_angle = Atan2( py - cy , px - cx )
local real v_length = SquareRoot( (py-cy)*(py-cy) + (px-cx)*(px-cx) )
// Vector from lower left corner to upper left corner
local real v1_angle = Atan2( ay - cy , ax - cx )
local real v1_length = SquareRoot( (ay-cy)*(ay-cy) + (ax-cx)*(ax-cx) )
// Vector from lower left corner to lower right corner
local real v2_angle = Atan2( by - cy , bx - cx )
local real v2_length = SquareRoot( (by-cy)*(by-cy) + (bx-cx)*(bx-cx) )

local real dot1 = v_length*v1_length*Cos(v_angle-v1_angle)
local real dot2 = v1_length*v1_length
local real dot3 = v_length*v2_length*Cos(v_angle*v2_angle)
local real dot4 = v2_length*v2_length

return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
endfunction

endlibrary``````

JASS:
``````library PointInRect

// Returns a boolean that tells whether the point is inside a rectangle.
// (px , py) = Point to check
// (cx , cy) = lower left corner of the rect
// (ax , ay) = upper left corner
// (bx , by) = lower right corner
function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean
local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)

return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
endfunction

endlibrary``````

How to make the library better? Anything wrong with it?

Last edited:

#### Maker

Level 37
So the advantage is this allows you to define a rectangle even if it's rotated?

Yes, the rectangle doesn't have to be axis-aligned.

I edited my script a bit because I don't need the angle difference function.

I'll test Nestharus' script.

#### PurplePoot

Level 40
Using component vectors would make infinitely more sense.

#### Nestharus

Level 31
A component vector is any vector with a tail at the origin. Rather than vectors like

[(11,16), (12,14)]

You can use the components, which would be tip minus tail

(5,2)

Those are the components in this case. Because you are simply checking for collision, you don't care about where the vector is. If everything is a component vector, it's a bit less math and it'll still check whether something collided with something else or not.

Also, units are not points, but rather circles. D4RK_G4ND4LF's script does exactly what you want.

JASS:
``````// We've got a line given by P1(x1, y1) and P2(x2, y2) as well as a ray given by P3(x3, y3) and angle a.
// This function returns the distance from P3 to the intersection point.
// The distance returned is negative if the ray points away from the line.
//
library GetIntersectionDistance

function GetIntersectionDistance takes real x1, real y1, real x2, real y2, real x3, real y3, real a returns real
local real m = x1 - x2
if (m == 0) then // Avoid division by zero
return (x1 - x3) / Cos(a)
endif
set m = (y1 - y2) / m
if (m == Tan(a)) then // Parallel (avoid division by zero again: Sin(a) - Tan(a) * Cos(a) == 0)
return 0.
endif
return (m * (x3 - x1) + y1 - y3) / (Sin(a) - m * Cos(a))
endfunction

endlibrary``````

That will return the intersection distance between a rectangular line segment (laser beam) and a point (unit). If the unit is being treated as a circle with radius 64, then the thing intersects if the distance is less than or equal to 64.

JASS:
``````set d = GetIntersectionDistance
if (d <= 64) then
//INTERSECT
endif``````

The IsPointInRectangle by me checks if a *point* is inside of a rectangle (no distance returned).

#### PurplePoot

Level 40
Give an example.
Use the directional components of the vector rather than a magnitude and direction. Notice how you start with components (relative positions of units), convert to a magnitude/direction format (arctangent and sqrt), and then use the magnitude/direction formula for your dot product when you could just get the components and use the component formula for your dot product.

Basically vectors don't have any position so we can just describe them by the coordinates of the point they would reach if positioned at the origin rather than a magnitude and direction. As a result, instead of describing a vector by (length, angle) you can describe it by (x, y). If you imagine the vector as the hypotenuse of a triangle originating from the origin (with the length of the hypotenuse being the vector's magnitude and the angle between the hypotenuse and the x axis being the vector's direction) then the x coordinate is its adjacent and the y coordinate is its opposite.

To further illustrate, here's a script which is identical to yours except that it instead uses component vectors (the dot product for two component vectors (x1, y1) and (x2, y2) is x1*x2 + y1*y2):

JASS:
``````library PointInRect

// Returns a boolean that tells whether the point is inside a rectangle.
// (px , py) = Point to check
// (cx , cy) = lower left corner of the rect
// (ax , ay) = upper left corner
// (bx , by) = lower right corner
function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean
local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
local real dot2 = l1*l1 //these don't actually exist so I'll just leave them
//like this
local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
local real dot4 = l2*l2 //these don't actually exist so I'll just leave them
//like this

return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
endfunction

endlibrary``````

Simpler and more efficient by any stretch of the imagination.

(l1 and l2 don't exist so I just left those equations the same out of lack of a better way to solve that)

A component vector is any vector with a tail at the origin. Rather than vectors like

[(11,16), (12,14)]

You can use the components, which would be tip minus tail

(5,2)

Those are the components in this case. Because you are simply checking for collision, you don't care about where the vector is. If everything is a component vector, it's a bit less math and it'll still check whether something collided with something else or not.
No sane person defines vectors as pairs of points. He was using the magnitude/direction representation which is really bad in this case. In fact, even your nonsensical method here would work better than his but that's a moot point since your method is strictly worse than proper component representation.

#### Nestharus

Level 31
Sorry, meant components of vector ;P.

If you just cared about direction, you could use a unit vector, which is the vector divided by its magnitude ;D.

#### PurplePoot

Level 40
I was referring to your description of a vector as a line between two points (or whatever you were even trying to denote with [(11,16), (12,14)]) not really making any sense since vectors don't have a fixed position and thus you are including unnecessary information without introducing any new functionality.

#### Nestharus

Level 31
When did I say that a vector was a line between two points? : P

The thing I wrote was a vector that wasn't at the origin.

It gets funner with R3 vectors though o-o... because then you have to retrieve the plane and make sure that the coordinates your are checking satisfies the equation of the plane ;P.

#### SanKakU

Level 13
i saw "is point in polygon" system somewhere...i think it required some kind of line thing called linked lists. i'm not sure how it would help you to acquire the 4 points, however. you'd have to figure that out on your own or through someone else. oh crap...check it out the file i have doesn't seem to work. world editor can't open the w3x file. well anyway, here's a link to the resource. since the map doesn't open, it might be old code that doesn't work anymore? idk.

#### Maker

Level 37
Thanks PurplePoot, that was a good explanation. I had an error there, the l1 and l2 I just copied from another function which I remove and forgot to change them.

Anyway, now it is like this and it seems to work.

JASS:
``````library PointInRect

// Returns a boolean that tells whether the point is inside a rectangle.
// (px , py) = Point to check
// (cx , cy) = lower left corner of the rect
// (ax , ay) = upper left corner
// (bx , by) = lower right corner
function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean
local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)

return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
endfunction

endlibrary``````

#### SanKakU

Level 13
looks like you got a simple solution. nice. i have a question, though, if you don't mind.

how did you get c, a, and b? i'm ever unfamiliar with many of the mathematical native function calls in jass.

#### Maker

Level 37
I calculate them, I use the beginning point of the ray as the base point.

Basically
XofPoint = basePointX + offset * Cos(angle)
YofPoint = basePointY + offset * Sin(angle)

For upper left corner the angle is the angle the ray is heading. For lower left corner it is angle - bj_PI. For the lower right it is angle - bj_PI/2

#### SanKakU

Level 13
I calculate them, I use the beginning point of the ray as the base point.

Basically
XofPoint = basePointX + offset * Cos(angle)
YofPoint = basePointY + offset * Sin(angle)

For upper left corner the angle is the angle the ray is heading. For lower left corner it is angle - bj_PI. For the lower right it is angle - bj_PI/2

interesting, i'll try that. thanks. i think i understood that ok. we'll see after i try it, heh.

Status
Not open for further replies.

Replies
1
Views
397
Replies
0
Views
559
Replies
0
Views
1K
Replies
7
Views
790
Replies
10
Views
620