1 /* -------------------------------------------------------------------------- *
2 * OpenSim: Marker.cpp *
3 * -------------------------------------------------------------------------- *
4 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
5 * See http://opensim.stanford.edu and the NOTICE file for more information. *
6 * OpenSim is developed at Stanford University and supported by the US *
7 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
8 * through the Warrior Web program. *
9 * *
10 * Copyright (c) 2005-2017 Stanford University and the Authors *
11 * Author(s): Peter Loan *
12 * *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
14 * not use this file except in compliance with the License. You may obtain a *
15 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
16 * *
17 * Unless required by applicable law or agreed to in writing, software *
18 * distributed under the License is distributed on an "AS IS" BASIS, *
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
20 * See the License for the specific language governing permissions and *
21 * limitations under the License. *
22 * -------------------------------------------------------------------------- */
23
24 //=============================================================================
25 // INCLUDES
26 //=============================================================================
27 #include "Marker.h"
28 #include "Model.h"
29
30 //=============================================================================
31 // STATICS
32 //=============================================================================
33 using namespace std;
34 using namespace OpenSim;
35 using SimTK::Vec3;
36
37 //=============================================================================
38 // CONSTRUCTOR(S) AND DESTRUCTOR
39 //=============================================================================
40 //_____________________________________________________________________________
41 /*
42 * Default constructor.
43 */
Marker()44 Marker::Marker() :
45 Station()
46 {
47 constructProperties();
48 }
49
50 //_____________________________________________________________________________
51 /*
52 * Convenience constructor.
53 */
Marker(const std::string & name,const PhysicalFrame & frame,const SimTK::Vec3 & location)54 Marker::Marker(const std::string& name, const PhysicalFrame& frame,
55 const SimTK::Vec3& location) :
56 Station(frame, location)
57 {
58 constructProperties();
59 setName(name);
60 }
61
62 //_____________________________________________________________________________
63 /*
64 * Destructor.
65 */
~Marker()66 Marker::~Marker()
67 {
68 }
69
70 //_____________________________________________________________________________
71 /*
72 * Set the data members of this Marker to their null values.
73 */
setNull()74 void Marker::setNull()
75 {
76
77 }
78 //_____________________________________________________________________________
79 /*
80 * Construct properties and initialize their default values.
81 */
constructProperties()82 void Marker::constructProperties()
83 {
84 // Indicate whether the Marker is fixed or not (for MarkerPlacement)
85 constructProperty_fixed(false);
86 }
87
setParentFrameName(const string & name)88 void Marker::setParentFrameName(const string& name)
89 {
90 updSocket<PhysicalFrame>("parent_frame").setConnecteePath(name);
91 }
92
93 //_____________________________________________________________________________
94 /*
95 * Get the 'frame name' field, which is used when the marker is added to
96 * an existing model.
97 */
98
getParentFrameName() const99 const string& Marker::getParentFrameName() const
100 {
101 return getSocket<PhysicalFrame>("parent_frame").getConnecteePath();
102 }
103
104
changeFrame(const PhysicalFrame & parentFrame)105 void Marker::changeFrame(const PhysicalFrame& parentFrame)
106 {
107 if (&parentFrame == &getParentFrame())
108 return;
109
110 setParentFrame(parentFrame);
111 }
112
changeFramePreserveLocation(const SimTK::State & s,const PhysicalFrame & parentFrame)113 void Marker::changeFramePreserveLocation(const SimTK::State& s,
114 const PhysicalFrame& parentFrame)
115 {
116
117 if (&parentFrame == &getParentFrame())
118 return;
119
120 // Preserve location means to switch bodies without changing
121 // the location of the marker in the inertial reference frame.
122 Vec3 newLocation;
123 newLocation = findLocationInFrame(s, parentFrame);
124 set_location(newLocation);
125 setParentFrame(parentFrame);
126 }
127
128 //_____________________________________________________________________________
129 /*
130 * Override default implementation by object to intercept and fix the XML node
131 * underneath the Marker to match current version
132 */
133 /*virtual*/
updateFromXMLNode(SimTK::Xml::Element & aNode,int versionNumber)134 void Marker::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber)
135 {
136
137 if (versionNumber < XMLDocument::getLatestVersion()){
138 if (versionNumber < 30501) {
139 // Parse name of Body under <body>node
140 SimTK::Xml::element_iterator bIter = aNode.element_begin("body");
141 SimTK::String bName = bIter->getValue();
142 // Create nodes for new layout
143 SimTK::Xml::Element connectorsElement("connectors");
144 SimTK::Xml::Element frameElement("Connector_PhysicalFrame_");
145 connectorsElement.insertNodeAfter(connectorsElement.node_end(), frameElement);
146 frameElement.setAttributeValue("name", "parent_frame");
147 SimTK::Xml::Element connecteeElement("connectee_name");
148 // Markers in pre-4.0 models are necessarily 1 level deep
149 // (model, markers), and Bodies were necessarily 1 level deep;
150 // here we create the correct relative path (accounting for sets
151 // being components).
152 bName = XMLDocument::updateConnecteePath30517("bodyset", bName);
153 connecteeElement.setValue(bName);
154 frameElement.insertNodeAfter(frameElement.node_end(), connecteeElement);
155 aNode.insertNodeAfter(bIter, connectorsElement);
156 aNode.eraseNode(bIter);
157 }
158 }
159 // Call base class now assuming _node has been corrected for current version
160 Super::updateFromXMLNode(aNode, versionNumber);
161 }
162
generateDecorations(bool fixed,const ModelDisplayHints & hints,const SimTK::State & state,SimTK::Array_<SimTK::DecorativeGeometry> & appendToThis) const163 void Marker::generateDecorations(bool fixed, const ModelDisplayHints& hints, const SimTK::State& state,
164 SimTK::Array_<SimTK::DecorativeGeometry>& appendToThis) const
165 {
166 Super::generateDecorations(fixed, hints, state, appendToThis);
167 if (!fixed) return;
168 if (!hints.get_show_markers()) return;
169
170 // @TODO default color, size, shape should be obtained from hints
171 const Vec3 color = hints.get_marker_color();
172 const OpenSim::PhysicalFrame& frame = getParentFrame();
173 //const Frame& bf = frame.findBaseFrame();
174 //SimTK::Transform bTrans = frame.findTransformInBaseFrame();
175 //const Vec3& p_BM = bTrans*get_location();
176 appendToThis.push_back(
177 SimTK::DecorativeSphere(.01).setBodyId(frame.getMobilizedBodyIndex())
178 .setColor(color).setOpacity(1.0)
179 .setTransform(get_location())
180 .setScaleFactors(Vec3(1)));
181
182 }
183