random place on a face with python I'm trying to place an object at a random place on a plane.
So far, I found out how to get the vertices locations in real world.
import bpy

obj = bpy.context.active_object
vert = obj.data.vertices

vertex_0 = obj.matrix_world @ vert[0].co
vertex_1 = obj.matrix_world @ vert[1].co
vertex_2 = obj.matrix_world @ vert[2].co
vertex_3 = obj.matrix_world @ vert[3].co

print(vertex_0, vertex_1)

But now, I'm stuck. How can I give an object coordinates somewhere between those vertices?
I can imagine how this would work in 2 dimensions, but with a rotated plane in 3D? My head explodes.
EDIT:
Another idea was to work in local space. Parent an object to the plane and work from there. But then will the child object be scaled with the parent object. And that is not what I want.
So I used the &quot;Child of&quot; constraint and disabled the scale like this:
import bpy

obj = bpy.context.object

# put the location on a vertex of the plane
obj.location = (-1,1,0)

# give the constraint to the selected object
obj.constraints.new('CHILD_OF')
obj.constraints[&quot;Child Of&quot;].use_scale_x = False
obj.constraints[&quot;Child Of&quot;].use_scale_y = False
obj.constraints[&quot;Child Of&quot;].use_scale_z = False
obj.constraints[&quot;Child Of&quot;].target = bpy.context.scene.objects['Plane']

But after clicking the &quot;Clear Inverse&quot; Button in the constraint, the objects location is not on the vertex of the plane how it should be (when the plane is scaled before the script is loaded). Instead, the origin of the object will be on the expected vertex, when the Scale X, Y and Z in the Constraint is enabled again. (Scale is disabled in the script).
So: How can I put an object on another object and having a child relationship without scaling but with the right location?
Use the local space.
The default plane in blender has local coordinates where x and y range from -1 to 1 and z is zero.
&gt;&gt;&gt; me = C.object.data
&gt;&gt;&gt; for v in me.vertices:
...     v.co[:]
...     
(-1.0, -1.0, 0.0)
(1.0, -1.0, 0.0)
(-1.0, 1.0, 0.0)
(1.0, 1.0, 0.0)

With this arrangement can consider only the x, y coordinates effectively making it 2D within the plane z=0.
Hence any point with x and y randomly chosen from that range will be on the plane.
Simple test script, with an object that is the default plane &quot;Plane&quot; with any arbitrary global transform, and it will add an empty on its surface.
Multiplying this local point by the objects matrix world will ensure it is at a global location on the surface of planes current position.
import bpy
from mathutils import Vector, Matrix                    
from random import uniform
context = bpy.context
scene = context.scene

plane = scene.objects.get(&quot;Plane&quot;)
if plane:
    vec = Vector((uniform(-1, 1), uniform(-1, 1), 0))
    bpy.ops.object.empty_add(
            location = plane.matrix_world @ vec,
            ) 

Will re-iterate this relies on the plane having its original local or mesh coordinates in range explained above, making it a simple task to place an empty on its surface.
Via Parenting.
Another way to use local coordinates is via parenting. In this case need only set the local location of the empty within range above to have it on the plane. This will have the effect of aligning the axes of empty to plane.
if plane:
    vec = Vector((uniform(-1, 1), uniform(-1, 1), 0))
    bpy.ops.object.empty_add()
    mt = context.object
    mt.parent = plane
    mt.location = vec 

To make the influence of the parent planes scale to empty unity for any subsequent children of the empty,.   Does a child object inherit the matrix from the parent?
if plane:
    mw = plane.matrix_world
    _, _, scale = mw.decompose()
    S = Matrix.Diagonal(scale.to_4d())
    vec = Vector((uniform(-1, 1), uniform(-1, 1), 0))
    bpy.ops.object.empty_add()
    mt = context.object
    mt.parent = plane
    mt.matrix_parent_inverse = S.inverted()
    mt.location = S @ vec 

For an arbitrarily un axis aligned plane it is a bit more complex. https://stackoverflow.com/questions/42352622/finding-points-within-a-bounding-box-with-numpy