1 #ifndef OPENSIM_GEOMETRY_H_
2 #define OPENSIM_GEOMETRY_H_
3 /* -------------------------------------------------------------------------- *
4  *                            OpenSim:  Geometry.h                            *
5  * -------------------------------------------------------------------------- *
6  * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
7  * See http://opensim.stanford.edu and the NOTICE file for more information.  *
8  * OpenSim is developed at Stanford University and supported by the US        *
9  * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
10  * through the Warrior Web program.                                           *
11  *                                                                            *
12  * Copyright (c) 2005-2017 Stanford University and the Authors                *
13  * Author(s): Ayman Habib                                                     *
14  *                                                                            *
15  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
16  * not use this file except in compliance with the License. You may obtain a  *
17  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
18  *                                                                            *
19  * Unless required by applicable law or agreed to in writing, software        *
20  * distributed under the License is distributed on an "AS IS" BASIS,          *
21  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
22  * See the License for the specific language governing permissions and        *
23  * limitations under the License.                                             *
24  * -------------------------------------------------------------------------- */
25 
26 #include <OpenSim/Common/Component.h>
27 #include "Appearance.h"
28 
29 namespace OpenSim {
30 
31 class Frame;
32 //=============================================================================
33 //=============================================================================
34 /**
35  Class Geometry is intended to be used as the base class for all
36  geometry that needs to be represented in the system, including mesh files,
37  and built in analytic shapes. Any ModelComponent can specify a list of
38  Geometry items to represent itself in graphics window. The relation between
39  a ModelComponent and specific Geometry utilizes the Component mechanism, as
40  the specific pieces of geometry are treated as subcomponents. The placement
41  of the Geometry in 3D space is computed from the Frame that the Geometry is
42  "Connected" to.
43 
44  Geometry (and all its subclasses) serve as the set of higher level primitives
45  available to OpenSim component writers to express the Geometry of interest.
46  The Geometry class handles serialization and also the translation to a set of
47  DecorativeGeometry objects that gets passed to the Visualization system to be
48  rendered.
49 
50  @author Ayman Habib
51  */
52 
53 // Base Geometry
54 class OSIMSIMULATION_API Geometry : public Component {
55     OpenSim_DECLARE_ABSTRACT_OBJECT(Geometry, Component);
56 public:
57 //==============================================================================
58 // PROPERTIES
59 //==============================================================================
60     OpenSim_DECLARE_PROPERTY(scale_factors, SimTK::Vec3,
61         "Scale factors in X, Y, Z directions respectively.");
62     OpenSim_DECLARE_UNNAMED_PROPERTY(Appearance,
63         "Default appearance attributes for this Geometry");
64 
65 //=============================================================================
66 // SOCKETS
67 //=============================================================================
68     OpenSim_DECLARE_SOCKET_FD(frame, Frame,
69         "The frame to which this geometry is attached. Note, being connected "
70         "to a Frame means its transform is used to position this Geometry." );
71 //=============================================================================
72 // INPUTS
73 //=============================================================================
74     OpenSim_DECLARE_INPUT(transform, SimTK::Transform, SimTK::Stage::Position,
75         "The transform that positions the Geometry in Ground so it can be "
76         "positioned. Note, either the Geometry is attached to a Frame OR "
77         "the input transform can be supplied, but not both. ");
78 
79     //--------------------------------------------------------------------------
80     // CONSTRUCTION
81     //--------------------------------------------------------------------------
82 public:
83     /// Default constructor
84     Geometry();
85 
86     /// Convenience constructor that takes a Frame
Geometry(const Frame & frame)87     Geometry(const Frame& frame) : Geometry() {
88         setFrame(frame);
89     }
90 
91     /// Default destructor
~Geometry()92     virtual ~Geometry() {}
93     /** Interface methods to handle the Frame which the Geometry is attached to. */
94     /** %Set the Frame of attachment **/
95     void setFrame(const Frame& frame);
96     /** Return a reference to the name of the Frame to which
97     this Geometry is attached (using a Socket). **/
98 
99     /** Return a reference to the actual Frame to which this Geometry
100     is attached. */
101     const Frame& getFrame() const;
102     //==========================================================================
103     // METHODS
104     //==========================================================================
105     // DEPRECATED: following methods are used by the GUI in version 3.3 and
106     // will be removed before release 4.0 in favor of a mechanism that
107     // handles local/global/shared Appearance objects
108     /// Convenient access to set Appearance/Color
109     /// color is RGB, each components is in the range [0, 1].
setColor(const SimTK::Vec3 & color)110     void setColor(const SimTK::Vec3& color) {
111         upd_Appearance().set_color(color);
112     };
113 
114     /// Convenient access to get Appearance/Color
115     /// returns RGB , each components is in the range [0, 1].
getColor()116     const SimTK::Vec3& getColor() const {
117         return get_Appearance().get_color();
118     };
119 
120     /// Convenient access to set Appearance/Opacity
setOpacity(const double opacity)121     void setOpacity(const double opacity) {
122         upd_Appearance().set_opacity(opacity);
123     };
124     /// Convenient access to get Appearance/Opacity
getOpacity()125     const double getOpacity() {
126         return get_Appearance().get_opacity();
127     };
128 
129     /// Convenient access to set Appearance/representation
setRepresentation(OpenSim::VisualRepresentation rep)130     void setRepresentation(OpenSim::VisualRepresentation rep) {
131         upd_Appearance().set_representation(rep);
132     };
133     /// Convenient access to get Appearance/representation
getRepresentation()134     OpenSim::VisualRepresentation getRepresentation() { return
135         get_Appearance().get_representation();
136     };
137     // END DEPRECATED
138 
139     /// Implement method from Component interface. Subclasses only need to
140     /// implement implementCreateDecorativeGeometry to generate an Array of
141     /// SimTK::DecorativeGeometry. From then on, setting Transforms & Appearance
142     /// is handled by the base class Geometry to avoid duplication.
143     void generateDecorations
144         (bool                                       fixed,
145         const ModelDisplayHints&                    hints,
146         const SimTK::State&                         state,
147         SimTK::Array_<SimTK::DecorativeGeometry>&   appendToThis) const override;
148 
149 
150 protected:
151     /// Map this Geometry into a list of primitives aka SimTK::DecorativeGeometry
152     /// and return the result in the passed in Array.
153     virtual void implementCreateDecorativeGeometry(
154         SimTK::Array_<SimTK::DecorativeGeometry>&) const = 0;
155 
156     void extendFinalizeConnections(Component& root) override;
157 
158 private:
159     // Compute Transform of this geometry relative to its base frame, utilizing
160     // passed in state. Both transform and body_id are set in the passed-in
161     // decorations as a side effect.
162     void setDecorativeGeometryTransform(
163         SimTK::Array_<SimTK::DecorativeGeometry>& decorations,
164         const SimTK::State& state) const;
165 
166     // Manage Appearance (how the Geometry is rendered) by applying Appearance
167     // from Geometry to DecorativeGeometry.
setDecorativeGeometryAppearance(SimTK::DecorativeGeometry & decoration)168     void setDecorativeGeometryAppearance(
169         SimTK::DecorativeGeometry& decoration) const {
170         decoration.setColor(get_Appearance().get_color());
171         decoration.setOpacity(get_Appearance().get_opacity());
172         if (get_Appearance().get_visible())
173             decoration.setRepresentation(
174                 (VisualRepresentation)
175                 get_Appearance().get_representation());
176         else
177             decoration.setRepresentation(SimTK::DecorativeGeometry::Hide);
178     };
179 
180     /// Specify the default values for properties of Geometry
constructProperties()181     void constructProperties() {
182         constructProperty_scale_factors(SimTK::Vec3(1));
183         constructProperty_Appearance(Appearance());
184     }
185 
setNull()186     void setNull() {
187         setAuthors("Ayman Habib");
188     }
189 //=============================================================================
190 };  // END of class Geometry
191 
192 /**
193  * LineGeometry is a utility class used to abstract a line segment.
194  * It is used by muscle segments so that it's as small and useful as possible.
195  *
196  * NOTE: LineGeometry assumes its Frame is Ground!
197  * TODO make LineGeometry draw between actual Points!
198  */
199 class OSIMSIMULATION_API LineGeometry : public Geometry
200 {
201     OpenSim_DECLARE_CONCRETE_OBJECT(LineGeometry, Geometry);
202 public:
203     // Property start_point
204     OpenSim_DECLARE_PROPERTY(start_point, SimTK::Vec3,
205         "Line start point.");
206     // Property end_point
207     OpenSim_DECLARE_PROPERTY(end_point, SimTK::Vec3,
208         "Line end point.");
209     /// Convenience constructor that takes two end points
LineGeometry(SimTK::Vec3 & aPoint1,SimTK::Vec3 & aPoint2)210     LineGeometry(SimTK::Vec3& aPoint1, SimTK::Vec3& aPoint2):
211       Geometry() {
212         constructProperties();
213         setPoints(aPoint1, aPoint2);
214     }
215 
216     /// default constructor, creates line (0,0,0)-(1,1,1)
LineGeometry()217     LineGeometry():
218       Geometry() {
219         constructProperties();
220     }
221 
222     /// destructor
~LineGeometry()223     virtual ~LineGeometry() {}
224     /// Get end points as Vec3 in passed in arguments
getPoints(SimTK::Vec3 & rPoint1,SimTK::Vec3 & rPoint2)225     void getPoints(SimTK::Vec3& rPoint1, SimTK::Vec3& rPoint2) const {
226         rPoint1 = get_start_point();
227         rPoint2 = get_end_point();
228     }
229     /// %Set end points from passed in arguments
setPoints(SimTK::Vec3 & aPoint1,SimTK::Vec3 & aPoint2)230     void setPoints(SimTK::Vec3& aPoint1, SimTK::Vec3& aPoint2) {
231         upd_start_point() = aPoint1;
232         upd_end_point() = aPoint2;
233     }
234 
235 protected:
236     /** Virtual method to map LineGeometry to SimTK::Array of
237     SimTK::DecorativeGeometry.  Appearance, Transforms are handled by base
238     Geometry class. */
239     void implementCreateDecorativeGeometry(
240         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
241 private:
constructProperties()242     void constructProperties() {
243         constructProperty_start_point(SimTK::Vec3(0));
244         constructProperty_end_point(SimTK::Vec3(1));
245     }
246 };
247 /**
248 * Arrow is a Geometry subclass used to represent an arrow. The arrow goes from
249 * start_point (Property) and has direction (Property) and length (Property)
250 *
251 */
252 class OSIMSIMULATION_API Arrow : public Geometry
253 {
254     OpenSim_DECLARE_CONCRETE_OBJECT(Arrow, Geometry);
255 public:
256     // Property start_point
257     OpenSim_DECLARE_PROPERTY(start_point, SimTK::Vec3,
258         "Arrow start point.");
259     // Property direction
260     OpenSim_DECLARE_PROPERTY(direction, SimTK::Vec3,
261         "direction of Arrow");
262 
263     OpenSim_DECLARE_PROPERTY(length, double, "length of Arrow");
264     /// constructor that takes startPoint, direction vector and length
Arrow(SimTK::Vec3 & aPoint1,SimTK::UnitVec3 & aUnitDir,double aLength)265     Arrow(SimTK::Vec3& aPoint1, SimTK::UnitVec3& aUnitDir, double aLength)
266     {
267         constructProperties();
268         updProperty_start_point() = aPoint1;
269         updProperty_direction() = aUnitDir;
270         updProperty_length() = aLength;
271     }
272     /// Default constructor that creates Arrow of length 1 starting at origin
273     /// in the direction (1,1,1)
Arrow()274     Arrow()
275     {
276         constructProperties();
277     }
278     /// destructor
~Arrow()279     virtual ~Arrow() {}
280 
281 protected:
282     /** Virtual method to map Arrow to SimTK::Array of SimTK::DecorativeGeometry.
283     Appearance, Transforms are handled by base Geometry class. */
284     void implementCreateDecorativeGeometry(
285         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
286 private:
constructProperties()287     void constructProperties() {
288         constructProperty_start_point(SimTK::Vec3(0));
289         constructProperty_direction(SimTK::Vec3(1));
290         constructProperty_length(1.0);
291     }
292 };
293 
294 
295 /**
296  * Abstract class for analytical geometry (e.g. surfaces of revolution) whose
297  * rendering is optimized by the graphics library (e.g. threejs). Unlike other
298  * geometry, property edits require a recreation of the AnalyticGeometry on
299  * the renderer and not simple updates. AnalyticGeometry is the base class for
300  * Sphere, Cylinder, Cone, Ellipsoid and Torus geometry.
301  */
302 class OSIMSIMULATION_API AnalyticGeometry : public Geometry
303 {
304     OpenSim_DECLARE_ABSTRACT_OBJECT(AnalyticGeometry, Geometry);
305 
306 public:
AnalyticGeometry()307     AnalyticGeometry() {}
~AnalyticGeometry()308     virtual ~AnalyticGeometry() {}
309 };
310 /**
311  * A class to represent Sphere geometry.
312  */
313 class OSIMSIMULATION_API Sphere : public AnalyticGeometry
314 {
315 OpenSim_DECLARE_CONCRETE_OBJECT(Sphere, AnalyticGeometry);
316 public:
317     OpenSim_DECLARE_PROPERTY(radius, double,
318         "Radius of sphere, defaults to 1.0");
319     /// Default constructor, creates a sphere of radius 1.0
Sphere()320     Sphere() :
321     AnalyticGeometry()
322     {
323         constructProperties();
324     }
325     /// Another constructor that takes in a specified radius
Sphere(double radius)326     Sphere(double radius):
327         AnalyticGeometry()
328         {
329         constructProperties();
330         upd_radius() = radius;
331         }
332     /// destructor
~Sphere()333     ~Sphere() {}
334 
335 protected:
336     /// Virtual method to map Sphere to Array of SimTK::DecorativeGeometry.
337     /// Appearance, Transforms are handled by base Geometry class
338     void implementCreateDecorativeGeometry(
339         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
340 private:
constructProperties()341     void constructProperties() {
342         constructProperty_radius(1.0);
343     }
344 };  // Sphere
345 
346 /**
347 * A class to represent an Ellipsoid geometry.
348 */
349 class OSIMSIMULATION_API Ellipsoid : public AnalyticGeometry
350 {
351     OpenSim_DECLARE_CONCRETE_OBJECT(Ellipsoid, AnalyticGeometry);
352 public:
353     OpenSim_DECLARE_PROPERTY(radii, SimTK::Vec3, "Radii of Ellipsoid.");
354     /// Default constructor, creates an Ellipsoid of radii 0.5, 1., 2.
Ellipsoid()355     Ellipsoid() :
356     AnalyticGeometry()
357     {
358         constructProperties();
359     }
360     /// Constructor that takes in three radii
Ellipsoid(double radius1,double radius2,double radius3)361     Ellipsoid(double radius1, double radius2, double radius3):
362         AnalyticGeometry(){
363         constructProperties();
364         setEllipsoidParams(radius1, radius2, radius3);
365     }
366     /// destructor
~Ellipsoid()367     ~Ellipsoid() {}
368     /// Convenience interface to set radii
setEllipsoidParams(double radius1,double radius2,double radius3)369     void setEllipsoidParams(double radius1, double radius2, double radius3)
370     {
371         upd_radii()[0] = radius1;
372         upd_radii()[1] = radius2;
373         upd_radii()[2] = radius3;
374     }
375 protected:
376     /** Virtual method to map Ellipsoid to SimTK::Array_ of
377     SimTK::DecorativeGeometry.  Appearance, Transforms are handled by base
378     Geometry class. */
379     void implementCreateDecorativeGeometry(
380         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
381 private:
constructProperties()382     void constructProperties() {
383         constructProperty_radii(SimTK::Vec3(0.5, 1., 2.));
384     }
385 };
386 
387 
388 /**
389 * A class to represent a Cylinder geometry.
390 */
391 
392 class OSIMSIMULATION_API Cylinder : public AnalyticGeometry
393 {
394     OpenSim_DECLARE_CONCRETE_OBJECT(Cylinder, AnalyticGeometry);
395 public:
396     // Property radius
397     OpenSim_DECLARE_PROPERTY(radius, double, "Radius of cylinder.");
398     // Property half_height
399     OpenSim_DECLARE_PROPERTY(half_height, double, "Half-Height of cylinder.");
400     /// Default constructor
Cylinder()401     Cylinder() :
402     AnalyticGeometry()
403     {
404         constructProperties();
405     }
406     /// Convenience constructor that takes radius and half-height
Cylinder(const double radius,const double hheight)407     Cylinder(const double radius, const double hheight):
408         AnalyticGeometry()
409         {
410         constructProperties();
411         upd_radius() = radius;
412         upd_half_height() = hheight;
413         }
414     /// destructor
~Cylinder()415     ~Cylinder() {}
416     /// Convenient way to get the two parameters that define the cylinder
getCylinderParams(SimTK::Vec2 & params)417     void getCylinderParams(SimTK::Vec2& params) const
418     {
419         params[0] = get_radius();
420         params[1] = get_half_height();
421     }
422 protected:
423     /** Virtual method to map Cylinder to SimTK::Array_ of SimTK::DecorativeGeometry.
424     Appearance, Transforms are handled by base Geometry class. */
425     void implementCreateDecorativeGeometry(
426         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
427 private:
constructProperties()428     void constructProperties() {
429         constructProperty_radius(0.5);
430         constructProperty_half_height(0.5);
431     }
432 };
433 
434 
435 
436 /**
437 * A class to represent a Cone geometry.
438 */
439 
440 class OSIMSIMULATION_API Cone : public AnalyticGeometry
441 {
442     OpenSim_DECLARE_CONCRETE_OBJECT(Cone, AnalyticGeometry);
443 public:
444     OpenSim_DECLARE_PROPERTY(origin, SimTK::Vec3, "origin of cone base");
445     OpenSim_DECLARE_PROPERTY(direction, SimTK::Vec3, "direction of cone axis.");
446     OpenSim_DECLARE_PROPERTY(base_radius, double, "Base radius of cone.");
447     OpenSim_DECLARE_PROPERTY(height, double, "Height of cone.");
448     /// Default constructor
Cone()449     Cone() :
450         AnalyticGeometry()
451     {
452         constructProperties();
453     }
454     /// Convenience constructor that takes radius and half-height
Cone(const SimTK::Vec3 & o,const SimTK::UnitVec3 & dir,double height,double base)455     Cone(const SimTK::Vec3& o, const SimTK::UnitVec3& dir,
456         double height, double base) :
457         AnalyticGeometry()
458     {
459         constructProperties();
460         upd_origin() = o;
461         upd_direction() = SimTK::Vec3(dir);
462         upd_base_radius() = base;
463         upd_height() = height;
464     }
465     /// destructor
~Cone()466     ~Cone() {}
467 protected:
468     /** Method to map Cone to SimTK::Array of SimTK::DecorativeGeometry.
469     Appearance, Transforms are handled by base Geometry class. */
470     void implementCreateDecorativeGeometry(
471         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
472 private:
constructProperties()473     void constructProperties() {
474         constructProperty_origin(SimTK::Vec3(0));
475         constructProperty_direction(SimTK::UnitVec3(1));
476         constructProperty_base_radius(0.5);
477         constructProperty_height(1.0);
478     }
479 };
480 
481 /**
482 * A class to represent Torus geometry. The torus is centered at the
483 origin with the axial direction aligned to the z-axis. It is defined by
484 a ring_radius (radius of the circular centerline of the torus, measured
485 from the origin), and a cross_section (radius of the torus cross-section:
486 perpendicular distance from the circular centerline to the surface).
487 */
488 class OSIMSIMULATION_API Torus : public AnalyticGeometry
489 {
490     OpenSim_DECLARE_CONCRETE_OBJECT(Torus, AnalyticGeometry);
491 public:
492     OpenSim_DECLARE_PROPERTY(cross_section, double, "Cross section radius");
493     OpenSim_DECLARE_PROPERTY(ring_radius, double, "Radius of the torus ring.");
494 public:
495     /// Default constructor
Torus()496     Torus():
497     AnalyticGeometry()
498     {}
499     /// Constructor that takes in two radii
Torus(const double ringRadius,const double crossSectionRadius)500     Torus(const double ringRadius, const double crossSectionRadius):
501     AnalyticGeometry()
502     {
503         upd_ring_radius()=ringRadius;
504         upd_cross_section()=crossSectionRadius;
505     }
~Torus()506     virtual ~Torus() {}
507 
508 protected:
509     /** Method to map Cone to Array of SimTK::DecorativeGeometry.
510     Appearance, Transforms are handled by base Geometry class. */
implementCreateDecorativeGeometry(SimTK::Array_<SimTK::DecorativeGeometry> & decoGeoms)511     void implementCreateDecorativeGeometry(
512         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override {};
513 };
514 
515 /**
516 * A class to represent Brick geometry. Brick is specified by three half_lengths
517 */
518 class OSIMSIMULATION_API Brick : public Geometry
519 {
520     OpenSim_DECLARE_CONCRETE_OBJECT(Brick, Geometry);
521 public:
522     OpenSim_DECLARE_PROPERTY(half_lengths, SimTK::Vec3,
523         "Half lengths in X, Y, Z respectively.");
524 
525 public:
526     /// Default constructor, makes a Brick with half-length 0.1,0.2,0.3
Brick()527     Brick() :
528     Geometry()
529     {
530         constructProperty_half_lengths(SimTK::Vec3(0.1, 0.2, 0.3));
531     }
532     /// Convenience constructor with specified half-lengths
Brick(const SimTK::Vec3 & halfLengths)533     Brick(const SimTK::Vec3& halfLengths) :
534         Geometry()
535     {
536         constructProperty_half_lengths(SimTK::Vec3(0.1, 0.2, 0.3));
537         upd_half_lengths() = halfLengths;
538     }
539     /// Destructor
~Brick()540     ~Brick() {}
541 protected:
542     /// Method to map Brick to Array of SimTK::DecorativeGeometry.
543     void implementCreateDecorativeGeometry(
544         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
545 
546 };
547 /**
548 * A class to represent Mesh geometry that comes from a file.
549 * Supported file formats .vtp, .stl, .obj but will grow over time
550 */
551 class OSIMSIMULATION_API Mesh : public Geometry
552 {
553     OpenSim_DECLARE_CONCRETE_OBJECT(Mesh, Geometry);
554 public:
555     OpenSim_DECLARE_PROPERTY(mesh_file, std::string,
556         "Name of geometry file.");
557 
558 public:
559     /// Default constructor
Mesh()560     Mesh() :
561         Geometry(),
562         cachedMesh(nullptr),
563         warningGiven(false)
564     {
565         constructProperty_mesh_file("");
566     }
567     /// Constructor that takes a mesh file name
Mesh(const std::string & geomFile)568     Mesh(const std::string& geomFile) :
569         Geometry(),
570         cachedMesh(nullptr),
571         warningGiven(false)
572     {
573         constructProperty_mesh_file("");
574         upd_mesh_file() = geomFile;
575     }
576     /// destructor
~Mesh()577     virtual ~Mesh() {};
578     /// Retrieve file name
getGeometryFilename()579     const std::string&  getGeometryFilename() const
580     {
581         return get_mesh_file();
582     };
583 protected:
584     // ModelComponent interface.
585     void extendFinalizeFromProperties() override;
586 
587 protected:
588     /// Method to map Mesh to Array of SimTK::DecorativeGeometry.
589     void implementCreateDecorativeGeometry(
590         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
591 private:
592     // We cache the DecorativeMeshFile if we successfully
593     // load the mesh from file so we don't try loading from disk every frame.
594     // This is mutable since it is not part of the public interface.
595     mutable SimTK::ResetOnCopy<std::unique_ptr<SimTK::DecorativeMeshFile>> cachedMesh;
596     mutable bool warningGiven;
597 };
598 
599 /**
600 * A class to represent Frame geometry. Knobs that can be changed
601 * are in Appearance::Representation, size, thickness.
602 */
603 class OSIMSIMULATION_API FrameGeometry : public Geometry
604 {
605     OpenSim_DECLARE_CONCRETE_OBJECT(FrameGeometry, Geometry);
606 public:
607     OpenSim_DECLARE_PROPERTY(display_radius, double,
608         "The radius of the arrow-shaft used to display the frame.");
609     /// Default constructor
Geometry()610     FrameGeometry(double scale=0.2) : Geometry()
611     {
612        constructProperties();
613        set_scale_factors(SimTK::Vec3(scale));
614     }
615     /// destructor
~FrameGeometry()616     virtual ~FrameGeometry() {};
617 
618     void generateDecorations
619         (bool                                       fixed,
620             const ModelDisplayHints&                    hints,
621             const SimTK::State&                         state,
622             SimTK::Array_<SimTK::DecorativeGeometry>&   appendToThis) const override;
623 protected:
624     /// Method to map FrameGeometry to Array of SimTK::DecorativeGeometry.
625     void implementCreateDecorativeGeometry(
626         SimTK::Array_<SimTK::DecorativeGeometry>& decoGeoms) const override;
627 private:
constructProperties()628     void constructProperties() {
629         constructProperty_display_radius(.004);
630     }
631 };
632 }; //namespace
633 //=============================================================================
634 //=============================================================================
635 
636 #endif //OPENSIM_GEOMETRY_H__
637