0
$\begingroup$

How can I do something like,

bpy.ops.object.select(object at location x,y,z)
bpy.ops.object.delete()
$\endgroup$
2
$\begingroup$

In the event you want to include some objects whose origin points are close but not exactly the location given. Please note this does not specify object type so any object (camera, armature, light, etc) within range will be deleted.

import bpy
from mathutils import Vector

target_loc = (1.0,1.0,1.0)
target_deviation = .1

objs = [obj for obj in bpy.data.objects if (
        (obj.location[0]-target_loc[0])**2 +
        (obj.location[1]-target_loc[1])**2 +
        (obj.location[2]-target_loc[2])**2 <= target_deviation**2)]

bpy.ops.object.select_all(action = 'DESELECT')
for obj in objs:
    obj.select = True
bpy.ops.object.delete()
$\endgroup$
  • 1
    $\begingroup$ I think this should be the way, even if you're looking for objects at the locations (using a tiny epsilon / deviation). Just to smear out floating-point errors. $\endgroup$ – Robin Betts Jan 5 at 11:31
  • 1
    $\begingroup$ Floating point errors is something I immediately thought when I saw the question as well, but I could not make them manifest themselves when testing. If I move an object randomly and then just copy the values from Blender's input fields it seems to work. I think they may become an issue, but not necessarily are an issue in all cases. $\endgroup$ – Martin Z Jan 5 at 12:26
  • $\begingroup$ I can be precise in my location because I'm removing objects I have placed whose location is recorded in a list of tuples. My focus is the list however, not the object, so my script is manipulating the tuples and then adding/removing objects at those locations. The issue therefore, is not whether there's an object there (I already know that), but how to issue the command, delete the object at the known location. $\endgroup$ – d8sconz Jan 5 at 12:27
  • $\begingroup$ @d8sconz I think floating point errors may be an issue in your described scenario. They occur because of the way values are stored in computer memory so it depends on what you are doing with those numbers and this answer can be very useful if those errors did become a problem at some point. $\endgroup$ – Martin Z Jan 5 at 12:33
  • 1
    $\begingroup$ There is no need for the euclidean formula when there is a vector API use the length, magnitude or length_squared property of the vector result of subtracting one location from another. Would only involve v = Vector(target_loc) to convert tuple to vector in code above. $\endgroup$ – batFINGER Jan 5 at 15:08
1
$\begingroup$

Vector maths

Blender uses vectors. The object's location is a point in 3D space designated by a mathutils.Vector.

Its local location relative to it's parent

lloc = ob.location

Its global location, relative to the global origin (0, 0, 0)

gloc = ob.matrix_world.to_translation()

If we have a point in space (global) P then the distance from the point to the object is the length of the vector gloc - P.

d = (gloc - P).length

If this distance is within some radius d, then we select. Setting this to a very small value, 1e-7 is around blender's error margin, and for most applications can be considered the same location.

Relying on equality of vectors v1 == v2 is IMO not reliable.

>>> Vector((0.9999999, 1, 1)) == Vector((1, 1, 1))
False
>>> Vector((1.0000001 , 1, 1)) == Vector((1, 1, 1))
True
>>> Vector((1.0000002 , 1, 1)) == Vector((1, 1, 1))
False

Test script, selects any object within d of scene cursor.

import bpy

context = bpy.context
d = 0.0001

loc = context.scene.cursor_location

for o in context.scene.objects:
    gloc = o.matrix_world.to_translation()
    # o.select = (gloc - loc).length < d # pre 2.80
    o.select_set((gloc - loc).length < d)

Since there is a chance the active object is not selected we'll set it to None before calling the delete op

# context.scene.objects.active # for pre 2.80
context.view_layer.objects.active = None
bpy.ops.object.delete()
$\endgroup$
  • $\begingroup$ Vector((0.9999999, 1, 1)) == Vector((1, 1, 1)) returning False is completely correct. Vector((0.99999999, 1, 1)) == Vector((1, 1, 1)) returning True isn't. $\endgroup$ – Martin Z Jan 5 at 15:13
0
$\begingroup$

You will have to loop trough all the objects in the scene and check its location. Then you can delete that obtained object if one is found.

import bpy
from mathutils import Vector

x = 0
y = 0
z = 0

objects = [ o for o in bpy.data.objects if o.location == Vector((x,y,z))]

if len(objects) > 0:
    for o in objects:
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects[o.name].select = True
        bpy.ops.object.delete()

Extension for multiple objects and multiple possible locations

import bpy
from mathutils import Vector

locations = [Vector((0,0,0)), Vector((4,0,0))]

objects = [ o for o in bpy.data.objects if o.location in locations]

if len(objects) > 0:
    for o in objects:
        bpy.ops.object.select_all(action='DESELECT')
        bpy.data.objects[o.name].select = True
        bpy.ops.object.delete()
$\endgroup$
0
$\begingroup$

I think one loop is enough for this:

import bpy 
from mathutils import Vector

location = Vector((0,0,0)) # this should be some location

for o in bpy.context.scene.objects: 
    if o.location == location:
        bpy.data.objects.remove(o) 

Obviously all kinds of conditions related to the location could be checked, but those should be another questions.

I think keeping in mind that floating point binary conversion errors do exist is a good idea in this context as well.

$\endgroup$
  • $\begingroup$ I'm trying to get my head around why any loop is needed. I have objects in known locations so I don't (in my mind) need to loop through all the objects to find if it's there. Are you saying that something like, bpy.data.objects.remove(o.location), is not possible? $\endgroup$ – d8sconz Jan 5 at 14:52
  • $\begingroup$ You only have objects that have the property of location. The space has no properties, you do not work with it in any way, so you cannot check what objects belong to what space, but only the other way around - what objects have that location in space. I don't know if what I am saying is making a lot of sense, but anyway, you can only do it checking all the objects you have. Only they are defined in Blender. $\endgroup$ – Martin Z Jan 5 at 15:01
  • $\begingroup$ Using equality to test floating points is an issue, see example in my answer. $\endgroup$ – batFINGER Jan 5 at 15:12
  • $\begingroup$ I think it can be and is likely to be. It not necessarily is in all cases. $\endgroup$ – Martin Z Jan 5 at 15:15
  • $\begingroup$ I think let's just cross that bridge when we come to it. There is no reason to assume that it definitely is a problem in this case. We don't know the wider context. $\endgroup$ – Martin Z Jan 5 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.