find if a object is inside a region

hello!
so, lets say i have two points in the world like this:

start = [0.0, 0.0, 0.0]
end = [10.0, 10.0, 0.0]

i need to retreive the names of the objects that are inside that region, i tried this:

for obj in scene.objects:
    if obj.position[0] < end[0] and obj.position[0] > start[0]:
        print ("do something")

but it doesnt works, i mean, it works, but sometimes the end variable goes negative and it doesnt works anymore, so is there any function that allows me to do this?

thanks
-lucki

What about using a collision check with a seperate layer?

like the items have a collision layer in common with a spawned cube?

You can use an object with a solid physics bounds (read, not using ‘Convex Hull’ or ‘Triangle Mesh’), give it a collision sensor with no property filter and use collision.hitObjectList to get the list of objects inside the region.

That’s the easiest way to do it, for your case, first of all it would be more straightforward to use ob.worldPosition rather than ob.position as the latter is an old attribute that’s not used much anymore.

Also, if looks like you’re using to use a little vector math in there, if you don’t know how such a thing works than things can get a little dicey. Though as an alternative that’s easier to understand, you can say.


if obj.worldPosition[0] > start[0] and obj.worldPosition[0] < end[0]:
         if obj.worldPosition[1] > start[1] and obj.worldPosition[1] < end[1]:
                 #do something#

This assumes that the end position values will always be above the start position values, to deal with cases where the value being checked goes negative when it need to be positive you need to do something like…

if abs(obj.worldPosition[0]) < start[0])

To note, when you’re using the ‘abs’ keyword, you’re telling the program to use the absolute value of the variable which is the distance from zero, so the value returned is always positive.

You need to “normalize” your bounding box coordinates. You are providing a 3D ‘start’ and 3D ‘end’ coordinate. This defines a 3D box in space. You just need to take this box that is defined and find out where the real minimum and maximum points are.

Once you have that, then you can use the “separating axis theorem” to test if your point is inside the bounding box.

You need to add some code to this to get the ‘scene’ object into the code (usually bge.logic.getCurrentScene())


from mathutils import Vector

# Defines a box in 3d space
start = [10, 10, 0]
end = [20, 20, 10 ]

# Normalizes the box coordinates so that lowerLeft is always the smallest x,y,z values
# of the box and upperRight is always the largest x,y,z values of the box
lowerLeft = Vector( [min(start[0], end[0]), min(start[1], end[1]), min(start[2], end[2])] )
upperRight = Vector( [max(start[0], end[0]), max(start[1], end[1]), max(start[2], end[2])] )


for obj in scene.objects:

  # Use "separating axis" to test if the point is strictly inside the bounding box.

  # Object's position relative to the lowerLeft corner of the bounding box.
  objectVector = Vector( obj.worldPosition - lowerLeft )

  # Project the ObjectVector onto the X,Y, and Z axes
  xVector = Vector( [upperRight[0] - lowerLeft[0], 0, 0] )
  yVector = Vector( [0, upperRight[1] - lowerLeft[1], 0] )
  zVector = Vector( [0, 0, upperRight[2] - lowerLeft[2]] )


  xDot = objectVector.dot( Vector((1,0,0)) )
  yDot = objectVector.dot( Vector((0,1,0)) )
  zDot = objectVector.dot( Vector((0,0,1)) )

  # See if the projection falls inside the box on all 3 axes.
  if (0.0 <= xDot and xDot <= xVector.magnitude) and (0.0 <= yDot and yDot <= yVector.magnitude) and (0.0 <= zDot and zDot <= zVector.magnitude):
    print("do something")
  else:
    print("none")



the thing is all about a selection box for a strategy game, and the “selection box” is a plane that i scale to get the size and shape the player wants, i tried using near and collision sensors, they worked when the box was on its original size(1 blender unit) but when i made it bigger, units didnt react to the box, i tried making the box sensor and using some hard-core code to select the units, that didnt work either, and my best choice was to make this, im going to go for Ace Dragon solutions, as they seem the easier.

thanks for the help!
-lucki

edit:
i couldnt make abs work, so i made a provisional code, i say provisional because this is not going to be FPS friendly…

if end[0] > 0.0 and end[1] > 0.0:           
    if objects.worldPosition[0] > start[0] and objects.worldPosition[0] < end[0]:
                if objects.worldPosition[1] > start[1] and objects.worldPosition[1] < end[1]:
                    if "selected" in objects:
                        objects["selected"] = True
        else:
            if objects.worldPosition[0] < start[0] and objects.worldPosition[0] > end[0]:
                if objects.worldPosition[1] > start[1] and objects.worldPosition[1] < end[1]:
                    if "selected" in objects:
                        objects["selected"] = True
                        
        if end[0] < 0.0 and end[1] < 0.0:
            if objects.worldPosition[0] < start[0] and objects.worldPosition[0] > end[0]:
                if objects.worldPosition[1] < start[1] and objects.worldPosition[1] > end[1]:
                    if "selected" in objects:
                        objects["selected"] = True
        else:
            if objects.worldPosition[0] > start[0] and objects.worldPosition[0] < end[0]:
                if objects.worldPosition[1] < start[1] and objects.worldPosition[1] > end[1]:
                    if "selected" in objects:
                        objects["selected"] = True

i think there is obiusly a way to make this easier, but in the meantime this will work

I think you could do this with bricks by making a mesh as the region, and say if within 0 distance to object.

i not know well how work dot yet.

anyway to make a selection box you have two vectors ,and it can be we say “inverted” .

so i suggest as kastoria say to re-order this two vector first of all.


from mathutils import Vector
#(...)


start = Vector((1,2,0))
end = Vector((-111,10,0))

# end.x  is "inverted" in this case , better replace it in  start vector to avoid more calculation after

MIN , MAX = Vector(), Vector() #2 new vectors empty
for i in range(3):
    MIN[i] = min(start[i], end[i])
    MAX[i] = max(start[i], end[i])

#now you have:
# MIN -> Vector((-111, 2 , 0))
# MAX -> Vector((1, 10 , 0))

# make a < list comp > already filtred by property (is more clean and more fast )
selectableObs = [i for i in scene.objects if "selectable" in i]

objInside = [] #emptyLIst
for ob in selectableObs:
    if MIN.x < ob.worldPosition.x < MAX.x : 
        if MIN.y < ob.worldPosition.y < MAX.y :
            objInside.append(ob)

print(objInside)

:wink: