Repository navigation
Expand file tree
/
Copy pathGraphing Program.bas
More file actions
244 lines (214 loc) · 7.34 KB
/
Copy pathGraphing Program.bas
File metadata and controls
244 lines (214 loc) · 7.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
' FreeBASIC 3D Graphing Program
' Modes: Cartesian, Polar, Cylindrical, Spherical
' Compile: fbc graph3d.bas
#include "fbgfx.bi"
Using FB
Const SCR_W = 1024
Const SCR_H = 768
Const PI = Atn(1) * 4
Const DEG2RAD = PI / 180
Enum ModeType
MODE_CARTESIAN = 0
MODE_POLAR
MODE_CYLINDRICAL
MODE_SPHERICAL
End Enum
Type Point3D
As Single x, y, z
End Type
Dim Shared As Integer mode = MODE_CARTESIAN
Dim Shared As Integer funcIdx = 0
Dim Shared As Single rotX = 25, rotY = 35
Dim Shared As Single scale = 1.8
Dim Shared As Single camDist = 6.0
Dim Shared As Integer gridN = 40
' ========== Function examples ==========
Function fCartesian(ByVal x As Single, ByVal y As Single) As Single
Select Case funcIdx
Case 0: Return Sin(x) * Cos(y) * 1.5 ' ripples
Case 1: Return (x*x - y*y) * 0.15 ' saddle
Case 2: Return Exp(-(x*x + y*y) * 0.4) * 2 ' gaussian
Case Else: Return Sin(Sqr(x*x + y*y)) * 1.2
End Select
End Function
Function fPolar(ByVal r As Single, ByVal th As Single) As Single
Select Case funcIdx
Case 0: Return Sin(r * 2) * Cos(th * 3) * 0.8
Case 1: Return (1 - r) * Sin(th * 5) * 1.2
Case 2: Return Exp(-r) * Cos(th * 4) * 1.5
Case Else: Return r * Cos(th * 2)
End Select
End Function
Function fCylindrical(ByVal rho As Single, ByVal th As Single) As Single
' Same as polar for z = f(ρ, θ)
Return fPolar(rho, th)
End Function
Function fSpherical(ByVal th As Single, ByVal ph As Single) As Single
' r = f(θ, φ)
Select Case funcIdx
Case 0: Return 1.5 + 0.4 * Sin(th * 4) * Cos(ph * 3)
Case 1: Return 1.2 + 0.6 * Cos(th * 3) * Sin(ph * 2)
Case 2: Return 1.0 + 0.5 * Sin(th) * Cos(ph * 5)
Case Else: Return 1.3 + 0.3 * Cos(2 * th)
End Select
End Function
Function GetModeName() As String
Select Case mode
Case MODE_CARTESIAN: Return "Cartesian z = f(x,y)"
Case MODE_POLAR: Return "Polar z = f(r,θ)"
Case MODE_CYLINDRICAL: Return "Cylindrical z = f(ρ,θ)"
Case MODE_SPHERICAL: Return "Spherical r = f(θ,φ)"
End Select
Return ""
End Function
Function GetFuncName() As String
Select Case mode
Case MODE_CARTESIAN
Select Case funcIdx
Case 0: Return "Sin(x)*Cos(y)"
Case 1: Return "x² - y²"
Case 2: Return "Gaussian"
Case Else: Return "Sin(sqrt(x²+y²))"
End Select
Case MODE_POLAR, MODE_CYLINDRICAL
Select Case funcIdx
Case 0: Return "Sin(2r)*Cos(3θ)"
Case 1: Return "(1-r)*Sin(5θ)"
Case 2: Return "Exp(-r)*Cos(4θ)"
Case Else: Return "r*Cos(2θ)"
End Select
Case MODE_SPHERICAL
Select Case funcIdx
Case 0: Return "1.5 + 0.4*Sin(4θ)*Cos(3φ)"
Case 1: Return "1.2 + 0.6*Cos(3θ)*Sin(2φ)"
Case 2: Return "1.0 + 0.5*Sin(θ)*Cos(5φ)"
Case Else: Return "1.3 + 0.3*Cos(2θ)"
End Select
End Select
Return ""
End Function
' ========== Projection ==========
Sub RotatePoint(ByRef p As Point3D, ByVal ax As Single, ByVal ay As Single)
Dim As Single sx = Sin(ax * DEG2RAD), cx = Cos(ax * DEG2RAD)
Dim As Single sy = Sin(ay * DEG2RAD), cy = Cos(ay * DEG2RAD)
Dim As Single y1 = p.y * cx - p.z * sx
Dim As Single z1 = p.y * sx + p.z * cx
Dim As Single x2 = p.x * cy + z1 * sy
Dim As Single z2 = -p.x * sy + z1 * cy
p.x = x2
p.y = y1
p.z = z2
End Sub
Sub Project(ByRef p As Point3D, ByRef sx As Integer, ByRef sy As Integer)
Dim As Single z = p.z + camDist
If z < 0.1 Then z = 0.1
Dim As Single factor = (SCR_H * 0.45 * scale) / z
sx = SCR_W \ 2 + CInt(p.x * factor)
sy = SCR_H \ 2 - CInt(p.y * factor)
End Sub
' ========== Generate surface points ==========
Sub GenerateSurface(points() As Point3D)
Dim As Integer i, j
Dim As Single u, v, x, y, z, r, th, ph
Select Case mode
Case MODE_CARTESIAN
For i = 0 To gridN
u = -3.0 + 6.0 * i / gridN
For j = 0 To gridN
v = -3.0 + 6.0 * j / gridN
points(i, j).x = u
points(i, j).y = fCartesian(u, v)
points(i, j).z = v
Next
Next
Case MODE_POLAR, MODE_CYLINDRICAL
For i = 0 To gridN
r = 0.05 + 2.8 * i / gridN
For j = 0 To gridN
th = 2 * PI * j / gridN
points(i, j).x = r * Cos(th)
points(i, j).z = r * Sin(th)
points(i, j).y = fPolar(r, th)
Next
Next
Case MODE_SPHERICAL
For i = 0 To gridN
th = 0.01 + (PI - 0.02) * i / gridN ' polar angle
For j = 0 To gridN
ph = 2 * PI * j / gridN ' azimuthal
r = fSpherical(th, ph)
points(i, j).x = r * Sin(th) * Cos(ph)
points(i, j).y = r * Cos(th)
points(i, j).z = r * Sin(th) * Sin(ph)
Next
Next
End Select
End Sub
' ========== Draw ==========
Sub DrawSurface()
Dim As Point3D points(0 To gridN, 0 To gridN)
Dim As Point3D p1, p2
Dim As Integer i, j, sx1, sy1, sx2, sy2
GenerateSurface(points())
ScreenLock
Cls
' Draw grid lines
For i = 0 To gridN
For j = 0 To gridN - 1
' Horizontal
p1 = points(i, j)
p2 = points(i, j + 1)
RotatePoint(p1, rotX, rotY)
RotatePoint(p2, rotX, rotY)
Project(p1, sx1, sy1)
Project(p2, sx2, sy2)
Line (sx1, sy1)-(sx2, sy2), RGB(80, 180, 255)
' Vertical
p1 = points(j, i)
p2 = points(j + 1, i)
RotatePoint(p1, rotX, rotY)
RotatePoint(p2, rotX, rotY)
Project(p1, sx1, sy1)
Project(p2, sx2, sy2)
Line (sx1, sy1)-(sx2, sy2), RGB(100, 220, 180)
Next
Next
' HUD
Draw String (10, 10), "Mode: " & GetModeName(), RGB(255, 255, 100)
Draw String (10, 30), "Func: " & GetFuncName(), RGB(255, 220, 100)
Draw String (10, 60), "Arrows = Rotate +/- = Zoom", RGB(200, 200, 200)
Draw String (10, 80), "M = Mode F = Function ESC = Quit", RGB(200, 200, 200)
Draw String (10, SCR_H - 30), "Grid: " & gridN & " Scale: " & Format(scale, "0.00"), RGB(150, 150, 150)
ScreenUnlock
End Sub
' ========== Main ==========
ScreenRes SCR_W, SCR_H, 32
WindowTitle "FreeBASIC 3D Graph - Cartesian / Polar / Cylindrical / Spherical"
Dim As String key
Dim As Integer mx, my, buttons
Do
DrawSurface()
key = InKey
Select Case key
Case "m", "M"
mode = (mode + 1) Mod 4
funcIdx = 0
Case "f", "F"
funcIdx = (funcIdx + 1) Mod 4
Case "+"
scale *= 1.08
Case "-"
scale /= 1.08
If scale < 0.2 Then scale = 0.2
Case Chr(255) & "H" ' Up
rotX -= 3
Case Chr(255) & "P" ' Down
rotX += 3
Case Chr(255) & "K" ' Left
rotY -= 3
Case Chr(255) & "M" ' Right
rotY += 3
End Select
Sleep 16
Loop Until key = Chr(27)
End