1411 lines
49 KiB
Python
1411 lines
49 KiB
Python
import io
|
|
import logging
|
|
import struct
|
|
import time
|
|
import zipfile
|
|
|
|
from vtkmodules.web import (
|
|
base64Encode,
|
|
hashDataArray,
|
|
getJSArrayType,
|
|
arrayTypesMapping,
|
|
getReferenceId,
|
|
)
|
|
|
|
from vtkmodules.vtkCommonCore import vtkTypeUInt32Array
|
|
from vtkmodules.vtkFiltersGeometry import vtkCompositeDataGeometryFilter
|
|
from vtkmodules.vtkFiltersGeometry import vtkDataSetSurfaceFilter
|
|
from vtkmodules.vtkRenderingCore import vtkColorTransferFunction
|
|
|
|
logger = logging.getLogger(__name__)
|
|
# Always DEBUG level for this logger. Users can change this
|
|
logger.setLevel(logging.DEBUG)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Array helpers
|
|
# -----------------------------------------------------------------------------
|
|
|
|
def zipCompression(name, data):
|
|
with io.BytesIO() as in_memory:
|
|
with zipfile.ZipFile(in_memory, mode="w") as zf:
|
|
zf.writestr("data/%s" % name, data, zipfile.ZIP_DEFLATED)
|
|
in_memory.seek(0)
|
|
return in_memory.read()
|
|
|
|
|
|
def dataTableToList(dataTable):
|
|
dataType = arrayTypesMapping[dataTable.GetDataType()]
|
|
elementSize = struct.calcsize(dataType)
|
|
nbValues = dataTable.GetNumberOfValues()
|
|
nbComponents = dataTable.GetNumberOfComponents()
|
|
nbytes = elementSize * nbValues
|
|
if dataType != " ":
|
|
with io.BytesIO(memoryview(dataTable)) as stream:
|
|
data = list(struct.unpack(dataType * nbValues, stream.read(nbytes)))
|
|
return [
|
|
data[idx * nbComponents : (idx + 1) * nbComponents]
|
|
for idx in range(nbValues // nbComponents)
|
|
]
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def linspace(start, stop, num):
|
|
delta = (stop - start) / (num - 1)
|
|
return [start + i * delta for i in range(num)]
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Convenience class for caching data arrays, storing computed sha sums, keeping
|
|
# track of valid actors, etc...
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
class SynchronizationContext:
|
|
def __init__(self):
|
|
self.dataArrayCache = {}
|
|
self.lastDependenciesMapping = {}
|
|
self.ingoreLastDependencies = False
|
|
|
|
def setIgnoreLastDependencies(self, force):
|
|
self.ingoreLastDependencies = force
|
|
|
|
def cacheDataArray(self, pMd5, data):
|
|
self.dataArrayCache[pMd5] = data
|
|
|
|
def getCachedDataArray(self, pMd5, binary=False, compression=False):
|
|
cacheObj = self.dataArrayCache[pMd5]
|
|
array = cacheObj["array"]
|
|
cacheTime = cacheObj["mTime"]
|
|
|
|
if cacheTime != array.GetMTime():
|
|
logger.debug(" ***** ERROR: you asked for an old cache key! ***** ")
|
|
|
|
if array.GetDataType() == 12:
|
|
# IdType need to be converted to Uint32
|
|
arraySize = array.GetNumberOfTuples() * array.GetNumberOfComponents()
|
|
newArray = vtkTypeUInt32Array()
|
|
newArray.SetNumberOfTuples(arraySize)
|
|
for i in range(arraySize):
|
|
newArray.SetValue(i, -1 if array.GetValue(i) < 0 else array.GetValue(i))
|
|
pBuffer = memoryview(newArray)
|
|
else:
|
|
pBuffer = memoryview(array)
|
|
|
|
if binary:
|
|
# Convert the vtkUnsignedCharArray into a bytes object, required by
|
|
# Autobahn websockets
|
|
return (
|
|
pBuffer.tobytes()
|
|
if not compression
|
|
else zipCompression(pMd5, pBuffer.tobytes())
|
|
)
|
|
|
|
return base64Encode(
|
|
pBuffer if not compression else zipCompression(pMd5, pBuffer.tobytes())
|
|
)
|
|
|
|
def checkForArraysToRelease(self, timeWindow=20):
|
|
cutOffTime = time.time() - timeWindow
|
|
shasToDelete = []
|
|
for sha in self.dataArrayCache:
|
|
record = self.dataArrayCache[sha]
|
|
array = record["array"]
|
|
count = array.GetReferenceCount()
|
|
|
|
if count == 1 and record["ts"] < cutOffTime:
|
|
shasToDelete.append(sha)
|
|
|
|
for sha in shasToDelete:
|
|
del self.dataArrayCache[sha]
|
|
|
|
def getLastDependencyList(self, idstr):
|
|
lastDeps = []
|
|
if idstr in self.lastDependenciesMapping and not self.ingoreLastDependencies:
|
|
lastDeps = self.lastDependenciesMapping[idstr]
|
|
return lastDeps
|
|
|
|
def setNewDependencyList(self, idstr, depList):
|
|
self.lastDependenciesMapping[idstr] = depList
|
|
|
|
def buildDependencyCallList(self, idstr, newList, addMethod, removeMethod):
|
|
oldList = self.getLastDependencyList(idstr)
|
|
|
|
calls = []
|
|
calls += [[addMethod, [wrapId(x)]] for x in newList if x not in oldList]
|
|
calls += [[removeMethod, [wrapId(x)]] for x in oldList if x not in newList]
|
|
|
|
self.setNewDependencyList(idstr, newList)
|
|
return calls
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Global variables
|
|
# -----------------------------------------------------------------------------
|
|
|
|
SERIALIZERS = {}
|
|
JS_CLASS_MAPPING = {}
|
|
context = None
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Global API
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def registerInstanceSerializer(name, method):
|
|
global SERIALIZERS
|
|
SERIALIZERS[name] = method
|
|
|
|
def registerJSClass(vtk_class, js_class):
|
|
global JS_CLASS_MAPPING
|
|
JS_CLASS_MAPPING[vtk_class] = js_class
|
|
|
|
def class_name(vtk_obj):
|
|
vtk_class = vtk_obj.GetClassName()
|
|
if vtk_class in JS_CLASS_MAPPING:
|
|
return JS_CLASS_MAPPING[vtk_class]
|
|
|
|
return vtk_class
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def serializeInstance(parent, instance, instanceId, context, depth):
|
|
instanceType = class_name(instance)
|
|
serializer = SERIALIZERS[instanceType] if instanceType in SERIALIZERS else None
|
|
|
|
if serializer:
|
|
return serializer(parent, instance, instanceId, context, depth)
|
|
|
|
logger.error(f"!!!No serializer for {instanceType} with id {instanceId}")
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def initializeSerializers():
|
|
# Actors/viewProps
|
|
registerInstanceSerializer("vtkActor", genericActorSerializer)
|
|
registerInstanceSerializer("vtkOpenGLActor", genericActorSerializer)
|
|
registerInstanceSerializer("vtkPVLODActor", genericActorSerializer)
|
|
|
|
# Volume/viewProps
|
|
registerInstanceSerializer("vtkVolume", genericVolumeSerializer)
|
|
|
|
# Mappers
|
|
registerInstanceSerializer("vtkMapper", genericMapperSerializer)
|
|
registerInstanceSerializer("vtkDataSetMapper", genericMapperSerializer)
|
|
registerInstanceSerializer("vtkPolyDataMapper", genericMapperSerializer)
|
|
registerInstanceSerializer("vtkImageDataMapper", genericMapperSerializer)
|
|
registerInstanceSerializer("vtkOpenGLPolyDataMapper", genericMapperSerializer)
|
|
registerInstanceSerializer("vtkCompositePolyDataMapper2", genericMapperSerializer)
|
|
registerJSClass("vtkPolyDataMapper", "vtkMapper")
|
|
registerJSClass("vtkDataSetMapper", "vtkMapper")
|
|
registerJSClass("vtkOpenGLPolyDataMapper", "vtkMapper")
|
|
registerJSClass("vtkCompositePolyDataMapper2", "vtkMapper")
|
|
|
|
registerInstanceSerializer("vtkVolumeMapper", genericVolumeMapperSerializer)
|
|
registerInstanceSerializer("vtkFixedPointVolumeRayCastMapper", genericVolumeMapperSerializer)
|
|
registerJSClass("vtkFixedPointVolumeRayCastMapper", "vtkVolumeMapper")
|
|
|
|
# LookupTables/TransferFunctions
|
|
registerInstanceSerializer("vtkLookupTable", lookupTableSerializer2)
|
|
registerInstanceSerializer(
|
|
"vtkPVDiscretizableColorTransferFunction", discretizableColorTransferFunctionSerializer
|
|
)
|
|
registerInstanceSerializer(
|
|
"vtkColorTransferFunction", colorTransferFunctionSerializer
|
|
)
|
|
registerInstanceSerializer("vtkPiecewiseFunction", pwfSerializer)
|
|
|
|
# Textures
|
|
registerInstanceSerializer("vtkTexture", textureSerializer)
|
|
registerInstanceSerializer("vtkOpenGLTexture", textureSerializer)
|
|
|
|
# Property
|
|
registerInstanceSerializer("vtkProperty", propertySerializer)
|
|
registerInstanceSerializer("vtkOpenGLProperty", propertySerializer)
|
|
|
|
# VolumeProperty
|
|
registerInstanceSerializer("vtkVolumeProperty", volumePropertySerializer)
|
|
|
|
# Datasets
|
|
registerInstanceSerializer("vtkPolyData", polydataSerializer)
|
|
registerInstanceSerializer("vtkImageData", imagedataSerializer)
|
|
registerInstanceSerializer("vtkUnstructuredGrid", mergeToPolydataSerializer)
|
|
registerInstanceSerializer("vtkMultiBlockDataSet", mergeToPolydataSerializer)
|
|
registerInstanceSerializer("vtkStructuredPoints", imagedataSerializer)
|
|
registerJSClass("vtkStructuredPoints", "vtkImageData")
|
|
|
|
|
|
# RenderWindows
|
|
registerInstanceSerializer("vtkRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkCocoaRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkXOpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkWin32OpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkEGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkOpenVRRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkOpenXRRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkGenericOpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkOSOpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkOpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkIOSRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkExternalOpenGLRenderWindow", renderWindowSerializer)
|
|
registerInstanceSerializer("vtkOffscreenOpenGLRenderWindow", renderWindowSerializer)
|
|
|
|
# Renderers
|
|
registerInstanceSerializer("vtkRenderer", rendererSerializer)
|
|
registerInstanceSerializer("vtkOpenGLRenderer", rendererSerializer)
|
|
|
|
# Cameras
|
|
registerInstanceSerializer("vtkCamera", cameraSerializer)
|
|
registerInstanceSerializer("vtkOpenGLCamera", cameraSerializer)
|
|
|
|
# Lights
|
|
registerInstanceSerializer("vtkLight", lightSerializer)
|
|
registerInstanceSerializer("vtkPVLight", lightSerializer)
|
|
registerInstanceSerializer("vtkOpenGLLight", lightSerializer)
|
|
|
|
# Annotations (ScalarBar/CubeAxes
|
|
registerInstanceSerializer("vtkCubeAxesActor", cubeAxesSerializer)
|
|
registerInstanceSerializer("vtkScalarBarActor", scalarBarActorSerializer)
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Helper functions
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def pad(depth):
|
|
padding = ""
|
|
for _ in range(depth):
|
|
padding += " "
|
|
return padding
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def wrapId(idStr):
|
|
return "instance:${%s}" % idStr
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
dataArrayShaMapping = {}
|
|
|
|
|
|
def digest(array):
|
|
objId = getReferenceId(array)
|
|
|
|
record = None
|
|
if objId in dataArrayShaMapping:
|
|
record = dataArrayShaMapping[objId]
|
|
|
|
if record and record["mtime"] == array.GetMTime():
|
|
return record["sha"]
|
|
|
|
record = {"sha": hashDataArray(array), "mtime": array.GetMTime()}
|
|
|
|
dataArrayShaMapping[objId] = record
|
|
return record["sha"]
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def getRangeInfo(array, component):
|
|
r = array.GetRange(component)
|
|
compRange = {}
|
|
compRange["min"] = r[0]
|
|
compRange["max"] = r[1]
|
|
compRange["component"] = array.GetComponentName(component)
|
|
return compRange
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def getArrayDescription(array, context):
|
|
if not array:
|
|
return None
|
|
|
|
pMd5 = digest(array)
|
|
context.cacheDataArray(
|
|
pMd5, {"array": array, "mTime": array.GetMTime(), "ts": time.time()}
|
|
)
|
|
|
|
root = {}
|
|
root["hash"] = pMd5
|
|
root["vtkClass"] = "vtkDataArray"
|
|
root["name"] = array.GetName()
|
|
root["dataType"] = getJSArrayType(array)
|
|
root["numberOfComponents"] = array.GetNumberOfComponents()
|
|
root["size"] = array.GetNumberOfComponents() * array.GetNumberOfTuples()
|
|
root["ranges"] = []
|
|
if root["numberOfComponents"] > 1:
|
|
for i in range(root["numberOfComponents"]):
|
|
root["ranges"].append(getRangeInfo(array, i))
|
|
root["ranges"].append(getRangeInfo(array, -1))
|
|
else:
|
|
root["ranges"].append(getRangeInfo(array, 0))
|
|
|
|
return root
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def extractRequiredFields(
|
|
extractedFields, parent, dataset, context, requestedFields=["Normals", "TCoords"]
|
|
):
|
|
arrays_to_export = set()
|
|
export_all = "*" in requestedFields
|
|
# Identify arrays to export
|
|
if not export_all:
|
|
# FIXME should evolve and support funky mapper which leverage many arrays
|
|
if parent and parent.IsA("vtkMapper"):
|
|
mapper = parent
|
|
scalarVisibility = mapper.GetScalarVisibility()
|
|
arrayAccessMode = mapper.GetArrayAccessMode()
|
|
colorArrayName = (
|
|
mapper.GetArrayName() if arrayAccessMode == 1 else mapper.GetArrayId()
|
|
)
|
|
# colorMode = mapper.GetColorMode()
|
|
scalarMode = mapper.GetScalarMode()
|
|
if scalarVisibility and scalarMode in (1, 3):
|
|
array_to_export = dataset.GetPointData().GetArray(colorArrayName)
|
|
if array_to_export is None:
|
|
array_to_export = dataset.GetPointData().GetScalars()
|
|
arrays_to_export.add(array_to_export)
|
|
if scalarVisibility and scalarMode in (2, 4):
|
|
array_to_export = dataset.GetCellData().GetArray(colorArrayName)
|
|
if array_to_export is None:
|
|
array_to_export = dataset.GetCellData().GetScalars()
|
|
arrays_to_export.add(array_to_export)
|
|
if scalarVisibility and scalarMode == 0:
|
|
array_to_export = dataset.GetPointData().GetScalars()
|
|
if array_to_export is None:
|
|
array_to_export = dataset.GetCellData().GetScalars()
|
|
arrays_to_export.add(array_to_export)
|
|
|
|
if parent and parent.IsA("vtkTexture") and dataset.GetPointData().GetScalars():
|
|
arrays_to_export.add(dataset.GetPointData().GetScalars())
|
|
|
|
arrays_to_export.update(
|
|
[
|
|
getattr(dataset.GetPointData(), "Get" + requestedField, lambda: None)()
|
|
for requestedField in requestedFields
|
|
]
|
|
)
|
|
|
|
# Browse all arrays
|
|
for location, field_data in [
|
|
("pointData", dataset.GetPointData()),
|
|
("cellData", dataset.GetCellData()),
|
|
]:
|
|
for array_index in range(field_data.GetNumberOfArrays()):
|
|
array = field_data.GetArray(array_index)
|
|
if export_all or array in arrays_to_export:
|
|
arrayMeta = getArrayDescription(array, context)
|
|
if arrayMeta:
|
|
arrayMeta["location"] = location
|
|
attribute = field_data.IsArrayAnAttribute(array_index)
|
|
arrayMeta["registration"] = (
|
|
"set" + field_data.GetAttributeTypeAsString(attribute)
|
|
if attribute >= 0
|
|
else "addArray"
|
|
)
|
|
extractedFields.append(arrayMeta)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Concrete instance serializers
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def genericActorSerializer(parent, actor, actorId, context, depth):
|
|
# This kind of actor has two "children" of interest, a property and a
|
|
# mapper
|
|
actorVisibility = actor.GetVisibility()
|
|
mapperInstance = None
|
|
propertyInstance = None
|
|
calls = []
|
|
dependencies = []
|
|
|
|
if actorVisibility:
|
|
mapper = None
|
|
if not hasattr(actor, "GetMapper"):
|
|
logger.debug("This actor does not have a GetMapper method")
|
|
else:
|
|
mapper = actor.GetMapper()
|
|
|
|
if mapper:
|
|
mapperId = getReferenceId(mapper)
|
|
mapperInstance = serializeInstance(
|
|
actor, mapper, mapperId, context, depth + 1
|
|
)
|
|
if mapperInstance:
|
|
dependencies.append(mapperInstance)
|
|
calls.append(["setMapper", [wrapId(mapperId)]])
|
|
|
|
prop = None
|
|
if hasattr(actor, "GetProperty"):
|
|
prop = actor.GetProperty()
|
|
else:
|
|
logger.debug("This actor does not have a GetProperty method")
|
|
|
|
if prop:
|
|
propId = getReferenceId(prop)
|
|
propertyInstance = serializeInstance(
|
|
actor, prop, propId, context, depth + 1
|
|
)
|
|
if propertyInstance:
|
|
dependencies.append(propertyInstance)
|
|
calls.append(["setProperty", [wrapId(propId)]])
|
|
|
|
# Handle texture if any
|
|
texture = None
|
|
if hasattr(actor, "GetTexture"):
|
|
texture = actor.GetTexture()
|
|
else:
|
|
logger.debug("This actor does not have a GetTexture method")
|
|
|
|
if texture:
|
|
textureId = getReferenceId(texture)
|
|
textureInstance = serializeInstance(
|
|
actor, texture, textureId, context, depth + 1
|
|
)
|
|
if textureInstance:
|
|
dependencies.append(textureInstance)
|
|
calls.append(["addTexture", [wrapId(textureId)]])
|
|
|
|
if actorVisibility == 0 or (mapperInstance and propertyInstance):
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": actorId,
|
|
"type": class_name(actor),
|
|
"properties": {
|
|
# vtkProp
|
|
"visibility": actorVisibility,
|
|
"pickable": actor.GetPickable(),
|
|
"dragable": actor.GetDragable(),
|
|
"useBounds": actor.GetUseBounds(),
|
|
# vtkProp3D
|
|
"origin": actor.GetOrigin(),
|
|
"position": actor.GetPosition(),
|
|
"scale": actor.GetScale(),
|
|
# vtkActor
|
|
"forceOpaque": actor.GetForceOpaque(),
|
|
"forceTranslucent": actor.GetForceTranslucent(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def genericVolumeSerializer(parent, actor, actorId, context, depth):
|
|
# This kind of actor has two "children" of interest, a property and a
|
|
# mapper
|
|
actorVisibility = actor.GetVisibility()
|
|
mapperInstance = None
|
|
propertyInstance = None
|
|
calls = []
|
|
dependencies = []
|
|
|
|
if actorVisibility:
|
|
mapper = None
|
|
if not hasattr(actor, "GetMapper"):
|
|
logger.debug("This actor does not have a GetMapper method")
|
|
else:
|
|
mapper = actor.GetMapper()
|
|
|
|
if mapper:
|
|
mapperId = getReferenceId(mapper)
|
|
mapperInstance = serializeInstance(
|
|
actor, mapper, mapperId, context, depth + 1
|
|
)
|
|
if mapperInstance:
|
|
dependencies.append(mapperInstance)
|
|
calls.append(["setMapper", [wrapId(mapperId)]])
|
|
|
|
prop = None
|
|
if hasattr(actor, "GetProperty"):
|
|
prop = actor.GetProperty()
|
|
else:
|
|
logger.debug("This actor does not have a GetProperty method")
|
|
|
|
if prop:
|
|
propId = getReferenceId(prop)
|
|
propertyInstance = serializeInstance(
|
|
actor, prop, propId, context, depth + 1
|
|
)
|
|
if propertyInstance:
|
|
dependencies.append(propertyInstance)
|
|
calls.append(["setProperty", [wrapId(propId)]])
|
|
|
|
if actorVisibility == 0 or (mapperInstance and propertyInstance):
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": actorId,
|
|
"type": class_name(actor),
|
|
"properties": {
|
|
# vtkProp
|
|
"visibility": actorVisibility,
|
|
"pickable": actor.GetPickable(),
|
|
"dragable": actor.GetDragable(),
|
|
"useBounds": actor.GetUseBounds(),
|
|
# vtkProp3D
|
|
"origin": actor.GetOrigin(),
|
|
"position": actor.GetPosition(),
|
|
"scale": actor.GetScale(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
return None
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def textureSerializer(parent, texture, textureId, context, depth):
|
|
# This kind of mapper requires us to get 2 items: input data and lookup
|
|
# table
|
|
dataObject = None
|
|
dataObjectInstance = None
|
|
calls = []
|
|
dependencies = []
|
|
|
|
if hasattr(texture, "GetInput"):
|
|
dataObject = texture.GetInput()
|
|
else:
|
|
logger.debug("This texture does not have GetInput method")
|
|
|
|
if dataObject:
|
|
dataObjectId = "%s-texture" % textureId
|
|
dataObjectInstance = serializeInstance(
|
|
texture, dataObject, dataObjectId, context, depth + 1
|
|
)
|
|
if dataObjectInstance:
|
|
dependencies.append(dataObjectInstance)
|
|
calls.append(["setInputData", [wrapId(dataObjectId)]])
|
|
|
|
if dataObjectInstance:
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": textureId,
|
|
"type": "vtkTexture",
|
|
"properties": {
|
|
"interpolate": texture.GetInterpolate(),
|
|
"repeat": texture.GetRepeat(),
|
|
"edgeClamp": texture.GetEdgeClamp(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def genericMapperSerializer(parent, mapper, mapperId, context, depth):
|
|
# This kind of mapper requires us to get 2 items: input data and lookup
|
|
# table
|
|
dataObject = None
|
|
dataObjectInstance = None
|
|
lookupTableInstance = None
|
|
calls = []
|
|
dependencies = []
|
|
|
|
if hasattr(mapper, "GetInputDataObject"):
|
|
mapper.GetInputAlgorithm().Update()
|
|
dataObject = mapper.GetInputDataObject(0, 0)
|
|
else:
|
|
logger.debug("This mapper does not have GetInputDataObject method")
|
|
|
|
if dataObject:
|
|
if dataObject.IsA("vtkDataSet"):
|
|
alg = vtkDataSetSurfaceFilter()
|
|
alg.SetInputData(dataObject)
|
|
alg.Update()
|
|
dataObject = alg.GetOutput()
|
|
|
|
dataObjectId = "%s-dataset" % mapperId
|
|
dataObjectInstance = serializeInstance(
|
|
mapper, dataObject, dataObjectId, context, depth + 1
|
|
)
|
|
|
|
if dataObjectInstance:
|
|
dependencies.append(dataObjectInstance)
|
|
calls.append(["setInputData", [wrapId(dataObjectId)]])
|
|
|
|
lookupTable = None
|
|
|
|
if hasattr(mapper, "GetLookupTable"):
|
|
lookupTable = mapper.GetLookupTable()
|
|
else:
|
|
logger.debug("This mapper does not have GetLookupTable method")
|
|
|
|
if lookupTable:
|
|
lookupTableId = getReferenceId(lookupTable)
|
|
lookupTableInstance = serializeInstance(
|
|
mapper, lookupTable, lookupTableId, context, depth + 1
|
|
)
|
|
if lookupTableInstance:
|
|
dependencies.append(lookupTableInstance)
|
|
calls.append(
|
|
["setLookupTable", [wrapId(lookupTableId)]]
|
|
)
|
|
|
|
if dataObjectInstance:
|
|
colorArrayName = (
|
|
mapper.GetArrayName()
|
|
if mapper.GetArrayAccessMode() == 1
|
|
else mapper.GetArrayId()
|
|
)
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": mapperId,
|
|
"type": class_name(mapper),
|
|
"properties": {
|
|
"resolveCoincidentTopology": mapper.GetResolveCoincidentTopology(),
|
|
"renderTime": mapper.GetRenderTime(),
|
|
"arrayAccessMode": mapper.GetArrayAccessMode(),
|
|
"scalarRange": mapper.GetScalarRange(),
|
|
"useLookupTableScalarRange": 1
|
|
if mapper.GetUseLookupTableScalarRange()
|
|
else 0,
|
|
"scalarVisibility": mapper.GetScalarVisibility(),
|
|
"colorByArrayName": colorArrayName,
|
|
"colorMode": mapper.GetColorMode(),
|
|
"scalarMode": mapper.GetScalarMode(),
|
|
"interpolateScalarsBeforeMapping": 1
|
|
if mapper.GetInterpolateScalarsBeforeMapping()
|
|
else 0,
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def genericVolumeMapperSerializer(parent, mapper, mapperId, context, depth):
|
|
# This kind of mapper requires us to get 2 items: input data and lookup
|
|
# table
|
|
dataObject = None
|
|
dataObjectInstance = None
|
|
lookupTableInstance = None
|
|
calls = []
|
|
dependencies = []
|
|
|
|
if hasattr(mapper, "GetInputDataObject"):
|
|
mapper.GetInputAlgorithm().Update()
|
|
dataObject = mapper.GetInputDataObject(0, 0)
|
|
else:
|
|
logger.debug("This mapper does not have GetInputDataObject method")
|
|
|
|
if dataObject:
|
|
dataObjectId = "%s-dataset" % mapperId
|
|
dataObjectInstance = serializeInstance(
|
|
mapper, dataObject, dataObjectId, context, depth + 1
|
|
)
|
|
|
|
if dataObjectInstance:
|
|
dependencies.append(dataObjectInstance)
|
|
calls.append(["setInputData", [wrapId(dataObjectId)]])
|
|
|
|
if dataObjectInstance:
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": mapperId,
|
|
"type": class_name(mapper),
|
|
"properties": {
|
|
# VolumeMapper
|
|
"sampleDistance": mapper.GetSampleDistance(),
|
|
"imageSampleDistance": mapper.GetImageSampleDistance(),
|
|
# "maximumSamplesPerRay": mapper.GetMaximumSamplesPerRay(),
|
|
"autoAdjustSampleDistances": mapper.GetAutoAdjustSampleDistances(),
|
|
"blendMode": mapper.GetBlendMode(),
|
|
# "ipScalarRange": mapper.GetIpScalarRange(),
|
|
# "filterMode": mapper.GetFilterMode(),
|
|
# "preferSizeOverAccuracy": mapper.Get(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
return None
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def lookupTableSerializer(parent, lookupTable, lookupTableId, context, depth):
|
|
# No children in this case, so no additions to bindings and return empty list
|
|
# But we do need to add instance
|
|
|
|
lookupTableRange = lookupTable.GetRange()
|
|
|
|
lookupTableHueRange = [0.5, 0]
|
|
if hasattr(lookupTable, "GetHueRange"):
|
|
try:
|
|
lookupTable.GetHueRange(lookupTableHueRange)
|
|
except Exception as inst:
|
|
pass
|
|
|
|
lutSatRange = lookupTable.GetSaturationRange()
|
|
lutAlphaRange = lookupTable.GetAlphaRange()
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": lookupTableId,
|
|
"type": class_name(lookupTable),
|
|
"properties": {
|
|
"numberOfColors": lookupTable.GetNumberOfColors(),
|
|
"valueRange": lookupTableRange,
|
|
"hueRange": lookupTableHueRange,
|
|
# 'alphaRange': lutAlphaRange, # Causes weird rendering artifacts on client
|
|
"saturationRange": lutSatRange,
|
|
"nanColor": lookupTable.GetNanColor(),
|
|
"belowRangeColor": lookupTable.GetBelowRangeColor(),
|
|
"aboveRangeColor": lookupTable.GetAboveRangeColor(),
|
|
"useAboveRangeColor": True
|
|
if lookupTable.GetUseAboveRangeColor()
|
|
else False,
|
|
"useBelowRangeColor": True
|
|
if lookupTable.GetUseBelowRangeColor()
|
|
else False,
|
|
"alpha": lookupTable.GetAlpha(),
|
|
"vectorSize": lookupTable.GetVectorSize(),
|
|
"vectorComponent": lookupTable.GetVectorComponent(),
|
|
"vectorMode": lookupTable.GetVectorMode(),
|
|
"indexedLookup": lookupTable.GetIndexedLookup(),
|
|
},
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def lookupTableToColorTransferFunction(lookupTable):
|
|
dataTable = lookupTable.GetTable()
|
|
table = dataTableToList(dataTable)
|
|
if table:
|
|
ctf = vtkColorTransferFunction()
|
|
tableRange = lookupTable.GetTableRange()
|
|
points = linspace(*tableRange, num=len(table))
|
|
for x, rgba in zip(points, table):
|
|
ctf.AddRGBPoint(x, *[x / 255 for x in rgba[:3]])
|
|
|
|
return ctf
|
|
|
|
return None
|
|
|
|
|
|
def lookupTableSerializer2(parent, lookupTable, lookupTableId, context, depth):
|
|
ctf = lookupTableToColorTransferFunction(lookupTable)
|
|
if ctf:
|
|
return colorTransferFunctionSerializer(
|
|
parent, ctf, lookupTableId, context, depth
|
|
)
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def propertySerializer(parent, propObj, propObjId, context, depth):
|
|
representation = (
|
|
propObj.GetRepresentation() if hasattr(propObj, "GetRepresentation") else 2
|
|
)
|
|
colorToUse = (
|
|
propObj.GetDiffuseColor() if hasattr(propObj, "GetDiffuseColor") else [1, 1, 1]
|
|
)
|
|
if representation == 1 and hasattr(propObj, "GetColor"):
|
|
colorToUse = propObj.GetColor()
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": propObjId,
|
|
"type": class_name(propObj),
|
|
"properties": {
|
|
"representation": representation,
|
|
"diffuseColor": colorToUse,
|
|
"color": propObj.GetColor(),
|
|
"ambientColor": propObj.GetAmbientColor(),
|
|
"specularColor": propObj.GetSpecularColor(),
|
|
"edgeColor": propObj.GetEdgeColor(),
|
|
"ambient": propObj.GetAmbient(),
|
|
"diffuse": propObj.GetDiffuse(),
|
|
"specular": propObj.GetSpecular(),
|
|
"specularPower": propObj.GetSpecularPower(),
|
|
"opacity": propObj.GetOpacity(),
|
|
"interpolation": propObj.GetInterpolation(),
|
|
"edgeVisibility": 1 if propObj.GetEdgeVisibility() else 0,
|
|
"backfaceCulling": 1 if propObj.GetBackfaceCulling() else 0,
|
|
"frontfaceCulling": 1 if propObj.GetFrontfaceCulling() else 0,
|
|
"pointSize": propObj.GetPointSize(),
|
|
"lineWidth": propObj.GetLineWidth(),
|
|
"lighting": 1 if propObj.GetLighting() else 0,
|
|
},
|
|
}
|
|
|
|
def volumePropertySerializer(parent, propObj, propObjId, context, depth):
|
|
calls = []
|
|
dependencies = []
|
|
|
|
# Color handling
|
|
lut = propObj.GetRGBTransferFunction()
|
|
if lut:
|
|
lookupTableId = getReferenceId(lut)
|
|
lookupTableInstance = serializeInstance(
|
|
propObj, lut, lookupTableId, context, depth + 1
|
|
)
|
|
|
|
if lookupTableInstance:
|
|
dependencies.append(lookupTableInstance)
|
|
calls.append(["setRGBTransferFunction", [0, wrapId(lookupTableId)]])
|
|
|
|
# Piecewise handling
|
|
pwf = propObj.GetScalarOpacity()
|
|
if pwf:
|
|
pwfId = getReferenceId(pwf)
|
|
pwfInstance = serializeInstance(
|
|
propObj, pwf, pwfId, context, depth + 1
|
|
)
|
|
|
|
if pwfInstance:
|
|
dependencies.append(pwfInstance)
|
|
calls.append(["setScalarOpacity", [0, wrapId(pwfId)]])
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": propObjId,
|
|
"type": class_name(propObj),
|
|
"properties": {
|
|
"independentComponents": propObj.GetIndependentComponents(),
|
|
"interpolationType": propObj.GetInterpolationType(),
|
|
"shade": propObj.GetShade(),
|
|
"ambient": propObj.GetAmbient(),
|
|
"diffuse": propObj.GetDiffuse(),
|
|
"specular": propObj.GetSpecular(),
|
|
"specularPower": propObj.GetSpecularPower(),
|
|
# "useLabelOutline": propObj.GetUseLabelOutline(),
|
|
# "labelOutlineThickness": propObj.GetLabelOutlineThickness(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def imagedataSerializer(parent, dataset, datasetId, context, depth, requested_fields = ["Normals", "TCoords"]):
|
|
if hasattr(dataset, "GetDirectionMatrix"):
|
|
direction = [dataset.GetDirectionMatrix().GetElement(0, i) for i in range(9)]
|
|
else:
|
|
direction = [1, 0, 0, 0, 1, 0, 0, 0, 1]
|
|
|
|
# Extract dataset fields
|
|
fields = []
|
|
extractRequiredFields(fields, parent, dataset, context, "*")
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": datasetId,
|
|
"type": class_name(dataset),
|
|
"properties": {
|
|
"spacing": dataset.GetSpacing(),
|
|
"origin": dataset.GetOrigin(),
|
|
"dimensions": dataset.GetDimensions(),
|
|
"direction": direction,
|
|
"fields": fields,
|
|
},
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def polydataSerializer(parent, dataset, datasetId, context, depth, requested_fields = ["Normals", "TCoords"]):
|
|
if dataset and dataset.GetPoints():
|
|
properties = {}
|
|
|
|
# Points
|
|
points = getArrayDescription(dataset.GetPoints().GetData(), context)
|
|
points["vtkClass"] = "vtkPoints"
|
|
properties["points"] = points
|
|
|
|
# Verts
|
|
if dataset.GetVerts() and dataset.GetVerts().GetData().GetNumberOfTuples() > 0:
|
|
_verts = getArrayDescription(dataset.GetVerts().GetData(), context)
|
|
properties["verts"] = _verts
|
|
properties["verts"]["vtkClass"] = "vtkCellArray"
|
|
|
|
# Lines
|
|
if dataset.GetLines() and dataset.GetLines().GetData().GetNumberOfTuples() > 0:
|
|
_lines = getArrayDescription(dataset.GetLines().GetData(), context)
|
|
properties["lines"] = _lines
|
|
properties["lines"]["vtkClass"] = "vtkCellArray"
|
|
|
|
# Polys
|
|
if dataset.GetPolys() and dataset.GetPolys().GetData().GetNumberOfTuples() > 0:
|
|
_polys = getArrayDescription(dataset.GetPolys().GetData(), context)
|
|
properties["polys"] = _polys
|
|
properties["polys"]["vtkClass"] = "vtkCellArray"
|
|
|
|
# Strips
|
|
if (
|
|
dataset.GetStrips()
|
|
and dataset.GetStrips().GetData().GetNumberOfTuples() > 0
|
|
):
|
|
_strips = getArrayDescription(dataset.GetStrips().GetData(), context)
|
|
properties["strips"] = _strips
|
|
properties["strips"]["vtkClass"] = "vtkCellArray"
|
|
|
|
# Fields
|
|
properties["fields"] = []
|
|
extractRequiredFields(properties["fields"], parent, dataset, context, requested_fields)
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": datasetId,
|
|
"type": class_name(dataset),
|
|
"properties": properties,
|
|
}
|
|
|
|
logger.debug("This dataset has no points!")
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def mergeToPolydataSerializer(parent, dataObject, dataObjectId, context, depth, requested_fields=["Normals", "TCoords"]):
|
|
dataset = None
|
|
|
|
if dataObject.IsA("vtkCompositeDataSet"):
|
|
gf = vtkCompositeDataGeometryFilter()
|
|
gf.SetInputData(dataObject)
|
|
gf.Update()
|
|
dataset = gf.GetOutput()
|
|
elif dataObject.IsA("vtkUnstructuredGrid"):
|
|
gf = vtkDataSetSurfaceFilter()
|
|
gf.SetInputData(dataObject)
|
|
gf.Update()
|
|
dataset = gf.GetOutput()
|
|
else:
|
|
dataset = mapper.GetInput()
|
|
|
|
return polydataSerializer(parent, dataset, dataObjectId, context, depth, requested_fields)
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def colorTransferFunctionSerializer(parent, instance, objId, context, depth):
|
|
nodes = []
|
|
|
|
for i in range(instance.GetSize()):
|
|
# x, r, g, b, midpoint, sharpness
|
|
node = [0, 0, 0, 0, 0, 0]
|
|
instance.GetNodeValue(i, node)
|
|
nodes.append(node)
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {
|
|
"clamping": 1 if instance.GetClamping() else 0,
|
|
"colorSpace": instance.GetColorSpace(),
|
|
"hSVWrap": 1 if instance.GetHSVWrap() else 0,
|
|
# 'nanColor': instance.GetNanColor(), # Breaks client
|
|
# 'belowRangeColor': instance.GetBelowRangeColor(), # Breaks client
|
|
# 'aboveRangeColor': instance.GetAboveRangeColor(), # Breaks client
|
|
# 'useAboveRangeColor': 1 if instance.GetUseAboveRangeColor() else 0,
|
|
# 'useBelowRangeColor': 1 if instance.GetUseBelowRangeColor() else 0,
|
|
"allowDuplicateScalars": 1 if instance.GetAllowDuplicateScalars() else 0,
|
|
"alpha": instance.GetAlpha(),
|
|
"vectorComponent": instance.GetVectorComponent(),
|
|
"vectorSize": instance.GetVectorSize(),
|
|
"vectorMode": instance.GetVectorMode(),
|
|
"indexedLookup": instance.GetIndexedLookup(),
|
|
"nodes": nodes,
|
|
},
|
|
}
|
|
|
|
def discretizableColorTransferFunctionSerializer(parent, instance, objId, context, depth):
|
|
ctf = colorTransferFunctionSerializer(parent, instance, objId, context, depth)
|
|
ctf["properties"]["discretize"] = instance.GetDiscretize()
|
|
ctf["properties"]["numberOfValues"] = instance.GetNumberOfValues()
|
|
return ctf
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
def pwfSerializer(parent, instance, objId, context, depth):
|
|
nodes = []
|
|
|
|
for i in range(instance.GetSize()):
|
|
# x, y, midpoint, sharpness
|
|
node = [0, 0, 0, 0]
|
|
instance.GetNodeValue(i, node)
|
|
nodes.append(node)
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {
|
|
"range": list(instance.GetRange()),
|
|
"clamping": instance.GetClamping(),
|
|
"allowDuplicateScalars": instance.GetAllowDuplicateScalars(),
|
|
"nodes": nodes,
|
|
},
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
def cubeAxesSerializer(parent, actor, actorId, context, depth):
|
|
"""
|
|
Possible add-on properties for vtk.js:
|
|
gridLines: True,
|
|
axisLabels: None,
|
|
axisTitlePixelOffset: 35.0,
|
|
axisTextStyle: {
|
|
fontColor: 'white',
|
|
fontStyle: 'normal',
|
|
fontSize: 18,
|
|
fontFamily: 'serif',
|
|
},
|
|
tickLabelPixelOffset: 12.0,
|
|
tickTextStyle: {
|
|
fontColor: 'white',
|
|
fontStyle: 'normal',
|
|
fontSize: 14,
|
|
fontFamily: 'serif',
|
|
},
|
|
"""
|
|
axisLabels = ["", "", ""]
|
|
if actor.GetXAxisLabelVisibility():
|
|
axisLabels[0] = actor.GetXTitle()
|
|
if actor.GetYAxisLabelVisibility():
|
|
axisLabels[1] = actor.GetYTitle()
|
|
if actor.GetZAxisLabelVisibility():
|
|
axisLabels[2] = actor.GetZTitle()
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": actorId,
|
|
"type": "vtkCubeAxesActor",
|
|
"properties": {
|
|
# vtkProp
|
|
"visibility": actor.GetVisibility(),
|
|
"pickable": actor.GetPickable(),
|
|
"dragable": actor.GetDragable(),
|
|
"useBounds": actor.GetUseBounds(),
|
|
# vtkProp3D
|
|
"origin": actor.GetOrigin(),
|
|
"position": actor.GetPosition(),
|
|
"scale": actor.GetScale(),
|
|
# vtkActor
|
|
"forceOpaque": actor.GetForceOpaque(),
|
|
"forceTranslucent": actor.GetForceTranslucent(),
|
|
# vtkCubeAxesActor
|
|
"dataBounds": actor.GetBounds(),
|
|
"faceVisibilityAngle": 8,
|
|
"gridLines": True,
|
|
"axisLabels": axisLabels,
|
|
"axisTitlePixelOffset": 35.0,
|
|
"axisTextStyle": {
|
|
"fontColor": "white",
|
|
"fontStyle": "normal",
|
|
"fontSize": 18,
|
|
"fontFamily": "serif",
|
|
},
|
|
"tickLabelPixelOffset": 12.0,
|
|
"tickTextStyle": {
|
|
"fontColor": "white",
|
|
"fontStyle": "normal",
|
|
"fontSize": 14,
|
|
"fontFamily": "serif",
|
|
},
|
|
},
|
|
"calls": [["setCamera", [wrapId(getReferenceId(actor.GetCamera()))]]],
|
|
"dependencies": [],
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
def scalarBarActorSerializer(parent, actor, actorId, context, depth):
|
|
dependencies = []
|
|
calls = []
|
|
lut = actor.GetLookupTable()
|
|
if not lut:
|
|
return None
|
|
|
|
lutId = getReferenceId(lut)
|
|
lutInstance = serializeInstance(actor, lut, lutId, context, depth + 1)
|
|
if not lutInstance:
|
|
return None
|
|
|
|
dependencies.append(lutInstance)
|
|
calls.append(["setScalarsToColors", [wrapId(lutId)]])
|
|
|
|
prop = None
|
|
if hasattr(actor, "GetProperty"):
|
|
prop = actor.GetProperty()
|
|
else:
|
|
logger.debug("This scalarBarActor does not have a GetProperty method")
|
|
|
|
if prop:
|
|
propId = getReferenceId(prop)
|
|
propertyInstance = serializeInstance(
|
|
actor, prop, propId, context, depth + 1
|
|
)
|
|
if propertyInstance:
|
|
dependencies.append(propertyInstance)
|
|
calls.append(["setProperty", [wrapId(propId)]])
|
|
|
|
axisLabel = actor.GetTitle()
|
|
width = actor.GetWidth()
|
|
height = actor.GetHeight()
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": actorId,
|
|
"type": "vtkScalarBarActor",
|
|
"properties": {
|
|
# vtkProp
|
|
"visibility": actor.GetVisibility(),
|
|
"pickable": actor.GetPickable(),
|
|
"dragable": actor.GetDragable(),
|
|
"useBounds": actor.GetUseBounds(),
|
|
# vtkActor2D
|
|
# "position": actor.GetPosition(),
|
|
# "position2": actor.GetPosition2(),
|
|
# "width": actor.GetWidth(),
|
|
# "height": actor.GetHeight(),
|
|
# vtkScalarBarActor
|
|
"automated": True,
|
|
"axisLabel": axisLabel,
|
|
# 'barPosition': [0, 0],
|
|
# 'barSize': [0, 0],
|
|
"boxPosition": [0.88, -0.92],
|
|
"boxSize": [width, height],
|
|
"axisTitlePixelOffset": 36.0,
|
|
"axisTextStyle": {
|
|
"fontColor": actor.GetTitleTextProperty().GetColor(),
|
|
"fontStyle": "normal",
|
|
"fontSize": 18,
|
|
"fontFamily": "serif",
|
|
},
|
|
"tickLabelPixelOffset": 14.0,
|
|
"tickTextStyle": {
|
|
"fontColor": actor.GetTitleTextProperty().GetColor(),
|
|
"fontStyle": "normal",
|
|
"fontSize": 14,
|
|
"fontFamily": "serif",
|
|
},
|
|
"drawNanAnnotation": actor.GetDrawNanAnnotation(),
|
|
"drawBelowRangeSwatch": actor.GetDrawBelowRangeSwatch(),
|
|
"drawAboveRangeSwatch": actor.GetDrawAboveRangeSwatch(),
|
|
},
|
|
"calls": calls,
|
|
"dependencies": dependencies,
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def rendererSerializer(parent, instance, objId, context, depth):
|
|
dependencies = []
|
|
viewPropIds = []
|
|
lightsIds = []
|
|
calls = []
|
|
|
|
# Camera
|
|
camera = instance.GetActiveCamera()
|
|
cameraId = getReferenceId(camera)
|
|
cameraInstance = serializeInstance(instance, camera, cameraId, context, depth + 1)
|
|
if cameraInstance:
|
|
dependencies.append(cameraInstance)
|
|
calls.append(["setActiveCamera", [wrapId(cameraId)]])
|
|
|
|
# View prop as representation containers
|
|
viewPropCollection = instance.GetViewProps()
|
|
for rpIdx in range(viewPropCollection.GetNumberOfItems()):
|
|
viewProp = viewPropCollection.GetItemAsObject(rpIdx)
|
|
viewPropId = getReferenceId(viewProp)
|
|
|
|
viewPropInstance = serializeInstance(
|
|
instance, viewProp, viewPropId, context, depth + 1
|
|
)
|
|
if viewPropInstance:
|
|
dependencies.append(viewPropInstance)
|
|
viewPropIds.append(viewPropId)
|
|
|
|
calls += context.buildDependencyCallList(
|
|
"%s-props" % objId, viewPropIds, "addViewProp", "removeViewProp"
|
|
)
|
|
|
|
# Lights
|
|
lightCollection = instance.GetLights()
|
|
for lightIdx in range(lightCollection.GetNumberOfItems()):
|
|
light = lightCollection.GetItemAsObject(lightIdx)
|
|
lightId = getReferenceId(light)
|
|
|
|
lightInstance = serializeInstance(instance, light, lightId, context, depth + 1)
|
|
if lightInstance:
|
|
dependencies.append(lightInstance)
|
|
lightsIds.append(lightId)
|
|
|
|
calls += context.buildDependencyCallList(
|
|
"%s-lights" % objId, lightsIds, "addLight", "removeLight"
|
|
)
|
|
|
|
if len(dependencies) > 1:
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {
|
|
"background": instance.GetBackground(),
|
|
"background2": instance.GetBackground2(),
|
|
"viewport": instance.GetViewport(),
|
|
# These commented properties do not yet have real setters in vtk.js
|
|
# 'gradientBackground': instance.GetGradientBackground(),
|
|
# 'aspect': instance.GetAspect(),
|
|
# 'pixelAspect': instance.GetPixelAspect(),
|
|
# 'ambient': instance.GetAmbient(),
|
|
"twoSidedLighting": instance.GetTwoSidedLighting(),
|
|
"lightFollowCamera": instance.GetLightFollowCamera(),
|
|
"layer": instance.GetLayer(),
|
|
"preserveColorBuffer": instance.GetPreserveColorBuffer(),
|
|
"preserveDepthBuffer": instance.GetPreserveDepthBuffer(),
|
|
"nearClippingPlaneTolerance": instance.GetNearClippingPlaneTolerance(),
|
|
"clippingRangeExpansion": instance.GetClippingRangeExpansion(),
|
|
"useShadows": instance.GetUseShadows(),
|
|
"useDepthPeeling": instance.GetUseDepthPeeling(),
|
|
"occlusionRatio": instance.GetOcclusionRatio(),
|
|
"maximumNumberOfPeels": instance.GetMaximumNumberOfPeels(),
|
|
"interactive": instance.GetInteractive(),
|
|
},
|
|
"dependencies": dependencies,
|
|
"calls": calls,
|
|
}
|
|
|
|
return None
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def cameraSerializer(parent, instance, objId, context, depth):
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {
|
|
"focalPoint": instance.GetFocalPoint(),
|
|
"position": instance.GetPosition(),
|
|
"viewUp": instance.GetViewUp(),
|
|
"clippingRange": instance.GetClippingRange(),
|
|
},
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def lightTypeToString(value):
|
|
"""
|
|
#define VTK_LIGHT_TYPE_HEADLIGHT 1
|
|
#define VTK_LIGHT_TYPE_CAMERA_LIGHT 2
|
|
#define VTK_LIGHT_TYPE_SCENE_LIGHT 3
|
|
|
|
'HeadLight';
|
|
'SceneLight';
|
|
'CameraLight'
|
|
"""
|
|
if value == 1:
|
|
return "HeadLight"
|
|
elif value == 2:
|
|
return "CameraLight"
|
|
|
|
return "SceneLight"
|
|
|
|
|
|
def lightSerializer(parent, instance, objId, context, depth):
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {
|
|
# 'specularColor': instance.GetSpecularColor(),
|
|
# 'ambientColor': instance.GetAmbientColor(),
|
|
"switch": instance.GetSwitch(),
|
|
"intensity": instance.GetIntensity(),
|
|
"color": instance.GetDiffuseColor(),
|
|
"position": instance.GetPosition(),
|
|
"focalPoint": instance.GetFocalPoint(),
|
|
"positional": instance.GetPositional(),
|
|
"exponent": instance.GetExponent(),
|
|
"coneAngle": instance.GetConeAngle(),
|
|
"attenuationValues": instance.GetAttenuationValues(),
|
|
"lightType": lightTypeToString(instance.GetLightType()),
|
|
"shadowAttenuation": instance.GetShadowAttenuation(),
|
|
},
|
|
}
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
def renderWindowSerializer(parent, instance, objId, context, depth):
|
|
dependencies = []
|
|
rendererIds = []
|
|
|
|
rendererCollection = instance.GetRenderers()
|
|
for rIdx in range(rendererCollection.GetNumberOfItems()):
|
|
# Grab the next vtkRenderer
|
|
renderer = rendererCollection.GetItemAsObject(rIdx)
|
|
rendererId = getReferenceId(renderer)
|
|
rendererInstance = serializeInstance(
|
|
instance, renderer, rendererId, context, depth + 1
|
|
)
|
|
if rendererInstance:
|
|
dependencies.append(rendererInstance)
|
|
rendererIds.append(rendererId)
|
|
|
|
calls = context.buildDependencyCallList(
|
|
objId, rendererIds, "addRenderer", "removeRenderer"
|
|
)
|
|
|
|
return {
|
|
"parent": getReferenceId(parent),
|
|
"id": objId,
|
|
"type": class_name(instance),
|
|
"properties": {"numberOfLayers": instance.GetNumberOfLayers()},
|
|
"dependencies": dependencies,
|
|
"calls": calls,
|
|
"mtime": instance.GetMTime(),
|
|
}
|