Checking if path is simple and closed using cairo

2019-05-31 15:48发布

问题:

I am using cairomm together with gtkmm for a GUI project. I have defined a GeometricShape abstract widget (which inherits from Gtk::DrawingArea) to inherit from if one needs to draw a square, a circle, etc. This class defines three regions:

  1. a fill (or body area);
  2. a border;
  3. a background area.

The fill area is used to fill in the shape with a certain body color. The border (usually black) defines the shape and the background area is used to fill the remaining space (everything but the border and its related fill area) with a color. Here is an example of how it looks for a circle:

In this case, the background color is green, the border color is blue and the fill region is red (just to be clear). Now one of my class invariants would need to be that the path represented by the border is a simple closed curve. How could I enforce this invariant?

I though about adding some underlying non-cairo logic to check this, for example by providing some kind of SimpleClosedPath object to pass on to cairo (which would itself check the invariant), but I'm not sure how this would be possible, since I want to allow both polygons and curved based shapes, like a circle.

I though about using cairo to perform the check, but the methods for checking paths seem pretty limited. I feel like cairo is not intended to solve this kind of problem.

Do you have any idea how I could ensure this invariant would be respected?

I'm not really looking for code, but more for an idea, something to try.

回答1:

but I'm not sure how this would be possible, since I want to allow both polygons and curved based shapes, like a circle.

Do you know about cairo_copy_path_flat? It gets a flattened copy of the current path, meaning that all curves are approximated with lines.

So, you would somehow get a cairo context (cairo_t in C), create your shape there (with line_to, curve_to, arc etc). Then you do not call fill or stroke, but instead cairo_copy_path_flat.

The resulting path is a series of move_to, line_to and close_path commands which you could then (somehow...) check for intersecting. Checking two straight lines for intersection is relatively straight forward, so you could e.g. just check each line for intersection with every other line.