3
$\begingroup$

Need help with creation of the script which could read particular edge length of the rectangular planes. Need to recognize which length is the width (just edges pointed in x) and which one height(just edges pointed in z). These values i would like to store as the width and height variables(dimension of the plane). All planes are oriented in the same direction (width will be always x and height always z) but there are thousands of them. Then i would need to use these width and height as the coordinates for UVs for each point of each polygon. x=width, y=height so i will get just one single point for whole rectangle. I tried to investigate how it would be possible and i found two scripts one for reading lengths for all edges and second one for writing UV coordinates. Everything could be possible to do just in edit mode after i will choose correct UVlayer. The second script works fine for me just i need to implement somehow the recognizin of the length and height values for each rectangle. enter image description here

Reading edge lengths

import bpy
import bmesh

object = bpy.context.active_object
bm = bmesh.from_edit_mesh(object.data)

for edge in bm.edges:
    length = edge.calc_length()
    print("length:",length)

Writing UV coordinates for each vertex

import bpy
import bmesh

obj = bpy.context.active_object
me = obj.data
bm = bmesh.from_edit_mesh(me) 
    
uv_layer = bm.loops.layers.uv.verify()

# adjust uv coordinates
for face in bm.faces:
    for loop in face.loops:
        loop_uv = loop[uv_layer]
        # use xy position of the vertex as a uv coordinate
        loop_uv.uv = loop.vert.co.x

bmesh.update_edit_mesh(me)

EDIT: I tried to implement this calculation into my code but still i dont know how can i get the desired width and length of the ractangle. In below code a wanted just simply to print these values but without success. Is there something what i missed?

import bpy
import bmesh
import mathutils

obj = bpy.context.active_object
me = obj.data
bm = bmesh.from_edit_mesh(me)
bm.edges.ensure_lookup_table()

x = mathutils.Vector((1,0,0))

for edge in bm.edges:
    edges_x = []
    edges_z = []
    v = edge.verts[0].co - edge.verts[1].co
    if abs(v.dot(x)) < .0001:
        edges_z.append(edge)
    else:
        edges_x.append(edge)
    width = edges_x.calc_length()
    height = edges_z.calc_length()
    print(width)
    print(height)
```
$\endgroup$

2 Answers 2

4
$\begingroup$

I would try

for face in bm.faces:
    # Compute edge vectors
    e1 = face.verts[1].co - face.verts[0].co
    e2 = face.verts[2].co - face.verts[1].co

    # Decide which is width and which is height
    if abs(e1.x) > abs(e1.z):
        w, h = e1.length, e2.length
    else:
        w, h = e2.length, e1.length

    # Assign UVs 
    for loop in face.loops:
        loop[uv_layer].uv = (w, h)
$\endgroup$
1
  • $\begingroup$ Wow. That works really fantastic. Thanks a lot!!! Appreciate it. $\endgroup$ Commented Jan 4, 2022 at 10:48
2
$\begingroup$

Assuming that you have applied any rotation and scale to the planes, this code will divide the edges of the planes into those parallel to the X axis and those parallel to the Z axis. (Really, those not parallel to the X axis, but I'm assuming your planes meet your criteria.) If you have not applied rotation and scale, then you need to vector multiply the coordinates of the edges by the object's matrix_world.

See the manual for details on bm.edges

edges = bm.edges
bm.edges.ensure_lookup_table()

x = Vector((1,0,0))
edges_x = []
edges_z = []
for edge in edges:
    v = edge.verts[0].co - edge.verts[1].co
    if abs(v.dot(x)) < .0001:
        edges_z.append(edge)
    else:
        edges_x.append(edge)

This relies on the fact that if two vectors are perpendicular their dot product will be zero. Since we're using floating point numbers, it's not wise to do a direct comparison to 0, so we compare to $epsilon$, here, just a very small number.

Now that you have the two lists of edges you can use them in your UV code as you need them.

$\endgroup$
6
  • $\begingroup$ I've been wondering recently (due to another question based on float32 precision), how often do we actually need to use epsilon with floats. Sometimes it's hard to reason, like here it's not immediately obvious with .dot(), but for example if instead you checked if abs(edge.verts[0].co.z) - abs(edge.verts[1].co.z) != 0 then you could be sure any equal pair of values will produce 0 (I guess not absolutely sure, but is there a reason to be paranoid and assume some Python bug?). A harder question: is there a pair of 2 non-equal values that produces 0 - but if so, that's a minimal threshold. $\endgroup$ Commented Jan 4, 2022 at 12:39
  • $\begingroup$ This is an interesting problem, BTW, I need to look around if a number can be represented with higher accuracy by increasing the fraction and decreasing the exponent, and this therefore can lead to situations where 2 numbers have a smaller difference than the smallest positive float (or the closest non-zero float to 0). Probably, but it's an interesting challenge to find such pair as a proof... $\endgroup$ Commented Jan 4, 2022 at 12:42
  • $\begingroup$ Maybe we should be paranoid... :D answers.microsoft.com/en-us/msoffice/forum/all/… $\endgroup$ Commented Jan 4, 2022 at 12:47
  • $\begingroup$ if you are comparing a value to itself, where 'itself' is, in fact, the same memory location, then unless you have a Pentium with a rather infamous hardware bug, the subtraction will always produce 0. But if you compare two float numbers that are stored in different locations and may have been computed differently, as in the question, then you need the epsilon test. I've even used computers where hardware float a * b did not always equal b * a because of an error in the design of the multiplier. $\endgroup$ Commented Jan 4, 2022 at 16:07
  • 1
    $\begingroup$ I don't feel criticized and I've certainly benefited from you taking a deeper look at my posts in the past. The reason for paranoia isn't the subtraction, but whether two numbers computed in different ways that should be analytically equal are the same floating point value. $\endgroup$ Commented Jan 4, 2022 at 16:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .