Den 8 dec. 2016 1:09 em skrev "Ch'Gans" <chg...@gna.org>: > > On 8 December 2016 at 20:40, Elvis Stansvik <elvst...@gmail.com> wrote: > > Den 8 dec. 2016 1:02 fm skrev "Ch'Gans" <chg...@gna.org>: > >> > >> Hi, > >> > >> The documentation of QPainterPathStroker's curve threshold says: > >> ---------------------------------------------------------------- > >> Specifies the curve flattening threshold, controlling the granularity > >> with which the generated outlines' curve is drawn. > >> > >> The default threshold is a well adjusted value (0.25), and normally > >> you should not need to modify it. However, you can make the curve's > >> appearance smoother by decreasing its value. > >> ---------------------------------------------------------------- > >> > >> However i have noticed that when used in a graphics scene with objects > >> of small size, the default threshold value is obviously too big, eg a > >> circle becomes a square! > >> > >> As the doc states that "normally you should not need to modify it", i > >> was reluctant to change it, but then I realised that maybe this > >> default value is actually well adjusted in the context of QWidget, > >> where the unit of measure is "pixel". In a QGraphicsScene the unit is > >> arbitrary. > >> If I'm right, there could be potentially a problem as well if the > >> scene object is too big, eg, a circle will be rendered as a regular > >> polygon with thousands of edges. So it all boil down to find the > >> correct threshold so that both small and big (in scene coordinates) > >> will be rendered in the view (pixel coordinates), using say 26 edges > >> polygon (icosikaihexagon [1][2] ;)) > >> > >> Could anyone shed a bit of light on what "well adjusted" mean and how > >> to actually adjust it to s specific use case? Is this threshold > >> actually expressed in a pixel-related unit of measure? Is it a ratio > >> of something (0.0 to 1.0) ? > > > > I've been wondering the same actually, though it was a long time ago. > > > > The QPainterPathStroker has no information about which scale you intend to > > paint the path, so I guess like you say, it must make some assumption based > > on pixel units and a regular screen size. > > > > For details of how it adjusts this value I think you'll have to look at the > > code. But maybe the docs should be extended a bit. > > Default value is indeed 0.25, but settings the stroke width will > adjust as follow: > threshold = strokeWidth > 4 ? 1.0/strokeWidth : 0.25 > > Tracking the usage of curve threshold lead me to QStroker, QTransform > and QBezier, but man, the code is hairy, even more than me! ;) > > The threshold seems to be adjusted dynamically too in some recursive > algorithm... > > Anyway, there's this interesting comment in QBezier::toPolygon(): > > // flattening is done by splitting the bezier until we can replace > the segment by a straight > // line. We split further until the control points are close > enough to the line connecting the > // boundary points. > // > // the Distance of a point p from a line given by the points (a,b) > is given by: > // > // d = abs( (bx - ax)(ay - py) - (by - ay)(ax - px) ) / line_length > // > // We can stop splitting if both control points are close enough > to the line. > // To make the algorithm faster we use the manhattan length of the line. > > [Note: AFAIK, any non-linear element in a QPainterPath is handled as a > bezier curve, read: circular and ellipsoidal arcs are stored as bezier > curves.] > > If i got it right, at the end of the day, this distance 'd' is > compared to the 'bezier_flattening_threshold' (which is the > curveThreshold from the stroker). Which means that the curve threshold > is actually a ratio b/w 2 distances, so it is unit-less. > > I have observed this problem twice (circle becomes square, couldn't > find the message in the archive). > The first time was due to performing QPainterPath set operations > (union, intersection) on small features (in the order of 10E-3), and > set operations first flatten the path. > Second time is quite similar, small features in a QGraphicsScene, no > set operations, but the path is flatten by the path stroker... > > So if the curve threshold is really unitless, then the only > explanation i can come with is that the flattening algorithm > deteriorate as the input numbers get smaller, due to limitation of > arithmetic on floating point numbers. > > Still, in the formula 'threshold = strokeWidth > 4 ? 1.0/strokeWidth : > 0.25', 0.25 and 4 are obviously magic numbers that seem to consider > the stroke width being expressed in pixels. And - if i'm not wrong - > the documentation is lying: the default is 0.25, *if* the stroke with > is greater than 4. > > To be continued...
Nice digging, I stand corrected. That looks like the normal algorithm for flattening beziers indeed, so I'm also puzzled why it deteriorates for you on small features. I don't think limited machine precision should cause this, unless you're working at a very small scale? Someone who knows the code can surely answer better than me. Elvis > > Chris > > > > > > > > Elvis > > > >> > >> Thanks, > >> Chris > >> > >> [1] https://www.voltage.com/math-2/approximating-a-circle-with-a-polygon/ > >> [2] http://mathforum.org/dr.math/faq/faq.polygon.names.html > >> _______________________________________________ > >> Interest mailing list > >> Interest@qt-project.org > >> http://lists.qt-project.org/mailman/listinfo/interest
_______________________________________________ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest