CTPv 0.1.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.
- CTPv/Camera/Intrinsics.py +205 -0
- CTPv/Camera/__init__.py +0 -0
- CTPv/Plucker/Line.py +526 -0
- CTPv/Plucker/__init__.py +0 -0
- CTPv/Transformation/TransformationMatrix.py +381 -0
- CTPv/Transformation/__init__.py +0 -0
- CTPv/__init__.py +0 -0
- ctpv-0.1.0.dist-info/METADATA +474 -0
- ctpv-0.1.0.dist-info/RECORD +12 -0
- ctpv-0.1.0.dist-info/WHEEL +5 -0
- ctpv-0.1.0.dist-info/licenses/LICENSE +7 -0
- ctpv-0.1.0.dist-info/top_level.txt +1 -0
CTPv/Plucker/Line.py
ADDED
@@ -0,0 +1,526 @@
|
|
1
|
+
import matplotlib.pyplot as plt
|
2
|
+
import numpy as np
|
3
|
+
|
4
|
+
def intersection_between_2_lines(L1, L2):
|
5
|
+
"""
|
6
|
+
Compute the intersection point and distance between two lines in 3D space.
|
7
|
+
|
8
|
+
Parameters:
|
9
|
+
L1, L2 : Line objects
|
10
|
+
Line objects containing start points and direction vectors.
|
11
|
+
|
12
|
+
Returns:
|
13
|
+
Point : numpy array of shape (3,)
|
14
|
+
The midpoint of the closest points on the two lines.
|
15
|
+
distance : float
|
16
|
+
The shortest distance between the two lines.
|
17
|
+
"""
|
18
|
+
p1, u = L1.Ps, L1.V
|
19
|
+
p3, v = L2.Ps, L2.V
|
20
|
+
w = (p1 + u) - (p3 + v)
|
21
|
+
b = np.sum(u * v, axis=1)
|
22
|
+
d = np.sum(u * w, axis=1)
|
23
|
+
e = np.sum(v * w, axis=1)
|
24
|
+
D = 1 - b ** 2
|
25
|
+
|
26
|
+
# Avoid division by zero for parallel lines
|
27
|
+
D[D == 0] = np.finfo(float).eps
|
28
|
+
|
29
|
+
sc = (b * e - d) / D
|
30
|
+
tc = (e - b * d) / D
|
31
|
+
|
32
|
+
point1 = p1 + u + (sc[:, np.newaxis] * u)
|
33
|
+
point2 = p3 + v + (tc[:, np.newaxis] * v)
|
34
|
+
|
35
|
+
Points = (point1 + point2) / 2
|
36
|
+
|
37
|
+
dP = w + (sc[:, np.newaxis] * u) - (tc[:, np.newaxis] * v)
|
38
|
+
distances = np.linalg.norm(dP, axis=1)
|
39
|
+
|
40
|
+
return Points, distances
|
41
|
+
|
42
|
+
class Line:
|
43
|
+
kind = 'Line' # class variable shared by all instances
|
44
|
+
|
45
|
+
def __init__(self, *args):
|
46
|
+
"""
|
47
|
+
Initialize a Line object.
|
48
|
+
|
49
|
+
Parameters:
|
50
|
+
*args : variable length argument list
|
51
|
+
If no arguments are provided, Ps and Pe are set to None.
|
52
|
+
If one argument is provided, it is assumed to be the Plucker coordinates.
|
53
|
+
If two arguments are provided, they are assumed to be the start and end points.
|
54
|
+
"""
|
55
|
+
if len(args) == 0:
|
56
|
+
self.Ps = None
|
57
|
+
self.Pe = None
|
58
|
+
elif len(args) == 1:
|
59
|
+
self.Plucker = args[0]
|
60
|
+
elif len(args) == 2:
|
61
|
+
self.Ps = args[0]
|
62
|
+
self.Pe = args[1]
|
63
|
+
else:
|
64
|
+
raise ValueError("Invalid number of arguments!")
|
65
|
+
|
66
|
+
@property
|
67
|
+
def V(self):
|
68
|
+
"""
|
69
|
+
Get the direction vector of the line.
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
numpy array of shape (3,)
|
73
|
+
The direction vector from Ps to Pe.
|
74
|
+
"""
|
75
|
+
if self.Ps is not None and self.Pe is not None:
|
76
|
+
return self._normalize_vectors(self.Pe - self.Ps)
|
77
|
+
return None
|
78
|
+
|
79
|
+
@V.setter
|
80
|
+
def V(self, value):
|
81
|
+
"""
|
82
|
+
Set the direction vector of the line.
|
83
|
+
|
84
|
+
Parameters:
|
85
|
+
value : numpy array of shape (3,)
|
86
|
+
The new direction vector.
|
87
|
+
"""
|
88
|
+
if self.Ps is not None:
|
89
|
+
self.Pe = value + self.Ps
|
90
|
+
|
91
|
+
@property
|
92
|
+
def Plucker(self):
|
93
|
+
"""
|
94
|
+
Get the Plucker coordinates of the line.
|
95
|
+
|
96
|
+
Returns:
|
97
|
+
numpy array of shape (6,)
|
98
|
+
The Plucker coordinates [V, U] where V is the direction vector and U is the moment vector.
|
99
|
+
"""
|
100
|
+
V = self.V
|
101
|
+
U = np.cross(self.Ps, self.Ps + V)
|
102
|
+
return np.hstack((V, U))
|
103
|
+
|
104
|
+
@Plucker.setter
|
105
|
+
def Plucker(self, value):
|
106
|
+
"""
|
107
|
+
Set the Plucker coordinates of the line.
|
108
|
+
|
109
|
+
Parameters:
|
110
|
+
value : numpy array of shape (6,)
|
111
|
+
The Plucker coordinates [V, U] where V is the direction vector and U is the moment vector.
|
112
|
+
"""
|
113
|
+
Vp = value[:, :3]
|
114
|
+
Up = value[:, 3:]
|
115
|
+
self.Ps = np.cross(Vp, Up)
|
116
|
+
self.V = Vp
|
117
|
+
|
118
|
+
@property
|
119
|
+
def Plucker2(self):
|
120
|
+
"""
|
121
|
+
Get not normalised representation of the Plucker coordinates of the line.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
numpy array of shape (6,)
|
125
|
+
The not normalised Plucker coordinates [m, b] where m is the moment vector and b is the direction vector.
|
126
|
+
"""
|
127
|
+
m = np.cross(self.Ps, self.Pe)
|
128
|
+
return np.hstack((m, self.Pe - self.Ps))
|
129
|
+
|
130
|
+
@Plucker2.setter
|
131
|
+
def Plucker2(self, value):
|
132
|
+
"""
|
133
|
+
Set the not normalised Plucker coordinates of the line.
|
134
|
+
|
135
|
+
Parameters:
|
136
|
+
value : numpy array of shape (6,)
|
137
|
+
The not normalised Plucker coordinates [m, b] where m is the moment vector and b is the direction vector.
|
138
|
+
"""
|
139
|
+
a = value[:, :3]
|
140
|
+
b = value[:, 3:]
|
141
|
+
self.Ps = np.column_stack((-a[:, 1] / b[:, 2], a[:, 0] / b[:, 2], np.zeros(a.shape[0])))
|
142
|
+
self.V = b
|
143
|
+
|
144
|
+
def GetAngle(self):
|
145
|
+
"""
|
146
|
+
Compute the angle between the line and the z-axis.
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
numpy array of shape (n, 1)
|
150
|
+
The angles in degrees between the line and the z-axis for each start point.
|
151
|
+
"""
|
152
|
+
v = np.array([0, 0, 1])
|
153
|
+
ThetaInDegrees = np.zeros((self.Ps.shape[0], 1))
|
154
|
+
for i in range(self.Ps.shape[0]):
|
155
|
+
ThetaInDegrees[i, 0] = np.degrees(np.arctan2(np.linalg.norm(np.cross(self.V[i, :], v)), np.dot(self.V[i, :], v)))
|
156
|
+
return ThetaInDegrees
|
157
|
+
|
158
|
+
def TransformLines(self, H):
|
159
|
+
"""
|
160
|
+
Transform the line using a homogeneous transformation matrix.
|
161
|
+
|
162
|
+
Parameters:
|
163
|
+
H : Homogeneous transformation matrix
|
164
|
+
The transformation matrix to apply to the line.
|
165
|
+
"""
|
166
|
+
self.Ps = H.transform(self.Ps)
|
167
|
+
self.Pe = H.transform(self.Pe)
|
168
|
+
|
169
|
+
def plot(self, limits=None, colors=None, linewidth=2, linestyle='-'):
|
170
|
+
"""
|
171
|
+
Plot the lines in 3D space.
|
172
|
+
|
173
|
+
Parameters:
|
174
|
+
limits : list of floats, optional
|
175
|
+
The limits of the plot in the format [xmin, xmax, ymin, ymax, zmin, zmax].
|
176
|
+
colors : numpy array, optional
|
177
|
+
The colors to use for the lines.
|
178
|
+
linewidth : float, optional
|
179
|
+
The width of the lines.
|
180
|
+
linestyle : str, optional
|
181
|
+
The style of the lines.
|
182
|
+
"""
|
183
|
+
if limits is None:
|
184
|
+
limits = [-5, 5, -5, 5, -5, 5]
|
185
|
+
if colors is None:
|
186
|
+
colors = plt.cm.jet(np.linspace(0, 1, self.Ps.shape[0]))
|
187
|
+
elif colors.shape[0] < self.Ps.shape[0]:
|
188
|
+
colors = np.tile(colors, (self.Ps.shape[0], 1))
|
189
|
+
|
190
|
+
xmin, xmax, ymin, ymax, zmin, zmax = limits
|
191
|
+
dirs = self.V
|
192
|
+
k_min = (np.array([xmin, ymin, zmin]) - self.Ps) / dirs
|
193
|
+
k_max = (np.array([xmax, ymax, zmax]) - self.Ps) / dirs
|
194
|
+
|
195
|
+
valid_x_min = self._is_within_bounds(self.Ps + dirs * k_min[:, 0], ymin, ymax, zmin, zmax)
|
196
|
+
valid_y_min = self._is_within_bounds(self.Ps + dirs * k_min[:, 1], xmin, xmax, zmin, zmax)
|
197
|
+
valid_z_min = self._is_within_bounds(self.Ps + dirs * k_min[:, 2], xmin, xmax, ymin, ymax)
|
198
|
+
|
199
|
+
valid_x_max = self._is_within_bounds(self.Ps + dirs * k_max[:, 0], ymin, ymax, zmin, zmax)
|
200
|
+
valid_y_max = self._is_within_bounds(self.Ps + dirs * k_max[:, 1], xmin, xmax, zmin, zmax)
|
201
|
+
valid_z_max = self._is_within_bounds(self.Ps + dirs * k_max[:, 2], xmin, xmax, ymin, ymax)
|
202
|
+
|
203
|
+
valid = np.column_stack((valid_x_min, valid_y_min, valid_z_min, valid_x_max, valid_y_max, valid_z_max))
|
204
|
+
assert np.all(np.sum(valid, axis=1) == 2), 'Not all lines fit in window range!'
|
205
|
+
|
206
|
+
k = np.column_stack((k_min, k_max))
|
207
|
+
k_valid = k[valid].reshape(2, -1).T
|
208
|
+
start_points = self.Ps + dirs * k_valid[:, 0]
|
209
|
+
end_points = self.Ps + dirs * k_valid[:, 1]
|
210
|
+
|
211
|
+
fig = plt.figure()
|
212
|
+
ax = fig.add_subplot(111, projection='3d')
|
213
|
+
for i in range(start_points.shape[0]):
|
214
|
+
ax.plot([start_points[i, 0], end_points[i, 0]],
|
215
|
+
[start_points[i, 1], end_points[i, 1]],
|
216
|
+
[start_points[i, 2], end_points[i, 2]],
|
217
|
+
color=colors[i], linewidth=linewidth, linestyle=linestyle)
|
218
|
+
plt.show()
|
219
|
+
|
220
|
+
def PlotLine(self, colori = 'g', linewidth = 2, *args):
|
221
|
+
"""
|
222
|
+
Plot a single line in 3D space.
|
223
|
+
|
224
|
+
Parameters:
|
225
|
+
colori : str, optional
|
226
|
+
The color of the line.
|
227
|
+
linewidth : float, optional
|
228
|
+
The width of the line.
|
229
|
+
*args : variable length argument list
|
230
|
+
If one argument is provided, it is assumed to be the end point.
|
231
|
+
"""
|
232
|
+
P1 = self.Ps
|
233
|
+
if len(args) == 1:
|
234
|
+
P3 = self.Pe
|
235
|
+
else:
|
236
|
+
P3 = self.Ps + self.V
|
237
|
+
|
238
|
+
if P1.shape[0] > 500:
|
239
|
+
P1 = self._downsample(P1, round(P1.shape[0] / 500) + 1)
|
240
|
+
P3 = self._downsample(P3, round(P3.shape[0] / 500) + 1)
|
241
|
+
print('Too many lines to plot, showing downsampled version')
|
242
|
+
|
243
|
+
fig = plt.figure()
|
244
|
+
ax = fig.add_subplot(111, projection='3d')
|
245
|
+
for i in range(P1.shape[0]):
|
246
|
+
color = 'b' if i == 0 or i == 4 else 'k' if i == 4 else 'b'
|
247
|
+
ax.plot([P1[i, 0], P3[i, 0]], [P1[i, 1], P3[i, 1]], [P1[i, 2], P3[i, 2]], color=color, linewidth=linewidth)
|
248
|
+
if i > 500:
|
249
|
+
print('Too many lines to plot')
|
250
|
+
break
|
251
|
+
plt.show()
|
252
|
+
|
253
|
+
def FindXYZNearestLine(self, XYZ):
|
254
|
+
"""
|
255
|
+
Find the index of the line closest to a given point.
|
256
|
+
|
257
|
+
Parameters:
|
258
|
+
XYZ : numpy array of shape (3,)
|
259
|
+
The point to find the closest line to.
|
260
|
+
|
261
|
+
Returns:
|
262
|
+
int
|
263
|
+
The index of the closest line.
|
264
|
+
"""
|
265
|
+
distances = self.DistanceLinePoint(XYZ)
|
266
|
+
return np.argmin(distances)
|
267
|
+
|
268
|
+
def FitLine(self, XYZ):
|
269
|
+
"""
|
270
|
+
Fit a line to a set of points.
|
271
|
+
|
272
|
+
Parameters:
|
273
|
+
XYZ : numpy array of shape (n, 3)
|
274
|
+
The points to fit the line to.
|
275
|
+
"""
|
276
|
+
l = self._fitline3d(XYZ.T).T
|
277
|
+
self.Ps = l[0]
|
278
|
+
self.Pe = l[1]
|
279
|
+
|
280
|
+
def FitLineRansac(self, XYZ, t=10):
|
281
|
+
"""
|
282
|
+
Fit a line to a set of points using the RANSAC algorithm.
|
283
|
+
|
284
|
+
Parameters:
|
285
|
+
XYZ : numpy array of shape (n, 3)
|
286
|
+
The points to fit the line to.
|
287
|
+
t : float, optional
|
288
|
+
The threshold distance for a point to be considered an inlier.
|
289
|
+
"""
|
290
|
+
Ps, Pe = self._ransac_fit_line(XYZ.T, t)
|
291
|
+
self.Ps = Ps.T
|
292
|
+
self.Pe = Pe.T
|
293
|
+
|
294
|
+
def NormaliseLine(self):
|
295
|
+
"""
|
296
|
+
Normalize the line so that the z-coordinate of the start point is zero.
|
297
|
+
"""
|
298
|
+
try:
|
299
|
+
scale = -self.Ps[:, 2] / self.V[:, 2]
|
300
|
+
self.Ps = self.Ps + scale[:, np.newaxis] * self.V
|
301
|
+
except:
|
302
|
+
pass
|
303
|
+
|
304
|
+
def DistanceLinePoint(self, XYZ):
|
305
|
+
"""
|
306
|
+
Compute the distance from a point to the line.
|
307
|
+
|
308
|
+
Parameters:
|
309
|
+
XYZ : numpy array of shape (3,)
|
310
|
+
The point to compute the distance to.
|
311
|
+
|
312
|
+
Returns:
|
313
|
+
numpy array of shape (n,)
|
314
|
+
The distances from the point to each line.
|
315
|
+
"""
|
316
|
+
return np.linalg.norm(np.cross(self.Pe - self.Ps, self.Ps - XYZ), axis=1) / np.linalg.norm(self.Pe - self.Ps, axis=1)
|
317
|
+
|
318
|
+
def Lenght(self):
|
319
|
+
"""
|
320
|
+
Compute the length of the line.
|
321
|
+
|
322
|
+
Returns:
|
323
|
+
numpy array of shape (n,)
|
324
|
+
The lengths of the lines.
|
325
|
+
"""
|
326
|
+
return np.linalg.norm(self.Ps - self.Pe, axis=1)
|
327
|
+
|
328
|
+
@staticmethod
|
329
|
+
def FromStartEnd(start_point, end_point):
|
330
|
+
"""
|
331
|
+
Create a Line object from start and end points.
|
332
|
+
|
333
|
+
Parameters:
|
334
|
+
start_point : numpy array of shape (3,)
|
335
|
+
The start point of the line.
|
336
|
+
end_point : numpy array of shape (3,)
|
337
|
+
The end point of the line.
|
338
|
+
|
339
|
+
Returns:
|
340
|
+
Line object
|
341
|
+
The line object created from the start and end points.
|
342
|
+
"""
|
343
|
+
line_object = Line()
|
344
|
+
line_object.Ps = start_point
|
345
|
+
line_object.Pe = end_point
|
346
|
+
return line_object
|
347
|
+
|
348
|
+
@staticmethod
|
349
|
+
def FromPlucker(VU):
|
350
|
+
"""
|
351
|
+
Create a Line object from Plucker coordinates.
|
352
|
+
|
353
|
+
Parameters:
|
354
|
+
VU : numpy array of shape (6,)
|
355
|
+
The Plucker coordinates [V, U] where V is the direction vector and U is the moment vector.
|
356
|
+
|
357
|
+
Returns:
|
358
|
+
Line object
|
359
|
+
The line object created from the Plucker coordinates.
|
360
|
+
"""
|
361
|
+
line_object = Line()
|
362
|
+
line_object.Plucker = VU
|
363
|
+
return line_object
|
364
|
+
|
365
|
+
def _normalize_vectors(self, vectors):
|
366
|
+
"""
|
367
|
+
Normalize a set of vectors.
|
368
|
+
|
369
|
+
Parameters:
|
370
|
+
vectors : numpy array of shape (n, 3)
|
371
|
+
The vectors to normalize.
|
372
|
+
|
373
|
+
Returns:
|
374
|
+
numpy array of shape (n, 3)
|
375
|
+
The normalized vectors.
|
376
|
+
"""
|
377
|
+
norms = np.linalg.norm(vectors, axis=1)
|
378
|
+
return vectors / norms[:, np.newaxis]
|
379
|
+
|
380
|
+
def _is_within_bounds(self, points, xmin, xmax, ymin, ymax, zmin, zmax):
|
381
|
+
"""
|
382
|
+
Check if points are within a given bounding box.
|
383
|
+
|
384
|
+
Parameters:
|
385
|
+
points : numpy array of shape (n, 3)
|
386
|
+
The points to check.
|
387
|
+
xmin, xmax, ymin, ymax, zmin, zmax : float
|
388
|
+
The bounds of the box.
|
389
|
+
|
390
|
+
Returns:
|
391
|
+
numpy array of shape (n,)
|
392
|
+
A boolean array indicating whether each point is within the bounds.
|
393
|
+
"""
|
394
|
+
return (points[:, 0] >= xmin) & (points[:, 0] <= xmax) & \
|
395
|
+
(points[:, 1] >= ymin) & (points[:, 1] <= ymax) & \
|
396
|
+
(points[:, 2] >= zmin) & (points[:, 2] <= zmax)
|
397
|
+
|
398
|
+
def _downsample(self, points, factor):
|
399
|
+
"""
|
400
|
+
Downsample a set of points.
|
401
|
+
|
402
|
+
Parameters:
|
403
|
+
points : numpy array of shape (n, 3)
|
404
|
+
The points to downsample.
|
405
|
+
factor : int
|
406
|
+
The downsampling factor.
|
407
|
+
|
408
|
+
Returns:
|
409
|
+
numpy array of shape (n/factor, 3)
|
410
|
+
The downsampled points.
|
411
|
+
"""
|
412
|
+
return points[::factor]
|
413
|
+
|
414
|
+
def _fitline3d(self, XYZ):
|
415
|
+
"""
|
416
|
+
Fit a line to a set of points in 3D space.
|
417
|
+
|
418
|
+
Parameters:
|
419
|
+
XYZ : numpy array of shape (3, n)
|
420
|
+
The points to fit the line to.
|
421
|
+
|
422
|
+
Returns:
|
423
|
+
numpy array of shape (2, 3)
|
424
|
+
The start and end points of the fitted line.
|
425
|
+
"""
|
426
|
+
# Placeholder for the actual fitline3d implementation
|
427
|
+
pass
|
428
|
+
|
429
|
+
def AngleBetweenLines(self, L1, L2):
|
430
|
+
"""
|
431
|
+
Compute the angle between two lines.
|
432
|
+
|
433
|
+
Parameters:
|
434
|
+
L1, L2 : Line objects
|
435
|
+
The lines to compute the angle between.
|
436
|
+
|
437
|
+
Returns:
|
438
|
+
tuple of floats
|
439
|
+
The angle in radians and degrees between the lines.
|
440
|
+
"""
|
441
|
+
T1 = (np.cross(L1.V, L2.V))
|
442
|
+
T2 = (np.dot(L1.V, np.transpose(L2.V)))
|
443
|
+
T1R = np.linalg.norm((T1))
|
444
|
+
Theta = np.arctan2(T1R, T2)
|
445
|
+
ThetaDegree = Theta * 180 / np.pi
|
446
|
+
return (Theta, ThetaDegree)
|
447
|
+
|
448
|
+
def _ransac_fit_line(self, XYZ, t):
|
449
|
+
"""
|
450
|
+
Fit a line to a set of points using the RANSAC algorithm.
|
451
|
+
|
452
|
+
Parameters:
|
453
|
+
XYZ : numpy array of shape (3, n)
|
454
|
+
The points to fit the line to.
|
455
|
+
t : float
|
456
|
+
The threshold distance for a point to be considered an inlier.
|
457
|
+
|
458
|
+
Returns:
|
459
|
+
tuple of numpy arrays
|
460
|
+
The start and end points of the fitted line.
|
461
|
+
"""
|
462
|
+
# Placeholder for the actual RANSAC fit line implementation
|
463
|
+
pass
|
464
|
+
|
465
|
+
def HomogeneousTransformation(self, H, points):
|
466
|
+
"""
|
467
|
+
Apply a homogeneous transformation to a set of points.
|
468
|
+
|
469
|
+
Parameters:
|
470
|
+
H : numpy array of shape (4, 4)
|
471
|
+
The homogeneous transformation matrix.
|
472
|
+
points : numpy array of shape (n, 3)
|
473
|
+
The points to transform.
|
474
|
+
|
475
|
+
Returns:
|
476
|
+
numpy array of shape (n, 3)
|
477
|
+
The transformed points.
|
478
|
+
"""
|
479
|
+
# Placeholder for the actual homogeneous transformation implementation
|
480
|
+
pass
|
481
|
+
|
482
|
+
def GenerateRay(self, I, uv, visualize = False):
|
483
|
+
"""
|
484
|
+
Generate rays from a sensor grid.
|
485
|
+
|
486
|
+
Parameters:
|
487
|
+
I : Sensor object
|
488
|
+
The sensor to generate rays from.
|
489
|
+
uv : numpy array of shape (n, 2)
|
490
|
+
The sensor grid points.
|
491
|
+
visualize : bool, optional
|
492
|
+
Whether to visualize the rays.
|
493
|
+
|
494
|
+
Returns:
|
495
|
+
Line object
|
496
|
+
The rays generated from the sensor grid.
|
497
|
+
"""
|
498
|
+
rays = Line()
|
499
|
+
Ps = uv.copy() # sensor points
|
500
|
+
|
501
|
+
# Adjust sensor points
|
502
|
+
Ps[:, 0] = Ps[:, 0] - I.cx
|
503
|
+
Ps[:, 1] = Ps[:, 1] - I.cy
|
504
|
+
scale = 2 / 1 # just so the 'sensor' is not bigger than the object (only for visualization)
|
505
|
+
Ps[:, 0] = Ps[:, 0] / I.fx * scale
|
506
|
+
Ps[:, 1] = Ps[:, 1] / I.fy * scale # f van Y
|
507
|
+
Ps[:, 2] = 1 * scale
|
508
|
+
|
509
|
+
Pf = np.zeros(Ps.shape)
|
510
|
+
Pf[:, 2] = 0 * scale
|
511
|
+
|
512
|
+
rays.Pe = Ps
|
513
|
+
rays.Ps = Pf
|
514
|
+
|
515
|
+
if visualize:
|
516
|
+
fig = plt.figure()
|
517
|
+
ax = fig.add_subplot(111, projection='3d')
|
518
|
+
ax.plot(rays.Pe[:, 0], rays.Pe[:, 1], rays.Pe[:, 2], 'g', linewidth=5)
|
519
|
+
ax.plot(rays.Ps[:, 0], rays.Ps[:, 1], rays.Ps[:, 2], 'g', linewidth=5)
|
520
|
+
ax.set_xlabel('x')
|
521
|
+
ax.set_ylabel('y')
|
522
|
+
ax.set_zlabel('z')
|
523
|
+
ax.set_aspect('equal')
|
524
|
+
plt.show()
|
525
|
+
|
526
|
+
return rays
|
CTPv/Plucker/__init__.py
ADDED
File without changes
|