Click or drag to resize
DigitalRuneGeometricObject Class
Defines an object that has a Shape and a Pose (position and orientation). (Default implementation of IGeometricObject.)
Inheritance Hierarchy
SystemObject
  DigitalRune.GeometryGeometricObject

Namespace: DigitalRune.Geometry
Assembly: DigitalRune.Geometry (in DigitalRune.Geometry.dll) Version: 1.18.0.0 (1.18.2.14427)
Syntax
[SerializableAttribute]
public class GeometricObject : IGeometricObject

The GeometricObject type exposes the following members.

Constructors
  NameDescription
Public methodGeometricObject
Initializes a new instance of the GeometricObject class.
Public methodGeometricObject(Shape)
Initializes a new instance of the GeometricObject class with a shape.
Public methodGeometricObject(Shape, Pose)
Initializes a new instance of the GeometricObject class with shape and pose (position and orientation).
Public methodGeometricObject(Shape, Vector3F)
Initializes a new instance of the GeometricObject class with shape and scale.
Public methodGeometricObject(Shape, Vector3F, Pose)
Initializes a new instance of the GeometricObject class with shape, scale and pose (position and orientation).
Top
Methods
  NameDescription
Public methodClone
Creates a new GeometricObject that is a clone (deep copy) of the current instance.
Protected methodCloneCore
Makes the instance a clone (deep copy) of the specified GeometricObject.
Protected methodCreateInstanceCore
When implemented in a derived class, creates a new instance of the GeometricObject derived class.
Public methodEquals
Determines whether the specified Object is equal to the current Object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetHashCode
Serves as a hash function for a particular type.
(Inherited from Object.)
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Protected methodOnPoseChanged
Raises the PoseChanged event.
Protected methodOnShapeChanged
Raises the ShapeChanged event.
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Top
Properties
  NameDescription
Public propertyAabb
Gets the axis-aligned bounding box (AABB).
Public propertyPose
Gets or sets the pose (position and orientation).
Public propertyScale
Gets or sets the scale.
Public propertyShape
Gets or sets the shape.
Top
Events
  NameDescription
Public eventPoseChanged
Occurs when the Pose was changed.
Public eventShapeChanged
Occurs when the Shape or Scale was changed.
Top
Explicit Interface Implementations
  NameDescription
Explicit interface implementationPrivate methodIGeometricObjectClone
Creates a new IGeometricObject that is a clone (deep copy) of the current instance.
Top
Remarks

Classes that need to implement IGeometricObject can derive from GeometricObject.

Important: An IGeometricObject instance registers event handlers for the Changed event of the contained Shape. Therefore, a Shape will have an indirect reference to the IGeometricObject. This is no problem if the geometric object exclusively owns the shape. However, this could lead to problems ("life extension bugs" a.k.a. "memory leaks") when multiple geometric objects share the same shape: One geometric object is no longer used but it cannot be collected by the garbage collector because the shape still holds a reference to the object.

Therefore, when Shapes are shared between multiple IGeometricObjects: Always set the property Shape to Empty when the IGeometricObject is no longer used. Empty is a special immutable shape that never raises any Changed events. Setting Shape to Empty ensures that the internal event handlers are unregistered and the object can be garbage-collected properly.

Cloning: Geometric objects are cloneable. The method Clone creates a deep copy of the geometric object - except when documented otherwise (see description of implementing classes).

Notes to Inheritors: The support for cloning of geometric objects is built-in in DigitalRune Geometry because several applications built upon the library rely on the cloning mechanism. The DigitalRune Geometry library internally does not use the cloning mechanism. So, if you need to write your own type that implements IGeometricObject and your own application does not require to clone geometric objects, you can simply omit the implementation of Clone - just throw a NotImplementedException.

Examples
The following is basically the implementation of GeometricObject. The source code is shown here to illustrate how the interface IGeometricObject should be implemented.
C#
using System;
using DigitalRune.Geometry.Shapes;
using DigitalRune.Mathematics.Algebra;


namespace DigitalRune.Geometry
{
  [Serializable]
  public class GeometricObject : IGeometricObject
  {
    //--------------------------------------------------------------
    #region Properties & Events
    //--------------------------------------------------------------

    public Aabb Aabb
    {
      get
      {
        if (_aabbIsValid == false)
        {
          _aabb = Shape.GetAabb(Scale, Pose);
          _aabbIsValid = true;
        }

        return _aabb;
      }
    }
    private Aabb _aabb;
    private bool _aabbIsValid;


    public Pose Pose
    {
      get 
      { 
        return _pose; 
      }
      set
      {
        if (_pose != value)
        {
          _pose = value;
          OnPoseChanged(EventArgs.Empty);
        }
      }
    }
    private Pose _pose;


    public Shape Shape
    {
      get 
      {   
        return _shape; 
      }
      set
      {
        if (value == null)
          throw new ArgumentNullException("value");

        if (_shape != null)
          _shape.Changed -= OnShapeChanged;

        _shape = value;
        _shape.Changed += OnShapeChanged;
        OnShapeChanged(ShapeChangedEventArgs.Empty);
      }
    }
    private Shape _shape;


    public Vector3F Scale
    {
      get 
      {
        return _scale; 
      }
      set
      {
        if (_scale != value)
        {
          _scale = value;
          OnShapeChanged(ShapeChangedEventArgs.Empty);
        }
      }
    }
    private Vector3F _scale;


    public event EventHandler<EventArgs> PoseChanged;


    public event EventHandler<ShapeChangedEventArgs> ShapeChanged;
    #endregion


    //--------------------------------------------------------------
    #region Creation & Cleanup
    //--------------------------------------------------------------

    public GeometricObject()
    {
      _shape = Shape.Empty;
      _scale = Vector3F.One;
      _pose = Pose.Identity;
    }
    #endregion


    //--------------------------------------------------------------
    #region Methods
    //--------------------------------------------------------------

    IGeometricObject IGeometricObject.Clone()
    {
      return Clone();
    } 


    public GeometricObject Clone()
    {
      GeometricObject clone = CreateInstance();
      clone.CloneCore(this);
      return clone;
    }


    private GeometricObject CreateInstance()
    {
      GeometricObject newInstance = CreateInstanceCore();
      if (GetType() != newInstance.GetType())
      {
        string message = String.Format(
          "Cannot clone shape. The derived class {0} does not implement CreateInstanceCore().",
          GetType());
        throw new InvalidOperationException(message);
      }

      return newInstance;
    }


    protected virtual GeometricObject CreateInstanceCore()
    {
      return new GeometricObject();
    }


    protected virtual void CloneCore(GeometricObject sourceShape)
    {
      Pose = sourceShape.Pose;
      Shape = sourceShape.Shape.Clone();
      Scale = sourceShape.Scale;
    }


    private void OnShapeChanged(object sender, ShapeChangedEventArgs eventArgs)
    {
      OnShapeChanged(eventArgs);
    }


    protected virtual void OnPoseChanged(EventArgs eventArgs)
    {
      _aabbIsValid = false;

      var handler = PoseChanged;

      if (handler != null)
        handler(this, eventArgs);
    }


    protected virtual void OnShapeChanged(ShapeChangedEventArgs eventArgs)
    {
      _aabbIsValid = false;

      var handler = ShapeChanged;

      if (handler != null)
        handler(this, eventArgs);
    }
    #endregion
  }
}
See Also