Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ performance and stability in wrapping solutions.
- Implemented `generateDecorations()` for `Station` to allow visualization in the Simbody visualizer. (#4169)
- Added `Component::removeComponent` and `Component::extractComponent` methods, which enable removing subcomponents that were previously added via `Component::addComponent` or the `<components>` XML element (#4174).
- Updated required language level to C++20. (#3929)
- Breaking: removed the `operator==` and `operator<` overloads in `ControlLinearNode` and replaced usages with the equivalent utility functions `isEqual()` and `isLessThan()`. (#4095)


v4.5.2
======
Expand Down
67 changes: 54 additions & 13 deletions OpenSim/Simulation/Control/ControlLinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ getParameterList(double aT,Array<int> &rList)

// FIND THE NODE
_searchNode.setTime(aT);
int i = _xNodes.searchBinary(_searchNode);
int i = searchBinary(_xNodes, _searchNode);

// LESS THAN TIME OF FIRST NODE
if(i<0) {
Expand All @@ -297,7 +297,7 @@ getParameterList(double aT,Array<int> &rList)
rList.append(size-1);

// EQUAL & LINEAR INTERPOLATION
} else if((!_useSteps) && (_searchNode == (*_xNodes.get(i)) )) {
} else if((!_useSteps) && (_searchNode.isEqual((*_xNodes.get(i))))) {
rList.append(i);

// BETWEEN & LINEAR INTERPOLATION
Expand Down Expand Up @@ -327,23 +327,23 @@ getParameterList(double aTLower,double aTUpper,Array<int> &rList)

// LOWER NODE
_searchNode.setTime(aTLower);
int iL = _xNodes.searchBinary(_searchNode);
int iL = searchBinary(_xNodes, _searchNode);
if(iL==-1) {
iL += 1;
} else if(iL==(size-1)) {
return(0);
} else if( (*_xNodes.get(iL)) == _searchNode ) {
} else if( (*_xNodes.get(iL)).isEqual(_searchNode) ) {
iL += 1;
} else {
iL += 2;
}

// UPPER NODE
_searchNode.setTime(aTUpper);
int iU = _xNodes.searchBinary(_searchNode);
int iU = searchBinary(_xNodes, _searchNode);
if(iU==-1) {
return(0);
} else if( (*_xNodes.get(iU)) < _searchNode) {
} else if( (*_xNodes.get(iU)).isLessThan(_searchNode) ) {
iU += 1;
}

Expand Down Expand Up @@ -380,7 +380,7 @@ void ControlLinear::
setControlValue(ArrayPtrs<ControlLinearNode> &aNodes,double aT,double aValue)
{
ControlLinearNode node(aT,aValue);
int lower = aNodes.searchBinary(node);
int lower = searchBinary(aNodes, node);

// NO NODE
if(lower<0) {
Expand All @@ -392,15 +392,15 @@ setControlValue(ArrayPtrs<ControlLinearNode> &aNodes,double aT,double aValue)
int upper = lower + 1;

// EQUAL TO LOWER NODE
if( (*aNodes[lower]) == node) {
if( (*aNodes[lower]).isEqual(node) ) {
aNodes[lower]->setTime(aT);
aNodes[lower]->setValue(aValue);

// NOT AT END OF ARRAY
} else if(upper<aNodes.getSize()) {

// EQUAL TO UPPER NODE
if( (*aNodes[upper]) == node) {
if( (*aNodes[upper]).isEqual(node) ) {
aNodes[upper]->setTime(aT);
aNodes[upper]->setValue(aValue);

Expand All @@ -426,7 +426,7 @@ getControlValue(ArrayPtrs<ControlLinearNode> &aNodes,double aT)

// GET NODE
_searchNode.setTime(aT);
int i = aNodes.searchBinary(_searchNode);
int i = searchBinary(aNodes, _searchNode);

// BEFORE FIRST
double value;
Expand Down Expand Up @@ -512,6 +512,47 @@ extrapolateAfter(ArrayPtrs<ControlLinearNode> &aNodes,double aT) const
return(value);
}

int ControlLinear::
searchBinary(const ArrayPtrs<ControlLinearNode>& nodes,
const ControlLinearNode& value) const
{
const int size = nodes.getSize();
if(size <= 0) {
return -1;
}

int lo = 0;
int hi = size - 1;
int mid = -1;

while(lo <= hi) {
mid = (lo + hi) / 2;
const ControlLinearNode& candidate = *nodes[mid];

if(value.isLessThan(candidate)) {
hi = mid - 1;
} else if(candidate.isLessThan(value)) {
lo = mid + 1;
} else {
break;
}
}

if(mid < 0) {
return -1;
}

if(value.isLessThan(*nodes[mid])) {
mid--;
}

if(mid < 0) {
return -1;
}

return mid;
}

//-----------------------------------------------------------------------------
// CONTROL VALUE
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -743,7 +784,7 @@ filter(double aT)
// FIND CONTROL NODE
// Find the control node at time aT
_searchNode.setTime(aT);
int i = _xNodes.searchBinary(_searchNode);
int i = searchBinary(_xNodes, _searchNode);
// The following property is true after binary search:
// _xNodes[i].getValue() <= getControlValue(aT)
// i.e. the node whose index (i) was returned is the node
Expand All @@ -767,7 +808,7 @@ filter(double aT)
return;
}
// True iff _xNodes[i] occurs at aT
bool nodeOccursAtGivenTime = (_searchNode == (*_xNodes.get(i)));
bool nodeOccursAtGivenTime = (_searchNode.isEqual((*_xNodes.get(i))));
// This if statement represents the case where the second
// node occurs at aT.
if ((i == 1) && nodeOccursAtGivenTime) {
Expand All @@ -778,7 +819,7 @@ filter(double aT)
// HANDLE ALL OTHER CASES
double dt, dtPrev, xPrev, xPrevPrev;
// If the time of the node at index i is equal to aT (where
// "equal" is determined by the operator== function of the
// "equal" is determined by the isEqual function of the
// ControlLinearNode class):
// (i <= 1 cases were handled above)
if (nodeOccursAtGivenTime) {
Expand Down
2 changes: 2 additions & 0 deletions OpenSim/Simulation/Control/ControlLinear.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(ControlLinear, Control);
double getControlValue(ArrayPtrs<ControlLinearNode> &aNodes,double aT);
double extrapolateBefore(const ArrayPtrs<ControlLinearNode> &aNodes,double aT) const;
double extrapolateAfter(ArrayPtrs<ControlLinearNode> &aNodes,double aT) const;
int searchBinary(const ArrayPtrs<ControlLinearNode>& nodes,
const ControlLinearNode& value) const;

//=============================================================================
}; // END of class ControlLinear
Expand Down
4 changes: 2 additions & 2 deletions OpenSim/Simulation/Control/ControlLinearNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ operator=(const ControlLinearNode &aNode)
* @return True if the times are equal, false otherwise.
*/
bool ControlLinearNode::
operator==(const ControlLinearNode &aNode) const
isEqual(const ControlLinearNode &aNode) const
{
if((_t) > aNode._t) return(false);
if((_t) < aNode._t) return(false);
Expand All @@ -159,7 +159,7 @@ operator==(const ControlLinearNode &aNode) const
* @return True if the time of this node is less than the time of aNode.
*/
bool ControlLinearNode::
operator<(const ControlLinearNode &aNode) const
isLessThan(const ControlLinearNode &aNode) const
{
if(_t<aNode._t) return(true);
else return(false);
Expand Down
4 changes: 2 additions & 2 deletions OpenSim/Simulation/Control/ControlLinearNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ OpenSim_DECLARE_CONCRETE_OBJECT(ControlLinearNode, Object);
public:
#ifndef SWIG
ControlLinearNode& operator=(const ControlLinearNode &aControl);
bool operator==(const ControlLinearNode &aControl) const;
bool operator<(const ControlLinearNode &aControl) const;

friend std::ostream& operator<<(std::ostream &aOut,
const ControlLinearNode &aControlLinearNode);
Expand All @@ -111,6 +109,8 @@ OpenSim_DECLARE_CONCRETE_OBJECT(ControlLinearNode, Object);
//--------------------------------------------------------------------------
// UTILITY
//--------------------------------------------------------------------------
bool isEqual(const ControlLinearNode &aControl) const;
bool isLessThan(const ControlLinearNode &aControl) const;
char* toString();

//=============================================================================
Expand Down
Loading