Important: Please read the Qt Code of Conduct -

Bezier curves and stroking a path

  • I have output of a graph from GraphViz displayed in a QSvgWidget. I would like to construct a list of QPolygon objects for the edges to use in the mouse events mouseMoveEvent and mousePressEvent. The edges are defined as curves by a list of Bézier control points (which GraphViz thankfully supplies in the output of its plain-text renderer), and I need to know how to construct a vector of points to represent an area of approx. 4 pixels on either side of the curve corresponding to a stroked curve of about 8 pixels width parallel to the edge. I would imagine that a small sample set of points would suffice since the polygon would not be displayed but merely used for click testing and for displaying tooltips.

    However, I have no idea how to go about calculating the set of points needed based on input of between 4 and up to 16 or more Bézier control points. Is there a good tutorial somewhere?

    PS - the nodes are no problem since they are merely ellipses.

  • I suppose using QPainterPath would be the correct way to do it instead of creating a polygon myself?

  • Update: GraphViz gives you the B-spline coordinates for each edge when you run it with the -Tplain option. In the meantime, I found the tinyspline tool which seems to do what I need. It seems that there is a difference between B-splines and Bézier curves, but tinyspline can handle both.

    Another problem is converting the coordinates in inches to pixels in the QSvgWidget. It seems that the SVG file is rendered as if in points, because when I multiply the inches and fractions from GraphViz by 72, the coordinates seem to line up fairly well with the center points of the node ellipses -- but not exactly; they are a little skewed to the left and top by a few pixels. Looking at the SVG file which is used, it appears that the width and height are also given as points.

    Then I tried calculating the coordinates as percentages (or ratios) of the graph width and height. They start out looking better than just using 72, but drift off center the farther down and to the right they are. It looks like there is some kind of rounding error at work.

    Can anyone give me a clue as to what might be going on here?

  • Problem solved: GraphViz adds 4 points padding to the X and Y coordinates. This is recorded in the SVG file's "transform" graph attribute. After a preliminary perusal of the GraphViz source code for the SVG rendering, it appears to be hard-wired for every case, as well as point vs. pixel output, but documentation is somewhat lacking about it.

    After adding in the padding, everything seems to line up and scale properly. So I am now marking this question as "solved".

  • Additional info:

    @Robert-Hairgrove said in Bezier curves and stroking a path:

    It seems that there is a difference between B-splines and Bézier curves

    Yes, there is a difference: Bezier curves/surfaces are a special case of B-Spline curves/surfaces.

    The most general description of curves/surfaces is given with Non Uniform Rational B-Splines (NURBS). With NURBS you can describe B-Splines and Bezier geometries.

  • There is documentation which I only found later, that the default padding is always 4 points if none is specified (under the graph's pad property).

Log in to reply