5

I just want to draw a dot if the condition is satisfied and otherwise cancel the drawing of the single dot. The following code is the simplified version of my real scenario. Please don't suggest other methods because the part I want to learn is to abort drawing.

The code below is intended to draw a dot for each point on the x-axis whenever its abscissa is an even number. More precisely, there is no dot for odd abscissa.

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\begin{document}
\begin{pspicture}[showgrid](-5,-5)(5,5)
    \multido{\i=-5+1}{11}{\qdisk(!\i\space 2 mod 0 eq {\i\space 0} {<don't draw a dot and continue the loop>} ifelse){2pt}}
\end{pspicture}
\end{document}

Is it possible to exit from the PostScript expression and abort the drawing just for certain dots that do not match the condition?

Edit

I want to get a solution that is useful not only for qdisk but also other graphic macros including the starred version.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor

\begin{document}
% Herbert's method
\begin{pspicture}[showgrid](10,4)
    \multido{\i=1+1}{9}
    {
        \pscircle*(!\i\space dup 2 mod 0 ne {/SD {pop pop pop} def} if 1){5pt}
        \pscircle(!\i\space dup 2 mod 0 ne {/SD {pop pop pop} def} if 3){5pt}
    }
\end{pspicture}

% modified Herbert's method
\begin{pspicture}[showgrid](10,4)
    \multido{\i=1+1}{9}
    {
        \pscircle*(!\i\space dup 2 mod 0 ne {/SD {} def} if 1){5pt}
        \pscircle(!\i\space dup 2 mod 0 ne {/SD {} def} if 3){5pt}
    }
\end{pspicture}

% modified AlexG's method
\begin{pspicture}[showgrid](10,4)
    \multido{\i=1+1}{9}
    {
        \pscircle*(!\i\space dup 2 mod 0 ne {mark Rand Rand /SD {cleartomark} def} if 1){5pt}
        \pscircle(!\i\space dup 2 mod 0 ne {mark Rand Rand /SD {cleartomark} def} if 3){5pt}
    }
\end{pspicture}

% my attempt with other macros
\begin{pspicture}[showgrid](10,4)
    \multido{\i=1+1}{9}
    {
        % compilable but result in a wrong output
        \psframe
            (!\i\space dup 2 mod 0 ne {/SD {pop pop pop} def} if .2 sub 2.8)
            (!\i\space dup 2 mod 0 ne {/SD {pop pop pop} def} if .2 add 3.2)
        %--------------------------------------------------------------------------------
        % does not compile with  GhostScript
        %\psframe
            %(!\i\space dup 2 mod 0 ne {mark Rand Rand /SD {cleartomark} def} if .2 sub 2.8)
            %(!\i\space dup 2 mod 0 ne {mark Rand Rand /SD {cleartomark} def} if .2 add 3.2)
    }
\end{pspicture}
\end{document}

Outputs in the same order.

enter image description here

enter image description here

enter image description here

enter image description here

3
  • So by "abort the drawing" do you mean you want to not draw the \qdisk, or not draw the entire drawing at all (and fail the process completely)?
    – Werner
    Jan 23, 2014 at 5:43
  • @Werner: Just abort the single dot that does not match the condition. Jan 23, 2014 at 6:52
  • I would imagine this is possible if you draw the disk directly in PS rather than using the interface provided by pstricks. That way you can condition on even/odd and draw something/not.
    – Werner
    Jan 23, 2014 at 7:05

2 Answers 2

5

No, this is not possible due to the stack nature of Postscript.

In this specific situation, the verbatim Postscript argument (!...) simply puts the disk coordinates on the operand stack. The disk itself gets drawn later, when the PS procedure SD (it implements the disk drawing) is put on the stack and executed.

In order to not draw selected disks, the code in the else-clause of your example would have to jump into a future state of the operand stack, that is, on top of the SD procedure. This is impossible, since SD hasn't arrived there yet.

All you can do is to temporarily redefine SD to clear the operand stack up to a certain position defined with the mark keyword:

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\begin{document}
\begin{pspicture}[showgrid](-5,-5)(5,5)
  \multido{\i=-5+1}{11}{\qdisk(!
    \i\space 2 mod 0 eq {\i\space 0} % put desired disk coordinates on the stack if condition is fulfilled 
    { %else
      mark  % mark stack position up to which the operand stack needs to be cleared
      -1 -1 % put some dummy coords on the stack to satisfy operators that come in between them and SD
      /SD {cleartomark} def % redefine SD to clear the stack upto the previously defined position
    } ifelse){2pt}}
\end{pspicture}
\end{document}

UPDATE:

For any other PSTricks graphical command you will have to look into its implementation to figure out which bit requires modification. Here are the \pscircle and \psframe examples:

\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{multido}
\SpecialCoor

\begin{document}
  \begin{pspicture}[showgrid](10,4)
    \multido{\i=1+1}{9}
    {
      \pscircle*(!\i\space dup 2 mod 0 ne
        {
          mark  % mark stack position up to which the operand stack needs to be cleared
          exch  % swap \i and mark
          /arc {cleartomark} def % redefine arc to clear the stack upto the previously defined position
        } if 1
      ){5pt}
      \pscircle(!\i\space dup 2 mod 0 ne {mark exch /arc {cleartomark} def} if 3){5pt}
    }
  \end{pspicture}

  \begin{pspicture}[showgrid](10,4)
      \multido{\i=1+1}{9}
      {
          \psframe
          (!\i\space dup 2 mod 0 ne { mark exch /Frame {cleartomark} def } if .2 sub 2.8)
          (!\i\space .2 add 3.2)
          %procedure `Frame' executed around here.
      }
  \end{pspicture}
\end{document}
6
  • +1 Could you please explain what your code does such that I can reuse it as a template for my other projects in the future? Jan 23, 2014 at 8:19
  • Do you have any idea about my other question here. Jan 23, 2014 at 8:28
  • @CodeMocker: I edited a second time. The mark keyword is inserted only if the condition is false.
    – AlexG
    Jan 23, 2014 at 8:52
  • @CodeMocker Ok. Herbert's answer is much shorter. He knows better how many operands to remove. Nevertheless, the essence is the same, SD needs to be redefined.
    – AlexG
    Jan 23, 2014 at 9:21
  • See my updated question. Your solution does not seem to work with \pscircle (unstarred) and other graphics macros (such as \psframe). Jan 24, 2014 at 8:14
5
\documentclass[pstricks,border=12pt,12pt]{standalone}
\SpecialCoor
\begin{document}

\begin{pspicture}[showgrid](-5,-5)(5,5)
  \psforeach{\iA}{-5,-4,..,5}{\qdisk(!
    \iA\space dup 2 mod 0 ne { /SD { pop pop pop } def } if 0 ){2pt}}
\end{pspicture}
\end{document}

or for any possible object:

\documentclass[pstricks,border=12pt,12pt]{standalone}
\makeatletter\let\Modulo\pst@mod\makeatother
\begin{document}

\begin{pspicture}[showgrid](-5,-5)(5,5)
  \psforeach{\iA}{-5,-4,..,5}{%
    \Modulo\iA2\Value
    \ifnum\Value=0 \pscircle(\iA,0){5pt}\fi}
\end{pspicture}

\end{document}
5
  • 1
    Interesting. The original meaning of SD doesn't need to be restored. Why?
    – AlexG
    Jan 23, 2014 at 9:04
  • it is used in an own dictionary
    – user2478
    Jan 23, 2014 at 9:13
  • I see. Within \qdisk the current dict is tx@Dict, and the original definition of SD was made outside of it. Thanks.
    – AlexG
    Jan 23, 2014 at 9:19
  • Interesting: \qdisk(!\iA\space dup 2 mod 0 ne { /SD {} def } if 0 ){2pt} also works. I applied it to my answer here (click). Jan 24, 2014 at 6:33
  • See my updated question. Your solution does not seem to work with \pscircle (unstarred) and other graphics macros (such as \psframe). Jan 24, 2014 at 8:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .