fritzo / jenn3d

A Toy for Visualizing Coxeter Polytopes
jenn3d.org
Other
40 stars 8 forks source link

Mathematical weakness if a edge line points directly in the center #5

Open furun opened 8 years ago

furun commented 8 years ago

I ask just for curiosity. Is there a clean mathematical way to solve the following problem?

There is a Mathematical weakness if a edge line points directly in the center. So if the two points of a edge are in a straight line to the center (0,0,0).

I speculate, it is the reason for the noise used in Animate::Animate(), to prevent that edge lines point directly in to the center.

Animate::Animate () {
...
    noise0 = 0.005f;
    noise1 = 0.0005f; 

For example: In this code part the resolut for n b is infinite/NaN, because r3_norm(N) and r3_norm(B) result is 0, if the edge line points to center.

inline float stereo_project (const Vect& x, const Vect& dx, Vect& y, Vect& N, Vect& B) {//projects a tangent vector : R^3 >--> S^3 --> R^3 to normal vectors 
...
    float n = scale / r3_norm(N);
    float b = scale / r3_norm(B); 

Or the Edge tube of such edges gets wobbly because it misses the adjustment.

fritzo commented 8 years ago

Hi furun, I believe (0,0,0) point is the point at infinity, not the point in the center. Jenn3D maps the 3-sphere S^3 onto euclidean space + a point at infinity (which is not drawn). The stereo_project function indeed fails at the singularity at (0,0,0), but this is unavoidable.

The purpose of noise in Animate::Animate is purely aesthetic: it is easier for human eyes to see depth in 3D structure if there is even just a little motion noise.

furun commented 8 years ago

Tanks very much fritzo for the replay!

To explain how this question come up...

I made a little optimisation in r3_norm(). If the sqr result is near 0, it is set to 0. (and near 1 set to 1, to avoid sqrt() for speed. Useful in other code with many 0 and 1 results.) And i set the noise to 0.

Then i was surprised to see no Edges anymore at the corners in a Hypercube (4,2,2,3,2,3;2,3,4). Without noise and without the sqrt() optimisations in r3_norm(), the tubes in the same edges get wobbly.

(I teached math to my self, this code is a bit about my level ;-)

furun commented 8 years ago

So much i understand, are no points or edges in infinity in a Hypercube on start position. It is a gen=2,3,4 form. Not one of for example the gen=1,2,3 witch generates infinite Geometrie. (not sure if i unterstand you right?)

Here a illustration of the problem. The noise hides this behavior, because it moves the edges a little of center, and gives the edge a little bow, it is then not a exact straight line anymore.. HyperCube

Noise=0, modified r3_normal() function: If the edge lines of the Hypercube pointing directly towards (0,0,0), the code in stereo_project "r3_norm(N)" is = 0, and produces a 1/0 error. The tube diameter step by step is destroyed, wen the geometry comes back from drifting to start position. The tube diameter could be defined in a difference way, wich not destroys the information of the diameter, in this special case. I worked on a solution, but have not found any now.

In drift lost1 Back to start lost2 lost3 lost4 lost5

Noise=0, original r3_normal() function: Because there is a little error in flouting point calculations, the original code always has a very small value left in r3_norm(N), r3_norm(B). Now a other problem shows up, in this special case wen edges pointing directly towards (0,0,0). The tube gets wobbly, wen the geometry comes back from drifting to start position. I speculate, the normal direction of the edge is lost, because it is defined be using the edge direction away from (0,0,0). (This is just a speculation, i have not proofed jet.)

In drift wobbly1 Start wobbly2

(Why the effort? It is one of the most coolest math software i know :-)

fritzo commented 8 years ago

Cool, yes that looks like a bug indeed! Also, you can switch to wireframe mode by pressing 'q', which is helpful for debugging. It might also help to log/print a warning if any denominator is too close to zero. You could do this at a bunch of places in the code to find which one is triggering.

You're right that in the projection of the hypercube you're examining, there are no points at infinity at the start position. BTW the N and B in the code you pointed me to are the Normal and Binormal vectors. It looks like one or both are ending up zero.

Let me know if you find a fix!

On Jul 20, 2016 6:00 AM, "furun" notifications@github.com wrote:

So much i understand, are no points or edges in infinity in a Hypercube on start position. It is a gen=2,3,4 form. Not one of for example the gen=1,2,3 witch generates infinite Geometrie. (not sure if i unterstand you right?)

Here a illustration of the problem. The noise hides this behavior, because it moves the edges a little of center, and gives the edge a little bow, it is then not a exact straight line anymore.. [image: HyperCube] https://camo.githubusercontent.com/8b4f99d19412b915234568448614ca0321d5bed6/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f6670727231373872736f3878776d372f4879706572437562652e706e67

_Noise=0, modified r3normal() function: If the edge lines of the Hypercube pointing directly towards (0,0,0), the code in stereo_project "r3_norm(N)" is = 0, and produces a 1/0 error. The tube diameter step by step is destroyed, wen the geometry comes back from drifting to start position. The tube diameter could be defined in a difference way, wich not destroys the information of the diameter, in this special case. I worked on a solution, but have not found any now.

In drift [image: lost1] https://camo.githubusercontent.com/9ff80c1b92c9528bc9ca23a2994b431d779ce272/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f6336313665656a77613539623833722f6c6f7374253230312e706e67 Back to start [image: lost2] https://camo.githubusercontent.com/cc6877524c0e380cabf9ebf39d9da02481e020ae/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f32396a6f6a667369306e76386e63642f6c6f7374253230322e706e67 [image: lost3] https://camo.githubusercontent.com/f8b4126aeca63533da573b7bc4e62ba24f674364/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f756b6f727368716f7732397a397a6b2f6c6f7374253230332e706e67 [image: lost4] https://camo.githubusercontent.com/76fecbfdff1d76e7ae664fbff2f0fb4210060fe7/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f6d353261786f7735686e34693435622f6c6f7374253230342e706e67 [image: lost5] https://camo.githubusercontent.com/ccc67c0f5b26765fe1f84ea8cc1d139828b814d6/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f396c39793338647a6a746e626577362f6c6f7374253230352e706e67

_Noise=0, original r3normal() function: Because there is a little error in flouting point calculations, the original code always has a very small value left in r3_norm(N), r3_norm(B). Now a other problem shows up, in this special case wen edges pointing directly towards (0,0,0). The tube gets wobbly, wen the geometry comes back from drifting to start position. I speculate, the normal direction of the edge is lost, because it is defined be using the edge direction away from (0,0,0). (This is just a speculation, i have not proofed jet.)

In drift [image: wobbly1] https://camo.githubusercontent.com/685ded89b5d1371441a3f801f2288beabb28aa10/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f36366c6a36656a3075626a7a747a642f776f62626c79253230312e706e67 Start [image: wobbly2] https://camo.githubusercontent.com/f43b3944f86f7492f3dc1c7c8d03d33436d2a667/68747470733a2f2f646c2e64726f70626f7875736572636f6e74656e742e636f6d2f732f35786d64716369317162787831616b2f776f62626c79253230322e706e67

(Why the effort? It is one of the most coolest math software i know :-)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/fritzo/jenn3d/issues/5#issuecomment-233941561, or mute the thread https://github.com/notifications/unsubscribe-auth/AAnlVGVgIz4XJz_MhB7WcLMGePYZMKYtks5qXhvXgaJpZM4JOT_k .

furun commented 8 years ago

OK... i tray, but don't laugh, like i said, i have not study math at uni, only self learnt skills.

I speculate that the cross product for normal and binormal has to be done in 4D space, for this stereo_project. Projected in 3D, the vector looses the needed info in case of a straight line to center. point1 and tangent are pointing in the same direction, it is basically the same vector. Similar like in a Gimbal-Lock problem, the geometric info is lost. But i have not figured out jet which 3. vector should be used for this, beside of point1 and tangent, in the 4D cross product.

Do you have a tip? In case me idea is right.

(Probable the wobbly tube can be fixed in a similar way.)

furun commented 8 years ago

I understand the problem a bit better now. The normal and binormal are defined by the tangent of the curvature. In case of no curvature / straight line, the normal vectors can not be calculated, its (0,0,0), it not defined / it is everywhere. And the tube gets wobbly beschaue the normal is everywhere, without a curvature or arc defining the direction. Near to the float precision it gets wobbly, on 0 the math gets infinite.

(Jenn crashes internally, the objects disappears from screen. This happens after some minutes, wenn one of the 1/0 situations happen.)

In the stereographic projection is the only situation wenn edges has no curvatures, if they point straight to the center. every other edge will have a curvature. To move the cross product to 4D not solves the problem, without the stereographic projection to 3D, in 4D are no curvatures at all.

I found no math solution jet. Maybe there is non(?) A special handling near to 0 is not really beautiful, and will cause a distortion along the edge. Like on the pictures, wenn the edge step by step disappear, it will step by step twist instead. The only way i see now is to use the adjoining edges instead of the curvature, to define the geometry(?)

fritzo commented 8 years ago

Great deubgging, that sounds plausible to me. I think it's fine to add special handling around zero for the normal and binormal vectors. What if you do something like:

furun commented 8 years ago

I think this is the best solution for now. To use adjoining edges like i supposed before, did not work either. At least not so easy. Such near 0 exception handlings are not so elegant, but it will work. To use most-normal will avoid all 1/0 errors. I tested this quick already with a simple up-vector (0,1,0), before i tested the adjoining-edges idea. But you will see that the tubes twist along the edge, if they comes back from drift. You can test it with a big near-0 limit like 0.1.

(Tanks for this code! i spend now quite some free time with it.)