# Left/Right Test

I am new to blender python scripting. I was stuck up with testing an object location whether it is left or right to the centroid. To describe in detail, I have a group of fishes going together (school) and I want to determine each fish location whether it is left or right to the centroid of the group and then turn all left fishes in one direction and other fishes in another direction.

Could anyone please advice me how to proceed with the finding the fish located left or right with respect to the centroid? These are all moving fishes, I want to determine left/right at one particular instance. Thank you in advance.

• imho there is no left or right respect a point, you need a symmetry plane. Say with local Y up, X front, then you need to calculate the distance, in local coords, from the plane centere to each fish: what is on negative Z is "left", positive Z is "right". Just a guess. – m.ardito Mar 6 '18 at 15:41
• @m.ardito Thank you for your response, Its kind of making sense I will try with that.I did see an example in Unity Game Engine.. forum.unity.com/threads/left-right-test-function.31420 but was not quite sure how to do this in blender python as there is no forward vector option blender python... – spod Mar 6 '18 at 15:46

## 1 Answer

From Math.Stackexhange

https://math.stackexchange.com/questions/214187/point-on-the-left-or-right-side-of-a-plane-in-3d-space

Let $A,B,C$ be the points that determine the plane. Then the cross product $(B-A) \times (C-A)$ gives us a normal ${\bf n}$ to the plane. Now consider a test point $(x,0,0)$ where $x$ is a huge positive number. This should be on the right side of the plane. Now $((x,0,0) - > A) \cdot {\bf n}$ is just the first coordinate of ${\bf n}$ times $x$ minus some constant. For large enough $x$ the sign of the dot product is then just the sign of the first coordinate of ${\bf n}$. Thus: If the sign of first coordinate of $n$ is positive, then the right side consists of the points $P$ with $(P - A) \cdot {\bf n} > 0$ and the left side consists of the points with $(P - A) \cdot {\bf n} < 0$. The inequalities are reversed if the sign of the first coordinate of $n$ is negative.

Have a group of fish objects "Cones" aligned -Y forward Z up. The x axis looks left and right. The plane of the fish is in ZY plane, and the normal X.

Calculate the "centroid fish" world matrix by averaging the world matrices of the fish. Its translation (loc) is the centre of geometry of all fish. It's X axis is our norm to test aganst. The "centroid fish" is represented by a cone shaped empty.

For each fish, if the dot product of the centroid normal to fish.matrix_world.translation - loc is greater than zero it's on the left, and colored red.

Simple test setup using single BI material with object color. Move the fishies around and run script

import bpy
from mathutils import Matrix, Vector
context = bpy.context
scene = context.scene

school = [f for f in scene.objects if f.name.startswith("Cone")]
N = len(school)
loc = sum([f.matrix_world.translation for f in school], Vector()) / N
mw = 1 / N * sum([f.matrix_world for f in school], Matrix())
left = mw.to_3x3().transposed()[0] # normal to the plane
left = -left if left.x < 0 else left # flip claus
# add an empty to show Centroid Location. (center of geom)
mt = scene.objects.get("Centroid")
if not mt:
mt = bpy.data.objects.new("Centroid", None)
scene.objects.link(mt)

mt.matrix_world = mw
mt.empty_draw_type = 'CONE'
mt.scale *= 4
mt.scale.y *= -1
mt.scale.x /= 5

for fish in school:
#calc the dot product
dot = left.dot((fish.matrix_world.translation - loc).normalized())
# red on fishes left
fish.color = (1, 0, 0, dot) if dot > 0 else (0, 1, 0, -dot)


Note: Suggest using center of mass instead of geometry.

The same test on other two axes will give forward / behind for Y and above / below for Z.