Graphics Library - Advanced Graphics

This library contains advanced graphics functions for creating complex visual stimuli and shapes.

BlockE()

Creates a block E as a useable polygon which can be added to a window directly.

Description:

Creates a polygon in the shape of a block E, pointing in one of four directions. Arguments include position in window.

  • <x> and <y> is the position of the center

  • <h> and <w> or the size of the E in pixels

  • <thickness> thickness of the E

  • <direction> specifies which way the E points: 1=right, 2=down, 3=left, 4=up.

  • <color> is a color object (not just the name)

    Like other drawn objects, the Block E must then be added to the window to appear.

Usage:

define BlockE(...)

Example:

win <- MakeWindow()
e1 <- BlockE(100,100,40,80,10,1,MakeColor("black"))
AddObject(e1,win)
Draw()

See Also:

Plus(), Polygon(), MakeStarPoints(), MakeNGonPoints()

ConvexHull()

Returns a convex subset of points for a set

Description:

Computes the convex hull of a set of [x,y] points. It returns a set of points that forms the convex hull, with the first and last point identical. A convex hull is the set of outermost points, such that a polygon connecting just those points will encompass all other points, and such that no angle is acute. It is used in MakeAttneave.

Usage:

define ConvexHull(...)

Example:

pts <- [[0.579081, 0.0327737],
         [0.0536094, 0.378258],
         [0.239628, 0.187751],
         [0.940625, 0.26526],
         [0.508748, 0.840846],
         [0.352604, 0.200193],
         [0.38684, 0.212413],
         [0.00114761, 0.768165],
         [0.432963, 0.629412]]
  Print(ConvexHull(pts))



output:

[[0.940625, 0.26526]
, [0.508748, 0.840846]
, [0.00114761, 0.768165]
, [0.0536094, 0.378258]
, [0.239628, 0.187751]
, [0.579081, 0.0327737]
, [0.940625, 0.26526]

See Also:

MakeAttneave,

GetAngle()

Returns the angle in degrees of a vector.

Description:

Gets an angle (in degrees) from (0,0) of an x,y coordinate

Usage:

define GetAngle(...)

Example:

##point sprite in the direction of a click
sprite <- LoadImage("car.png")
AddObject(sprite,gWin)
Move(sprite,300,300)
xy <- WaitForDownClick()
newangle <- GetAngle(First(xy)-300,Second(xy)-300)
sprite.rotation <- newangle
Draw()

See Also:

DegtoRad, RadToDeg

GetAngle3()

Gets angle abc.

Description:

Gets an angle (in radians) of abc.

Usage:

define GetAngle3(...)

Example:

 a <- [0.579081, 0.0327737]
 b <- [0.0536094, 0.378258]
 c <- [0.239628, 0.187751]

Print(GetAngle3(a,b,c)) ## .2157

See Also:

DegtoRad, RadToDeg, GetAngle, ToRight

KaniszaPolygon()

Description:

Creates generic polygon, defined only by with pac-man circles at specified vertices.

Usage:

define KaniszaPolygon(...)

Example:

For detailed usage example, see: `http://peblblog.blogspot.com/2010/11/kanizsa-shapes.html`
Part of a script using KaniszaPolygon:

   #Specify the xy points
   xys <- [[10,10],[10,50],[130,60],[100,100],[150,100],
           [150,20],[80,-10],[45,10]]

    #Specify which vertices to show (do all)
    show <- [1,1,1,1,1,1,1,1]

    #Make one, showing the line
    x <-  KaniszaPolygon(xys,show,10,fg,bg,1)
    AddObject(x,gWin);   Move(x,200,200)

    #Make a second, not showing the line
    x2 <-  KaniszaPolygon(xys,show,10,fg,bg,0)
    AddObject(x2,gWin);   Move(x2,400,200)

    #Make a third, only showing some vertices:
    x3 <-  KaniszaPolygon(xys,[1,1,1,1,1,0,0,1],10,fg,bg,0)
    AddObject(x3,gWin);  Move(x3,600,200)

See Also:

Polygon(), KaneszaSquare()

KaniszaSquare()

Description:

Creates generic Kanesza Square, one defined only by with pac-man circles at its vertices:

Usage:

define KaniszaSquare(...)

Example:

For detailed usage example, see
`http://peblblog.blogspot.com/2010/11/kanizsa-shapes.html`



   gWin <- MakeWindow()
   square <- KaniszaSquare(150,20,MakeColor("red"),
                                  MakeColor("green"))
   AddObject(square,gWin)
   Move(square,200,200)
   Draw()
   WaitForAnyKeyPress()

See Also:

Polygon(), KaneszaPolygon()

LayoutGrid()

Creates [x,y] pairs in a grid for graphical layout

Description:

Creates a grid of x,y points in a range, that are spaced in a specified number of rows and columns. Furthermore, you can specify whether they are vertical or horizontally laid out.

Usage:

define LayoutGrid(...)

Example:

Example PEBL Program using NonoverlapLayout:

define Start(p)
{
   gWin <- MakeWindow()
   gVideoWidth <- 800
   gVideoHeight <- 300

   lab1 <- EasyLabel("LayoutGrid, horizontal",
                     200,25,gWin,24)
   lab2 <- EasyLabel("LayoutGrid, vertical",
                     600,25,gWin,24)
   nums <- Sequence(1,20,1)
   stim1 <- []
   stim2 <- []

   font <- MakeFont(gPeblBaseFont,0,25,
              MakeColor("black"),MakeColor("white"),0)
   loop(i,nums)
   {
     stim1 <- Append(stim1,MakeLabel(i+"",font))
     stim2 <- Append(stim2,MakeLabel(i+"",font))
    }

  layout1 <- LayoutGrid(50,gVideoWidth/2-50,
                       50,gVideoHeight-50,5,4,0)
  layout2 <- LayoutGrid(gVideoWidth/2+50,gVideoWidth-50,
                       50,gVideoHeight-50,5,4,1)


  ##Now, layout the stuff.

  loop(i,Transpose([stim1,layout1]))
   {
      obj <- First(i)
      xy <- Second(i)
      AddObject(obj,gWin)
      Move(obj, First(xy),Second(xy))
   }

  loop(i,Transpose([stim2,layout2]))
   {
      obj <- First(i)
      xy <- Second(i)
      AddObject(obj,gWin)
      Move(obj, First(xy),Second(xy))
   }

  Draw()
  WaitForAnyKeyPress()
}


The output of the above program is shown below.  Even for the left configuration, which is too compact (and which takes a couple seconds to run), the targets are fairly well distributed.

See Also:

NonOverlapLayout()

MakeAttneave()

Makes a complex ``Attneave’’ polygon

Description:

Makes a random ‘Attneave’ figure((Collin, C. A., & Mcmullen, P. A. (2002). Using Matlab to generate families of similar Attneave shapes. Behavior Research Methods Instruments and Computers, 34(1), 55-68.).). An Attneave figure is a complex polygon that can be used as a stimulus in a number of situations. It returns a sequence of points for use in Polygon(). {} MakeAttneave uses ConvexHull, InsertAttneavePointRandom() and ValidateAttneaveShape(), found in Graphics.pbl. Override these to change constraints such as minimum/maximum side lengths, angles, complexity, etc. MakeAttneave uses a sampling-and-rejection scheme to create in-bounds shapes. Thus, if you specify impossible or nearly-impossible constraints, the time necessary to create shapes may be very long or infinite. The arguments to MakeAttneave are:

  • size: size, in pixels, of a circle from which points are sampled in a uniform distribution.

  • numpoints: number of points in the polygon.

  • minangle: smallest angle acceptable (in degrees).

  • maxangle: largest angle acceptable (in degrees).

Usage:

define MakeAttneave(...)

Example:

gWin <- MakeWindow()
shape <- MakeAttneave(100,5+RandomDiscrete(5),5,170)
pts <- Transpose(shape)
poly <- Polygon(200,200,First(pts),Second(pts),
                MakeColor("blue"),1)
AddObject(poly,gWin)
Draw()
WaitForAnyKeyPress()

See Also:

MakeImage(), Polygon(), Square()

MakeGabor()

Creates a ‘gabor patch’ with specified parameters

Description:

Creates a greyscale gabor patch, with seven variables:

  • size (in pixels) of square the patch is drawn on

  • freq: frequency of grating (number of wavelengths in size)

  • sd: standard deviation, in pixels, of gaussian window

  • angle: angle of rotation of grating, in radians

  • phase: phase offset of grating (in radians)

  • bglev: number between 0 and 255 indicating background color in greyscale.

    { }

Usage:

define MakeGabor(...)

Example:

win <- MakeWindow()
patch <- MakeGabor(80, 0,10,0,0,100)
AddObject(patch,win)
Move(patch,200,200)
Draw()

See Also:

MakeAttneave(), SetPixel(), MakeCanvas()

MakeGraph()

Description:

Creates a simple bargraph that can be added to/moved on a window..

Usage:

define MakeGraph(...)

MakeNGonPoints()

Creates points for a polygon, which can then be fed to Polygon

Description:

Creates a set of points that form a regular n-gon. It can be transformed with functions like RotatePoints, or it can be used to create a graphical object with Polygon. Note: MakeNGonPoints returns a list like:

  [[x1, x2, x3,...],[y1,y2,y3,...]],

while Polygon() takes the X and Y lists independently.

Usage:

define MakeNGonPoints(...)

Example:

window <- MakeWindow()
ngonp <- MakeNGonPoints(50,10)
ngon <- Polygon(200,200,First(ngonp),Nth(ngonp,2),
                MakeColor("red"),1)
AddObject(ngon,window)
Draw()

See Also:

MakeStarPoints, Polygon, RotatePoints, ZoomPoints

MakeStarPoints()

Creates points for a star, which can then be fed to Polygon

Description:

Creates a set of points that form a regular star. It can be transformed with functions like RotatePoints, or it can be used to create a graphical object with Polygon. Note: MakeStarPoints returns a list:

  [[x1, x2, x3,...],[y1,y2,y3,...]],

while ``Polygon()`` takes the X and Y lists independently.

Usage:

define MakeStarPoints(...)

Example:

window <- MakeWindow()
sp <- MakeStarPoints(50,20,10)
star <- Polygon(200,200,First(sp),Nth(sp,2),
                MakeColor("red"),1)
AddObject(star,window)
Draw()

See Also:

MakeNGonPoints, Polygon, RotatePoints, ZoomPoints

NonOverlapLayout()

Creates a set of num points that don’t overlap, but fails gracefully

Description:

Creates a set of num points in a xy range, that have a (soft) minimum tolerance of ‘tol’ between points. That is, to the extent possible, the returned points will have a minumum distance between them of <tol>. This may not be possible or be very difficult, and so after a limited number of attempts (by default, 100), the algorithm will return the current configuration, which may have some violations of the minimum tolerance rule, but it will usually be fairly good. The algorithm works by initializing with a random set of points, then computing a pairwise distance matrix between all points, finding the closest two points, and resampling one of them until its minumum distance is larger than the current. Thus, each internal iteration uniformly improves (or keeps the configuration the same), and the worst points are reconfigured first, so that even if a configuration that does not satisfy the constraints, it will usually be very close. Internally, the function (located in pebl-lib/Graphics.pbl) has a variable that controls how many steps are taken, called limit, which is set to 100. For very compacted or very large iterations, this limit can be increased by editing the file or making a copy of the function. The function usually returns fairly quickly, so it can often be used real-time between trials. However, for complex enough configurations, it can take on the order of seconds; furthermore, more complex configurations might take longer than less complex configurations, which could represent a potential confound (if more complex stimuli have longer ISIs). Users should thus consider creating the configurations when the test is initialized, or created prior to the study and then saved out to a file for later use. newpage

Usage:

define NonOverlapLayout(...)

Example:

Example PEBL Program using NonoverlapLayout:

define Start(p)
 {
   win <- MakeWindow()
   ## Make 25 points in a square in the middle
   ## of the screen, a minimum of 50 pixels apart.
   ## This is too compact, but it will be OK.

   points <- NonOverlapLayout(100,300,200,400,50,25)
   circs <- []
   ##This should non-overlapping circles of radius 25
   loop(i,points)
    {
       tmp <- Circle(First(i),Second(i),25,
                     MakeColor("blue"),0)
       AddObject(tmp,win)
       circs <- Append(circs,tmp)
    }


   rect1 <- Square(200,300,200,MakeColor("black"),0)
   rect2 <- Square(600,300,200,MakeColor("black"),0)

   AddObject(rect1,win)
   AddObject(rect2,win)
   ##Reduce the tolerance: this one should be bettter
   points <- NonOverlapLayout(500,700,200,400,50,15)


   ##This should non-overlapping circles of radius 15
   loop(i,points)
    {
       tmp <- Circle(First(i),Second(i),
                     15,MakeColor("blue"),0)
       AddObject(tmp,win)
        circs <- Append(circs,tmp)
    }
   Draw()
   WaitForAnyKeyPress()

}

The output of the above program is shown below.  Even for the left configuration, which is too compact (and which takes a couple seconds to run), the targets are fairly well distributed.

See Also:

LayoutGrid()

Plus()

Creates a plus sign as a useable polygon which can be added to a window directly.

Description:

Creates a polygon in the shape of a plus sign. Arguments include position in window.

  • <x> and <y> is the position of the center

  • <size> or the size of the plus sign in pixels

  • <width> thickness of the plus

  • <color> is a color object (not just the name)

    Like other drawn objects, the plus must then be added to the window to appear.

Usage:

define Plus(...)

Example:

win <- MakeWindow()
p1 <- Plus(100,100,80,15,MakeColor("red"))
AddObject(p1,win)
Draw()

See Also:

BlockE(), Polygon(), MakeStarPoints(), MakeNGonPoints()

ReflectPoints()

Reflects points on vertical axis

Description:

Takes a set of points (defined in a joined list [[x1,x2,x3,…],[y1,y2,y3,…]] and reflects them around the vertical axis x=0, returning a similar [[x],[y]] list. Identical to ZoomPoints(pts,-1,1)

Usage:

define ReflectPoints(...)

Example:

points <- [[1,2,3,4],[20,21,22,23]]
newpoints <- ReflectPoints(points)

See Also:

ZoomPoints(), RotatePoints()

ResetCanvas()

Resets a canvas to its background, erasing anything drawn on the canvas

Description:

Resets a canvas, so that anything drawn onto it is erased and returned to its background color. Implemented by resetting the background color to itself:

 canvas.color <- canvas.

The function does not return the canvas,   but has the side effect of resetting it.

Usage:

define ResetCanvas(...)

Example:

#create a canvas, add pixel noise, then reset and repeat.
define Start(p)
{
  gWin <- MakeWindow()
  canvas <- MakeCanvas(100,100,MakeColor("black"))
  AddObject(canvas,gWin); Move(canvas,300,300)
  Draw()
  white <- MakeColor("white")
  ##add pixel noise
  j <- 1
  while(j < 5)
   {
  i <- 1
  while(i < 200)
   {
     SetPixel(canvas,Round(Random()*100),
              Round(Random()*100),white)
     i <- i +1
   }
  Draw()
  WaitForAnyKeyPress()
  ResetCanvas(canvas)
  Draw()
   j <- j + 1
  }
  WaitForAnyKeyPress()

}

See Also:

SetPixel(), MakeCanvas(), Draw()

RGBtoHSV()

Converts a color to HSV triple

Description:

Converts a color object to HSV values. May be useful for computing color-space distances an so on. No HSVtoRGB is currently implemented.

Usage:

define RGBtoHSV(...)

Example:

x <- RGBtoHSV(MakeColor("red))

See Also:

MakeColor(), MakeColorRGB()

RotatePoints()

Description:

Takes a set of points (defined in a joined list [[x1,x2,x3,...], [y1,y2,y3,...]] and rotates them <angle> degrees around the point [0,0], returning a similar [[x],[y]] list.

Usage:

define RotatePoints(...)

Example:

points <- [[1,2,3,4],[20,21,22,23]]
newpoints <- RotatePoints(points,10)

See Also:

ZoomPoints(), ReflectPoints()

SegmentsIntersect()

Determines whether line segment ab intersects cd.

Description:

Determines whether two line segments, defined by four xy point pairs, intersect. Two line segments that share a corner return 0, although they could be considered to intersect. This function is defined in pebl-lib/Graphics.pbl

Usage:

define SegmentsIntersect(...)

Example:

SegmentsIntersect(1,0,2,0,
                  1,2,2,2)  #0

#returns 0, though they share (1,0)
SegmentsIntersect(1,0,2,0,
                   1,0,2,2)
SegmentsIntersect(1,1,3,1,
                  2,2,2,0)  #1

See Also:

GetAngle3, ToRight

ToRight()

Determines whether p3 is te the right of line p1p2

Description:

Determines whether a point p3 is ‘to the right’ of a line segment defined by p1 to p2. Works essentially by computing the determinant.

Usage:

define ToRight(...)

Example:

a <- [100,0]
b <- [100,100]
c <- [150,50]
ToRight(a,b,c) # returns 1; true
ToRight(b,a,c) # returns 0; false

See Also:

GetAngle(), GetAngle3(), SegmentsIntersect()

ZoomPoints()

Zooms a set of points in 2 directions

Description:

Takes a set of points (defined in a joined list [[x1,x2,x3,…],[y1,y2,y3,…]] and adjusts them in the x and y direction independently, returning a similar [[x],[y]] list. Note: The original points should be centered at zero, because the get adjusted relative to zero, not relative to their center.

Usage:

define ZoomPoints(...)

Example:

points <- [[1,2,3,4],[20,21,22,23]]
newpoints <- ZoomPoints(points,2,.5)
##Produces [[2,4,6,8],[10,11.5,11,11.5]]

See Also:

RotatePoints(), ReflectPoints()

Functions Pending Documentation

GetMinDist()

Finds the minimum distance between any two points in a list

Description:

Computes and returns the minimum distance between any pair of points in a list of [x,y] coordinate pairs. This function examines all possible pairs of points and returns the smallest distance found. Useful for validating point distributions, checking spacing constraints, or analyzing geometric layouts.

Usage:

define GetMinDist(pts)

Example:

points <- [[0, 0], [10, 0], [5, 5], [100, 100]]
minDist <- GetMinDist(points)
Print(minDist)
# Result: 7.07107  (distance between [5,5] and [10,0])

# Check if points are spaced far enough apart
layout <- NonOverlapLayout(100, 400, 100, 400, 50, 20)
spacing <- GetMinDist(layout)
if(spacing < 50)
{
   Print("Warning: some points are too close together")
}

See Also:

NonOverlapLayout(), Dist()

HideObject()

Hides a custom graphical object

Description:

Hides a custom graphical object by hiding its canvas. This function is designed for use with complex custom objects that have a .canv property containing their graphical representation. The object remains in memory but is not displayed until shown again with ShowObject(). This is useful for temporarily removing custom stimuli from view without destroying them.

Usage:

define HideObject(obj)

Example:

# Create a custom object with a canvas
myObject <- MakeCustomShape()  # hypothetical function

# Display the object
ShowObject(myObject)
Draw()
Wait(1000)

# Hide the object temporarily
HideObject(myObject)
Draw()
Wait(1000)

# Show it again
ShowObject(myObject)
Draw()

See Also:

ShowObject(), Hide(), Show()

LandoltRing()

Creates a Landolt C ring stimulus for visual acuity testing

Description:

Creates a Landolt C (also known as Landolt ring), a classic visual acuity stimulus used in optometry and vision research. The Landolt C is a ring with a gap at a specified angular position. Subjects identify the location of the gap to assess visual acuity. The function returns a canvas object containing the rendered stimulus.

The Landolt C was introduced by Edmund Landolt in 1888 (Landolt, E. Methode optométrique simple. Bull Mem Soc Fran Ophtalmol. 1888;6:213–4) and remains a standard stimulus in visual psychophysics and clinical vision testing.

Parameters:

  • outer: Outer diameter of the ring in pixels

  • inner: Inner diameter (size of the central hole) in pixels

  • angle: Angular position of the gap in degrees (0=right, 90=down, 180=left, 270=up)

  • lgap: Width of the gap in pixels

  • color: Color object for the ring

  • bgcolor: Color object for the background and gap

Usage:

define LandoltRing(outer, inner, angle, lgap, color, bgcolor)

Example:

gWin <- MakeWindow()
black <- MakeColor("black")
white <- MakeColor("white")

# Create a Landolt C with gap on the right (0 degrees)
ring1 <- LandoltRing(100, 60, 0, 20, black, white)
AddObject(ring1, gWin)
Move(ring1, 200, 200)

# Create a smaller ring with gap at bottom (90 degrees)
ring2 <- LandoltRing(60, 40, 90, 12, black, white)
AddObject(ring2, gWin)
Move(ring2, 400, 200)

# Create rings at different orientations for acuity test
angles <- [0, 45, 90, 135, 180, 225, 270, 315]
loop(i, Sequence(1, Length(angles), 1))
{
   ring <- LandoltRing(80, 50, Nth(angles, i), 15, black, white)
   AddObject(ring, gWin)
   Move(ring, 100 + i*80, 300)
}

Draw()
WaitForAnyKeyPress()

See Also:

Circle(), BlockE(), MakeCanvas()

MakeTable()

Creates a formatted table display with headers and data

Description:

Creates a visual table object containing data arranged in rows and columns with headers. Returns a custom table object drawn on a canvas that can be added to a window and positioned like other graphical objects. The table includes horizontal rules separating the header from data and bordering the table. Headers can be multi-row (nested lists). Useful for displaying results, feedback, or structured information to participants.

Parameters:

  • data: Nested list of data values (rows × columns)

  • header: List of column headers (can be nested for multi-row headers)

  • width: Total width of the table in pixels

  • height: Total height of the table in pixels

  • fontsize: Base font size for table text

  • fgcol: Foreground color object for text and lines

  • bgcolor: Background color object for the table

  • layout: Layout mode (default: 1)

Usage:

define MakeTable(data, header, width, height, fontsize, fgcol, bgcol, layout: 1)

Example:

gWin <- MakeWindow()
black <- MakeColor("black")
white <- MakeColor("white")

# Create a simple results table
headers <- ["Trial", "RT (ms)", "Accuracy"]
data <- [[1, 523, "Correct"],
         [2, 456, "Correct"],
         [3, 678, "Error"],
         [4, 501, "Correct"]]

table <- MakeTable(data, headers, 400, 300, 16, black, white)
AddObject(table.canv, gWin)
Move(table.canv, 400, 300)
Draw()
WaitForAnyKeyPress()

See Also:

MakeCanvas(), MakeLabel(), EasyLabel()

ShowObject()

Shows a custom graphical object

Description:

Shows a custom graphical object by displaying its canvas. This function is designed for use with complex custom objects that have a .canv property containing their graphical representation. Use this to display objects that were previously hidden with HideObject() or to initially display custom objects after creation. The object must have been created with a canvas property for this function to work properly.

Usage:

define ShowObject(obj)

Example:

# Create a custom object with a canvas
myObject <- MakeCustomShape()  # hypothetical function

# Initially hide the object
HideObject(myObject)
Draw()

# Wait for user input
WaitForAnyKeyPress()

# Now show the object
ShowObject(myObject)
Draw()

# Toggle visibility
if(someCondition)
{
   ShowObject(myObject)
} else {
   HideObject(myObject)
}

See Also:

HideObject(), Show(), Hide()

Functions Under Investigation

ThickLine2()

Warning

Under investigation. This function’s status is being reviewed.

Usage:

define ThickLine2(x1,y1,x2,y2,size,color)