mathlib's is_within_box()

Please post any questions about developing your plugin here. Please use the search function before posting!
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

mathlib's is_within_box()

Postby stonedegg » Wed Sep 10, 2014 3:34 pm

So I'm trying to check if a location is between a box using vector.is_within_box(point1, point2).
I'm obtaining all the vectors I need using playerinfo.get_abs_origin() and saving them in three different variables (location, point1, point2)
Somehow the function location.is_within_box(point1, point2) is always returning false, even if the location is between those two points.
Am I missing something or how does this work?
User avatar
Ayuto
Project Leader
Posts: 2209
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Wed Sep 10, 2014 3:45 pm

Works fine for me.

Syntax: Select all

from mathlib import Vector

point0 = Vector()
point1 = Vector(100, 100, 100)

# Prints True
print(Vector(5, 5, 5).is_within_box(point0, point1))

# Prints False
print(Vector(5, 5, 101).is_within_box(point0, point1))
What's you test code?
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Wed Sep 10, 2014 4:04 pm

Basically just like this:

Syntax: Select all

# saving player locations earlier (two different locations)
point1 = playerinfo.get_abs_origin()
point2 = playerinfo.get_abs_origin() #point2 is above point1

# getting current player location later
location = playerinfo.get_abs_origin()

# while location is between both points
if location.is_within_box(point1, point2):
return True

# won't return True...
User avatar
satoon101
Project Leader
Posts: 2703
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Wed Sep 10, 2014 4:10 pm

That isn't exactly full test code, but I have to ask, did you print out the 3 x/y/z coordinates each time?
Image
User avatar
Ayuto
Project Leader
Posts: 2209
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Wed Sep 10, 2014 4:11 pm

Please show me your test code. I need something to reproduce the behaviour you explained in your first post. There is no useful information in the code you just posted.
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Wed Sep 10, 2014 4:29 pm

Okay sorry, I thought it would be enough.

In my HUD following was printed:

Code: Select all

player 1167 2595 96
point1 1075 2715 96
point2 1249 2544 170

This should return True, shouldn't it?




Syntax: Select all

# Players
from players.entity import PlayerEntity

# Filters
from filters.players import PlayerIter

# Messages
from messages import SayText2
from messages import HintText

# Ticklistener
from listeners import TickListenerManager

# Commands
from commands.say import SayCommandManager

def load():
SayCommandManager.register_filter(say_filter)
TickListenerManager.register_listener(tick_listener)

def unload():
SayCommandManager.unregister_filter(say_filter)
TickListenerManager.unregister_listener(tick_listener)


point1 = None
point2 = None

def say_filter(playerinfo, teamonly, command):
text = command[1]
if text.startswith('!point1'):
point1 = playerinfo.get_abs_origin()
SayText2(message="Set point1 to {0} {1} {2}".format(point1.x, point1.y, point1.z)).send()
elif text.startswith('!point2'):
point2 = playerinfo.get_abs_origin()
SayText2(message="Set point2 to {0} {1} {2}".format(point2.x, point2.y, point2.z)).send()

return True

def tick_listener():
if point1 == None or point2 == None:
return
for index in PlayerIter('alive'):
player = PlayerEntity(index)
playerinfo = player.playerinfo
location = playerinfo.get_abs_origin()
HintText(message="player: {0} {1} {2}\npoint1: {3} {4} {5} \npoint2: {6} {7} {8}".format(
int(location.x), int(location.y), int(location.z), int(point1.x), int(point1.y), int(point1.z),
int(point2.x), int(point2.y), int(point2.z))).send(index)
if location.is_within_box(point1, point2):
SayText2(message="True").send()



Edit:
I found out why it wasn't working for me. When I tested the code and set the two points, the Y coordinate from point1 was bigger than the Y coordinate from point2, so the function would never return True.
But when I set both points so that the Y coordinate from point1 is smaller then the Y coordinate from point2 (like in ayutos example above), the function returns True.
So, from what I understand, the function only returns True if point2.y >= location.y >= point1.y, but shouldn't it return True if point1.y >= location.y >= point2.y as well?

Edit2:
After more testing I had the same problem with the X coordinate when switching point1 and point2 to different corners of the box.
So I made this simple function now, that seems to work very well for me (can be done a lot better I guess):

Syntax: Select all

def is_within_box(loc, point1, point2):
if (point2.x >= loc.x >= point1.x or point1.x >= loc.x >= point2.x) and \
(point2.y >= loc.y >= point1.y or point1.y >= loc.y >= point2.y) and \
point2.z >= loc.z >= point1.z:
return True


Maybe you can copy that idea into your code ;)
User avatar
Ayuto
Project Leader
Posts: 2209
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Thu Sep 11, 2014 10:09 am

I just had a look at the implementation of Vector::WithinAABox().

Syntax: Select all

bool Vector::WithinAABox( Vector const &boxmin, Vector const &boxmax)
{
return (
( x >= boxmin.x ) && ( x <= boxmax.x) &&
( y >= boxmin.y ) && ( y <= boxmax.y) &&
( z >= boxmin.z ) && ( z <= boxmax.z)
);
}
So, what you found out by testing can be proved by this snippet. Maybe we should add an own implementation of this method instead of using the engine implementation.

However, you can also use this workaround.

Syntax: Select all

if location.is_within_box(point1.min(point2), point2.max(point1)):

Edit: I added this fix to the repo. https://github.com/Source-Python-Dev-Team/Source.Python/commit/d485236a850b04499b153c9cb94ba351bce7f099
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Thu Sep 11, 2014 1:49 pm

Nice, thanks!

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 115 guests