complex_polygon

24 views
Skip to first unread message

holm.h...@gmail.com

unread,
Dec 30, 2021, 3:56:54 AM12/30/21
to fltk.general

Hello,

I want to implement my own version of fl_complex_polygon.
I want to draw a concave polygon to a pixmap.

To me it seems like fltk have efficient argorithms to do that. I have been looking around to find the code where this is implemented without any luck.

Can any please give me a hint on how this is implemented in fltk / code ?

Best regards
Håvard

Albrecht Schlosser

unread,
Dec 30, 2021, 7:24:36 AM12/30/21
to fltkg...@googlegroups.com
On 12/30/21 9:56 AM holm.h...@gmail.com wrote:
I want to implement my own version of fl_complex_polygon.
I want to draw a concave polygon to a pixmap.

Why do you want to reinvent the wheel?


To me it seems like fltk have efficient argorithms to do that.

Yes.


I have been looking around to find the code where this is implemented without any luck.

Note that FLTK code is provided under its copyright, you are generally not allowed to *copy* the code to your own source files.


Can any please give me a hint on how this is implemented in fltk / code ?

This code is platform dependent and you can find large portions of it in the platform specific graphics driver code, e.g. src/Fl_Graphics_Driver.cxx (platform independent parts) and src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx (Windows driver(s)) but there are more files involved which I can't enumerate here.

If you still can't find what you're looking for you can run example code with a debugger and follow the calling sequence ...

Matthias Melcher

unread,
Dec 30, 2021, 11:18:14 AM12/30/21
to fltk.general
There are several resources out there that explain how it's done step by step. Google is your friend. FLTK does not draw polygons on a pixel level, but uses the polygon drawing functions that are available on the give host system.


Ian MacArthur

unread,
Dec 31, 2021, 12:29:27 PM12/31/21
to Fltk General
Håvard,

What is it you are trying to do?
You can pretty easily use the fltk drawing functions to draw concave polygons into an Fl_Image_Surface (or some other offscreen surface) and then use that for your pixmap.

I think others have understood your question as asking how the low-level drawing actually works at the OS level, but I’m not sure if that was what you were asking or not.

So... what are you trying to achieve, and we can see where we are...

Cheers.


ps: and a Happy New Year to all our readers (etc., at least for those following some variation on the Gregorian calendar scheme...)

holm.h...@gmail.com

unread,
Jan 2, 2022, 3:50:20 AM1/2/22
to fltk.general
Hi Ian,

I use OpenGL for rendering some graphics. This is useful especially for 3d objects. OpenGL do however not have routines for drawing complex polygons. It is possible to draw complex polygons using tessellation, but this approach also have its limitations. Also I would like to know which pixels are encapsulated by polygons since I want to treat these areas special.

I have tested a variety of codes/routines out there for drawing a complex polygon, but I find it difficult to compete with the routines implemented in fltk.

Currently I do :
 oscr = fl_create_offscreen(nx, ny);
 fl_begin_offscreen(oscr);
fl_rectf(0, 0, 100, 50);  // for testing: draw some objects..
fl_read_image(pix, 0, 0, nx, ny, 0);
fl_end_offscreen();
fl_delete_offscreen(oscr);

This is done repeatably (can be several times a second).  nx and ny can be up to 3840.

In this way I get a pixmap which indicate which pixels are encapsulated be polygons.
My concerns:
    Routines should be fast.
    Require as little memory as possible (a char-pix would do)

Does it make sense to implement this as done above ? Should oscr be a static variable, and only be recreated when  nx,ny changes ?
Is is possible to use a one-char pixmap in fl_read_image ?

Best regards
Håvard

holm.h...@gmail.com

unread,
Jan 2, 2022, 5:00:25 AM1/2/22
to fltk.general

Hi,

Feels like my code now is quite a bit slower, also showed by gprof:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total          
 time   seconds   seconds    calls  ms/call  ms/call  name    
 85.66      2.21     2.21                             Fl_X11_Screen_Driver::read_win_rectangle(int, int, int, int, Fl_Window*, bool, bool*)
  3.49      2.30     0.09                             fl_read_image(unsigned char*, int, int, int, int, int)

I think read_win_rectangle is called from fl_read_image and do eat quite some cpu-cycles.

Best regard
Håvard

Matthias Melcher

unread,
Jan 2, 2022, 3:01:33 PM1/2/22
to fltk.general
I doubt that this is solving your original problem, especially if you are in the 3D OpenGL world. Triangulation is IMHO the correct way to go, and it has no limitations that I am aware of. Anyway, the code below draws a complex polygon by drawing horizontal lines to fill the area.

```

  class Vertex {

  public:

    void set(float x, float y, bool gap = false) { pX = x; pY = y; pIsGap = gap; }

    float pX, pY;

    bool pIsGap;

  };


void Fl_Android_Graphics_Driver::end_complex_polygon()

{

  if (pnVertex < 2) return;


  gap(); // adds the first coordinate of this loop and marks it as a gap

  int begin = 0, end = pnVertex;


  Vertex *v = pVertex+0;

  int xMin = v->pX, xMax = xMin, yMin = v->pY, yMax = yMin;

  for (int i = begin+1; i < end; i++) {

    v = pVertex+i;

    if (v->pX < xMin) xMin = v->pX;

    if (v->pX > xMax) xMax = v->pX;

    if (v->pY < yMin) yMin = v->pY;

    if (v->pY > yMax) yMax = v->pY;

  }

  xMax++; yMax++;


  int nodes, nodeX[end - begin], pixelX, pixelY, i, j, swap;


  //  Loop through the rows of the image.

  for (pixelY = yMin; pixelY < yMax; pixelY++) {

    //  Build a list of nodes.

    nodes = 0;

    for (i = begin+1; i < end; i++) {

      j = i-1;

      if (pVertex[j].pIsGap)

        continue;

      if (   (pVertex[i].pY < pixelY && pVertex[j].pY >= pixelY)

          || (pVertex[j].pY < pixelY && pVertex[i].pY >= pixelY) )

      {

        float dy = pVertex[j].pY - pVertex[i].pY;

        if (fabsf(dy)>.0001) {

          nodeX[nodes++] = (int)(pVertex[i].pX +

                                 (pixelY - pVertex[i].pY) / dy

                                 * (pVertex[j].pX - pVertex[i].pX));

        } else {

          nodeX[nodes++] = pVertex[i].pX;

        }

      }

    }

    //Fl_Android_Application::log_e("%d nodes (must be even!)", nodes);


    //  Sort the nodes, via a simple “Bubble” sort.

    i = 0;

    while (i < nodes - 1) {

      if (nodeX[i] > nodeX[i + 1]) {

        swap = nodeX[i];

        nodeX[i] = nodeX[i + 1];

        nodeX[i + 1] = swap;

        if (i) i--;

      } else {

        i++;

      }

    }


    //  Fill the pixels between node pairs.

    for (i = 0; i < nodes; i += 2) {

      if (nodeX[i] >= xMax) break;

      if (nodeX[i + 1] > xMin) {

        if (nodeX[i] < xMin) nodeX[i] = xMin;

        if (nodeX[i + 1] > xMax) nodeX[i + 1] = xMax;

        xyline(nodeX[i], pixelY, nodeX[i + 1]);

      }

    }

  }

}

```

Reply all
Reply to author
Forward
0 new messages