Shape
This class is Abstract.
Contents
classdef Shape < handle
%This Class defines the Shape object. The Shape object has two subclasses: % 1. Primitive Shape (eg: brick, cone etc) % 2. Complex Shape (eg: car, wheel etc made of multiple primitive shapes) %This is an abstract class in the sense that you cannot instantiate an object %of type Shape. % % All Primitive Shapes have: % BranchGroup --> TransformGroup --> shape3D % All Complex Shapes have: % BranchGroup --> TransformGroup % Assumptions: % The first element of coord_system is the location of the shape's cg % wrt the shape's parent cg. % URL : $URL: $ % Log : $Id: Shape.html,v 1.1 2008/07/23 12:51:20 jberg Exp $ % Copyright (c) 2008 The MathWorks, Inc.
Class Properties
properties ( SetAccess = 'public', GetAccess = 'public' ) % name = 'New Shape'; % (char) name; % (char) coord_system; % ({CoordSystem}) end properties ( GetAccess = 'public', Dependent = true ) % The first CoordSystem stores the Shape's relative origin and % orientation with respect to the Shape's parent's CG. For the upper % most Shape, (i.e., body), the parent is the global origin. BranchGroup; % (javax.media.j3d.BranchGroup) TransformGroup; % (javax.media.j3d.TransformGroup) n_coord_system; % (int) end properties ( GetAccess = 'protected', Dependent = true ) orientation; % (3-element double array) origin; % (3-element double array) end methods
Constructor
function obj = Shape() end
Destructor
function delete(obj) % disp(sprintf('%s:delete() %s',mfilename,obj.name)); end
SET Methods
function set.coord_system(obj, in) prop_name = 'coord_system'; prop_type = 'CoordSystem'; [valid_flag in] = Validate.ARRAY(in,'type',prop_type,'Cell',true); if valid_flag obj.(prop_name) = in; end end function set.name(obj, in) prop_name = 'name'; prop_type = 'char'; [valid_flag in] = Validate.ARRAY(in,'type',prop_type); if valid_flag obj.(prop_name) = in; end end
GET Methods
function coord_system = get.coord_system(varargin) % returns all the coord_systems if index is not provided % If index or name is provided as the argument, it searches all % the CSs of this shape and returns that particular CS. obj = varargin{1}; coord_system = obj.coord_system; if (nargin==2) if(isnumeric(varargin{2})) % Find CS using index index = varargin{2}; if(index > length(coord_system)) error('index (%d) entered exceeds coord_system length (%d)', index, length(coord_system)); else coord_system = coord_system{index}; end else % Find CS using name cs_name = varargin{2}; ii = 1; while(ii <= length(coord_system)) if(strcmp(cs_name,coord_system{ii}.name)) coord_system = coord_system{ii}; break; end ii = ii+1; end if(ii > obj.n_coord_system) error('CS Name: (%s) entered could not be found',cs_name); end end end end function n = get.n_coord_system(obj) n = length(obj.coord_system); end function pos = get.origin(obj) pos = obj.coord_system{1}.origin; end function dir = get.orientation(obj) dir = obj.coord_system{1}.orientation; end function BranchGroup = get.BranchGroup(obj) % The Shape's BranchGroup is identical to that of the main % CoordSystem. BranchGroup = obj.coord_system{1}.triad.BranchGroup; end function TransformGroup = get.TransformGroup(obj) % The Shape's TransformGroup is identical to that of the main % CoordSystem. TransformGroup = obj.coord_system{1}.triad.TransformGroup; end
Public HELPER Methods
function change_axes_length(obj, a_length) % This method sets the axes length for the triad of this % shape and of all of the children of this shape. the_coord_systems = obj.coord_system; for ii = 1:length(the_coord_systems) the_coord_systems{ii}.triad.length = a_length; end if isa(obj,'ComplexShape') the_children = obj.children; for ii = 1:length(the_children) the_children{ii}.change_axes_length(a_length); end end end function update_coord_system(obj,the_cs_name,dimension_id,a_value) % This is responsible for changing a Shape's Coordinate System % and the Shape's location in the Viewing Pane. idx = strfind('xyz',dimension_id(1)); coord_system = CoordSystem.get_by_name(obj.coord_system,the_cs_name); switch lower(dimension_id) case {'x_pos','y_pos','z_pos'} the_values = coord_system.origin; the_values(idx) = a_value; coord_system.origin = the_values; case {'x_rot','y_rot','z_rot'} the_values = coord_system.orientation; the_values(idx) = a_value; coord_system.orientation = the_values; otherwise error([mfilename ':update_coord_system only accepts x_pos, y_pos, z_pos, x_rot, etc. for dimension ID']); end % Is this the CG that is changing? if (~isempty(strfind(the_cs_name,'Origin'))) % Need to reflect the change in Shape location in the Viewing % Pane. obj.update_shape_location; end end function add_coord_system(obj,a_coord_system) if (nargin==1) % Add the Shape's first CoordSystem to property coord_system. % The first CS is named 'Origin' and it provides the % shape'representation of origin and orientation relative to its % parent. The first CS of a new Shape is initially placed to % coincide with the first CS of its parent. In the case of a % PrimitiveShape, the first CS is also its CG. % the_length = 0.25; Main_CS = CoordSystem('name','Origin',... 'is_deletable',false,... 'parent_shape',obj); % To fully define a CoordSystem, you need the reference % CoordSystem. This is done when the Shape is attached to % another Shape. obj.coord_system = {Main_CS}; obj.update_shape_location; else obj.coord_system{end+1} = a_coord_system; end end function remove_coord_system_by_index(obj,idx) if obj.n_coord_system >= idx obj.coord_system(idx) = []; end end function remove_coord_system(obj,a_CS) coord_systems = obj.coord_system; for ii = 1:length(coord_systems) if(strcmp(coord_systems{ii}.name,a_CS.name)) obj.remove_coord_system_by_index(ii); break; end end end function toggle_axes_display(obj) % This method toggles the visibility for the triad of this % shape and of all of the children of this shape. the_coord_systems = obj.coord_system; for ii = 1:length(the_coord_systems) is_visible = the_coord_systems{ii}.triad.is_visible; the_coord_systems{ii}.triad.is_visible = ~is_visible; end if isa(obj,'ComplexShape') the_children = obj.children; for ii = 1:length(the_children) the_children{ii}.toggle_axes_display; end end end function cs_to_orig_refCS = prepare_CS_to_save(obj) % To avoid saving anything above the intended objects, one thing that needs % to be done is to remove references to all coordinate systems above the % selected body. We do this by changing such references to the % World.Origin. We address how to avoid saving World.Origin later. % For each coord_system, check to see if the parent_shape of the % reference_CS is identical to the current shape. If it is, fine. If the % parent_shape of the reference_CS is empty (i.e., reference_CS = % World.Origin), fine. Otherwise, convert reference_CS to World.Origin. We % need to keep track of all conversions so that we can convert them back % after saving. cs_to_orig_refCS =cell(0); for ii = 1:obj.n_coord_system if ~isempty(obj.coord_system{ii}.reference_CS) && ... ~isequal(obj.coord_system{ii}.reference_CS.parent_shape,obj) cs_to_orig_refCS{end+1,1} = obj.coord_system{ii}; cs_to_orig_refCS{end,2} = obj.coord_system{ii}.reference_CS; obj.coord_system{ii}.convert_local_coordinates_to_world; end end end function return_CS_to_orig_state(obj,cs_to_orig_refCS) for ii=1:size(cs_to_orig_refCS,1) cs_to_orig_refCS{ii,1}.reference_CS = cs_to_orig_refCS{ii,2}; end end
end methods ( Access = 'protected' )
Protected HELPER Methods
function update_shape_location(the_shape) % This is called whenever a Shape's CG coordinate system changes import javax.vecmath.*; import javax.media.j3d.*; % Get the location of the Shape wrt it's parent's CG. the_origin = the_shape.origin; the_orientation = the_shape.orientation*pi/180; the_TG = the_shape.TransformGroup; tmpTrans = javax.media.j3d.Transform3D(); tmpTrans2 = javax.media.j3d.Transform3D(); tmpTrans.rotX(the_orientation(1)); tmpTrans2.rotY(the_orientation(2)); tmpTrans.mul(tmpTrans2); tmpTrans2.rotZ(the_orientation(3)); tmpTrans.mul(tmpTrans2); the_translation = javax.vecmath.Vector3d(); % Vector3d the_translation.set(the_origin(1), the_origin(2), the_origin(3)); tmpTrans.setTranslation(the_translation); the_TG.setTransform(tmpTrans); end
end
end