Jump to content
DCarpenter

Extending a line from it's center

Recommended Posts

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

Share this post


Link to post

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

 

Share this post


Link to post

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 

Share this post


Link to post

Hopefully one of the other gurus will see this post and tell me I am wrong ;-)

 

 

Share this post


Link to post

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

 

Share this post


Link to post

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

 

 

Share this post


Link to post

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

Share this post


Link to post

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

Share this post


Link to post

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.


 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×
×
  • Create New...