-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
canvas.pathIntersections index out of range #280
Comments
Thanks for the bug report and the proposed PR. Let me take a look at this after the weekend. |
Could you send me the score.svg file? I'm wondering if it is slow to parse the SVG, or slow to render the PNG. What final image resolution do you use with JSVG? The rasterizer depends heavily on the final image size, but it is already optimized with ASM so not sure how much can be won there. The SVG parser was put together quickly though, so hopefully that might be the performance issue. |
I actually attached the score to the first message. It's the second line. |
Ah yes, it shows up almost invisible in GitHub because of its width. The problem is in detecting a line-ellipse intersection that is not found due to a numerical precision error. The problem is that we have a half-circle arc on one path, and the other path is part of that arc, but then goes outwards with a straight line segment. It detects the tangents on the parallel/overlapping arcs, but does not find the same tangent (which should cancel out only together) at the end of the line segment. EDIT: the problem is in error propagation. The arcs are not exactly overlapping, one has a 6e-13 difference in the ending Y coordinate, this is making its center be 1e-12 off, the radii be 3e-13 off, ending angle be 1e-11 off, which causes the line-ellipse calculation to be off by more than 1e-10 and takes them to be not touching. |
To explain further, we're trying to find intersections between two paths. In this case, it is the path with itself to eliminate self-intersections caused by stroking. This particular path touches/intersects itself several times, but the problem is the following situation: One part of the path is a circular arc:
The other part of the path is a linear segment and a circular arc:
According to the code, the linear segment's end ALMOST touches the circular arc, it is off by 5.7e-4 (that is significant). But is also almost touches its own next path segment (circular arc as well) by the same distance, but two following segments MUST touch at their endpoints, so something is off and is generating a very large error. My suspicion is that parsing the circular arc representation to a center+angles representation is very prone to numerical error propagation (https://github.com/tdewolff/canvas/blob/master/path_util.go#L65). Will investigate further. We MUST find all such touching collisions because otherwise further on we can't figure out if two subsequent touching endpoints of a path actually intersect the other path (which may happen when two paths intersect at 90°, but one or both paths have a line segment ending/starting exactly at the intersection point). This is why your PR is almost certainly wrong as it tries to address the issue "too late". |
Maybe you are talking about some rendering which is necessary. But I'm comparing the performance with https://github.com/weisJ/jsvg |
I was just adding information to this issue in order to document the bug hunting. The SVG file has no faulty arcs of course, though it is quite suboptimal in describing its shapes, which stretches the numerical stability of the library. I'm expecting to fix this soon. 850 ms for a 42852x539 rasterization is probably right. This library should be in the same ball park. Parsing the SVG takes 30 ms on my machine (fairly slow in my opinion), but the rasterization should take the brunt of the execution time. How long did it take this library to render the SVG (using your PR I suppose) for you? |
|
I've fixed this issue by disabling ellipses (and flatten them much like Beziérs) in the intersection detection code. This should have no visual effect, but generates flattened paths after @geniot The fact that it took so long is because you were trying to create an image of dimension 137126x1728, something my image viewer doesn't even display because it is too big. This is because you were using A comparison with other tools:
So it really is not trivial to render an image that large, I'm actually happy that my library is the fastest out of those well-known tools! Could you please try again and tell me how long it takes to generate the image on your machine with the fix I posted above? If JSVG is really faster I would like to know their "secret". EDIT: after profiling, of the 1.9 seconds it takes me to generate the image, about 1.3 seconds is spent on generating the PNG file (image/png.filter and compress/flate) which is not something that can be sped up. Only 0.2 seconds is spent on rasterization, wow! EDIT2: saving the file as BMP (which doesn't use an expensive compression method) takes only 0.3 seconds in total, to parse and render the SVG, which proves my profiling above. Impressive. |
@geniot Hey Vitaly, I'm still very interested to see how JSVG and this library compare with each other while saving to a PNG image of the same size. If you find time to check that would be great! You could also compare with writing to a BMP file since I suspect that most time is spent on compressing to PNG for both libraries. |
I'm trying to convert a large SVG to PNG:
But I'm getting an exception:
So I found this place in the source code and fixed it somehow. If you could you take a look at my PR, maybe you find it ok and merge it.
Next step: performance, it takes ages to convert this SVG. I'm looking at JSVG (written in Java), it takes a second or two there.
My conversion code:
The text was updated successfully, but these errors were encountered: