Hi, I wonder if anyone could point me to the general location of the code that is responsible for converting a circular arc to its corresponding cubic Bezier approximations for the case where the arc has no sodipodi attributes. I know that the file src\sp-ellipse.cpp does this if sodipodi attributes are present, but it appears that the non-sodipodi case is handled separately.
This is in reference to LP Bug 653315, which points out some rendering problems in this case.
tia, Alvin
On 2010-10-06 11:34, Alvin Penner wrote:
Hi, I wonder if anyone could point me to the general location of the code that is responsible for converting a circular arc to its corresponding cubic Bezier approximations for the case where the arc has no sodipodi attributes. I know that the file src\sp-ellipse.cpp does this if sodipodi attributes are present, but it appears that the non-sodipodi case is handled separately.
My guess is that one of TWO(???) methods to convert an arc to an SBasis in lib2geom is used (indirectly?). One is in 2geom/elliptical-arc.cpp, the other in 2geom/svg-elliptical-arc.cpp (search for toSBasis). Perhaps one of the lib2geom developers can comment.
Note that these files should not be changed in Inkscape. Ideally you'd fix current lib2geom and the change will be incorporated in Inkscape the next time our copy of the source is updated.
2010/10/6 Jasper van de Gronde <th.v.d.gronde@...528...>:
My guess is that one of TWO(???) methods to convert an arc to an SBasis in lib2geom is used (indirectly?). One is in 2geom/elliptical-arc.cpp, the other in 2geom/svg-elliptical-arc.cpp (search for toSBasis). Perhaps one of the lib2geom developers can comment.
The code in svg-elliptical-arc.cpp is used. However, this is not very relevant anymore because in 2Geom trunk SVGEllipticalArc is now a subclass of EllipticalArc. We really need to do a 2Geom sync, preferably immediately after 0.48.1 is out of the door.
There might be additional versions of the conversion code, hich go directly from elliptical arcs to Beziers, somewhere in SVG elliptical arc toys.
PS: Direct conversion to Beziers is a common operation. Doesn't it make sense to have a virtual function in Curve for it, rather than going through SBasis?
Regards, Krzysztof
thanks, I'll check it out.
Alvin
I have been browsing the code to find usages of SVGEllipticalArc that may affect Bug 653315. So far the most interesting reference is in:
\src\display\inkscape-cairo.cpp, around line 136, routine 'feed_curve_to_cairo'
the code is:
.................................................................................................
// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) { // //TODO: get at the innards and spit them out to cairo // } else { //this case handles sbasis as well as all other curve types Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
//recurse to convert the new path resulting from the sbasis to svgd for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) { feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke); } }
......................................................................................
what I am curious about is the tolerance value of 0.1 in the call to Geom::cubicbezierpath_from_sbasis.
Two questions: - is this code responsible for rendering ellipses? - would it be worthwhile to try a lower tolerance?
(there are other instances of this usage, in the files geom.cpp, PathCutting.cpp, svg-path.cpp, but I hope the current one is most relevant.)
thanks, Alvin
On 2010-10-11 23:51, Alvin Penner wrote:
I have been browsing the code to find usages of SVGEllipticalArc that may affect Bug 653315. So far the most interesting reference is in:
\src\display\inkscape-cairo.cpp, around line 136, routine 'feed_curve_to_cairo' ... what I am curious about is the tolerance value of 0.1 in the call to Geom::cubicbezierpath_from_sbasis.
Two questions:
- is this code responsible for rendering ellipses?
I doubt it (in general at least), as Inkscape only uses Cairo in outline mode(?) for now, until Krzysztof's branch is merged with trunk.)
- would it be worthwhile to try a lower tolerance?
Just try it. I'm not entirely sure what it will do though, as I would expect converting an SBasis curve to Bezier's to be exact as long as the SBasis curve has a low enough degree, but maybe it simple doesn't have a low enough degree?
(there are other instances of this usage, in the files geom.cpp, PathCutting.cpp, svg-path.cpp, but I hope the current one is most relevant.)
Note that more hidden uses can also occur (through the use of virtual function calls). I would recommend putting a printf (or std::cout) in the actual conversion function to see when it's being called. Or use a proper debugger (although I personally prefer the former to gdb).
OK, thanks. I don't have mingw installed on my computer, just VC++5, but I'll look into it.
Alvin
Attached is a modified version of the files src\2geom\sbasis-to-bezier.cpp, and *.h. The original call to the routine : sbasis_to_bezier(bez, B, 4) has been replaced with a call to a new routine : sbasis_to_cubic_bezier(bez, B) in order to improve the conversion from sbasis to cubic bezier. In the original routine the cubic bezier was specified by fitting the four variables : dx/dt(0), dy/dt(0), dx/dt(1), dy/dt(1), where t is the independent variable in the parametric representation. In the new routine the bezier is specified by fitting the four variables dx/dy(0), dx/dy(1), x(0.5), y(0.5). Numerical tests have shown that the original routine, if applied to a circular arc, will yield a bezier curve whose control arms have a length
d/r = theta/3
where
d = Bezier control arm length r = radius theta = angle of arc.
This is a correct zeroth order result for small theta, but is not appropriate for large theta. Numerical tests using the new routine on a circular arc yield a bezier control arm length that is consistent with
d/r = 4*tan(theta/4)/3
This is identical to the formula that is currently being used in the routine sp_genericellipse_set_shape (src\sp-ellipse.cpp) to render those ellipses that have sodipodi attributes associated with them. When applied to LP Bug 653315, file p.svg, this patch appears to resolve the rendering problem shown there.
Alvin Penner
http://old.nabble.com/file/p30327020/sbasis-to-bezier.cpp sbasis-to-bezier.cpp http://old.nabble.com/file/p30327020/sbasis-to-bezier.h sbasis-to-bezier.h
participants (3)
-
Alvin Penner
-
Jasper van de Gronde
-
Krzysztof Kosiński