1 /* -------------------------------------------------------------------------- *
2  *                       Simbody(tm): SimTKcommon                             *
3  * -------------------------------------------------------------------------- *
4  * This is part of the SimTK biosimulation toolkit originating from           *
5  * Simbios, the NIH National Center for Physics-Based Simulation of           *
6  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
7  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
8  *                                                                            *
9  * Portions copyright (c) 2006-12 Stanford University and the Authors.        *
10  * Authors: Michael Sherman                                                   *
11  * Contributors: Jack Middleton, Peter Eastman                                *
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 #include "SimTKcommon/basics.h"
25 #include "SimTKcommon/Simmatrix.h"
26 #include "SimTKcommon/internal/DecorativeGeometry.h"
27 
28 #include "DecorativeGeometryRep.h"
29 
30 #include <cmath>
31 
32 namespace SimTK {
33 
34 // Some common RGB values; these constants are global external symbols exported
35 // by the library, defined as externs in DecorativeGeometry.h.
36 
37 const Vec3 Black   = Vec3( 0, 0, 0);
38 const Vec3 Gray    = Vec3(.5,.5,.5);
39 const Vec3 Red     = Vec3( 1, 0, 0);
40 const Vec3 Green   = Vec3( 0, 1, 0);
41 const Vec3 Blue    = Vec3( 0, 0, 1);
42 const Vec3 Yellow  = Vec3( 1, 1, 0);
43 const Vec3 Orange  = Vec3( 1,.5, 0);
44 const Vec3 Magenta = Vec3( 1, 0, 1);
45 const Vec3 Purple  = Vec3(.5, 0,.5);
46 const Vec3 Cyan    = Vec3( 0, 1, 1);
47 const Vec3 White   = Vec3( 1, 1, 1);
48 
49     /////////////////////////
50     // DECORATIVE GEOMETRY //
51     /////////////////////////
52 
53 // This is an owner handle if there is no rep or if the rep points back
54 // to this handle.
isOwnerHandle() const55 bool DecorativeGeometry::isOwnerHandle() const {
56     return rep==0 || rep->myHandle == this;
57 }
isEmptyHandle() const58 bool DecorativeGeometry::isEmptyHandle() const {return rep==0;}
59 
~DecorativeGeometry()60 DecorativeGeometry::~DecorativeGeometry() {
61     if (isOwnerHandle())
62         delete rep;
63     rep = 0;
64 }
65 
DecorativeGeometry(const DecorativeGeometry & src)66 DecorativeGeometry::DecorativeGeometry(const DecorativeGeometry& src) : rep(0) {
67     if (src.rep) {
68         rep = src.rep->clone();
69         rep->setMyHandle(*this);
70     }
71 }
72 
operator =(const DecorativeGeometry & src)73 DecorativeGeometry& DecorativeGeometry::operator=(const DecorativeGeometry& src) {
74     if (&src != this) {
75         if (isOwnerHandle()) delete rep;
76         rep = 0;
77         if (src.rep) {
78             rep = src.rep->clone();
79             rep->setMyHandle(*this);
80         }
81     }
82     return *this;
83 }
84 
setBodyId(int b)85 DecorativeGeometry& DecorativeGeometry::setBodyId(int b) {updRep().setBodyId(b);return *this;}
getBodyId() const86 int DecorativeGeometry::getBodyId() const {return getRep().getBodyId();}
setIndexOnBody(int x)87 DecorativeGeometry& DecorativeGeometry::setIndexOnBody(int x) {updRep().setIndexOnBody(x);return *this;}
getIndexOnBody() const88 int DecorativeGeometry::getIndexOnBody() const {return getRep().getIndexOnBody();}
setUserRef(void * p)89 DecorativeGeometry& DecorativeGeometry::setUserRef(void* p) {updRep().setUserRef(p);return *this;}
getUserRef() const90 void* DecorativeGeometry::getUserRef() const {return getRep().getUserRef();}
91 
setTransform(const Transform & X_BD)92 DecorativeGeometry& DecorativeGeometry::setTransform(const Transform& X_BD) {updRep().setTransform(X_BD);return *this;}
getTransform() const93 const Transform& DecorativeGeometry::getTransform() const    {return getRep().getTransform();}
94 
setResolution(Real r)95 DecorativeGeometry& DecorativeGeometry::setResolution(Real r) {updRep().setResolution(r);return *this;}
getResolution() const96 Real DecorativeGeometry::getResolution() const {return getRep().getResolution();}
97 
setScaleFactors(const Vec3 & s)98 DecorativeGeometry& DecorativeGeometry::setScaleFactors(const Vec3& s)
99 {   updRep().setScaleFactors(s); return *this; }
getScaleFactors() const100 const Vec3& DecorativeGeometry::getScaleFactors() const
101 {   return getRep().getScaleFactors(); }
102 
setColor(const Vec3 & rgb)103 DecorativeGeometry& DecorativeGeometry::setColor(const Vec3& rgb) {updRep().setColor(rgb);return *this;}
getColor() const104 const Vec3& DecorativeGeometry::getColor() const   {return getRep().getColor();}
105 
setOpacity(Real o)106 DecorativeGeometry& DecorativeGeometry::setOpacity(Real o)  {updRep().setOpacity(o);return *this;}
getOpacity() const107 Real DecorativeGeometry::getOpacity()  const {return getRep().getOpacity();}
108 
setLineThickness(Real t)109 DecorativeGeometry& DecorativeGeometry::setLineThickness(Real t) {updRep().setLineThickness(t);return *this;}
getLineThickness() const110 Real DecorativeGeometry::getLineThickness() const {return getRep().getLineThickness();}
111 
setRepresentation(const DecorativeGeometry::Representation & r)112 DecorativeGeometry& DecorativeGeometry::setRepresentation(const DecorativeGeometry::Representation& r) {
113     updRep().setRepresentation(r);return *this;
114 }
115 
setFaceCamera(int shouldFace)116 DecorativeGeometry& DecorativeGeometry::setFaceCamera(int shouldFace)
117 {   updRep().setFaceCamera(shouldFace);return *this; }
getFaceCamera() const118 int DecorativeGeometry::getFaceCamera() const
119 {   return getRep().getFaceCamera(); }
120 
121 DecorativeGeometry::Representation
getRepresentation() const122 DecorativeGeometry::getRepresentation() const {return getRep().getRepresentation();}
123 
implementGeometry(DecorativeGeometryImplementation & geometry) const124 void DecorativeGeometry::implementGeometry(DecorativeGeometryImplementation& geometry) const
125 {
126     getRep().implementGeometry(geometry);
127 }
128 
129 
130     //////////////////////
131     // DECORATIVE POINT //
132     //////////////////////
133 
134 /*static*/ bool
isInstanceOf(const DecorativeGeometry & s)135 DecorativePoint::isInstanceOf(const DecorativeGeometry& s) {
136     return DecorativePointRep::isA(s.getRep());
137 }
138 /*static*/ const DecorativePoint&
downcast(const DecorativeGeometry & s)139 DecorativePoint::downcast(const DecorativeGeometry& s) {
140     assert(isInstanceOf(s));
141     return static_cast<const DecorativePoint&>(s);
142 }
143 /*static*/ DecorativePoint&
updDowncast(DecorativeGeometry & s)144 DecorativePoint::updDowncast(DecorativeGeometry& s) {
145     assert(isInstanceOf(s));
146     return static_cast<DecorativePoint&>(s);
147 }
148 
149 const DecorativePointRep&
getRep() const150 DecorativePoint::getRep() const {
151     return SimTK_DYNAMIC_CAST_DEBUG<const DecorativePointRep&>(*rep);
152 }
153 DecorativePointRep&
updRep()154 DecorativePoint::updRep() {
155     return SimTK_DYNAMIC_CAST_DEBUG<DecorativePointRep&>(*rep);
156 }
157 
DecorativePoint(const Vec3 & p)158 DecorativePoint::DecorativePoint(const Vec3& p) {
159     rep = new DecorativePointRep(p);
160     rep->setMyHandle(*this);
161 }
setPoint(const Vec3 & p)162 DecorativePoint& DecorativePoint::setPoint(const Vec3& p) {
163     DecorativePointRep::downcast(*rep).setPoint(p); return *this;
164 }
getPoint() const165 const Vec3& DecorativePoint::getPoint() const {
166     return DecorativePointRep::downcast(*rep).getPoint();
167 }
168 
169 
170     /////////////////////
171     // DECORATIVE LINE //
172     /////////////////////
173 
174 /*static*/ bool
isInstanceOf(const DecorativeGeometry & s)175 DecorativeLine::isInstanceOf(const DecorativeGeometry& s) {
176     return DecorativeLineRep::isA(s.getRep());
177 }
178 /*static*/ const DecorativeLine&
downcast(const DecorativeGeometry & s)179 DecorativeLine::downcast(const DecorativeGeometry& s) {
180     assert(isInstanceOf(s));
181     return static_cast<const DecorativeLine&>(s);
182 }
183 /*static*/ DecorativeLine&
updDowncast(DecorativeGeometry & s)184 DecorativeLine::updDowncast(DecorativeGeometry& s) {
185     assert(isInstanceOf(s));
186     return static_cast<DecorativeLine&>(s);
187 }
188 
189 const DecorativeLineRep&
getRep() const190 DecorativeLine::getRep() const {
191     return SimTK_DYNAMIC_CAST_DEBUG<const DecorativeLineRep&>(*rep);
192 }
193 DecorativeLineRep&
updRep()194 DecorativeLine::updRep() {
195     return SimTK_DYNAMIC_CAST_DEBUG<DecorativeLineRep&>(*rep);
196 }
197 
DecorativeLine(const Vec3 & p1,const Vec3 & p2)198 DecorativeLine::DecorativeLine(const Vec3& p1, const Vec3& p2) {
199     rep = new DecorativeLineRep(p1,p2);
200     rep->setMyHandle(*this);
201 }
setPoint1(const Vec3 & p1)202 DecorativeLine& DecorativeLine::setPoint1(const Vec3& p1) {
203     DecorativeLineRep::downcast(*rep).setPoint1(p1); return *this;
204 }
setPoint2(const Vec3 & p2)205 DecorativeLine& DecorativeLine::setPoint2(const Vec3& p2) {
206     DecorativeLineRep::downcast(*rep).setPoint2(p2); return *this;
207 }
setEndpoints(const Vec3 & p1,const Vec3 & p2)208 DecorativeLine& DecorativeLine::setEndpoints(const Vec3& p1, const Vec3& p2) {
209     DecorativeLineRep::downcast(*rep).setEndpoints(p1,p2); return *this;
210 }
getPoint1() const211 const Vec3& DecorativeLine::getPoint1() const {
212     return DecorativeLineRep::downcast(*rep).getPoint1();
213 }
getPoint2() const214 const Vec3& DecorativeLine::getPoint2() const {
215     return DecorativeLineRep::downcast(*rep).getPoint2();
216 }
217 
218 
219     ///////////////////////
220     // DECORATIVE CIRCLE //
221     ///////////////////////
222 
DecorativeCircle(Real radius)223 DecorativeCircle::DecorativeCircle(Real radius) {
224     rep = new DecorativeCircleRep(radius);
225     rep->setMyHandle(*this);
226 }
setRadius(Real r)227 DecorativeCircle& DecorativeCircle::setRadius(Real r) {
228     DecorativeCircleRep::downcast(*rep).setRadius(r); return *this;
229 }
getRadius() const230 Real DecorativeCircle::getRadius() const {
231     return DecorativeCircleRep::downcast(*rep).getRadius();
232 }
233 
234 
235     ///////////////////////
236     // DECORATIVE SPHERE //
237     ///////////////////////
238 
DecorativeSphere(Real radius)239 DecorativeSphere::DecorativeSphere(Real radius) {
240     rep = new DecorativeSphereRep(radius);
241     rep->setMyHandle(*this);
242 }
243 
setRadius(Real r)244 DecorativeSphere& DecorativeSphere::setRadius(Real r) {
245     DecorativeSphereRep::downcast(*rep).setRadius(r); return *this;
246 }
getRadius() const247 Real DecorativeSphere::getRadius() const {
248     return DecorativeSphereRep::downcast(*rep).getRadius();
249 }
250 
251 
252     //////////////////////////
253     // DECORATIVE ELLIPSOID //
254     //////////////////////////
255 
DecorativeEllipsoid(const Vec3 & radii)256 DecorativeEllipsoid::DecorativeEllipsoid(const Vec3& radii) {
257     rep = new DecorativeEllipsoidRep(radii);
258     rep->setMyHandle(*this);
259 }
260 
setRadii(const Vec3 & r)261 DecorativeEllipsoid& DecorativeEllipsoid::setRadii(const Vec3& r) {
262     DecorativeEllipsoidRep::downcast(*rep).setRadii(r); return *this;
263 }
getRadii() const264 const Vec3& DecorativeEllipsoid::getRadii() const {
265     return DecorativeEllipsoidRep::downcast(*rep).getRadii();
266 }
267     //////////////////////
268     // DECORATIVE BRICK //
269     //////////////////////
270 
DecorativeBrick(const Vec3 & xyzHalfLengths)271 DecorativeBrick::DecorativeBrick(const Vec3& xyzHalfLengths) {
272     rep = new DecorativeBrickRep(xyzHalfLengths);
273     rep->setMyHandle(*this);
274 }
275 
setHalfLengths(const Vec3 & xyzHalfLengths)276 DecorativeBrick& DecorativeBrick::setHalfLengths(const Vec3& xyzHalfLengths) {
277     DecorativeBrickRep::downcast(*rep).setHalfLengths(xyzHalfLengths);
278     return *this;
279 }
getHalfLengths() const280 const Vec3& DecorativeBrick::getHalfLengths() const {
281     return DecorativeBrickRep::downcast(*rep).getHalfLengths();
282 }
283 
284     /////////////////////////
285     // DECORATIVE CYLINDER //
286     /////////////////////////
287 
DecorativeCylinder(Real radius,Real halfHeight)288 DecorativeCylinder::DecorativeCylinder(Real radius, Real halfHeight) {
289     rep = new DecorativeCylinderRep(radius,halfHeight);
290     rep->setMyHandle(*this);
291 }
292 
setRadius(Real r)293 DecorativeCylinder& DecorativeCylinder::setRadius(Real r) {
294     DecorativeCylinderRep::downcast(*rep).setRadius(r); return *this;
295 }
setHalfHeight(Real r)296 DecorativeCylinder& DecorativeCylinder::setHalfHeight(Real r) {
297     DecorativeCylinderRep::downcast(*rep).setHalfHeight(r); return *this;
298 }
299 
getRadius() const300 Real DecorativeCylinder::getRadius() const {
301     return DecorativeCylinderRep::downcast(*rep).getRadius();
302 }
getHalfHeight() const303 Real DecorativeCylinder::getHalfHeight() const {
304     return DecorativeCylinderRep::downcast(*rep).getHalfHeight();
305 }
306 
307     //////////////////////
308     // DECORATIVE FRAME //
309     //////////////////////
310 
DecorativeFrame(Real axisLength)311 DecorativeFrame::DecorativeFrame(Real axisLength) {
312     rep = new DecorativeFrameRep(axisLength);
313     rep->setMyHandle(*this);
314 }
315 
setAxisLength(Real l)316 DecorativeFrame& DecorativeFrame::setAxisLength(Real l) {
317     DecorativeFrameRep::downcast(*rep).setAxisLength(l); return *this;
318 }
getAxisLength() const319 Real DecorativeFrame::getAxisLength() const {
320     return DecorativeFrameRep::downcast(*rep).getAxisLength();
321 }
322 
323 
324     /////////////////////
325     // DECORATIVE TEXT //
326     /////////////////////
327 
DecorativeText(const std::string & label)328 DecorativeText::DecorativeText(const std::string& label) {
329     rep = new DecorativeTextRep(label);
330     rep->setMyHandle(*this);
331 }
332 
setText(const std::string & label)333 DecorativeText& DecorativeText::setText(const std::string& label) {
334     DecorativeTextRep::downcast(*rep).setText(label); return *this;
335 }
getText() const336 const std::string& DecorativeText::getText() const {
337 return DecorativeTextRep::downcast(*rep).getText();
338 }
339 
setIsScreenText(bool isScreen)340 DecorativeText& DecorativeText::setIsScreenText(bool isScreen) {
341     DecorativeTextRep::downcast(*rep).setIsScreenText(isScreen);
342     return *this;
343 }
getIsScreenText() const344 bool DecorativeText::getIsScreenText() const {
345 return DecorativeTextRep::downcast(*rep).getIsScreenText();
346 }
347 
348     /////////////////////
349     // DECORATIVE MESH //
350     /////////////////////
351 
DecorativeMesh(const PolygonalMesh & mesh)352 DecorativeMesh::DecorativeMesh(const PolygonalMesh& mesh) {
353     rep = new DecorativeMeshRep(mesh);
354     rep->setMyHandle(*this);
355 }
getMesh() const356 const PolygonalMesh& DecorativeMesh::getMesh() const {
357     return DecorativeMeshRep::downcast(*rep).getMesh();
358 }
359 
360 
361     /////////////////////
362     // DECORATIVE MESHFILE //
363     /////////////////////
364 
DecorativeMeshFile(const std::string & meshFile)365 DecorativeMeshFile::DecorativeMeshFile(const std::string& meshFile) {
366     rep = new DecorativeMeshFileRep(meshFile);
367     rep->setMyHandle(*this);
368 }
getMeshFile() const369 const std::string& DecorativeMeshFile::getMeshFile() const {
370     return DecorativeMeshFileRep::downcast(*rep).getMeshFile();
371 }
372 
getMesh() const373 const PolygonalMesh& DecorativeMeshFile::getMesh() const {
374     return DecorativeMeshFileRep::downcast(*rep).getMesh();
375 }
376 
377 /////////////////////
378 // DECORATIVE TORUS //
379 /////////////////////
380 
DecorativeTorus(Real torusR,Real tubeR)381 DecorativeTorus::DecorativeTorus(Real torusR, Real tubeR) {
382     rep = new DecorativeTorusRep(torusR, tubeR);
383     rep->setMyHandle(*this);
384 }
385 
getTorusRadius() const386 Real DecorativeTorus::getTorusRadius() const {
387     return DecorativeTorusRep::downcast(*rep).getTorusRadius();
388 }
389 
getTubeRadius() const390 Real DecorativeTorus::getTubeRadius() const {
391     return DecorativeTorusRep::downcast(*rep).getTubeRadius();
392 }
393 
setTorusRadius(Real torR)394 DecorativeTorus& DecorativeTorus::setTorusRadius(Real torR) {
395     DecorativeTorusRep::downcast(*rep).setTorusRadius(torR); return *this;
396 }
setTubeRadius(Real tubeR)397 DecorativeTorus& DecorativeTorus::setTubeRadius(Real tubeR) {
398     DecorativeTorusRep::downcast(*rep).setTubeRadius(tubeR); return *this;
399 }
400 
401 /////////////////////
402 // DECORATIVE ARROW //
403 /////////////////////
404 
DecorativeArrow(const Vec3 & startPoint,const Vec3 & endPoint,Real tipLength)405 DecorativeArrow::DecorativeArrow
406     (const Vec3& startPoint, const Vec3& endPoint, Real tipLength) {
407     rep = new DecorativeArrowRep(startPoint, endPoint, tipLength);
408     rep->setMyHandle(*this);
409 }
410 
getStartPoint() const411 const Vec3& DecorativeArrow::getStartPoint() const {
412     return DecorativeArrowRep::downcast(*rep).getStartPoint();
413 };
getEndPoint() const414 const Vec3& DecorativeArrow::getEndPoint() const {
415     return DecorativeArrowRep::downcast(*rep).getEndPoint();
416 };
417 
getTipLength() const418 const Real& DecorativeArrow::getTipLength() const{
419     return DecorativeArrowRep::downcast(*rep).getTipLength();
420 };
421 
setStartPoint(const Vec3 & start)422 DecorativeArrow& DecorativeArrow::setStartPoint(const Vec3& start) {
423     DecorativeArrowRep::downcast(*rep).setStartPoint(start); return *this;
424 }
425 
setEndPoint(const Vec3 & end)426 DecorativeArrow& DecorativeArrow::setEndPoint(const Vec3& end) {
427     DecorativeArrowRep::downcast(*rep).setEndPoint(end); return *this;
428 }
429 
setTipLength(Real tipLength)430 DecorativeArrow& DecorativeArrow::setTipLength(Real tipLength) {
431     DecorativeArrowRep::downcast(*rep).setTipLength(tipLength); return *this;
432 }
433 
434 /////////////////////
435 // DECORATIVE CONE //
436 /////////////////////
437 
DecorativeCone(const Vec3 & p1,const UnitVec3 & dir,Real height,Real baseRadius)438 DecorativeCone::DecorativeCone
439     (const Vec3& p1, const UnitVec3& dir, Real height, Real baseRadius) {
440     rep = new DecorativeConeRep(p1, dir, height, baseRadius);
441     rep->setMyHandle(*this);
442 }
443 
getOrigin() const444 const Vec3& DecorativeCone::getOrigin() const {
445     return DecorativeConeRep::downcast(*rep).getOrigin();
446 };
getDirection() const447 const UnitVec3& DecorativeCone::getDirection() const {
448     return DecorativeConeRep::downcast(*rep).getDirection();
449 };
getHeight() const450 const Real& DecorativeCone::getHeight() const{
451     return DecorativeConeRep::downcast(*rep).getHeight();
452 };
getBaseRadius() const453 const Real& DecorativeCone::getBaseRadius() const{
454     return DecorativeConeRep::downcast(*rep).getBaseRadius();
455 };
456 
457 
setOrigin(const Vec3 & origin)458 DecorativeCone& DecorativeCone::setOrigin(const Vec3& origin) {
459     DecorativeConeRep::downcast(*rep).setOrigin(origin); return *this;
460 }
461 
setDirection(const UnitVec3 & direction)462 DecorativeCone& DecorativeCone::setDirection(const UnitVec3& direction) {
463     DecorativeConeRep::downcast(*rep).setDirection(direction); return *this;
464 }
465 
setHeight(Real height)466 DecorativeCone& DecorativeCone::setHeight(Real height) {
467     DecorativeConeRep::downcast(*rep).setHeight(height); return *this;
468 }
469 
setBaseRadius(Real baseR)470 DecorativeCone& DecorativeCone::setBaseRadius(Real baseR) {
471     DecorativeConeRep::downcast(*rep).setBaseRadius(baseR); return *this;
472 }
473 
474 
475     /////////////////
476     // DECORATIONS //
477     /////////////////
478 
479 /*static*/ bool
isInstanceOf(const DecorativeGeometry & s)480 Decorations::isInstanceOf(const DecorativeGeometry& s) {
481     return DecorationsRep::isA(s.getRep());
482 }
483 /*static*/ const Decorations&
downcast(const DecorativeGeometry & s)484 Decorations::downcast(const DecorativeGeometry& s) {
485     assert(isInstanceOf(s));
486     return static_cast<const Decorations&>(s);
487 }
488 /*static*/ Decorations&
updDowncast(DecorativeGeometry & s)489 Decorations::updDowncast(DecorativeGeometry& s) {
490     assert(isInstanceOf(s));
491     return static_cast<Decorations&>(s);
492 }
493 
494 const DecorationsRep&
getRep() const495 Decorations::getRep() const {
496     return SimTK_DYNAMIC_CAST_DEBUG<const DecorationsRep&>(*rep);
497 }
498 DecorationsRep&
updRep()499 Decorations::updRep() {
500     return SimTK_DYNAMIC_CAST_DEBUG<DecorationsRep&>(*rep);
501 }
502 
Decorations()503 Decorations::Decorations() {
504     rep = new DecorationsRep();
505     rep->setMyHandle(*this);
506 }
Decorations(const DecorativeGeometry & decoration)507 Decorations::Decorations(const DecorativeGeometry& decoration) {
508     rep = new DecorationsRep();
509     rep->setMyHandle(*this);
510     updRep().addDecoration(decoration);
511 }
512 Decorations& Decorations::
addDecoration(const DecorativeGeometry & decoration)513 addDecoration(const DecorativeGeometry& decoration) {
514     updRep().addDecoration(decoration);
515     return *this;
516 }
517 Decorations& Decorations::
addDecoration(const Transform & placement,const DecorativeGeometry & decoration)518 addDecoration(const Transform& placement,
519               const DecorativeGeometry& decoration) {
520     updRep().addDecoration(placement, decoration);
521     return *this;
522 }
getNumDecorations() const523 int Decorations::getNumDecorations() const
524 {   return getRep().getNumDecorations(); }
getDecoration(int i) const525 const DecorativeGeometry& Decorations::getDecoration(int i) const
526 {   return getRep().getDecoration(i); }
527 
528 } // namespace SimTK
529 
530