0
$\begingroup$

I would like to sort objects faces with the Python API based on their normals, and more specifically, the orientation of the Z axis of the normals. What would be the easiest way to do so? Comparing the normals directly does not work because I want to overlook the rotation about the z axis (that is to say, I am only interested in whether the face normal has its z axis parallel or perpendicular to the z axis of the world frame).

Thank you for helping

$\endgroup$
3
  • 1
    $\begingroup$ do you want the math or do you need how to access normals? $\endgroup$ Feb 2 '16 at 15:24
  • $\begingroup$ blender.stackexchange.com/questions/43985/… (it is Not really specific to Animation Nodes) the script does exactly what you do (compare to world xyz) and my answer shows exactly how to compare normals due to the float imprecision issues. $\endgroup$
    – o.g.
    Feb 2 '16 at 17:12
  • $\begingroup$ Note that: 1. the normals are just vectors, there is no rotation around normal axis, 2. sorting is one, filtering some is different. 3. Are those faces in an object? Or generated by the script? Is the object moved/rotated or we calc only as default .. $\endgroup$
    – o.g.
    Feb 2 '16 at 17:17
1
$\begingroup$

Here's an example that shows you what normal is parallel or perpendicular.

(I'm not sorting the list, cause you say sorting, but then only care for parallel/ perp. ?)

  • check the object type and if has faces
  • list normals, including obj world rotation + scale
  • compare with vector.dot so that 1/-1 are parallel, 0 is perpendicular

Note the > < 0.0001 comparison rather than == cause of the float precision issues.

from mathutils import Vector

orientZ = []

if Object is not None and getattr(Object, 'type', '') == 'MESH':
    if Object.data.polygons:
        worldZ = Vector([0, 0, 1])

        mat = Object.matrix_world
        loc = mat.to_translation()
        normals = [(mat * p.normal - loc).normalized() for p in Object.data.polygons]

        # if dot is 0, is perpendicular, 1/-1 are up, down
        for n in normals:
            dotN = n.dot(worldZ)

            if   abs(dotN) > 0.9999: orientZ.append(1)
            elif abs(dotN) < 0.0001: orientZ.append(0)
            else:
                orientZ.append(-1)

and gives a list of 1, 0, -1 for Z, perp, others

enter image description here


Another example is this How can I compare normals in AN with python, doing the same, by distance compare to world XYZ axes.

$\endgroup$
1
  • $\begingroup$ Thank you for your answer! And yes, using the word "sort" was actually incorrect, sorry for the confusion! $\endgroup$
    – Kirjain
    Feb 3 '16 at 10:40

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.