-
Notifications
You must be signed in to change notification settings - Fork 71
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
Better SVD (preparation for making Arc
work like Ellipse
)
#250
Comments
I'm following this loosely, it looks pretty cool. I'm also thinking I might adapt it into Vello for the stroke rework; it currently doesn't apply non-angle preserving transforms to strokes correctly, and knowing the "eccentricity" of that transform looks like it would be useful. That's the ratio of the two values of the Σ diagonal, if I'm reading this correctly. |
Yep the two singular values are the two radii of the ellipse (mapped from the unit circle), so their ratio will be the eccentricity IIUC. There might be a way to compute them more directly - I don't know enough to say one way or the other. |
I was also wondering if it is worth adding some more linear algebra methods, like condition number and spectral (RMS) norm. The latter would be useful for measuring the difference between at least the linear part of the affine map, e.g. for testing approximate equality. The condition number would be useful for stability of the linear map (in this case the affine part is always stable so I think we don't have to worry about it). The condition number requires finding eigenvalues so adding eigendecomposition would be a prerequisite. |
Pardon my density, I'm here just trying to learn :) In your example code and inline comments above you only discuss about rotation in the context of the orthogonal matrices that are returned as part of SVD, but never mention that reflection is also orthogonal and can well be returned from SVD.. https://en.wikipedia.org/wiki/Singular_value_decomposition
Is your SVD code special in the sense that only deals with rotation specifically? E.g if I do this in Python with a 2x2 matrix I picked at random, both U and V* happen to be reflections.. >>> import numpy as np
>>> A = np.array([[1.0, 0.5], [0.5, 4.0]])
>>> U, s, Vt = np.linalg.svd(A)
>>> U
array([[ 0.16018224, 0.98708746],
[ 0.98708746, -0.16018224]])
>>> np.linalg.det(U) # determinant is -1.0, hence a reflection
-0.9999999999999998
>>> np.linalg.det(Vt)
-0.9999999999999996 Maybe the code does handle all that and it's just a matter of adjusting the terminology used in the comments accompanying the code (I haven't actually digged in the implementation details). Anyway, thanks! |
@anthrotype yep I think you're right. We should change the language. I forgot about reflections because they haven't come up in the things I've used the SVD for, but of course they would need to be considered if the function was made public. For the ellipse case (where the code is currently used) I think you could get a reflection if you used negative radii, but I think everything should 'just work'. Perhaps I should experiment. |
Maybe I'm not understanding, but I'd expect a reflection to be represented as one positive and one negative diagonal coefficient in the Σ matrix, which falls under "nonuniform scaling." |
IIUC, the problem is that the reflection will get 'moved' into one of the orthonormal matrices, and that the singular values are always two positive numbers. None of this matters for ellipses, but it might do for other things. |
I've been working on an alternative SVD implementation based on https://scicomp.stackexchange.com/questions/8899/robust-algorithm-for-2-times-2-svd#answer-28506 which includes the initial rotation. The reasons for the change are twofold
Arc
s (because they have a start angle that is influenced by this initial rotation)It uses an RQ decomposition as an intermediate step to improve stability.
Currently I'm returning the angle at the end, but eventually I will return sin and cos the angles instead, because algorithms that use this result tend to use the rotation matrix and so it makes no sense to go to polar coordinates and back again.
I'm posting it here as a request for comments, and also to discuss whether the RQ or SVD decompositions might be made public in the future.
The text was updated successfully, but these errors were encountered: