1 /* -------------------------------------------------------------------------- *
2  *                         OpenSim:  ObjectGroup.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 "ObjectGroup.h"
28 
29 //=============================================================================
30 // STATICS
31 //=============================================================================
32 using namespace std;
33 using namespace OpenSim;
34 
35 //=============================================================================
36 // CONSTRUCTOR(S) AND DESTRUCTOR
37 //=============================================================================
38 //_____________________________________________________________________________
39 /**
40  * Default constructor.
41  */
ObjectGroup()42 ObjectGroup::ObjectGroup() :
43    Object(),
44     _memberNames(_memberNamesProp.getValueStrArray())
45 {
46     setNull();
47     setupProperties();
48 }
49 
50 //_____________________________________________________________________________
51 /**
52  * Constructor taking the group name but no member names.
53  */
ObjectGroup(const string & aName)54 ObjectGroup::ObjectGroup(const string& aName) :
55    Object(),
56     _memberNames(_memberNamesProp.getValueStrArray())
57 {
58     setName(aName);
59     setNull();
60     setupProperties();
61 }
62 
63 //_____________________________________________________________________________
64 /**
65  * Destructor.
66  */
~ObjectGroup()67 ObjectGroup::~ObjectGroup()
68 {
69 }
70 
71 //_____________________________________________________________________________
72 /**
73  * Copy constructor.
74  *
75  * @param aGroup Group to be copied.
76  */
ObjectGroup(const ObjectGroup & aGroup)77 ObjectGroup::ObjectGroup(const ObjectGroup &aGroup) :
78    Object(aGroup),
79     _memberNames(_memberNamesProp.getValueStrArray())
80 {
81     setupProperties();
82     copyData(aGroup);
83 }
84 
85 //=============================================================================
86 // CONSTRUCTION METHODS
87 //=============================================================================
88 //_____________________________________________________________________________
89 /**
90  * Copy data members from one ObjectGroup to another.
91  *
92  * @param aGroup ObjectGroup to be copied.
93  */
copyData(const ObjectGroup & aGroup)94 void ObjectGroup::copyData(const ObjectGroup &aGroup)
95 {
96    _memberNames = aGroup._memberNames;
97     _memberObjects = aGroup._memberObjects; // TODO: this copies pointers... but as long as call setup afterwards it should be okay
98 }
99 
100 //_____________________________________________________________________________
101 /**
102  * Set the data members of this ObjectGroup to their null values.
103  */
setNull()104 void ObjectGroup::setNull()
105 {
106     _memberObjects.setSize(0);
107 }
108 
109 //_____________________________________________________________________________
110 /**
111  * Connect properties to local pointers.
112  */
setupProperties()113 void ObjectGroup::setupProperties()
114 {
115     _memberNamesProp.setName("members");
116     _propertySet.append(&_memberNamesProp);
117 }
118 
119 //=============================================================================
120 // OPERATORS
121 //=============================================================================
122 //_____________________________________________________________________________
123 /**
124  * Assignment operator.
125  *
126  * @return Reference to this object.
127  */
operator =(const ObjectGroup & aGroup)128 ObjectGroup& ObjectGroup::operator=(const ObjectGroup &aGroup)
129 {
130     // BASE CLASS
131     Object::operator=(aGroup);
132 
133     copyData(aGroup);
134 
135     return(*this);
136 }
137 
138 //_____________________________________________________________________________
139 /**
140  * Check if the group contains an object with a certain name.
141  *
142  * @param aName the name of the object.
143  * @return Boolean indicating whether or not the group contains the object.
144  */
contains(const string & aName) const145 bool ObjectGroup::contains(const string& aName) const
146 {
147     for(int i=0; i<_memberObjects.getSize(); i++)
148         if(_memberObjects[i] && _memberObjects[i]->getName()==aName)
149             return true;
150     return false;
151 }
152 
153 //_____________________________________________________________________________
154 /**
155  * Add an object to the group.
156  *
157  * @param aObject pointer to the object.
158  */
add(const Object * aObject)159 void ObjectGroup::add(const Object* aObject)
160 {
161     if (aObject != NULL) {
162         // check if object is already a member of this group
163         if (_memberObjects.findIndex(aObject) != -1) return;
164 
165         _memberObjects.append(aObject);
166         _memberNames.append(aObject->getName());
167     }
168 }
169 
170 //_____________________________________________________________________________
171 /**
172  * Remove an object from the group.
173  *
174  * @param aObject pointer to the object.
175  */
remove(const Object * aObject)176 void ObjectGroup::remove(const Object* aObject)
177 {
178     if (aObject != NULL)
179     {
180         int index = _memberObjects.findIndex(const_cast<Object*>(aObject));
181         if(index >= 0) {
182             _memberObjects.remove(index);
183             _memberNames.remove(index);
184         }
185     }
186 }
187 
188 //_____________________________________________________________________________
189 /**
190  * Replace an object in the group with another object.
191  *
192  * @param aOldObject pointer to the old object.
193  * @param aNewObject pointer to the new object.
194  */
replace(const Object * aOldObject,const Object * aNewObject)195 void ObjectGroup::replace(const Object* aOldObject, const Object* aNewObject)
196 {
197     if (aOldObject != NULL && aNewObject != NULL)
198     {
199         int index = _memberObjects.findIndex(const_cast<Object*>(aOldObject));
200         if(index >= 0) {
201             _memberObjects.updElt(index) = aNewObject;
202             _memberNames.updElt(index) = aNewObject->getName();
203         }
204     }
205 }
206 
207 //_____________________________________________________________________________
208 /**
209  * Set up the group, after the member names have been deserialized.
210  * For each member name, if the name is the name of an object in
211  * aObject (the objects in the set that this group belongs to), then
212  * store a pointer to the object in the same index in _memberObjects
213  * as the name is in _memberNames. If the member name does not correspond
214  * to an object in aObjects, remove the name from _memberNames.
215  *
216  * @param aObjects list of objects that are in the set that this group belongs to.
217  */
setupGroup(ArrayPtrs<Object> & aObjects)218 void ObjectGroup::setupGroup(ArrayPtrs<Object>& aObjects)
219 {
220     _memberObjects.setSize(0); // clear existing contents
221     for (int i=0; i<_memberNames.getSize();) {
222         int index = aObjects.getIndex(_memberNames.get(i));
223         if (index > -1) {
224             _memberObjects.insert(i, aObjects.get(index));
225             i++;
226         } else {
227             _memberNames.remove(i);
228         }
229     }
230 }
231