[visionegg] Re: anti-aliasing of FilledCircle

Thanks Gijs and Peter, I've put your changes into the code repository.

Cheers!
Andrew

Gijs Plomp wrote:

> I was lucky and had some help already. We changed the FilledCircle
> code in MoreStimuli.py so that it now does anti-aliasing, just like
> Target2D. Maybe this could be incorporated a future versions?
>
> New code below, thanks entirely to Peter Jurica:
>
> class FilledCircle(VisionEgg.Core.Stimulus):
>   """A circular stimulus, typically used as a fixation point.
>
>   (Note, this implementation almost certainly could be made faster
>   using display lists.)
>
>   Parameters
>   ==========
>   anchor        -- how position parameter is used (String)
>                    Default: center
>   color         -- color (AnyOf(Sequence3 of Real or Sequence4 of Real))
>                    Default: (1.0, 1.0, 1.0)
>   num_triangles -- number of triangles used to draw circle (Integer)
>                    Default: 51
>   on            -- draw? (Boolean)
>                    Default: True
>   position      -- position in eye coordinates (AnyOf(Sequence2 of
> Real or Sequence3 of Real or Sequence4 of Real))
>                    Default: (320.0, 240.0)
>   radius        -- radius in eye coordinates (Real)
>                    Default: 2.0
>   """
>
>   parameters_and_defaults = VisionEgg.ParameterDefinition({
>       'on':(True,
>             ve_types.Boolean,
>             'draw?'),
>       'color':((1.0,1.0,1.0),
>                ve_types.AnyOf(ve_types.Sequence3(ve_types.Real),
>                               ve_types.Sequence4(ve_types.Real)),
>                'color'),
>       'anti_aliasing':(True,
>                        ve_types.Boolean),
>       'position' : ( ( 320.0, 240.0 ), # in eye coordinates
>                      ve_types.AnyOf(ve_types.Sequence2(ve_types.Real),
>                                     ve_types.Sequence3(ve_types.Real),
>                                     ve_types.Sequence4(ve_types.Real)),
>                      'position in eye coordinates'),
>       'anchor' : ('center',
>                   ve_types.String,
>                   'how position parameter is used'),
>       'radius':(2.0,
>               ve_types.Real,
>               'radius in eye coordinates'),
>       'num_triangles':(51,
>                        ve_types.Integer,
>                        'number of triangles used to draw circle'),
>       })
>   __slots__ = VisionEgg.Core.Stimulus.__slots__ + (
>       '_gave_alpha_warning',
>       )
>
>   def __init__(self,**kw):
>       VisionEgg.Core.Stimulus.__init__(self,**kw)
>       self._gave_alpha_warning = 0
>
>   def draw(self):
>       p = self.parameters # shorthand
>       if p.on:
>           # calculate center
>           center =
> VisionEgg._get_center(p.position,p.anchor,(p.radius, p.radius))
>           gl.glDisable(gl.GL_DEPTH_TEST)
>           gl.glDisable(gl.GL_TEXTURE_2D)
>           gl.glDisable(gl.GL_BLEND)
>
>           gl.glColorf(*p.color)
>
>           # Build filled circle from points
> #           gl.glBegin(gl.GL_POINTS)
> #           radius = int(math.ceil(p.radius))
> #           for i in range(-radius, radius):
> #               for j in range(-radius, radius):
> #                   if(i * i + j * j < radius * radius):
> #                       gl.glVertex3f(p.position[0] + i, p.position[1]
> + j, 0.0)
> #           gl.glEnd() # GL_POINTS
>
>           # Build filled circle from triangles (this is typically faster
>           # then the commented code above with the points)
>           gl.glBegin(gl.GL_TRIANGLE_FAN)
>           gl.glVertex3f(p.position[0], p.position[1], 0.0)
>           angles =
> Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
>           verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
>           verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
>           verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
>           for i in range(verts.shape[0]):
>               gl.glVertex2fv(verts[i])
>           gl.glVertex2fv(verts[0])
>
>           gl.glEnd() # GL_TRIANGLE_FAN
>           if p.anti_aliasing:
>               if not self._gave_alpha_warning:
>                   if len(p.color) > 3 and p.color[3] != 1.0:
>                       logger = logging.getLogger('VisionEgg.Arrow')
>                       logger.warning("The parameter anti_aliasing is "
>                                      "set to true in the Arrow "
>                                      "stimulus class, but the color "
>                                      "parameter specifies an alpha "
>                                      "value other than 1.0.  To "
>                                      "acheive anti-aliasing, ensure "
>                                      "that the alpha value for the "
>                                      "color parameter is 1.0.")
>                       self._gave_alpha_warning = 1
>
>               # We've already drawn a filled polygon (aliased), now
> redraw
>               # the outline of the polygon (with anti-aliasing). (Using
>               # GL_POLYGON_SMOOTH results in artifactual lines where
>               # triangles were joined to create quad, at least on some
> OpenGL
>               # implementations.)
>
>               # Calculate coverage value for each pixel of outline
>               # and store as alpha
>               gl.glEnable(gl.GL_LINE_SMOOTH)
>               # Now specify how to use the alpha value
>               gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
>               gl.glEnable(gl.GL_BLEND)
>
>               # Draw a second polygon in line mode, so the edges are
> anti-aliased
>               gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
>               gl.glBegin(gl.GL_TRIANGLE_FAN)
>               gl.glVertex3f(p.position[0], p.position[1], 0.0)
>               angles =
> Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
>               verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
>               verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
>               verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
>               for i in range(verts.shape[0]):
>                   gl.glVertex2fv(verts[i])
>               gl.glVertex2fv(verts[0])
>               gl.glEnd() # GL_TRIANGLE_FAN
>
>               # Set the polygon mode back to fill mode
>               gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
>               gl.glDisable(gl.GL_LINE_SMOOTH)
>
> ======================================
> The Vision Egg mailing list
> Archives: http://www.freelists.org/archives/visionegg
> Website: http://www.visionegg.org/mailinglist.html


======================================
The Vision Egg mailing list
Archives: http://www.freelists.org/archives/visionegg
Website: http://www.visionegg.org/mailinglist.html

Other related posts: