No BSD License  

Highlights from
ansim

from ansim by Tim Chang
Animate simple objects based on inputs from a Simulink model.

andot( Action, hTarget, u )
function xOut = andot( Action, hTarget, u )
%ANDOT	Dot creation, modification, and display function.
%       ANDOT is specifically for the ANSIM Simulation Animation block.
%
%ANDOT( ACTION, TARGET, DATA ) apply ACTION to the TARGET using DATA.
%       
%	ACTION may be one of four strings:
%	    '#Draw'  Draw dot object (TARGET Dot handle and DATA vector, u, required)
%	     '#New'  Create new dot object (TARGET Figure and Dot DATA optional)
%	  '#Modify'  Modify dot object parameters. (TARGET Dot required)
%	  '#Update'  Update object paramater record stored in object's UserData.
%                (TARGET Dot required)
%
%   TARGET will be a single Figure handle, or one or more Dot Object handles,
%   depending on the ACTION specified.
%
%   DATA will be the Simulink input data vector, u; or a data structure 
%   containing the information for drawing the object. Required fields:
%       DATA.Xdata       - X-coordinate
%       DATA.Ydata       - Y-coordinate
%       DATA.Size        - MarkerSize
%       DATA.Color       - Color
%
%   Valid call combinations:
%    andot( #Draw  ,  hObj,        u ) redraw object hObj using data vector u
%    andot( #New                     ) add new generic obj to gcbf
%    andot( #New   ,  hAx            ) add new generic obj to hAx
%    andot( #New   ,  hAx , [X,Y]    ) add new generic obj to hAx at [X,Y]
%    andot( #New   ,  hAx , sObjData ) add new obj to hAx using sObjData
%    andot( #Modify,  hObj           ) modify the obj (hFig = grandparent of hObj)
%    andot( #Modify,  hObj,     hFig ) modify the obj (hFig for free)
%    andot( #UpdateIC,  hObj,          ) update UserData of hObj based on Position
%    andot( #UpdateIC,  hObj, sObjData ) update UserData of hObj based on sObjData
%    andot( #Select,    hObj           ) select hObj (change to select color)
%    andot( #Deselect,  hObj           ) deselect hObj (change to regular color)
%
%	See also ANLINE, ANPATCH, ANRECT, ANTEXT, ANOBJ.

%   Complete Dot UserData structure:
%       sObjUserData.Animated    - flag to indicate that there is a DrawString
%       sObjUserData.DrawString  - text to redraw the object based on u
%       sObjUserData.Method      - 'andot'
%       sObjUserData.Xdata       - X-coordinate
%       sObjUserData.Ydata       - Y-coordinate
%       sObjUserData.Size        - MarkerSize
%       sObjUserData.Color       - Color
%       sObjUserData.SelectColor - Color used when selected/hilited

%	Writen By: Loren Dean 
%   Writen On: March, 1995.
%   4/02/97 KGK converted to switch/case from if(strcmp)
%   4/02/97 KGK converted to use the Figure's new UserData Structure
%   4/02/97 KGK check inputs up front
%   4/02/97 KGK hard code a str2mat call
%   4/07/97 KGK convert TextStrings and Values to cell arrays for prpdlg
%   4/07/97 KGK make one prpdlg callback for all fields
%   4/09/97 KGK Total revamp of #New, #Update, and #Modify using new Data Structure
%   4/10/97 KGK Redo #Draw
%   4/11/97 KGK Redo function call systax and help text
%   4/11/97 KGK Finialize v5 optimization and begin debugging!
%   4/14/97 KGK Add #Select and #Deselect to Action list
%   4/14/97 KGK Change #Update to #UpdateIC
%   4/15/97 KGK Tax time! Ooops, properties must be stored as string expressions!
%   4/15/97 KGK Whoopie! Add AnimationFlag and DrawString to UserData structure!
%   4/17/97 KGK Update #UpdateIC to handle calls from andrag (i.e. no data)
%   4/25/97 KGK Update #Modify, #UpdateIC, and #Draw for Ansim2
%   5/02/97 KGK Clean up
%   $Author$  $State$
%	Copyright (c) 1990-97 by The MathWorks, Inc.
% 	$Revision$  $Date$
%
%###############################################################################
%       %
% BEGIN %  main
%       %
%###############################################################################
%-------------------------------------------------------------------------------
% Check input data -- we must know the target object!
%-------------------------------------------------------------------------------
if nargin == 1,  hTarget = gcbo;     end;
if nargin < 3 ,        u =   [];      end;

%-------------------------------------------------------------------------------
% Retrieve UserData structure (keeper of all knowledge--and handles!)
% Note: hTarget may be either the animation Figure or the animation Object.
% They both have userdata structures, though, and usage will depend on ACTION.
%-------------------------------------------------------------------------------
sTargetUserData = get( hTarget, 'UserData' ); 

%-------------------------------------------------------------------------------
% Perform the task specified by Action
%-------------------------------------------------------------------------------
switch Action,

%%%%%%%%%%%%
%%% Draw %%%
%%%%%%%%%%%%
case '#Draw',
    %---------------------------------------------------------------------------
    % This is it! Simulation time! Assume all data is correct and Move Fast!
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %
    % Valid call combinations (ACTION-specific variable names):
    %    andot( #Draw, hObj, u ) redraw object hObj using data vector u    
    %---------------------------------------------------------------------------
    
    % Check to see if this object is animated
    if sTargetUserData.Animated,
        % u-specific properties exist. Evaluate the draw string.
        % Display error message if there is a problem, but keep on going!
        % NOTE: DrawString assumes parameter variable is named: u
        % NOTE: DrawString assumes object handle is named: hTarget
        eval( ['set(hTarget' sTargetUserData.DrawString ')'], 'disp(lasterr);'); 
    end % if sTargetUserData.Animated

%%%%%%%%%%%%%%%%%%%
%%% Mouse Click %%%
%%%%%%%%%%%%%%%%%%%
case '#MouseClick',
    %---------------------------------------------------------------------------
    % Mouse click on object. Limited input expected, so we have to derive stuff
    %---------------------------------------------------------------------------
    % Valid call combinations (ACTION-specific variable names):
    %    andot #MouseClick   (hTarget assumed to be gcbo)
    %---------------------------------------------------------------------------

    % Pass off info to the Axes to deal with.
    anaxes( '#ButtonPress', get( hTarget, 'Parent' ), hTarget )
    
    
%%%%%%%%%%%
%%% New %%%
%%%%%%%%%%%
case '#New',
    %---------------------------------------------------------------------------
    % Make a new Object
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Axes
    %   u               = [],
    %                     OR [X,Y] coordinates,
    %                     OR data structure describing new object properties
    %
    % Valid call combinations (ACTION-specific variable names):
    %  andot( #New , hAxes           ) add new generic obj to the axes
    %  andot( #New , hAxes, [X,Y]    ) add new generic obj at [X,Y] in the axes
    %  andot( #New , hAxes, sObjData ) add new obj using data in structre
    %---------------------------------------------------------------------------
    if nargin==1, error('Axes handle not provided. New object was not added.'); end
    
    % Create the new object
    hDot = local_MakeNewObject( hTarget, u );
    
    % Return output, if requested
    if nargout, xOut = hDot; end    
    
%%%%%%%%%%%%%%
%%% Modify %%%
%%%%%%%%%%%%%%
case '#Modify',
    %---------------------------------------------------------------------------
    % User wants to modify object properties. Build a property dialog box.
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %   u               = [], OR handle to animation figure
    %
    % Valid call combinations (ACTION-specific variable names):
    %  andot( #Modify,  hObj       ) modify the obj (hFig = grandparent of hObj)
    %  andot( #Modify,  hObj, hFig ) modify the obj (hFig for free)
    %---------------------------------------------------------------------------
    local_ModifyObject( hTarget, sTargetUserData, u );

%%%%%%%%%%%%%%%%%%
%%% ChangeLook %%%
%%%%%%%%%%%%%%%%%%
case '#ChangeLook',
    %---------------------------------------------------------------------------
    % The object is being modified, and we just want to see what the changes 
    % look like (purely cosmetic).
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %   u               = handle to uicontrol which has made change
    %
    % Valid call combinations (ACTION-specific variable names):
    %   andot( #UpdateIC, hObj, hUI ) update hObj based on uicontrol hUI
    %---------------------------------------------------------------------------
    ItWorked = local_CosmeticChange( hTarget, sTargetUserData, u );
    if nargout, xOut = ItWorked; end


%%%%%%%%%%%%%%
%%% Update %%%
%%%%%%%%%%%%%%
case '#UpdateIC',
    %---------------------------------------------------------------------------
    % The object has been modified, now we need to update it's internal
    % records and adjust the axes position, etc.
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %   u               = property/value structure w/fields named by property
    %                     OR []
    % Valid call combinations (ACTION-specific variable names):
    %   andot( #UpdateIC, hObj,          ) update hObj based on Position
    %   andot( #UpdateIC, hObj, sObjData ) update hObj based on sObjData
    %---------------------------------------------------------------------------
    local_UpdateObject( hTarget, sTargetUserData, u )
    
%%%%%%%%%%%%%%
%%% Select %%%
%%%%%%%%%%%%%%
case '#Select',
    %---------------------------------------------------------------------------
    % The object has been selected! Woopie! Change to select color
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %
    % Valid call combinations (ACTION-specific variable names):
    %   andot( #Select, hObj ) select hObj (change to select color)
    %---------------------------------------------------------------------------
    %---------------------------------------------------------------------------    
    % Get the proper color from the object's UserData
    %---------------------------------------------------------------------------

    % SelectColor does not have to be evaluated, because it is automatically
    % Changed when the object is updated, so the exact value was known and 
    % (hopefully:-) stored in the data structure
    set( hTarget, 'Color', sTargetUserData.SelectColor )

%%%%%%%%%%%%%%%%
%%% Deselect %%%
%%%%%%%%%%%%%%%%
case '#Deselect',
    %---------------------------------------------------------------------------
    % The object(s) have been deselected! Change back to regular color
    %---------------------------------------------------------------------------
    % Translation of input variables and their derivitives:
    %   hTarget         = Object
    %   sTargetUserData = Object UserData
    %
    % Valid call combinations (ACTION-specific variable names):
    %    andot( #Deselect,  hObj ) deselect hObj (change to regular color)
    %---------------------------------------------------------------------------
    
    %---------------------------------------------------------------------------    
    % Get the initial conditions from figure, if not already available
    % (Figure is parent of axes is parent of object)
    %---------------------------------------------------------------------------
    if nargin ~= 3 | isempty(u),
        u = angetic( get( get( hTarget, 'Parent' ), 'Parent' ) );
    end
    
    %---------------------------------------------------------------------------    
    % Evaluate the object's UserData to get the proper color
    %---------------------------------------------------------------------------
    eval( ['set( hTarget, ''Color'',' sTargetUserData.Color ');'] );
    
%%%%%%%%%%%
%%% END %%%
%%%%%%%%%%%

end % if strcmp action

%###############################################################################
%       %
%  END  %  main
%       %
%###############################################################################

%###############################################################################
%       %
% BEGIN %  local_MakeNewObject
%       %
%###############################################################################
function hDot = local_MakeNewObject( WorkingAxes, sObjectData )

% LOCAL_MAKENEWOBJECT creates a new object on the WorkingAxes
% Assume that someone else will modify the new object
% 
% local_MakeNewObject( AXES, DATA ) adds a new DOT using DATA
% If DATA is a vector, the elements must be:
%       [x,y]
% If DATA is a structure, the fields must be:
%       DATA.Xdata      x-coordinate of dot
%       DATA.Ydata      x-coordinate of dot
%       DATA.Size       MarkerSize of dot
%       DATA.Color      RGB Color of dot
%
% Writen By: Kevin G Kohrt
% Writen On: April 1997
% 5/6/97 KGK change ButtonDown function to call anaxes directly so this
%             could become a Private function
% 5/7/97 KGK change inputs to accept Axes rather than figure
%             (thereby reducing assumptions about figure's data structure)

%-------------------------------------------------------------------------------
% Evaluate/Define the object's properties
%-------------------------------------------------------------------------------
if isstruct( sObjectData ),
    %--------------------------------------------------------------------
    % We've been given all of the object information in a data structure
    % (i.e. new object came from data file or property dialog box)
    %--------------------------------------------------------------------
    % Get the initial conditions for this figure
    u = angetic( get( WorkingAxes, 'Parent' ) );
    % evaluate all parameters based in IC
    eval( [     'XPos =' sObjectData.Xdata ';'  , ...
                'YPos =' sObjectData.Ydata ';'  , ...
             'MySize =' sObjectData.Size  ';'  , ...
            'MyColor =' sObjectData.Color ';'  , ...
            'Hiliting = angetclr(''#Hilite'',' sObjectData.Color ');' ...
          ], ...
          'disp( lasterr ); return;' ...
        ); 
        
    % Make sure special fields are set properly
    sObjectData.Method      = 'andot';
    sObjectData.SelectColor = angetclr( '#Hilite', MyColor );
    sObjectData.Animated    = logical(0);
    sObjectData.DrawString  = '';        
else,
    %--------------------------------------------------------------------
    % We must define our own default values
    % (i.e. new object from menus or toolbar)
    %--------------------------------------------------------------------
    % Get reasonable x & y positions based on how the user called for a new obj
    % Note: if from menu, sObjectData should be empty, else use last mouse click
    cXYLim = get( WorkingAxes, {'Xlim','Ylim','XTick','YTick'} );
    if isempty(sObjectData)
        % Put object in middle of axes
        XPos   = mean( cXYLim{1} );
        YPos   = mean( cXYLim{2} );
    else,
        XPos = sObjectData(1);
        YPos = sObjectData(2);
    end

    % Round the position off to 1/10 of an axes gradation,
    % or, if ticks are turned off, use 1/20th of the axes limits)
    XPos = round2num( XPos, min( [ diff(cXYLim{3}), diff(cXYLim{1})/2 ] )/10 );
    YPos = round2num( YPos, min( [ diff(cXYLim{4}), diff(cXYLim{2})/2 ] )/10 );

    % arbitrarily define remaining properties
    MySize      =  30;                                   % MarkerSize, in points
    MyColor     = [1 1 1] - get( WorkingAxes, 'Color' ); % High contrast    
    HiliteColor = angetclr( '#Hilite', MyColor );       % select color

    % Initialize a new UserData structure -- remember, store as strings!
    % (With the exception of SelectColor )
    sObjectData = struct( 'Animated'   , logical(0)                         , ...
                       'DrawString' , ''                                 , ...
                       'Method'     , 'andot'                            , ...
                       'Xdata'      , num2str( XPos )                    , ...
                       'Ydata'      , num2str( YPos )                    , ...
                       'Size'       , num2str( MySize )                  , ...
                       'Color'      , ['[ ' num2str( MyColor )    ' ]']  , ...
                       'SelectColor', angetclr( '#Hilite', MyColor )      ...
                     );        
                     
end; % if isstruct( sObjectData )

%-------------------------------------------------------------------------------
% Create the object
%-------------------------------------------------------------------------------                     
hDot = line( ...
             'Parent'        , WorkingAxes                  , ...   
             'LineStyle'     ,'none'                        , ...                 
             'Marker'        , '.'                          , ...
             'MarkerSize'    , MySize                       , ...
             'XData'         , XPos                         , ...
             'YData'         , YPos                         , ...
             'Color'         , MyColor                       , ...
             'ButtonDownFcn' , ...
                'anaxes(''#ButtonPress'',get(gcbo,''Parent''),gcbo)', ...
             'EraseMode'     , 'normal'                     , ...             
             'BusyAction'    , 'queue'                      , ...                
             'Interruptible' , 'off'                        , ...
             'UserData'      , sObjectData                     , ...
             'Tag'           , 'AnimDot'                      ...
            );


%###############################################################################
%       %
%  END  %  local_MakeNewObject
%       %
%###############################################################################

%###############################################################################
%       %
% BEGIN %  local_ModifyObject
%       %
%###############################################################################
function local_ModifyObject( hObject, sObjUserData, WorkingFig )

% local_ModifyObject gathers a property list & calls up a property dialog box
%
% Writen By: Kevin G Kohrt
% Writen On: April 1997

%-------------------------------------------------------------------------------
% Define the HG Object Properties that are to be (re)defined on the object
%-------------------------------------------------------------------------------
cObjectProperties = { 'XData'
                      'YData'
                      'MarkerSize'
                      'Color'
                    };

%-------------------------------------------------------------------------------
% Retrieve current property expressions (strings) to put in Property Dialog Box
%-------------------------------------------------------------------------------
cPropertyValues = { sObjUserData.Xdata
                    sObjUserData.Ydata
                    sObjUserData.Size 
                    sObjUserData.Color
                  };
                  
%-------------------------------------------------------------------------------
% Record the field names so we get a proper structure back with #UpdateIC
%-------------------------------------------------------------------------------
cFieldNames = { 'Xdata'
                'Ydata'
                'Size' 
                'Color'
              };

%-------------------------------------------------------------------------------
% Define prompts for ETBoxes in which user will enter new data 
% Note: order must match Object Properties, above
%-------------------------------------------------------------------------------
cTextStrings = { 'X Coordinate:'
			     'Y Coordinate:'
			     'Marker Size:'
			     'Color ([R,G,B]):'
              };
         
%-------------------------------------------------------------------------------
% Get the WorkingFigure, if not already provided, and its UserData 
%-------------------------------------------------------------------------------
if isempty( WorkingFig ) | ~ishandle( WorkingFig )
    % Figure is parent of axes is parent of object
    WorkingFig = get( get( hObject, 'Parent' ), 'Parent' );
end % if
sFigUserData = get( WorkingFig, 'UserData' );

%-------------------------------------------------------------------------------
% Assign an appropriate Tag and Title for the Property Dialog box  
%-------------------------------------------------------------------------------
FigTitle  = [ 'Dot Object Properties: ', ...
            get_param( sFigUserData.m.hAnimationBlock, 'Name') ];
                    
%-------------------------------------------------------------------------------
% Create the Property Dialog box    
%-------------------------------------------------------------------------------
anprpdlg( '#Initialize'     , hObject           , WorkingFig , ...
          cTextStrings      , cObjectProperties , ...
          cPropertyValues   , cFieldNames       , ...
          'andot'           , '#UpdateIC'       , ...
          FigTitle                                ...
        );

%###############################################################################
%       %
%  END  %  local_ModifyObject
%       %
%###############################################################################

%###############################################################################
%       %
% BEGIN %  local_UpdateObject
%       %
%###############################################################################

function local_UpdateObject( hObject, sObjectUserData, s )

%-------------------------------------------------------------------------------
% The object has been modified, now we need to update it's internal records
%-------------------------------------------------------------------------------


%-------------------------------------------------------------------------------
% Check to make sure we have s
%-------------------------------------------------------------------------------
if isempty( s ),
    % Only the Object's position has been changed
    % Make our own u vector based on those facts
    
    % Get the old position
    OldXString = sObjectUserData.Xdata;
    OldYString = sObjectUserData.Ydata;
    
    % Get the new position
    NewPos = get( hObject, {'XData', 'YData'} );
    
    % Get initial condtions (must be u vector)
    u = angetic( get( get( hObject, 'Parent' ), 'Parent' ) );

    % Calculate change in position
    DiffX = NewPos{1} - eval( OldXString );
    DiffY = NewPos{2} - eval( OldYString );
   
    % Create our own u structure based on the old info
    s = struct( 'Xdata'         , OldXString            , ...
                'Ydata'         , OldYString            , ...
                'Color'         , sObjectUserData.Color , ...
                'Size'          , sObjectUserData.Size    ...
              );              

    % Only change data if this object has actually moved
    if DiffX | DiffY,
        s.Xdata = [ OldXString ' + ' num2str( DiffX ) ];
        s.Ydata = [ OldYString ' + ' num2str( DiffY ) ];
    end % if DiffX | DiffY
    
end % if isempty

%-------------------------------------------------------------------------------
% Put together a drawing string to speed up the drawing process!
%-------------------------------------------------------------------------------
DrawStr = '';
% Check to see if each property is simulation-dependent by looking for 
% a "u()" in the property value expression. Add simulation-dependent
% property-value pair to the draw string.
if findstr('u(', s.Xdata), DrawStr = [ DrawStr ',''XData'','      s.Xdata ]; end
if findstr('u(', s.Ydata), DrawStr = [ DrawStr ',''YData'','      s.Ydata ]; end
if findstr('u(', s.Color), DrawStr = [ DrawStr ',''Color'','      s.Color ]; end
if findstr('u(', s.Size ), DrawStr = [ DrawStr ',''MarkerSize'',' s.Size  ]; end

%-------------------------------------------------------------------------------
% Determine if the object is animated
%-------------------------------------------------------------------------------
sObjectUserData.Animated    = ~isempty( DrawStr ); % If empty, it's not animated

%-------------------------------------------------------------------------------
% Complete the DrawString if it is animated
%-------------------------------------------------------------------------------
if sObjectUserData.Animated,
    % Convert the object handle into an accurate string
    % (accurate to 999 plus 14 decimal places)
    chObjectHandle = num2str( hObject, 17 );
    % Assemble fully functional DrawString
    DrawStr = [ 'set(' chObjectHandle DrawStr ');' ];

end % if sObjectUserData.Animated

%-------------------------------------------------------------------------------
% Fill the Object's UserData structure with data passed in
% (except the hilite color, which is a fixed value based on current color)
%-------------------------------------------------------------------------------
sObjectUserData.DrawString  = DrawStr;
sObjectUserData.Xdata       = s.Xdata;
sObjectUserData.Ydata       = s.Ydata;
sObjectUserData.Size        = s.Size;
sObjectUserData.Color       = s.Color;
sObjectUserData.SelectColor = angetclr( '#Hilite', get( hObject, 'Color' ) );

%-------------------------------------------------------------------------------
% Put the UserData back in the object
%-------------------------------------------------------------------------------
set( hObject, 'UserData', sObjectUserData )

%-------------------------------------------------------------------------------
% Force Rescale of the axes
%-------------------------------------------------------------------------------
anscale( get(hObject,'Parent'), hObject, 'Force' )

%-------------------------------------------------------------------------------
% Tell the figure to deselect this dot (it's color has probably changed anyway)
%-------------------------------------------------------------------------------
anfigure( '#DeselectObj', get( get( hObject, 'Parent' ), 'Parent' ), hObject );

%###############################################################################
%       %
%  END  %  local_UpdateObject
%       %
%###############################################################################

%###############################################################################
%       %
% BEGIN %  local_CosmeticChange
%       %
%###############################################################################
function ItWorked = local_CosmeticChange( hObj, sObjUserData, hETBox )

%---------------------------------------------------------------------------
% The object is being modified, and we just want to see what the changes 
% look like (purely cosmetic).
%---------------------------------------------------------------------------
% Translation of input variables and their derivitives:
%   hTarget         = Object
%   sTargetUserData = Object UserData
%   u               = handle to uicontrol which has made change
%
% Valid call combinations (ACTION-specific variable names):
%   andot( #UpdateIC, hObj, hUI ) update hObj based on uicontrol hUI
%---------------------------------------------------------------------------

% Get the initial conditions for the object's figure
u = angetic( get( get( hObj, 'Parent' ), 'Parent' ) );

% Find the Property and Value to be changed, as well as the change record
% Note: we have cleverly stored the exact object property in the UI's tag
% So that all we have to do is get it and eval it!
cPropValHist   = get( hETBox, {'Tag','String'} );
ObjProperty    = cPropValHist{1};
PropertyValue  = cPropValHist{2};

% Adjust the color string if necessary
if strcmp( ObjProperty, 'Color' )
    PropertyValue = colorfixer( PropertyValue );
    set( hETBox, 'String', PropertyValue );
end

% Assume all goes well (makes for cleaner EVAL statements below)         
ItWorked = 1; 

% Try to set the property to the value    
% (Should be a numeric property value)
eval( [ 'set( hObj, ObjProperty,' PropertyValue ');' ], ...
            'ItWorked = 0;' ...
    );

Contact us at files@mathworks.com