DCarpenter Posted June 11, 2020 Share Posted June 11, 2020 I've created a PIO that selects all the lines from the visible layer on the drawing. Now I simple want to increase each line's length by 2" (user defined), from it's center. How do I make sure it's length changes from it's center? Dave Quote Link to comment
Pat Stanford Posted June 11, 2020 Share Posted June 11, 2020 Lines in Vectorscript and Python are defined by their beginning and ending points. So you can change the length, but that will just change the ending point. You will have to calculate the distance that you need and move the line by that amount as well as the amount you need to change the length of the line. Probably need to break our your high school trigonometry book to calculate the X/Y movement based on the angle of the line. Or you might be able to use the HScale command which takes the center of the object as the point to scale by. You can find the center of a line by using the difference between the corner points of the Bounding Box GetBBox(Handle). Quote Link to comment
DCarpenter Posted June 11, 2020 Author Share Posted June 11, 2020 Thank you for the clarity. I was hoping there was a way of selecting the center of the line and then changing it's length like I can do in the OIP manually, without doing all the math, but I guess not. Bummer. HScale might work for me though. Thank you once again. Dave Quote Link to comment
Pat Stanford Posted June 11, 2020 Share Posted June 11, 2020 Hopefully one of the other gurus will see this post and tell me I am wrong ;-) Quote Link to comment
Julian Carr Posted June 11, 2020 Share Posted June 11, 2020 Pat is right. Scaling the line using HScale2D is the way to go and it is easy enough: Procedure T; VAR h1 : HANDLE; rCenterX, rCenterY : REAL; rScaleFactor : REAL; rExistLen, rNewLen : REAL; BEGIN h1 := FSActLayer; HCenter(h1, rCenterX, rCenterY); rExistLen := HLength(h1); rNewLen := RealDialog('New Length?', Concat(rExistLen)); rScaleFactor := rNewLen / rExistLen; HScale2D(h1, rCenterX, rCenterY, rScaleFactor, rScaleFactor, False); Redraw; END; Run(T); Quote Link to comment
Pat Stanford Posted June 11, 2020 Share Posted June 11, 2020 I hate it when I am right about stuff that could be so much easier. :-( Quote Link to comment
MullinRJ Posted June 12, 2020 Share Posted June 12, 2020 Just for variety, here is a vector approach to do the same thing. It's just a little more code than Julian's scaling approach, and to the original request it will increment every line on visible layers. If you want the script to only work on the Active Layer, then change the last "2" to a "0" in the following line: ForEachObjectInLayer(GrowLine, 0, 0, 2); { All objects, Shallow, Visible layers } ForEachObjectInLayer(GrowLine, 0, 0, 0); { All objects, Shallow, Current layer } Procedure GrowLinesByInc; { Grow each line on visible layers by a user input length. If the user input is positive } { the line length increases, if it is negative, the line length decreases. } VAR dLength : REAL; function GrowLine(H :Handle) :Boolean; { Use global variable "dLength" to calculate a vector in the same direction } { of each line and add half of it to each end. } Var P1, P2, Vdelta :Vector; Begin if (GetTypeN(H) = 2) then begin { type 2 is a LINE } GetSegPt1(H, P1.x, P1.y); { start point of line } GetSegPt2(H, P2.x, P2.y); { stop point of line } Vdelta := UnitVec(P2 - P1) * dLength/2; P1 := P1 - Vdelta; { move away from center } P2 := P2 + Vdelta; { move away from center } SetSegPt1(H, P1.x, P1.y); { new start point of line } SetSegPt2(H, P2.x, P2.y); { new stop point of line } end; { if } end; { GrowLine } BEGIN dLength := RealDialog('Length increment?', '0'); if not DidCancel do ForEachObjectInLayer(GrowLine, 0, 0, 2); { All objects, Shallow, Visible layers } END; Run(GrowLinesByInc); Raymond Quote Link to comment
DCarpenter Posted June 12, 2020 Author Share Posted June 12, 2020 WOW!! I feel like I got the "A" team jumping on this, and so interesting to see how each of you would tackle this issue. I like the way Julian came at my problem so I took his code and revised it a bit to meet my needs. It still needs to be refined a bit but it does what I need it to do for now. I probably lost hours of time trying to figure out which selection procedures to use between the Selection class and the Document List Handling class. The code you all shared with me was super helpful with helping me steer my thoughts and direction. Thank you all for offering your help. The three of you are the pillars of this Forum. I wrote this code because sometimes I get DWG files where the end points of lines to exactly match, so when I use the 2D polygon, paint bucket, tool, I'm unable to fill different cavities quickly. So I figured a quick little script to extend all the lines 2" in either direction should do the trick, and then when I was done, I could use the same tool to restore everything back to normal. Dave PROCEDURE IncreaseLength; VAR h1 : HANDLE; i,k: INTEGER; rCenterX, rCenterY : REAL; rScaleFactor : REAL; rExistLen, rNewLen : REAL; MyH: DYNARRAY [] OF HANDLE; BEGIN SelectObj(T=2); i:=NumSObj(ActLayer); ALLOCATE MyH[1..i]; h1:=FSActLayer; FOR k:=1 TO i DO BEGIN MyH[k]:=h1; h1:=NextSObj(h1); END; DSelectAll; rNewLen := RealDialog('Length increase:','2'); k:=1; WHILE (k <= i) & (i <> 0)DO BEGIN HCenter(MyH[k], rCenterX, rCenterY); rExistLen := HLength(MyH[k]); rScaleFactor := (rExistLen+rNewLen) / rExistLen; SetSelect(MyH[k]); Scale(rScaleFactor, rScaleFactor); DSelectAll; k:=k+1; END; END; Run(IncreaseLength); Quote Link to comment
Julian Carr Posted June 12, 2020 Share Posted June 12, 2020 While is seems logical to try and emulate how you work with the mouse to select objects then edit them in some way, if you want to get into scripting then you'll find it much easier to work with handles. And the single most useful call for this is ForEachObject(), because it uses criteria to choose what gets processed. This can be object type, class, layer, colour, selection state, etc. Using FEO would look something like this: Procedure T; VAR grNewLen : REAL; Procedure DoIt(h1 : HANDLE); VAR rCenterX, rCenterY : REAL; rScaleFactor : REAL; rExistLen : REAL; BEGIN HCenter(h1, rCenterX, rCenterY); rExistLen := HLength(h1); rScaleFactor := (rExistLen + grNewLen) / rExistLen; HScale2D(h1, rCenterX, rCenterY, rScaleFactor, rScaleFactor, False); END; BEGIN { main } grNewLen := RealDialog('New Length?', '2'); IF NOT DidCancel THEN ForEachObject(DoIt, (T = Line)); Redraw; END; Run(T); 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.