LDraw.org Discussion Forums
Rounding Errors in primitives? - Printable Version

+- LDraw.org Discussion Forums (https://forums.ldraw.org)
+-- Forum: General (https://forums.ldraw.org/forum-12.html)
+--- Forum: Official File Specifications/Standards (https://forums.ldraw.org/forum-32.html)
+--- Thread: Rounding Errors in primitives? (/thread-24515.html)



Rounding Errors in primitives? - Tery Hamer - 2021-03-25

I'm a newbie, so I am nervous about asking... can someone confirm that either A) I'm talking BS, or B) there are rounding errors in the Official LDraw Primitive .dat files?

These are mostly derived from PrimGen2 (- but I haven't checked all).  Some of these files are perhaps 10 years old. Has anybody noticed this before?

AKAIK the standard is for the vectors in .dat files to be shown to 4 decimal places, removing trailing zeros.

For Rings, Cones the vector points for higher values of radii are a multiple of the cos/sin values of the segment angles times the radius. However, it would appear that the rounding is carried out on the cos/sin for the base radius (1, as used for Circle, Disc, etc), and <then> multiplied. That would be a No-No.  For the base and lower radii, the error may be only 0.0001 in a few cases.  But for the higher radii, these rounding errors mount up and impact the third decimal position.

So, BS or BUG?


tery


RE: Rounding Errors in primitives? - Travis Cobbs - 2021-03-25

(2021-03-25, 18:42)Tery Hamer Wrote: I'm a newbie, so I am nervous about asking... can someone confirm that either A) I'm talking BS, or B) there are rounding errors in the Official LDraw Primitive .dat files?

These are mostly derived from PrimGen2 (- but I haven't checked all).  Some of these files are perhaps 10 years old. Has anybody noticed this before?

AKAIK the standard is for the vectors in .dat files to be shown to 4 decimal places, removing trailing zeros.

For Rings, Cones the vector points for higher values of radii are a multiple of the cos/sin values of the segment angles times the radius. However, it would appear that the rounding is carried out on the cos/sin for the base radius (1, as used for Circle, Disc, etc), and <then> multiplied. That would be a No-No.  For the base and lower radii, the error may be only 0.0001 in a few cases.  But for the higher radii, these rounding errors mount up and impact the third decimal position.

Scaling up the rounded values might be intentional. It would allow scaled primitives to perfectly align with non-scaled ones. (I'm not saying for sure that it's intentional, just that it might be.)

I took a quick look at 4-4ring3.dat, and it appears to be multiplying the 4-digit rounded numbers by the radii (3 and 4).


RE: Rounding Errors in primitives? - Philippe Hurbain - 2021-03-25

(2021-03-25, 18:42)Tery Hamer Wrote: For Rings, Cones the vector points for higher values of radii are a multiple of the cos/sin values of the segment angles times the radius. However, it would appear that the rounding is carried out on the cos/sin for the base radius (1, as used for Circle, Disc, etc), and <then> multiplied. That would be a No-No.  For the base and lower radii, the error may be only 0.0001 in a few cases.  But for the higher radii, these rounding errors mount up and impact the third decimal position.
Hi Teri,
Welcome here!
Very good observation... and actually, this is intended. For historical reasons, rings and cones are not normalized. Rounding is done this way for ring and cones (ok, seems weird at first sight!!!) so their vertices match exactly those of scaled normalized primitives (edges, cylis, discs and so on...)


RE: Rounding Errors in primitives? - Tery Hamer - 2021-03-25

(2021-03-25, 19:45)Philippe Hurbain Wrote: Hi Teri,
Welcome here!
Very good observation... and actually, this is intended. For historical reasons, rings and cones are not normalized. Rounding is done this way for ring and cones (ok, seems weird at first sight!!!) so their vertices match exactly those of scaled normalized primitives (edges, cylis, discs and so on...)

Thanks for the explanation - weird though it is. I'll definitely have another look, but - yes - I can see why compatability with other scaled primitives would be necessary.

This arose because I was investigating importing models into Blender and noticing some of the chunkiness.  I thought creating higher resolution files of 1/96 rather than 1/48 might 'improve' the smoothing.  This can, of course, be done piecemeal using custom parameters to PrimGen2, which then produces those 'non-normalised' values,  but I got fed up with all that clicking!!   I thought I'd do it in python, and auto-generate the primitives.  Still a WIP - havent tackled Torus yet - but 3855 Rings, Cones, Circles, Discs, Ndiscs, Chords, Cylinders .dat files take about 5 seconds to generate. 
I'll switch back to generating the 'non-normalised' values. Loads of time to play at this - we seem to have months of Lockdown to go ....

BTW, you seem to have rounded my name from Tery to Teri. Rolleyes


RE: Rounding Errors in primitives? - Chris Dee - 2021-03-26

(2021-03-25, 19:45)Philippe Hurbain Wrote: Hi Teri,
Welcome here!
Very good observation... and actually, this is intended. For historical reasons, rings and cones are not normalized. Rounding is done this way for ring and cones (ok, seems weird at first sight!!!) so their vertices match exactly those of scaled normalized primitives (edges, cylis, discs and so on...)

Yes, this is intentional for the reasons Philo explains.


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-04-29

Thanks for the explanation! I am using this to improve the automated testing framework that I am currently working on.

However. I have found an issue with 4-4con12.dat. The official file uses the following point in the quads:

-11.0868 1 4.5924

Such as in the following quads:

4 16 -8.4852 1 8.4852 -11.0868 1 4.5924 -12.0107 0 4.9751 -9.1923 0 9.1923
4 16 -11.0868 1 4.5924 -12 1 0 -13 0 0 -12.0107 0 4.9751

And even this conditional line:

5 24 -11.0868 1 4.5924 -12.0107 0 4.9751 -8.4853 1 8.4853 -12 1 0

However. The other conditional lines, where I expect the same point to be used, use:

-11.0866 1 4.5922

such as in:

5 24 -8.4852 1 8.4852 -9.1923 0 9.1923 -4.5922 1 11.0866 -11.0866 1 4.5922
5 24 -12 1 0 -13 0 0 -11.0866 1 4.5922 -11.0866 1 -4.5922


You can get to this point by computing the points without using the tip from this thread. With full decimals through the full calculation, the point should be:


11.08655439013544 1 4.592201188381077

which rounds to 4 decimals as:

-11.0866 1 4.5922

How do I know which method to use in conditional lines?

Please note that other cones, such as the following do not have this issue:
  • 2-4con0.dat
  • 2-4con1.dat
  • 4-4con0.dat
  • 4-4con1.dat
  • 4-4con2.dat
  • 4-4con3.dat
  • 4-4con4.dat
  • 4-4con5.dat
  • 4-4con6.dat
  • 4-4con7.dat
  • 4-4con8.dat
  • 4-4con9.dat
  • 4-4con10.dat
  • 4-4con11.dat

Edit: It seems that for a conditional line A B C D, A and B use the scaling trick from this thread, while the control points C and D do not.


RE: Rounding Errors in primitives? - Travis Cobbs - 2021-04-29

(2021-04-29, 19:59)Lasse Deleuran Wrote: However. I have found an issue with 4-4con12.dat. The official file uses the following point in the quads:

...

Edit: It seems that for a conditional line A B C D, A and B use the scaling trick from this thread, while the control points C and D do not.

I would say that the part is incorrect, and all instances of that coordinate should be the same.


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-04-29

(2021-04-29, 20:14)Travis Cobbs Wrote: I would say that the part is incorrect, and all instances of that coordinate should be the same.

I have now gone through all the official 4-4con[x].dat files, and these are my findings:

Of the 41 files, 10 of them have the incorrect control points. These are:

4-4con12.dat
4-4con25.dat
4-4con33.dat
4-4con42.dat
4-4con43.dat
4-4con46.dat
4-4con47.dat
4-4con48.dat
4-4con80.dat
4-4con81.dat


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-04-29

(2021-04-29, 20:14)Travis Cobbs Wrote: I would say that the part is incorrect, and all instances of that coordinate should be the same.

It is easy for me to generate new primitives that have one or the other type of control points using the testing library, so just tell me if you want any of them generated.


RE: Rounding Errors in primitives? - Magnus Forsberg - 2021-04-29

The file claims to be made using PrimGen2, but if I re-create a new version today, I get correct values.

   


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-04-29

(2021-04-29, 20:54)Magnus Forsberg Wrote: The file claims to be made using PrimGen2, but if I re-create a new version today, I get correct values.

Then it seems like an open and shut case.

I am currently on a MAC without access to PrimGen2. Are you able to generate 1-4ring5.dat and compare it to the official file as well? It also appears to have a mix of computed points. If I compute the primitive in what I believe is the correct way, then I get the point:

5.5434 0 2.2962

such as in the quad:

4 16 6 0 0 5.5434 0 2.2962 4.6195 0 1.9135 5 0 0

which differst from the official file:

4 16 6 0 0 5.5433 0 2.2961 4.6195 0 1.9135 5 0 0

The point should come from scaling the points from the simple primitives. In this case we can take 1-4edge.dat with the point:

0.9239 0 0.3827

Multiply by 6 and you get the "5.5434 0 2.2962" point and not the one in the official file!


Now. If I generate this primitive without regards to the trick, then I get another issue. I get the following quad:

4 16 6 0 0 5.5433 0 2.2961 4.6194 0 1.9134 5 0 0

which ALSO differs from the quad in the official file:

4 16 6 0 0 5.5433 0 2.2961 4.6195 0 1.9135 5 0 0

So how was this primitive generated?


RE: Rounding Errors in primitives? - Travis Cobbs - 2021-04-29

(2021-04-29, 20:54)Magnus Forsberg Wrote: The file claims to be made using PrimGen2, but if I re-create a new version today, I get correct values.

Your screenshot shows both 4.5922 and 4.5924 (the reported problem).


RE: Rounding Errors in primitives? - Magnus Forsberg - 2021-05-02

Your first example show that the official file is not correct.

   

Your second example, is correct compaired to the official file, but your calculation is not.


RE: Rounding Errors in primitives? - Magnus Forsberg - 2021-05-03

How do you want to continue?
A have a set of the 11 mentioned ring and cone prims, ready for recycling.


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-05-05

(2021-05-03, 15:57)Magnus Forsberg Wrote: How do you want to continue?
A have a set of the 11 mentioned ring and cone prims, ready for recycling.

With official parts I have previously sent an email directly to Chris Dee with the fixed files.


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-05-05

(2021-05-02, 19:45)Magnus Forsberg Wrote: (...) Your second example, is correct compaired to the official file, but your calculation is not.

I want to learn how to perform the correct calculation, so that my testing framework can include these primitives as well.
Can you please tell me where I am making a wrong assumption below?


1-4ring5.dat consists of quads based on the points from 1-4edge.dat. 

The points in 1-4edge.dat are those of the quarter circle with diameter 1:
1 0 0
0.9239 0 0.3827
0.7071 0 0.7071
0.3827 0 0.9239
0 0 1

1-4ring5.dat spans from the quarter circle of diameter 5 to the quarter circle of diameter 6. It consists of the following points:

5 0 0
4.6195 0 1.9135
3.5355 0 3.5355
1.9135 0 4.6195
0 0 5

6 0 0 
5.5433 0 2.2961 
4.2426 0 4.2426
2.2961 0 5.5433
0 0 6

By scaling the points from 1-4edge.dat with 5 and 6, respectively, we get:

5 0 0 
4.6195 0 1.9135
3.5355 0 3.5355
1.9135 0 4.6195
0 0 5

6 0 0 
5.5434 0 2.2962 
4.2426 0 4.2426
2.2962 0 5.5434 
0 0 6

Which differ from the points in the official file where highlighted.


Calculations done in JS console, by:
'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 5*x).join(' ');
'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 6*x).join(' ');


RE: Rounding Errors in primitives? - Magnus Forsberg - 2021-05-05

(2021-05-05, 8:50)Lasse Deleuran Wrote: I want to learn how to perform the correct calculation, so that my testing framework can include these primitives as well.
Can you please tell me where I am making a wrong assumption below?

I'm sorry, I can't point in any direction.  I don't speak math...

Do you know that PrimGen2 is integrated in LDPE? And LDPE is platform independant, right?


RE: Rounding Errors in primitives? - Travis Cobbs - 2021-05-06

I'm pretty sure that 1-4ring5.dat is wrong.


RE: Rounding Errors in primitives? - Orion Pobursky - 2021-05-06

(2021-05-05, 15:29)Magnus Forsberg Wrote: I'm sorry, I can't point in any direction.  I don't speak math...

Do you know that PrimGen2 is integrated in LDPE? And LDPE is platform independant, right?

LDPE doesn't do any good for the WebGL framework Lasse maintains. He's trying to figure out what the correct way is in order to generate these primitives such that the code framework can validate them correctly (for error checking) and auto-generate them (to save time have to parse and render these files client side).


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-06-06

(2021-05-06, 18:48)Travis Cobbs Wrote: I'm pretty sure that 1-4ring5.dat is wrong.

But how can we figure out if it is wrong or not? I do not have access to the source code of PrimGen2, and I cannot find any documentation for how the points are computed. 

All I can do for now is to relax the comparisons to allow large errors. 

Not even allowing an error of 0.0001 is sufficient, as 1-4ring7.dat has the following quad:

4 16 8 0 0 7.391 0 3.0614 6.4672 0 2.6788 7 0 0

But using the same computation as mentioned above, I get the following where differences over 0.0001 are highlighted:

4 16 8 0 0 7.3912 0 3.0616 6.4673 0 2.6789 7 0 0




Full transparency. The points of the quad are computed exactly as before by scaling the points of 1-4edge.dat in Javascript:

'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 7*x).join(' ');

'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 8*x).join(' ');


RE: Rounding Errors in primitives? - Travis Cobbs - 2021-06-06

(2021-06-06, 11:49)Lasse Deleuran Wrote: But how can we figure out if it is wrong or not?

By doing it right and comparing.

  1. Compute the X and Z for the given angle using sin and cos and a radius of 1.
  2. Round each number to 4 decimal places.
  3. Multiply the rounded numbers by the desired radius.



RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-06-10

(2021-06-06, 23:16)Travis Cobbs Wrote: By doing it right and comparing.

  1. Compute the X and Z for the given angle using sin and cos and a radius of 1.
  2. Round each number to 4 decimal places.
  3. Multiply the rounded numbers by the desired radius.

Here are the calculations:

1) 
1-4edge.dat consists of a quarter circle of radius 1 with three points between the end points.

The angles of the three points to put into cos and sin in order to get the coordinates of the points are:

1*PI/8
2*PI/8
3*PI/8

cos and sin for the four angles give us the points (note the symmetries and redo these computations by pasting the left hand sides into google):

cos(1*PI/8) = 0.92387953251
cos(2*PI/8) = 0.70710678118
cos(3*PI/8) = 0.38268343236
sin(1*PI/8) = 0.38268343236
sin(2*PI/8) = 0.70710678118
sin(3*PI/8) = 0.92387953251

2)
Rounding these to 4 decimals

0.92387953251 -> 0.9239
0.70710678118 -> 0.7071
0.38268343236 -> 0.3827

This shows that the values of 1-4edge.dat are correct. The content is copied below for transparency:

2 24 1 0 0 0.9239 0 0.3827
2 24 0.9239 0 0.3827 0.7071 0 0.7071
2 24 0.7071 0 0.7071 0.3827 0 0.9239
2 24 0.3827 0 0.9239 0 0 1

3)
Since the points of 1-4edge.dat are correct, the points of 1-4ring5.dat can be computed as in my previous post. Recall that the points of 1-4ring5.dat span from the quarter circle of diameter 5 to the quarter circle of diameter 6:

5 0 0
4.6195 0 1.9135
3.5355 0 3.5355
1.9135 0 4.6195
0 0 5

6 0 0
5.5434 0 2.2962
4.2426 0 4.2426
2.2962 0 5.5434
0 0 6

Which differ from the points in the official file where highlighted.

Final calculations done in JS console, by:
'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 5*x).join(' ');
'1 0 0 0.9239 0 0.3827 0.7071 0 0.7071 0.3827 0 0.9239 0 0 1'.split(' ').map(x => 6*x).join(' ');

Shall I start submitting the fixed files to Chris?


RE: Rounding Errors in primitives? - Orion Pobursky - 2021-06-10

(2021-06-10, 17:42)Lasse Deleuran Wrote: Shall I start submitting the fixed files to Chris?

Go for it with this caveat:
We need to look at all the files that use the primitive(s) in question to ensure that they also don't need to be adjusted.


RE: Rounding Errors in primitives? - Lasse Deleuran - 2021-06-11

(2021-06-10, 17:59)Orion Pobursky Wrote: Go for it with this caveat:
We need to look at all the files that use the primitive(s) in question to ensure that they also don't need to be adjusted.

That is a good callout. I will take the files one by one and work on them. Luckily the parts tracker is great at showing dependencies, which helps a lot with this.