I am not sure if this is the correct stack exchange for this question. I normally use javascript and a canvas to graph an equation. I am trying out Octave. I am having trouble getting any function with the same variable on both sides of a division to render. Test equation:
x=0:1:512;
Vr=x/100;
clf;
plot((50*Vr.^2-200*Vr)/(Vr-3), 'k-', 'linewidth', 3.0);
axis([0 512 -256 256]);
It works just fine without the division:
plot((50*Vr.^2-200*Vr), 'k-', 'linewidth', 3.0);
Screenscrapes: https://imgur.com/a/nWkXstX
The third is the equation with the division rendered with javascript.
Does octave not support this rather basic arithmetic, or is there a syntax eccentricity that I'm missing?
As much as I hate to be the guy who answers his own question, I found the answer in octave's docs.
https://octave.org/doc/v4.2.1/Arithmetic-Ops.html
'/' Multiplies the left by the inverse of the right. Seemed right, as the opposite of the (Vr/3) sounds like what I wanted, until I read on. './' is "Element-by-element right division." So the plot function treats Vr as a matrix of all the coordinates and computes a matrix with one equation. That was not clear in any of the documentation I read. Seriously, this should have been in the top level help section.
So "syntax eccentricity" it is. The correct syntax for octave is:
plot((50*Vr.^2-200*Vr)./(Vr-3), 'k-', 'linewidth', 3.0)
This works. I think I'll stick to JS though, if only to avoid needing to transform my equations to and from octave's weird syntax. Still, it's nice to have a non-browser-dependent option handy, however eccentric.
Related
I am trying to write a Minecraft Datapack, which will plot a full armorstand circle around whatever runs the particular command. I am using a 3rd party mathematics datapack to use Sin and Cos. However, when running the command, the resulting plot was... not good. As you can see here: 1. Broken Circle., rather than have each vertex evenly placed in a circular line, I find a strange mess instead.
I would have thought loosing precision in Cos and Sin would simply make the circle more angular, I didn't expect it to spiral. What confuses me, is that +z (the red square) and -x (the purple one) are all alone. You can see on the blue ring (Which was made with a smaller radius) the gap between them persists.
My main issue is; How did my maths go from making a circle to a shredded mushroom, and is there a way to calculate the vertices with a greater precision?
Going into the project I knew I could simply spin the centre entity, and summon an armorstand x blocks in front using ^5 ^ ^, however I wanted to avoid this, due to my desire to be able to change the radius without needing to edit the datapack. To solve this, I used the Sin and Cos components to plot a new point, using a radius defined with scoreboards.
I first tested this using Scratch, in order to check my maths. You can see my code here: 2. Scratch code.
With an addition of the pen blocks, I was able to produce a perfect circle, which you can see here:
. Scratch visual proof.
With my proof of concept working, I looked online and found a Mathematical Functions datapack by yosho27, since the Cos and Sin functions are not built into the game. However, due to how Minecraft scoreboards are only Integers, Yosho27 multiplied the result of Cos and Sin by 100 to preserve 2 decimal places.
To start with, I am using a central armorstand with the tag center, which is at x: 8.5 z: 8.5. The scoreboards built into yosho's datapack that I am using is math_in for the values I want converted and math_out, which is where the final value is dumped.
Using signs, I keep track of the important values I am working with, as seen here: 4. Sign maths.
As I was writing this, I decided to actually compare both numbers to find this: 5. Image comparison, which shows me that somewhere in this calculation process, the maths has gone wrong. I modified the scratch side to match the minecraft conditions as much as possible, such as x100 and adding 850 to the result. From this result, I can see a disparity between x and z, even though they should be equal. Where Minecraft says 1: x= 864 z= 1487, Scratch says 1: x= 862.21668448: z= 1549.89338664. I assume this means the datapack's Cos and Sin are not accurate enough?
In light of this , I looked in yosho's datapack, I found this: 6. Yosho's code., which I just modified to be *= 10 instead of divide, in the hope of getting more precision. Modifying the rest of my code to match, I couldn't see any improvement in the numbers, although the armorstand vertices were a few pixels off the original circle, although I couldn't find a discernible pattern to this shift.
While this doesn't answer your full question, I'd like to point out two different ways you can solve the original issue at hand, no need to rely on some foreign math library:
^ ^ ^
Use Math, but let the game do it for you.
You can use the fact that the game is doing those rotational conversions for you already when using local coordinates. So, if you (or any entity) go to 0 0 0 and look / rotate in the angle that you want to calculate, then move forward by ^ ^ ^1, the position you're at now is basically <sin> 0 <cos>.
You can now take those numbers with your desired precision using data get and continue using them in whatever way you see fit.
Use recursive functions to move in incremenets
You point out in your question that
Going into the project I knew I could simply spin the centre entity, and summon an armorstand x blocks in front using ^5 ^ ^, however I wanted to avoid this, due to my desire to be able to change the radius without needing to edit the datapack. To solve this, I used the Sin and Cos components to plot a new point, using a radius defined with scoreboards.
So, to go back to that original idea, you could fairly easily (at least easier than trying to calculate the SIN/COS manually) find a solution that works for (almost) arbitrary radii and steps: By making the datapack configurable through e.g. scores, you can set it up to for example move forward by ^^^0.1 blocks for every point in a score, that way you can change that score to 50 to get a distance of ^^^5 and to 15 to get a distance of ^^^1.5.
Similarly you could set the "minimum" rotation between summons to be 0.1 degrees, then repeating said rotation for however many times you desire.
Both of these things can be achieved with recursive functions. Here is a quick example where you can control the rotational angle using the #rot steps score and the distance using the #dist steps score as described above (you might want to limit how often this runs with a score, too, like 360/rotation or whatever if you want to do one full circle). This example technically recurses twice, as I'm not using an entity to store the rotation. If there is an entity, you don't need to call the forward function from the rotate function but can call it from step (at the entity).
step.mcfunction
# copy scores over so we can use them
scoreboard players operation #rot_steps steps = #rot steps
scoreboard players operation #dist_steps steps = #dist steps
execute rotated ~ ~0.1 function foo:rotate
rotate.mcfunction
scoreboard players remove #rot_steps steps 1
execute if score #rot_steps matches ..0 positioned ^ ^ ^.1 run function foo:forward
execute if score #rot_steps matches 1.. rotated ~ ~0.1 run function foo:rotate
forward.mcfunction
scoreboard players remove #dist_steps steps 1
execute if score #dist_steps matches ..0 run summon armor_stand
execute if score #dist_steps matches 1.. positioned ^ ^ ^.1 run function foo:forward
I'm working on constraining an IK program so that the normal vector in the end-effector frame is parallel to a known vector in the world-frame, when both are projected to the xy-plane. My initial thought was to use an AddAnglesBetweenVectorsConstraint, but that only allows me to specify the total angle between vectors, and no difference between the different axes. Is there currently a way in Drake to do this?
Edit: it turns out that this was not exactly the problem I needed to solve. In my answer below, I describe the real problem I was solving.
It seems that AddOrientationConstraint will do what you need? If not, then you could accomplish the same with adding two PositionConstraints; I do precisely that in the interactive IK example in the notes for this chapter: https://manipulation.csail.mit.edu/trajectories.html .
Turns out, you can do what I wanted to do using an AddAnglesBetweenVectorsConstraint, I just misdescribed my problem. Specifically, what I really wanted was to do was enforce that the y-axis in the end effector frame (where z-axis is the direction of the end-effector, and the x-axis is straight up in said frame) was perpdinicular both to the z-axis in the world frame and the known vector in the world-frame. This is exactly what AddAngleBetweenVectorsConstraint, and it worked very nicely.
I'm raymarching Signed Distance Fields in CUDA and the scene I'm rendering contains thousands of spheres (spheres have their location stored in device buffer, so my SDF function iterates through all of the spheres for each pixel).
Currently, I'm computing distance to sphere surface as:
sqrtf( dot( pos - sphere_center, pos - sphere_center ) ) - sphere_radius
With the sqrt() function, the rendering took about 250ms for my scene. However, when I removed the call to sqrt() and left just dot( pos - sphere_center, pos - sphere_center ) - sphere_radius, the rendering time dropped to 17ms (and rendering black image).
The sqrt() function seems to be the bottleneck so I want to ask if there is a way I can improve my rendering time (either by using different formula that does not use square root or different rendering approach)?
I'm already using -use-fast-math.
Edit: I've tried formula suggested by Nico Schertler, but it didn't work in my renderer. Link to M(n)WE on Shadertoy.
(Making my comment into an answer since it seems to have worked for OP)
You're feeling the pain of having to compute sqrt(). I sympathize... It would be great if you could just, umm, not do that. Well, what's stopping you? After all, the square-distance to a sphere is a monotone function from $R^+$ to $R^+$ - hell, it's actually a convex bijection! The problem is that you have non-squared distances coming from elsewhere, and you compute:
min(sqrt(square_distance_to_the_closest_sphere),
distance_to_the_closest_object_in_the_rest_of_the_scene)
So let's just do things the other way around: Instead of taking the square-root of the squared distance to the sphere, let's square the other distance:
min(square_distance_to_the_closest_sphere,
distance_to_the_closest_object_in_the_rest_of_the_scene^2)
This makes the same choice as the un-squared min() computation, due to the monotonicity of the squaring function. From here, try to propagate the use of the squared distance further in your program, avoiding taking a root as far as possible, perhaps even all the way.
Im trying to optimize my skeletal animation system by using tracks (curve) instead of keyframe. Each curve take care of a specific component then (for now) I linearly interpolate the values. Work fine for my bone positions, however Im having a hard time getting rid of the "jagyness" of the quaternion component interpolation...
Basically I have 1 curve for each component (XY and Z) for each bones quaternion and I use the following code to interpolate the XY and Z curves independently:
// Simple lerp... (f is always a value between 0.0f and 1.0f)
return ( curve->data_array[ currentframe ].value * ( 1.0f - f ) ) +
( curve->data_array[ nextframe ].value * f );
When I interpolate the quaternion XYZ then I use the following code to rebuild the W component of the quaternion before normalizing it and affecting it to my bone before drawing:
Quaternion QuaternionW( const Quaternion q )
{
Quaternion t = { q.x, q.y, q.z };
float l = 1.0f - ( q.x * q.x ) - ( q.y * q.y ) - ( q.z * q.z );
t.w = ( l < 0.0f ) ? 0.0f : -sqrtf( l );
return t;
}
The drawing look fine at the exception that the bones become all jerky from time to time, would it be due to the floating point precision? Or the recalculation of the W component? Or there is absolutely no way I can linearly interpolate each component of a quaternion this way?
ps: On a side note, in my curve interpolation function if I replace the code above with:
return curve->data_array[ currentframe ].value;
instead or linearly interpolating, everything is fine... So the data is obviously correct... Im puzzled...
[ EDIT ]
After more research I found that the problem comes from the frame data... I got i.e. the following:
Frame0:
quat.x = 0.950497
Frame1:
quat.x = -0.952190
Frame2:
quat.x = 0.953192
This is what causes the inversion and jaggyness... I tried to detect this case and inverse the sign of the data but it still doesn't fix the problem fully as some frame now simply look weird (visually when drawing).
Any ideas how to properly fix the curves?
Your data are probably not wrong. Quaternion representations of orientation have the funny property of being 2x redundant. If you negate all four elements of a quaternion, you're left with the same orientation. It's easy to see this if you think of the quaternion as an axis/angle representation: Rotating by Θ around axis a, is the same as rotating by -Θ around axis -a.
So what should you do about it? As mentioned before, slerp is the right thing to do. Quaternion orientations exist on the unit hypersphere. If you linearly interpolate between points on a sphere, you leave the sphere. However, if the points are close by each other, it's often not a big deal (although you should still renormalize afterward). What you absolutely do need to make sure you do is check the inner-product of your two quaternions before interpolating them: e.g.,
k=q0[0]*q1[0] + q0[1]*q1[1] + q0[2]*q1[2] + q0[3]*q1[3];
If k<0, negate one of the quaternions: for (ii=0;ii<4;++ii) q1[ii]=-q1[ii]; This makes sure that you're not trying to interpolate the long way around the circle. This does mean, however, that you have to treat the quaternions as a whole, not in parts. Completely throwing away one component is particularly problematic because you need its sign to keep the quaternion from being ambiguous.
Naive considerations
Linear interpolation is fine for things that operate additively, i.e. that add something to something else every time you execute the corresponding operation. Queternions, however, are multiplicative: you multiply them to chain them.
For this reason, I originally suggested computing the following:
pow(secondQuaternion, f)*pow(firstQuaternion, 1. - f)
Wikipedia has a section on computing powers of quaternions, among other things. As your comment below states that this does not work, the above is for reference only.
Proper interpolation
Since writing this post, I've read a bit more about slerp (spherical linear interpolation) and found that wikipedia has a section on quaternion slerp. Your comment above suggests that the term is already familiar to you. The formula is a bit more complicated than what I wrote above, but it is still rather related due to the way it uses powers. I guess you'd do best by adapting or porting an available implementatin of that formula. This page for example comes with a bit of code.
Fixing data
As to your updated question
Any ideas how to properly fix the curves?
Fixing errors while maintaining correct data requires some idea of what kinds of errors do occur. So I'd start by trying to locate the source of that error, if at all possible. If that can be fixed to generate correct data, then good. If not, it should still give you a better idea of what to expect, and when.
I have a large set of 3D data points to which I want to fit to an ellipsoid.
My maths is pretty poor, so I'm having trouble implementing the least squares method without any math libraries.
Does anyone know of or have a piece of code that can fit an ellipsoid to data which I can plug straight into my project? In C would be best, but it should be no problem for me to convert from C++, Java, C#, python etc.
EDIT: Just being able to find the centre would be a huge help too. Note that the points aren't evenly spaced so taking the mean won't result in the centre.
here you go:
This paper describes fitting an ellipsoid to multiple dimensions AS WELL AS finding the center for the ellipois. Hope this helps,
http://www.physics.smu.edu/~scalise/SMUpreprints/SMU-HEP-10-14.pdf
(btw, I'm assuming this answer is a bit late, but I figured I would add this solution for anyone who stumbles across your question in search for the same thing :)
If you want the minimum-volume enclosing ellipsoid, check out this SO answer for a bounding ellipsoid.
If you want the best fitting ellipse in a least-squares sense, check out this MATLAB code for error ellipsoids where you find the covariance matrix of your mean-shifted 3D points and use that to construct the ellipsoid.
Least Squares data fitting is probably a good methodology give the nature of the data you describe. The GNU Scientific Library contains linear and non-linear least squares data fitting routines. In your case, you may be able to transform your data into a linear space and use linear least-squares, but that would depend on your actual use case. Otherwise, you'll need to use non-linear methods.
I could not find a good Java based algorithm for fitting an ellipsoid, so I ended up writing it myself. There were some good algorithms for an ellipse with 2D points, but not for an ellipsoid with 3D points. I experimented with a few different MATLAB scripts and eventually settled on Yury Petrov's Ellipsoid Fit. It fits an ellipsoid to the polynomial Ax^2 + By^2 + Cz^2 + 2Dxy + 2Exz + 2Fyz + 2Gx + 2Hy + 2Iz = 1. It doesn't use any constraints to force an ellipsoid, so you have to have a fairly large number of points to prevent a random quardic from being fit instead of the ellipsoid. Other than that, it works really well. I wrote a small Java library using Apache Commons Math that implements Yury Petrov's script in Java. The GIT repository can be found at https://github.com/BokiSoft/EllipsoidFit.
We developed a set of Matlab and Java codes to fit ellipsoids here:
https://github.com/pierre-weiss
You can also check our open-source Icy plugin. The following tutorial can be helpful:
https://www.youtube.com/endscreen?video_referrer=watch&v=nXnPOG_YCxw
Note: most of the existing codes fit a generic quadric and do not impose an ellipsoidal shape. To get more robustness, you need to go to convex programming rather than just linear algebra. This is what is done in the indicated sources.
Cheers,
Pierre
Here is unstrict solution with fast and simple random search approach*. Best side - no heavy linear algebra library required**. Seems it worked fine for mesh collision detection.
Is assumes that ellipsoid center matches cloud center and then uses some sort of mirrored average to search for main axis.
Full working code is slightly bigger and placed on git, idea of main axis search is here:
np.random.shuffle(pts)
pts_len = len(pts)
pt_average = np.sum(pts, axis = 0) / pts_len
vec_major = pt_average * 0
minor_max, major_max = 0, 0
# may be improved with overlapped pass,
for pt_cur in pts:
vec_cur = pt_cur - pt_average
proj_len, rej_len = proj_length(vec_cur, vec_major)
if proj_len < 0:
vec_cur = -vec_cur
vec_major += (vec_cur - vec_major) / pts_len
major_max = max(major_max, abs(proj_len))
minor_max = max(minor_max, rej_len)
It can be improved/optimized even more at some points. Examples what it will produce:
And full experiment code with plots
*i.e. adjusting code lines randomly until they work
**was actually reason to figure out this solution
I have an idea. Approximately solution, not the best but will keep points inside. In XY plane find the radius R1 that will obtain all points. Same do for the XZ plane (R2) and YZ plane (R3). Then use the maximums on each axes. A=max(R1,R2), B=max(R1,R3) and C=max(R2,R3).
But, first of all find the average (center) of all points and align it to origin.
I have just gone through the same process.
Here is a python module which is based on work by Nima Moshtagh. Referenced in many places but also in this question about a Bounding ellipse
This module also handles plotting of the final ellipsoid. Enjoy!
https://github.com/minillinim/ellipsoid/blob/master/ellipsoid.py
I ported Yury Petrov's least-squares Matlab fitter to Java some time ago, it only needs JAMA: https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitEllipsoid.java