Post Reply 
FILLCIRCLE_P()
02-22-2020, 10:57 PM
Post: #1
FILLCIRCLE_P()
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.)

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;
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
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
FILLCIRCLE_P() - DrDarius - 02-22-2020 10:57 PM
RE: FILLCIRCLE_P() - Carlos295pz - 02-22-2020, 11:22 PM
RE: FILLCIRCLE_P() - DrDarius - 02-23-2020, 01:10 AM
RE: FILLCIRCLE_P() - tgallo - 03-01-2020, 01:25 AM



User(s) browsing this thread: 1 Guest(s)