Freedom-of-Form-Foundation / anatomy3d

A CAD tool for humanoid anatomy alterations. See the anatomy3d-blender repository for more recent work.
https://freedomofform.org/1856/3d-anatomy-project-scope-phase-1-focus-on-a-limb-joint/
GNU General Public License v2.0
7 stars 5 forks source link

Unexpected behavior with radiusPoints in ExampleBone.cs #58

Closed zennithn closed 2 years ago

zennithn commented 3 years ago

I've been messing around with the current version of the program. It appears that control over the central spline of a bone is matching expectation, however I'm encountering unexpected behavior with the current implementation of radiusPoints. The unexpected behavior occurs whether the bone's central spline is a SpatialCubicSpline or just a LineSegment; therefore, the unexpected behavior is due to QuadraticSpline1D itself, and not the implementation of the underlying central spline.

It's possible I'm just using this in the wrong way, but if that's true, that at least means the current implementation about radius control is unintuitive and worth a fresh look.

I've made a bone using the following "EXAMPLE A":

` SortedList<float, Numerics.Vector3> centerPoints = new SortedList<float, Numerics.Vector3>(); centerPoints.Add(0.0f, new Numerics.Vector3(-4.0f, -0.5f, 0.0f)); centerPoints.Add(0.25f, new Numerics.Vector3(-2.0f, -0.05f, 0.0f)); centerPoints.Add(0.5f, new Numerics.Vector3(0.0f, 0.0f, 0.2f)); centerPoints.Add(0.75f, new Numerics.Vector3(2.0f, 0.0f, 0.0f)); centerPoints.Add(1.0f, new Numerics.Vector3(4.0f, 0.0f, 0.0f)); SpatialCubicSpline boneCenter = new SpatialCubicSpline(centerPoints);

SortedList<float, float> radiusPoints = new SortedList<float, float>();
radiusPoints.Add(-5.0f, 0.9f);
radiusPoints.Add(-3.0f, 0.9f);
radiusPoints.Add(-0.5f, 0.8f);
radiusPoints.Add(0.02f, 0.9f);
radiusPoints.Add(0.15f, 0.7f);
radiusPoints.Add(0.5f, 0.7f);
radiusPoints.Add(2.8f, 0.8f);
radiusPoints.Add(3.9f, 0.8f);
radiusPoints.Add(6.0f, 0.8f);
QuadraticSpline1D boneRadius = new QuadraticSpline1D(radiusPoints);

`

The intent was to have a bone with a bulge at one end, a slight bulge part of the way down, a slightly thinner shaft, and a modest enlargement again near where I think a trochlea might go in the future.

It appears that the defined radiusPoints along boneRadius have to extend with a length similar to or greater than that of the length along SpatialCubicSpline boneCenter, so that is why I had the 0th radiusPoint be at key -5.0f and the last radiusPoint be at key 6.0f.

With radius values ranging from 0.7f at lowest to 0.9f at highest, it is unexpected for a multi-fold-change difference in observed radii of the bone as rendered.

image

I've tried a few different arrangements of radiusPoints, and the behavior appears to be highly irregular and seemingly exclusively due to radiusPoints.

See these examples: Example B Same centerPoints as above. radiusPoints.Add(-5.0f, 0.9f); radiusPoints.Add(-0.5f, 0.8f); radiusPoints.Add(0.02f, 0.9f); radiusPoints.Add(0.5f, 0.7f); radiusPoints.Add(6.0f, 0.8f)

image

Example C Same centerPoints as above. radiusPoints.Add(-5.0f, 0.9f); radiusPoints.Add(-0.5f, 0.8f); radiusPoints.Add(0.5f, 0.7f); radiusPoints.Add(6.0f, 0.8f) image

Example D - testing if the cartesian placement of the centerPoints affects anything, in comparison to Example B. Conclusion: cartesian placement has no effect. ` SortedList<float, Numerics.Vector3> centerPoints = new SortedList<float, Numerics.Vector3>(); centerPoints.Add(0.0f, new Numerics.Vector3(1.0f, -0.5f, 0.0f)); centerPoints.Add(0.25f, new Numerics.Vector3(3.0f, -0.05f, 0.0f)); centerPoints.Add(0.5f, new Numerics.Vector3(5.0f, 0.0f, 0.2f)); centerPoints.Add(0.75f, new Numerics.Vector3(7.0f, 0.0f, 0.0f)); centerPoints.Add(1.0f, new Numerics.Vector3(9.0f, 0.0f, 0.0f)); SpatialCubicSpline boneCenter = new SpatialCubicSpline(centerPoints);

SortedList<float, float> radiusPoints = new SortedList<float, float>();
radiusPoints.Add(-5.0f, 0.9f);
radiusPoints.Add(-0.5f, 0.8f);
radiusPoints.Add(0.02f, 0.9f);
radiusPoints.Add(0.5f, 0.7f);
radiusPoints.Add(6.0f, 0.8f);
QuadraticSpline1D boneRadius = new QuadraticSpline1D(radiusPoints);

` image

I'd also love to have a discussion about ways we can more clearly define what the expected behavior is, as well as how to test for it. Thus, I'd definitely appreciate Kistaro's help as well.

AdamNorberg commented 3 years ago

I’m pretty sure the radius points are only evaluated between 0 and 1, so every X value outside that range will be ignored in rendering, although used for spline calculation.

zennithn commented 3 years ago

Playing a lot with the range of 0 to 1, that does seem to be true, though there's still a bit of weirdness going on. Please see the following results:

SortedList<float, Numerics.Vector3> centerPoints = new SortedList<float, Numerics.Vector3>();
centerPoints.Add(0.0f, new Numerics.Vector3(-4.0f, -0.5f, 0.0f));
centerPoints.Add(0.25f, new Numerics.Vector3(-2.0f, -0.05f, 0.0f));
centerPoints.Add(0.5f, new Numerics.Vector3(0.0f, 0.0f, 0.2f));
centerPoints.Add(0.75f, new Numerics.Vector3(2.0f, 0.0f, 0.0f));
centerPoints.Add(1.0f, new Numerics.Vector3(3.5f, 0.1f, 0.1f));
SpatialCubicSpline boneCenter = new SpatialCubicSpline(centerPoints);

Using those center points, I used radiusPoints that differed only on the radius for the first four key/value pairs in the radiusPoints SortedList. I'm observing some weird bulging that appears to diverge from the relatively small changes in radius I would personally expect.

image

image

zennithn commented 3 years ago

In some testing, LinearSpline1D appears to reduce unexpected behavior. Therefore, I interpret this to suggest we should work more carefully to figure out useful ways of interpolating between defined radii along a bone. Please compare the below images to prior images in this issue discussion.

Compare to my reply comment's first picture: image

Compare to my reply's second picture: image

Compare to Example D from my first issue post: image

Compare to Example A from my first issue post: image