in (pure) cairo it is possible to stroke a path, after restoring the current state/transformation:
cairo_set_line_width (cr, 0.1); cairo_save (cr); cairo_scale (cr, 0.5, 1); cairo_arc (cr, 0.5, 0.5, 0.40, 0, 2 * M_PI); cairo_restore (cr); cairo_stroke (cr); So we can scale the circle arc to an elliptic one, without scaling the stroke width. >From my observation, this is not possible with the current athens rendering scheme: steps in AthensCanvas draw-> setPathTransform loadpath stroke/fill Igor, did I miss something, is it possible with the Athens API ? nicolai 2014-04-23 14:54 GMT+02:00 Henrik Johansen <henrik.s.johan...@veloxit.no>: > > On 23 Apr 2014, at 2:31 , Igor Stasenko <siguc...@gmail.com> wrote: > > > > > On 23 April 2014 13:17, Henrik Johansen <henrik.s.johan...@veloxit.no> > wrote: > >> >> On 22 Apr 2014, at 2:23 , Igor Stasenko <siguc...@gmail.com> wrote: >> >> > as for why there's 4 arc segments instead of one, its because >> > of bad approximation, when drawing more that 90 degree arcs. >> > >> > also, in athens, arc segment is defined with following inputs: >> > - end point of previous segment (implicit) >> > - angle >> > - direction (clockwise/counterclockwise) >> > - end point >> > >> > the radius, therefore calculated automatically, because with given set >> of parameters there's only one way to draw an arc connecting given points. >> > >> > Now if you put angle of 360 degrees, you cannot draw arc without >> specifying radius, >> > because your end points will coincide, which means there's infinite >> number of ways to draw full circle passing through a single point, with any >> radius. >> > >> > cairo using different inputs for specifying arc segments.. >> > - center, radius, start angle, end angle >> > >> > the problem with such parametrization is that it is completely separate >> from rest of commands (line/move/bezier etc).. and you will be very lucky >> if your arc will be connected with rest of your path.. because arc's >> starting point depends on start angle, instead of last point of previous >> path segment. >> > >> > this was the main reason to use more appropriate parametrization to get >> rid of inconsistency.. while losing ability to draw full circle with single >> command.. >> >> AFAICT, still doesn’t explain how to draw an ellipse with constant stroke >> path width, which was the original question :) >> >> > Right, what is missing is elliptical arc segment type. And there's no > direct support for it in Cairo.. so it can be only approximated by other > segment types, like lines or bezier curves. > There's a work started on calculating path geometry using approximation > with line segments.. it can be used to represent any kind of curves defined > parametrically. > But it is not yet plugged into the API. > > > One way is to not use a transformed circle path altogether, but draw the >> actual ellipsis path using cubic beziers: >> >> http://www.charlespetzold.com/blog/2012/12/Bezier-Circles-and-Bezier-Ellipses.html >> >> ellipsisOfExtent := [:builder :anExtent | | halfX halfY | >> halfX := anExtent x / 2. >> halfY := anExtent y / 2. >> “We expect relative builder, and start the ellipsis at >> anExtent x / 2 @ 0" >> builder >> curveVia: 0@(halfY negated * 0.55) and: (0.45 * >> halfX)@halfY negated to: halfX@ halfY negated; >> curveVia: halfX* 0.55 @ 0 and: halfX@ (0.45 * >> halfY) to: halfX @ halfY; >> curveVia: 0 @ (halfY * 0.55 ) and: (0.45 * halfX >> negated @ halfY) to: halfX negated @ halfY; >> curveVia: (halfX negated * 0.55) @ 0 and: halfX >> negated @ (halfY negated * 0.45) to: halfX negated @ halfY negated; >> close]. >> >> AthensSceneView new >> scene: [ :can | >> | path | >> >> path := can >> createPath: [ :builder | >> builder moveTo: 10@60. >> ellipsisOfExtent value: builder >> value: 200@100 ]. >> (can >> >> setStrokePaint: Color red) >> width: 8 asFloat. >> can drawShape: path ] ; >> openInWindow >> >> > quite nice approximation. What is an error measure comparing to true > ellipse? > > > From the abstract of the paper cited in the linked site: > > *We provide a surprisingly simple cubic Bézier curve which gives a very > accurate approximation to a segment of a circle. Joining the Bézier > segments we obtain an approximation to the circle with continuous tangent > and curvature. For 45° segments the error is approximately 2·10-6, and in > general the approximation is sixth order accurate.* > > Considering the code simply stretches a bezier circle’s control points, > I’d say quite. In fact, I’d be surprised if the arc primitive in cairo is > implemented using a different method. > > (Of course, even less error using the actual value of the formula for 90 > degrees, instead of approximate values .55 / 1- 0.55.) > > Cheers, > Henry >