[visionegg] Re: anti-aliasing of FilledCircle

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

Other related posts: