90 const OpenSim::Model& sourceModel,
91 OpenSim::Model& resultModel)
const final
98 const SimTK::Rotation rotateCylinderXToSurfacePointDirection{get_surface_projection_theta(), SimTK::ZAxis};
99 const SimTK::UnitVec3 surfacePointDirectionInCylinderSpace{rotateCylinderXToSurfacePointDirection * SimTK::Vec3{1.0, 0.0, 0.0}};
102 const SimTK::Vec3 midlinePointInCylinderSpace{0.0, 0.0, get_midline_projection_distance()};
105 for (
int i = 0; i < getProperty_wrap_cylinders().size(); ++i) {
106 const auto* sourceWrapCylinder = FindComponent<OpenSim::WrapCylinder>(sourceModel, get_wrap_cylinders(i));
107 OSC_ASSERT_ALWAYS(sourceWrapCylinder &&
"could not find a `WrapCylinder` in the source model");
110 auto* resultWrapCylinder = FindComponentMut<OpenSim::WrapCylinder>(resultModel, get_wrap_cylinders(i));
111 OSC_ASSERT_ALWAYS(resultWrapCylinder &&
"could not find a `WrapCylinder` in the model");
114 const SimTK::Vec3 newOriginPointInParent = cache.lookupTPSWarpedRigidPoint(
117 sourceWrapCylinder->get_translation(),
118 resultWrapCylinder->get_translation(),
119 sourceWrapCylinder->getFrame(),
120 resultWrapCylinder->getFrame(),
121 *commonParams.sourceLandmarksFrame,
122 *commonParams.resultLandmarksFrame,
123 commonParams.tpsInputs,
124 commonParams.compensateForFrameChanges
128 const SimTK::Vec3 sourceMidlinePointInParent = sourceWrapCylinder->getTransform() * midlinePointInCylinderSpace;
129 const SimTK::Vec3 resultMidlinePointInParent = resultWrapCylinder->getTransform() * midlinePointInCylinderSpace;
130 const SimTK::Vec3 newMidlinePointInParent = cache.lookupTPSWarpedRigidPoint(
133 sourceMidlinePointInParent,
134 resultMidlinePointInParent,
135 sourceWrapCylinder->getFrame(),
136 resultWrapCylinder->getFrame(),
137 *commonParams.sourceLandmarksFrame,
138 *commonParams.resultLandmarksFrame,
139 commonParams.tpsInputs,
140 commonParams.compensateForFrameChanges
144 const SimTK::Vec3 sourceSurfacePointInCylinderSpace = sourceWrapCylinder->get_radius() * surfacePointDirectionInCylinderSpace;
145 const SimTK::Vec3 resultSurfacePointInCylinderSpace = resultWrapCylinder->get_radius() * surfacePointDirectionInCylinderSpace;
146 const SimTK::Vec3 sourceSurfacePointInParent = sourceWrapCylinder->getTransform() * sourceSurfacePointInCylinderSpace;
147 const SimTK::Vec3 resultSurfacePointInParent = resultWrapCylinder->getTransform() * resultSurfacePointInCylinderSpace;
148 const SimTK::Vec3 newSurfacePointInParent = cache.lookupTPSWarpedRigidPoint(
151 sourceSurfacePointInParent,
152 resultSurfacePointInParent,
153 sourceWrapCylinder->getFrame(),
154 resultWrapCylinder->getFrame(),
155 *commonParams.sourceLandmarksFrame,
156 *commonParams.resultLandmarksFrame,
157 commonParams.tpsInputs,
158 commonParams.compensateForFrameChanges
163 const SimTK::UnitVec3 newZAxisDirectionInParent{newMidlinePointInParent - newOriginPointInParent};
174 const SimTK::Vec3 newSurfacePointVectorInParent{newSurfacePointInParent - newOriginPointInParent};
175 const SimTK::UnitVec3 newSurfacePointDirectionInParent{newSurfacePointVectorInParent};
176 OSC_ASSERT((SimTK::dot(newZAxisDirectionInParent, newSurfacePointDirectionInParent) < 1.0 - SimTK::Eps) &&
"cylinder surface point somehow points along Z axis - warping is too strong?");
177 const SimTK::Vec3 newSurfacePointProjectionAlongZVector = newZAxisDirectionInParent * SimTK::dot(newZAxisDirectionInParent, newSurfacePointDirectionInParent);
178 const SimTK::Vec3 newSurfacePointRejectionVector = newSurfacePointVectorInParent - newSurfacePointProjectionAlongZVector;
179 const SimTK::UnitVec3 newSurfacePointRejectionDirection{newSurfacePointRejectionVector};
184 const SimTK::UnitVec3 newXAxisDirectionInParent{rotateCylinderXToSurfacePointDirection.invert() * newSurfacePointRejectionDirection};
187 const SimTK::Rotation newCylinderRotation{newZAxisDirectionInParent, SimTK::ZAxis, newXAxisDirectionInParent, SimTK::XAxis};
193 const double newRadius = newSurfacePointVectorInParent.norm();
196 resultWrapCylinder->set_translation(newOriginPointInParent);
197 resultWrapCylinder->set_xyz_body_rotation(newCylinderRotation.convertRotationToBodyFixedXYZ());
198 resultWrapCylinder->set_radius(newRadius);