Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_MEASURE_H_ 00002 #define SimTK_SimTKCOMMON_MEASURE_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2008-13 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00037 #include "SimTKcommon/basics.h" 00038 #include "SimTKcommon/Simmatrix.h" 00039 00040 #include <cassert> 00041 00062 // Helper macro shared by SimTK_MEASURE_HANDLE_PREAMBLE and 00063 // SimTK_MEASURE_HANDLE_PREAMBLE_ABSTRACT. 00064 #define SimTK_MEASURE_HANDLE_PREAMBLE_BASE(MH,PH) \ 00065 class Implementation; \ 00066 explicit MH(Implementation* imp) : PH(imp) {} \ 00067 MH(SimTK::Subsystem& sub, Implementation* imp, \ 00068 const SimTK::AbstractMeasure::SetHandle& sh) \ 00069 : PH(sub,imp,sh) {} \ 00070 MH& operator=(const MH& src) {PH::operator=(src); return *this;}\ 00071 MH& shallowAssign(const MH& src) {PH::shallowAssign(src); return *this;}\ 00072 MH& deepAssign(const MH& src) {PH::deepAssign(src); return *this;} 00073 00074 00075 // The default constructor for concrete classes should instantiate 00076 // a default-constructed Implementation object if no Implementation object 00077 // is provided. 00078 #define SimTK_MEASURE_HANDLE_PREAMBLE(MH,PH) \ 00079 SimTK_MEASURE_HANDLE_PREAMBLE_BASE(MH,PH) \ 00080 MH() : PH(new Implementation()) {} \ 00081 explicit MH(SimTK::Subsystem& sub) \ 00082 : PH(sub,new Implementation(), typename PH::SetHandle()) {} 00083 00084 00085 00086 // The default constructor for a still-abstract derived class can't 00087 // instantiate an Implementation. 00088 #define SimTK_MEASURE_HANDLE_PREAMBLE_ABSTRACT(MH,PH) \ 00089 SimTK_MEASURE_HANDLE_PREAMBLE_BASE(MH,PH) \ 00090 MH() : PH() {} 00091 00111 #define SimTK_MEASURE_HANDLE_POSTSCRIPT(MH,PH) \ 00112 static bool isA(const SimTK::AbstractMeasure& m) \ 00113 { return dynamic_cast<const Implementation*>(&m.getImpl()) != 0; } \ 00114 static const MH& getAs(const SimTK::AbstractMeasure& m) \ 00115 { assert(isA(m)); return static_cast<const MH&>(m); } \ 00116 static MH& updAs(SimTK::AbstractMeasure& m) \ 00117 { assert(isA(m)); return static_cast<MH&>(m); } \ 00118 const Implementation& getImpl() const \ 00119 { return SimTK_DYNAMIC_CAST_DEBUG<const Implementation&> \ 00120 (SimTK::AbstractMeasure::getImpl());} \ 00121 Implementation& updImpl() \ 00122 { return SimTK_DYNAMIC_CAST_DEBUG<Implementation&> \ 00123 (SimTK::AbstractMeasure::updImpl());} 00124 00125 namespace SimTK { 00126 00127 class State; 00128 class Subsystem; 00129 class System; 00130 class EventId; 00131 00133 SimTK_DEFINE_UNIQUE_INDEX_TYPE(MeasureIndex); 00134 00135 //============================================================================== 00136 // ABSTRACT MEASURE 00137 //============================================================================== 00151 class SimTK_SimTKCOMMON_EXPORT AbstractMeasure { 00152 protected: 00156 class SetHandle {}; 00157 00158 public: 00159 class Implementation; // local; name is AbstractMeasure::Implementation 00160 00164 explicit AbstractMeasure(Implementation* g=0); 00165 00170 AbstractMeasure(Subsystem&, Implementation* g, const SetHandle&); 00171 00174 AbstractMeasure(const AbstractMeasure&); 00175 00179 AbstractMeasure& operator=(const AbstractMeasure& source) 00180 { return shallowAssign(source); } 00181 00184 ~AbstractMeasure(); 00185 00191 AbstractMeasure& shallowAssign(const AbstractMeasure&); 00192 00197 AbstractMeasure& deepAssign(const AbstractMeasure& source); 00198 00206 int getNumTimeDerivatives() const; 00207 00216 Stage getDependsOnStage(int derivOrder=0) const; 00217 00218 00220 bool isSameMeasure(const AbstractMeasure& other) const 00221 { return impl && impl==other.impl;} 00222 00223 bool isEmptyHandle() const {return !hasImpl();} 00224 00226 bool isInSubsystem() const; 00230 const Subsystem& getSubsystem() const; 00234 MeasureIndex getSubsystemMeasureIndex() const; 00235 00236 // Internal use only 00237 00238 // dynamic_cast the returned reference to a reference to your concrete 00239 // Implementation class. 00240 const Implementation& getImpl() const {assert(impl); return *impl;} 00241 Implementation& updImpl() {assert(impl); return *impl;} 00242 bool hasImpl() const {return impl!=0;} 00243 00244 int getRefCount() const; 00245 private: 00246 // This is the only data member in this class. Also, any class derived 00247 // from AbstractMeasure must have *NO* data members at all (data goes 00248 // in the Implementation class). 00249 Implementation* impl; 00250 00251 friend class Implementation; 00252 }; 00253 00254 00255 //============================================================================== 00256 // MEASURE <T> 00257 //============================================================================== 00260 template <class T> 00261 class Measure_ : public AbstractMeasure { 00262 public: 00265 SimTK_MEASURE_HANDLE_PREAMBLE_ABSTRACT(Measure_, AbstractMeasure); 00266 00274 const T& getValue(const State& s, int derivOrder=0) const 00275 { return getImpl().getValue(s,derivOrder); } 00276 00283 Measure_& setDefaultValue(const T& defaultValue) 00284 { updImpl().setDefaultValue(defaultValue); return *this; } 00285 00288 const T& getDefaultValue() const 00289 { return getImpl().getDefaultValue(); } 00290 00291 // These are built-in Measures with local class names. 00292 00293 // Templatized measures may have restrictions on the allowable template 00294 // type and may be specialized for particular types. 00295 class Zero; // T is any numerical type 00296 class One; // T is any numerical type 00297 class Constant; // T is any assignable type 00298 class Time; // T is any type for which T(t) makes sense. 00299 class Variable; // T is any assignable type (state) 00300 class Result; // T is any assignable type (cache) 00301 class SampleAndHold;// T is any assignable type 00302 class Delay; // T is any assignable type 00303 00304 // This requires any numerical type. 00305 class Plus; 00306 class Minus; 00307 class Scale; 00308 class Differentiate; 00309 00310 // These find extreme values *in time*, not among inputs at the same 00311 // time. They perform elementwise on aggregate types. 00312 class Extreme; // base class for min/max/minabs/maxabs 00313 class Minimum; // most positive value 00314 class Maximum; // most negative value 00315 class MinAbs; // the signed quantity whose absolute value was min 00316 class MaxAbs; // the signed quantity whose absolute value was max 00317 00318 // These accept floating point numerical template arguments only. 00319 class Integrate; 00320 class Sinusoid; 00321 00322 SimTK_MEASURE_HANDLE_POSTSCRIPT(Measure_, AbstractMeasure); 00323 }; 00324 00328 typedef Measure_<Real> Measure; 00329 00330 00331 //============================================================================== 00332 // CONSTANT 00333 //============================================================================== 00338 template <class T> 00339 class Measure_<T>::Constant : public Measure_<T> { 00340 public: 00341 SimTK_MEASURE_HANDLE_PREAMBLE(Constant, Measure_<T>); 00342 00345 explicit Constant(const T& value) 00346 : Measure_<T>(new Implementation(value)) {} 00347 00350 Constant(Subsystem& sub, const T& value) 00351 : Measure_<T>(sub, new Implementation(value), 00352 AbstractMeasure::SetHandle()) {} 00353 00356 Constant& setValue(const T& value) 00357 { updImpl().setValue(value); return *this; } 00358 00359 SimTK_MEASURE_HANDLE_POSTSCRIPT(Constant, Measure_<T>); 00360 }; 00361 00362 //============================================================================== 00363 // ZERO 00364 //============================================================================== 00368 template <class T> 00369 class Measure_<T>::Zero : public Measure_<T>::Constant { 00370 public: 00371 Zero(); 00372 explicit Zero(Subsystem& sub); 00373 }; 00374 00375 template <> 00376 class Measure_< Vector >::Zero : public Measure_< Vector >::Constant { 00377 public: 00378 explicit Zero(int size); 00379 Zero(Subsystem& sub, int size); 00380 }; 00381 00382 //============================================================================== 00383 // ONE 00384 //============================================================================== 00388 template <class T> 00389 class Measure_<T>::One : public Measure_<T>::Constant { 00390 public: 00391 One(); 00392 explicit One(Subsystem& sub); 00393 }; 00394 00395 template <> 00396 class Measure_< Vector >::One : public Measure_< Vector >::Constant { 00397 public: 00398 explicit One(int size); 00399 One(Subsystem& sub, int size); 00400 }; 00401 00402 //============================================================================== 00403 // TIME 00404 //============================================================================== 00406 template <class T> 00407 class Measure_<T>::Time : public Measure_<T> { 00408 public: 00409 SimTK_MEASURE_HANDLE_PREAMBLE(Time, Measure_<T>); 00410 00411 SimTK_MEASURE_HANDLE_POSTSCRIPT(Time, Measure_<T>); 00412 }; 00413 00414 //============================================================================== 00415 // VARIABLE 00416 //============================================================================== 00419 template <class T> 00420 class Measure_<T>::Variable : public Measure_<T> { 00421 public: 00422 SimTK_MEASURE_HANDLE_PREAMBLE(Variable, Measure_<T>); 00423 00424 // TODO: should not require invalidated Stage here. Instead, 00425 // should have a unique "generation" counter for this variable 00426 // and allow subsequent users to check it. 00427 Variable(Subsystem& sub, Stage invalidates, const T& defaultValue) 00428 : Measure_<T>(sub, new Implementation(invalidates, defaultValue), 00429 AbstractMeasure::SetHandle()) {} 00430 00431 00432 void setValue(State& state, const T& value) const 00433 { getImpl().setValue(state, value); } 00434 00435 SimTK_MEASURE_HANDLE_POSTSCRIPT(Variable, Measure_<T>); 00436 }; 00437 00438 //============================================================================== 00439 // RESULT 00440 //============================================================================== 00454 template <class T> 00455 class Measure_<T>::Result : public Measure_<T> { 00456 public: 00457 SimTK_MEASURE_HANDLE_PREAMBLE(Result, Measure_<T>); 00458 00459 // TODO: should not require invalidated Stage here. Instead, 00460 // should have a unique "generation" counter for this cache entry 00461 // and allow subsequent users of the value to check it. 00462 00477 Result(Subsystem& sub, Stage dependsOn, Stage invalidated) 00478 : Measure_<T>(sub, new Implementation(dependsOn, invalidated), 00479 AbstractMeasure::SetHandle()) {} 00480 00482 Stage getDependsOnStage() const {return getImpl().getDependsOnStage();} 00484 Stage getInvalidatedStage() const {return getImpl().getInvalidatedStage();} 00492 Result& setDependsOnStage(Stage dependsOn) 00493 { updImpl().setDependsOnStage(dependsOn); return *this; } 00499 Result& setInvalidatedStage(Stage invalidated) 00500 { updImpl().setInvalidatedStage(invalidated); return *this; } 00501 00514 Result& setIsPresumedValidAtDependsOnStage(bool presume) 00515 { updImpl().setIsPresumedValidAtDependsOnStage(presume); return *this; } 00516 00519 bool getIsPresumedValidAtDependsOnStage() const 00520 { return getImpl().getIsPresumedValidAtDependsOnStage(); } 00521 00522 00528 T& updValue(const State& state) const 00529 { return getImpl().updValue(state); } 00530 00537 void markAsValid(const State& state) const {getImpl().markAsValid(state);} 00538 00542 bool isValid(const State& state) const {return getImpl().isValid(state);} 00543 00551 void markAsNotValid(const State& state) const 00552 { getImpl().markAsNotValid(state); } 00553 00557 void setValue(const State& state, const T& value) const 00558 { updValue(state) = value; markAsValid(state); } 00559 00560 SimTK_MEASURE_HANDLE_POSTSCRIPT(Result, Measure_<T>); 00561 }; 00562 00563 //============================================================================== 00564 // SINUSOID 00565 //============================================================================== 00572 template <class T> 00573 class Measure_<T>::Sinusoid : public Measure_<T> { 00574 public: 00575 SimTK_MEASURE_HANDLE_PREAMBLE(Sinusoid, Measure_<T>); 00576 00577 Sinusoid(Subsystem& sub, 00578 const T& amplitude, 00579 const T& frequency, 00580 const T& phase=T(0)) 00581 : Measure_<T>(sub, new Implementation(amplitude,frequency,phase), 00582 AbstractMeasure::SetHandle()) {} 00583 00584 SimTK_MEASURE_HANDLE_POSTSCRIPT(Sinusoid, Measure_<T>); 00585 }; 00586 00587 //============================================================================== 00588 // PLUS 00589 //============================================================================== 00594 template <class T> 00595 class Measure_<T>::Plus : public Measure_<T> { 00596 public: 00597 SimTK_MEASURE_HANDLE_PREAMBLE(Plus, Measure_<T>); 00598 00599 Plus(Subsystem& sub, const Measure_<T>& left, const Measure_<T>& right) 00600 : Measure_<T>(sub, new Implementation(left, right), 00601 AbstractMeasure::SetHandle()) 00602 { SimTK_ERRCHK_ALWAYS 00603 ( this->getSubsystem().isSameSubsystem(left.getSubsystem()) 00604 && this->getSubsystem().isSameSubsystem(right.getSubsystem()), 00605 "Measure_<T>::Plus::ctor()", 00606 "Arguments must be in the same Subsystem as this Measure."); 00607 } 00608 00609 SimTK_MEASURE_HANDLE_POSTSCRIPT(Plus, Measure_<T>); 00610 }; 00611 00612 //============================================================================== 00613 // MINUS 00614 //============================================================================== 00619 template <class T> 00620 class Measure_<T>::Minus : public Measure_<T> { 00621 public: 00622 SimTK_MEASURE_HANDLE_PREAMBLE(Minus, Measure_<T>); 00623 00624 Minus(Subsystem& sub, const Measure_<T>& left, const Measure_<T>& right) 00625 : Measure_<T>(sub, new Implementation(left, right), 00626 AbstractMeasure::SetHandle()) 00627 { SimTK_ERRCHK_ALWAYS 00628 ( this->getSubsystem().isSameSubsystem(left.getSubsystem()) 00629 && this->getSubsystem().isSameSubsystem(right.getSubsystem()), 00630 "Measure_<T>::Minus::ctor()", 00631 "Arguments must be in the same Subsystem as this Measure."); 00632 } 00633 00634 SimTK_MEASURE_HANDLE_POSTSCRIPT(Minus, Measure_<T>); 00635 }; 00636 00637 //============================================================================== 00638 // SCALE 00639 //============================================================================== 00644 template <class T> 00645 class Measure_<T>::Scale : public Measure_<T> { 00646 public: 00647 SimTK_MEASURE_HANDLE_PREAMBLE(Scale, Measure_<T>); 00648 00649 Scale(Subsystem& sub, Real factor, const Measure_<T>& operand) 00650 : Measure_<T>(sub, new Implementation(factor, operand), 00651 AbstractMeasure::SetHandle()) 00652 { SimTK_ERRCHK_ALWAYS 00653 (this->getSubsystem().isSameSubsystem(operand.getSubsystem()), 00654 "Measure_<T>::Scale::ctor()", 00655 "Argument must be in the same Subsystem as this Measure."); 00656 } 00657 00659 const Measure_<T>& getOperandMeasure() const 00660 { return getImpl().getOperandMeasure(); } 00661 00662 SimTK_MEASURE_HANDLE_POSTSCRIPT(Scale, Measure_<T>); 00663 }; 00664 00665 //============================================================================== 00666 // INTEGRATE 00667 //============================================================================== 00674 template <class T> 00675 class Measure_<T>::Integrate : public Measure_<T> { 00676 public: 00677 SimTK_MEASURE_HANDLE_PREAMBLE(Integrate, Measure_<T>); 00678 00685 Integrate(Subsystem& subsystem, 00686 const Measure_<T>& deriv, 00687 const Measure_<T>& ic, 00688 const T& initAlloc=T(0)) 00689 : Measure_<T>(subsystem, new Implementation(deriv,ic,initAlloc), 00690 AbstractMeasure::SetHandle()) {} 00691 00694 void setValue(State& s, const T& value) const 00695 { return getImpl().setValue(s, value); } 00696 00698 const Measure_<T>& getDerivativeMeasure() const 00699 00700 { return getImpl().getDerivativeMeasure(); } 00703 const Measure_<T>& getInitialConditionMeasure() const 00704 { return getImpl().getInitialConditionMeasure(); } 00705 00706 Integrate& setDerivativeMeasure(const Measure_<T>& d) 00707 { updImpl().setDerivativeMeasure(d); return *this; } 00708 Integrate& setInitialConditionMeasure(const Measure_<T>& ic) 00709 { updImpl().setInitialConditionMeasure(ic); return *this; } 00710 00711 SimTK_MEASURE_HANDLE_POSTSCRIPT(Integrate, Measure_<T>); 00712 }; 00713 00714 //============================================================================== 00715 // DIFFERENTIATE 00716 //============================================================================== 00741 template <class T> 00742 class Measure_<T>::Differentiate : public Measure_<T> { 00743 public: 00744 SimTK_MEASURE_HANDLE_PREAMBLE(Differentiate, Measure_<T>); 00745 00750 Differentiate(Subsystem& subsystem, const Measure_<T>& operand) 00751 : Measure_<T>(subsystem, new Implementation(operand), 00752 AbstractMeasure::SetHandle()) {} 00753 00758 bool isUsingApproximation() const 00759 { return getImpl().isUsingApproximation(); } 00760 00763 const Measure_<T>& getOperandMeasure() const 00764 { return getImpl().getOperandMeasure(); } 00765 00769 Differentiate& setOperandMeasure(const Measure_<T>& operand) 00770 { updImpl().setOperandMeasure(operand); return *this; } 00771 00775 void setForceUseApproximation(bool mustApproximate) 00776 { updImpl().setForceUseApproximation(mustApproximate); } 00777 00782 bool getForceUseApproximation() const 00783 { return getImpl().getForceUseApproximation(); } 00784 00785 SimTK_MEASURE_HANDLE_POSTSCRIPT(Differentiate, Measure_<T>); 00786 }; 00787 00788 //============================================================================== 00789 // EXTREME, MINIMUM, MAXIMUM, MINABS, MAXABS 00790 //============================================================================== 00834 template <class T> 00835 class Measure_<T>::Extreme : public Measure_<T> { 00836 public: 00837 SimTK_MEASURE_HANDLE_PREAMBLE(Extreme, Measure_<T>); 00838 00839 enum Operation { 00840 MaxAbs, // default 00841 Maximum, 00842 MinAbs, 00843 Minimum 00844 }; 00845 00849 Extreme(Subsystem& sub, const Measure_<T>& operand, Operation op=MaxAbs) 00850 : Measure_<T>(sub, new Implementation(operand, op), 00851 AbstractMeasure::SetHandle()) {} 00852 00854 Extreme& setOperation(Operation op) 00855 { updImpl().setOperation(op); return *this; } 00856 00858 Operation getOperation() const {return getImpl().getOperation();} 00859 00865 Real getTimeOfExtremeValue(const State& state) const 00866 { return getImpl().getTimeOfExtremeValue(state); } 00867 00868 void setValue(State& s, const T& value) const 00869 { return getImpl().setValue(s, value); } 00870 00871 const Measure_<T>& getOperandMeasure() const 00872 { return getImpl().getOperandMeasure(); } 00873 00874 Extreme& setOperandMeasure(const Measure_<T>& s) 00875 { updImpl().setOperandMeasure(s); return *this; } 00876 00877 SimTK_MEASURE_HANDLE_POSTSCRIPT(Extreme, Measure_<T>); 00878 }; 00879 00882 template <class T> 00883 class Measure_<T>::Minimum : public Measure_<T>::Extreme { 00884 typedef typename Measure_<T>::Extreme Super; 00885 public: 00886 Minimum(Subsystem& sub, const Measure_<T>& operand) 00887 : Super(sub, operand, Super::Minimum) {} 00888 }; 00889 00892 template <class T> 00893 class Measure_<T>::Maximum : public Measure_<T>::Extreme { 00894 typedef typename Measure_<T>::Extreme Super; 00895 public: 00896 Maximum(Subsystem& sub, const Measure_<T>& operand) 00897 : Super(sub, operand, Super::Maximum) {} 00898 }; 00899 00902 template <class T> 00903 class Measure_<T>::MaxAbs : public Measure_<T>::Extreme { 00904 typedef typename Measure_<T>::Extreme Super; 00905 public: 00906 MaxAbs(Subsystem& sub, const Measure_<T>& operand) 00907 : Super(sub, operand, Super::MaxAbs) {} 00908 }; 00909 00913 template <class T> 00914 class Measure_<T>::MinAbs : public Measure_<T>::Extreme { 00915 typedef typename Measure_<T>::Extreme Super; 00916 public: 00917 MinAbs(Subsystem& sub, const Measure_<T>& operand) 00918 : Super(sub, operand, Super::MinAbs) {} 00919 }; 00920 00921 //============================================================================== 00922 // DELAY 00923 //============================================================================== 00970 template <class T> 00971 class Measure_<T>::Delay : public Measure_<T> { 00972 public: 00974 SimTK_MEASURE_HANDLE_PREAMBLE(Delay, Measure_<T>); 00979 Delay(Subsystem& sub, const Measure_<T>& source, Real delay) 00980 : Measure_<T>(sub, new Implementation(source, delay), 00981 AbstractMeasure::SetHandle()) {} 00982 00988 Delay& setUseLinearInterpolationOnly(bool linearOnly) 00989 { updImpl().setUseLinearInterpolationOnly(linearOnly); return *this; } 00990 01004 Delay& setCanUseCurrentValue(bool canUseCurrentValue) 01005 { updImpl().setCanUseCurrentValue(canUseCurrentValue); return *this; } 01006 01008 Delay& setSourceMeasure(const Measure_<T>& source) 01009 { updImpl().setSourceMeasure(source); return *this; } 01010 01012 Delay& setDelay(Real delay) 01013 { updImpl().setDelay(delay); return *this; } 01014 01016 bool getUseLinearInterpolationOnly() const 01017 { return getImpl().getUseLinearInterpolationOnly(); } 01018 01020 bool getCanUseCurrentValue() const 01021 { return getImpl().getCanUseCurrentValue(); } 01022 01024 const Measure_<T>& getSourceMeasure() const 01025 { return getImpl().getSourceMeasure(); } 01026 01029 Real getDelay() const 01030 { return getImpl().getDelay(); } 01031 01033 SimTK_MEASURE_HANDLE_POSTSCRIPT(Delay, Measure_<T>); 01035 }; 01036 01037 //============================================================================== 01038 // SAMPLE AND HOLD 01039 //============================================================================== 01054 template <class T> 01055 class Measure_<T>::SampleAndHold : public Measure_<T> { 01056 public: 01057 SimTK_MEASURE_HANDLE_PREAMBLE(SampleAndHold, Measure_<T>); 01058 01059 SampleAndHold(Subsystem& sub, const Measure_<T>& source, EventId e); 01060 01063 void setValue(State& s, const T& value) const; 01064 01066 void sample(State& s) const; 01067 01068 const Measure_<T>& getSource() const; 01069 EventId getEventId() const; 01070 01071 SampleAndHold& setSource(const Measure_<T>& s); 01072 SampleAndHold& setEventId(EventId); 01073 01074 SimTK_MEASURE_HANDLE_POSTSCRIPT(SampleAndHold, Measure_<T>); 01075 }; 01076 01077 } // namespace SimTK 01078 01079 #endif // SimTK_SimTKCOMMON_MEASURE_H_