# Euclid Book 1 Proposition 2

Euclid’s 2nd proposition draws a line at point A equal in length to a line BC. It uses proposition 1 and is used by proposition 3. I tried to make a generic program I could use for both the primary job of illustrating the theorem and for the purpose of being used by subsequent theorems, but it is simpler to separate those into two sub procedures. The programming was pretty easy except when a line is extended to meet a circle, there are two intersections, and one of them has to be selected. A good illustration with labeled objects helps keep it straight.

In autocad 1-2 is not a problem. The solution would be to copy or move the line endpoint to endpoint. In Euclid, lines cannot be moved. The compass cannot be used to transfer a distance by being picked up off the page. In autocad items are rigid. When two objects the same are copied to the same location they exactly coincide. Euclid’s 4th Axiom is “Things that coincide with one another are equal to one another”. This has caused remarks as to its real meaning. If you cannot move an object to super-impose, how would you know, and even if you could move them, no physical object will perfectly cover another. This common belief, things that are the same coincide, is intended to point to ideal form, like we have in a cad program.

```Sub prime_pr2()
'given ptA and lineBC call proposition2

Dim ptA(0 To 2) As Double
Dim ptB(0 To 2) As Double
Dim ptC(0 To 2) As Double

Dim Ax As Double, Ay As Double
Dim Bx As Double, By As Double
Dim Cx As Double, Cy As Double

Ax = rnddbl(0, 5)
Ay = rnddbl(0, 5)
Bx = rnddbl(6, 10)
By = rnddbl(0, 10)
Cx = rnddbl(6, 20)
Cy = rnddbl(15, 25)

Call pt(ptA, Ax, Ay, 0)
Call pt(ptB, Bx, By, 0)
Call pt(ptC, Cx, Cy, 0)

Call pr2(ptA, ptB, ptC)
End Sub

Sub pr2(ptA() As Double, ptB() As Double, ptC() As Double)

Dim r As Double
Dim intpts As Variant

Dim ptD(0 To 2) As Double
Dim ptG(0 To 2) As Double
Dim ptL(0 To 2) As Double

'now we need Euclid 1-1 to draw equilateral triangle
Call pr2_pr1_sub(ptA, ptB)

'vertex found
ptD(0) = ptG1(0)
ptD(1) = ptG1(1)
ptD(2) = ptG1(2)

'find ptG, do lineBG
r = distance(ptB, ptC)
intpts = lineBD.IntersectWith(circH, acExtendThisEntity)
Call intpts_eval(intpts)

'want ptG intersection farthest from ptD
If distance(ptD, ptG1) > distance(ptD, ptG2) Then
ptG(0) = ptG1(0)
ptG(1) = ptG1(1)
ptG(2) = ptG1(2)

Else
ptG(0) = ptG2(0)
ptG(1) = ptG2(1)
ptG(2) = ptG2(2)
End If

'now find ptL, do lineAL
r = distance(ptD, ptG)

Call intpts_eval(intpts)

'going to take the lesser y value
If ptG1(1) > ptG2(1) Then
ptG1(0) = ptG2(0)
ptG1(1) = ptG2(1)
ptG1(2) = ptG2(2)
End If

ptL(0) = ptG1(0)
ptL(1) = ptG1(1)
ptL(2) = ptG1(2)

'ptG1 is same as ptL
End Sub

Sub pr2_pr1_sub(ptA() As Double, ptB() As Double)
'just the bare necessities - no drawing - calculate vertex

Dim r As Double
r = distance(ptA, ptB)

r = distance(ptB, ptA)

Dim intpts As Variant
intpts = circD.IntersectWith(circE, acExtendNone)
Call intpts_eval(intpts)

'going to take positive y value
'this is how i am passing back found vertex
If ptG2(1) > ptG1(1) Then
ptG1(0) = ptG2(0)
ptG1(1) = ptG2(1)
ptG1(2) = ptG2(2)
End If

circD.Delete
circE.Delete

End Sub

```

The Ellipse

Autocad has an ellipse object. The AddEllipse method takes a center point, a second point which is the end of the major axis, and a factor autodesk calls RadiusRatio, which is just b / a. This is not the same thing as Eccentricity which is c / a, though similar but inverse and they both must be less than 1. I have not seen RadiusRatio in a math book. RadiusRatio gives a circle if it is equal to 1. If it is greater than 1 it throws an error. Eccentricity is a math term and gives a circle when it is zero. If it were 1 i believe the ellipse would collapse to a straight line.

To create an autocad vba ellipse with vertical axis, make the second point, MajorAxis, vertical above the center point. Autocad gives no indication where the Focus is. It has to be calculated from the values of A and B.

```Sub init_frm_ellipse()
a = frm_Ellipse.txt_a1
b = frm_Ellipse.txt_b1
End Sub

Sub horz_new_ellipse()
'RadiusRatio must be less than or equal to 1
'MajorAxis is a relative point off the center, not an absolute point
Call init_frm_ellipse

Dim ptctr(0 To 2) As Double
Dim pta(0 To 2) As Double
Call initpt(ptctr, 0, 0, 0)
Call initpt(pta, a, 0, 0)

obj_ellipse.Update
End Sub

Sub vert_new_ellipse()
Call init_frm_ellipse

Dim ptctr(0 To 2) As Double
Dim pta(0 To 2) As Double
Call initpt(ptctr, 0, 0, 0)
Call initpt(pta, 0, a, 0)

obj_ellipse.Update
End Sub
```

The autodesk method advantage is that by specifying a center, then a relative point from the center for the end of the major axis, the ellipse can be turned to any angle. With some simple trig we can accept input in degrees and calculate the major axis vertex.

``` Function deg2rad(deg As Double) As Double
deg2rad = deg * Pi / 180
End Function

Sub init_frm_ellipse()
a = frm_Ellipse.txt_a1
b = frm_Ellipse.txt_b1
c = frm_Ellipse.txt_c1
End Sub

Sub new_ellipse()
'RadiusRatio must be less than or equal to 1
'MajorAxis is a point, not a length
Call init_frm_ellipse

Dim ptctr(0 To 2) As Double
Dim pta(0 To 2) As Double
Dim x1 As Double, y1 As Double

Call initpt(ptctr, 0, 0, 0)
Call initpt(pta, x1, y1, 0)

obj_ellipse.Update
End Sub
```

we can move the ellipse off the center. The input for AddEllipse does not require an absolute point for MajorAxis. It takes a point relative to the center.

Drawing the ellipse is straightforward. calculating the focus and end points to mark them requires some trig to accomodate the angled axes.

```
Sub new_ellipse()
'takes input from the form
'a major axis
'b minor axis
'd degree of major axis
'h and k, xy values for center of ellipse
'converts input to
'RadiusRatio must be less than or equal to 1
'MajorAxis is a point relative from the center, not an absolute point
Call init_frm_ellipse ' gets the values from the form

Dim ctr(0 To 2) As Double
Dim pt_a(0 To 2) As Double
Dim x1 As Double, y1 As Double

Call initpt(ctr, h, k, 0)
Call initpt(pt_a, x1, y1, 0)

obj_ellipse.Update

'to plot points
Dim pt_a1(0 To 2) As Double
Dim pt_a2(0 To 2) As Double
Dim pt_b1(0 To 2) As Double
Dim pt_b2(0 To 2) As Double
Dim pt_f1(0 To 2) As Double
Dim pt_f2(0 To 2) As Double

Dim fx1 As Double, fy1 As Double, fx2 As Double, fy2 As Double
Dim ax1 As Double, ay1 As Double, ax2 As Double, ay2 As Double
Dim bx1 As Double, by1 As Double, bx2 As Double, by2 As Double

'c is the focal distance from ctr
c = (a ^ 2 - b ^ 2) ^ 0.5
fx1 = h + c * Cos(deg2rad(d))
fy1 = k + c * Sin(deg2rad(d))
fx2 = h - c * Cos(deg2rad(d))
fy2 = k - c * Sin(deg2rad(d))

bx1 = h + b * Cos(deg2rad(d + 90))
by1 = k + b * Sin(deg2rad(d + 90))

bx2 = h - b * Cos(deg2rad(d + 90))
by2 = k - b * Sin(deg2rad(d + 90))

ax1 = h + a * Cos(deg2rad(d))
ay1 = k + a * Sin(deg2rad(d))

ax2 = h - a * Cos(deg2rad(d))
ay2 = k - a * Sin(deg2rad(d))

Call initpt(pt_a1, ax1, ay1, 0)
Call initpt(pt_a2, ax2, ay2, 0)
Call initpt(pt_b1, bx1, by1, 0)
Call initpt(pt_b2, bx2, by2, 0)
Call initpt(pt_f1, fx1, fy1, 0)
Call initpt(pt_f2, fx2, fy2, 0)

Update

End Sub
```

In astronomy, planets orbit around the sun in ellipses with the sun at one focus. To draw these orbits we need to input the different numbers but always draw one focus, the sun, at the origin.

orbits of the nine planets (simplified with major axes aligned, no inclination). The sun and all planets are drawn full size, but the distances of the orbits are so vast they are not seen. this is much more fun to do yourself to zoom around and get a feel for the distance than to look at a screenshot.

the astronomy book gives the half major axis in (x 10^6 km), Orbital Eccentricity, and planet radius in km. those are the inputs. The value for Uranus caused Long and Double variable types to overflow but i had no issues using Currency data type. don’t base your senior thesis on this, i dont have supervision. it gives a visually correct orbit for pluto that it actually crosses inside neptune’s orbit because of pluto’s higher eccentricity. there are other 3D factors i do not take into consideration, inclination – ellipse tilt – and two other twists in 3D space. so neptune and pluto can never collide.

```Public Const xkm As Currency = 1000000

Sub solar_system()
'testCall planetary_ellipse(6, 0.5, 1)

Dim pt0(0 To 2) As Double
Call initpt(pt0, 0, 0, 0)

'this is the sun

'mercury
Call planetary_ellipse(57.9 * xkm, 0.206, 2440)

'venus
Call planetary_ellipse(108.2 * xkm, 0.007, 6052)

'earth
Call planetary_ellipse(149.6 * xkm, 0.017, 6378)

'mars
Call planetary_ellipse(227.9 * xkm, 0.093, 3397)

'jupiter
Call planetary_ellipse(778.4 * xkm, 0.048, 71492)

'saturn
Call planetary_ellipse(1427 * xkm, 0.054, 60268)

'too large
'uranus
Call planetary_ellipse(2871 * xkm, 0.047, 25559)

'neptune
Call planetary_ellipse(4498 * xkm, 0.009, 24764)

'pluto
Call planetary_ellipse(5906 * xkm, 0.249, 1195)

End Sub

Sub planetary_ellipse(a As Currency, e As Double, r As Long)
'a is major axis km
'e is eccentricity
'r is planetary equatorial radius in km

'RadiusRatio must be less than or equal to 1
'MajorAxis is a point, not a length

Dim b As Double
Dim c As Double

Dim ctr(0 To 2) As Double
Dim f1(0 To 2) As Double
Dim f2(0 To 2) As Double
Dim pt_a(0 To 2) As Double
Dim pt_p(0 To 2) As Double
Dim a_vector(0 To 2) As Double

c = a * e
b = a * (1 - e ^ 2) ^ 0.5

Call initpt(ctr, c, 0, 0)
Call initpt(f1, 0, 0, 0)
Call initpt(f2, 2 * c, 0, 0)
Call initpt(pt_a, a + c, 0, 0)
Call initpt(pt_p, c - a, 0, 0)

Call initpt(a_vector, 1 * a, 0, 0)

obj_ellipse.Update

End Sub

```

# Autocad VBA Logo Turtle Graphics

Logo was a lisp like educational language designed to introduce children to coding. I believe there may be no serious impediments to implementing an experimental version in Autocad VBA. This is a work in process, first post is proof of concept. The full implementation is yet to be planned. I wont worry too much about deviating from standard logo methods or syntax. If i hit a problem that cannot be coded around, that will be information gained. I believe the concepts may turn out to be useful for more general VBA parametric autocad code.

For all of my projects, I code in an Excel XLSM file. I have a standard ACAD_CONNECT sub i use, and reference the Autocad Type Library in the Excel VBAProject. i have never downloaded the Autocad VBA implementation. It is not necessary to code Autocad VBA. I use the VBA editor provided routinely in Excel.

The fundamental element of turtle geometry is the current position of the pen, and the heading or direction it is pointing. This prototype will be 2D, so we need a global variable for the X and Y position, and a variable for the heading. We will keep heading in degrees and convert it in the low level subs to radians.

The first thing we will need is a line subroutine that takes logo style input – current point, distance, and heading – to draw the line and change the pen position to the end of the line. The user wont call this sub directly but will use std routines like Forward, PenUP, Right, Left, etc.

```Option Explicit
Public px As Double 'position x
Public py As Double 'position y
Public hxy As Double 'heading degree

Sub line_hd(x1 As Double, y1 As Double, dist As Double, heading As Double)

Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double

pt1(0) = x1: pt1(1) = y1: pt1(2) = 0

'px and py are global position

pt2(0) = px: pt2(1) = py: pt2(2) = 0

Update
End Sub
```

standard logo subroutines FORWARD, RIGHT, LEFT and BACK to get started are pretty simple at this point. i dont have a PENUP, PENDOWN yet that will modify these.

```Sub forward(dist As Double)
Call line_hd(px, py, dist, hxy)
End Sub

Sub right(deg As Double)
hxy = hxy - deg
End Sub

Sub left(deg As Double)
hxy = hxy + deg
End Sub

Sub back(dist As Double)
End Sub
```

a sample user prototype sub and init sub helper.

``` Sub init_turtle()
px = 0
py = 0
hxy = 0
End Sub

Sub to_honeycomb()
init_turtle
Dim i As Integer, j As Integer

For j = 1 To 3
For i = 1 To 6
forward 6
left 60
Next i

left 120
Next j

End Sub
```

``` Sub to_star()
init_turtle
Dim i As Integer

For i = 1 To 5
forward 6
right 144
Next i

End Sub
```

the circle routine according to python turtle graphics just takes a radius. from the position and heading of the turtle, it makes a 360 arc back to the starting point. if the radius is positive, it turns counterclockwise, if negative then opposite. the task then is to run a normal perpendicular off the heading vector the same distance as the radius to find the center.

this is a little messy, i dont think it will stay this way.

first a demo calling program, then the circle primitive code.

```Sub test_circle()
init_turtle

For i = 1 To 21
forward 6
right 15 + i
forward 6
curcle 3
forward 3
curcle -3
forward 6
curcle -3
forward 3
curcle 3
Next i

End Sub

End Sub

Sub circle_turtle(x1 As Double, y1 As Double, radius As Double, hxy As Double)
' circle wrapper
Dim Cx As Double, Cy As Double
Dim pt2(0 To 2) As Double

Else
End If

'px and py are global position
'we are calculating circle center but not changing position
pt2(0) = Cx: pt2(1) = Cy: pt2(2) = 0

Update
End Sub

```

more to come

A non-trivial VBA parametric project requires some structure to re-use standard techniques and a guide drawing to be made with user parameters identified that specifies the point values to be drawn. This sample project is a sheet metal frame that would be used to cap a hole. There are only two parts, top/bottom and side, but they are drawn both in front assembly and laid out flat before bending, so there are 4 basic drawing sub-routines. The drawing subroutines create geometry. Their only other job is to initialize bounding box variables so the calling program has the option to move into assembly, block, and/or rotate.

The parts are always drawn with lower left corner at or near 0,0. The master drawing is created manually before the programming is started. If carefully done, and revised until it works as needed, it will make the programming much easier.

Give each project its own module. It solves naming issues if each project is given a simple project ID, then prefix all the subs with the ID. The draw subs are at the bottom and the controlling program at the top. The draw subs are completed first, all in a similar manner. Again it makes programming much simpler if all the controlling sketches are laid out consistently and thoroughly. The only variables passed are the user variables. Calculations are made in the drawing sub. The sketches should be consistent – variable D1 in one sketch is the same value D1 in another sketch.

```
Sub B1_chan_top_bent(A As Double, D As Double, E As Double)
Dim pt As Variant
Dim A1 As Double, A2 As Double
A1 = A + D + D
A2 = A + D

'bounding box pt_ll and pt_ur are global vars
Call initpt(pt_ll, -1, -1, 0)
Call initpt(pt_ur, A1 + 2, D + 2, 0)

pt = Array(0, E, D, E, D, 0, _
A2, 0, A2, E, A1, E, _
A1, D, 0, D)
Call draw_array(pt)

Call line(D, E, A2, E)

'each drawing sub re-sets current layer to 0
Update
End Sub

Sub B1_chan_side_bent(B As Double, D As Double, E As Double)
Dim pt As Variant
Dim B1 As Double
B1 = B + E + E

'bounding box
Call initpt(pt_ll, -1, -1, 0)
Call initpt(pt_ur, B1 + 2, D + 2, 0)

pt = Array(0, 0, B1, 0, B1, D, 0, D)
Call draw_array(pt)

Call line(0, E, B1, E)

Update
End Sub

Sub B1_chan_top_flat(A As Double, C As Double, D As Double, E As Double)
Dim pt As Variant
Dim A1 As Double, A2 As Double, C1 As Double, C2 As Double, D1 As Double
A1 = A + D + D
A2 = A + D
D1 = D - E
C1 = C + D1
C2 = C + D1 + D1

'bounding box
Call initpt(pt_ll, -1, -1, 0)
Call initpt(pt_ur, A1 + 2, C2 + 2, 0)

pt = Array(0, 0, A1, 0, A1, D1, _
A2, D1, A2, C1, A1, C1, _
A1, C2, 0, C2, 0, C1, _
D, C1, D, D1, 0, D1)
Call draw_array(pt)

Call line(D, D1, A2, D1)
Call line(D, C1, A2, C1)

Update
End Sub

Sub B1_chan_side_flat(B As Double, C As Double, D As Double, E As Double)
Dim pt As Variant
Dim B1 As Double, C1 As Double, C2 As Double, D1 As Double
B1 = B + E + E
D1 = D - E
C1 = C + D1
C2 = C + D1 + D1

'bounding box
Call initpt(pt_ll, -1, -1, 0)
Call initpt(pt_ur, B1 + 2, C2 + 2, 0)

'outside box
pt = Array(0, 0, B1, 0, B1, C2, 0, C2)
Call draw_array(pt)

Call line(0, D1, B1, D1)
Call line(0, C1, B1, C1)

Update
End Sub
```

These can be called in any order. In this project i call the bent pieces first. I block them, then move them to an assembly position, using an arbitrary location (K, K). The side piece is drawn horizontal, so it is first rotated and moved about the same point. Again these points are located first on the sketches. The parts are blocked with a sub that accepts the bounding box coordinates, a name and a point for insert point. That routine works with any similar project. It creates a selection set using the bounding box, creates the block with name and insert point, adds the selection set entities to the block, erases the original entities and finally inserts the block. It assigns the block to a global var so the calling program can move it. These routines are in their own module shared by multiple projects.

```Sub make_ss_blk(pt_ll() As Double, pt_ur() As Double, strblkname As String, pt_insert() As Double)
'creates new ss, adds items to it with a crossing window
'creates new block, adds ss to blk with counting loop
'deletes original entities and inserts the block
'creates an object reference to the block objpersistent for moving/rotating

Dim i As Integer

objss.Select acSelectionSetCrossing, pt_ll, pt_ur

' make_blk(objss, strblkname, pt_insert)
On Error Resume Next
objBlock.Delete
On Error GoTo 0

ReDim Obj(0 To objss.Count - 1) As AcadObject
'Copy each object selected in the block
For i = 0 To objss.Count - 1
Set Obj(i) = objss(i)
Next i

objss.Erase
objss.Delete

Set objpersistent = acadDoc.ModelSpace.InsertBlock(pt_insert, strblkname, 1, 1, 1, 0)

End Sub

On Error Resume Next
If "" = strname Then
Exit Sub
End If

objss.Delete
If objss Is Nothing Then
MsgBox "unable to add " & strname
Else
End If
End Sub
```

The main calling program will vary depending on interface. Here is the basic one with variable values called out near the top.

```
Option Explicit
'ProjID B1
'Project Name - Inside Cap Channel
'ProjDesc - to cap existing hole
'a b c d e

Public Const Pi As Double = 3.14159265359
Public Const halfPI = Pi / 2

Public pt0(0 To 2) As Double
Public pt_ll(0 To 2) As Double
Public pt_ur(0 To 2) As Double

Sub B1_draw_inside_cap_chan_assy()

Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double
Dim K As Double
K = 50
Call init_part

'assy vars
Dim A As Double, B As Double, C As Double, D As Double, E As Double
'A is X, B is Y, C is ID THK, D is BENT FLG, E is GA

A = 24
B = 36
C = 4.125
D = 2.5
E = 0.125

Call B1_chan_top_bent(A, D, E)
Call make_ss_blk(pt_ll, pt_ur, "B1_chan_top", pt0)
Call initpt(pt1, A / 2 + D, 0, 0)
Call initpt(pt2, K, K + B / 2, 0)
objpersistent.Move pt1, pt2

Call B1_chan_side_bent(B, D, E)
Call make_ss_blk(pt_ll, pt_ur, "B1_chan_side", pt0)
Call initpt(pt1, B / 2 + E, 0, 0)
Call initpt(pt2, K + A / 2, K, 0)
objpersistent.Rotate pt1, -halfPI
objpersistent.Move pt1, pt2

Call B1_chan_top_flat(A, C, D, E)
objss.Select acSelectionSetWindow, pt_ll, pt_ur

Call initpt(pt2, 0, 48, 0)
For Each objent In objss
objent.Move pt0, pt2
Next

Call B1_chan_side_flat(B, C, D, E)
objss.Select acSelectionSetWindow, pt_ll, pt_ur

Call initpt(pt2, 0, 24, 0)
For Each objent In objss
objent.Move pt0, pt2
Next

Call initpt(pt2, K, K, 0)
Call cap_chan_sect(C + (2 * E), D, E)
objpersistent.Move pt0, pt2

Update
End Sub
```

This creates –

The section view is a straightforward drawing sub

```Sub cap_chan_sect(C As Double, D As Double, E As Double)
Dim pt As Variant
Call initpt(pt_ll, -1, -1, 0)
Call initpt(pt_ur, D + 2, C + 2, 0)

pt = Array(0, 0, D, 0, D, E, E, E, E, C - E, D, C - E, D, C, 0, C)
Call draw_array(pt)

Update
End Sub
```

The init-part sub is simply because i like to be able to run programs in a completely new blank drawing. it creates layers, but also makes the initial connection between excel VBA code and autocad.

```Sub init_part()
Call initpt(pt0, 0, 0, 0)
Call newlayer("UP", 4, acLnWtByLwDefault, "Continuous")
Call newlayer("Down", 6, acLnWtByLwDefault, "Hidden")
Call newlayer("Hidden", 6, acLnWtByLwDefault, "Hidden")
End Sub
```

Anything you can draw manually with specificity and clearly defined variables you can automate. It is only slightly more effort to automate dimensioning. Practice will refine your technique.

# Creating the Graph Point Data

Autocad AddLightWeightPolyline method requires an array of doubles. It does not require the lowerbound of the array to be zero. An array simply has to have an even number of elements, one element for each X and each Y alternating. (x1, y1, x2, y2, x3, y3…) For indexes and loops I typically use the counting numbers, which do not include zero. I am evaluating an autocad work-alike program that is similar but requires arrays to be zero-based. It does not throw an error with a one-based array but results are a failure. it creates zero values for non-existent indexes that it expects. However there is no reason the arrays cannot be zero-based so they run in both packages. To that end for that reason i am re-doing the graph loops.

Only the array needs to be zero based. The loop still executes one time for each point. The index of the array starts with zero.

Calculation of points for Coordinate XY graphing –

Autocad does not care what indexes the array pt (below) was created with. The work-alike absolutely requires a starting index of zero.

```Dim plineobj As AcadLWPolyline
```

in line drawing mode, subtracting lbound from ubound adding one and dividing by two will give the number of points in the array. There is one less line. Since we know lbound is zero we could remove that. The loop iterates once for each line drawn. We could do the loop to handle any lbound value, but it would be a little messy with no immediate benefit. For now we expect a zero base array.

```Sub draw_lines(ByRef pt() As Double)
Dim i As Integer, numpts As Integer, numlines As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double

numpts = (UBound(pt) - LBound(pt) + 1) / 2
numlines = numpts - 1

'this requires a zero base array
For i = 1 To numlines
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
x2 = pt(i * 2)
y2 = pt(i * 2 + 1)

pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
pt2(0) = x2: pt2(1) = y2: pt2(2) = 0

Next i

Update
End Sub
```

Lines w/limits mode we use when the Y value approaches infinity, such as y=1/x near x=0. It is otherwise the same.

```Sub draw_lines_wlimits(xlim As Double, ylim As Double, ByRef pt() As Double)
Dim i As Integer, numpts As Integer, numlines As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim pt1(0 To 2) As Double
Dim pt2(0 To 2) As Double

numpts = (UBound(pt) - LBound(pt) + 1) / 2
numlines = numpts - 1

'this requires a zero base array
For i = 1 To numlines
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
x2 = pt(i * 2)
y2 = pt(i * 2 + 1)

If Abs(x1) < xlim And Abs(y1) < ylim And Abs(x2) < xlim And Abs(y2) < ylim Then
pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
pt2(0) = x2: pt2(1) = y2: pt2(2) = 0
End If
Next i

Update
End Sub
```

point mode

```
Sub draw_points(ByRef pt() As Double)
Call pointmode
Dim i As Integer, numpts As Integer
Dim x1 As Double, y1 As Double

Dim pt1(0 To 2) As Double
numpts = (UBound(pt) - LBound(pt) + 1) / 2

'this requires a zero base array
For i = 1 To numpts
x1 = pt(i * 2 - 2)
y1 = pt(i * 2 - 1)
pt1(0) = x1: pt1(1) = y1: pt1(2) = 0
Next i

Update
End Sub

```

# the Cochleoid

the Cochleoid is a polar spiral that spirals in on itself, because Sin A varies between -1 and 1, but A gets ever larger.

at point 8 A is 210, not 30, but because the Sin is negative, R is negative. The graph passes thru 0,0 every time the sin is zero.

running the graph from negative 1080 (-6 pi) to -1 (to avoid divide by zero error) draws the mirror image graph from the inside out.

wolfram reference
http://mathworld.wolfram.com/Cochleoid.html