Search code examples
graphicstrigonometrycairobounding-box

Calculate bounding box of line with thickness


I have a problem calculating the bounding boxes of specific lines. I have drawn the three types of lines I use in the following figure.

lines with different caps

The lines are specified by 3 points (marked red) but can have an arbitrary number of points. The lines can have different line caps:

  1. no line cap
  2. rectangular cap (line is line_width/2 longer at the ends)
  3. round caps (circle with radius line_width/2)

Is it possible to create such a line using a graphics framework like Cairo and get the bounding box out of Cairo, or do I have to calculate it using trigonometric approaches on my own?

I program in C.

I already have a function to calculate the bounding box of a polygon. Is there an easy way to convert these lines into polygons so that I can use my existing functions?

I'm asking this question because I hope someone has an efficient approach to solving this problem. My program has to parse a big graphics file with a lot of these lines and extract the individual bounding boxes.


Edit

I have found following link for Cairo. It seems to support these line types: Cairo line caps

I wanted to add: I have never used Cairo. I just stumbled across it during my search. I am a complete beginner with it.


Solution

  • I have discovered the Cairo Recoding Surface which exactly does, what I need. I draw my objects inside the unlimited recording surface and let Cairo compute the bounding box.

    A small example that creates some lines and calculates the bounding box looks as follows:

    void main(void)
    {
      cairo_surface_t *rec;
      cairo_t *cr;
      double x0, y0, width, height;
    
      rec = cairo_recording_surface_create(CAIRO_CONTENT_COLOR_ALPHA, NULL);
      cr = cairo_create(rec);
      cairo_scale(cr, 10, 10);
    
      cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
      cairo_set_line_width(cr, 2);
    
      cairo_move_to(cr, 0, 0);
      cairo_rel_line_to(cr, 0, 20);
      cairo_rel_line_to(cr, 5, 0);
      cairo_rel_line_to(cr, 1, 1);
      cairo_stroke(cr);
    
      cairo_recording_surface_ink_extents(rec, &x0, &y0, &width, &height);
      printf("Size: %lf / %lf at (%lf, %lf)\n", width, height, x0, y0);
    }