Jump to content

Rotating Objects with Set3DRot along a curve


tbexon

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)

 

image.thumb.png.1854c013d544e42204027c65a7fa8e17.png

 

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)

 

image.thumb.png.dbcc56dcfd639c51cb29ab9d8e4f520a.png

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

 

 

Link to comment

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
def VecAdd (A, 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 
NextInsPt = VecAdd(InsertionPt,  RotVec(DispV, PartRotation))

 

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
added VecSub definition
Link to comment

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).

Link to comment
  • 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)
  • Like 1
Link to comment

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

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

×
×
  • Create New...