• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] IsPointInRect -check code pl0x

Status
Not open for further replies.
Level 37
Joined
Mar 6, 2006
Messages
9,240
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:


WC3ScrnShot_032311_135233_02.jpg



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:
Level 31
Joined
Jul 10, 2007
Messages
6,306
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).
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
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.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
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.
 
Level 13
Joined
May 11, 2008
Messages
1,198
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.
http://www.wc3c.net/showthread.php?t=108898
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
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
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
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
 
Level 13
Joined
May 11, 2008
Messages
1,198
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.
Top