function RespObj = plotgrid(RespObj)
%PLOTGRID  Plots or adjusts grid for response plots.
%
%   RESPOBJ = PLOTGRID(RESPOBJ) plots a Nichols chart on the axis 
%   associated with the SISO response object RESPOBJ.  
%
%   See also RESPFCN.

%   Authors: P. Gahinet and K. Gondoly
%   Revised: Adam W. DiVergilio
%   Copyright 1986-2000 The MathWorks, Inc. 
%   $Revision: 1.11 $  $Date: 2000/06/14 20:09:39 $


% Get plot axis and current axis limits
AllRespProps = get(RespObj,'Undocumented');
ax = AllRespProps.PlotAxes;
CurrentLims = get(ax,{'Xlim','Ylim'});
ZoomTight = strcmp(AllRespProps.Zoom,'tight');

% If the grid handle set is empty or partially stale, generate and 
% plot new grid that covers whole data range
GridLines = RespObj.GridLines;

%---If units are not dB/deg, then show HG grid instead
if ~(strcmpi(AllRespProps.MagnitudeUnits,'db') & strcmpi(AllRespProps.PhaseUnits,'deg'))
   delete(GridLines(ishandle(GridLines)));
   set(ax,'XGrid','on','YGrid','on');
   RespObj.GridLines = [];
   return;
end

if isempty(GridLines) | ~all(ishandle(GridLines))
   % First clean up
   delete(GridLines(ishandle(GridLines)))
   set(ax,'Xgrid','off','Ygrid','off')
   
   % Determine X and Y extent of entire set of response lines (visible or not)
   % and generate grid for these limits
   [AutoXlims,AutoYlims] = niclims(RespObj,'alltight');
   [phase,gain,labels] = nicchart(AutoXlims{1}(1),AutoXlims{1}(2),AutoYlims{1}(1));
   
   % Plot new grid and store all related handles
   Color   = get(ax,'XColor');
   TColor  = localTextColor(ax);
   FSize   = get(ax,'FontSize');
   FWeight = get(ax,'FontWeight');
   FAngle  = get(ax,'FontAngle');
   GridHandles = line(phase,gain,'LineStyle',':','Color',Color,...
      'Parent',ax,'Tag','CSTgridLines','HandleVisibility','off','HitTest','off');
   TextHandles = zeros(size(labels,2),1);
   for j=1:length(TextHandles)
      TextHandles(j) = text(labels(1,j),labels(2,j),...
         sprintf(' %.3g dB',labels(3,j)),'Parent',ax,...
         'Color',TColor,'FontWeight',FWeight,'FontAngle',FAngle,'FontSize',FSize,...
         'Tag','CSTgridLines','HandleVisibility','off','HitTest','off');
   end
   RespObj.GridLines = [GridHandles; TextHandles];
end


% When user-controlled XlimMode is auto, reset X limits based on 
% current limits so that grid is clipped at multiples of 180 degrees
% RE: don't change axis limits when zoomed out with grid on
if ZoomTight | strcmp(AllRespProps.XlimMode,'auto'),
   % RE: CurrentLimits is based on all visible models in auto mode
   Pmax = 360*ceil(CurrentLims{1}(2)/360);
   Pmin = min(Pmax-360,360*floor(CurrentLims{1}(1)/360));
   if Pmax-Pmin>360,
      % Delete empty 180 degree portions
      Pmax = 180*ceil(CurrentLims{1}(2)/180);
      Pmin = 180*floor(CurrentLims{1}(1)/180);
   end
   % RE: Don't set RespObj.Xlim directly (would affect XlimMode)
   Xlims = {[Pmin Pmax]};
else
   Xlims = CurrentLims(1);
end

% Same for Y limits
if ZoomTight | strcmp(AllRespProps.YlimMode,'auto'),
   Gmin = min([-20 20*floor(CurrentLims{2}(1)/20)]);
   Gmax = max([40 20*ceil(CurrentLims{2}(2)/20)]);
   Ylims = {[Gmin Gmax]};
else
   Ylims = CurrentLims(2);
end

% Set X and Y limits 
RespObj = respfcn('setxylims',RespObj,Xlims,Ylims);


% Position grid labels to multiple of 360 degree nearest to rightmost X limit
% and show only labels within axis limits
CurrentLims = get(ax,{'Xlim' 'Ylim'});
DesiredX = 360 * round(0.999 * CurrentLims{1}(2)/360);  % desired position
TextHandles = findobj(RespObj.GridLines,'Type','text');
TextPositions = get(TextHandles,{'Position'});
CurrentX = 360 * round(TextPositions{1}(1)/360);
ShiftX = DesiredX-CurrentX;
for h=TextHandles(:)'
   Position = get(h,'Position');
   NewPosition = [Position(1)+ShiftX , Position(2:end)];
   if prod(NewPosition(1)-CurrentLims{1})<0 & ...
         prod(NewPosition(2)-CurrentLims{2})<0,
      % Label within current axis limits
      set(h,'Position',NewPosition,'Visible','on')
   else
      set(h,'Position',NewPosition,'Visible','off')
   end

   %---Change anchor point if label lies outside of axes limit
   ex = get(h,'Extent');
   if ex(1)+ex(3)>CurrentLims{1}(2), set(h,'HorizontalAlignment','right'); end
   if ex(2)      <CurrentLims{2}(1), set(h,'VerticalAlignment','bottom');  end
   if ex(2)+ex(4)>CurrentLims{2}(2), set(h,'VerticalAlignment','top');     end
end


%%%%%%%%%%%%%%%%%%
% localTextColor %
%%%%%%%%%%%%%%%%%%
function C = localTextColor(Ax)
%---Determine good color for grid text in axes Ax
 C  = get(Ax,'XColor');
 AC = get(Ax,'Color');
 if isstr(AC), AC = get(get(Ax,'Parent'),'Color'); end
 if sum(AC)>1.5
    C = C*0.5;
 else
    C = C + 0.5*([1 1 1]-C);
 end
