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