1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
|
/*
SCREENFillArc.cpp
Draw a filled arc, like a part of a pie-chart.
AUTHORS:
Allen.Ingling@nyu.edu awi
mario.kleiner at tuebingen.mpg.de mk
PLATFORMS:
Should compile and work for all platforms.
NOTES:
HISTORY:
12/11/05 mk Created. Derived from Allen Inglings gluDisc.
TO DO:
*/
#include "Screen.h"
// The routine that does the real work - see at bottom of file:
void PsychRenderArc(unsigned int mode);
PsychError SCREENDrawArc(void)
{
// If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
static char useString[] = "Screen('DrawArc',windowPtr,[color],[rect],startAngle,arcAngle)";
// 1 2 3 4 5
static char synopsisString[] =
"Draw an arc inscribed within the rect. 'color' is the clut index (scalar "
"or [r g b] triplet) that you want to poke into each pixel; default produces "
"black with the standard CLUT for this window's pixelSize. Default 'rect' is "
"entire window. Angles are measured clockwise from vertical.";
static char seeAlsoString[] = "FrameArc FillArc";
//all sub functions should have these two lines
PsychPushHelp(useString, synopsisString,seeAlsoString);
if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
//check for superfluous arguments
PsychErrorExit(PsychCapNumInputArgs(5)); //The maximum number of inputs
PsychErrorExit(PsychRequireNumInputArgs(3)); //The minimum number of inputs
PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs
// Render arc of type 1 - Just the outline.
PsychRenderArc(1);
return(PsychError_none);
}
PsychError SCREENFrameArc(void)
{
// If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
static char useString[] = "Screen('FrameArc',windowPtr,[color],[rect],startAngle,arcAngle, [penWidth], [penHeight], [penMode])";
// 1 2 3 4 5 6 7 8
static char synopsisString[] =
"Draw an arc inscribed within the rect. 'color' is the clut index (scalar "
"or [r g b] triplet) that you want to poke into each pixel; default produces "
"black with the standard CLUT for this window's pixelSize. Default 'rect' is "
"entire window. Angles are measured clockwise from vertical. 'penWidth' and "
"'penHeight' are the width and height of the pen to use. penWidth must equal "
"penHeight and the 'penMode' argument is currently ignored.";
static char seeAlsoString[] = "DrawArc FillArc";
//all sub functions should have these two lines
PsychPushHelp(useString, synopsisString,seeAlsoString);
if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
//check for superfluous arguments
PsychErrorExit(PsychCapNumInputArgs(8)); //The maximum number of inputs
PsychErrorExit(PsychRequireNumInputArgs(3)); //The minimum number of inputs
PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs
// Render arc of type 2 - Just the outline with penWidth.
PsychRenderArc(2);
return(PsychError_none);
}
PsychError SCREENFillArc(void)
{
// If you change useString then also change the corresponding synopsis string in ScreenSynopsis.c
static char useString[] = "Screen('FillArc',windowPtr,[color],[rect],startAngle,arcAngle)";
// 1 2 3 4 5
static char synopsisString[] =
"Draw a filled arc inscribed within the rect. 'color' is the clut index (scalar "
"or [r g b a] triplet) that you want to poke into each pixel; default produces "
"black with the standard CLUT for this window's pixelSize. Default 'rect' is "
"entire window. Angles are measured clockwise from vertical.";
static char seeAlsoString[] = "DrawArc FrameArc";
//all sub functions should have these two lines
PsychPushHelp(useString, synopsisString,seeAlsoString);
if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
//check for superfluous arguments
PsychErrorExit(PsychCapNumInputArgs(5)); //The maximum number of inputs
PsychErrorExit(PsychRequireNumInputArgs(3)); //The minimum number of inputs
PsychErrorExit(PsychCapNumOutputArgs(0)); //The maximum number of outputs
// Render arc of type 3 - Filled arc.
PsychRenderArc(3);
return(PsychError_none);
}
void PsychRenderArc(unsigned int mode)
{
PsychColorType color;
PsychRectType rect;
double *startAngle, *arcAngle, *penWidth, *penHeight;
PsychWindowRecordType *windowRecord;
double whiteValue;
double dotSize = 1;
psych_bool isArgThere;
GLUquadric *diskQuadric = NULL;
double cx, cy, w, h;
//get the window record from the window record argument and get info from the window record
PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord);
//Get the color argument or use the default, then coerce to the form determened by the window depth.
isArgThere=PsychCopyInColorArg(kPsychUseDefaultArgPosition, FALSE, &color);
if(!isArgThere){
whiteValue=PsychGetWhiteValueFromWindow(windowRecord);
PsychLoadColorStruct(&color, kPsychIndexColor, whiteValue ); //index mode will coerce to any other.
}
PsychCoerceColorMode( &color);
// Get the rect to which the object should be inscribed: Default is "full screen"
PsychMakeRect(rect, 0, 0, PsychGetWidthFromRect(windowRecord->clientrect), PsychGetHeightFromRect(windowRecord->clientrect));
PsychCopyInRectArg(3, FALSE, rect);
if (IsPsychRectEmpty(rect)) return;
w=PsychGetWidthFromRect(rect);
h=PsychGetHeightFromRect(rect);
PsychGetCenterFromRectAbsolute(rect, &cx, &cy);
if (w==0 || h==0) PsychErrorExitMsg(PsychError_user, "Invalid rect (width or height equals zero) provided!");
// Get start angle:
PsychAllocInDoubleArg(4, TRUE, &startAngle);
PsychAllocInDoubleArg(5, TRUE, &arcAngle);
if (mode==2) {
// Get pen width and height:
penWidth=NULL;
penHeight=NULL;
PsychAllocInDoubleArg(6, FALSE, &penWidth);
PsychAllocInDoubleArg(7, FALSE, &penHeight);
// Check if penWidth and penHeight spec'd. If so, they
// need to be equal:
if (penWidth && penHeight && (*penWidth!=*penHeight)) {
PsychErrorExitMsg(PsychError_user, "penWidth and penHeight must be equal if both are specified!");
}
dotSize=1;
if (penWidth) dotSize = *penWidth;
if (penHeight) dotSize = *penHeight;
}
// Enable this windowRecords framebuffer as current drawingtarget:
PsychSetDrawingTarget(windowRecord);
// Set default drawshader:
PsychSetShader(windowRecord, -1);
PsychUpdateAlphaBlendingFactorLazily(windowRecord);
PsychSetGLColor(&color, windowRecord);
if (PsychIsGLClassic(windowRecord)) {
// Backup our modelview matrix:
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Position disk at center of rect:
glTranslated(cx, cy, 0);
// Scale in order to fit to rect in case w!=h:
glScaled(1.0, -h/w, 1.0);
// Draw filled partial disk:
diskQuadric=gluNewQuadric();
switch (mode) {
case 1: // One pixel thin arc: InnerRadius = OuterRadius - 1
gluPartialDisk(diskQuadric, (w/2) - 1.0, w/2, (int) w, 2, *startAngle, *arcAngle);
break;
case 2: // dotSize thick arc: InnerRadius = OuterRadius - dotsize
gluPartialDisk(diskQuadric, (dotSize < (w/2)) ? (w/2) - dotSize : 0, w/2, (int) w, 2, *startAngle, *arcAngle);
break;
case 3: // Filled arc:
gluPartialDisk(diskQuadric, 0, w/2, (int) w, 1, *startAngle, *arcAngle);
break;
}
gluDeleteQuadric(diskQuadric);
// Restore old matrix:
glPopMatrix();
}
else {
switch (mode) {
case 1: // One pixel thin arc: InnerRadius = OuterRadius - 1
PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) ((w/2) - 1.0), (float) w/2, (int) w, (float) 1, (float) -h / (float) w, (float) *startAngle, (float) *arcAngle);
break;
case 2: // dotSize thick arc: InnerRadius = OuterRadius - dotsize
PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) ((dotSize < (w/2)) ? (w/2) - dotSize : 0), (float) w / 2, (int) w, (float) 1, (float) -h/ (float) w, (float) *startAngle, (float) *arcAngle);
break;
case 3: // Filled arc:
PsychDrawDisc(windowRecord, (float) cx, (float) cy, (float) 0, (float) w / 2, (int) w, (float) 1, (float) -h / (float) w, (float) *startAngle, (float) *arcAngle);
break;
}
}
// Mark end of drawing op. This is needed for single buffered drawing:
PsychFlushGL(windowRecord);
return;
}
|