opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
scaling_state.h
Go to the documentation of this file.
1#pragma once
2
8
9#include <filesystem>
10#include <format>
11#include <memory>
12#include <utility>
13#include <vector>
14
15namespace opyn
16{
17 // Top-level input state that's required to actually perform model scaling.
18 class ScalingState final { // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19 public:
20 explicit ScalingState()
21 {
22 scalingDocument->finalizeConnections(*scalingDocument);
23 scalingDocument->finalizeFromProperties();
24 }
25
26 ScalingState(const ScalingState& other) :
27 sourceModel{std::make_shared<BasicModelStatePair>(*other.sourceModel)},
28 scalingDocument{std::make_shared<ModelWarperV3Document>(*other.scalingDocument)}
29 {
30 // care: separate `ScalingState`s should act like separate instances with no
31 // reference sharing between them, but the shared pointers in the "main"
32 // `ScalingState` might already be divvied out to UI components, so we
33 // can't just switch the pointers around.
34 scalingDocument->clearConnections();
35 scalingDocument->finalizeConnections(*scalingDocument);
36 scalingDocument->finalizeFromProperties();
37 }
38
39 ScalingState(ScalingState&& tmp) noexcept :
40 ScalingState{static_cast<const ScalingState&>(tmp)}
41 {}
42
43 ~ScalingState() noexcept = default;
44
45 ScalingState& operator=(const ScalingState& other)
46 {
47 // care: separate `ScalingState`s should act like separate instances with no
48 // reference sharing between them, but the shared pointers in the "main"
49 // `ScalingState` might already be divvied out to UI components, so we
50 // can't just switch the pointers around.
51 if (&other == this) {
52 return *this;
53 }
54 *sourceModel = *other.sourceModel;
55 *scalingDocument = *other.scalingDocument;
56 scalingDocument->clearConnections();
57 scalingDocument->finalizeConnections(*scalingDocument);
58 scalingDocument->finalizeFromProperties();
59 return *this;
60 }
61
62 ScalingState& operator=(ScalingState&& tmp) noexcept { return *this = static_cast<const ScalingState&>(tmp); }
63
64 // Source Model Methods
65
66 const ModelStatePair& getSourceModel() const { return *sourceModel; }
67 std::shared_ptr<ModelStatePair> getSourceModelPtr() { return sourceModel; }
68 void loadSourceModelFromOsim(const std::filesystem::path& path)
69 {
70 sourceModel = std::make_shared<BasicModelStatePair>(path);
71 }
73 {
74 sourceModel = std::make_shared<BasicModelStatePair>();
75 }
76
77 // Scaling Document Methods
78
79 std::shared_ptr<const ModelWarperV3Document> getScalingDocumentPtr() const { return scalingDocument; }
80 bool hasScalingSteps() const { return scalingDocument->hasScalingSteps(); }
81 auto iterateScalingSteps() const { return scalingDocument->iterateScalingSteps(); }
82 void addScalingStep(std::unique_ptr<ScalingStep> step)
83 {
84 scalingDocument->addScalingStep(std::move(step));
85 }
87 {
88 return scalingDocument->removeScalingStep(step);
89 }
90 bool eraseScalingStep(const OpenSim::ComponentPath& path)
91 {
92 if (auto* scalingStep = findScalingComponentMut<ScalingStep>(path)) {
93 return eraseScalingStep(*scalingStep);
94 }
95 else {
96 return false;
97 }
98 }
100 {
101 OpenSim::Component* component = findScalingComponentMut(edit.getComponentAbsPath());
102 if (not component) {
103 return;
104 }
105 OpenSim::AbstractProperty* property = FindPropertyMut(*component, edit.getPropertyName());
106 if (not property) {
107 return;
108 }
109 edit.apply(*property);
110 scalingDocument->clearConnections();
111 scalingDocument->finalizeConnections(*scalingDocument);
112 scalingDocument->finalizeFromProperties();
113 }
114 bool disableScalingStep(const OpenSim::ComponentPath& path)
115 {
116 if (auto* scalingStep = findScalingComponentMut<ScalingStep>(path)) {
117 scalingStep->set_enabled(false);
118 scalingDocument->clearConnections();
119 scalingDocument->finalizeConnections(*scalingDocument);
120 scalingDocument->finalizeFromProperties();
121 return true;
122 }
123 else {
124 return false;
125 }
126 }
127 std::vector<ScalingDocumentValidationMessage> getEnabledScalingStepValidationMessages(ScalingCache& scalingCache) const
128 {
129 std::vector<ScalingDocumentValidationMessage> rv;
130
131 if (not hasScalingSteps()) {
132 return rv;
133 }
134
135 const ScalingParameters scalingParameters = getEffectiveScalingParameters();
136
137 for (const auto& scalingStep : scalingDocument->getComponentList<ScalingStep>()) {
138 if (not scalingStep.get_enabled()) {
139 // Only aggregate validation errors from enabled `ScalingStep`s at the document-level.
140 continue;
141 }
142 auto stepMessages = scalingStep.validate(scalingCache, scalingParameters, *sourceModel);
143 rv.reserve(rv.size() + stepMessages.size());
144 for (auto& stepMessage : stepMessages) {
146 .sourceScalingStepAbsPath = scalingStep.getAbsolutePath(),
147 .payload = std::move(stepMessage),
148 });
149 }
150 }
151 return rv;
152 }
154 {
155 return not getEnabledScalingStepValidationMessages(scalingCache).empty();
156 }
158 {
159 scalingDocument = std::make_shared<ModelWarperV3Document>();
160 scalingDocument->finalizeConnections(*scalingDocument);
161 scalingDocument->finalizeFromProperties();
162 }
163 void loadScalingDocument(const std::filesystem::path& path)
164 {
165 scalingDocument = std::make_shared<ModelWarperV3Document>(path);
166 }
167 std::optional<std::filesystem::path> scalingDocumentFilesystemLocation() const
168 {
169 if (const auto filename = scalingDocument->getDocumentFileName(); not filename.empty()) {
170 return std::filesystem::path{filename};
171 }
172 else {
173 return std::nullopt;
174 }
175 }
176
177 bool hasScalingParameterDeclarations() const { return scalingDocument->hasScalingParameters(); }
178 ScalingParameters getEffectiveScalingParameters() const { return scalingDocument->getEffectiveScalingParameters(); }
179 bool setScalingParameterOverride(const std::string& scalingParamName, ScalingParameterValue newValue)
180 {
181 return scalingDocument->setScalingParameterOverride(scalingParamName, newValue);
182 }
183
184 // Model Scaling
185
186 // Tries to generate a scaled version of the source model using the current
187 // scaling steps and scaling parameters.
188 std::unique_ptr<BasicModelStatePair> tryGenerateScaledModel(ScalingCache& scalingCache) const
189 {
190 if (hasScalingStepValidationIssues(scalingCache)) {
191 return nullptr; // there are validation errors, so scaling isn't possible
192 }
193
194 // Create an independent copy of the source model, which will be scaled in-place.
195 OpenSim::Model resultModel = sourceModel->getModel();
196 resultModel.clearConnections();
197 InitializeModel(resultModel);
198 InitializeState(resultModel);
199
200 if (not hasScalingSteps()) {
201 // There are no scaling steps, so a copy of the source model is a scaled model (trivially).
202 return std::make_unique<BasicModelStatePair>(std::move(resultModel));
203 }
204
205 // Calculate the effective scaling parameters (defaults + user-enacted overrides)
206 const ScalingParameters scalingParams = getEffectiveScalingParameters();
207
208 // Apply each scaling step to the scaled model
209 for (const auto& step : scalingDocument->getComponentList<ScalingStep>()) {
210 step.applyScalingStep(scalingCache, scalingParams, *sourceModel, resultModel);
211 }
212
213 // Return the warped model
214 return std::make_unique<BasicModelStatePair>(std::move(resultModel));
215 }
216
217 private:
218 template<typename T = OpenSim::Component>
219 T* findScalingComponentMut(const OpenSim::ComponentPath& p) { return FindComponentMut<T>(*scalingDocument, p); }
220
221 std::shared_ptr<BasicModelStatePair> sourceModel = std::make_shared<BasicModelStatePair>();
222 std::shared_ptr<ModelWarperV3Document> scalingDocument = std::make_shared<ModelWarperV3Document>();
223 };
224}
Definition basic_model_state_pair.h:22
Definition model_state_pair.h:19
Definition model_warper_v3_document.h:25
Definition scaling_cache.h:31
Definition scaling_parameters.h:14
Definition scaling_state.h:18
void applyScalingObjectPropertyEdit(osc::ObjectPropertyEdit edit)
Definition scaling_state.h:99
std::unique_ptr< BasicModelStatePair > tryGenerateScaledModel(ScalingCache &scalingCache) const
Definition scaling_state.h:188
void resetScalingDocument()
Definition scaling_state.h:157
bool eraseScalingStep(const OpenSim::ComponentPath &path)
Definition scaling_state.h:90
void addScalingStep(std::unique_ptr< ScalingStep > step)
Definition scaling_state.h:82
const ModelStatePair & getSourceModel() const
Definition scaling_state.h:66
void loadSourceModelFromOsim(const std::filesystem::path &path)
Definition scaling_state.h:68
std::shared_ptr< const ModelWarperV3Document > getScalingDocumentPtr() const
Definition scaling_state.h:79
auto iterateScalingSteps() const
Definition scaling_state.h:81
bool hasScalingParameterDeclarations() const
Definition scaling_state.h:177
std::shared_ptr< ModelStatePair > getSourceModelPtr()
Definition scaling_state.h:67
std::vector< ScalingDocumentValidationMessage > getEnabledScalingStepValidationMessages(ScalingCache &scalingCache) const
Definition scaling_state.h:127
ScalingState()
Definition scaling_state.h:20
bool hasScalingStepValidationIssues(ScalingCache &scalingCache) const
Definition scaling_state.h:153
ScalingState(const ScalingState &other)
Definition scaling_state.h:26
void loadScalingDocument(const std::filesystem::path &path)
Definition scaling_state.h:163
bool hasScalingSteps() const
Definition scaling_state.h:80
~ScalingState() noexcept=default
ScalingState & operator=(ScalingState &&tmp) noexcept
Definition scaling_state.h:62
bool eraseScalingStep(ScalingStep &step)
Definition scaling_state.h:86
std::optional< std::filesystem::path > scalingDocumentFilesystemLocation() const
Definition scaling_state.h:167
ScalingState(ScalingState &&tmp) noexcept
Definition scaling_state.h:39
ScalingParameters getEffectiveScalingParameters() const
Definition scaling_state.h:178
bool setScalingParameterOverride(const std::string &scalingParamName, ScalingParameterValue newValue)
Definition scaling_state.h:179
void resetSourceModel()
Definition scaling_state.h:72
bool disableScalingStep(const OpenSim::ComponentPath &path)
Definition scaling_state.h:114
Definition scaling_step.h:25
Definition object_property_edit.h:15
void apply(OpenSim::AbstractProperty &)
const std::string & getPropertyName() const
const std::string & getComponentAbsPath() const
Definition component_registry.h:14
void InitializeModel(OpenSim::Model &)
double ScalingParameterValue
Definition scaling_parameter_value.h:9
OpenSim::AbstractProperty * FindPropertyMut(OpenSim::Component &, const std::string &)
SimTK::State & InitializeState(OpenSim::Model &)
Definition scaling_document_validation_message.h:12
OpenSim::ComponentPath sourceScalingStepAbsPath
Definition scaling_document_validation_message.h:13