find world position of end of cylinder

I need to find the world positions of the two ends of a cylinder. Right now I have an empty placed at each end, but for what I’m working on I need a lot of these cylinders, and I don’t want to have to have two empties for each cylinder. Thanks for any help.

I don’t know if this is gonna be of any help, maybe you need to be a bit more specific, but anyway here goes: select the cylinder and jump into Edit Mode. I suppose the cylinder has a vertex in the center of each cap, so just select that vertex and check its coordinates with the Global button enabled.

I need to find the position real-time, while the cylinder is moving. And yes, it will be where the end vertexes are.

I guess Python will be your best friend on that matter. I’m not ax expert in that field, but this thread might help you:

http://blenderartists.org/forum/showthread.php?t=650

I would suggest the empty method as well. It cost not that much to keep the empties, as they are not rendered.
If you are afraid to add all the empties you might have a look at groups or addObjects. Both can replicate an object with all its children.

The reason I want to do this is I have a script running on each cylinder which uses the locations of the empties. I am currently using properties on the cylinder to enter the name of each empties that are accessed by the script. At the moment I have to change the properties for each cylinder, and I am going to have at least 200 cylinders, So I would rather not have to change that many properties. Thanks for helping.

If you know how long the cylinders are and you can get their location and orientation with a bit of trigonometry in your script you can locate the centre of the ends.

Can you please explain how to do this, I’m still 15, so don’t know much about trig. The cylinders are 2 blender units from end to end, so 1 BU from the centre to the end point. If it’s possible would the be a way to make this work automatically even if I change the size, this isn’t necessary, but would be very nice? Sorry for sounding so demanding, but I’m really stuck here.

Yo. It’s not something I can explain here. But if you’re 15 and made 765 posts it would be a good move to study a bit of basic trig. Any old second hand Year ?8 math text would do.

If you need to continue with the empty route for now, one empty per cylinder will do. The other end will be the same distance back and down from the location of the cylinder.

Ok, I’ll ask my math/computer science teacher when I see him on Sunday, he should be able to help. Until then, I will seek help through google. If anyone knows how to do this though, help is still welcome. Thanks for trying.

Asking your teacher would be the right way I guess.

You have 200 (equal?) cylinders with properties that contain the name of 200 empties?

Why not parent the empty to the cylinder. Give the empty a special name e.g. cap… or a property e.g. cap. Then your script can step through the cylinder’s children looking for the empty (which name starts with “cap”/ that has the property “cap”).

As I said, if they are all equal, use groups, so you need to setup the logic, just once.

I wrote my own physics engine and I’m 16 lol (http://physm.com - haven’t updated it in a while :/). Okay, you want to find the edge of the cube? Easy…

first we need to know the size of it…

sizex,sizey,sizez = obj.scaling

now let’s get the position of the object…

posix,posiy,posiz = obj.position

Now it’s time for the fun part! Let’s find the position of all the bounds (top, bottom, left, right)!

top = posiz+sizez
bottom = posiz-sizez
left = posix-sizex
right = posix+sizex

basic math my friend. Any more questions?

@-[killer]-

  • you would need to use worldPosition, position is deprecated
  • scaling gives you the scaling transformation not the dimensions of the object

Your idea would give you the sizes of a 2x2x2 box around the object center.
This is not the bounding box, as it does not care the geometry.
This does not care of any rotation of the object.

@mcguinessdr:
I think this can be achived with some assumptions:

  • One end of the cylinder is at [0,0,1] while the other is at [0,0,-1] in local space

now you need to transform this local coordinates to world coordinates.

I can’t remember, so I do some google… does not help.

I have to dig into my brain… ouch :ba:ouch :spin: uhhhh

here it is:
build the transformation matrix of the cylinder. Right-Multiply it with the vector pointing to the local position you want to transform.

worldPosition = localPosition * transformationMatrix

Here is a script:


import Mathutils
def localPointToWorldPosition(obj, localPoint):
 '''
 Transforms the local position into world position.
 
 by Monster
 '''
 o = obj.worldOrientation
 p = obj.worldPosition
 s = obj.worldScale
 
 # transformation matrix of obj
 matrix = Mathutils.Matrix(
  [ o[0][0]*s[0], o[1][0],      o[2][0],      0.0],
  [ o[0][1],      o[1][1]*s[1], o[2][1],      0.0],
  [ o[0][2],      o[1][2],      o[2][2]*s[2], 0.0],
  [ p[0],         p[1],         p[2],         1.0])
 # from list to vector (4 terms)
 localVector = Mathutils.Vector(localPoint+[1.0])
 
 # transform the local coordinates to world coordinates
 worldVector = localVector * matrix
 
 return worldVector[:3]
 
def test(cont):
 '''
 Expects TWO DIFFERENT objects connected by TWO controller-Actuators
 '''
 cylinder = cont.owner
 markerButton = cont.actuators[1].owner
 
 markerTop = cont.actuators[0].owner
 markerTop.worldPosition = localPointToWorldPosition(cylinder, [0,0,1])
 
 markerButton = cont.actuators[1].owner
 markerButton.worldPosition = localPointToWorldPosition(cylinder, [0,0,-1])
 

If you want tu use it with a Python module controller. Call it Text.py and enter Text.text as module.
Otherwise just take the function localPointToWorldPosition(obj, localPoint) and use it in your own script.
In function test() you can see how to use it.

I hope it helps

Attachments

vector test.blend (155 KB)

Assuming the object centre of the cylinder is set at the actual centre and assuming that it is orientated so it is ‘standing up’ (i.e. end points aligned on the z axis) you can use the orientation matrix of the cylinder to find the endpoints.

from Mathutils import Vector, Matrix

HEIGHT = 2 # replace with the actual height of the cylinder

cont = GameLogic.getCurrentController()
own = cont.owner

ori = Matrix(*own.worldOrientation)

p1 = Vector(own.worldPosition) + Vector(0,0, HEIGHT/2) * ori
p2 = Vector(own.worldPosition) +  Vector(0,0, -HEIGHT/2) * ori

Thats the 2.49 API. Just say if you need it in the 2.5 API

Edit: Ouch, monster your math make my head hurt :frowning:

Perhaps there is no need for a 4*3 matrix and 4D vector? I believe simply multiplying a local vector by the the worldOrientation matrix should solve the problem. Though I have to admit my knowledge of matricies doesn’t extend beyond the mathutils module at all :stuck_out_tongue:

I think getAxisVect is the way to go.

TopPos = own.getAxisVect([ 0.0, 0.0, 1.0 ])
BotPos = own.getAxisVect([ 0.0, 0.0, -1.0 ])

The tuplets returned give you the position of the centres of the ends of the standard “unit” cylinder sitting at the origin. Even if it’s been rotated. If it’s been scaled along it’s z-axis get the z scaling factor (the [2] tuplet) and call it sfZ:
TopPos = own.getAxisVect([ 0.0, 0.0, 1.0sfZ ])
BotPos = own.getAxisVect([ 0.0, 0.0, -1.0sfZ ])

Get your cylinders worldPosition’s and add the tuplets to the tuplets returned by TopPos and BotPos.

Equip; Very useful function, I was not aware of it. However it sounds like that after the vector is returned, you must add the world position of the cylinder to it. Take that into account if it isn’t working.

Yo Andrew, I live in Melbourne. I’m pretty much a noob and when I’m writing scripts I spend a lot of time naming and renaming variables and then trimming out the dead wood as I go. I leave just enough, sometimes by way of comments, so that I can remember how I did it it. I haven’t yet tackled a blend to demonstrate mcguinessdr’s problem but I might.

I was sure there is a function for that :).

This is basic for 3D graphics, but usually “behind the scenes”.
@Andrew-101:
a 4x4 matrix is needed (at least a 3x4) to have all transformations = translation, rotation, scale in one matrix. With a 3x3 you can’t get the translation bit.

getVectAlign, does just the rotation part (which is indeed a 3x3 Matrix). That is the reason why it is necessary to add the position later. Equip added the scaling to the input (sfZ) of getVectAlign.

I have to say Equip’s code looks much nicer than my one :smiley:

I understand what equip is saying, mostly, but how do I add the world position to get the world positions of the end points? And will this give me the right position even if the cylinder doesn’t start at the origin?
Thank you for putting so much effort into this problem.

this means:

worldTopPos =Vector(own.worldPosition) + TopPos
worldBotPos =Vector(own.worldPosition) + BotPos

Finally it just means add each single term of one position with the term of the other position. Vectors do that for you already with the + operation.
On lists you would do c[0] = a[0] + b[0] …