Add Button.value Event parameter
Add test
Small fix
1 | 7 |
import base64 |
2 | 7 |
import hashlib |
3 | 7 |
import io |
4 | 7 |
import struct |
5 | 7 |
import sys |
6 | 7 |
import time |
7 | 7 |
import zipfile |
8 |
|
|
9 | 7 |
from vtk.vtkCommonCore import vtkTypeUInt32Array, vtkTypeInt32Array |
10 | 7 |
from vtk.vtkFiltersGeometry import vtkCompositeDataGeometryFilter, vtkGeometryFilter |
11 | 7 |
from vtk.vtkRenderingCore import vtkColorTransferFunction |
12 |
|
|
13 |
# -----------------------------------------------------------------------------
|
|
14 |
# Python compatibility handling 2.6, 2.7, 3+
|
|
15 |
# -----------------------------------------------------------------------------
|
|
16 |
|
|
17 | 7 |
py3 = sys.version_info >= (3, 0) |
18 |
|
|
19 | 7 |
if py3: |
20 | 7 |
def iteritems(d, **kwargs): |
21 |
return iter(d.items(**kwargs)) |
|
22 |
else: |
|
23 |
def iteritems(d, **kwargs): |
|
24 |
return d.iteritems(**kwargs) |
|
25 |
|
|
26 | 7 |
if sys.version_info >= (2, 7): |
27 | 7 |
buffer = memoryview |
28 | 7 |
base64Encode = lambda x: base64.b64encode(x).decode('utf-8') |
29 |
else: |
|
30 |
buffer = buffer |
|
31 |
base64Encode = lambda x: x.encode('base64') |
|
32 |
|
|
33 |
# -----------------------------------------------------------------------------
|
|
34 |
# Array helpers
|
|
35 |
# -----------------------------------------------------------------------------
|
|
36 |
|
|
37 | 7 |
arrayTypesMapping = [ |
38 |
' ', # VTK_VOID 0 |
|
39 |
' ', # VTK_BIT 1 |
|
40 |
'b', # VTK_CHAR 2 |
|
41 |
'B', # VTK_UNSIGNED_CHAR 3 |
|
42 |
'h', # VTK_SHORT 4 |
|
43 |
'H', # VTK_UNSIGNED_SHORT 5 |
|
44 |
'i', # VTK_INT 6 |
|
45 |
'I', # VTK_UNSIGNED_INT 7 |
|
46 |
'l', # VTK_LONG 8 |
|
47 |
'L', # VTK_UNSIGNED_LONG 9 |
|
48 |
'f', # VTK_FLOAT 10 |
|
49 |
'd', # VTK_DOUBLE 11 |
|
50 |
'L', # VTK_ID_TYPE 12 |
|
51 |
' ', # VTK_STRING 13 |
|
52 |
' ', # VTK_OPAQUE 14 |
|
53 |
' ', # UNDEFINED |
|
54 |
'l', # VTK_LONG_LONG 16 |
|
55 |
'L', # VTK_UNSIGNED_LONG_LONG 17 |
|
56 |
]
|
|
57 |
|
|
58 | 7 |
javascriptMapping = { |
59 |
'b': 'Int8Array', |
|
60 |
'B': 'Uint8Array', |
|
61 |
'h': 'Int16Array', |
|
62 |
'H': 'UInt16Array', |
|
63 |
'i': 'Int32Array', |
|
64 |
'I': 'Uint32Array', |
|
65 |
'l': 'Int32Array', |
|
66 |
'L': 'Uint32Array', |
|
67 |
'f': 'Float32Array', |
|
68 |
'd': 'Float64Array' |
|
69 |
}
|
|
70 |
|
|
71 |
|
|
72 | 7 |
def hashDataArray(dataArray): |
73 | 7 |
return hashlib.md5(buffer(dataArray)).hexdigest() |
74 |
|
|
75 |
|
|
76 | 7 |
def getJSArrayType(dataArray): |
77 | 7 |
return javascriptMapping[arrayTypesMapping[dataArray.GetDataType()]] |
78 |
|
|
79 |
|
|
80 | 7 |
def zipCompression(name, data): |
81 | 7 |
with io.BytesIO() as in_memory: |
82 | 7 |
with zipfile.ZipFile(in_memory, mode="w") as zf: |
83 | 7 |
zf.writestr('data/%s' % name, |
84 |
data, zipfile.ZIP_DEFLATED) |
|
85 | 7 |
in_memory.seek(0) |
86 | 7 |
return in_memory.read() |
87 |
|
|
88 |
|
|
89 | 7 |
def dataTableToList(dataTable): |
90 |
dataType = arrayTypesMapping[dataTable.GetDataType()] |
|
91 |
elementSize = struct.calcsize(dataType) |
|
92 |
nbValues = dataTable.GetNumberOfValues() |
|
93 |
nbComponents = dataTable.GetNumberOfComponents() |
|
94 |
nbytes = elementSize * nbValues |
|
95 |
if dataType != ' ': |
|
96 |
with io.BytesIO(buffer(dataTable)) as stream: |
|
97 |
data = list(struct.unpack(dataType*nbValues ,stream.read(nbytes))) |
|
98 |
return [data[idx*nbComponents:(idx+1)*nbComponents] |
|
99 |
for idx in range(nbValues//nbComponents)] |
|
100 |
|
|
101 |
|
|
102 | 7 |
def getScalars(mapper, dataset): |
103 | 7 |
scalars = None |
104 | 7 |
cell_flag = 0 |
105 | 7 |
scalar_mode = mapper.GetScalarMode() |
106 | 7 |
array_access_mode = mapper.GetArrayAccessMode() |
107 | 7 |
array_id = mapper.GetArrayId() |
108 | 7 |
array_name = mapper.GetArrayName() |
109 | 7 |
pd = dataset.GetPointData() |
110 | 7 |
cd = dataset.GetCellData() |
111 | 7 |
fd = dataset.GetFieldData() |
112 | 7 |
if scalar_mode == 0: # VTK_SCALAR_MODE_DEFAULT |
113 | 7 |
scalars = pd.GetScalars() |
114 | 7 |
cell_flag = 0 |
115 | 7 |
if scalars is None: |
116 | 7 |
scalars = cd.GetScalars() |
117 | 7 |
cell_flag = 1 |
118 | 7 |
elif scalar_mode == 1: # VTK_SCALAR_MODE_USE_POINT_DATA |
119 | 7 |
scalars = pd.GetScalars() |
120 | 7 |
cell_flag = 0 |
121 | 7 |
elif scalar_mode == 2: # VTK_SCALAR_MODE_USE_CELL_DATA |
122 | 7 |
scalars = cd.GetScalars() |
123 | 7 |
cell_flag = 1 |
124 | 7 |
elif scalar_mode == 3: # VTK_SCALAR_MODE_USE_POINT_FIELD_DATA |
125 |
if array_access_mode == 0: # VTK_GET_ARRAY_BY_ID |
|
126 |
scalars = pd.GetAbstractArray(array_id) |
|
127 |
else: # VTK_GET_ARRAY_BY_NAME |
|
128 |
scalars = pd.GetAbstractArray(array_name) |
|
129 |
cell_flag = 0 |
|
130 | 7 |
elif scalar_mode == 4: # VTK_SCALAR_MODE_USE_CELL_FIELD_DATA |
131 |
if array_access_mode == 0: # VTK_GET_ARRAY_BY_ID |
|
132 |
scalars = cd.GetAbstractArray(array_id) |
|
133 |
else: # VTK_GET_ARRAY_BY_NAME |
|
134 |
scalars = cd.GetAbstractArray(array_name) |
|
135 |
cell_flag = 1 |
|
136 |
else: # VTK_SCALAR_MODE_USE_FIELD_DATA |
|
137 | 7 |
if array_access_mode == 0: # VTK_GET_ARRAY_BY_ID |
138 | 7 |
scalars = fd.GetAbstractArray(array_id) |
139 |
else: # VTK_GET_ARRAY_BY_NAME |
|
140 |
scalars = fd.GetAbstractArray(array_name) |
|
141 | 7 |
cell_flag = 2 |
142 | 7 |
return scalars, cell_flag |
143 |
|
|
144 |
|
|
145 | 7 |
def retrieveArrayName(mapper_instance, scalar_mode): |
146 | 7 |
colorArrayName = None |
147 | 7 |
try: |
148 | 7 |
ds = [deps for deps in mapper_instance['dependencies'] if deps['id'].endswith('dataset')][0] |
149 | 7 |
location = "pointData" if scalar_mode in (1, 3) else "cellData" |
150 | 7 |
for arrayMeta in ds['properties']['fields']: |
151 | 7 |
if arrayMeta["location"] == location and arrayMeta.get("registration", None) == "setScalars": |
152 | 7 |
colorArrayName = arrayMeta["name"] |
153 |
except Exception: |
|
154 |
pass
|
|
155 | 7 |
return colorArrayName |
156 |
|
|
157 |
|
|
158 | 7 |
def linspace(start, stop, num): |
159 |
delta = (stop - start)/(num-1) |
|
160 |
return [start + i*delta for i in range(num)] |
|
161 |
|
|
162 |
# -----------------------------------------------------------------------------
|
|
163 |
# Convenience class for caching data arrays, storing computed sha sums, keeping
|
|
164 |
# track of valid actors, etc...
|
|
165 |
# -----------------------------------------------------------------------------
|
|
166 |
|
|
167 |
|
|
168 | 7 |
class SynchronizationContext(): |
169 |
|
|
170 | 7 |
def __init__(self, id_root=None, serialize_all_data_arrays=False, debug=False): |
171 | 7 |
self.serializeAllDataArrays = serialize_all_data_arrays |
172 | 7 |
self.dataArrayCache = {} |
173 | 7 |
self.lastDependenciesMapping = {} |
174 | 7 |
self.ingoreLastDependencies = False |
175 | 7 |
self.idRoot = id_root |
176 | 7 |
self.debugSerializers = debug |
177 | 7 |
self.debugAll = debug |
178 |
|
|
179 | 7 |
def getReferenceId(self, instance): |
180 | 7 |
if not self.idRoot or (hasattr(instance, 'IsA') and instance.IsA('vtkCamera')): |
181 | 7 |
return getReferenceId(instance) |
182 |
else: |
|
183 | 7 |
return self.idRoot + getReferenceId(instance) |
184 |
|
|
185 | 7 |
def setIgnoreLastDependencies(self, force): |
186 |
self.ingoreLastDependencies = force |
|
187 |
|
|
188 | 7 |
def cacheDataArray(self, pMd5, data): |
189 | 7 |
self.dataArrayCache[pMd5] = data |
190 |
|
|
191 | 7 |
def getCachedDataArray(self, pMd5, binary=False, compression=False): |
192 | 7 |
cacheObj = self.dataArrayCache[pMd5] |
193 | 7 |
array = cacheObj['array'] |
194 | 7 |
cacheTime = cacheObj['mTime'] |
195 |
|
|
196 | 7 |
if cacheTime != array.GetMTime(): |
197 |
if context.debugAll: |
|
198 |
print(' ***** ERROR: you asked for an old cache key! ***** ') |
|
199 |
|
|
200 | 7 |
if array.GetDataType() in (12, 16, 17): |
201 | 7 |
arraySize = array.GetNumberOfTuples() * array.GetNumberOfComponents() |
202 | 7 |
if array.GetDataType() in (12, 17): |
203 |
# IdType and unsigned long long need to be converted to Uint32
|
|
204 | 7 |
newArray = vtkTypeUInt32Array() |
205 |
else: |
|
206 |
# long long need to be converted to Int32
|
|
207 |
newArray = vtkTypeInt32Array() |
|
208 | 7 |
newArray.SetNumberOfTuples(arraySize) |
209 | 7 |
for i in range(arraySize): |
210 | 7 |
newArray.SetValue(i, -1 if array.GetValue(i) |
211 |
< 0 else array.GetValue(i)) |
|
212 | 7 |
pBuffer = buffer(newArray) |
213 |
else: |
|
214 | 7 |
pBuffer = buffer(array) |
215 |
|
|
216 | 7 |
if binary: |
217 |
# Convert the vtkUnsignedCharArray into a bytes object, required by
|
|
218 |
# Autobahn websockets
|
|
219 | 7 |
return pBuffer.tobytes() if not compression else zipCompression(pMd5, pBuffer.tobytes()) |
220 |
|
|
221 | 7 |
return base64Encode(pBuffer if not compression else zipCompression(pMd5, pBuffer.tobytes())) |
222 |
|
|
223 | 7 |
def checkForArraysToRelease(self, timeWindow=20): |
224 | 7 |
cutOffTime = time.time() - timeWindow |
225 | 7 |
shasToDelete = [] |
226 | 7 |
for sha in self.dataArrayCache: |
227 | 7 |
record = self.dataArrayCache[sha] |
228 | 7 |
array = record['array'] |
229 | 7 |
count = array.GetReferenceCount() |
230 |
|
|
231 | 7 |
if count == 1 and record['ts'] < cutOffTime: |
232 | 7 |
shasToDelete.append(sha) |
233 |
|
|
234 | 7 |
for sha in shasToDelete: |
235 | 7 |
del self.dataArrayCache[sha] |
236 |
|
|
237 | 7 |
def getLastDependencyList(self, idstr): |
238 | 7 |
lastDeps = [] |
239 | 7 |
if idstr in self.lastDependenciesMapping and not self.ingoreLastDependencies: |
240 | 7 |
lastDeps = self.lastDependenciesMapping[idstr] |
241 | 7 |
return lastDeps |
242 |
|
|
243 | 7 |
def setNewDependencyList(self, idstr, depList): |
244 | 7 |
self.lastDependenciesMapping[idstr] = depList |
245 |
|
|
246 | 7 |
def buildDependencyCallList(self, idstr, newList, addMethod, removeMethod): |
247 | 7 |
oldList = self.getLastDependencyList(idstr) |
248 |
|
|
249 | 7 |
calls = [] |
250 | 7 |
calls += [[addMethod, [wrapId(x)]] |
251 |
for x in newList if x not in oldList] |
|
252 | 7 |
calls += [[removeMethod, [wrapId(x)]] |
253 |
for x in oldList if x not in newList] |
|
254 |
|
|
255 | 7 |
self.setNewDependencyList(idstr, newList) |
256 | 7 |
return calls |
257 |
|
|
258 |
# -----------------------------------------------------------------------------
|
|
259 |
# Global variables
|
|
260 |
# -----------------------------------------------------------------------------
|
|
261 |
|
|
262 | 7 |
SERIALIZERS = {} |
263 | 7 |
context = None |
264 |
|
|
265 |
# -----------------------------------------------------------------------------
|
|
266 |
# Global API
|
|
267 |
# -----------------------------------------------------------------------------
|
|
268 |
|
|
269 |
|
|
270 | 7 |
def registerInstanceSerializer(name, method): |
271 |
global SERIALIZERS |
|
272 | 7 |
SERIALIZERS[name] = method |
273 |
|
|
274 |
# -----------------------------------------------------------------------------
|
|
275 |
|
|
276 |
|
|
277 | 7 |
def serializeInstance(parent, instance, instanceId, context, depth): |
278 | 7 |
instanceType = instance.GetClassName() |
279 | 7 |
serializer = SERIALIZERS[ |
280 |
instanceType] if instanceType in SERIALIZERS else None |
|
281 |
|
|
282 | 7 |
if serializer: |
283 | 7 |
return serializer(parent, instance, instanceId, context, depth) |
284 |
|
|
285 | 7 |
if context.debugSerializers: |
286 |
print('%s!!!No serializer for %s with id %s' % |
|
287 |
(pad(depth), instanceType, instanceId)) |
|
288 |
|
|
289 |
# -----------------------------------------------------------------------------
|
|
290 |
|
|
291 |
|
|
292 | 7 |
def initializeSerializers(): |
293 |
# Actors/viewProps
|
|
294 | 7 |
registerInstanceSerializer('vtkImageSlice', genericProp3DSerializer) |
295 | 7 |
registerInstanceSerializer('vtkVolume', genericProp3DSerializer) |
296 | 7 |
registerInstanceSerializer('vtkOpenGLActor', genericActorSerializer) |
297 | 7 |
registerInstanceSerializer('vtkFollower', genericActorSerializer) |
298 | 7 |
registerInstanceSerializer('vtkPVLODActor', genericActorSerializer) |
299 |
|
|
300 |
|
|
301 |
# Mappers
|
|
302 | 7 |
registerInstanceSerializer( |
303 |
'vtkOpenGLPolyDataMapper', genericPolyDataMapperSerializer) |
|
304 | 7 |
registerInstanceSerializer( |
305 |
'vtkCompositePolyDataMapper2', genericPolyDataMapperSerializer) |
|
306 | 7 |
registerInstanceSerializer('vtkDataSetMapper', genericPolyDataMapperSerializer) |
307 | 7 |
registerInstanceSerializer( |
308 |
'vtkFixedPointVolumeRayCastMapper', genericVolumeMapperSerializer) |
|
309 | 7 |
registerInstanceSerializer( |
310 |
'vtkSmartVolumeMapper', genericVolumeMapperSerializer) |
|
311 | 7 |
registerInstanceSerializer( |
312 |
'vtkOpenGLImageSliceMapper', imageSliceMapperSerializer) |
|
313 |
|
|
314 |
# LookupTables/TransferFunctions
|
|
315 | 7 |
registerInstanceSerializer('vtkLookupTable', lookupTableSerializer) |
316 | 7 |
registerInstanceSerializer( |
317 |
'vtkPVDiscretizableColorTransferFunction', colorTransferFunctionSerializer) |
|
318 | 7 |
registerInstanceSerializer( |
319 |
'vtkColorTransferFunction', colorTransferFunctionSerializer) |
|
320 |
|
|
321 |
# opacityFunctions
|
|
322 | 7 |
registerInstanceSerializer( |
323 |
'vtkPiecewiseFunction', piecewiseFunctionSerializer) |
|
324 |
|
|
325 |
# Textures
|
|
326 | 7 |
registerInstanceSerializer('vtkOpenGLTexture', textureSerializer) |
327 |
|
|
328 |
# Property
|
|
329 | 7 |
registerInstanceSerializer('vtkOpenGLProperty', propertySerializer) |
330 | 7 |
registerInstanceSerializer('vtkVolumeProperty', volumePropertySerializer) |
331 | 7 |
registerInstanceSerializer('vtkImageProperty', imagePropertySerializer) |
332 |
|
|
333 |
# Datasets
|
|
334 | 7 |
registerInstanceSerializer('vtkPolyData', polydataSerializer) |
335 | 7 |
registerInstanceSerializer('vtkImageData', imageDataSerializer) |
336 | 7 |
registerInstanceSerializer( |
337 |
'vtkStructuredGrid', mergeToPolydataSerializer) |
|
338 | 7 |
registerInstanceSerializer( |
339 |
'vtkUnstructuredGrid', mergeToPolydataSerializer) |
|
340 | 7 |
registerInstanceSerializer( |
341 |
'vtkMultiBlockDataSet', mergeToPolydataSerializer) |
|
342 |
|
|
343 |
# RenderWindows
|
|
344 | 7 |
registerInstanceSerializer('vtkCocoaRenderWindow', renderWindowSerializer) |
345 | 7 |
registerInstanceSerializer( |
346 |
'vtkXOpenGLRenderWindow', renderWindowSerializer) |
|
347 | 7 |
registerInstanceSerializer( |
348 |
'vtkWin32OpenGLRenderWindow', renderWindowSerializer) |
|
349 | 7 |
registerInstanceSerializer('vtkEGLRenderWindow', renderWindowSerializer) |
350 | 7 |
registerInstanceSerializer('vtkOpenVRRenderWindow', renderWindowSerializer) |
351 | 7 |
registerInstanceSerializer( |
352 |
'vtkGenericOpenGLRenderWindow', renderWindowSerializer) |
|
353 | 7 |
registerInstanceSerializer( |
354 |
'vtkOSOpenGLRenderWindow', renderWindowSerializer) |
|
355 | 7 |
registerInstanceSerializer('vtkOpenGLRenderWindow', renderWindowSerializer) |
356 | 7 |
registerInstanceSerializer('vtkIOSRenderWindow', renderWindowSerializer) |
357 | 7 |
registerInstanceSerializer( |
358 |
'vtkExternalOpenGLRenderWindow', renderWindowSerializer) |
|
359 |
|
|
360 |
# Renderers
|
|
361 | 7 |
registerInstanceSerializer('vtkOpenGLRenderer', rendererSerializer) |
362 |
|
|
363 |
# Cameras
|
|
364 | 7 |
registerInstanceSerializer('vtkOpenGLCamera', cameraSerializer) |
365 |
|
|
366 |
|
|
367 |
# -----------------------------------------------------------------------------
|
|
368 |
# Helper functions
|
|
369 |
# -----------------------------------------------------------------------------
|
|
370 |
|
|
371 |
|
|
372 | 7 |
def pad(depth): |
373 |
padding = '' |
|
374 |
for _ in range(depth): |
|
375 |
padding += ' ' |
|
376 |
return padding |
|
377 |
|
|
378 |
# -----------------------------------------------------------------------------
|
|
379 |
|
|
380 |
|
|
381 | 7 |
def wrapId(idStr): |
382 | 7 |
return 'instance:${%s}' % idStr |
383 |
|
|
384 |
# -----------------------------------------------------------------------------
|
|
385 |
|
|
386 |
|
|
387 | 7 |
def getReferenceId(ref): |
388 | 7 |
if ref: |
389 | 7 |
try: |
390 | 7 |
return ref.__this__[1:17] |
391 |
except Exception: |
|
392 |
idStr = str(ref)[-12:-1] |
|
393 |
print('====> fallback ID %s for %s' % (idStr, ref)) |
|
394 |
return idStr |
|
395 | 7 |
return '0x0' |
396 |
|
|
397 |
# -----------------------------------------------------------------------------
|
|
398 |
|
|
399 | 7 |
dataArrayShaMapping = {} |
400 |
|
|
401 |
|
|
402 | 7 |
def digest(array): |
403 | 7 |
objId = getReferenceId(array) |
404 |
|
|
405 | 7 |
record = None |
406 | 7 |
if objId in dataArrayShaMapping: |
407 | 7 |
record = dataArrayShaMapping[objId] |
408 |
|
|
409 | 7 |
if record and record['mtime'] == array.GetMTime(): |
410 | 7 |
return record['sha'] |
411 |
|
|
412 | 7 |
record = { |
413 |
'sha': hashDataArray(array), |
|
414 |
'mtime': array.GetMTime() |
|
415 |
}
|
|
416 |
|
|
417 | 7 |
dataArrayShaMapping[objId] = record |
418 | 7 |
return record['sha'] |
419 |
|
|
420 |
# -----------------------------------------------------------------------------
|
|
421 |
|
|
422 |
|
|
423 | 7 |
def getRangeInfo(array, component): |
424 | 7 |
r = array.GetRange(component) |
425 | 7 |
compRange = {} |
426 | 7 |
compRange['min'] = r[0] |
427 | 7 |
compRange['max'] = r[1] |
428 | 7 |
compRange['component'] = array.GetComponentName(component) |
429 | 7 |
return compRange |
430 |
|
|
431 |
# -----------------------------------------------------------------------------
|
|
432 |
|
|
433 |
|
|
434 | 7 |
def getArrayDescription(array, context): |
435 | 7 |
if not array: |
436 |
return None |
|
437 |
|
|
438 | 7 |
pMd5 = digest(array) |
439 | 7 |
context.cacheDataArray(pMd5, { |
440 |
'array': array, |
|
441 |
'mTime': array.GetMTime(), |
|
442 |
'ts': time.time() |
|
443 |
})
|
|
444 |
|
|
445 | 7 |
root = {} |
446 | 7 |
root['hash'] = pMd5 |
447 | 7 |
root['vtkClass'] = 'vtkDataArray' |
448 | 7 |
root['name'] = array.GetName() |
449 | 7 |
root['dataType'] = getJSArrayType(array) |
450 | 7 |
root['numberOfComponents'] = array.GetNumberOfComponents() |
451 | 7 |
root['size'] = array.GetNumberOfComponents() * array.GetNumberOfTuples() |
452 | 7 |
root['ranges'] = [] |
453 | 7 |
if root['numberOfComponents'] > 1: |
454 | 7 |
for i in range(root['numberOfComponents']): |
455 | 7 |
root['ranges'].append(getRangeInfo(array, i)) |
456 | 7 |
root['ranges'].append(getRangeInfo(array, -1)) |
457 |
else: |
|
458 | 7 |
root['ranges'].append(getRangeInfo(array, 0)) |
459 |
|
|
460 | 7 |
return root |
461 |
|
|
462 |
# -----------------------------------------------------------------------------
|
|
463 |
|
|
464 |
|
|
465 | 7 |
def extractAllDataArrays(extractedFields, dataset, context): |
466 |
pointData = dataset.GetPointData() |
|
467 |
for id_arr in range(pointData.GetNumberOfArrays()): |
|
468 |
arrayMeta = getArrayDescription(pointData.GetArray(id_arr), context) |
|
469 |
if arrayMeta: |
|
470 |
arrayMeta['location'] = 'pointData' |
|
471 |
extractedFields.append(arrayMeta) |
|
472 |
cellData = dataset.GetCellData() |
|
473 |
for id_arr in range(cellData.GetNumberOfArrays()): |
|
474 |
arrayMeta = getArrayDescription(cellData.GetArray(id_arr), context) |
|
475 |
if arrayMeta: |
|
476 |
arrayMeta['location'] = 'cellData' |
|
477 |
extractedFields.append(arrayMeta) |
|
478 |
fieldData = dataset.GetCellData() |
|
479 |
for id_arr in range(fieldData.GetNumberOfArrays()): |
|
480 |
arrayMeta = getArrayDescription(fieldData.GetArray(id_arr), context) |
|
481 |
if arrayMeta: |
|
482 |
arrayMeta['location'] = 'fieldData' |
|
483 |
extractedFields.append(arrayMeta) |
|
484 |
|
|
485 |
# -----------------------------------------------------------------------------
|
|
486 |
|
|
487 |
|
|
488 | 7 |
def extractRequiredFields(extractedFields, parent, dataset, context, requestedFields=['Normals', 'TCoords']): |
489 |
# FIXME should evolve and support funky mapper which leverage many arrays
|
|
490 | 7 |
if any(parent.IsA(cls) for cls in ['vtkMapper', 'vtkVolumeMapper', 'vtkImageSliceMapper', 'vtkTexture']): |
491 | 7 |
if parent.IsA("vtkAbstractMapper"): # GetScalars method should exists |
492 | 7 |
scalarVisibility = 1 if not hasattr(parent, "GetScalarVisibility") else parent.GetScalarVisibility() |
493 | 7 |
scalars, cell_flag = getScalars(parent, dataset) |
494 | 7 |
if context.serializeAllDataArrays: |
495 |
extractAllDataArrays(extractedFields, dataset, context) |
|
496 |
if scalars: |
|
497 |
for arrayMeta in extractedFields: |
|
498 |
if arrayMeta['name'] == scalars.GetName(): |
|
499 |
arrayMeta['registration'] = 'setScalars' |
|
500 | 7 |
elif scalars and scalarVisibility and not context.serializeAllDataArrays: |
501 | 7 |
arrayMeta = getArrayDescription(scalars, context) |
502 | 7 |
if cell_flag == 0: |
503 | 7 |
arrayMeta['location'] = 'pointData' |
504 | 7 |
elif cell_flag == 1: |
505 | 7 |
arrayMeta['location'] = 'cellData' |
506 |
else: |
|
507 |
raise NotImplementedError("Scalars on field data not handled") |
|
508 | 7 |
arrayMeta['registration'] = 'setScalars' |
509 | 7 |
extractedFields.append(arrayMeta) |
510 | 7 |
elif dataset.GetPointData().GetScalars(): |
511 | 7 |
arrayMeta = getArrayDescription(dataset.GetPointData().GetScalars(), context) |
512 | 7 |
arrayMeta['location'] = 'pointData' |
513 | 7 |
arrayMeta['registration'] = 'setScalars' |
514 | 7 |
extractedFields.append(arrayMeta) |
515 |
|
|
516 |
# Normal handling
|
|
517 | 7 |
if 'Normals' in requestedFields: |
518 | 7 |
normals = dataset.GetPointData().GetNormals() |
519 | 7 |
if normals: |
520 | 7 |
arrayMeta = getArrayDescription(normals, context) |
521 | 7 |
if arrayMeta: |
522 | 7 |
arrayMeta['location'] = 'pointData' |
523 | 7 |
arrayMeta['registration'] = 'setNormals' |
524 | 7 |
extractedFields.append(arrayMeta) |
525 |
|
|
526 |
# TCoord handling
|
|
527 | 7 |
if 'TCoords' in requestedFields: |
528 | 7 |
tcoords = dataset.GetPointData().GetTCoords() |
529 | 7 |
if tcoords: |
530 | 7 |
arrayMeta = getArrayDescription(tcoords, context) |
531 | 7 |
if arrayMeta: |
532 | 7 |
arrayMeta['location'] = 'pointData' |
533 | 7 |
arrayMeta['registration'] = 'setTCoords' |
534 | 7 |
extractedFields.append(arrayMeta) |
535 |
|
|
536 |
# -----------------------------------------------------------------------------
|
|
537 |
# Concrete instance serializers
|
|
538 |
# -----------------------------------------------------------------------------
|
|
539 |
|
|
540 | 7 |
def genericPropSerializer(parent, prop, popId, context, depth): |
541 |
# This kind of actor has two "children" of interest, a property and a
|
|
542 |
# mapper (optionnaly a texture)
|
|
543 | 7 |
mapperInstance = None |
544 | 7 |
propertyInstance = None |
545 | 7 |
calls = [] |
546 | 7 |
dependencies = [] |
547 |
|
|
548 | 7 |
mapper = None |
549 | 7 |
if not hasattr(prop, 'GetMapper'): |
550 |
if context.debugAll: |
|
551 |
print('This volume does not have a GetMapper method') |
|
552 |
else: |
|
553 | 7 |
mapper = prop.GetMapper() |
554 |
|
|
555 | 7 |
if mapper: |
556 | 7 |
mapperId = context.getReferenceId(mapper) |
557 | 7 |
mapperInstance = serializeInstance( |
558 |
prop, mapper, mapperId, context, depth + 1) |
|
559 | 7 |
if mapperInstance: |
560 | 7 |
dependencies.append(mapperInstance) |
561 | 7 |
calls.append(['setMapper', [wrapId(mapperId)]]) |
562 |
|
|
563 | 7 |
properties = None |
564 | 7 |
if hasattr(prop, 'GetProperty'): |
565 | 7 |
properties = prop.GetProperty() |
566 |
else: |
|
567 |
if context.debugAll: |
|
568 |
print('This image does not have a GetProperty method') |
|
569 |
|
|
570 | 7 |
if properties: |
571 | 7 |
propId = context.getReferenceId(properties) |
572 | 7 |
propertyInstance = serializeInstance( |
573 |
prop, properties, propId, context, depth + 1) |
|
574 | 7 |
if propertyInstance: |
575 | 7 |
dependencies.append(propertyInstance) |
576 | 7 |
calls.append(['setProperty', [wrapId(propId)]]) |
577 |
|
|
578 |
# Handle texture if any
|
|
579 | 7 |
texture = None |
580 | 7 |
if hasattr(prop, 'GetTexture'): |
581 | 7 |
texture = prop.GetTexture() |
582 |
|
|
583 | 7 |
if texture: |
584 | 7 |
textureId = context.getReferenceId(texture) |
585 | 7 |
textureInstance = serializeInstance( |
586 |
prop, texture, textureId, context, depth + 1) |
|
587 | 7 |
if textureInstance: |
588 | 7 |
dependencies.append(textureInstance) |
589 | 7 |
calls.append(['addTexture', [wrapId(textureId)]]) |
590 |
|
|
591 | 7 |
return { |
592 |
'parent': context.getReferenceId(parent), |
|
593 |
'id': popId, |
|
594 |
'type': prop.GetClassName(), |
|
595 |
'properties': { |
|
596 |
# vtkProp
|
|
597 |
'visibility': prop.GetVisibility(), |
|
598 |
'pickable': prop.GetPickable(), |
|
599 |
'dragable': prop.GetDragable(), |
|
600 |
'useBounds': prop.GetUseBounds(), |
|
601 |
},
|
|
602 |
'calls': calls, |
|
603 |
'dependencies': dependencies |
|
604 |
}
|
|
605 |
|
|
606 |
# -----------------------------------------------------------------------------
|
|
607 |
|
|
608 |
|
|
609 | 7 |
def genericProp3DSerializer(parent, prop3D, prop3DId, context, depth): |
610 |
# This kind of actor has some position properties to add
|
|
611 | 7 |
instance = genericPropSerializer(parent, prop3D, prop3DId, context, depth) |
612 |
|
|
613 | 7 |
if not instance: return |
614 |
|
|
615 | 7 |
instance['properties'].update({ |
616 |
# vtkProp3D
|
|
617 |
'origin': prop3D.GetOrigin(), |
|
618 |
'position': prop3D.GetPosition(), |
|
619 |
'scale': prop3D.GetScale(), |
|
620 |
'orientation': prop3D.GetOrientation(), |
|
621 |
})
|
|
622 |
|
|
623 | 7 |
if prop3D.GetUserMatrix(): |
624 |
instance['properties'].update({ |
|
625 |
'userMatrix': [prop3D.GetUserMatrix().GetElement(i%4,i//4) for i in range(16)], |
|
626 |
})
|
|
627 | 7 |
return instance |
628 |
|
|
629 |
# -----------------------------------------------------------------------------
|
|
630 |
|
|
631 |
|
|
632 | 7 |
def genericActorSerializer(parent, actor, actorId, context, depth): |
633 |
# may have texture and
|
|
634 | 7 |
instance = genericProp3DSerializer(parent, actor, actorId, context, depth) |
635 |
|
|
636 | 7 |
if not instance: return |
637 |
|
|
638 |
# # actor may have a backface property instance (not used by vtkjs rendering)
|
|
639 |
# # https://github.com/Kitware/vtk-js/issues/1545
|
|
640 |
|
|
641 |
# backfaceProperties = actor.GetBackfaceProperty()
|
|
642 |
|
|
643 |
# if backfaceProperties:
|
|
644 |
# backfacePropId = context.getReferenceId(backfaceProperties)
|
|
645 |
# backPropertyInstance = serializeInstance(
|
|
646 |
# actor, backfaceProperties, backfacePropId, context, depth + 1)
|
|
647 |
# if backPropertyInstance:
|
|
648 |
# instance['dependencies'].append(backPropertyInstance)
|
|
649 |
# instance['calls'].append(['setBackfaceProperty', [wrapId(backfacePropId)]])
|
|
650 |
|
|
651 | 7 |
instance['properties'].update({ |
652 |
# vtkActor
|
|
653 |
'forceOpaque': actor.GetForceOpaque(), |
|
654 |
'forceTranslucent': actor.GetForceTranslucent() |
|
655 |
})
|
|
656 |
|
|
657 | 7 |
if actor.IsA('vtkFollower'): |
658 | 7 |
camera = actor.GetCamera() |
659 | 7 |
cameraId = context.getReferenceId(camera) |
660 | 7 |
cameraInstance = serializeInstance( |
661 |
actor, camera, cameraId, context, depth + 1) |
|
662 | 7 |
if cameraInstance: |
663 | 7 |
instance['dependencies'].append(cameraInstance) |
664 | 7 |
instance['calls'].append(['setCamera', [wrapId(cameraId)]]) |
665 |
|
|
666 | 7 |
return instance |
667 |
|
|
668 |
# -----------------------------------------------------------------------------
|
|
669 |
|
|
670 |
|
|
671 | 7 |
def genericMapperSerializer(parent, mapper, mapperId, context, depth): |
672 |
# This kind of mapper requires us to get 2 items: input data and lookup
|
|
673 |
# table
|
|
674 | 7 |
dataObject = None |
675 | 7 |
dataObjectInstance = None |
676 | 7 |
lookupTableInstance = None |
677 | 7 |
calls = [] |
678 | 7 |
dependencies = [] |
679 |
|
|
680 | 7 |
if hasattr(mapper, 'GetInputDataObject'): |
681 | 7 |
dataObject = mapper.GetInputDataObject(0, 0) |
682 |
else: |
|
683 |
if context.debugAll: |
|
684 |
print('This mapper does not have GetInputDataObject method') |
|
685 |
|
|
686 | 7 |
if dataObject: |
687 | 7 |
dataObjectId = '%s-dataset' % mapperId |
688 | 7 |
if parent.IsA('vtkActor') and not mapper.IsA('vtkTexture'): |
689 |
# vtk-js actors can render only surfacic datasets
|
|
690 |
# => we ensure to convert the dataset in polydata
|
|
691 | 7 |
dataObjectInstance = mergeToPolydataSerializer( |
692 |
mapper, dataObject, dataObjectId, context, depth + 1) |
|
693 |
else: |
|
694 | 7 |
dataObjectInstance = serializeInstance( |
695 |
mapper, dataObject, dataObjectId, context, depth + 1) |
|
696 | 7 |
if dataObjectInstance: |
697 | 7 |
dependencies.append(dataObjectInstance) |
698 | 7 |
calls.append(['setInputData', [wrapId(dataObjectId)]]) |
699 |
|
|
700 | 7 |
lookupTable = None |
701 |
|
|
702 | 7 |
if hasattr(mapper, 'GetLookupTable'): |
703 | 7 |
lookupTable = mapper.GetLookupTable() |
704 | 7 |
elif parent.IsA('vtkActor'): |
705 |
if context.debugAll: |
|
706 |
print('This mapper actor not have GetLookupTable method') |
|
707 |
|
|
708 | 7 |
if lookupTable: |
709 | 7 |
lookupTableId = context.getReferenceId(lookupTable) |
710 | 7 |
lookupTableInstance = serializeInstance( |
711 |
mapper, lookupTable, lookupTableId, context, depth + 1) |
|
712 | 7 |
if lookupTableInstance: |
713 | 7 |
dependencies.append(lookupTableInstance) |
714 | 7 |
calls.append(['setLookupTable', [wrapId(lookupTableId)]]) |
715 |
|
|
716 | 7 |
if dataObjectInstance: |
717 | 7 |
return { |
718 |
'parent': context.getReferenceId(parent), |
|
719 |
'id': mapperId, |
|
720 |
'properties': {}, |
|
721 |
'calls': calls, |
|
722 |
'dependencies': dependencies |
|
723 |
}
|
|
724 |
|
|
725 |
# -----------------------------------------------------------------------------
|
|
726 |
|
|
727 |
|
|
728 | 7 |
def genericPolyDataMapperSerializer(parent, mapper, mapperId, context, depth): |
729 | 7 |
instance = genericMapperSerializer(parent, mapper, mapperId, context, depth) |
730 |
|
|
731 | 7 |
if not instance: return |
732 |
|
|
733 | 7 |
instance['type'] = mapper.GetClassName() |
734 | 7 |
instance['properties'].update({ |
735 |
'resolveCoincidentTopology': mapper.GetResolveCoincidentTopology(), |
|
736 |
'renderTime': mapper.GetRenderTime(), |
|
737 |
'arrayAccessMode': 1, # since we can't set mapper arrayId on vtkjs, we force acess mode by name and use retrieve name function |
|
738 |
'scalarRange': mapper.GetScalarRange(), |
|
739 |
'useLookupTableScalarRange': 1 if mapper.GetUseLookupTableScalarRange() else 0, |
|
740 |
'scalarVisibility': mapper.GetScalarVisibility(), |
|
741 |
'colorByArrayName': retrieveArrayName(instance, mapper.GetScalarMode()), |
|
742 |
'colorMode': mapper.GetColorMode(), |
|
743 |
'scalarMode': mapper.GetScalarMode(), |
|
744 |
'interpolateScalarsBeforeMapping': 1 if mapper.GetInterpolateScalarsBeforeMapping() else 0 |
|
745 |
})
|
|
746 | 7 |
return instance |
747 |
|
|
748 |
# -----------------------------------------------------------------------------
|
|
749 |
|
|
750 |
|
|
751 | 7 |
def genericVolumeMapperSerializer(parent, mapper, mapperId, context, depth): |
752 | 7 |
instance = genericMapperSerializer(parent, mapper, mapperId, context, depth) |
753 |
|
|
754 | 7 |
if not instance: return |
755 |
|
|
756 | 7 |
imageSampleDistance = ( |
757 |
mapper.GetImageSampleDistance() |
|
758 |
if hasattr(mapper, 'GetImageSampleDistance') |
|
759 |
else 1 |
|
760 |
)
|
|
761 | 7 |
instance['type'] = mapper.GetClassName() |
762 | 7 |
instance['properties'].update({ |
763 |
'sampleDistance': mapper.GetSampleDistance(), |
|
764 |
'imageSampleDistance': imageSampleDistance, |
|
765 |
# 'maximumSamplesPerRay',
|
|
766 |
'autoAdjustSampleDistances': mapper.GetAutoAdjustSampleDistances(), |
|
767 |
'blendMode': mapper.GetBlendMode(), |
|
768 |
})
|
|
769 | 7 |
return instance |
770 |
|
|
771 |
# -----------------------------------------------------------------------------
|
|
772 |
|
|
773 |
|
|
774 | 7 |
def textureSerializer(parent, texture, textureId, context, depth): |
775 | 7 |
instance = genericMapperSerializer(parent, texture, textureId, context, depth) |
776 |
|
|
777 | 7 |
if not instance: return |
778 |
|
|
779 | 7 |
instance['type'] = texture.GetClassName() |
780 | 7 |
instance['properties'].update({ |
781 |
'interpolate': texture.GetInterpolate(), |
|
782 |
'repeat': texture.GetRepeat(), |
|
783 |
'edgeClamp': texture.GetEdgeClamp(), |
|
784 |
})
|
|
785 | 7 |
return instance |
786 |
|
|
787 |
# -----------------------------------------------------------------------------
|
|
788 |
|
|
789 |
|
|
790 | 7 |
def imageSliceMapperSerializer(parent, mapper, mapperId, context, depth): |
791 |
# On vtkjs side : vtkImageMapper connected to a vtkImageReslice filter
|
|
792 |
|
|
793 |
instance = genericMapperSerializer(parent, mapper, mapperId, context, depth) |
|
794 |
|
|
795 |
if not instance: return |
|
796 |
|
|
797 |
instance['type'] = mapper.GetClassName() |
|
798 |
|
|
799 |
return instance |
|
800 |
|
|
801 |
# -----------------------------------------------------------------------------
|
|
802 |
|
|
803 |
|
|
804 | 7 |
def lookupTableSerializer(parent, lookupTable, lookupTableId, context, depth): |
805 |
# No children in this case, so no additions to bindings and return empty list
|
|
806 |
# But we do need to add instance
|
|
807 | 7 |
arrays = [] |
808 | 7 |
lookupTableRange = lookupTable.GetRange() |
809 |
|
|
810 | 7 |
lookupTableHueRange = [0.5, 0] |
811 | 7 |
if hasattr(lookupTable, 'GetHueRange'): |
812 | 7 |
try: |
813 | 7 |
lookupTable.GetHueRange(lookupTableHueRange) |
814 | 7 |
except Exception: |
815 | 7 |
pass
|
816 |
|
|
817 | 7 |
lutSatRange = lookupTable.GetSaturationRange() |
818 |
# lutAlphaRange = lookupTable.GetAlphaRange()
|
|
819 | 7 |
if lookupTable.GetTable(): |
820 | 7 |
arrayMeta = getArrayDescription(lookupTable.GetTable(), context) |
821 | 7 |
if arrayMeta: |
822 | 7 |
arrayMeta['registration'] = 'setTable' |
823 | 7 |
arrays.append(arrayMeta) |
824 |
|
|
825 | 7 |
return { |
826 |
'parent': context.getReferenceId(parent), |
|
827 |
'id': lookupTableId, |
|
828 |
'type': lookupTable.GetClassName(), |
|
829 |
'properties': { |
|
830 |
'numberOfColors': lookupTable.GetNumberOfColors(), |
|
831 |
'valueRange': lookupTableRange, |
|
832 |
'range': lookupTableRange, |
|
833 |
'hueRange': lookupTableHueRange, |
|
834 |
# 'alphaRange': lutAlphaRange, # Causes weird rendering artifacts on client
|
|
835 |
'saturationRange': lutSatRange, |
|
836 |
'nanColor': lookupTable.GetNanColor(), |
|
837 |
'belowRangeColor': lookupTable.GetBelowRangeColor(), |
|
838 |
'aboveRangeColor': lookupTable.GetAboveRangeColor(), |
|
839 |
'useAboveRangeColor': True if lookupTable.GetUseAboveRangeColor() else False, |
|
840 |
'useBelowRangeColor': True if lookupTable.GetUseBelowRangeColor() else False, |
|
841 |
'alpha': lookupTable.GetAlpha(), |
|
842 |
'vectorSize': lookupTable.GetVectorSize(), |
|
843 |
'vectorComponent': lookupTable.GetVectorComponent(), |
|
844 |
'vectorMode': lookupTable.GetVectorMode(), |
|
845 |
'indexedLookup': lookupTable.GetIndexedLookup(), |
|
846 |
},
|
|
847 |
'arrays': arrays, |
|
848 |
}
|
|
849 |
|
|
850 |
# -----------------------------------------------------------------------------
|
|
851 |
|
|
852 |
|
|
853 | 7 |
def lookupTableToColorTransferFunction(lookupTable): |
854 |
dataTable = lookupTable.GetTable() |
|
855 |
table = dataTableToList(dataTable) |
|
856 |
if table: |
|
857 |
ctf = vtkColorTransferFunction() |
|
858 |
tableRange = lookupTable.GetTableRange() |
|
859 |
points = linspace(*tableRange, num=len(table)) |
|
860 |
for x, rgba in zip(points, table): |
|
861 |
ctf.AddRGBPoint(x, *[x/255 for x in rgba[:3]]) |
|
862 |
return ctf |
|
863 |
|
|
864 |
# -----------------------------------------------------------------------------
|
|
865 |
|
|
866 |
|
|
867 | 7 |
def lookupTableSerializer2(parent, lookupTable, lookupTableId, context, depth): |
868 |
ctf = lookupTableToColorTransferFunction(lookupTable) |
|
869 |
if ctf: |
|
870 |
return colorTransferFunctionSerializer(parent, ctf, lookupTableId, context, depth) |
|
871 |
|
|
872 |
# -----------------------------------------------------------------------------
|
|
873 |
|
|
874 |
|
|
875 | 7 |
def propertySerializer(parent, propObj, propObjId, context, depth): |
876 | 7 |
representation = propObj.GetRepresentation() if hasattr( |
877 |
propObj, 'GetRepresentation') else 2 |
|
878 | 7 |
colorToUse = propObj.GetDiffuseColor() if hasattr( |
879 |
propObj, 'GetDiffuseColor') else [1, 1, 1] |
|
880 | 7 |
if representation == 1 and hasattr(propObj, 'GetColor'): |
881 |
colorToUse = propObj.GetColor() |
|
882 |
|
|
883 | 7 |
return { |
884 |
'parent': context.getReferenceId(parent), |
|
885 |
'id': propObjId, |
|
886 |
'type': propObj.GetClassName(), |
|
887 |
'properties': { |
|
888 |
'representation': representation, |
|
889 |
'diffuseColor': colorToUse, |
|
890 |
'color': propObj.GetColor(), |
|
891 |
'ambientColor': propObj.GetAmbientColor(), |
|
892 |
'specularColor': propObj.GetSpecularColor(), |
|
893 |
'edgeColor': propObj.GetEdgeColor(), |
|
894 |
'ambient': propObj.GetAmbient(), |
|
895 |
'diffuse': propObj.GetDiffuse(), |
|
896 |
'specular': propObj.GetSpecular(), |
|
897 |
'specularPower': propObj.GetSpecularPower(), |
|
898 |
'opacity': propObj.GetOpacity(), |
|
899 |
'interpolation': propObj.GetInterpolation(), |
|
900 |
'edgeVisibility': 1 if propObj.GetEdgeVisibility() else 0, |
|
901 |
'backfaceCulling': 1 if propObj.GetBackfaceCulling() else 0, |
|
902 |
'frontfaceCulling': 1 if propObj.GetFrontfaceCulling() else 0, |
|
903 |
'pointSize': propObj.GetPointSize(), |
|
904 |
'lineWidth': propObj.GetLineWidth(), |
|
905 |
'lighting': 1 if propObj.GetLighting() else 0, |
|
906 |
}
|
|
907 |
}
|
|
908 |
|
|
909 |
# -----------------------------------------------------------------------------
|
|
910 |
|
|
911 | 7 |
def volumePropertySerializer(parent, propObj, propObjId, context, depth): |
912 | 7 |
dependencies = [] |
913 | 7 |
calls = [] |
914 |
# TODO: for the moment only component 0 handle
|
|
915 |
|
|
916 |
#OpactiyFunction
|
|
917 | 7 |
ofun = propObj.GetScalarOpacity() |
918 | 7 |
if ofun: |
919 | 7 |
ofunId = context.getReferenceId(ofun) |
920 | 7 |
ofunInstance = serializeInstance( |
921 |
propObj, ofun, ofunId, context, depth + 1) |
|
922 | 7 |
if ofunInstance: |
923 | 7 |
dependencies.append(ofunInstance) |
924 | 7 |
calls.append(['setScalarOpacity', [0, wrapId(ofunId)]]) |
925 |
|
|
926 |
# ColorTranferFunction
|
|
927 | 7 |
ctfun = propObj.GetRGBTransferFunction() |
928 | 7 |
if ctfun: |
929 | 7 |
ctfunId = context.getReferenceId(ctfun) |
930 | 7 |
ctfunInstance = serializeInstance( |
931 |
propObj, ctfun, ctfunId, context, depth + 1) |
|
932 | 7 |
if ctfunInstance: |
933 | 7 |
dependencies.append(ctfunInstance) |
934 | 7 |
calls.append(['setRGBTransferFunction', [0, wrapId(ctfunId)]]) |
935 |
|
|
936 | 7 |
calls += [ |
937 |
['setScalarOpacityUnitDistance', [0, propObj.GetScalarOpacityUnitDistance(0)]], |
|
938 |
['setComponentWeight', [0, propObj.GetComponentWeight(0)]], |
|
939 |
['setUseGradientOpacity', [0, int(not propObj.GetDisableGradientOpacity())]], |
|
940 |
]
|
|
941 |
|
|
942 | 7 |
return { |
943 |
'parent': context.getReferenceId(parent), |
|
944 |
'id': propObjId, |
|
945 |
'type': propObj.GetClassName(), |
|
946 |
'properties': { |
|
947 |
'independentComponents': propObj.GetIndependentComponents(), |
|
948 |
'interpolationType': propObj.GetInterpolationType(), |
|
949 |
'ambient': propObj.GetAmbient(), |
|
950 |
'diffuse': propObj.GetDiffuse(), |
|
951 |
'shade': propObj.GetShade(), |
|
952 |
'specular': propObj.GetSpecular(0), |
|
953 |
'specularPower': propObj.GetSpecularPower(), |
|
954 |
},
|
|
955 |
'dependencies': dependencies, |
|
956 |
'calls': calls, |
|
957 |
}
|
|
958 |
|
|
959 |
# -----------------------------------------------------------------------------
|
|
960 |
|
|
961 |
|
|
962 | 7 |
def imagePropertySerializer(parent, propObj, propObjId, context, depth): |
963 |
calls = [] |
|
964 |
dependencies = [] |
|
965 |
|
|
966 |
lookupTable = propObj.GetLookupTable() |
|
967 |
if lookupTable: |
|
968 |
ctfun = lookupTableToColorTransferFunction(lookupTable) |
|
969 |
ctfunId = context.getReferenceId(ctfun) |
|
970 |
ctfunInstance = serializeInstance( |
|
971 |
propObj, ctfun, ctfunId, context, depth + 1) |
|
972 |
if ctfunInstance: |
|
973 |
dependencies.append(ctfunInstance) |
|
974 |
calls.append(['setRGBTransferFunction', [wrapId(ctfunId)]]) |
|
975 |
|
|
976 |
return { |
|
977 |
'parent': context.getReferenceId(parent), |
|
978 |
'id': propObjId, |
|
979 |
'type': propObj.GetClassName(), |
|
980 |
'properties': { |
|
981 |
'interpolationType': propObj.GetInterpolationType(), |
|
982 |
'colorWindow': propObj.GetColorWindow(), |
|
983 |
'colorLevel': propObj.GetColorLevel(), |
|
984 |
'ambient': propObj.GetAmbient(), |
|
985 |
'diffuse': propObj.GetDiffuse(), |
|
986 |
'opacity': propObj.GetOpacity(), |
|
987 |
},
|
|
988 |
'dependencies': dependencies, |
|
989 |
'calls': calls, |
|
990 |
}
|
|
991 |
|
|
992 |
# -----------------------------------------------------------------------------
|
|
993 |
|
|
994 |
|
|
995 | 7 |
def imageDataSerializer(parent, dataset, datasetId, context, depth): |
996 | 7 |
datasetType = dataset.GetClassName() |
997 |
|
|
998 | 7 |
if hasattr(dataset, 'GetDirectionMatrix'): |
999 | 7 |
direction = [dataset.GetDirectionMatrix().GetElement(0, i) |
1000 |
for i in range(9)] |
|
1001 |
else: |
|
1002 |
direction = [1, 0, 0, |
|
1003 |
0, 1, 0, |
|
1004 |
0, 0, 1] |
|
1005 |
|
|
1006 |
# Extract dataset fields
|
|
1007 | 7 |
arrays = [] |
1008 | 7 |
extractRequiredFields(arrays, parent, dataset, context) |
1009 |
|
|
1010 | 7 |
return { |
1011 |
'parent': context.getReferenceId(parent), |
|
1012 |
'id': datasetId, |
|
1013 |
'type': datasetType, |
|
1014 |
'properties': { |
|
1015 |
'spacing': dataset.GetSpacing(), |
|
1016 |
'origin': dataset.GetOrigin(), |
|
1017 |
'dimensions': dataset.GetDimensions(), |
|
1018 |
'direction': direction, |
|
1019 |
},
|
|
1020 |
'arrays': arrays |
|
1021 |
}
|
|
1022 |
|
|
1023 |
# -----------------------------------------------------------------------------
|
|
1024 |
|
|
1025 |
|
|
1026 | 7 |
def polydataSerializer(parent, dataset, datasetId, context, depth): |
1027 | 7 |
datasetType = dataset.GetClassName() |
1028 |
|
|
1029 | 7 |
if dataset and dataset.GetPoints(): |
1030 | 7 |
properties = {} |
1031 |
|
|
1032 |
# Points
|
|
1033 | 7 |
points = getArrayDescription(dataset.GetPoints().GetData(), context) |
1034 | 7 |
points['vtkClass'] = 'vtkPoints' |
1035 | 7 |
properties['points'] = points |
1036 |
|
|
1037 |
# Verts
|
|
1038 | 7 |
if dataset.GetVerts() and dataset.GetVerts().GetData().GetNumberOfTuples() > 0: |
1039 |
_verts = getArrayDescription(dataset.GetVerts().GetData(), context) |
|
1040 |
properties['verts'] = _verts |
|
1041 |
properties['verts']['vtkClass'] = 'vtkCellArray' |
|
1042 |
|
|
1043 |
# Lines
|
|
1044 | 7 |
if dataset.GetLines() and dataset.GetLines().GetData().GetNumberOfTuples() > 0: |
1045 |
_lines = getArrayDescription(dataset.GetLines().GetData(), context) |
|
1046 |
properties['lines'] = _lines |
|
1047 |
properties['lines']['vtkClass'] = 'vtkCellArray' |
|
1048 |
|
|
1049 |
# Polys
|
|
1050 | 7 |
if dataset.GetPolys() and dataset.GetPolys().GetData().GetNumberOfTuples() > 0: |
1051 | 7 |
_polys = getArrayDescription(dataset.GetPolys().GetData(), context) |
1052 | 7 |
properties['polys'] = _polys |
1053 | 7 |
properties['polys']['vtkClass'] = 'vtkCellArray' |
1054 |
|
|
1055 |
# Strips
|
|
1056 | 7 |
if dataset.GetStrips() and dataset.GetStrips().GetData().GetNumberOfTuples() > 0: |
1057 |
_strips = getArrayDescription( |
|
1058 |
dataset.GetStrips().GetData(), context) |
|
1059 |
properties['strips'] = _strips |
|
1060 |
properties['strips']['vtkClass'] = 'vtkCellArray' |
|
1061 |
|
|
1062 |
# Fields
|
|
1063 | 7 |
properties['fields'] = [] |
1064 | 7 |
extractRequiredFields(properties['fields'], parent, dataset, context) |
1065 |
|
|
1066 | 7 |
return { |
1067 |
'parent': context.getReferenceId(parent), |
|
1068 |
'id': datasetId, |
|
1069 |
'type': datasetType, |
|
1070 |
'properties': properties |
|
1071 |
}
|
|
1072 |
|
|
1073 |
if context.debugAll: |
|
1074 |
print('This dataset has no points!') |
|
1075 |
|
|
1076 |
# -----------------------------------------------------------------------------
|
|
1077 |
|
|
1078 |
|
|
1079 | 7 |
def mergeToPolydataSerializer(parent, dataObject, dataObjectId, context, depth): |
1080 | 7 |
dataset = None |
1081 |
|
|
1082 | 7 |
if dataObject.IsA('vtkCompositeDataSet'): |
1083 | 7 |
gf = vtkCompositeDataGeometryFilter() |
1084 | 7 |
gf.SetInputData(dataObject) |
1085 | 7 |
gf.Update() |
1086 | 7 |
dataset = gf.GetOutput() |
1087 | 7 |
elif (dataObject.IsA('vtkUnstructuredGrid') or |
1088 |
dataObject.IsA('vtkStructuredGrid') or |
|
1089 |
dataObject.IsA('vtkImageData')): |
|
1090 | 7 |
gf = vtkGeometryFilter() |
1091 | 7 |
gf.SetInputData(dataObject) |
1092 | 7 |
gf.Update() |
1093 | 7 |
dataset = gf.GetOutput() |
1094 |
else: |
|
1095 | 7 |
dataset = parent.GetInput() |
1096 |
|
|
1097 | 7 |
return polydataSerializer(parent, dataset, dataObjectId, context, depth) |
1098 |
|
|
1099 |
# -----------------------------------------------------------------------------
|
|
1100 |
|
|
1101 |
|
|
1102 | 7 |
def colorTransferFunctionSerializer(parent, instance, objId, context, depth): |
1103 | 7 |
nodes = [] |
1104 |
|
|
1105 | 7 |
for i in range(instance.GetSize()): |
1106 |
# x, r, g, b, midpoint, sharpness
|
|
1107 | 7 |
node = [0, 0, 0, 0, 0, 0] |
1108 | 7 |
instance.GetNodeValue(i, node) |
1109 | 7 |
nodes.append(node) |
1110 |
|
|
1111 | 7 |
return { |
1112 |
'parent': context.getReferenceId(parent), |
|
1113 |
'id': objId, |
|
1114 |
'type': instance.GetClassName(), |
|
1115 |
'properties': { |
|
1116 |
'clamping': 1 if instance.GetClamping() else 0, |
|
1117 |
'colorSpace': instance.GetColorSpace(), |
|
1118 |
'hSVWrap': 1 if instance.GetHSVWrap() else 0, |
|
1119 |
# 'nanColor': instance.GetNanColor(), # Breaks client
|
|
1120 |
# 'belowRangeColor': instance.GetBelowRangeColor(), # Breaks client
|
|
1121 |
# 'aboveRangeColor': instance.GetAboveRangeColor(), # Breaks client
|
|
1122 |
# 'useAboveRangeColor': 1 if instance.GetUseAboveRangeColor() else 0,
|
|
1123 |
# 'useBelowRangeColor': 1 if instance.GetUseBelowRangeColor() else 0,
|
|
1124 |
'allowDuplicateScalars': 1 if instance.GetAllowDuplicateScalars() else 0, |
|
1125 |
'alpha': instance.GetAlpha(), |
|
1126 |
'vectorComponent': instance.GetVectorComponent(), |
|
1127 |
'vectorSize': instance.GetVectorSize(), |
|
1128 |
'vectorMode': instance.GetVectorMode(), |
|
1129 |
'indexedLookup': instance.GetIndexedLookup(), |
|
1130 |
'nodes': nodes |
|
1131 |
}
|
|
1132 |
}
|
|
1133 |
|
|
1134 |
# -----------------------------------------------------------------------------
|
|
1135 |
|
|
1136 |
|
|
1137 | 7 |
def piecewiseFunctionSerializer(parent, instance, objId, context, depth): |
1138 | 7 |
nodes = [] |
1139 |
|
|
1140 | 7 |
for i in range(instance.GetSize()): |
1141 |
# x, y, midpoint, sharpness
|
|
1142 | 7 |
node = [0, 0, 0, 0] |
1143 | 7 |
instance.GetNodeValue(i, node) |
1144 | 7 |
nodes.append(node) |
1145 |
|
|
1146 | 7 |
return { |
1147 |
'parent': context.getReferenceId(parent), |
|
1148 |
'id': objId, |
|
1149 |
'type': instance.GetClassName(), |
|
1150 |
'properties': { |
|
1151 |
'clamping': instance.GetClamping(), |
|
1152 |
'allowDuplicateScalars': instance.GetAllowDuplicateScalars(), |
|
1153 |
'nodes': nodes, |
|
1154 |
}
|
|
1155 |
}
|
|
1156 |
# -----------------------------------------------------------------------------
|
|
1157 |
|
|
1158 |
|
|
1159 | 7 |
def rendererSerializer(parent, instance, objId, context, depth): |
1160 | 7 |
dependencies = [] |
1161 | 7 |
viewPropIds = [] |
1162 | 7 |
calls = [] |
1163 |
|
|
1164 |
# Camera
|
|
1165 | 7 |
camera = instance.GetActiveCamera() |
1166 | 7 |
cameraId = context.getReferenceId(camera) |
1167 | 7 |
cameraInstance = serializeInstance( |
1168 |
instance, camera, cameraId, context, depth + 1) |
|
1169 | 7 |
if cameraInstance: |
1170 | 7 |
dependencies.append(cameraInstance) |
1171 | 7 |
calls.append(['setActiveCamera', [wrapId(cameraId)]]) |
1172 |
|
|
1173 |
# View prop as representation containers
|
|
1174 | 7 |
viewPropCollection = instance.GetViewProps() |
1175 | 7 |
for rpIdx in range(viewPropCollection.GetNumberOfItems()): |
1176 | 7 |
viewProp = viewPropCollection.GetItemAsObject(rpIdx) |
1177 | 7 |
viewPropId = context.getReferenceId(viewProp) |
1178 |
|
|
1179 | 7 |
viewPropInstance = serializeInstance( |
1180 |
instance, viewProp, viewPropId, context, depth + 1) |
|
1181 | 7 |
if viewPropInstance: |
1182 | 7 |
dependencies.append(viewPropInstance) |
1183 | 7 |
viewPropIds.append(viewPropId) |
1184 |
|
|
1185 | 7 |
calls += context.buildDependencyCallList('%s-props' % |
1186 |
objId, viewPropIds, 'addViewProp', 'removeViewProp') |
|
1187 |
|
|
1188 | 7 |
return { |
1189 |
'parent': context.getReferenceId(parent), |
|
1190 |
'id': objId, |
|
1191 |
'type': instance.GetClassName(), |
|
1192 |
'properties': { |
|
1193 |
'background': instance.GetBackground(), |
|
1194 |
'background2': instance.GetBackground2(), |
|
1195 |
'viewport': instance.GetViewport(), |
|
1196 |
# These commented properties do not yet have real setters in vtk.js
|
|
1197 |
# 'gradientBackground': instance.GetGradientBackground(),
|
|
1198 |
# 'aspect': instance.GetAspect(),
|
|
1199 |
# 'pixelAspect': instance.GetPixelAspect(),
|
|
1200 |
# 'ambient': instance.GetAmbient(),
|
|
1201 |
'twoSidedLighting': instance.GetTwoSidedLighting(), |
|
1202 |
'lightFollowCamera': instance.GetLightFollowCamera(), |
|
1203 |
'layer': instance.GetLayer(), |
|
1204 |
'preserveColorBuffer': instance.GetPreserveColorBuffer(), |
|
1205 |
'preserveDepthBuffer': instance.GetPreserveDepthBuffer(), |
|
1206 |
'nearClippingPlaneTolerance': instance.GetNearClippingPlaneTolerance(), |
|
1207 |
'clippingRangeExpansion': instance.GetClippingRangeExpansion(), |
|
1208 |
'useShadows': instance.GetUseShadows(), |
|
1209 |
'useDepthPeeling': instance.GetUseDepthPeeling(), |
|
1210 |
'occlusionRatio': instance.GetOcclusionRatio(), |
|
1211 |
'maximumNumberOfPeels': instance.GetMaximumNumberOfPeels(), |
|
1212 |
'interactive': instance.GetInteractive(), |
|
1213 |
},
|
|
1214 |
'dependencies': dependencies, |
|
1215 |
'calls': calls |
|
1216 |
}
|
|
1217 |
|
|
1218 |
# -----------------------------------------------------------------------------
|
|
1219 |
|
|
1220 |
|
|
1221 | 7 |
def cameraSerializer(parent, instance, objId, context, depth): |
1222 | 7 |
return { |
1223 |
'parent': context.getReferenceId(parent), |
|
1224 |
'id': objId, |
|
1225 |
'type': instance.GetClassName(), |
|
1226 |
'properties': { |
|
1227 |
'focalPoint': instance.GetFocalPoint(), |
|
1228 |
'position': instance.GetPosition(), |
|
1229 |
'viewUp': instance.GetViewUp(), |
|
1230 |
'clippingRange': instance.GetClippingRange(), |
|
1231 |
}
|
|
1232 |
}
|
|
1233 |
|
|
1234 |
# -----------------------------------------------------------------------------
|
|
1235 |
|
|
1236 |
|
|
1237 | 7 |
def renderWindowSerializer(parent, instance, objId, context, depth): |
1238 | 7 |
dependencies = [] |
1239 | 7 |
rendererIds = [] |
1240 |
|
|
1241 | 7 |
rendererCollection = instance.GetRenderers() |
1242 | 7 |
for rIdx in range(rendererCollection.GetNumberOfItems()): |
1243 |
# Grab the next vtkRenderer
|
|
1244 | 7 |
renderer = rendererCollection.GetItemAsObject(rIdx) |
1245 | 7 |
rendererId = context.getReferenceId(renderer) |
1246 | 7 |
rendererInstance = serializeInstance( |
1247 |
instance, renderer, rendererId, context, depth + 1) |
|
1248 | 7 |
if rendererInstance: |
1249 | 7 |
dependencies.append(rendererInstance) |
1250 | 7 |
rendererIds.append(rendererId) |
1251 |
|
|
1252 | 7 |
calls = context.buildDependencyCallList( |
1253 |
objId, rendererIds, 'addRenderer', 'removeRenderer') |
|
1254 |
|
|
1255 | 7 |
return { |
1256 |
'parent': context.getReferenceId(parent), |
|
1257 |
'id': objId, |
|
1258 |
'type': instance.GetClassName(), |
|
1259 |
'properties': { |
|
1260 |
'numberOfLayers': instance.GetNumberOfLayers() |
|
1261 |
},
|
|
1262 |
'dependencies': dependencies, |
|
1263 |
'calls': calls, |
|
1264 |
'mtime': instance.GetMTime(), |
|
1265 |
}
|
Read our documentation on viewing source code .