# Help with python moving verts along an edge

• Hi,

I have a closed ring of verts that I want to slide along the connecting edges say 5 degrees clockwise but the maths is beating me, any help would be appreciated.

• Hi,

I have a closed ring of verts that I want to slide along the connecting edges say 5 degrees clockwise but the maths is beating me, any help would be appreciated.

Isn't that the same thing as rotating the whole ring 5 degrees clockwise? That will be true if the ring is circular. If so then

XYZU = ROT * XYZU

where XYZU = 4-vector with x,y,z; ROT = homogeneous rotation matrix; * = matrix multiplication

Now, if the ring is not circular, it gets more complicated, as you can't just rotate everything. I'd say this... If V0 = (vx(0), vy(0), vz(0)) is a vertex and V1 = (vx(1),vy(1),vz(1)) is the next vertex in the ring, and O = (ox, oy, oz) is an arbitrary point, then

Line from V0 to V1: V(t) = V0 + t * (V1-V0) = (vx(0)+t(vx(1)-vx(0)), vy(0)+t(vy(1)-vy(0)), vz(0)+t(vz(1)-vz(0))

Now from the arbitrary point O From that we have two vectors OV0 and OV(t)... dot vector multiply gives

OV0 . OV(t) = ||OV(0)|| . ||OV(t)|| . cos(theta), where "." is dot vector multiply

You know cos(theta) = cos(5 deg), and you know OV0 = (vx(0)-ox, vy(0)-oy, vz(0)-oz), and you also know OV(t) = (vx(0)-ox+t(vx(1)-vx(0)), vy(0)-oy+t(vy(1)-vy(0)), vz(0)-oz0t(vz(1)-vz(0))

So, this could be resolved for t directly through brute force, but that's a 4th order equation, so the resolution is lengthy. I think A better approach is probably to calculate a rotation vector that is perpendicular to OV0 and OV1, as

VEC = OV0 x OV1, where x is vector product
ROT = ( 1/||VEC|| ) . VEC

now that we have the rotation vector ROT, we just build the homogenous rotation matrix ROT4 and calculate the rotated vertex V0R:

VOR = ROT4 . V0

so we know that V0, V1, V0R and 0 are all in the same plane, therefore V0V1 and OV0R intersect. Just find the intersection point P and that's your vertex rotated by 5 degrees along the edge between V0 and V1. This approach has more steps due to the vector product and matrix multiplication, but it does avoid the 4th order polinomial.

Now, notice that the rotation center is 100% arbitrary; that's correct, as the notion of a vertex sliding 5 degrees along an edge depends completely from where you're measuring that angle from. But a natural rotation center may be the centroid of your ring, like

O = (V0 + V1 + V2 .. + Vn) / N

• Isn't that the same thing as rotating the whole ring 5 degrees clockwise? That will be true if the ring is circular. If so then

You are right that it isn't a non-deformed cylinder, and I should have mentioned that, so thanks for guessing that's what I wanted

...This approach has more steps due to the vector product and matrix multiplication, but it does avoid the 4th order polinomial.

I sort of followed the maths however how I get vector products let alone matrix multiplication is, I'm afraid, beyond me :0(

Amanda

• @fbs7 I understand you are not so much looking at rotation. In that case you better just create an object with the vertices, rotate it, scale it, and let Poser do the math.
You asked about moving the vertices along the edge. Could that be a fraction of the edge length? You mention 5 degrees, or 360/5 = 1/72 of a complete turn.
If your loop has say 10 vertices you would get something like you look for if you move the vertices by 10/72 of the distance to the next vertex.
This could give very interesting patterns when animated.

• @fverbaas Yes that was what I was actually after moving each vertex say 1oth on an inch around the edge loop. Probably better done in blender than poser but I'm stumped with the maths, sigh

• @amethystpendant
It gets complicated when you think in terms of angles and rotations. You then need a rotation axis and the idea of angle only works if vertices are in a regular n-gon around the axis. If not, then the angle will be different for each vertex anyway.

If vi is a vertex of the loop and vii is its successor, then then location of vi in step m+1 can be calculated from the positions in step m from:
vi(m+1)=vi(m)+r(vii(m)-vi(m))

With r being a scalar for the step size, with a value typically but not necessarily between 0 and 1. A first estimate of a value for r can be made as above.
This should work for any shape in any dimension, but the result is not necressarily a legal definition for a surface that will be of any use for rendering in Poser (or in any app).

• @amethystpendant
It gets complicated when you think in terms of angles and rotations. You then need a rotation axis and the idea of angle only works if vertices are in a regular n-gon around the axis. If not, then the angle will be different for each vertex anyway.

If vi is a vertex of the loop and vii is its successor, then then location of vi in step m+1 can be calculated from the positions in step m from:
vi(m+1)=vi(m)+r(vii(m)-vi(m))

With r being a scalar for the step size, with a value typically but not necessarily between 0 and 1. A first estimate of a value for r can be made as above.

Precisely, so it's much easier if one wants to displace the vertex by say 10% of the distance from next vertex. That's very simple math, and probably that's a better option for @amethystpendant.

But if @amethystpendant really needs a displacement that makes it exactly 5 degrees from some origin, then that becomes much more complicated. In that case r (which I called t in the first approach) becomes the solution of a 4th order polinomial if one goes for the algebraic approach.

If one goes the vector rotation it involves a vector product to get a rotation vector, then matrix product to do the actual rotation, then a line intersection to calculate the actual point in the line.

Now, I got a night of sleep and I'm thinking r (= t) can be calculated more easily in 2D; any three 3D vertexes make a 2D triangle with sizes of known lengths; we can even normalize one of the sides to be 1.00:

so, given V1(x,y,z), V2(x,y,z) and O(x,y,z), we calculate

a2 = (v1x-ox)^2 + (v1y-oy)^2 + (v1z-oz)^2
b2 = (v2x-ox)^2 + (v2y-oy)^2 + (v2z-oz)^2
c2 = (v1x-v2x)^2 + (v1x-v2x)^2 + (v1z-v2z)^2
a = sqrt(a2/c2)
b = sqrt(a2/c2)

So, how to get an easy approach for that 2D problem, and solve r for theta = 5 degrees... hmm.. let's think...

• I got so used to thinking in terms of vectors in college, I'm very rusty with 2D geometry... but let's try... call that middle line c, and the angle in V1 as alpha:

law of cosines in alpha:

b^2 = a^2 + 1 - 2a cos(alpha)
alpha = arccos( (a^2+1-b^2)/2a )

now we know alpha, by law of sines:

c/sin(alpha) = r/sin(theta)
r = c sin(theta)/sin(alpha)

So it's pretty easy with sines and cosines... we can reduce further:

sin( arccos(x)) = sqrt(1-x^2)

so...

x = (a^2+1-b^2)/2a
s = sqrt(1-x^2)
r = c . sin(theta) / s

then finally
v1x_new = v1x + r * (v2x - v1x)
v1y_new = v1y + r * (v2y - v2y)
v1z_new = v1z + r * (v2z - v2y)

I still suggest that O(x,y,z) to be calculated as the centroid of the vertices:

ox = 0.0; oy = 0.0; oy = 0.0
for( i=0; i<n; i++ ){ ox += vx[i]; oy += vy[i]; oz += vz[i] )
ox = ox/n; oy = oy/n; oz = oz/n

• That should be it, I think (provided I didn't mess up any formula, which is quite possible)... no vectors, no homogeneous matrices, no vector multiplications, no inner multiplications... good old 2D geometry to the rescue.

• Oh, shucks, I forgot to calculate c; that comes from law of sines again:

c / sin(alpha) = a / sin(pi-alpha-theta) = a / sin(alpha+theta) = a / (sin(alpha)cos(theta) + cos(alpha)sin(theta))
c = a / ( cos(theta) + sin(theta) cotan(alpha) )

That can be simplified with:

cotan( arccos(x) ) = x / sqrt(1-x^2)

so, all put together, from n vertices v1, v2, v3... and angle theta = 5 degrees:

ox = (v1x+v2x+v3x+...)/n
oy = (v1y+v2y+v3y+...)/n
oz = (v1z+v2z+v3z+...)/n

for each pair v1,v2, loop the calculations:

a2 = (v1x-ox)^2 + (v1y-oy)^2 + (v1z-oz)^2
b2 = (v2x-ox)^2 + (v2y-oy)^2 + (v2z-oz)^2
c2 = (v1x-v2x)^2 + (v1x-v2x)^2 + (v1z-v2z)^2
a = sqrt(a2/c2)
b = sqrt(a2/c2)
x = (a^2+1-b^2)/2a
s = sqrt(1-x^2)
t = x / s
c = a / (cos(theta) + sin(theta) * t)
r = c . sin(theta) / s
v1x_new = v1x + r * (v2x - v1x)
v1y_new = v1y + r * (v2y - v2y)
v1z_new = v1z + r * (v2z - v2y)

• By the way, @amethystpendant, why do you want to do this particular transformation?

I don't see many advantages on it... it doesn't preserve distances, doesn't preserve angles and I'm pretty confident that unless the angle is pretty small it won't preserve shape either.

It's non-reversible (that is, has no inverse); also, where the poly-line is convex relative to the centroid it will deform inwards (and if you repeat it many times these vertices will end up together in the center), and where the poly-line is concave relative to the centroid the opposite will happen, the vertices will deform outwards (and if you repeat many times these vertices will be blown away).

So I fear this transformation can only be applied a few times and with small angles... after that I suspect the mesh will be pretty deformed...

What kind of effect you're trying to achieve? A regular rotation has many more advantages than this one, as it preserves angles, distances, shapes and is reversible.

• That is, consider this ring:

When seen from the centroid O, the concave parts will move inwards as they rotate, because the next vertex will pull them inwards as compared to a plain old rotation. Meanwhile the convex regions will do the opposite.

I suspect after you repeat this transform a few times you'll end up with something all convex, what will make it get smaller and smaller and you repeat the transform until it collapses in a single point in the center.

• Another example... each transformation in this square is exactly as you proposed, small offsets along the edges... notice how the square has become significantly smaller even after a few transformations. Any regular polygon will suffer the same effect, from a triangle to a million sides n-gon, due to their convex nature:

• Now, this is something that may be wicked to do with this transformation; instead of concatenating them as above, you can apply progressively along say a tube; always keep track of the initial position, and then apply the rotation for different thetas along the tube, always calculating from the initial vertex positions (instead of the applying to the last calculated position, that would be really bad); it would generate a twisting-y thing-y that's hard to describe exactly what is (it's not a real twist, as twists are true rotations), but might produce a wicked effect. This is an exaggeration of that, starting with r = 0.2 then going to r = 0.9 in the middle then back to r = 0.0.

• @fbs7 Wow, thank you!

The reason I want it is because I made a pair of dynamic stockings for PE. I did this by making a cylinder in Blender then pulling it up over her leg. I had already UV'd the cylinder which meant that the stocking will have a real stretched look. However the Poser cloth sim works top left to bottom right and this resulted in a spiraling of the edge rings from top to bottom, not too big a deal as it looks right until you try and create a material zone for the back seam. What I was hoping to do was try and unwind this spiral one loop at a time. Using edge slide seemed to work but because the movement is relative to the view and cursor the front moves clockwise while the back moves anticlockwise until 2 verts intersect.

Your explanation of the mesh getting progressively smaller looks like it wouldn't work anyway once you got away from small adjustments. I did try and compensate sor the spiralijng by twisting the cloth as it simmed but although that helped to some degree I couldn't get it to fully cancel out the spiraling.

I will, even if just to prove to myself i can, try and implement the maths you have so thoroughly provided into a python script and I'll let you know how I got on.

Amanda

• @amethystpendant is the blender cylinder a triangulated or quad mesh? I ask because if it were triangulated and all the diagonals sloped the same way, that might inherently induce a twist in the simulation. If so, you could try alternating the slope of the diagonals between each row, or even within each row, if you have an even number of verticals.

If quads, it might be worth trying with a triangulated mesh.

Just a couple of thoughts.

• @fbs7 Wow, thank you!

The reason I want it is because I made a pair of dynamic stockings for PE. I did this by making a cylinder in Blender then pulling it up over her leg. I had already UV'd the cylinder which meant that the stocking will have a real stretched look. However the Poser cloth sim works top left to bottom right and this resulted in a spiraling of the edge rings from top to bottom, not too big a deal as it looks right until you try and create a material zone for the back seam. What I was hoping to do was try and unwind this spiral one loop at a time. Using edge slide seemed to work but because the movement is relative to the view and cursor the front moves clockwise while the back moves anticlockwise until 2 verts intersect.

Your explanation of the mesh getting progressively smaller looks like it wouldn't work anyway once you got away from small adjustments. I did try and compensate sor the spiralijng by twisting the cloth as it simmed but although that helped to some degree I couldn't get it to fully cancel out the spiraling.

I will, even if just to prove to myself i can, try and implement the maths you have so thoroughly provided into a python script and I'll let you know how I got on.

Amanda

@amethystpendant Oh, you really should consider using the Fitting Room. In the fitting room you can move the vertices around, then tight fit, then smooth them, then tight fit, then rotate, then tight fit, then flatten them (to stop the spiraling), then tight fit, and keep repeating until you're satisfied.

I'm a huge fan of the fitting room; far exceeds Blender and DAZ's capabilities. I think that tool is miraculous and is a winner, both to obtain initial fitting morphs for dynamic clothes, and to fit conforming clothes.

Now, I'm also an enthusiastic programmer, so I see your point of programming the tool if only for the satisfaction of doing it. I did the same just a couple of months ago. Best of luck with that, and lemme know if I can help!

• @anomalaus Hi, the mesh is quads, I never thought about trying it with tris, I'll give it a go

• A sample with the fitting room; I just closed my eyes and chose a random toon, this case Ichiro2:

Then I built me a subdivided cylinder in Blender; this actually took me 30 minutes, as I suck in Blender, then just imported as obj:

now into fitting tool:

then just 30 seconds later with just plain tight fitting:

now the trouble of moving the foot back to the original position; the toes were giving me trouble, so I added in an ellipsoid to help with fitting the toes:

then after some 15-20 mins of moving that foot back to rest and wrangling with fitting tool to show who is his daddy:

now, we do see artifacts around:

in particular I found it odd the shape around the toes.. it should be way more smooth, but the problem is back in the mesh from blender:

you see I left duplicate vertices in the original mesh (I really suck in Blender, hahaha), and these ended up getting spread in that region; that's why the odd artifact around the toes; so a sensible person would go back to the original mesh in blender and fix those duplicate vertices, but i'm way too lazy for that, and this is just a demo, so I left as is

Now group tool, add all vertices, create prop (to bake in global transformations and the fitting morph); now it's ready to be used as a dynamic sock for Ichiro and keep her feet warm in the winter; so a reasonable step would be back to blender, clean up the geometry, generate uv map, but I find all that boring; what I like is this - fitting room, fit, create figure, add morphs, conform to Ichiro (and repurpose that ellipsoid to avoid showing Ichiro's intimates), voila, Ichiro got some socks - hooray!

• @fbs7 I must admit, I for get about the fitting room! I will definitely give that method a go! See, I should have said in the first place WHY I wanted the maths!

Thank you