%%
%% Package `pst-pad.tex'
%%
%% Patrick Drechsler
%%
%% Version: $Id: pst-pad.tex 343 2008-08-19 21:05:10Z patrick $
%% 
%%
%% DESCRIPTION:
%%
%% `pst-pad' is a PSTricks package to draw adhesion systems like
%% Johnson-Kendall-Roberts (JKR) models, Hertz adhesion model and wet adhesion
%% model.
%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 
%%% TODO: 
%% 
%% PDTODO:A Implement "rough surfaces"
%%
%% PDTODO:A Create fluid contact angle option for Fluid. Not implemented yet.
%%
%% PDTODO:B Create options for surface combinations (basics of surface 
%%          macros are present):
%%
%%          - flat flat (ff): PstWall - PstWall
%%
%%          - flat sphere (fs): PstWall - PstSphere
%%
%%          - flat Fsphere (fp): PstWall - FSphere
%%
%%          - surface rougness (roughness)
%%
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%  ============================================================
\csname PSTpadLoaded\endcsname%
\let\PSTpadLoaded\endinput%
%
%% Require PSTricks, pst-node, multido and pst-xkey packages:
%
\ifx\PSTMultidoLoaded\endinput\else\input multido.tex\fi%
\ifx\PSTricksLoaded\endinput\else\input pstricks.tex\fi%
\ifx\PSTnodeLoaded\endinput\else\input pst-node.tex\fi%
\ifx\PSTXKeyLoaded\endinput\else\input pst-xkey \fi%
%
%% Define Version info:
%
\def\fileversion{0.3c}%
\def\filedate{2008/08/19}%
\message{`pst-pad' v\fileversion (pd)}%
%
% Allow to use the @ character for all internal macros
\edef\PstAtCode{\the\catcode`\@}%
\catcode`\@=11\relax%
%
%% Create new xkeyval family:
%
\pst@addfams{pst-pad}%
%
%% Not needed so far:
% \pstheader{pst-pad.pro}
%
%% Activate special coordinates:
%
\SpecialCoor%
%
%  ============================================================
% Key definitions: ============================================
%  ============================================================
\define@key[psset]{pst-pad}{WallThickness}{\pst@getlength{#1}\Pst@WallThickness}%
\define@key[psset]{pst-pad}{WallLineWidth}{\pst@getlength{#1}\Pst@WallLineWidth}%
\define@key[psset]{pst-pad}{WallLineColor}{\pst@getcolor{#1}\Pst@WallLineColor}%
\define@key[psset]{pst-pad}{WallString}{\def\psk@WallString{#1}}%
\define@key[psset]{pst-pad}{WallAngle}{\pst@getangle{#1}\Pst@WallAngle}%
%%
\define@key[psset]{pst-pad}{SphereRadius}{\pst@getlength{#1}\Pst@SphereRadius}%
\define@key[psset]{pst-pad}{SphereStartAngle}{\pst@getangle{#1}\Pst@SphereStartAngle}%
\define@key[psset]{pst-pad}{SphereEndAngle}{\pst@getangle{#1}\Pst@SphereEndAngle}%
\define@key[psset]{pst-pad}{SphereString}{\def\psk@SphereString{#1}}%
\define@key[psset]{pst-pad}{SphereOffset}{\pst@getlength{#1}\Pst@SphereOffset}%
\define@key[psset]{pst-pad}{SphereFillColor}{\pst@getcolor{#1}\Pst@SphereFillColor}%
\define@key[psset]{pst-pad}{SphereLineWidth}{\pst@getlength{#1}\Pst@SphereLineWidth}%
\define@key[psset]{pst-pad}{SphereLineColor}{\pst@getcolor{#1}\Pst@SphereLineColor}%
%%
\define@key[psset]{pst-pad}{FSphereHeight}{\pst@getlength{#1}\Pst@FSphereHeight}%
\define@key[psset]{pst-pad}{FSphereFillColor}{\pst@getcolor{#1}\Pst@FSphereFillColor}%
\define@key[psset]{pst-pad}{FSphereString}{\def\psk@FSphereString{#1}}%
\define@key[psset]{pst-pad}{FSphereLineWidth}{\pst@getlength{#1}\Pst@FSphereLineWidth}%
\define@key[psset]{pst-pad}{FSphereLineColor}{\pst@getcolor{#1}\Pst@FSphereLineColor}%
%%
\define@key[psset]{pst-pad}{FluidMaxRadius}{\pst@getlength{#1}\Pst@FluidMaxRadius}%
\define@key[psset]{pst-pad}{FluidMinRadius}{\pst@getlength{#1}\Pst@FluidMinRadius}%
\define@key[psset]{pst-pad}{FluidShearOffsetX}{\pst@getlength{#1}\Pst@FluidShearOffsetX}%
\define@key[psset]{pst-pad}{FluidShearOffsetY}{\pst@getlength{#1}\Pst@FluidShearOffsetY}%
\define@key[psset]{pst-pad}{FluidHeight}{\pst@getlength{#1}\Pst@FluidHeight}%
\define@key[psset]{pst-pad}{FluidFillColor}{\pst@getcolor{#1}\Pst@FluidFillColor}%
\define@key[psset]{pst-pad}{FluidString}{\def\psk@FluidString{#1}}%
\define@key[psset]{pst-pad}{FluidLineWidth}{\pst@getlength{#1}\Pst@FluidLineWidth}%
\define@key[psset]{pst-pad}{FluidLineColor}{\pst@getcolor{#1}\Pst@FluidLineColor}%
%%
\define@key[psset]{pst-pad}{StringA}{\def\psk@StringA{#1}}%
\define@key[psset]{pst-pad}{StringB}{\def\psk@StringB{#1}}%
%%
\define@key[psset]{pst-pad}{TotalAngle}{\pst@getangle{#1}\Pst@TotalAngle}%
%%
%% TODO: Change this variables from dim to number:
\define@key[psset]{pst-pad}{RoughnessMax}{\pst@getlength{#1}\Pst@RoughnessMax}%
\define@key[psset]{pst-pad}{RoughnessWidth}{\pst@getlength{#1}\Pst@RoughnessWidth}%
%%
\define@boolkey[psset]{pst-pad}[Pst@]{fluid}[true]{}%
%%
\define@boolkey[psset]{pst-pad}[Pst@]{rough}[true]{}%
\define@boolkey[psset]{pst-pad}[Pst@]{roughA}[true]{}%
\define@boolkey[psset]{pst-pad}[Pst@]{roughB}[true]{}%

%% I might need something like this for defining different surfaces.
%%
%% Adapted From pst-labo.tex :
%%
%%  0->PAD  1->WALL   2->SPHERE
% \def\pst@@PAD{pad}
% \def\pst@@WALL{wall}
% \def\pst@@SPHERE{sphere}
% %
% \define@key[psset]{pst-pad}{surfaceType}{%
%   \def\pst@tempA{#1}
%   \edef\psk@surfaceType{%
%     \ifx\pst@@PAD\pst@tempA 0 \else     
%     \ifx\pst@@WALL\pst@tempA 1 \else    
%     \ifx\pst@@SPHERE\pst@tempA 2 \else 0
%       \typeout{pst-pad: unknown surfaceType -> #1}
%       \typeout{          using type "pad" instead.}
%     \fi\fi\fi\fi%                               % default is pad
% }}

%  ============================================================
% Default psset values: =======================================
%  ============================================================
\psset[pst-pad]{%
  fluid=true, rough=false, roughA=false, roughB=false,%
  %
  WallThickness=1,WallString={},WallAngle=0,WallLineWidth=1pt,WallLineColor=black,%
  %%
  SphereStartAngle=180,SphereEndAngle=360,SphereRadius=1,SphereString={},%
  SphereOffset=0,SphereFillColor=white,SphereLineWidth=1pt,SphereLineColor=black,%
  %%
  FSphereHeight=2,FSphereFillColor=lightgray,FSphereString={},FSphereLineWidth=1pt,%
  FSphereLineColor=black,%
  %%
  FluidMaxRadius=1,FluidMinRadius=.5,FluidHeight=.5,%
  FluidFillColor=yellow,FluidString={},%
  FluidShearOffsetX=0,FluidShearOffsetY=0,FluidLineWidth=1pt,%
  FluidLineColor=black,%
  %%
  RoughnessMax=0, RoughnessWidth=0,%
  %%
  StringA={},StringB={},TotalAngle=0} %

% %% Redefine RoughnessMax and RoughnessWidth:
% \def\Pst@Rm{\Pst@RoughnessMax\space 0.5 mul }%
% %% testing:
% \def\Rw{\Pst@RoughnessWidth\space \Pst@RoughnessMax }%


%  ============================================================
% PstFluid ====================================================
%  ============================================================
\def\PstFluid{\@ifnextchar[{\pst@PstFluid@i}{\pst@PstFluid@i[]}}%
\def\pst@PstFluid@i[#1](#2){{%
    \psset{#1}%
    \begin@ClosedObj%
      \rput{\Pst@WallAngle}(#2){%
        %% Nodes (currently not used; They can be used outside of the macro as
        %% referece points):
        %% Fbr (Fluid bottom right):
        \pnode(! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg){Fbr}%
        %% Fbl (Fluid bottom left):
        \pnode(! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add neg \Pst@FluidHeight neg){Fbl}%
        %% Ftl (Fluid top left):
        \pnode(! \Pst@FluidMaxRadius neg \Pst@FluidShearOffsetX add \Pst@FluidHeight){Ftl}%
        %% Ftr (Fluid top right):
        \pnode(! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add \Pst@FluidHeight){Ftr}%
        %% 
        %% 
        \pscustom[linewidth=\Pst@FluidLineWidth,linecolor=\Pst@FluidLineColor,unit=1pt]{%
          %% Left meniscus:
          \pscurve%
          (! \Pst@FluidMaxRadius neg \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
          (! \Pst@FluidMinRadius neg 0 \Pst@FluidShearOffsetY add)%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add neg \Pst@FluidHeight neg)%
          %% Bottom line:
          \psline%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add neg \Pst@FluidHeight neg)%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
          %%
          %% PDTODO:A Fix ZigZag and Curved line:
          %%
          %% Bottom line with zigzag:
          % \multido{\rX=-\Pst@FluidMaxRadius+10}{5}{%
          % \multido{\rX=-\Pst@FluidMaxRadius+10}{! \Pst@FluidMaxRadius 2 mul 10 div floor}{%
          %   \psline(\rX,-\Pst@FluidHeight)%
          %   (! \rX\space 2.5 add \Pst@FluidHeight neg 5 add)%
          %   (! \rX\space 7.5 add \Pst@FluidHeight neg 5 sub)%
          %   (! \rX\space 10 add \Pst@FluidHeight neg)%
          % }
          %% Bottom line with curve:
          % \multido{\rX=-\Pst@FluidMaxRadius+10}{5}{%
          %   \pscurve(\rX,-\Pst@FluidHeight)%
          %   (! \rX\space 2.5 add \Pst@FluidHeight neg 5 add)%
          %   (! \rX\space 7.5 add \Pst@FluidHeight neg 5 sub)%
          %   (! \rX\space 10 add \Pst@FluidHeight neg)%
          % }
          %% Right meniscus:
          \pscurve[liftpen=1]%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
          (! \Pst@FluidMinRadius 0 \Pst@FluidShearOffsetY sub)%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
          %% Top line:
          \psline%
          (! \Pst@FluidMaxRadius \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
          (! \Pst@FluidMaxRadius neg \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
          %% Fill:
          \fill[fillstyle=solid,fillcolor=\Pst@FluidFillColor]%
        }%
        %% String placement if String is present:
        \ifx\psk@FluidString\@empty\else%
        \rput[C]{-\Pst@TotalAngle}(0,0){\psk@FluidString}%
        \fi}%
    \end@ClosedObj%
  }\ignorespaces}%

%  ============================================================
% PstWall =====================================================
%  ============================================================
\def\PstWall{\pst@object{PstWall}}%
\def\PstWall@i(#1){{%
    \pst@killglue%
    \addbefore@par{linewidth=2pt}%
    \use@par%				
    \rput{\Pst@WallAngle}(#1){%
      \psset{unit=1pt,linewidth=\Pst@WallLineWidth,linecolor=\Pst@WallLineColor,dimen=middle}%
      %% Main rectangle frame:
      \psframe[linestyle=none,fillstyle=hlines]%
      (! \Pst@FluidMaxRadius 10 add neg \Pst@WallThickness neg)%
      (! \Pst@FluidMaxRadius 10 add 0)%
      %% Extra line for "surface":
      \psline%
      (! \Pst@FluidMaxRadius 10 add neg 0)%
      (! \Pst@FluidMaxRadius 10 add 0)%
      %% String placement if string is present:
      \ifx\psk@WallString\@empty\else%
      \rput*[C]{\Pst@WallAngle}% pdtodo: fix this
      % \rput*[C]{! \Pst@TotalAngle \Pst@WallAngle sub}%
      (! -\Pst@WallThickness .5 mul 0 exch){\psk@WallString}%
      \fi}%
  }\ignorespaces}%


%  ============================================================
% PstWallRough ================================================
%  ============================================================
%%
%% PDTODO:A This macro is not implemented yet.
%%
\def\PstWallRough{\pst@object{PstWallRough}}%
\def\PstWallRough@i(#1){{%
    \pst@killglue
    \addbefore@par{linewidth=1pt}%
    \use@par%				
    \rput{\Pst@WallAngle}(#1){%
      \psset{unit=1pt,linewidth=\Pst@WallLineWidth,dimen=middle}%		     
      %%
      % \def\maxtmp{!\Pst@FluidMaxRadius\space 2 diff }
      \psframe[fillstyle=solid,fillcolor=gray]%
      (-\Pst@FluidMaxRadius,-\Pst@WallThickness)(\Pst@FluidMaxRadius,-\Pst@RoughnessMax)%
      % (! \maxtmp \Pst@WallThickness neg)(\Pst@FluidMaxRadius,-\Pst@RoughnessMax)
      %%
      \pscustom{%
        %% TODO:C Replace algebraic with RPN notation:
        \psplot[plotpoints=100,algebraic=true]{-\Pst@FluidMaxRadius}{\Pst@FluidMaxRadius}%
        {\Pst@RoughnessMax*sin(x*Pi*\Pst@RoughnessWidth-(Pi/2))}%
%         \psplot[plotpoints=100]{-\Pst@FluidMaxRadius}{\Pst@FluidMaxRadius}%
%         %% TODO:A Ignore pt units for this numeric test and use the original
%         %% input number!!!!:
%         {\Pst@RoughnessWidth round 2 mod 0 eq %  <- IF CONDITION
%           {/MyFac \Pst@RoughnessWidth round 1 add def }% IF == TRUE STATEMENT 
%           {/MyFac \Pst@RoughnessWidth round 2 div floor def } % <- ELSE STATEMENT
%           ifelse % <- END IF-ELSE
%           x \Pst@FluidMaxRadius round div MyFac mul 180 mul sin%
%         }% end psplot
        \gsave%
        \psline(\Pst@FluidMaxRadius,-\Pst@RoughnessMax)(-\Pst@FluidMaxRadius,-\Pst@RoughnessMax)%
        \fill[fillcolor=gray,fillstyle=solid]%
        \grestore%
      }%
      %% String placement if String is present:
      \ifx\psk@WallString\@empty\else%
      \rput*[C]{\Pst@WallAngle}% pdtodo: fix this
      % \rput*[C]{! \Pst@TotalAngle \Pst@WallAngle sub}%
      (! -\Pst@WallThickness .5 mul 0 exch){\psk@WallString}%
      \fi%
    }%
  }\ignorespaces}%

%  ============================================================
% PstSphere =====================================================
%  ============================================================
\def\PstSphere{\pst@object{PstSphere}}%
\def\PstSphere@i(#1){{%
    \pst@killglue
    \addbefore@par{linewidth=1pt}%
    \use@par%
    \rput(#1){%
      \psset{unit=1pt,linewidth=\Pst@SphereLineWidth,linecolor=\Pst@SphereLineColor,dimen=middle}%
      %% Draw the "sphere" using the psarc macro:
      \psarc[fillstyle=solid,fillcolor=\Pst@SphereFillColor]%
      (0,\Pst@SphereRadius){\Pst@SphereRadius}%
      {\Pst@SphereStartAngle}{\Pst@SphereEndAngle}%
      %% Display string if present:
      \ifx\psk@SphereString\@empty\else%
      \rput[C]{\Pst@TotalAngle}%
      (! \Pst@SphereRadius .5 mul \pst@number\pslinewidth add 0 exch)%
      {\psk@SphereString}%
      \fi}%
  }\ignorespaces}%

%  ============================================================
% PstFlattenedSphere ==========================================
%  ============================================================
\def\PstFlattenedSphere{\pst@object{PstFlattenedSphere}}%
\def\PstFlattenedSphere@i(#1){{%
    \pst@killglue
    \addbefore@par{linewidth=1pt}%
    \use@par%
    \rput(#1){%
      \psset{unit=1pt,linewidth=\Pst@FSphereLineWidth,linecolor=\Pst@FSphereLineColor,dimen=middle}%
      %% The "flattened sphere" is drawn as a rectangle frame with rounded
      %% corners (arc). It is then overlayed and clipped by a rectangle half
      %% the height to produce the look of a flattened sphere.
      \begin{psclip}{%
          \psframe[linestyle=none]%
          (!\Pst@FSphereHeight .5 mul \Pst@FluidMaxRadius add neg 0)%
          (!\Pst@FSphereHeight .5 mul \Pst@FluidMaxRadius add \Pst@FSphereHeight .5 mul)%
        }%
        \psframe[framearc=2,fillstyle=solid,fillcolor=\Pst@FSphereFillColor]%
        (!\Pst@FluidMaxRadius neg \Pst@FSphereHeight .5 mul sub 0)%
        (!\Pst@FluidMaxRadius \Pst@FSphereHeight .5 mul add \Pst@FSphereHeight)% 
      \end{psclip}%
      %% Display string if present:
      \ifx\psk@FSphereString\@empty\else%
      \rput[C]{-\Pst@TotalAngle}(! \Pst@FSphereHeight .3 mul 0 exch){\psk@FSphereString}%
      \fi}%
  }\ignorespaces}%

%  ============================================================
% PstPad ======================================================
%  ============================================================
\def\PstPad{\pst@object{PstPad}}%
\def\PstPad@i(#1){{%
    \pst@killglue%
    \addbefore@par{linewidth=1pt}%
    \use@par%
    \rput{\Pst@TotalAngle}(#1){%
      \psset{unit=1pt}%
      %% Test for fluid true/false:
      \ifPst@fluid%
      %%fluid = true:
      \PstFluid(0,0)%
      \PstFlattenedSphere[FSphereString=\psk@StringA]%
      (! 0 \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
      %% Test if WallString is empty:
      \ifx\psk@WallString\@empty%
      \PstWall%
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \else%
      \PstWall[WallString=\psk@WallString]%
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \fi%
      \else%
      %%fluid = false:
      \PstFlattenedSphere(0,0)%
      \PstWall(0,0)%
      \fi%
    }%
  }\ignorespaces}%


%  ============================================================
% WallToWall ==================================================
%  ============================================================
\def\PstWallToWall{\pst@object{PstWallToWall}}%
\def\PstWallToWall@i(#1){{%
    \pst@killglue%
    \addbefore@par{linewidth=4pt}%
    \use@par%
    \rput{\Pst@TotalAngle}(#1){%
      \psset{unit=1pt}%
      \PstFluid(0,0)%
      %% Test if StringA is empty:
      \ifx\psk@StringA\@empty%
      \PstWall[WallAngle=180]%
      (! 0 \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
      \else%
      \PstWall[WallAngle=180,WallString=\psk@StringA]%
      (! 0 \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
      \fi%
      %% Test if StringB is empty:
      \ifx\psk@StringB\@empty%
      \PstWall%
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \else%
      \PstWall[WallString=\psk@StringB]%
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \fi%
    }%
  }\ignorespaces}%

%  ============================================================
% SphereToWall ================================================
%  ============================================================
%%
%%  PDTODO:A I would like this macro to have "fluid = false" as the default
%%  value (all other major macros need "fluid = true" as default values).
\def\PstSphereToWall{\pst@object{PstSphereToWall}}%
\def\PstSphereToWall@i(#1){{%
    \pst@killglue%
    \addbefore@par{linewidth=1pt}%
    \use@par%
    \rput{\Pst@TotalAngle}(#1){%
      \psset{unit=1pt}%
      %% Test for fluid true/false:
      \ifPst@fluid% fluid = true:
      \PstFluid(0,0)% <- display fluid macro
      \PstSphere[SphereString=\psk@StringA]%
      (! 0 \Pst@FluidShearOffsetX add \Pst@FluidHeight)%
      %% Test if StringB is empty:
      \ifx\psk@StringB\@empty%
      \PstWall[fillstyle=none]% <- display wall macro
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \else%
      \PstWall[fillstyle=none,WallString=\psk@StringB]% <- display wall macro
      (! 0 \Pst@FluidShearOffsetX sub \Pst@FluidHeight neg)%
      \fi%
      \else% fluid = false:
      \PstWall[linewidth=1pt,fillstyle=none,WallString=\psk@StringB](0,0)% <- display wall macro
      \PstSphere[SphereString=\psk@StringA](0,-\Pst@SphereOffset)% <- display sphere macro
      \psline[linewidth=0.8pt,linestyle=dashed,linecolor=gray]%
      (-\Pst@FluidMaxRadius,0)(\Pst@FluidMaxRadius,0)%
      \PstWall[linewidth=1pt,fillstyle=none](0,0)% <- display wall macro
      % \PstWallRough[unit=1cm](0,\Pst@RoughnessMax)%
      \fi%
    }%
  }\ignorespaces}%
