ComplexShape
This class is a child of Shape.
Contents
classdef ComplexShape < Shape
%This Class defines the Complex Shape object. Complex Shape is a %subclass of superclass Shape. These are custom shapes built by the user %in BodyBuilder and may consist of multiple primitive shapes. % % URL : $URL: $ % Log : $Id: ComplexShape.html,v 1.1 2008/07/23 12:51:18 jberg Exp $ % Copyright (c) 2008 The MathWorks, Inc.
Class Properties
properties ( Dependent = true )
n_children; % (int)
end
properties ( SetAccess = 'private', GetAccess = 'public' )
children; % ({<Complex/Primitive Shapes>})
end
properties ( SetAccess = 'private', GetAccess = 'private', Constant = true )
PROPERTY_LIST = {
'name' % From parent class Shape
};
end
methods
Constructor
function obj = ComplexShape(varargin) prop_list = eval([mfilename '.PROPERTY_LIST']); n_props = length(prop_list); Log.msg(sprintf('\n%s::%s',mfilename,mfilename)); obj.add_coord_system; % Add Origin CS if(mod(nargin,2)~=0) error('Expecting inputs as property name-value pairs.') end error(nargchk(0, 2*n_props, nargin,'string')); % Child-specific default obj.name = 'New Assembly'; % Property Name-Value pair matching for ii=1:2:nargin prop = varargin{ii}; val = varargin{ii+1}; idx = strmatch(lower(prop),lower(prop_list),'exact'); if isempty(idx) error('%s: This property is unknown',... 'or cannot be set during the construction',... 'of the object: %s ',prop,mfilename); else obj.(prop_list{idx}) = val; end end end
Destructor
function delete(obj) % disp(sprintf('%s:delete() %s',mfilename,obj.name)); end
SET Methods
function set.children(obj, in) prop_name = 'children'; prop_type = 'Shape'; [valid_flag in] = Validate.ARRAY(in,'type',prop_type,'Cell',true); if valid_flag obj.(prop_name) = in; end end
Public HELPER Methods
function mass = mass(obj) % mass = Summation(mass_of_each_child) mass = 0; the_children = obj.children; for ii = 1:obj.n_children mass = mass + the_children{ii}.mass; end end function vol = volume(obj) % volume = Summation(volume_of_each_child) vol = 0; the_children = obj.children; for ii = 1:obj.n_children vol = vol + the_children{ii}.volume; end end function center_of_mass = center_of_mass(obj) % The coordinate values are calculated wrt to the % ref_CS which is passed argument. the_children = obj.children; origin = obj.coord_system{1}; % Initialize the CG of this complex shape to be a duplicate of % the complex shape's origin. If there are no children, pass % this directly else calculate the new origin values. position = zeros(1,3); if(obj.n_children ~= 0) for ii = 1:obj.n_children child_CM = the_children{ii}.center_of_mass; child_mass = the_children{ii}.mass; % Convert the child's CG wrt parent's origin pos = child_CM.convert_coordinates_wrt_new_refCS(origin); position = position + pos*child_mass; end % CM wrt to the selected complex shape's origin if (obj.mass == 0) position = position/eps; else position = position/obj.mass; end end CS_name = [obj.name '.CM']; center_of_mass = CoordSystem('name',CS_name,... 'origin',position,... 'orientation',[0 0 0],... 'parent_shape',obj); center_of_mass.reference_CS = origin; end function inertia_tensor = moment_of_inertia_about_CG(obj) % Memory Note: I believe child_CG and CG CoordSystem objects % get deleted at the end of the function call. However it is % important to verify this as otherwise there will be lots of % these CoordSystems dangling somewhere in the ether. the_children = obj.children; % Initialize the inertia_tensor. If there are no children, just % return this tensor. inertia_tensor = zeros(3); if(obj.n_children == 0) return; end % For each child, % Step 1: Calculate the child's CG coords wrt my CG (selected % parent complex shape's CG (center of mass)) % Step 2: Calculate the MI of the child shape wrto an axis sharing % the origin as its CG but orientation coinciding with the % parent axis (basically invert the angles and rotation % sequence would be Z-Y-X). Let us call this CS_int % Step 3: Use Parallel Axis Theorem and calculate MI wrt to the % CG of the parent complex shape % Step 4: Add this tensor to the MI of the complex shape CG = obj.center_of_mass; for ii = 1:obj.n_children % Step 1: child_CG = the_children{ii}.center_of_mass; [the_pos the_dir] = child_CG.convert_coordinates_wrt_new_refCS(CG); % Step 2: % Calculate the unit vectors along each of the X, Y and Z % directions of the CS_int wrt to the child CG coordsystem. % For this, first calculate the Transformation matrices % which would be Euler Z-Y-X to get back to CS_int from % child_CG and then apply them on each of the unit vectors % [1; 0; 0], [0; 1; 0] and [0; 0; 1]. theta_x = the_dir(1)*pi/180; theta_y = the_dir(2)*pi/180; theta_z = the_dir(3)*pi/180; Rx = [1 0 0;... 0 cos(theta_x) sin(theta_x);... 0 -sin(theta_x) cos(theta_x)]; Ry = [cos(theta_y) 0 -sin(theta_y);... 0 1 0;... sin(theta_y) 0 cos(theta_y)]; Rz = [cos(theta_z) sin(theta_z) 0;... -sin(theta_z) cos(theta_z) 0;... 0 0 1]; % Dir_Cosine_Matrix contains unit_vectors as columns. dir_cosine_mat = Rx*Ry*Rz; child_MI = the_children{ii}.moment_of_inertia_about_CG; MI_temp = dir_cosine_mat'*child_MI*dir_cosine_mat; % Step 3: Using parallel axis theorem. child_mass = the_children{ii}.mass; X = the_pos(1); Y = the_pos(2); Z = the_pos(3); MI(1,1) = MI_temp(1,1) + child_mass*(Y^2+Z^2); MI(1,2) = MI_temp(1,2) + child_mass*(X*Y); MI(1,3) = MI_temp(1,3) + child_mass*(X*Z); MI(2,1) = MI_temp(2,1) + child_mass*(X*Y); MI(2,2) = MI_temp(2,2) + child_mass*(X^2+Z^2); MI(2,3) = MI_temp(2,3) + child_mass*(Y*Z); MI(3,1) = MI_temp(3,1) + child_mass*(X*Z); MI(3,2) = MI_temp(3,2) + child_mass*(Y*Z); MI(3,3) = MI_temp(3,3) + child_mass*(X^2+Y^2); % Step 4: inertia_tensor = inertia_tensor + MI; end end function n = get.n_children(obj) n = length(obj.children); end function idx = retrieve_child_idx_from_name(obj, a_name) % Iterate through child vector to find one whos name matches % a_name % Construct cell array of child names by retrieving the names of % each child contained in this shape. the_children = obj.children; ch_names = cell(obj.n_children,1); for ii = 1:obj.n_children ch_names{ii} = the_children{ii}.name; end idx = strmatch(a_name,ch_names,'exact'); if isempty(idx) warning('%s:%s Could not find a match',... mfilename,'retrieve_child_from_name'); end end function child = retrieve_child_from_name(obj, a_name) idx = retrieve_child_idx_from_name(obj, a_name); if isempty(idx) child = []; else child = obj.children{idx}; end end function add_child(obj, a_child) % Add a child shape to vector children. if ~obj.n_children obj.children = cell(0); end a_name = a_child.name(); % Check to see if the shape's name is available, else rename. % Construct cell array of child names by retrieving the names of % each child contained in this ComplexShape. ch_names = cell(obj.n_children,1); for ii = 1:obj.n_children ch_names{ii} = obj.children{ii}.name; end % Make sure there isn't already a child of the same exact name % contained in this ComplexShape. idx_exact = strmatch(a_name,ch_names,'exact'); if (idx_exact) ii = 0; while true ii = ii + 1; good_name = sprintf('%s_%d',a_name,ii); if isempty(strmatch(good_name,ch_names,'exact')) break; end end else good_name = a_name; end a_child.name = good_name; obj.children{end+1} = a_child; end function remove_child(obj, a_child) % Remove the given child shape from body. idx = retrieve_child_idx_from_name(obj, a_child.name); if ~isempty(idx) the_children = obj.children; the_children(idx) = []; obj.children = the_children; end end function change_name(obj, idx, new_name) obj.retrieve_child_from_idx(idx).name = new_name; end function dimension_info = make_dimension_info(obj) dimension_info = cell(0,2); end function [vertexInfo normalInfo] = get_vertex_info(obj) % Vertex info is returned to enable exporting to .stl document. n = obj.n_children; vertexInfo = cell(n,1); normalInfo = cell(n,1); for ii = 1:n the_child = obj.children{ii}; [vertexInfo{ii} normalInfo{ii}] = the_child.get_vertex_info; end end
end methods ( Access = 'private' )
Private HELPER Methods
function child = retrieve_child_from_idx(obj, idx) child = obj.children{idx}; end
end
end