PrimitiveShape
This class is a child of Shape.
Contents
classdef PrimitiveShape < Shape
%This Class defines the Primitive Shape object. Primitive Shape is a %subclass of superclass Shape. These are native shapes available in %BodyBuilder and consist of a material and geometrical properties. A %complex shape usually consists of multiple primitive shapes. %This is an abstract class in the sense that each primitive shape for %instance brick, cone etc have separate class definitions. These can be %instantiated. However you cannot instantiate an object of type %Primitive Shape. % % URL : $URL: $ % Log : $Id: PrimitiveShape.html,v 1.1 2008/07/23 12:51:19 jberg Exp $ % Copyright (c) 2008 The MathWorks, Inc.
Class Properties
properties ( SetAccess = 'public', GetAccess = 'public' ) % material = ShapeMaterial; % (ShapeMaterial) material; % (ShapeMaterial) end properties ( Dependent = true ) center_of_mass; % (CoordSystem) mass; % (pos semidef double) end properties ( SetAccess = 'protected', GetAccess = 'public' ) primitive; % (com.sun.j3d.utils.geometry...) generator; % (org.j3d.geom...) end methods
Constructor
function obj = PrimitiveShape() Log.msg(sprintf('\n%s::%s',mfilename,mfilename)); obj.material = ShapeMaterial; end
Destructor
function delete(obj) % disp(sprintf('%s:delete() %s',mfilename,obj.name)); end
SET Methods
function set.generator(obj, in) % This property contains unserializable object(s), which creates a % problem for saving and loading. As a workaround, this set will % first check for the keyword 'deflate', which indicates that the % user wishes to substitute the object currently stored in the % property with a description of how to recreate the object(s). The % description will be in the form of a structure with fields cmd and % args. If the property is currently empty, it remains empty (no % harm, no foul). prop_name = 'generator'; obj.(prop_name) = in; end function set.material(obj, in) prop_name = 'material'; prop_type = 'ShapeMaterial'; % This is responsible for changing a Shape's material property and % the Shape's appearance in the Viewing Pane. [valid_flag in] = Validate.SCALAR(in,'type',prop_type); if valid_flag obj.(prop_name) = in; if ~isempty(in) obj.update_shape_appearance; end end end function set.primitive(obj, in) prop_name = 'primitive'; obj.(prop_name) = in; Log.msg(sprintf('%s::set.primitive (%s)',... mfilename, in.toString.toCharArray)); end
GET Methods
function mass = get.mass(obj) if strcmp(class(obj),'PrimitiveShape') % Should only be the case during debug since we do not normally % instantiate a Primitive object mass = obj.material.density; else mass = obj.material.density * obj.volume; end end function center_of_mass = get.center_of_mass(obj) % Get the shape's CG center_of_mass = obj.coord_system{2}; % Convert the CG wrt to the parent's origin % [the_pos the_dir] = CG.convert_coordinates_wrt_new_refCS(ref_CS); % center_of_mass = the_pos; end
Public HELPER Methods
function change_geometry(the_shape,dimension_idx,the_value) % This is responsible for changing a Shape's geometry properties and % the Shape's dimensions in the Viewing Pane. the_dimension = the_shape.dimension_order{dimension_idx}; eval(['the_shape.' the_dimension ' = ' the_value(:)' ';']); the_shape.update_shape_geometry(); end function dimension_info = make_dimension_info(obj) % Get all dimensions for the primitive shape the_shape_dimensions = obj.dimension_order; n_dimensions = length(the_shape_dimensions); dimension_info = cell(n_dimensions,2); dimension_info(:,1) = the_shape_dimensions; for ii = 1:n_dimensions dimension_info{ii,2} = eval(['obj.' the_shape_dimensions{ii} '()']); end end function attach_primitive_common(obj,a_primitive) % Set all Shape3D objects for the primitive to enable modifications % to the appearance (in case the material type is changed). % Attach this shape's primitive to this shape's TransformGroup. if isempty(obj.TransformGroup) % This happens when we are reloading a model because the % primitive property is loaded before the TransformGroup % property due to the fact that TransformGroup is part of the % superclass Shape whereas primitive is part of PrimitiveShape. % As we see below, attaching the primitive requires the % TransformGroup. return end if true % Using org.j3d.renderer.java3d.geom.* for primitives a_primitive.setCapability(javax.media.j3d.Shape3D.ALLOW_APPEARANCE_READ); a_primitive.setCapability(javax.media.j3d.Shape3D.ALLOW_APPEARANCE_WRITE); a_primitive.setCapability(javax.media.j3d.Shape3D.ALLOW_GEOMETRY_WRITE); else % Using com.sun.j3d.utils.geometry.* for primitives ii = 0; while true a_shape3D = a_primitive.getShape(ii); if isempty(a_shape3D) break; else a_shape3D.setCapability(a_shape3D.ALLOW_APPEARANCE_READ); a_shape3D.setCapability(a_shape3D.ALLOW_APPEARANCE_WRITE); a_shape3D.setCapability(a_shape3D.ALLOW_GEOMETRY_WRITE); ii = ii+1; end end end % Attach this shape's primitive to this shape's TransformGroup. obj.TransformGroup.addChild(a_primitive); end function [vertexInfo normalInfo] = get_vertex_info(obj) % Vertex info is returned to enable exporting to .stl document. geom = obj.primitive.getGeometry; n_vertex = geom.getVertexCount; vertexInfo = zeros(n_vertex,3); normalInfo = zeros(n_vertex,3); P3f = javax.vecmath.Point3f; V3f = javax.vecmath.Vector3f; for ii = 1:n_vertex geom.getCoordinate(ii-1,P3f); vertexInfo(ii,:) = [P3f.x P3f.y P3f.z]; geom.getNormal(ii-1,V3f); normalInfo(ii,:) = [V3f.x V3f.y V3f.z]; end end
end methods ( Access = 'private' )
Private HELPER Methods
function update_shape_appearance(obj) % This is called whenever a Shape's material type has changed a_primitive = obj.primitive; if ~isempty(a_primitive) if true % Using org.j3d.renderer.java3d.geom.* for primitives a_primitive.setAppearance(obj.material.appearance); else % Using com.sun.j3d.utils.geometry.* for primitives ii = 0; while true a_shape3D = a_primitive.getShape(ii); if isempty(a_shape3D) break; else a_shape3D.setAppearance(obj.material.appearance); % a_shape3D.getAppearance.setMaterial(obj.material) ii = ii+1; end end end end end function update_shape_geometry(obj) % This is called whenever a Shape's dimensions change import org.j3d.geom.*; import javax.media.j3d.*; a_primitive = obj.primitive; % Get the latest dimensions and create evaluation string the_dimension_info = obj.make_dimension_info(); if ~isempty(a_primitive) try if true % Using org.j3d.renderer.java3d.geom.* for primitives % For some reason, setDimensions does not work for % Spheres. For them, we use SphereGenerator. if isa(a_primitive,'org.j3d.renderer.java3d.geom.Sphere') obj.update_shape_geometry_using_shape_generator; else obj.primitive.setDimensions(the_dimension_info{:,2}); end else % Using com.sun.j3d.utils.geometry.* for primitives end catch ME msg = sprintf(... '--> In %s:update_shape_geometry: Trouble Setting Geometry',... mfilename); % Get last segment of the error message identifier. idSegLast = regexp(ME.identifier, '(?<=:)\w+$', 'match'); error([msg idSegLast{:}]); end end end function update_shape_geometry_using_shape_generator(obj) % This is called whenever a Shape's dimensions change disp(sprintf('%s:%s (%s)',mfilename,... 'update_shape_geometry_using_shape_generator',class(obj))); import org.j3d.geom.*; import javax.media.j3d.*; data = GeometryData(); data.geometryType = GeometryData.INDEXED_TRIANGLE_STRIPS; data.geometryComponents = ... GeometryData.TEXTURE_2D_DATA + GeometryData.NORMAL_DATA; the_generator = obj.generator(); % Get the latest dimensions the_dimension_info = obj.make_dimension_info(); switch lower(class(obj)) case 'sphere' the_generator.setDimensions(the_dimension_info{:,2},false); % False for full sphere (vs hemi-sphere) case 'cylinder' the_generator.setDimensions(the_dimension_info{:,2},true,true); % True to generate faces for the ends case 'cone' the_generator.setDimensions(the_dimension_info{:,2},true); % True if to generate faces for the bottom case 'torus' the_generator.setDimensions(the_dimension_info{:,2}); % True if to generate faces for the bottom otherwise the_generator.setDimensions(the_dimension_info{:,2}); end the_generator.generate(data); format = GeometryArray.COORDINATES + GeometryArray.NORMALS; i_geom = IndexedTriangleStripArray(... data.vertexCount,... format,... data.indexesCount,... data.stripCounts); i_geom.setCoordinateIndices(0, data.indexes); i_geom.setNormalIndices(0, data.indexes); geom = i_geom; geom.setCoordinates(0, data.coordinates); geom.setNormals(0, data.normals); a_primitive = obj.primitive; if ~isempty(a_primitive) try if true % Using org.j3d.renderer.java3d.geom.* for primitives a_primitive.setGeometry(geom); else % Using com.sun.j3d.utils.geometry.* for primitives ii = 0; while true a_shape3D = a_primitive.getShape(ii); if isempty(a_shape3D) break; else a_shape3D.setGeometry(geom); ii = ii+1; end end % a_shape3D.setAppearance(obj.material.appearance); % a_shape3D.getAppearance.setMaterial(obj.material) end catch ME msg = sprintf(... '--> In %s:update_shape_geometry: Trouble Setting Geometry',... mfilename); % Get last segment of the error message identifier. idSegLast = regexp(ME.identifier, '(?<=:)\w+$', 'match'); error([msg idSegLast{:}]); end end end
end
end