Microsoft Small Basic

Program Listing: JLD998
' Connected Circles
' Version 0.1
' Copyright © 2018 Nonki Takahashi. The MIT License.
' Last update 2018-12-12

GraphicsWindow.Title = "Connected Circles | Toggle Shapes opacity with mouse"
Init()
rMin = 20
rMax = 100
pw = 0
pc = "Black"
x3 = 0 ' dummy for the future
y3 = 0 ' dummy for the future
While "True"
bc = "Red"
r1 = Math.GetRandomNumber(rMax - rMin + 1) + (rMin - 1)
r2 = r1
x1 = Math.GetRandomNumber(gw - 2 * r1 - 20) + r1 + 10
y1 = Math.GetRandomNumber(gh - 2 * r1 - 20) + r1 + 10
x2 = Math.GetRandomNumber(gw - 2 * r2 - 20) + r2 + 10
y2 = Math.GetRandomNumber(gh - 2 * r2 - 20) + r2 + 10
ConnectedCircles()
Delay()
RemoveShapes()
bc = "Blue"
rL = 1
rS = 1
While (2 < (rL / rS)) Or (rL = rS)
r1 = Math.GetRandomNumber(rMax - rMin + 1) + (rMin - 1)
r2 = Math.GetRandomNumber(rMax - rMin + 1) + (rMin - 1)
rL = Math.Max(r1, r2)
rS = Math.Min(r1, r2)
EndWhile
x1 = Math.GetRandomNumber(gw - 2 * r1 - 20) + r1 + 10
y1 = Math.GetRandomNumber(gh - 2 * r1 - 20) + r1 + 10
x2 = Math.GetRandomNumber(gw - 2 * r2 - 20) + r2 + 10
y2 = Math.GetRandomNumber(gh - 2 * r2 - 20) + r2 + 10
ConnectedCircles()
Delay()
RemoveShapes()
EndWhile

Sub AddEllipse
i = i + 1
GraphicsWindow.PenColor = pc
GraphicsWindow.PenWidth = pw
GraphicsWindow.BrushColor = bc
shp[i] = Shapes.AddEllipse(width, height)
Shapes.Move(shp[i], x, y)
Shapes.SetOpacity(shp[i], op)
EndSub

Sub AddLine
If 0 < pw Then
i = i + 1
GraphicsWindow.PenColor = pc
GraphicsWindow.PenWidth = pw
shp[i] = Shapes.AddLine(x1, y1, x2, y2)
Shapes.Move(shp[i], x, y)
Shapes.SetOpacity(shp[i], op)
EndIf
EndSub

Sub AddRectangle
i = i + 1
GraphicsWindow.PenColor = pc
GraphicsWindow.PenWidth = pw
GraphicsWindow.BrushColor = bc
shp[i] = Shapes.AddRectangle(width, height)
Shapes.Move(shp[i], x, y)
Shapes.Rotate(shp[i], angle)
Shapes.SetOpacity(shp[i], op)
EndSub

Sub AddTriangle
i = i + 1
GraphicsWindow.PenColor = pc
GraphicsWindow.PenWidth = pw
GraphicsWindow.BrushColor = bc
shp[i] = Shapes.AddTriangle(x1, y1, x2, y2, x3, y3)
Shapes.Move(shp[i], x, y)
Shapes.Rotate(shp[i], angle)
Shapes.SetOpacity(shp[i], op)
EndSub

Sub ConnectedCircles
' param r1 - the radius of the circle1
' param r2 - the radius of the circle2
' param x1, y1 - the center coordinate of the circle 1
' param x2, y2 - the cneter coordinate of the circle2
GraphicsWindow.PenColor = pc
GraphicsWindow.PenWidth = pw
If r1 = r2 Then
r = r1
SameSize()
Else
If r1 < r2 Then
rL = r2
xL = x2
yL = y2
rS = r1
xS = x1
yS = y1
Else
rL = r1
xL = x1
yL = y1
rS = r2
xS = x2
yS = y2
EndIf
x = xS - xL
y = yS - yL
Math_CartesianToPolar()
d = r
DifferentSize()
EndIf
EndSub

Sub Delay
t = Clock.ElapsedMilliseconds
mouseDown = "False"
While Clock.ElapsedMilliseconds < (t + 3000)
If mouseDown Then
If op = 100 Then
op = 70
Else
op = 100
EndIF
For i = 1 To Array.GetItemCount(shp)
Shapes.SetOpacity(shp[i], op)
EndFor
mouseDown = "False"
EndIf
EndWhile
EndSub

Sub DifferentSize
' param rL - the radius of the large circle
' param rS - the radius of the small circle
' param xL, yL - the center coordinate of the large circle
' param xS, yS - the cneter coordinate of the small circle
' param a - the angle between (xL, yL) and (xS, yS)
' param d - the distance between (xL, yL) and (xS, yS)
_x1 = x1
_y1 = y1
_x2 = x2
_y2 = y2
i = 0
width = 2 * rL
height = 2 * rL
x = xL - rL
y = yL - rL
AddEllipse()
width = 2 * rS
height = 2 * rS
x = xS - rS
y = yS - rS
AddEllipse()
dr = rL - rS
w = Math.SquareRoot(d * d - dr * dr)
_θ = Math.ArcCos(w / d)
θ = Math.GetDegrees(_θ)
_a = Math.GetRadians(a)
_pw = pw
For j = 1 To 2
pw = 0
If j = 1 Then
sign = -1
Else
sign = 1
EndIf
width = w
height = rL
px = xS + rS * Math.Cos(_a + sign * (_θ - π / 2))
py = yS + rS * Math.Sin(_a + sign * (_θ - π / 2))
x = (xL + px) / 2 - w / 2
y = (yL + py) / 2 - rL / 2
angle = a + sign * θ
AddRectangle()
pw = _pw
x1 = xS + (rS - pw / 2) * Math.Cos(_a + sign * (_θ - π / 2))
y1 = yS + (rS - pw / 2) * Math.Sin(_a + sign * (_θ - π / 2))
x2 = xL + (rL - pw / 2) * Math.Cos(_a + sign * (_θ - π / 2))
y2 = yL + (rL - pw / 2) * Math.Sin(_a + sign * (_θ - π / 2))
x = 0
y = 0
angle = 0
AddLine()
EndFor
pw = _pw
x1 = _x1
y1 = _y1
x2 = _x2
y2 = _y2
EndSub

Sub Init
Not = "True=False;False=True;"
π = Math.Pi
gw = 598
gh = 428
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.PenWidth = 0
op = 100
GraphicsWindow.MouseDown = OnMouseDown
EndSub

Sub OnMouseDown
mouseDown = "True"
EndSub

Sub SameSize
' param r - radius
' param x1, y1 - the center coordinate of the circle 1
' param x2, y2 - the cneter coordinate of the circle2
_x1 = x1
_y1 = y1
_x2 = x2
_y2 = y2
i = 0
width = 2 * r
height = 2 * r
x = x1 - r
y = y1 - r
AddEllipse()
x = x2 - r
y = y2 - r
AddEllipse()
x = x2 - x1
y = y2 - y1
_r = r
Math_CartesianToPolar()
d = r
r = _r
_pw = pw
pw = 0
width = d
height = 2 * r
x = (x1 + x2) / 2 - d / 2
y = (y1 + y2) / 2 - r
angle = a
AddRectangle()
_a = Math.GetRadians(a)
pw = _pw
x = 0
y = 0
angle = 0
For j = 1 To 2
If j = 1 Then
sign = 1
Else
sign = -1
EndIf
x1 = _x1 + (r - pw / 2) * Math.Cos(_a - sign * π / 2)
y1 = _y1 + (r - pw / 2) * Math.Sin(_a - sign * π / 2)
x2 = _x2 + (r - pw / 2) * Math.Cos(_a - sign * π / 2)
y2 = _y2 + (r - pw / 2) * Math.Sin(_a - sign * π / 2)
AddLine()
EndFor
x1 = _x1
y1 = _y1
x2 = _x2
y2 = _y2
EndSub

Sub RemoveShapes
n = Array.GetItemCount(shp)
For i = 1 To n
Shapes.Remove(shp[i])
shp[i] = ""
EndFor
EndSub

Sub Math_CartesianToPolar
' Math | convert cartesian coodinate To polar coordinate
' param x, y - cartesian coordinate
' return r, a - polar coordinate
r = Math.SquareRoot(x * x + y * y)
If x = 0 And y > 0 Then
a = 90 ' [degree]
ElseIf x = 0 And y < 0 Then
a = -90
ElseIf x = 0 Then
a = 0
Else
a = Math.ArcTan(y / x) * 180 / Math.Pi
EndIf
If x < 0 Then
a = a + 180
ElseIf x >= 0 And y < 0 Then
a = a + 360
EndIf
EndSub