Инструмент для наложения кругов чако

Я хотел бы создать инструмент наложения кругов с Chaco, который является гораздо более простой версией BetterSelectingZoom: левый вниз устанавливает центр круга, перетаскивает, а левый вниз рисует круг, левый вверх отбрасывает круг. К сожалению, я не могу точно следовать коду в better_selecting_zoom.py; в частности, я не совсем понимаю, как добавить, удалить или изменить оверлейный круг на лету. Попытка использования класса CircleTool приведена ниже. Кто-нибудь может подтолкнуть меня в правильном направлении?

import sys
import numpy as np
from traits.api import HasTraits, Instance
from traits.api import Bool, Tuple, Float
from traitsui.api import View, Item
from enable.api import Component, ComponentEditor
from chaco.api import Plot, ArrayPlotData
from chaco.api import AbstractOverlay, BaseTool

class CircleTool(AbstractOverlay,BaseTool):
    '''
    provides dynamic circle overlay on a plot: left down sets circle center,
    left down drag draws circle, left up removes circle overlay.
    '''

    _select_on = Bool(False) 
    _select_center = Tuple((0,0))
    _select_radius = Float(0)

    def __init__(self,component=None,**kwargs):
        '''
        initialize CircleTool as an overlay and a tool
        '''
        AbstractOverlay.__init__(self,component=component,**kwargs)
        BaseTool.__init__(self,component=component,**kwargs)

    def normal_left_down(self,event):
        '''
        set selection flag to True; save circle center; CircleTool to the
        overlays list of component (plot); discard event.
        '''
        self._select_on = True
        self._select_center = (event.x,event.y)
        self.component.overlays.append(self)        
        event.handled = True

    def normal_left_up(self,event):
        '''
        set selection flag to False; get index of the CircleTool overlay in 
        component's overlays list; discard CircleTool overlay; redraw plot;
        discard event.
        '''
        self._select_on = False
        ixself = self.component.overlays.index(self)
        self.component.overlays.pop(ixself)
        self.component.request_redraw()
        event.handled = True        

    def normal_mouse_move(self,event):
        '''
        if selection flag is True, get circle centre and current point;
        compute radius (coordinates and radius units are screen pixels.)
        demand redraw of plot which calls self.overlay()
        '''
        if not self._select_on: return
        xc, yc = self._select_center
        xp, yp = (event.x,event.y)
        self._select_radius = float(np.sqrt((xc-xp)**2 + (yc-yp)**2))
        self.component.request_redraw()

    def overlay(self,component,gc,view_bounds=None,mode='normal'):
        '''
        draw gc (Kiva Graphics Context System object) on component; define
        gc as a circle.  
        ??? in Chaco code, with gc is used.  Why?
        '''
        gc.set_line_width(2)
        gc.set_stroke_color((0,0,0))
        gc.clip_to_rect(component.x, component.y, component.width, component.height)
        gc.arc(self._select_center[0],self._select_center[1],self._select_radius,0,2*np.pi)
        gc.stroke_path()

class CircleOverlay(AbstractOverlay):
    '''
    basic test overlay: red circle at (200,300) with radius 50.
    '''
    def overlay(self,component,gc,view_bounds=False,mode='normal'):
        gc.set_stroke_color((1,0,0))
        gc.set_line_width(2)
        gc.arc(200,300,50,0,2*np.pi)
        gc.stroke_path()


class PlotExample(HasTraits):
    plot = Instance(Component)
    traits_view = View(Item('plot',editor=ComponentEditor()),
                       width=500,height=500,resizable=True,
                       title='TEST-CIRCLE-TOOL')

    def __init__(self,*args,**kwargs):
        super(PlotExample,self).__init__(*args,**kwargs)
        # create plot
        x = np.linspace(0,2*np.pi,100)
        y = np.sin(x)
        plotData = ArrayPlotData(x=x,y=y)
        plot = Plot(plotData)
        plot.plot(('x','y'),type='line')

        # append circle tool
        circleTool = CircleTool(component=plot)
        plot.tools.append(circleTool)

        # append circle overlay
        circleOverlay = CircleOverlay(component=plot)
        plot.overlays.append(circleOverlay)

        # save plot for later
        self.plot = plot

if __name__ == '__main__':
    plotExample = PlotExample()
    plotExample.configure_traits()

0 ответов

Другие вопросы по тегам