Round Walls

From Vectorlab
Jump to: navigation, search

Writing PIOs for Round Walls is a challenge. To make sure the begin and end points of your PIO are on the desired offset from the wall centre you will need to know the radius of the wall, which way the wall is bending (Clock Wise or Counter Clock Wise), the flip state of the PIO and the rotation angle of the PIO. The user may also have inserted the PIO on one of the edges, while you intended the PIO for the Centre Line.

First of all you have to determine if you are going to write a Point PIO or a Line PIO. Some of the problems mentioned above have different solutions for the two PIO types. Although Line PIO's are not well supported for Walls as yet (VW 2008), they will probably be better supported in future versions of VectorWorks.

One of the things we don't have to bother about is the origin. PIOs have their own origin and at the moment of a redraw the User origin is reset to match the PIO's insertion point, so all coordinates used are related to the (0,0) of the PIO, unless a function is used that returns its values related to the Absolute Origin. See also the Absolute Origin article.


Point PIO

Ppio in rnd wall 001.gif

A very simple PIO inserted in a wall might look like the image shown here. (I would really prefer a radial cut over the current parallel cut!) The insertion point of the PIO is placed on the wall, therefor leaving the endpoints sticking out. To calculate the distance (d) over which to move the drawn objects inside the PIO (the PIO insertion point stays in its place).

d := r -Sqrt(Sqr(r) -Sqr(0.5 *width));

r = the distance from the wall centre point to the insertion point of the PIO, which is not necessarily the same as the radius of the wall.

IF GetType(gWallhand) = 89 THEN BEGIN

	HCenter(gWallhand, cx, cy);
	GetSymLoc(ghParm, px, py);
	r := Sqrt(Sqr(px -cx) +Sqr(py -cy));
	d := r -Sqrt(Sqr(r) -Sqr(0.5 *w));

As you can see in the right image, the PIO maybe flipped in the wall. To determine which way the PIO is flipped we use the flip state of the PIO and its angle and compare that with the angle of an imaginary vector from wall centre point to PIO insertion point.

Ppio in rnd wall 002.gif
	pioangle := GetSymRot(ghParm);
	v.x := px -cx; { loading a vector v }
	v.y := py -cy;
	testangle := vec2ang(v); 
		{ Using vector v only to determine the angle }
	IF IsObjectFlipped(ghParm) THEN 
		pioangle := pioangle +180;
		{ correcting for a flip over the PIO's Y axes }
	
	pioangle := pioangle +90;
		{ pointing in the direction of, or away from the Wall centre point }
	IF pioangle > 180 THEN 
		pioangle := pioangle -360;
		{ making sure the values of the angles are in a comparable range }
	
	IF (pioangle = testangle) THEN
		d := -d;
END;

Adding the code above to the simple point PIO. Makes for a Round Wall Corrected Point PIO.


Raising The Bar

When the PIO is inserted on the centre of the wall then that is where we draw it. But what if the PIO was placed on one of the edges of the wall? It would be nice if we could sink the door/window back into the wall. To determine on what side of the wall the PIO was placed, we can compare the radius of the wall with the distance of the insertion point to the wall centre point.

The radius of the wall is always measured from Wall centre point to the centre arc of the wall, and is always returned in millimeter, so don't forget to correct for that, using GetPrefReal(152).

Wr := (GetPrefReal(152)/25.4) *GetObjectVariableReal(Wallhand, 571); { Radius at the centre line }

From the previous paragraph:

	HCenter(gWallhand, cx,cy);
	GetSymLoc(ghParm, px,py);
	r := Sqrt(Sqr(px -cx) +Sqr(py -cy));

Subtracting:

	Curb := r -Wr;
	IF Curb < 0 THEN 
		curb := -1
	ELSE IF Curb > 0 THEN 
		curb := 1;
		{ -1 = inner side of the bend, 1 = outerside of the bend, 0 = heart }

so:

	IF curb *d < 0 THEN 
		curbD := -thickness/2 
	ELSE IF curb *d > 0 THEN 
		curbD := thickness/2 
	ELSE
		curbD := 0;
Ppio in rnd wall 003.gif

The Round Wall And Edge Corrected Point PIO. The left image shows the PIO without Edge correction. For the other two the edge correction is added to the code.


Topping It Off

The above was perfectly nice for interior walls. However, exterior walls have an inside and an outside, determined by the direction of drawing.

Looking from the start point (arrow) in the direction of drawing we assume the Left side to be outside and the Right side to be inside. It really doesn't matter how your office as agreed on this, as long as everybody (at least within the office) draws in the same fashion. We'll talk about Left and Right from this point on.

The following function will tell us if the wall was drawn clockwise (False) or counterclockwise (True):

	GetObjectVariableBoolean(wallH, 570);
Ppio in rnd wall 004.gif

The PIO might have a different finish on the inside; perhaps a frame around the wall opening. Let's also give the door some proper posts.

	Rect( -0.5*w -67mm, 0.5*t +d, -0.5*w, -0.5*t +d); { Left post }
	Rect(0.5*w, 0.5*t +d, 0.5*w +67mm, -0.5*t +d); { Right post }
	Rect( -0.5*w, 0.5*t +d, 0.5*w, 0.5*t +d -40mm); { a new door }


Line PIO

Examples

The Simple Point PIO

PROCEDURE P_PIO;
VAR
	w, t, x1, y1, x2, y2, x3, y3 : REAL;

BEGIN
	w := PWIDTH;
	t := PTHICKNESS;
	x1 := -w/2;
	y1 := t/2;
	x2 := -x1;
	y2 := -y1;
	x3 := w *cos(10 *pi /180) -(w/2); { Door ajar 10° }
	y3 := w *sin(10 *pi /180) +(t/2); { Door ajar 10° }

	Rect(x1, y1, x2, y2);
	MoveTo(x1, y1);
	LineTo(x3, y3);
END;
Run(P_PIO);


The Round Wall Corrected Point PIO

PROCEDURE P_PIO;
VAR
	w, t, x1, y1, x2, y2, x3, y3, d : REAL;
	gPIOName, gMerk	: STRING;
	gFlag : BOOLEAN;
	ghParm, gParmRecordHand, gWallHand	: HANDLE;

FUNCTION RoundWallCorrection : REAL;
VAR
	r, d, cx, cy, px, py, pioangle, testangle	: REAL;
	v : VECTOR;

	BEGIN { RoundWallCorrection }
		HCenter(gWallhand, cx, cy);
		GetSymLoc(ghParm, px, py);
		r := Sqrt(Sqr(px -cx) +Sqr(py -cy));
		d := r -Sqrt(Sqr(r) -Sqr(0.5 *w));

		pioangle := GetSymRot(ghParm);
		v.x := px -cx; { loading a vector v }
		v.y := py -cy;
		
		testangle := Vec2ang(v); { Using vector v only to determine the angle }
		
		IF IsObjectFlipped(ghParm) THEN 
			pioangle := pioangle +180;
			{ correcting for the flip state }
		
		pioangle := pioangle +90;
			{ pointing in the direction of, or away from the Wall centre point }
			
		IF pioangle > 180 THEN 
			pioangle := pioangle -360;
			{ making sure the values of the angles are in a comparable range }
		
		IF (pioangle = testangle) THEN
			d := -d;
			
		RoundWallCorrection := d;
	END; { RoundWallCorrection }

BEGIN { main }
	gFlag := GetCustomObjectInfo(gPIOName, ghParm, gParmRecordHand, gWallHand);

	w := PWIDTH;
	t := PTHICKNESS;
	x1 := -w/2;
	y1 := t/2;
	x2 := -x1;
	y2 := -y1;
	x3 := w *Cos(10 *pi/180) -(w/2); { Door ajar 10° }
	y3 := w *sin(10 *pi/180) +(t/2); { Door ajar 10° }

	IF GetType(gWallhand) = 89 THEN
		d := RoundWallCorrection
	ELSE
		d := 0;

	Rect(x1, y1 +d, x2, y2 +d);
	MoveTo(x1, y1 +d); LineTo(x3, y3 +d);
END; { main }
RUN(P_PIO);


The Round Wall And Edge Corrected Point PIO

PROCEDURE P_PIO;
VAR
	w, t, x1, y1, x2, y2, x3, y3, d, curbD : REAL;
	Upi	: REAL;
	ufraction, udisplay : LONGINT; 
	nr, uforma : INTEGER;
	gPIOName, gMerk, uname, usquareName : STRING;
	gFlag : BOOLEAN;
	ghParm, gParmRecordHand, gWallHand : HANDLE;
	
	FUNCTION RoundWallCorrection : REAL;
	VAR
		r, d, cx, cy, px, py, pioangle, testangle	: REAL;
		v : VECTOR;

	BEGIN { RoundWallCorrection }
		HCenter(gWallhand, cx, cy);
		GetSymLoc(ghParm, px, py);
		r := Sqrt(Sqr(px -cx) +Sqr(py -cy));
		d := r -Sqrt(Sqr(r) -Sqr(0.5 *w));

		pioangle := GetSymRot(ghParm);
		v.x := px -cx; { loading a vector v }
		v.y := py -cy;
		testangle := Vec2Ang(v); 
			{ Using vector v only to determine the angle }
		
		IF IsObjectFlipped(ghParm) THEN 
			pioangle := pioangle +180;
			{ correcting for the flip state }
		
		pioangle := pioangle +90;
			{ pointing in the direction of, or away from the Wall centre point }
		
		IF pioangle > 180 THEN
			pioangle := pioangle -360;
			{ making sure the values of the angles are in a comparable range }
		
		IF (pioangle = testangle) THEN
			d := -d;
		RoundWallCorrection := d;
		{ message(concat(GetType(gWallhand),' ',d,' ',w)); }
	END; { RoundWallCorrection }


	FUNCTION Curb : INTEGER;
	VAR
		Wr, cx, cy, px, py, r : REAL;
	
	BEGIN
		Wr := (GetPrefReal(152)/25.4) *GetObjectVariableReal(gWallhand, 571); { Radius at the centre line }
		HCenter(gWallhand, cx, cy);
		GetSymLoc(ghParm, px, py);
		r := Sqrt(Sqr(px -cx) +Sqr(py -cy));
		
		Curb := r -Wr;
		IF Curb <0 THEN 
			Curb := -1
		ELSE IF Curb >0 THEN 
			Curb := 1
		ELSE 
			Curb := 0
			{ -1 = inner side of the bend, 1 = outer side of the bend, 0 = heart }
	END; { Curb }


BEGIN { main }
	gFlag := GetCustomObjectInfo(gPIOName, ghParm, gParmRecordHand, gWallHand);
	GetUnits(ufraction, udisplay, uformat, upi, uname, usquareName);
	
	w := PWIDTH;
	t := PTHICKNESS;
	
	x1 := -w/2;
	y1 := t/2;
	x2 := -x1;
	y2 := -y1;
	x3 := w *Cos(10 *pi/180) -(w/2); { Door ajar 10° }
	y3 := w *sin(10 *pi/180) +(t/2); { Door ajar 10° }

	IF GetType(gWallhand) = 89 THEN BEGIN
		d := RoundWallCorrection;
		IF curb *d < 0 THEN 
			curbD := -t *0.5
		ELSE IF curb *d > 0 THEN
			curbD := t *0.5
		ELSE 
			curbD :=0;
		
		d := d +curbD;
		
	END ELSE
		d := 0;

	Rect(x1, y1 +d, x2, y2 +d);
	MoveTo(x1, y1 +d); LineTo(x3, y3 +d);
END; { main }
Run(P_PIO);