-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtelescope.py
129 lines (94 loc) · 4.7 KB
/
telescope.py
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
import numscrypt as ns
class Telescope:
def __init__ (self):
'''Initialize constants
'''
dirVec0Plane = ns.array ((1, 0, 0))
dirVec1Plane = ns.array ((0, 1, 0))
def zoom (self, zoomFactor = 40):
''' Zoom by shifting image plane
'''
self.zoomFactor = zoomFactor
self.zoomShift = 40 / zoomFactor
self.supVecPlane = ns.array ((0, 0, -zoomShift / 6))
def project (self, celestialBodyVec, rField, rScreen):
'''Project a celestial body onto the screen
y * celestial body
| *
\ | *
* \|
eye * z - - - + - - -
(origin) |\
| \
| x
image plane
Let vs be the vector from the origin to the celestial body.
Let vl be any vector that ends on the line through the origin and the celestial body.
Then vl = a vs
Let vp be any vector that ends on the image plane
Let d the distance from the origin to the center of the image plane
Let ux, uy and uz be the unitvectors in directions x, y and z respectively
Then vp = b ux + c uy - d uz
The star is shown on the image plane at the intersection with the line between eye and star.
At his intersection:
a vs = b ux + c uy - d uz ==>
d uz = a vs - b ux + - uy ==>
(vsx) (-1) ( 0)
d uz = a (vsy) + b ( 0) + c (-1)
(vsz) ( 0) ( 0)
(vsx, -1, 0) (a)
d uz = (vsy, 0, -1) (b) ==>
(vsz, 0, 0) (c)
(a) (vsx, -1, 0)
d uz = D (b) with direction matrix D = (vsy, 0, -1) ==>
(c) (vsz, 0, 0)
(a) -1
(b) = D d uz
(c)
The screen coordinates of the projected star are (a, b)
'''
# Bail out if object in front of image plane
if projectableVec3D [2] < supVecPlane [2]:
return None
# Compute inverse of direction matrix D
invDirMat = (dirVecLine * ns.array ((1, 0, 0)) .T + dirVec0Plane * ns.array ((-1, 0, 0)) .T + dirVec1Plane * ns.array ((0, -1, 0)) .T) .I
# Compute projected 3D vector
projectedCelestialBodyVec = invDirMat @ projectableVec
# rField in pixels / rScreen in m will map object with size of rScreen m exactly to rField pixels
projectedVec2D = (
(rField / (rScreen / 6d)) * projectedVec3D [1],
(rField / (rScreen / 6d)) * projectedVec3D [2]
)
return true
boolean map (double [] mappedVec2D, double [] mappableVec3D, double rField, double rScreen) {
double [] rotAngVec = new double [] {Math.PI / 180d * tilt, Math.PI/180d * course, 0d};
double s, c;
s = Math.sin (rotAngVec [1]);
c = Math.cos (rotAngVec [1]);
double rotZCourseMat [][] = new double [][] {
{ c, -s, 0d},
{ s, c, 0d},
{0d, 0d, 1d}
};
s = Math.sin (rotAngVec [0]);
c = Math.cos (rotAngVec [0]);
double rotYTiltMat [][] = new double [][] {
{ c, 0d, s},
{0d, 1d, 0d},
{-s, 0d, c}
};
double rotationMat [][] = new double [3][3];
double [] zoomedVec3D = new double [3];
double [] rotatedVec = new double [3];
LinAlg.mul (rotationMat, rotYTiltMat, rotZCourseMat);
LinAlg.mul (zoomedVec3D, zoomFactor / 30d, mappableVec3D);
LinAlg.mul (rotatedVec, rotationMat, zoomedVec3D);
return project (mappedVec2D, rotatedVec, rField, rScreen);
}
boolean mapEyepiece (EyepieceImage eyepieceImage, Eyepiece eyepiece, double rField, double focLenObjective) {
double magnif = focLenObjective / eyepiece.focLen;
double angleUniverse = eyepiece.angle / magnif;
eyepieceImage.rOnField = zoomFactor * rField * Math.sin ((Math.PI / 180d) * (angleUniverse / 2d));
return eyepieceImage.rOnField < rField;
}
}