# Source code for sympy.physics.mechanics.body

from sympy import Symbol
from sympy.physics.mechanics import (RigidBody, Particle, ReferenceFrame,
inertia)
from sympy.physics.vector import Point, Vector

__all__ = ['Body']

[docs]class Body(RigidBody, Particle):
"""
Body is a common representation of RigidBody or a Particle.

A Body represents either a rigid body or particle in classical mechanics.
Bodies have a body-fixed reference frame, a mass, a mass center and
possibly a body-fixed inertia.

Parameters
----------
name: String
Defines the name of the body. It is used as the base for defining body
specific properties.
masscenter : Point, optional
A point that represents the center of mass of the body or particle. If no
point is given, a point is generated.
frame : ReferenceFrame (optional)
The ReferenceFrame that represents the reference frame of the body. If
no frame is given, a frame is generated.
mass : Sympifyable, optional
A Sympifyable object which represents the mass of the body. if no mass
is passed, one is generated.
Central inertia dyadic of the body. If none is passed while creating
RigidBody, a default inertia is generated.

Examples
--------
Default behaviour. It creates a RigidBody after defining mass,
mass center, frame and inertia.

>>> from sympy.physics.mechanics import Body
>>> body = Body('name_of_body')

Passing attributes of Rigidbody. All the arguments needed to create a
RigidBody can be passed while creating a Body too.

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import ReferenceFrame, Point, inertia
>>> from sympy.physics.mechanics import Body
>>> mass = Symbol('mass')
>>> masscenter = Point('masscenter')
>>> frame = ReferenceFrame('frame')
>>> ixx = Symbol('ixx')
>>> body_inertia = inertia(frame, ixx, 0, 0)
>>> body = Body('name_of_body',masscenter,mass,frame,body_inertia)

Creating a Particle. If masscenter and mass are passed, and inertia is
not then a Particle is created.

>>> from sympy import Symbol
>>> from sympy.physics.vector import Point
>>> from sympy.physics.mechanics import Body
>>> mass = Symbol('mass')
>>> masscenter = Point('masscenter')
>>> body = Body('name_of_body',masscenter,mass)

Similarly, A frame can also be passed while creating a Particle.

"""
def __init__(self, name, masscenter=None, mass=None, frame=None,
central_inertia=None):

self.name = name

if frame is None:
frame = ReferenceFrame(name + '_frame')

if masscenter is None:
masscenter = Point(name + '_masscenter')

if central_inertia is None and mass is None:
ixx = Symbol(name + '_ixx')
iyy = Symbol(name + '_iyy')
izz = Symbol(name + '_izz')
izx = Symbol(name + '_izx')
ixy = Symbol(name + '_ixy')
iyz = Symbol(name + '_iyz')
_inertia = (inertia(frame, ixx, iyy, izz, ixy, iyz, izx),
masscenter)
else:
_inertia = (central_inertia, masscenter)

if mass is None:
_mass = Symbol(name + '_mass')
else:
_mass = mass

masscenter.set_vel(frame, 0)

# If user passes masscenter and mass then a particle is created
# otherwise a rigidbody. As a result a body may or may not have inertia.
if central_inertia is None and mass is not None:
self.frame = frame
self.masscenter = masscenter
Particle.__init__(self, name, masscenter, _mass)
else:
RigidBody.__init__(self, name, masscenter, frame, _mass, _inertia)

[docs]    def apply_force(self, vec, point=None):
"""
Adds the force to the point (center of mass by default) on the body.

Parameters
----------
vec: Vector
Defines the force vector. Can be any vector w.r.t any frame or
combinations of frame.
point: Point, optional
Defines the point on which the force must be applied. Default is
Body's center of mass.

Example
-------
To apply a unit force in x direction of body's frame to body's
center of mass.

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> body = Body('body')
>>> g = Symbol('g')
>>> body.apply_force(body.mass * g * body.frame.x)

To apply force to any other point than center of mass, pass that point
as well.

>>> from sympy import Symbol
>>> from sympy.physics.mechanics import Body
>>> parent = Body('parent')
>>> child = Body('child')
>>> g = Symbol('g')
>>> frame = parent.frame
>>> l = Symbol('l')
>>> point = child.masscenter.locatenew('force_point', l * body.frame.y)
>>> gravity = child.mass * g
>>> body.apply_force(gravity * body.frame.x, point)

"""
if not isinstance(point, Point):
if point is None:
point = self.masscenter  # masscenter
else:
raise TypeError("A Point must be supplied to apply force to.")
if not isinstance(vec, Vector):
raise TypeError("A Vector must be supplied to apply force.")

[docs]    def apply_torque(self, vec):
"""