.. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_texturedrawing.py: Texture drawing --------------- Drawing ROI on a mesh in a texture. Of course the SurfPaint module allows to do it with much richer features, but this example demonstrates how to code the basics of it in a relatively small program. .. code-block:: default from __future__ import print_function from __future__ import absolute_import import anatomist.direct.api as anatomist from soma import aims from soma.aims import colormaphints import sys import os import math import six sys.path.insert(0, '.') userLevel = 4 # determine wheter we are using Qt4 or Qt5, and hack a little bit accordingly # the boolean qt4 gloabl variable will tell it for later usage from soma.qt_gui.qt_backend import QtCore, QtGui from soma.qt_gui.qt_backend import loadUi # do we have to run QApplication ? if QtGui.QApplication.instance() is None: runqt = True else: runqt = False import sphere import numpy selmesh = None selanamesh = None class TexDrawAction(anatomist.cpp.Action): def name(self): return 'TexDrawAction' def takePolygon(self, x, y, globx, globy): # print('takePolygon', x, y) w = self.view().aWindow() obj = w.objectAtCursorPosition(x, y) if obj is not None: print('object:', obj, obj.name()) surf = None if obj.objectTypeName(obj.type()) == 'SURFACE': surf = obj elif isinstance(obj, anatomist.cpp.MObject): surf = [o for o in obj if o.type() == 3] if len(surf) != 1: return surf = surf[0] if surf is not None: poly = w.polygonAtCursorPosition(x, y, obj) if poly == 0xffffff: # white return # background print('polygon:', poly) mesh = anatomist.cpp.AObjectConverter.aims(surf) # print('mesh:', mesh) ppoly = mesh.polygon()[poly] vert = mesh.vertex() global selmesh, selanamesh if selmesh is None: selmesh = aims.AimsSurfaceTriangle() selmesh.vertex().assign([vert[ppoly[0]], vert[ppoly[1]], vert[ppoly[2]]]) selmesh.polygon().assign([aims.AimsVector_U32_3(0, 1, 2)]) if selanamesh is None: selanamesh = anatomist.cpp.AObjectConverter.anatomist( selmesh) a = anatomist.Anatomist() a.execute('SetMaterial', objects=[ selanamesh], diffuse=[0, 0, 1., 1.]) a.execute('AddObject', objects=[selanamesh], windows=[w]) selanamesh.setChanged() selanamesh.notifyObservers() def delPolygon(self): global selmesh, selanamesh selmesh = None # keep object ID and release python reference to it id = a.convertSingleObjectParamsToIDs(selanamesh) selanamesh = None a.execute('DeleteElement', elements=[id]) def newtexture(self, x, y, globx, globy): print('new texture') w = self.view().aWindow() aw = a.AWindow(a, w) obj = w.objectAtCursorPosition(x, y) # print('object:', obj) if obj is not None: if obj.objectTypeName(obj.type()) == 'SURFACE': surf = obj texs = [] # elif obj.objectTypeName( obj.type() ) == 'TEXTURED SURF.': # print('TEXTURED SURF.') # surf = [ o for o in obj if o.type() == 3 ] # if len( surf ) != 1: # print('not one mesh, but', len( surf )) # return # surf = surf[0] # texs = [ o for o in obj if o.type() == 18 ] # self._texsurf = obj # print('draw initiated') # return else: return gl = surf.glAPI() if gl: vs = anatomist.cpp.ViewState() nv = gl.glNumVertex(vs) if nv > 0: tex = aims.TimeTexture_FLOAT() t = tex[0] t.reserve(nv) for i in six.moves.xrange(nv): t.push_back(0.) atex = a.toAObject(tex) atex.releaseAppRef() # atex = a.AObject( a, surf ).generateTexture() texs.append(atex) # ... tsurf = a.fusionObjects( [atex, obj], method='FusionTexSurfMethod') tsurf.setPalette(palette='Blue-Red-fusion') self._texsurf = tsurf # tsurf.takeRef() aw.removeObjects(obj) aw.addObjects(tsurf) def startDraw(self, x, y, globx, globy): self._startDraw(x, y, 1.) def startErase(self, x, y, globx, globy): self._startDraw(x, y, 0.) def _startDraw(self, x, y, value): w = self.view().aWindow() obj = w.objectAtCursorPosition(x, y) # print('object:', obj) if obj is not None: texs = [] if obj.objectTypeName(obj.type()) == 'SURFACE': surf = obj p = obj.parents() found = False for o in p: if o.objectTypeName(o.type()) == 'TEXTURED SURF.' \ and w.hasObject(o): texs = [ob for ob in o if ob.type() == 18] self._texsurf = o found = True break if not found: # create a new texture self.newtexture(x, y, 0, 0) self._startDraw(x, y, value) return elif obj.objectTypeName(obj.type()) == 'TEXTURED SURF.': surf = [o for o in obj if o.type() == 3] if len(surf) != 1: return surf = surf[0] texs = [o for o in obj if o.type() == 18] self._texsurf = obj else: return if len(texs) == 0: return self._surf = surf self._tex = texs[-1] self._mesh = anatomist.cpp.AObjectConverter.aims(surf) self._aimstex = anatomist.cpp.AObjectConverter.aims( self._tex, {'scale': 0}) self.draw(x, y, value) def endDraw(self, x, y, globx, globy): if hasattr(self, '_aimstex'): del self._aimstex del self._mesh del self._tex del self._surf def moveDraw(self, x, y, globx, globy): self.draw(x, y, 1.) def erase(self, x, y, globx, globy): self.draw(x, y, 0.) def draw(self, x, y, value): if not hasattr(self, '_aimstex'): return w = self.view().aWindow() obj = self._texsurf poly = w.polygonAtCursorPosition(x, y, obj) if poly == 0xffffff or poly < 0 or poly >= len(self._mesh.polygon()): return ppoly = self._mesh.polygon()[poly] print('poly:', poly, ppoly) vert = self._mesh.vertex() pos = aims.Point3df() pos = w.positionFromCursor(x, y) print('pos:', pos) v = ppoly[numpy.argmin([(vert[p] - pos).norm() for p in ppoly])] print('vertex:', v, vert[v]) self._aimstex[0][v] = value self._tex.setChanged() self._tex.notifyObservers() class TexDrawControl(anatomist.cpp.Control): def __init__(self, prio=25): anatomist.cpp.Control.__init__(self, prio, 'TexDrawControl') def eventAutoSubscription(self, pool): key = QtCore.Qt NoModifier = key.NoModifier ShiftModifier = key.ShiftModifier ControlModifier = key.ControlModifier AltModifier = key.AltModifier self.mouseLongEventSubscribe( key.LeftButton, NoModifier, pool.action('TexDrawAction').startDraw, pool.action('TexDrawAction').moveDraw, pool.action('TexDrawAction').endDraw, False) self.mouseLongEventSubscribe( key.LeftButton, NoModifier, pool.action('TexDrawAction').startDraw, pool.action('TexDrawAction').moveDraw, pool.action('TexDrawAction').endDraw, False) self.mouseLongEventSubscribe( key.LeftButton, ControlModifier, pool.action('TexDrawAction').startErase, pool.action('TexDrawAction').erase, pool.action('TexDrawAction').endDraw, False) self.mousePressButtonEventSubscribe( key.RightButton, ControlModifier, pool.action('TexDrawAction').newtexture) # polygon picking self.mousePressButtonEventSubscribe(key.RightButton, NoModifier, pool.action('TexDrawAction').takePolygon) self.keyPressEventSubscribe(key.Key_Escape, NoModifier, pool.action("TexDrawAction").delPolygon) # now plug the standard actions self.mouseLongEventSubscribe(key.MidButton, ShiftModifier, pool.action("Zoom3DAction").beginZoom, pool.action("Zoom3DAction").moveZoom, pool.action("Zoom3DAction").endZoom, True) self.wheelEventSubscribe(pool.action("Zoom3DAction").zoomWheel) self.keyPressEventSubscribe(key.Key_C, ControlModifier, pool.action("Trackball").setCenter) self.keyPressEventSubscribe(key.Key_C, AltModifier, pool.action("Trackball").showRotationCenter) self.mouseLongEventSubscribe(key.MidButton, ControlModifier, pool.action( "Translate3DAction").beginTranslate, pool.action( "Translate3DAction").moveTranslate, pool.action("Translate3DAction").endTranslate, True) self.mouseLongEventSubscribe( key.MidButton, NoModifier, pool.action('ContinuousTrackball').beginTrackball, pool.action('ContinuousTrackball').moveTrackball, pool.action('ContinuousTrackball').endTrackball, True) self.keyPressEventSubscribe(key.Key_Space, ControlModifier, pool.action("ContinuousTrackball").startOrStop) # a = anatomist.Anatomist() # pix = QtGui.QPixmap( 'control.xpm' ) # anatomist.cpp.IconDictionary.instance().addIcon( 'MyControl', # pix ) # ad = anatomist.cpp.ActionDictionary.instance() # ad.addAction( 'MyAction', lambda: MyAction() ) # cd = anatomist.cpp.ControlDictionary.instance() # cd.addControl( 'MyControl', lambda: MyControl(), 25 ) # cm = anatomist.cpp.ControlManager.instance() # cm.addControl( 'QAGLWidget3D', '', 'MyControl' ) # s = sphere.ASphere() # a.registerObject( s ) # aw = a.createWindow( '3D' ) # a.addObjects( [ s ], [ aw ] ) a = anatomist.Anatomist() qapp = QtGui.QApplication.instance() pix = QtGui.QPixmap('control.xpm') anatomist.cpp.IconDictionary.instance().addIcon('TexDrawControl', pix) ad = anatomist.cpp.ActionDictionary.instance() ad.addAction('TexDrawAction', TexDrawAction) cd = anatomist.cpp.ControlDictionary.instance() cd.addControl('TexDrawControl', TexDrawControl, 26) cm = anatomist.cpp.ControlManager.instance() cm.addControl('QAGLWidget3D', '', 'TexDrawControl') s = a.loadObject('test.mesh') aw = a.createWindow('3D') a.addObjects([s], [aw]) a.execute('SetControl', windows=[aw], control='TexDrawControl') QtGui.QMessageBox.information( None, 'texture drawing', '1. put a mesh in a 3D view\n2.select the "Mickey" control\n3. ctrl+right click on the mesh to create an empty texture or initiate the drawing session\n4. draw on the mesh using the mouse left button\n ctrl+left button erases', QtGui.QMessageBox.Ok) # run Qt if runqt: qapp.exec_() del ad, cm, aw, s, pix .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 0.000 seconds) .. _sphx_glr_download_auto_examples_texturedrawing.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download :download:`Download Python source code: texturedrawing.py ` .. container:: sphx-glr-download :download:`Download Jupyter notebook: texturedrawing.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_