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

LongitudinalStructure - proposed function and scope of the new class #49

Open zennithn opened 3 years ago

zennithn commented 3 years ago

I want to go ahead and propose a summary of the "LongitudinalStructure" class, which is intended to be part of the overall job of refactoring some data out of LongBone and enable a more flexible data structure overall. We've discussed the idea in abstract, but not formally yet. Since this may impact other areas of the program, I want to call this out for explicit discussion, just in case:

"A LongitudinalStructure represents the simplest geometry defining a first-order approximation of long anatomical shapes, such as a Long Bone. LongitudinalStructure includes information of the central spline (which might be a single spline, or branching), as well as diameter or other information about cross-sectional profile along that spline's shape. In this way, the simple first-order approximation can be separated from more unique and interesting properties of bones, joints, muscles, and other anatomical parts."

LongitudinalStructure.cs will go in FreedomOfFormFoundation.AnatomyEngine.Anatomy

If this is not a problem, that's fine! I just want to make sure this proposal gets extra eyes.

Lathreas commented 3 years ago

Thanks for posting this here! I would like to ask a few questions regarding this refactoring so that I can toy around with the idea. First of all, which additional places beyond a LongBone do you expect a LongitudinalStructure to be used? From what I can see, a LongitudinalStructure would be exactly a Capsule (geometry/Capsule.cs) except with optional branch points alongside it. Is this correct? As far as I am aware, currently only LongBones would be capable of having branch points in our current design, since muscles are modelled by non-branching deformed cylinders and joints by even simpler geometric objects. Though, since you indicate that it is a geometric object, it does warrant being a separate type.

That said, I'd argue LongitudinalStructure belongs to FreedomOfFormFoundation.AnatomyEngine.Geometry instead, since it is a purely geometrical object (since you say "A LongitudinalStructure represents the simplest geometry[...]"). That would be in line with the Capsule shape (in geometry/Capsule.cs), which defines a longitudinal structure without branch points, and stores information about the cross-sectional profile as well.

I'd then also argue that it should be called BranchingCapsule to avoid any ambiguities between the two types. (Of course, a BranchingCapsule with 0 branching points is still possible, just like a spline can still be a straight line yet there's a different Line.cs type as well).

Is this comparison I'm making with Capsule correct, or do you intend there to be different (or more specialized) behavior for the LongitudinalStructure? Would it be possible to use a Capsule for now, avoiding the need for a branched capsule type?

If so, I personally think it'd be faster for now if we stick to using a Capsule to represent a LongBone's first-order geometric approximation, since it already contains the tools you need (central spline, varying radius) minus the branching part. This is because implementing branching will probably take a long time, due to the fact that making such a shape with no intersecting surface parts is not trivial and will have a lot of edge cases. I understand that using branching leads to a more satisfying biologically inspired primary-ossification-center type geometry, but I think that the development time can be reduced by a couple of months if we make do with the tools we have now. I think for the Radius, Ulna and Humerus (and most if not all other long bones) we can still safely use a Capsule without too much trouble due to their length, and that would allow you to go ahead and implement an actual Radius, Ulna or Humerus bone with visual feedback. If it turns out we really cannot go without any branch points, then we can always decide to introduce it, but that'd of course be wasted development time if it isn't absolutely necessary.

Lathreas commented 3 years ago

Ah, looking over your code I think I see what you intend. ^.=.^ LongitudinalStructure is a wrapper around Capsule, right? What additional functionality do you intend to put into LongitudinalStructure have that cannot be found in Capsule?

zennithn commented 3 years ago

@Lathreas 1 - Response about Capsule, and what I'm trying to do Something I'm trying to do is to expose the exact, concrete nodes that define the eventual shape of a Capsule. Currently, I don't see how it's possible to access those exact nodes, due to the Capsule's height map. The Capsule's height map is flexibly specified to be a ContinuousMap<Vector2, float>, and I have no idea how to natively save/load that as data. It's hard to figure out how a user would manipulate it with GUI input, or how a coder would invoke a constructor when defining a LongBone.

Furthermore, Capsule currently seems used only to pass data to the rendering engine. That is suggested from the GetGeometry() method in anatomy3d/engine/anatomy/bones/LongBone.cs (https://github.com/Freedom-of-Form-Foundation/anatomy3d/blob/master/engine/anatomy/bones/LongBone.cs). The Capsule returned is newly instantiated, and doesn't natively encode the authoritative data belonging to that LongBone.

The closest authoritative method to store data I have seen for a LongBone is simply at anatomy3d/gui/ExampleBone.cs (https://github.com/Freedom-of-Form-Foundation/anatomy3d/blob/master/gui/ExampleBone.cs). There, the SortedList<float, float> radiusPoints and SortedList<float, Numerics.Vector3> centerPoints at lines 36 and 49 respectively are the closest thing I've seen to data that can be edited by the user, and easy to validate correct saving and loading to/from files.

2 - Future usage of LongitudinalStructure concept I believe the concept of LongitudinalStructure may likely be used by however we implement muscles, and could also be used in other things like tendons, blood vessels, nerves, or anything else that comes to mind.

3 - What I'd like to see going forward in implementation For a good data format, as well as allowing a user to easily customize various points along a bone, it would be beneficial to have native data encoding for the central spline, as well as for a varying radius along points of that spline. The user should be able to: (a) adjust any discrete point's 3D position along that spline, (b) adjust the radius at discrete longitudinal positions along that spline, and (c) for any radial adjustment in (b), adjust aspects of that radius at discrete angles about that spline.

Branching can happen later, but good design now will help. For now, let's leave branching out of the discussion though.

It is my belief that the SortedList<float, float> radiusPoints and SortedList<float, Numerics.Vector3> centerPoints are the closest existing implementations we have to something that is easily edited, saved, and loaded. (Acknowledging that radiusPoints would preferably be more like a SortedList<float, SortedList<float, float>> perhaps, in order to discretely represent data that would feed into a ContinuousMap<Vector2, float>).

If data resembling the SortedList<float, float> radiusPoints and SortedList<float, Numerics.Vector3> centerPoints can be natively edited within a Capsule object, then perhaps that is satisfactory. If so, then I'd encourage the LongBone implementation (and any other eventual anatomical parts) to natively use Capsule as the sole, authoritative way to store their first-order geometric approximation. If not, then a separate LongitudinalStructure class would be an appropriate way to store that data, as far as I can tell.

Lathreas commented 3 years ago

Update Based on the discussion of 2021-07-25, we decided to implement this idea as a "more opinionated" (subclassed) Capsule class that stores a list of points that can be accessed and updated directly. The name of this class is not yet decided upon, but for now let's refer to it as the "opinionated Capsule". This class is meant to be interactive and persistent, so changes made to the opinionated Capsule are stored in the class instance itself.

This structure would contain a SortedList member variable (or similar list structure) to represent the points of the spline, and the radii. In a future addition, a user might be able to switch between the interpolation functions between connecting points, such as linear interpolation, quadratic interpolation, cubic interpolation, Bezier interpolation, etc.