GSOF-3dWireFrame 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. GSOF_3dWireFrame/Example_F16.py +141 -0
  2. GSOF_3dWireFrame/Example_dynamicWorld.py +99 -0
  3. GSOF_3dWireFrame/Example_motionWorld.py +75 -0
  4. GSOF_3dWireFrame/Example_staticWorld.py +112 -0
  5. GSOF_3dWireFrame/F16_Class.py +163 -0
  6. GSOF_3dWireFrame/Lib3D/Assembly.py +72 -0
  7. GSOF_3dWireFrame/Lib3D/Lib3D.py +145 -0
  8. GSOF_3dWireFrame/Lib3D/Object_WireFrame.py +66 -0
  9. GSOF_3dWireFrame/Lib3D/Object_base.py +122 -0
  10. GSOF_3dWireFrame/Lib3D/Objects.py +91 -0
  11. GSOF_3dWireFrame/Lib3D/Utils.py +9 -0
  12. GSOF_3dWireFrame/Lib3D/WireFrame_display.py +37 -0
  13. GSOF_3dWireFrame/Lib3D/__init__.py +7 -0
  14. GSOF_3dWireFrame/Lib3D/stlToObj.py +40 -0
  15. GSOF_3dWireFrame/MathLib/MathLib.py +460 -0
  16. GSOF_3dWireFrame/MathLib/__init__.py +7 -0
  17. GSOF_3dWireFrame/attitudeViewer.py +5 -0
  18. GSOF_3dWireFrame/modules/AttitudeViewer_class.py +115 -0
  19. GSOF_3dWireFrame/modules/Controls.py +60 -0
  20. GSOF_3dWireFrame/modules/__init__.py +7 -0
  21. GSOF_3dWireFrame/objects/Axis.json +40 -0
  22. GSOF_3dWireFrame/objects/F16.stl +0 -0
  23. GSOF_3dWireFrame/objects/LandingGear.json +28 -0
  24. GSOF_3dWireFrame/objects/Plume.json +34 -0
  25. GSOF_3dWireFrame/objects/Spark.json +15 -0
  26. GSOF_3dWireFrame/objects/cube.json +31 -0
  27. GSOF_3dWireFrame/objects/cube_flex.json +31 -0
  28. GSOF_3dWireFrame/objects/frame.json +16 -0
  29. GSOF_3dWireFrame/objects/house.json +50 -0
  30. GSOF_3dWireFrame/objects/net.json +3 -0
  31. GSOF_3dWireFrame/objects/plane.stl +0 -0
  32. GSOF_3dWireFrame/objects/pyramid.json +22 -0
  33. GSOF_3dWireFrame/stlToObject.py +32 -0
  34. gsof_3dwireframe-1.0.0.dist-info/METADATA +48 -0
  35. gsof_3dwireframe-1.0.0.dist-info/RECORD +39 -0
  36. gsof_3dwireframe-1.0.0.dist-info/WHEEL +5 -0
  37. gsof_3dwireframe-1.0.0.dist-info/licenses/AUTHORS +1 -0
  38. gsof_3dwireframe-1.0.0.dist-info/licenses/LICENSE +7 -0
  39. gsof_3dwireframe-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,460 @@
1
+ ## By: Guy Soffer (GSOF) 22/Feb/2024
2
+ __version__ = "1.0.0"
3
+ __author__ = "Guy Soffer"
4
+ __copyright__ = ""
5
+ __credits__ = [""]
6
+ __license__ = ""
7
+ __maintainer__ = ""
8
+ __email__ = "gsoffer@yahoo.com"
9
+ __status__ = "Development"
10
+
11
+ import math, copy
12
+ pi = math.pi
13
+
14
+ def radToDeg(rad) -> float:
15
+ """ Convert radians to degrees """
16
+ return 180*rad/pi # or use this math.degrees(rad)
17
+
18
+ def modulu(val, modulu):
19
+ """ Returns the modulus of val%modulu """
20
+ while val > modulu:
21
+ val -= modulu
22
+ while val < -modulu:
23
+ val += modulu
24
+ return val
25
+
26
+ def clip(val, Min, Max) -> float:
27
+ """ Return the cliped (clamp) result of the input value """
28
+ if val < Min:
29
+ val = Min
30
+ elif val > Max:
31
+ val = Max
32
+ return val
33
+
34
+ def int_V2(v) -> list:
35
+ return int(v[0]), int(v[1])
36
+
37
+ def int_V3(v) -> list:
38
+ return int(v[0]), int(v[1]), int(v[2])
39
+
40
+ def intV(v) -> list:
41
+ out = [0]*len(v)
42
+ for i, elm in enumerate(v):
43
+ out[i] = int(elm)
44
+ return out
45
+
46
+ def scale_V2(v, s) -> list:
47
+ return v[0] * s, v[1] * s
48
+
49
+ def scale_V3(v, s) -> list:
50
+ return v[0] * s, v[1] * s, v[2] * s
51
+
52
+ def negR_V2(R) -> list:
53
+ """ TBR """
54
+ R[0][1] *= -1
55
+ R[1][0] *= -1
56
+ return R
57
+
58
+ def absV_V2(V) -> float:
59
+ """ Return the magnitude of 2D vector """
60
+ return math.sqrt((V[0]**2) +(V[1]**2))
61
+
62
+ def angle_V2(V) -> float:
63
+ """ Return the angle of 2D vector """
64
+ return math.atan2(V[1], V[0])
65
+
66
+ def polar_V2(V) -> float:
67
+ """ Return the polar coordinates of 2D vector """
68
+ return [absV(V), angle_V2(V)]
69
+
70
+ def rotation_V2(rad, V) -> list:
71
+ #sinX = math.sin(rad)
72
+ #cosX = math.cos(rad)
73
+ #DCM = ((cosX, -sinX), (sinX, cosX))
74
+ return MxV_2x2(DCM_V2(rad), V)
75
+
76
+ def absV_V3(V) -> float:
77
+ """ Return the magnitude of 2D vector """
78
+ return math.sqrt((V[0]**2) +(V[1]**2) +(V[2]**2))
79
+
80
+ def angle_V3(v) -> list:
81
+ r = absV_V3(v)
82
+ _absV2 = absV_V2( v[0:2] )
83
+ elevation = pi / 2.0 #< For case 0 and 1
84
+ #elevation = 0.0 #< For case2
85
+ if _absV2 > 0.001:
86
+ elevation = math.arctan( v[2] / _absV2 ) #< Case1 - https://keisan.casio.com/exec/system/1359533867 (Passed targeting test)
87
+ #elevation = -math.arctan2( _absV2, v[2]) +pi/2 #< Case2 - https://keisan.casio.com/exec/system/1359533867
88
+ #elevation = math.arcsin( r / v[2]) #< Case3 - https://www.mechamath.com/trigonometry/cartesian-to-spherical-coordinates-formulas-and-examples/
89
+ azimuth = math.arctan2(v[1], v[0])
90
+ return azimuth, elevation, r
91
+
92
+ def cartesianToPolar_V3(pos):
93
+ return angle_V3(pos)
94
+
95
+ def polarToCartesian_V3(azimuth, elevation, distance):
96
+ abs_xy = distance * math.cos(elevation)
97
+ x = abs_xy * math.cos(azimuth)
98
+ y = abs_xy * math.sin(azimuth)
99
+ z = distance * math.sin(elevation)
100
+ return x, y, z
101
+
102
+ def DCM_V2(rad) -> list:
103
+ """ Return the 2D rotation matrix """
104
+ cosA = math.cos(rad)
105
+ sinA = math.sin(rad)
106
+ return [[cosA,-sinA],[sinA,cosA]]
107
+
108
+ ### https://en.wikipedia.org/wiki/Rotation_matrix
109
+ def DCM_XZY(a, b, c) -> list:
110
+ """ a is around X, b is around Z, and c is around Y"""
111
+ ca = math.cos(a)
112
+ cb = math.cos(b)
113
+ cc = math.cos(c)
114
+
115
+ sa = math.sin(a)
116
+ sb = math.sin(b)
117
+ sc = math.sin(c)
118
+ DCM = [ [ cb*cc, -sb, cb*sc ],
119
+ [sa*sc+ca*cc*sb, ca*cb, ca*sb*sc-cc*sa],
120
+ [cc*sa*sb-ca*sc, cb*sa, ca*sb*sc ]]
121
+ return DCM
122
+
123
+ def get_abc_XZY(dcm) -> list:
124
+ R32 = dcm[2][1]
125
+ R11 = dcm[0][0]
126
+ R12 = dcm[0][1]
127
+ R13 = dcm[0][2]
128
+ R22 = dcm[1][1]
129
+ a = math.atan(R32/R22)
130
+ b = math.asin(-R12)
131
+ c = math.atan(R13/R11)
132
+ return (a,b,c)
133
+
134
+ def DCM_XYZ(a, b, c) -> list:
135
+ """ a is around X, b is around Y, and c is around Z"""
136
+ ca = math.cos(a)
137
+ cb = math.cos(b)
138
+ cc = math.cos(c)
139
+
140
+ sa = math.sin(a)
141
+ sb = math.sin(b)
142
+ sc = math.sin(c)
143
+ DCM = [ [ cb*cc, -cb*sc, sb ],
144
+ [ca*sc+sa*sb*cc, ca*cc-sa*sb*sc, -sa*cb],
145
+ [sa*sc-ca*sb*cc, sa*cc+ca*sb*sc, ca*cb]]
146
+ return DCM
147
+
148
+ def get_abc_XYZ(dcm) -> list:
149
+ R11 = dcm[0][0]
150
+ R12 = dcm[0][1]
151
+ R13 = dcm[0][2]
152
+ R23 = dcm[1][2]
153
+ R33 = dcm[2][2]
154
+ a = math.atan(-R23/R33)
155
+ b = math.asin(R13)
156
+ c = math.atan(-R12/R11)
157
+ return (a,b,c)
158
+
159
+ def DCM_YXZ(a, b, c) -> list:
160
+ """ a is around Y, b is around X, and c is around Z"""
161
+ ca = math.cos(a)
162
+ cb = math.cos(b)
163
+ cc = math.cos(c)
164
+
165
+ sa = math.sin(a)
166
+ sb = math.sin(b)
167
+ sc = math.sin(c)
168
+ DCM = [ [ca*cc+sa*sb*sc, cc*sa*sb-ca*sc, cb*sa],
169
+ [ cb*sc , cb*cc, -sb],
170
+ [ca*sb*sc-cc*sa, ca*cc*sb+sa*sc, ca*cb]]
171
+ return DCM
172
+
173
+ def get_abc_YXZ(dcm) -> list:
174
+ R13 = dcm[0][2]
175
+ R21 = dcm[1][0]
176
+ R22 = dcm[1][1]
177
+ R23 = dcm[1][2]
178
+ R33 = dcm[2][2]
179
+ a = math.atan(R13/R33)
180
+ b = math.asin(-R23)
181
+ c = math.atan(R21/R22)
182
+ return (a,b,c)
183
+
184
+
185
+ def DCM_YZX(a, b, c) -> list:
186
+ """ a is around Y, b is around Z, and c is around X"""
187
+ ca = math.cos(a)
188
+ cb = math.cos(b)
189
+ cc = math.cos(c)
190
+
191
+ sa = math.sin(a)
192
+ sb = math.sin(b)
193
+ sc = math.sin(c)
194
+ DCM = [ [ca*cb , sa*sc-ca*cc*sb, cc*sa+ca*sb*sc],
195
+ [ sb , cb*cc, -cb*sc ],
196
+ [-cb*sa , ca*sc+cc*sa*sb, ca*cc-sa*sb*sc]]
197
+ return DCM
198
+
199
+ def get_abc_YZX(dcm) -> list:
200
+ R31 = dcm[2][0]
201
+ R11 = dcm[0][0]
202
+ R21 = dcm[1][0]
203
+ R22 = dcm[1][1]
204
+ R23 = dcm[1][2]
205
+ a = math.atan(-R31/R11)
206
+ b = math.asin(R21)
207
+ c = math.atan(-R23/R22)
208
+ return (a,b,c)
209
+
210
+ def DCM_ZYX(a, b, c) -> list:
211
+ """ a is around Z, b is around Y, and c is around X"""
212
+ ca = math.cos(a)
213
+ cb = math.cos(b)
214
+ cc = math.cos(c)
215
+
216
+ p = pi/2
217
+ sa = math.cos(a -p) #<math.sin(a)
218
+ sb = math.cos(b -p) #<math.sin(b)
219
+ sc = math.cos(c -p) #<math.sin(c)
220
+
221
+ DCM = [ [ca*cb, ca*sb*sc-cc*sa, sa*sc+ca*sb*cc],
222
+ [sa*cb, sa*sb*sc+ca*cc, cc*sa*sb-ca*sc],
223
+ [ -sb, cb*sc, cb*cc ]]
224
+ return DCM
225
+
226
+ def get_abc_ZYX(dcm) -> list:
227
+ R11 = dcm[0][0]
228
+ R21 = dcm[1][0]
229
+ R31 = dcm[2][0]
230
+ R32 = dcm[2][1]
231
+ R33 = dcm[2][2]
232
+ a = math.atan(R21/R11)
233
+ b = math.asin(-R31)
234
+ c = math.atan(R32/R33)
235
+ return (a,b,c)
236
+
237
+ def DCM_ZXY(a, b, c) -> list:
238
+ """ a is around Z, b is around X, and c is around Y"""
239
+ ca = math.cos(a)
240
+ cb = math.cos(b)
241
+ cc = math.cos(c)
242
+
243
+ p = pi/2
244
+ sa = math.cos(a -p) #<math.sin(a)
245
+ sb = math.cos(b -p) #<math.sin(b)
246
+ sc = math.cos(c -p) #<math.sin(c)
247
+
248
+ DCM = [ [ca*cb, ca*sb*sc-cc*sa, sa*sc+ca*sb*cc],
249
+ [sa*cb, sa*sb*sc+ca*cc, cc*sa*sb-ca*sc],
250
+ [ -sb, cb*sc, cb*cc ]]
251
+ return DCM
252
+
253
+ def get_abc_ZXY(dcm) -> list:
254
+ R12 = dcm[0][1]
255
+ R22 = dcm[1][1]
256
+ R31 = dcm[2][0]
257
+ R32 = dcm[2][1]
258
+ R33 = dcm[2][2]
259
+ a = math.atan(-R12/R22)
260
+ b = math.asin(R32)
261
+ c = math.atan(-R31/R33)
262
+ return (a,b,c)
263
+
264
+ def MxV_2x2(M,V) -> list:
265
+ """ Return the result of 2x2 matrix and 2D vector multiplication """
266
+ O = [0,0]
267
+ O[0] = M[0][0]*V[0] +(M[0][1]*V[1])
268
+ O[1] = M[1][0]*V[0] +(M[1][1]*V[1])
269
+ return O
270
+
271
+ def MxV(M,V) -> list:
272
+ """ Return the result of NxM matrix and V vector multiplication """
273
+ N = len(M)
274
+ O = [0]*N
275
+ for r,row in enumerate(M):
276
+ for m,v in zip(row,V):
277
+ O[r] += m*v
278
+ return O
279
+
280
+ def getCol(M, col) -> list:
281
+ """ Returns a copy of column 'col' from the matrix 'M' """
282
+ rows = len(M)
283
+ V = [0]*rows
284
+ for i, row in enumerate(M):
285
+ V[i] = row[col]
286
+ return V
287
+
288
+ def getRow(M, row) -> list:
289
+ """ Returns a copy of row 'row' from the matrix 'M' """
290
+ return copy.copy(M[row])
291
+
292
+ def MUL_3x3(M, V):
293
+ return [ M[0][0]*V[0] +M[0][1]*V[1] +M[0][2]*V[2],
294
+ M[1][0]*V[0] +M[1][1]*V[1] +M[1][2]*V[2],
295
+ M[2][0]*V[0] +M[2][1]*V[1] +M[2][2]*V[2] ]
296
+
297
+ def MUL_4x4(M, V):
298
+ return [ M[0][0]*V[0] +M[0][1]*V[1] +M[0][2]*V[2] +M[0][3]*V[3],
299
+ M[1][0]*V[0] +M[1][1]*V[1] +M[1][2]*V[2] +M[1][3]*V[3],
300
+ M[2][0]*V[0] +M[2][1]*V[1] +M[2][2]*V[2] +M[2][3]*V[3],
301
+ M[3][0]*V[0] +M[3][1]*V[1] +M[3][2]*V[2] +M[3][3]*V[3] ]
302
+
303
+ def MxM(M1, M2) -> list:
304
+ """ Return the result two matrix multiplication """
305
+ rows = len(M2) #< If vector instead of matrix make a matrix
306
+ try:
307
+ colsM2 = len(M2[0])
308
+ except:
309
+ M2 = [M2]
310
+ rows = 1
311
+
312
+ try: #< If vector instead of matrix make a matrix
313
+ cols = len(M1[0])
314
+ except:
315
+ cols = len(M1)
316
+ M1 = [M1]
317
+
318
+ rows = len(M1) #< Rows in M1
319
+ cols = len(M2[0]) #< Columns in M2
320
+ O = zeros(rows, cols) #< The output
321
+ for r in range(0,rows):
322
+ row = getRow(M1, r)
323
+ for c in range(0, cols):
324
+ col = getCol(M2, c) #< col is a row vector
325
+ O[r][c] = VxV(row[0:len(col)], col)
326
+ return O
327
+
328
+ def add_V2(V1, V2) -> list:
329
+ """ Return the result of 2D vector addition """
330
+ return [V1[0]+V2[0], V1[1]+V2[1]]
331
+
332
+ #def addV(V1, V2) -> list:
333
+ # out = [0]*len(V1)
334
+ # for i, elm1, elm2 in enumerate(zip(V1,V2)):
335
+ # out[i] = elm1+elm2
336
+ # return out
337
+
338
+ def addV(V1, V2) -> list:
339
+ """ Return the result of vector addition """
340
+ O = [0]*len(V1)
341
+ i = 0
342
+ for v1,v2 in zip(V1, V2):
343
+ O[i] = v1+v2
344
+ i += 1
345
+ return O
346
+
347
+ def absV(V) -> float:
348
+ """ Return the magnitude of vector """
349
+ s2 = 0
350
+ for v in V:
351
+ s2 += v**2
352
+ return math.sqrt(s2)
353
+
354
+ def scaleV(V, s) -> list:
355
+ """ Return the scaled vector 'V' by the scaler 's' """
356
+ O = [0]*len(V)
357
+ for i, e in enumerate(V):
358
+ O[i] = e*s
359
+ return O
360
+
361
+ def VxV(V1, V2) -> float:
362
+ """ Returns the result of two vector multiplacation """
363
+ Sum = 0
364
+ for e1, e2 in zip(V1, V2):
365
+ Sum += e1*e2
366
+ return Sum
367
+
368
+ def matrix(rows, cols, val=0) -> list:
369
+ """ Returns the rows by cols matrix M filled with value val """
370
+ M = [0]*rows
371
+ for row in range(0,rows):
372
+ M[row] = [val]*cols
373
+ return M
374
+
375
+ def zeros(rows, cols) -> list:
376
+ """ Returns the rows by cols zero matrix Z """
377
+ return matrix(rows, cols, val=0)
378
+
379
+ def ones(rows, cols) -> list:
380
+ """ Returns the rows by cols zero matrix Z """
381
+ return matrix(rows, cols, val=1)
382
+
383
+ def I(size) -> list:
384
+ """ Returns the size by size identity matrix I """
385
+ I = [0]*size
386
+ for row in range(0,size):
387
+ I[row] = [0]*size
388
+ I[row][row] = 1
389
+ return I
390
+
391
+ def T(M) -> list:
392
+ """ Returns the transposed Matrix of M """
393
+ rows = len(M)
394
+ try:
395
+ cols = len(M[0])
396
+ except:
397
+ cols = rows
398
+ rows = 1
399
+ M = [M]
400
+ O = [0]*cols
401
+ for i in range(0,cols):
402
+ O[i] = getCol(M,i)
403
+ return O
404
+
405
+ def invM(M) -> list:
406
+ """ Not ready yet, Returns the inverse of the matrix M (Using Naive Gauss elimination method) """
407
+ rows = len(M)
408
+ cols = rows
409
+ O = [0]*rows
410
+ O[0] = copy.copy(M[0]) #scaleV(M[0], 1)
411
+ for col in range(0, cols-1):
412
+ stRow = col
413
+ refRow = M[stRow]
414
+ for i in range(stRow +1, rows):
415
+ row = M[i]
416
+ tmpRow1 = scaleV(refRow, -row[col])
417
+ tmpRow2 = scaleV(row, refRow[col])
418
+ O[i] = addV(tmpRow2, tmpRow1)
419
+ M = copy.copy(O)
420
+ return O
421
+
422
+ def LU(M) -> list:
423
+ """ Not ready yet, Returns the lower and upper (LU) matrixes that forms the matrix M """
424
+ rows = len(M)
425
+ cols = rows
426
+ L = I(rows)
427
+ U = [0]*rows
428
+ U[0] = copy.copy(M[0]) #scaleV(M[0], 1)
429
+ for col in range(0, cols-1):
430
+ stRow = col
431
+ refRow = M[stRow]
432
+ for i in range(stRow +1, rows):
433
+ row = M[i]
434
+ tmpRow1 = scaleV(refRow, -row[col])
435
+ tmpRow2 = scaleV(row, refRow[col])
436
+ L[i][col] = refRow[col]/row[col]
437
+ U[i] = addV(tmpRow2, tmpRow1)
438
+ M = copy.copy(U)
439
+ return (L, U)
440
+
441
+ def copyIntoMatrix(M, S, rs=0, cs=0, rn=3, cn=3) -> list:
442
+ for ri in range(0,rn):
443
+ row = S[ri]
444
+ for ci in range(0, cn):
445
+ M[rs+ri][cs+ci] = row[ci]
446
+ return M
447
+
448
+ if __name__ == "__main__":
449
+ # M = [[1,2,3,4],
450
+ # [4,5,60,7],
451
+ # [7,8,9,11],
452
+ # [17,18,19,10],
453
+ # ]
454
+ M = [[1,2,3],
455
+ [4,5,6],
456
+ [7,8,11],
457
+ ]
458
+
459
+ #o = invM(M)
460
+ l,u = LU(M)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env python
2
+
3
+ # this is a wrapper module for different platform implementations
4
+ #
5
+ # (C) 2019 Guy Soffer <gsoffer@yahoo.com>
6
+
7
+ VERSION = '101'
@@ -0,0 +1,5 @@
1
+ from modules.AttitudeViewer_class import AttitudeViewer
2
+
3
+ if __name__ == "__main__":
4
+ attitude = AttitudeViewer()
5
+ attitude.start()
@@ -0,0 +1,115 @@
1
+ import pygame, math, json
2
+ from Lib3D import Object_WireFrame as OWF
3
+ from Lib3D import Object_base as OB
4
+ from Lib3D import WireFrame_display as DISP
5
+ from Lib3D import Objects
6
+ from modules import Controls
7
+
8
+ SCREEN_WIDTH = 800
9
+ SCREEN_HEIGHT = 600
10
+ WHITE = (255,255,255)
11
+ BLACK = (0,0,0)
12
+ PI = math.pi
13
+
14
+ def newScreen(title="New", resX=SCREEN_WIDTH, resY=SCREEN_HEIGHT, color=WHITE):
15
+ screen = pygame.display.set_mode( (resX, resY) )
16
+ screen.fill(color)
17
+ pygame.display.set_caption(title)
18
+ return screen
19
+
20
+ class AttitudeViewer():
21
+ def __init__(self):
22
+ net = OWF.Object_wireFrame(obj=Objects.net(25,25), color=(0,100,0)).rotate(x=PI/2, y=0, z=0).translate(V=(0, 0, 0), initShape=True).scale(0.2, initShape=True)
23
+ axis = OWF.Object_wireFrame(filename="./objects/axis.json", color=(10,10,10)).translate(V=(0, 0, 0), initShape=True).scale(5.0, initShape=True)
24
+ self.f16 = OWF.Object_wireFrame(filename="./objects/F16.stl", color=(0,0,255)).translate(V=(0, 0, 0), initShape=True)
25
+ self.f16.setOrigin( origin=self.f16.getOrigin(origin="arithCenter"), initShape=True ).scale(0.02, initShape=True)
26
+ # f16.translate(V=(0, 0, 200), initShape=True)
27
+ # f16.rotate(x=0, y=PI/2, z=PI, origin="arithCenter", initShape=True)
28
+ # f16.translate(V=(-50, -50, 0), initShape=True)
29
+
30
+ self.world = OB.Object_container(objList = (
31
+ axis,
32
+ net,
33
+ self.f16,
34
+ ))
35
+
36
+ pygame.init()
37
+ self.clock = pygame.time.Clock()
38
+ self.screen = newScreen("3D Wire Frame - Attitude Viewer", SCREEN_WIDTH, SCREEN_HEIGHT, WHITE)
39
+ self.wireframe = DISP.WireFrame(self.screen, pygame.draw.line, f=50, scale=10)
40
+ self.viewer = Controls.Viewer( pos=(0,0,-1200),
41
+ center=(int(self.screen.get_width()/2),int(self.screen.get_height()/2)),
42
+ moveLeftKey = pygame.K_a,
43
+ moveRightKey = pygame.K_d,
44
+ moveUpKey = pygame.K_UP,
45
+ moveDownKey = pygame.K_DOWN,
46
+ moveFwdKey = pygame.K_w,
47
+ moveBackKey = pygame.K_x,
48
+ tiltLeft = pygame.K_COMMA,
49
+ tiltRight = pygame.K_PERIOD
50
+ )
51
+ self.uut = Controls.Object( pos=(200,200,200),
52
+ center=(int(self.screen.get_width()/2), int(self.screen.get_height()/2)),
53
+ moveLeftKey = pygame.K_a,
54
+ moveRightKey = pygame.K_d,
55
+ moveUpKey = pygame.K_UP,
56
+ moveDownKey = pygame.K_DOWN,
57
+ moveFwdKey = pygame.K_w,
58
+ moveBackKey = pygame.K_x,
59
+ tiltLeft = pygame.K_COMMA,
60
+ tiltRight = pygame.K_PERIOD
61
+ )
62
+
63
+ self.fps = 30
64
+ self.dt = 1/self.fps
65
+ self.t = 0.0
66
+ self.objects = [self.viewer, self.uut]
67
+ self.objSel = 0
68
+ self.run = False
69
+
70
+ def _clearScreen(self, color=(255,255,255)) -> None:
71
+ self.screen.fill(color)
72
+
73
+ def start(self):
74
+ self.run = True
75
+ while self.run:
76
+ ### Get inputs
77
+ for event in pygame.event.get():
78
+ if event.type == pygame.QUIT:
79
+ self.run = False
80
+
81
+ keys = pygame.key.get_pressed()
82
+ (mPosX, mPosY) = pygame.mouse.get_pos()
83
+ if keys[pygame.K_v]:
84
+ self.objSel = 0
85
+ elif keys[pygame.K_u]:
86
+ self.objSel = 1
87
+
88
+ self.objects[self.objSel].update(keys, mPosX, mPosY, speed=2)
89
+
90
+ self.wireframe.f += -(keys[pygame.K_1] - keys[pygame.K_2])*10
91
+
92
+ ### Calculate next step state
93
+ # t += dt
94
+
95
+ ### Update 3D world
96
+ self.world.reset()
97
+ self.f16.rotate( *self.uut.getAttitude() ).translate( V=self.uut.getPosition() )
98
+ self.world.translate( V=self.viewer.getPosition() ).rotate( *self.viewer.getAttitude() )
99
+
100
+ ### Draw 3D world
101
+ self._clearScreen(WHITE)
102
+ self.wireframe.draw(self.world)
103
+
104
+ ### Wait for next step time
105
+ self.clock.tick(30)
106
+
107
+ ### Display output
108
+ pygame.display.flip()
109
+
110
+ pygame.quit()
111
+
112
+ if __name__ == "__main__":
113
+ attitude = AttitudeViewer()
114
+ attitude.start()
115
+
@@ -0,0 +1,60 @@
1
+ import math
2
+
3
+ class Viewer():
4
+ def __init__(self, pos=(0,0,0), att=(0,0,0), center=(0,0),
5
+ moveLeftKey=0, moveRightKey=0,
6
+ moveUpKey=0, moveDownKey=0,
7
+ moveFwdKey=0, moveBackKey=0,
8
+ tiltLeft=0, tiltRight=0):
9
+ self.posX = pos[0]
10
+ self.posY = pos[1]
11
+ self.posZ = pos[2]
12
+ self.attX = att[0]
13
+ self.attY = att[1]
14
+ self.attZ = att[2]
15
+ self.centerX = center[0]
16
+ self.centerY = center[1]
17
+ self.moveLeftKey = moveLeftKey
18
+ self.moveRightKey = moveRightKey
19
+ self.moveUpKey = moveUpKey
20
+ self.moveDownKey = moveDownKey
21
+ self.moveFwdKey = moveFwdKey
22
+ self.moveBackKey = moveBackKey
23
+ self.tiltLeft = tiltLeft
24
+ self.tiltRight = tiltRight
25
+
26
+ def update(self, keys, mPosX, mPosY, speed=2) -> list:
27
+ pos = self.updatePos(keys, mPosX, mPosY, speed)
28
+ att = self.updateAtt(keys, mPosX, mPosY, speed)
29
+ return (pos, att)
30
+
31
+ def getPosition(self):
32
+ return (self.posX, self.posY, self.posZ)
33
+
34
+ def getAttitude(self):
35
+ return (self.attX, self.attY, self.attZ)
36
+
37
+ def updateAtt(self, keys, mPosX, mPosY, speed) -> list:
38
+ self.attY = 0.5*math.pi*(mPosX/self.centerX -1)
39
+ self.attX = 0.5*math.pi*(mPosY/self.centerY -1)
40
+ return self.getAttitude()
41
+
42
+ def updatePos(self, keys, mPosX, mPosY, speed) -> list:
43
+ self.posX += -(keys[self.moveRightKey] -keys[self.moveLeftKey])*2.0*speed
44
+ self.posY += -(keys[self.moveUpKey] -keys[self.moveDownKey])*2.0*speed
45
+ self.posZ += -(keys[self.moveBackKey] -keys[self.moveFwdKey])*5.0*speed
46
+ return self.getPosition()
47
+
48
+ class Object(Viewer):
49
+ def updateAtt(self, keys, mPosX, mPosY, speed) -> list:
50
+ self.attY = 0.5*math.pi*(mPosX/self.centerX -1)
51
+ self.attX = 0.5*math.pi*(mPosY/self.centerY -1)
52
+ speed = 3*math.pi/180 #< 3 deg
53
+ self.attZ += (keys[self.tiltRight] -keys[self.tiltLeft])*speed
54
+ return self.getAttitude()
55
+
56
+ def updatePos(self, keys, mPosX, mPosY, speed) -> list:
57
+ self.posX += -(keys[self.moveRightKey] -keys[self.moveLeftKey])*2.0*speed
58
+ self.posY += -(keys[self.moveUpKey] -keys[self.moveDownKey])*2.0*speed
59
+ self.posZ += -(keys[self.moveFwdKey] -keys[self.moveBackKey])*5.0*speed
60
+ return self.getPosition()
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env python
2
+
3
+ # this is a wrapper module for different platform implementations
4
+ #
5
+ # (C) 2019 Guy Soffer <gsoffer@yahoo.com>
6
+
7
+ VERSION = '101'
@@ -0,0 +1,40 @@
1
+ {"scale":100.0,
2
+ "color":[10,10,10],
3
+ "points_xyz":[
4
+ [0, 0, 0],
5
+ [1, 0, 0],
6
+ [0, 1, 0],
7
+ [0, 0, 1],
8
+
9
+ [1.05, 0.1, 0.0],
10
+ [1.25, -0.1, 0.0],
11
+ [1.25, 0.1, 0.0],
12
+ [1.05, -0.1, 0.0],
13
+
14
+ [-0.1, 1.15, 0.0],
15
+ [ 0.0, 1.05, 0.0],
16
+ [ 0.1, 1.15, 0.0],
17
+ [-0.1, 0.95, 0.0],
18
+
19
+ [-0.1, 0.1, 1.05],
20
+ [ 0.1, 0.1, 1.05],
21
+ [-0.1, -0.1, 1.05],
22
+ [ 0.1, -0.1, 1.05]
23
+ ],
24
+
25
+ "connections":[
26
+ [0,1],
27
+ [0,2],
28
+ [0,3],
29
+
30
+ [4,5],
31
+ [6,7],
32
+
33
+ [8,9],
34
+ [10,11],
35
+
36
+ [12,13],
37
+ [13,14],
38
+ [14,15]
39
+ ]
40
+ }
Binary file