Jump to content
LarryO

GetPtL (VW2013) not collecting point values

Recommended Posts

Some curious activity happens with this preliminary scripting. Testing units are mm.

Message screen is displayed before closing plugin's default record initialization dialog.

Message screen is updated to reflect changes in default record initialization dialog before GetPtL point has completed selection.

GetPtL doesn't save value of point selected. Zero is being displayed as value stored in cpHeight.y

And finally ControlPoint01Y is not being overwritten with the value in cpHeight.y. (perhaps cpHeight.y is NIL and not zero, but Message displays 0 and not NIL)

What am I not understanding?

VAR
PIO_Handle,PIO_ParentWall,PIO_Record: HANDLE;
PIO_WorldOrigin: POINT;
PIO_Rotation,rTemp:REAL;
iAccuracy: INTEGER;
Class_Name,PIO_Name:STRING;
Bool1,Bool2:BOOLEAN;

cpHeight: VECTOR;

 

BEGIN

PushAttrs;
FillColorByClass; FPatByClass; PenColorByClass; LSByClass; LWByClass; MarkerByClass; OpacityByClass;
Class_Name:=ActiveClass;
Bool1:=GetCustomObjectInfo(PIO_Name,PIO_Handle,PIO_Record,PIO_ParentWall);
GetSymLoc(PIO_Handle,PIO_WorldOrigin.x,PIO_WorldOrigin.y);
IF GetPrefReal(152)=1.0 THEN iAccuracy:=4 ELSE iAccuracy:=0;

 

IF IsNewCustomObject(PIO_Name) THEN BEGIN

    GetPtL(0.0, 0.0, cpHeight.x, cpHeight.y);
    
    SetRField(PIO_Handle,'_StairOutline','ControlPoint01X',Num2Str(iAccuracy, cpHeight.x));
    SetRField(PIO_Handle,'_StairOutline','ControlPoint01Y',Num2Str(iAccuracy, cpHeight.y));

    END;

MoveTo(0,0);LineTo(cpHeight.x,cpHeight.y);


MoveTo(0,0);LineTo(600,0.0);
    {ResetObject(PIO_Handle);}

Message(PControlPoint01Y,'x',cpHeight.y);
PopAttrs;
END;

Share this post


Link to post

The issues you are seeing with Message are mostly a function of how Message and plug-in events work.  Your plug-in code is going to run several times before the actual insertion.  For example, the code runs in order to generate the object's preview when you first select the tool.

 

The Message displays PControlPoint01Y, which is a constant loaded at the beginning of the script's run.  If you're updating the value with SetRField, you would only see the new value with GetRField.  As you do here, ignore the PParam value and just use cpHeight for your script.

 

You only set the value of cpHeight if the object is new.  You want to execute cpHeight.y := PControlPoint01Y before the IF IsNew… block.

 

This may not impact your code, but two tips:

The record name is going to be PIO_Name.  This can prevent errors with Set/GetRGield.  

You can use Num2StrF to change the real to a string.  This will properly format it to deal with units indicators and you don't have to worry about the accuracy parameter.

Share this post


Link to post

I would guess from what I have observed is that GetPt and GetPtL are not suitable for inside a Plugin object (VW2013).

This will display the Message and draw the Line and request a point from the user.

Bool2:=FALSE;

IF IsNewCustomObject(PIO_Name) THEN Bool2:=TRUE;

IF Bool2 THEN Message(cpHeight.y,'x',bool2);

IF Bool2 THEN GetPt(cpHeight.x,cpHeight.y);

MoveTo(0,0);

LineTo(0,0);

 

This will draw the Line and request a point from the user, but not display the Message.

Bool2:=FALSE;

IF IsNewCustomObject(PIO_Name) THEN Bool2:=TRUE;

IF Bool2 THEN GetPt(cpHeight.x,cpHeight.y);

 

IF Bool2 THEN Message(cpHeight.y,'x',bool2);

MoveTo(0,0);

LineTo(0,0);

 

This will draw the Line and request a point from the user, but not display the Message.

Bool2:=FALSE;

IF IsNewCustomObject(PIO_Name) THEN Bool2:=TRUE;

IF Bool2 THEN GetPt(cpHeight.x,cpHeight.y);

 

MoveTo(0,0);

Message(cpHeight.y,'x',bool2);

LineTo(0,0);

Share this post


Link to post

I've had issues with using a variable in the name location of SetRField so I've always typed it in.

The thing is that the control point is not moving to the user selected point location. I suspect GetPtL is not capturing values during first pass. The control point remains at the default location set by the parameter default values.

The exercise here is an attempt to have the control point set during the first run (placement) of the plugin and not have to drag it over to the correct location afterwards.

Edited by LarryO
clarification

Share this post


Link to post
59 minutes ago, LarryO said:

I've had issues with using a variable in the name location of SetRField so I've always typed it in.

 

I almost always use constants or variables for SetRField, so you shouldn't have any problem doing so.

 

Looking further into this, you have to make sure the tool doesn't run while creating the preview of the object and the tool collection runs at the end of the code.  There are some ways around this, but I think it's a lot for your coding level.  You're better off with an insertion tool here.

 

As a side question, is there a reason you need each picket to be a separate object?  You could have a line PIO that defines the top or bottom rail, and automatically draw the other rail and the pickets between them.

Share this post


Link to post

The pickets are only a series of lines on the slope of the rail. I group them when drawing them manually.

So I am capturing 3 points and pre-setting picket diameter and max gap values.

The nature of doing shop drawings, updating for site measures is that I created a tool which defines the measured stair with only two points and a few pre-set building code defined values; drawing in top and bottom rails that can be traced over or used as is. Then we manually place posts due to the variety of (un)suitable anchoring conditions, locations and styles that seem to occur within a single flight sometimes. And finally draw in pickets where required on a separate layer to make them print grey). So I am finally getting around to making a plugin to automate the task of calculating quantity and then spacing them equally along the incline of the rail. Hence my desire to simplify it all down to a three point task (2 steps) from what is currently about 12-14 steps if one does them in the correct order.

I'm sure that the SetRField works as you say it does; I just have a problem mixing up strings and character arrays all the time.

 

ATM I am trying to decide if I should Create the first line and copy along the incline or or draw along the axis and rotate them all into position. The latter is how I approached the stair tool because HDuplicate(objecthandle, distancevariable, # anglevariable d); fails. The angle mode indicator # does not appear capable of accepting a value from a variable. So much simpler if Polar vector variables were an option.

Share this post


Link to post
14 hours ago, LarryO said:

... because HDuplicate(objecthandle, distancevariable, # anglevariable d); fails. The angle mode indicator # does not appear capable of accepting a value from a variable. So much simpler if Polar vector variables were an option.

Larry,

   I've been at this a long time, but it was exactly two days ago I tried, as you did, to use hDuplicate() with polar coordinates and it failed. Here's a short program I used to test  the snippet of code I used to make it work. The built in vector function Ang2Vec() converts Polar to Rectangular coordinates. If you want, copy the PolarDup() function to your code and use it like you would use HDuplicate(). 

PROCEDURE xxx;
{ Duplicate selected object and move it a fixed distance in the direction of a user drawn Line. }
CONST
	Dist = 3;
VAR
	H, H1 :Handle;
	P1, P2 :Vector;
	Ang :Real;


	function PolarDup(H :Handle; Dist, Ang :Real) :Handle;
	{ Same as HDuplicate(), but accepts POLAR coordinates. Returns a handle to the new object. }
	Var
		V :Vector;
	Begin
		V := Ang2Vec(Ang, Dist);		{ set distance and direction to move }
		PolarDup := HDuplicate(H, V.x, V.y);	{ duplicate retains select state of original }
	End;	{ PolarDup }


BEGIN
	GetLine(P1.x, P1.y, P2.x, P2.y);	{ Get 2 points to define direction, distance is not important }
	Ang := Vec2Ang(P2-P1);
	
	H := FSActLayer;
	H1 := PolarDup(H, Dist, Ang);

	SysBeep;
END;
Run(xxx);

 

HTH,

Raymond

 

 

 

Share this post


Link to post

Thanks Josh & Raymond for the assistance.

I still have to tackle moving my control point into position so that it remains vertical to the origin in World space and making the code flip friendly. The latter I've done before so it will not be too much trouble. I still hope to figure out how to have GetPt retrieve values and pass them into a variable before the code finishes. It'll be such a pain if I have to deselect the tool every time to move the control point into position (it identifies the upper boundary of the pickets) and then re-select the tool to draw the next set of pickets.

This is a functional result, but has limitations. Only works from left to right ATM. It still has fluff code in it and some clarity formatting was lost during pasting.

 

Procedure Picketeer;
VAR
 PIO_Handle,PIO_ParentWall,PIO_Record,hLine1,hLine2: HANDLE;
 PIO_WorldOrigin: POINT;
 PIO_Rotation,rOffsetDistance:REAL;
 iAccuracy: INTEGER;
 Quantity: LONGINT;
 PIO_Name:STRING;
 Bool1:BOOLEAN;
 cpLocation,cpDestination: VECTOR;

{This Function may be required during improvements, leave in}
Function HDuplicatePolar(H :Handle; Dist, Ang :Real) :Handle; { Same as HDuplicate() using POLAR coordinate input }
    Var
        V :Vector;
    Begin
        V := Ang2Vec(Ang, Dist);        { convert polar to rectangular}
        HDuplicatePolar := HDuplicate(H, V.x, V.y);
    End;    { Function HDuplicatePolar}


BEGIN

PushAttrs;
FillColorByClass; FPatByClass; PenColorByClass; LSByClass; LWByClass; MarkerByClass; OpacityByClass;

{initialize required variables' values}
Bool1:=GetCustomObjectInfo(PIO_Name,PIO_Handle,PIO_Record,PIO_ParentWall);
GetSymLoc(PIO_Handle,PIO_WorldOrigin.x,PIO_WorldOrigin.y);
PIO_Rotation:=HAngle(PIO_Handle);
    {IF GetPrefReal(152)=1.0 THEN iAccuracy:=4 ELSE iAccuracy:=0;}    {imp vs mm, currently not req'd}
cpLocation.x:=PControlPoint01X; cpLocation.y:=PControlPoint01Y;
cpDestination:=Ang2Vec(PIO_Rotation, PLineLength);
Quantity:=0.5+(cpDestination.x+PPicketSize)/(PMaxGap+PPicketSize); {includes final picket which is replaced by next post}
rOffsetDistance:=(PlineLength+Ppicketsize)/Quantity; {centre to centre picket spacing}

MoveTo(0.0,0.0); {creating first picket}
LineTo(0.0,NORM(cpLocation));
hLine1:=LNewObj;
HRotate(hLine1,0,0,-PIO_Rotation); {orient first picket line vertically}
hLine2:= HDuplicate(hLine1, -PPicketsize/Cos(Deg2Rad(-PIO_Rotation)),0);

Hmove(hLine1,rOffsetDistance,0.0);    {Move first pickets into place. Could have started at this location instead of orgin.}
Hmove(hLine2,rOffsetDistance,0.0);    {Easier debugging of flip & rotation issues}

While (Quantity>2) Do {place remaining pickets}
    BEGIN
    hLine1:=HDuplicate(hLine1,rOffsetDistance,0.0);
    hLine2:=HDuplicate(hLine2,rOffsetDistance,0.0);
    Quantity:=Quantity-1;
    End;

PopAttrs;
END;
RUN(Picketeer);

Share this post


Link to post

You could maybe try RunTempTool() to get your control point value.   You're going to have to make sure that you only run the tool if the object is being inserted (IsNewCustomObject) AND the object is not in preview (GetParent(PIO_Handle) <> nil).  Unfortunately, these aren't true at the same time (though I didn't confirm with event enabled objects looking at states), you have to do something like (edited for brevity):

 

if IsNewCustomObject then

  SetRField( '__IsNew', Concat( TRUE) );

if P__IsNew then

  SetRField( '__IsNew', Concat( FALSE) );

  if GetParent <> nil THEN

    run tool

 

Otherwise, you're going to need to make a separate tool for placing pickets.  That could also help solve your left / right issue, as your placement tool could determine whether to flip the object.

Share this post


Link to post

I can't see how RunTempTool could work.

One has to pass it a Function and GetPt and GetPtL can only be called from a Procedure.

I experimented vstGetPt2D also choosing index #0, 1 and 2. Zero returns the world coordinate point for the PIO origin and one returns the second world coordinate point of the linear PIO. Two returns garbage, not the control point location. I do not think that these user interactive calls can work in a linear PIO. Once the PIO environment is created they crash and burn because they seem to be seeking information from the world environment that is somehow not available to them anymore.

So it would seem that I am stuck with what I have or taking some lessons on creating a custom tool to collect three points then call the linear PIO and somehow pass the values onto the procedure. While still permitting the procedure to act alone in regenerating itself after OIP changes and dragged point changes. hmmm

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×