02-22-2020, 10:57 PM
HP Prime does not have a function which draws a filled circle. I have seen many attempts to implement a substitute by drawing concentric circles with one pixel increment radii, but it does not work well, and the area of such a circle is usually not uniform.
Recently I was working on an application that really could use such a filled circle... it was not absolutely necessary, but it definitely look nice... I decided to spend an hour or two on writing such a procedure.
Maybe somebody will find it useful, and will save time he would otherwise have to spend on writing it.
A program below consists of a procedure drawing a filled circle (FILLCIRCLE_P), and a few small demo/test additions. FILLCIRCLE_P() can be included in the program, or in a library. It draws a filled polygon (a function supported by HP Prime) which vertices are placed on the perimeter of the circle. (One of many methods to draw a filled circle; I am not saying the best one or the fastest one.)
The code is very simple and self explanatory.
One comment I would like to make is that the first, initial version of the code was not taking advantage of the symmetry of circle quadrants. I optimized the code later counting on increase of the speed of drawing. To my surprise, the increase of speed was smaller than 20%! This means that either calculation of trigonometric functions is fast, or that calculations related to list indexing and/or drawing filled polygon is slow. I did not have time to explore this subject deeper.
Darius
Recently I was working on an application that really could use such a filled circle... it was not absolutely necessary, but it definitely look nice... I decided to spend an hour or two on writing such a procedure.
Maybe somebody will find it useful, and will save time he would otherwise have to spend on writing it.
A program below consists of a procedure drawing a filled circle (FILLCIRCLE_P), and a few small demo/test additions. FILLCIRCLE_P() can be included in the program, or in a library. It draws a filled polygon (a function supported by HP Prime) which vertices are placed on the perimeter of the circle. (One of many methods to draw a filled circle; I am not saying the best one or the fastest one.)
Code:
EXPORT FILLCIRCLE_P (nG, nX, nY, nRadius, nSmoothness, nColor)
BEGIN
// Print filled circle ver. 1.2, (c) dap, 2020
// Arguments:
// nG - graphic variable to use for printing
// nX, nY - pixel coordinates of the center of the circle
// nRadius - radius of the circle (in pixels)
// nSmoothness - smoothness of the circle defined as length of sagitta (in pixels, may be fractional)
// nColor - color of the circle
// Returns 0 if no error, (-1) if nSmoothness below limit
LOCAL lVertices = {};
LOCAL I, nHAngleBuffer, nAlpha, nNumberOfPoints;
// check input parameters
IF nSmoothness<0.05 THEN
RETURN (-1);
END;
nHAngleBuffer := HAngle;
HAngle := 1; // set angle to degrees
// caclulate angle increment
nNumberOfPoints := CEILING(90/(2*ACOS(1-nSmoothness/nRadius)));
nAlpha := 90/nNumberOfPoints;
// calculate polygon vertices
nNumberOfPoints := FLOOR (nNumberOfPoints);
FOR I FROM 1 TO nNumberOfPoints DO
lVertices(I) := (nX+ROUND(nRadius*SIN((I-1)*nAlpha),0), nY-ROUND(nRadius*COS((I-1)*nAlpha),0));
lVertices(nNumberOfPoints+I):= (nX+(nY-IM(lVertices(I))), nY+(RE(lVertices(I))-nX));
lVertices(2*nNumberOfPoints+I):= (2*nX-(RE(lVertices(I))), 2*nY-(IM(lVertices(I))));
lVertices(3*nNumberOfPoints+I):= (nX+(IM(lVertices(I))-nY), nY-(RE(lVertices(I))-nX));
END;
// print polygon
FILLPOLY_P (nG, lVertices, nColor);
// *** for debugging ***
// print vertices
// when enabled, vertices are marked with white dots
// (to see vertices only, comment out FILLPOLY_P above)
// FOR I FROM 1 TO SIZE(lVertices) DO
// PIXON_P (G0, RE(lVertices(I)), IM(lVertices(I)), RGB(255,255,255));
// END;
HAngle := nHAngleBuffer; // restore previous angle setting
RETURN 0;
END;
// *** DEBUGGING/TEST PROCEDURES ***
// (exit by pressing Esc)
// prototypes
WAIT_FOR_ESCAPE_KEY ();
EXPORT SPEED_TEST ()
BEGIN
// test speed
// prints concentric circles of given smoothness and calculates printing times
LOCAL I, J, nIndex, R, G, B;
LOCAL nTStart, nTAccumulated;
LOCAL nRuns := 100;
LOCAL nSmoothness;
LOCAL lSmoothness := {0.1, 0.2, 0.5, 1.0, 2.0, 5.0};
CHOOSE(nIndex, "Choose smoothness", "0.05", "0.1", "0.2", "0.5", "1.0", "2.0","0.05 one time","2.0 one time");
CASE
IF (nIndex==7) THEN
nSmoothness := 0.05;
nRuns := 1;
END;
IF (nIndex==8) THEN
nSmoothness := 2.0;
nRuns := 1;
END;
DEFAULT
nSmoothness := lSmoothness(nIndex);
END; // CASE
STARTVIEW(-1);
RECT(RGB(0,0,0));
FOR I FROM 16 DOWNTO 1 DO
nTAccumulated := 0;
FOR J FROM 0 TO nRuns DO
R := RANDINT(0,255);
G := RANDINT(0,255);
B := RANDINT(0,255);
nTStart := TICKS();
FILLCIRCLE_P (G0, 160, 120, I*10, nSmoothness, RGB(R, G, B));
nTAccumulated := nTAccumulated+(TICKS()-nTStart);
END;
TEXTOUT_P (nTAccumulated/nRuns, 2, 10+12*(I-1), 1, RGB(255,255,0));
END;
WAIT_FOR_ESCAPE_KEY ();
END;
EXPORT SMOOTHNESS_TEST ()
BEGIN
// prints 12 circles of different smoothness
LOCAL I, J;
LOCAL lSmoothness := {0.05, 0.1, 0.2, 0.5, 0.8, 1.0, 1.5, 2.0, 4.0, 6.0, 8.0, 9.0};
STARTVIEW(-1);
RECT(RGB(0,0,0));
FOR J FROM 1 TO 3 DO
FOR I FROM 1 TO 4 DO
FILLCIRCLE_P (G0, 64*I, 60*J, 24, lSmoothness(I+(J-1)*4), RGB(255,0,0));
TEXTOUT_P (STRING(lSmoothness(I+(J-1)*4),2,2), 64*I-10, 60*J-4, 2, RGB(255,255,255));
END;
END;
WAIT_FOR_ESCAPE_KEY ();
END;
EXPORT JUST_ONE_CENTERED_CIRCLE ()
BEGIN
// prints single centered circle
STARTVIEW(-1);
RECT(RGB(0,0,0));
FILLCIRCLE_P (G0, 160, 120, 100, 0.05, RGB(255,0,0));
LINE_P(G0, 0, 120, 319, 120, RGB(0,255,0));
LINE_P(G0, 160, 0, 160, 239, RGB(0,255,0));
WAIT_FOR_ESCAPE_KEY ();
END;
EXPORT BUBBLES ()
BEGIN
// prints circles of random color, size, and smoothness at random locations
STARTVIEW(-1);
RECT(RGB(255,255,255));
REPEAT
FILLCIRCLE_P (G0, RANDINT(0,319), RANDINT(0,239), RANDINT(5,80), RANDINT(5,500)/100, RGB(RANDINT(0,255),RANDINT(0,255),RANDINT(0,255)));
WAIT(0.5);
UNTIL GETKEY()==4;
END;
// *** supporting procedures ***
WAIT_FOR_ESCAPE_KEY ()
BEGIN
// wait until Esc key is pressed
LOCAL nKey;
REPEAT
nKey:=GETKEY;
UNTIL nKey==4;
END;
One comment I would like to make is that the first, initial version of the code was not taking advantage of the symmetry of circle quadrants. I optimized the code later counting on increase of the speed of drawing. To my surprise, the increase of speed was smaller than 20%! This means that either calculation of trigonometric functions is fast, or that calculations related to list indexing and/or drawing filled polygon is slow. I did not have time to explore this subject deeper.
Darius