Example #1
0
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle(
            QtGui.QApplication.translate("MainWindow", "3DLP Slicer", None,
                                         QtGui.QApplication.UnicodeUTF8))

        #load previous settings from config file here:
        self.parser = SafeConfigParser()
        filename = 'sliceconfig.ini'
        if hasattr(sys, '_MEIPASS'):
            # PyInstaller >= 1.6
            os.chdir(sys._MEIPASS)
            filename = os.path.join(sys._MEIPASS, filename)
            APPNAME = '3DLP'
            APPDATA = os.path.join(os.environ['APPDATA'], APPNAME)
            if not os.path.isdir(os.path.join(APPDATA)):
                os.mkdir(os.path.join(APPDATA))
                shutil.copy(filename, os.path.join(APPDATA, ''))
                self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                self.LoadSettingsFromConfigFile()
            else:
                if not os.path.isfile(os.path.join(APPDATA,
                                                   'sliceconfig.ini')):
                    shutil.copy(filename, os.path.join(APPDATA))
                else:
                    self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                    self.LoadSettingsFromConfigFile()
        else:  #otherwise it's running in pydev environment: use the dev config file
            os.chdir(os.path.dirname(sys.argv[0]))
            filename = os.path.join(os.path.dirname(sys.argv[0]), filename)
            self.parser.read('sliceconfig.ini')
            self.LoadSettingsFromConfigFile()

        self.ren = vtk.vtkRenderer()
        self.ren.SetBackground(.4, .4, .4)

        # create the modelview widget
        self.ModelView = QVTKRenderWindowInteractor(self.ui.ModelFrame)
        self.ModelView.SetInteractorStyle(MyInteractorStyle())
        self.ModelView.Initialize()
        self.ModelView.Start()

        self.renWin = self.ModelView.GetRenderWindow()
        self.renWin.AddRenderer(self.ren)
        self.ModelView.show()

        self.ModelView.resize(1006 - 17, 716 - 39)
        #self.ModelView.resize(self.ui.ModelFrame.geometry().width()-1,self.ui.ModelFrame.geometry().height()-1)

        self.modelList = []
Example #2
0
class Main(QtGui.QMainWindow):
    def resizeEvent(self, Event):
        pass
        #self.ModelView.resize(self.ui.ModelFrame.geometry().width()-15,self.ui.ModelFrame.geometry().height()-39)

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle(
            QtGui.QApplication.translate("MainWindow", "3DLP Slicer", None,
                                         QtGui.QApplication.UnicodeUTF8))

        #load previous settings from config file here:
        self.parser = SafeConfigParser()
        filename = 'sliceconfig.ini'
        if hasattr(sys, '_MEIPASS'):
            # PyInstaller >= 1.6
            os.chdir(sys._MEIPASS)
            filename = os.path.join(sys._MEIPASS, filename)
            APPNAME = '3DLP'
            APPDATA = os.path.join(os.environ['APPDATA'], APPNAME)
            if not os.path.isdir(os.path.join(APPDATA)):
                os.mkdir(os.path.join(APPDATA))
                shutil.copy(filename, os.path.join(APPDATA, ''))
                self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                self.LoadSettingsFromConfigFile()
            else:
                if not os.path.isfile(os.path.join(APPDATA,
                                                   'sliceconfig.ini')):
                    shutil.copy(filename, os.path.join(APPDATA))
                else:
                    self.parser.read(os.path.join(APPDATA, 'sliceconfig.ini'))
                    self.LoadSettingsFromConfigFile()
        else:  #otherwise it's running in pydev environment: use the dev config file
            os.chdir(os.path.dirname(sys.argv[0]))
            filename = os.path.join(os.path.dirname(sys.argv[0]), filename)
            self.parser.read('sliceconfig.ini')
            self.LoadSettingsFromConfigFile()

        self.ren = vtk.vtkRenderer()
        self.ren.SetBackground(.4, .4, .4)

        # create the modelview widget
        self.ModelView = QVTKRenderWindowInteractor(self.ui.ModelFrame)
        self.ModelView.SetInteractorStyle(MyInteractorStyle())
        self.ModelView.Initialize()
        self.ModelView.Start()

        self.renWin = self.ModelView.GetRenderWindow()
        self.renWin.AddRenderer(self.ren)
        self.ModelView.show()

        self.ModelView.resize(1006 - 17, 716 - 39)
        #self.ModelView.resize(self.ui.ModelFrame.geometry().width()-1,self.ui.ModelFrame.geometry().height()-1)

        self.modelList = []

    def AddModel(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, 'Open 3D Model',
                                                     '.', '*.stl')
        if filename == '':  #user hit cancel
            return
        modelObject = model(self, filename)
        self.modelList.append(modelObject)
        self.ui.modelList.addItem(os.path.basename(str(filename)))
        if len(self.modelList) == 1:
            self.FirstOpen()

        self.ren.ResetCamera()
        self.ModelView.Render()  #update model view

    def FirstOpen(self):
        #create annotated cube anchor actor
        self.axesActor = vtk.vtkAnnotatedCubeActor()
        self.axesActor.SetXPlusFaceText('Right')
        self.axesActor.SetXMinusFaceText('Left')
        self.axesActor.SetYMinusFaceText('Front')
        self.axesActor.SetYPlusFaceText('Back')
        self.axesActor.SetZMinusFaceText('Bot')
        self.axesActor.SetZPlusFaceText('Top')
        self.axesActor.GetTextEdgesProperty().SetColor(.8, .8, .8)
        self.axesActor.GetZPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetZMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetXPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetXMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetYPlusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetYMinusFaceProperty().SetColor(.8, .8, .8)
        self.axesActor.GetTextEdgesProperty().SetLineWidth(2)
        self.axesActor.GetCubeProperty().SetColor(.2, .2, .2)
        self.axesActor.SetFaceTextScale(0.25)
        self.axesActor.SetZFaceTextRotation(90)

        #create orientation markers
        self.axes = vtk.vtkOrientationMarkerWidget()
        self.axes.SetOrientationMarker(self.axesActor)
        self.axes.SetInteractor(self.ModelView)
        self.axes.EnabledOn()
        self.axes.InteractiveOff()

        self.ui.Transform_groupbox.setEnabled(True)

    def SliceModel(self):
        try:
            if self.modelActor:  #check to see if a model is loaded, if not it will throw an exception
                pass
        except:  #self.modelActor doesn't exist (hasn't been instantiated with a model yet)
            QtGui.QMessageBox.critical(
                self, 'Error slicing model',
                "You must first load a model to slice it!",
                QtGui.QMessageBox.Ok)
            return
        self.outputFile = str(
            QFileDialog.getSaveFileName(self, "Save file", "", ".3dlp"))
        self.slicer = slicer.slicer(self)
        self.slicer.imageheight = int(self.imageHeight)
        self.slicer.imagewidth = int(self.imageWidth)
        # check to see if starting depth is less than ending depth!! this assumption is crucial
        self.slicer.startingdepth = float(self.startingDepth)
        self.slicer.endingdepth = float(self.endingDepth)
        self.slicer.layerincrement = float(self.slicingIncrement)
        self.slicer.OpenModel(self.filename)
        self.slicer.slice()

    def UpdateModelOpacity(self):
        try:
            if self.modelActor:  #check to see if a model is loaded, if not it will throw an exception
                opacity, ok = QtGui.QInputDialog.getText(
                    self, 'Model Opacity',
                    'Enter the desired opacity (0-100):')
                if not ok:  #the user hit the "cancel" button
                    return
                self.modelActor.GetProperty().SetOpacity(float(opacity) / 100)
                self.ren.Render()
                self.ModelView.Render()
        except:  #self.modelActor doesn't exist (hasn't been instantiated with a model yet)
            QtGui.QMessageBox.critical(
                self, 'Error setting opacity',
                "You must first load a model to change its opacity!",
                QtGui.QMessageBox.Ok)

    def ModelIndexChanged(self, new, previous):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        self.ui.positionX.setValue(modelObject.CurrentXPosition)
        self.ui.positionY.setValue(modelObject.CurrentYPosition)
        self.ui.positionZ.setValue(modelObject.CurrentZPosition)
        self.ui.rotationX.setValue(modelObject.CurrentXRotation)
        self.ui.rotationY.setValue(modelObject.CurrentYRotation)
        self.ui.rotationZ.setValue(modelObject.CurrentZRotation)
        self.ui.scale.setValue(modelObject.CurrentScale)

    def Update_Position_X(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate((float(position) - modelObject.CurrentXPosition),
                            0.0, 0.0)
        modelObject.CurrentXPosition = modelObject.CurrentXPosition + (
            float(position) - modelObject.CurrentXPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Position_Y(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate(0.0,
                            (float(position) - modelObject.CurrentYPosition),
                            0.0)
        modelObject.CurrentYPosition = modelObject.CurrentYPosition + (
            float(position) - modelObject.CurrentYPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Position_Z(self, position):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.Translate(0.0, 0.0,
                            (float(position) - modelObject.CurrentZPosition))
        modelObject.CurrentZPosition = modelObject.CurrentZPosition + (
            float(position) - modelObject.CurrentZPosition)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_X(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateX((float(rotation) - modelObject.CurrentXRotation))
        modelObject.CurrentXRotation = modelObject.CurrentXRotation + (
            float(rotation) - modelObject.CurrentXRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_Y(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateY((float(rotation) - modelObject.CurrentYRotation))
        modelObject.CurrentYRotation = modelObject.CurrentYRotation + (
            float(rotation) - modelObject.CurrentYRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Rotation_Z(self, rotation):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform
        transform.RotateZ((float(rotation) - modelObject.CurrentZRotation))
        modelObject.CurrentZRotation = modelObject.CurrentZRotation + (
            float(rotation) - modelObject.CurrentZRotation)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def Update_Scale(self, scale):
        modelObject = self.modelList[self.ui.modelList.currentRow()]
        transform = modelObject.transform

        self.reader = vtk.vtkSTLReader()
        self.reader.SetFileName(str(self.filename))

        self.mapper = vtk.vtkPolyDataMapper()
        self.mapper.SetInputConnection(self.reader.GetOutputPort())

        #create model actor
        self.actor = vtk.vtkActor()
        self.actor.GetProperty().SetColor(1, 1, 1)
        self.actor.GetProperty().SetOpacity(1)
        self.actor.SetMapper(self.mapper)

        #create outline mapper
        self.outline = vtk.vtkOutlineFilter()
        self.outline.SetInputConnection(self.reader.GetOutputPort())
        self.outlineMapper = vtk.vtkPolyDataMapper()
        self.outlineMapper.SetInputConnection(self.outline.GetOutputPort())

        #create outline actor
        self.outlineActor = vtk.vtkActor()
        self.outlineActor.SetMapper(self.outlineMapper)

        #add actors to parent render window
        self.parent.ren.AddActor(self.actor)
        self.parent.ren.AddActor(self.outlineActor)

        delta = modelObject.PreviousScale - modelObject.CurrentScale
        modelObject.transform
        #transform.Scale((float(scale)-modelObject.CurrentScale)/100.0, (float(scale)-modelObject.CurrentScale)/100.0, (float(scale)-modelObject.CurrentScale)/100.0)
        transform.Scale
        modelObject.CurrentScale = modelObject.CurrentScale + (
            float(scale) - modelObject.CurrentScale)
        transformFilter = vtk.vtkTransformPolyDataFilter()
        transformFilter.SetTransform(modelObject.transform)
        transformFilter.SetInputConnection(modelObject.reader.GetOutputPort())
        transformFilter.Update()
        modelObject.mapper.SetInputConnection(transformFilter.GetOutputPort())
        modelObject.mapper.Update()
        self.ren.Render()
        self.ModelView.Render()

    def LoadSettingsFromConfigFile(self):
        self.imageHeight = int(
            self.parser.get('slicing_settings', 'Image_Height'))
        self.imageWidth = int(
            self.parser.get('slicing_settings', 'Image_Width'))
        self.startingDepth = int(
            self.parser.get('slicing_settings', 'Starting_Depth'))
        self.endingDepth = int(
            self.parser.get('slicing_settings', 'Ending_Depth'))
        self.slicingIncrement = int(
            self.parser.get('slicing_settings', 'Slicing_Increment'))
        self.slicingplane = self.parser.get('slicing_settings',
                                            'Slicing_Plane')

    def OpenSettingsDialog(self):
        self.SettingsDialog = StartSettingsDialog(self)
        self.connect(self.SettingsDialog, QtCore.SIGNAL('ApplySettings()'),
                     self.getSettingsDialogValues)
        self.SettingsDialog.imageHeight.setText(str(self.imageHeight))
        self.SettingsDialog.imageWidth.setText(str(self.imageWidth))
        self.SettingsDialog.startingDepth.setText(str(self.startingDepth))
        self.SettingsDialog.endingDepth.setText(str(self.endingDepth))
        self.SettingsDialog.slicingIncrement.setText(str(
            self.slicingIncrement))
        self.slicingplaneDict = {"XZ": 0, "XY": 1, "YZ": 2}
        try:
            self.SettingsDialog.slicingPlane.setCurrentIndex(
                self.slicingplaneDict[self.slicingplane])
        except:  #anything other than a valid entry will default to XZ (index 0)
            self.SettingsDialog.slicingPlane.setCurrentIndex(0)
        self.SettingsDialog.exec_()

    def getSettingsDialogValues(self):
        self.imageHeight = int(self.SettingsDialog.imageHeight.text())
        self.parser.set('slicing_settings', 'Image_Height',
                        "%s" % self.imageHeight)
        self.imageWidth = int(self.SettingsDialog.imageWidth.text())
        self.parser.set('slicing_settings', 'Image_Width',
                        "%s" % self.imageWidth)
        self.startingDepth = int(self.SettingsDialog.startingDepth.text())
        self.parser.set('slicing_settings', 'Starting_Depth',
                        "%s" % self.startingDepth)
        self.endingDepth = int(self.SettingsDialog.endingDepth.text())
        self.parser.set('slicing_settings', 'Ending_Depth',
                        "%s" % self.endingDepth)
        self.slicingIncrement = int(
            self.SettingsDialog.slicingIncrement.text())
        self.parser.set('slicing_settings', 'Slicing_Increment',
                        "%s" % self.slicingIncrement)
        self.slicingplane = self.SettingsDialog.slicingPlane.currentText()
        self.parser.set('slicing_settings', 'Slicing_Plane',
                        "%s" % self.slicingplane)

        filename = 'sliceconfig.ini'
        if hasattr(sys, '_MEIPASS'):
            # PyInstaller >= 1.6
            APPNAME = '3DLP'
            APPDATA = os.path.join(os.environ['APPDATA'], APPNAME)
            filename = os.path.join(APPDATA, filename)
            outputini = open(
                filename, 'w'
            )  #open a file pointer for the config file parser to write changes to
            self.parser.write(outputini)
            outputini.close()  #done writing config file changes
        else:  #otherwise it's running in pydev environment: use the dev config file
            os.chdir(os.path.dirname(sys.argv[0]))
            filename = os.path.join(os.path.dirname(sys.argv[0]), filename)
            outputini = open(
                filename, 'w'
            )  #open a file pointer for the config file parser to write changes to
            self.parser.write(outputini)
            outputini.close()  #done writing config file changes