# Rotating Objects with Set3DRot along a curve

## Recommended Posts

HI All

I've been bashing my head against this problem for a couple of days now, and struggling to come up with a solution.

I'm trying to create a PIO that draws a line of rectangle extrudes that are rotated by a specific amount, and aligned so that the bottom left corner touches the previous Bottom right. (image showing desired end result)

At the moment it nearly works, however I am having issues with the more objects I insert they start to "drift" and gaps appear. (SS Below)

I think this is basically because as the rotation of the rectangle increases the total length along the X axis reduces, and I am struggling to find a way to calculate this offset. I've managed to deal with the Y Offset by using vs.GetBBox() to get the Bottom RightY Value and using this as Y value for lining the next object up with the previous.

However for the X axis this doesn't seem to work as the X bounding box value will default to furthest point on X axis which is the TOP Right point not bottom right.

Is there a way I can easily get the co ordinates of each corner of the rectangle once it's rotated? Or do I need to try and remember how to do Trig and calculate this myself?

I'm also wondering whether the issue is with the X, Y, Z Distance within Set3d Rot? Currently i'm trying to make the rotation centre the bottom left corner, but i'm wondering whether I should be using some other static centre for all of them.

Any help is greatly appreciated! I've been staring at this for so long now I can't see the wood for the trees!

Relevant Code below:

```def MakeCurvedScreen():
"""
Creates a curved screen based on user specified number of panels & rows
:return:
"""

TileWidth = 1000  # Tile Width (X)
TileDepth = 95  # Tile Depth (Y)
TileHeight = 1000  # Tile Height (Z)
TileQty = 8  # Number of tiles in each Row
NoOfRows = 1  # Number of Rows
tileZRot = -2  # Rotation angle for each Tile

tileXoffset = 0  # Amount to offset each tile along X Axis by to create rows
tileZOffset = 0  # Amount to offset each tile along the Z axis by to create columns
curTileQty = 0  # Tracks current amoutn of tiles inserted in current row
curtileZRot = 0  # Tracks current height of row being inserted
totalTiles = TileQty * NoOfRows  # Total Tiles in screen
col_index = 0  # Tracks what Column we are currently inserting into
prevTileYLoc = 0
CorrectionX = 0

for EachTile in range(totalTiles):
# Iterates through all tiles building wall
if curTileQty == TileQty:
# If a full row of tiles has been inserted, start new row
tileZOffset += TileHeight
curtileZRot += tileZRot

curTileQty = 0
tileXoffset = 0
col_index = 0
prevTileYLoc = 0

# Creates Tile as extrude, adds a Y offset to account for the rotated tile being lower
tileH = MakeSingleTile(0 + tileXoffset , 0 + tileZOffset, TileWidth, TileDepth, TileHeight, YOffset=prevTileYLoc)
# Rotate Tile
vs.Set3DRot(tileH, 0, 0, tileZRot * col_index, TileWidth*col_index,(TileDepth*col_index)*-1, 0)  # Rotates Tile

(p1X, p1Y), (p2X, p2Y) = vs.GetBBox(tileH)  # Gets previous tiles co ords

prevTileYLoc = p2Y  # Gets the Bottom Right corner of current Tile for use with lining up the next tile

tileXoffset += TileWidth  # Increases Overall Row width count by panel width
curTileQty += 1
col_index += 1

def MakeSingleTile(startX,startZ,width,depth,height, **kwargs):
"""
Creates a Single Tile from Rectangle of user specified Width & Depth
:return: Handle
"""
vs.BeginXtrd(0,height)
vs.RectangleN((0,0),(1,0),width,depth)

vs.EndXtrd()
tileH = vs.LNewObj()
if 'YOffset' in kwargs:  # If a Y Offset has been specified
vs.Move3DObj(tileH, startX, kwargs['YOffset'], startZ)
else:
vs.Move3DObj(tileH,startX,0,startZ)
return tileH```

Without breaking out your high school Geometry books, you can use vectors to keep track of where you are and where you want to go. Without knowing where you reference your base part I cannot give you exact code for your problem, but it should look something like this:

```# rotate 2D vector V by Ang degrees
def RotVec(V, Ang):
return vs.Ang2Vec(vs.Vec2Ang(V)+Ang, vs.Norm(V))

# add vectors A and B
return tuple(map(sum, zip(A, B)))

# subtract vector B from A
def VecSub (A, B):
return tuple(map(lambda x, y: x - y, A, B))

...

DispV = VecSub(LRcornerPt, InsertionPt)      % displacement vector

where PartRotation is vs.GetSymRot(symHd) for symbols, or an angle value you keep track of programmatically; and the vector values are tuples of (X, Y).

I have not tested this, so proceed with caution. If you need more help, write back or contact me offline. I'd be more than happy to help.

Raymond

Edited by MullinRJ

You are correct that it is the GetBBox that is causing the problem. As you rotate the object the bounding box expands as the BBox is always vertical/horizontal.

Either use Sin/Cos to calculate the end point of the first/ start point of the second (x change and y change) or use Raymond's idea and use Vectors.

The easiest way I would handle it is convert the polyline path to straight line segments use

objH = vs.Polygonize(srcpathH,seglen,TRUE)

and then step along the polygonized path, getting each vertex in turn to determine the vector (in relation to the previous vertex) for placing the rectangle extrudes. You even get a vector length which will pick up shorter segment lengths at line/curve transitions. The other advantage of Polygonize is that straight segements can also be split to seglen lengths (ie set as TRUE above).

• 2 weeks later...

it looks like you are trying to make a curved LED wall... I was in a similar boat that no amount of math I did could get it perfect...

the way I built mine is I inserted the tile then put in a loci at the location you want to curve to happen and store the handle of it and then on the next tile I repeat the process and moved the tile to the location of the previous loci I made and use the vs.RotatePoint() to rotate the desired amount. I also store all the loci in a list and delete them all after I'm done.

this is VERY disjointed but here's the basic premise...

```vs.Symbol(fulltile, 0,0 , 0)
vs.Locus3D(phywidth*curve_interval,0,0)
last_loc = vs.LNewObj()

### other random code here ###

curloc = vs.GetLocus3D(last_loc)
vs.Move3DObj(last, curloc[0], curloc[1], 0)
vs.RotatePoint(curloc[0], curloc[1], cur_angle)```

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Restore formatting

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×

• KBASE
• #### MARIONETTE

×
• Create New...