def __init__(self, model, parent=None): ''' Constructor ''' super(SimpleVizWidget, self).__init__(parent) self._ui = Ui_SimpleVizWidget() self._ui.setupUi(self) self._model = model self._ui.sceneviewer_widget.setContext(model.getContext()) self._ui.sceneviewer_widget.graphicsInitialized.connect(self._graphicsInitialized) self._doneCallback = None self._makeConnections()
class SimpleVizWidget(QtGui.QWidget): ''' classdocs ''' def __init__(self, model, parent=None): ''' Constructor ''' super(SimpleVizWidget, self).__init__(parent) self._ui = Ui_SimpleVizWidget() self._ui.setupUi(self) self._model = model self._ui.sceneviewer_widget.setContext(model.getContext()) self._ui.sceneviewer_widget.graphicsInitialized.connect(self._graphicsInitialized) self._doneCallback = None self._makeConnections() def _graphicsInitialized(self): ''' Callback for when SceneviewerWidget is initialised Set custom scene from model ''' sceneviewer = self._ui.sceneviewer_widget.getSceneviewer() if sceneviewer is not None: scene = self._model.getRootRegion().getScene() sceneviewer.setScene(scene) self._ui.sceneviewer_widget.setSelectModeAll() self._ui.sceneviewer_editor_widget.setSceneviewer(sceneviewer) self.viewAll() def _makeConnections(self): self._ui.done_button.clicked.connect(self._doneButtonClicked) self._ui.view_all_button.clicked.connect(self.viewAll) self._ui.toolBox.currentChanged.connect(self._toolBoxPageChanged) self._ui.region_chooser.currentIndexChanged.connect(self._regionChanged) self._makeConnectionsTime() self._makeConnectionsRendering() self._makeConnectionsDataColouring() self._makeConnectionsOutput() def initialise(self): ''' Clear the model and view, reset display of widgets ''' self._model.initialise() self._graphicsInitialized() self._ui.dockWidget.setFloating(False) self._ui.toolBox.setCurrentIndex(0) self._allSettingsDisplay() def getModel(self): return self._model def registerDoneExecution(self, doneCallback): self._doneCallback = doneCallback def _doneButtonClicked(self): self.initialise() # to free model resources self._doneCallback() def loadScript(self, inputScriptFileName): success = self._model.loadScript(inputScriptFileName) rootRegion = self._model.getRootRegion() # rebuild region chooser tree self._ui.region_chooser.setRootRegion(rootRegion) scene = rootRegion.getScene() self._ui.scene_editor.setScene(scene) self.viewAll() self._allSettingsDisplay() return success def _toolBoxPageChanged(self, page): # enable view widget updates only when looking at them self._ui.sceneviewer_editor_widget.setEnableUpdates(page == 1) def _displayReal(self, widget, value): ''' Display real value in a widget ''' newText = '{:.5g}'.format(value) widget.setText(newText) def _displayScaleInteger(self, widget, values, numberFormat = '{:d}'): ''' Display vector of integer values in a widget, separated by '*' ''' newText = "*".join(numberFormat.format(value) for value in values) widget.setText(newText) def _parseScaleInteger(self, widget): ''' Return integer vector from comma separated text in line edit widget ''' text = widget.text() values = [int(value) for value in text.split('*')] if len(values) < 1: raise return values def _allSettingsDisplay(self): ''' Show initial values on widgets ''' self._timeSettingsDisplay() self._renderingSettingsDisplay() self._dataColouringSettingsDisplay() # ----- Graphics Settings ----- def _regionChanged(self): region = self._ui.region_chooser.getRegion() self._ui.scene_editor.setScene(region.getScene()) # ----- View Settings ----- def viewAll(self): ''' Ask sceneviewer to show all of scene. ''' if self._ui.sceneviewer_editor_widget.getSceneviewer() is not None: self._ui.sceneviewer_editor_widget.viewAll() # ----- Time Settings ----- def _makeConnectionsTime(self): self._ui.time_autorange_button.clicked.connect(self._timeAutorangeClicked) self._ui.time_minimum_lineedit.editingFinished.connect(self._timeMinimumEntered) self._ui.time_maximum_lineedit.editingFinished.connect(self._timeMaximumEntered) self._ui.time_lineedit.editingFinished.connect(self._timeEntered) QtCore.QObject.connect(self._ui.time_slider, QtCore.SIGNAL("valueChanged(int)"), self._timeSliderChanged) def _timeSettingsDisplay(self): self._timeMinimumDisplay() self._timeMaximumDisplay() self._timeDisplay() self._timeSliderDisplay() def _timeAutorangeClicked(self): ''' Set time min/max to time range of finite element field parameters. ''' self._model.autorangeTime() self._timeSettingsDisplay() def _timeMinimumDisplay(self): self._displayReal(self._ui.time_minimum_lineedit, self._model.getMinimumTime()) def _timeMinimumEntered(self): try: minimumTime = float(self._ui.time_minimum_lineedit.text()) self._model.setMinimumTime(minimumTime) except: pass self._timeMinimumDisplay() def _timeMaximumDisplay(self): self._displayReal(self._ui.time_maximum_lineedit, self._model.getMaximumTime()) def _timeMaximumEntered(self): try: maximumTime = float(self._ui.time_maximum_lineedit.text()) self._model.setMaximumTime(maximumTime) except: pass self._timeMaximumDisplay() def _timeDisplay(self): self._displayReal(self._ui.time_lineedit, self._model.getTime()) def _timeEntered(self): try: time = float(self._ui.time_lineedit.text()) self._model.setTime(time) except: pass self._timeDisplay() self._timeSliderDisplay() def _timeSliderDisplay(self): minimumTime = self._model.getMinimumTime() maximumTime = self._model.getMaximumTime() time = self._model.getTime() # don't want signal for my change self._ui.time_slider.blockSignals(True) if maximumTime != minimumTime: value = int(time*(10000.999/(maximumTime - minimumTime))) else: value = 0 self._ui.time_slider.setValue(value) self._ui.time_slider.blockSignals(False) def _timeSliderChanged(self, value): minimumTime = self._model.getMinimumTime() maximumTime = self._model.getMaximumTime() if maximumTime != minimumTime: time = float(value)*((maximumTime - minimumTime)/10000.0) else: time = minimumTime self._model.setTime(time) self._timeDisplay() # ----- Rendering Settings ----- def _makeConnectionsRendering(self): self._ui.tessellation_minimum_divisions_lineedit.returnPressed.connect(self._tessellationMinimumDivisionsEntered) self._ui.tessellation_refinement_factors_lineedit.returnPressed.connect(self._tessellationRefinementFactorsEntered) self._ui.tessellation_circle_divisions_lineedit.returnPressed.connect(self._tessellationCircleDivisionsEntered) self._ui.tessellation_minimum_divisions_lineedit.editingFinished.connect(self._tessellationMinimumDivisionsDisplay) self._ui.tessellation_refinement_factors_lineedit.editingFinished.connect(self._tessellationRefinementFactorsDisplay) self._ui.tessellation_circle_divisions_lineedit.editingFinished.connect(self._tessellationCircleDivisionsDisplay) QtCore.QObject.connect(self._ui.perturb_lines_checkbox, QtCore.SIGNAL("clicked(bool)"), self._perturbLinesStateChanged) def _renderingSettingsDisplay(self): self._tessellationMinimumDivisionsDisplay() self._tessellationRefinementFactorsDisplay() self._tessellationCircleDivisionsDisplay() def _checkTessellationDivisions(self, minimumDivisions, refinementFactors, widget): ''' Check total divisions not too high or get user confirmation Call with both of the vectors set, each must have at least one component. Returns True if can apply. ''' if self._model.checkTessellationDivisions(minimumDivisions, refinementFactors): return True # block signals otherwise editingFinished() is triggered widget.blockSignals(True) msgBox = QtGui.QMessageBox() msgBox.setWindowTitle("SimpleViz") msgBox.setText("Warning! Fine tessellation divisions can take a long time to apply.") msgBox.setInformativeText("Please confirm action.") msgBox.setStandardButtons(QtGui.QMessageBox.Apply | QtGui.QMessageBox.Cancel) msgBox.setDefaultButton(QtGui.QMessageBox.Cancel) result = msgBox.exec_() widget.blockSignals(False) return result == QtGui.QMessageBox.Apply def _tessellationMinimumDivisionsDisplay(self): self._displayScaleInteger(self._ui.tessellation_minimum_divisions_lineedit, self._model.getTessellationMinimumDivisions()) def _tessellationMinimumDivisionsEntered(self): try: minimumDivisions = self._parseScaleInteger(self._ui.tessellation_minimum_divisions_lineedit) # pack to len 3 to allow comparison with old values while len(minimumDivisions) < 3: minimumDivisions.append(minimumDivisions[-1]) if minimumDivisions != self._model.getTessellationMinimumDivisions(): if self._checkTessellationDivisions(minimumDivisions, self._model.getTessellationRefinementFactors(), self._ui.tessellation_minimum_divisions_lineedit): self._model.setTessellationMinimumDivisions(minimumDivisions) except: pass self._tessellationMinimumDivisionsDisplay() def _tessellationRefinementFactorsDisplay(self): self._displayScaleInteger(self._ui.tessellation_refinement_factors_lineedit, self._model.getTessellationRefinementFactors()) def _tessellationRefinementFactorsEntered(self): try: refinementFactors = self._parseScaleInteger(self._ui.tessellation_refinement_factors_lineedit) # pack to len 3 to allow comparison with old values while len(refinementFactors) < 3: refinementFactors.append(refinementFactors[-1]) if refinementFactors != self._model.getTessellationRefinementFactors(): if self._checkTessellationDivisions(self._model.getTessellationMinimumDivisions(),refinementFactors, self._ui.tessellation_refinement_factors_lineedit): self._model.setTessellationRefinementFactors(refinementFactors) except: pass self._tessellationRefinementFactorsDisplay() def _tessellationCircleDivisionsDisplay(self): self._displayReal(self._ui.tessellation_circle_divisions_lineedit, self._model.getTessellationCircleDivisions()) def _tessellationCircleDivisionsEntered(self): try: circleDivisions = int(self._ui.tessellation_circle_divisions_lineedit.text()) self._model.setTessellationCircleDivisions(circleDivisions) except: pass self._tessellationCircleDivisionsDisplay() def _perturbLinesStateChanged(self, state): sceneviewer = self._ui.sceneviewer_widget.getSceneviewer() sceneviewer.setPerturbLinesFlag(state) # ----- Data Colouring Settings ----- def _makeConnectionsDataColouring(self): self._ui.spectrum_autorange_button.clicked.connect(self._spectrumAutorangeClicked) self._ui.spectrum_minimum_lineedit.editingFinished.connect(self._spectrumMinimumEntered) self._ui.spectrum_maximum_lineedit.editingFinished.connect(self._spectrumMaximumEntered) self._ui.spectrum_add_colour_bar_button.clicked.connect(self._spectrumAddColourBarClicked) def _dataColouringSettingsDisplay(self): self._spectrumMinimumDisplay() self._spectrumMaximumDisplay() def _spectrumAutorangeClicked(self): ''' Set spectrum min/max to fit range of visible data in scene graphics. ''' scenefilter = self._ui.sceneviewer_widget.getSceneviewer().getScenefilter() self._model.spectrumAutorange(scenefilter) self._dataColouringSettingsDisplay() def _spectrumMinimumDisplay(self): self._displayReal(self._ui.spectrum_minimum_lineedit, self._model.getSpectrumMinimum()) def _spectrumMinimumEntered(self): try: minimum = float(self._ui.spectrum_minimum_lineedit.text()) self._model.setSpectrumMinimum(minimum) except: pass self._spectrumMinimumDisplay() def _spectrumMaximumDisplay(self): self._displayReal(self._ui.spectrum_maximum_lineedit, self._model.getSpectrumMaximum()) def _spectrumMaximumEntered(self): try: maximum = float(self._ui.spectrum_maximum_lineedit.text()) self._model.setSpectrumMaximum(maximum) except: pass self._spectrumMaximumDisplay() def _spectrumAddColourBarClicked(self): self._model.addSpectrumColourBar() # ensure scene editor graphics list is redisplayed scene = self._model.getRootRegion().getScene() self._ui.scene_editor.setScene(scene) # ----- Output Settings ----- def _makeConnectionsOutput(self): self._ui.save_image_button.clicked.connect(self._saveImageClicked) self._ui.save_webgl_button.clicked.connect(self._saveWebGLClicked) def _saveImageClicked(self): ''' Save the view in the window to an image file. ''' fileNameTuple = QtGui.QFileDialog.getSaveFileName(self, "Save image", "", "Image files (*.jpg *.png *.tif *.*)") fileName = fileNameTuple[0] if not fileName: return image = self._ui.sceneviewer_widget.grabFrameBuffer() image.save(fileName) def exportSceneViewersettings(self, outputPrefix, numberOfResources): scene = self._ui.sceneviewer_widget.getSceneviewer().getScene() si = scene.createStreaminformationScene() si.setIOFormat(si.IO_FORMAT_THREEJS) si.setIODataType(si.IO_FORMAT_THREEJS) timekeepermodule = scene.getTimekeepermodule() timekeeper = timekeepermodule.getDefaultTimekeeper() minimum = timekeeper.getMinimumTime() maximum = timekeeper.getMaximumTime() time_enabled = 0 if (maximum - minimum) > 0.001: time_enabled = 1 sv = self._ui.sceneviewer_widget.getSceneviewer() sv.viewAll() nearPlane = sv.getNearClippingPlane() farPlane = sv.getFarClippingPlane() result, eyePos, lookat, upVector = sv.getLookatParameters() obj = { "nearPlane": nearPlane, "farPlane": farPlane, "eyePosition": eyePos, "targetPosition": lookat, "upVector": upVector, "numberOfResources": numberOfResources, "timeEnabled" : [time_enabled]} outputName = outputPrefix + "_view.json" export_f = open(outputName, "w+") export_f.write(json.dumps(obj)) export_f.close() def exportScene(self, outputPrefix): scene = self._ui.sceneviewer_widget.getSceneviewer().getScene() si = scene.createStreaminformationScene() si.setIOFormat(si.IO_FORMAT_THREEJS) si.setIODataType(si.IO_FORMAT_THREEJS) timekeepermodule = scene.getTimekeepermodule() timekeeper = timekeepermodule.getDefaultTimekeeper() minimum = timekeeper.getMinimumTime() maximum = timekeeper.getMaximumTime() if (maximum - minimum) > 0.0: si.setInitialTime(minimum) si.setFinishTime(maximum) si.setNumberOfTimeSteps(51) number = si.getNumberOfResourcesRequired() i = 0 srs = [] while i < number: outputName = outputPrefix + "_" + str(i + 1) + ".json" srs.append(si.createStreamresourceFile(outputName)) i = i + 1 scene.write(si) return number def _saveWebGLClicked(self): ''' Save the view in the window to WebGL content. ''' fileNameTuple = QtGui.QFileDialog.getSaveFileName(self, "Specify prefix", "") fileName = fileNameTuple[0] if not fileName: return numberOfResources = self.exportScene(fileName) self.exportSceneViewersettings(fileName, numberOfResources)