# Round Walls

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

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.

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

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

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