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
>

Reply via email to