tbexon Posted December 7, 2023 Share Posted December 7, 2023 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 Quote Link to comment
MullinRJ Posted December 7, 2023 Share Posted December 7, 2023 (edited) 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 December 7, 2023 by MullinRJ added VecSub definition Quote Link to comment
Pat Stanford Posted December 7, 2023 Share Posted December 7, 2023 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. Quote Link to comment
BillW Posted December 8, 2023 Share Posted December 8, 2023 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). Quote Link to comment
Jayme McColgan Posted December 17, 2023 Share Posted December 17, 2023 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) 1 Quote Link to comment
Recommended Posts
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.