# Dimensions and vertical alignment of "dynamic" PSTricks picture

I am creating a environment in which I can add numbers of PSTricks objects (basically shapes, defined as macros, vertically arranged), each one with argument (content of the shape) so I don't know the actual height of each object.

I am now facing two problems :

1. I don't know the dimensions of the whole picture in order to save space around it! I can easily calculate them but I don't see how I can use them. For the moment, the whole picture has zero size (normal behaviour with PSTricks). If I wrap the picture into a pspicture environment, I know I can enter coordinates but I don't know them before all the shapes are drawn...

2. I'd like to be able to align the baseline of the surrounding text of the picture with the baseline of the content of one specific shape. I thought about using nodes with shapes numbering but no success as I couldn't know their position beforehand. I also tried a pspicture environment in order to use the shift option but the same problem remains: how to specify a value that will be calculated later... Furthermore, the whole picture may be scaled, so it modifies the baseline position. :(

(I know I can achieve this easily with TikZ and its baseline and scale option, but I want to do it with PSTricks).

Thx in advance if you could help me.

Here is a piece of code with only two different shapes, with and without the pspicture wrapping.

\documentclass[a4paper,12pt]{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pstricks}

% shapes position
\newdimen\verticalOffset
\verticalOffset=0pt

% space between shapes
\newdimen\verticalSep
\verticalSep=15pt

\newsavebox{\shapebox}

% rectangle shape
\newcommand*{\shapeR}[1]{%
\setbox\shapebox\hbox{\hspace{10pt}\bfseries#1\hspace{10pt}\vrule height20pt depth10pt width0pt\relax}%
\rput[Bl](0,\verticalOffset){%
\psframe(0,0)(\the\dimexpr\wd\shapebox,\the\dimexpr-\ht\shapebox-\dp\shapebox)%
\rput[Bl](0,\the\dimexpr-\ht\shapebox){\copy\shapebox}%
}%
}

% oval shape
\newcommand*{\shapeO}[1]{%
\setbox\shapebox\hbox{\hspace{15pt}\bfseries#1\hspace{15pt}\vrule height25pt depth15pt width0pt\relax}%
\rput[Bl](0,\verticalOffset){%
\psellipse(\the\dimexpr\wd\shapebox/2,\the\dimexpr-\ht\shapebox/2-\dp\shapebox/2)(\the\dimexpr\wd\shapebox/2,\the\dimexpr\ht\shapebox/2+\dp\shapebox/2)%
\rput[Bl](0,\the\dimexpr-\ht\shapebox){\copy\shapebox}%
}%
}

\newsavebox{\drawbox}

% drawing env
\newenvironment{drawWithoutPspic}[1]%
{% begin def
\def\drawscalefactor{#1}%
\verticalOffset=0pt%
\begin{lrbox}{\drawbox}%
}
{% end def
\end{lrbox}%
\psscalebox{\drawscalefactor}{\usebox{\drawbox}}%
}

% drawing env, shapes wrapped into a pspicture
\newenvironment{drawWithPspic}[1]%
{% begin def
\def\drawscalefactor{#1}%
\verticalOffset=0pt%
\begin{lrbox}{\drawbox}%
\begin{pspicture}[shift=0](0,0)(0,0)% <---- ??
}
{% end def
\end{pspicture}%
\end{lrbox}%
\psscalebox{\drawscalefactor}{\usebox{\drawbox}}%
}

\begin{document}

Without \emph{pspicture}
\begin{drawWithoutPspic}{0.9}
\shapeR{Hello World!}\shapeO{Foo bar baz}\shapeO{Ooooohhhhhh!}\shapeR{D/L}
\end{drawWithoutPspic}

\vspace{180pt}
With \emph{pspicture}
\begin{drawWithPspic}{0.7}
\shapeR{Hello World!}\shapeO{Foo bar baz}\shapeO{Ooooohhhhhh!}\shapeR{D/L}
\end{drawWithPspic}

\end{document}

Here the picture:

## EDIT - One solution

Well, I finally managed to obtain what I wanted. Given that I was placing shapes and texts explicitly with precise lengths, I decided to use the vertical offset to determine the height of the picture, and I added a new length and shapes numbering to determine which text of a specific shape will be on the baseline.

Now, the environment needs two arguments: the first one is the scale factor, the second is the shape number for the baseline.

Here is the code.

\documentclass[a4paper,12pt]{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pstricks}

% shapes position
\newdimen\verticalOffset
\verticalOffset=0pt

% space between shapes
\newdimen\verticalSep
\verticalSep=15pt

% baseline position
\newdimen\baselineOffset
\baselineOffset=0pt

% shapes counter
\newcounter{shapeno}

\newsavebox{\shapebox}

% rectangle shape
\newcommand*{\shapeR}[1]{%
\ifdim \verticalOffset = 0pt%
\else%
\fi%
\setbox\shapebox\hbox{\hspace{2pt}\bfseries#1\hspace{2pt}\vrule height14pt depth5pt width0pt\relax}%
\rput[Bl](0,\verticalOffset){%
\psframe(0,0)(\the\dimexpr\wd\shapebox,\the\dimexpr-\ht\shapebox-\dp\shapebox)%
\rput[Bl](0,\the\dimexpr-\ht\shapebox){\copy\shapebox}%
}%
\ifnum\theshapeno = 1%
\global\baselineOffset=\dimexpr\verticalOffset-\ht\shapebox\relax%
\else%
\ifnum\theshapeno = \baselineno%
\global\baselineOffset=\dimexpr\verticalOffset-\ht\shapebox\relax%
\fi%
\fi%
\stepcounter{shapeno}%
\ignorespaces
}

% oval shape
\newcommand*{\shapeO}[1]{%
\ifdim \verticalOffset = 0pt%
\else%
\fi%
\setbox\shapebox\hbox{\hspace{2pt}\bfseries#1\hspace{2pt}\vrule height18pt depth10pt width0pt\relax}%
\rput[Bl](0,\verticalOffset){%
\psellipse(\the\dimexpr\wd\shapebox/2,\the\dimexpr-\ht\shapebox/2-\dp\shapebox/2)(\the\dimexpr\wd\shapebox/2,\the\dimexpr\ht\shapebox/2+\dp\shapebox/2)%
\rput[Bl](0,\the\dimexpr-\ht\shapebox){\copy\shapebox}%
}%
\ifnum\theshapeno = 1%
\global\baselineOffset=\dimexpr\verticalOffset-\ht\shapebox\relax%
\else%
\ifnum\theshapeno = \baselineno%
\global\baselineOffset=\dimexpr\verticalOffset-\ht\shapebox\relax%
\fi%
\fi%
\stepcounter{shapeno}%
\ignorespaces
}

\newsavebox{\drawbox}

% drawing env, shapes wrapped into a pspicture
\newenvironment{drawWithPspic}[2]%
{% begin def
\def\drawscalefactor{#1}%
\def\baselineno{#2}%
\verticalOffset=0pt%
\baselineOffset=0pt%
\setcounter{shapeno}{1}
\begin{lrbox}{\drawbox}%
}
{% end def
\end{lrbox}%
\begin{pspicture}[shift=\drawscalefactor\dimexpr\noexpand\verticalOffset-\noexpand\baselineOffset](0,\drawscalefactor\noexpand\verticalOffset)(2,0)% <--- last thing to do : calculation of the actual width
\psscalebox{\drawscalefactor}{\usebox{\drawbox}}%
\end{pspicture}%
}

\begin{document}

% Blue baseline
\leavevmode\rlap{\color{blue}\rule{\linewidth}{.1pt}}%
...text before...

% Red baseline
\leavevmode\rlap{\color{orange}\rule{\linewidth}{.1pt}}%
Aligned with 2\textsuperscript{nd} shape :
\begin{drawWithPspic}{0.5}{2}
\shapeR{Hello World!}
\shapeO{Foo bar baz}
\shapeO{Ooooohhhhhh!}
\shapeR{D/L}
\end{drawWithPspic}
Aligned with 3\textsuperscript{th} shape :
\begin{drawWithPspic}{0.6}{3}
\shapeR{Hello World!}
\shapeO{Foo bar baz}
\shapeO{Ooooohhhhhh!}
\shapeR{D/L}
\shapeO{Hi!}
\end{drawWithPspic}

% Blue baseline
\leavevmode\rlap{\color{blue}\rule{\linewidth}{.1pt}}%
...text after...

\end{document}

• Always I have not undestood the question. My English is bad and I have thought of attach your picture. :-). Apr 26, 2018 at 21:56
• PSTricks works differently to TikZ. It is not possible to know width and height of a PStricks object. You have to define the dimensions on TeX level, but the the drawing is done on PostScript level. And on PostScript level all the TeX work (width/height) of a box must already be done. However, with nodes it is a bit diffferent, because the text is set on TeX level. Put a node into a box and then you can measure width and height of the box.
– user2478
Apr 27, 2018 at 5:51
• @Herbert: thanks for your answer and the clarifications. I played with nodes during all day yesterday but didn't managed to achieve what I wanted. However, I think I may have solved it. I'll edit my post later on.
– F...
Apr 28, 2018 at 15:12

I also do not know how to compute the bounding box in the way you describe, but I am not sure if you need this. All your shapes can be conveniently defined as nodes, which have their own bounding box. Here are a few examples:

\documentclass[a4paper,12pt]{article}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pstricks}

% shapes position
\newdimen\verticalOffset
\verticalOffset=0pt

% space between shapes
\newdimen\verticalSep
\verticalSep=15pt

\newcommand{\boxnode}[2]{\rnode[c]{#1}{\psframebox[framearc=0.2]{#2}}}
\begin{document}
Again without \emph{pspicture}:
\begin{flushleft}
\boxnode{A}{Hello World!}\\[0.1cm]
\ovalnode{B}{Foo bar bz}\\[0.1cm]
\ovalnode{C}{Ooooohhhhhh!}\\[0.1cm]
\boxnode{D}{D/L}
\end{flushleft}
And here we go on.
\begin{flushleft}
\boxnode{E}{Hello World!}\\[0.1cm]
\boxnode{H}{D/L}\ncarc[linecolor=blue]{->}{G}{H}
\end{flushleft}
\begin{tabular}{ll}
&\boxnode{I}{Hello World!}\\[0.1cm]
aligned with the second \rnode[r]{shape}{shape}:&\ovalnode[shadow=true,blur=true]{J}{Foo bar bz}\\[0.1cm]
&\boxnode{L}{D/L}\ncarc[linecolor=blue]{->}{shape}{J}
\end{tabular}
\end{document}

And you could also put these things in scaleboxes and of course tables and so on. And you can do many things with them without explicitly starting a pspicture. As illustrated, you can connect them with arcs, but there are tons of other things, see e.g. section 31 of the pstricks manual.

• Thanks for your answer. I've tested many ways with nodes but I couldn't achieve what I wanted. I present a solution on my first post, based on the use of the pspicture environment in which I actually managed to use the calculated dimensions of the picture. Thanks again for your help.
– F...
Apr 28, 2018 at 19:41
• @F... That's really very interesting!! (But you could have achieved the same thing with a simple tabular environment and my proposal.)
– user121799
Apr 28, 2018 at 19:44
• I am certain of that. But my project is more complicated than this, in which every shape is connected to others into a big picture. I posted here just the little part concerning the container. But, even if I succeeded in doing it, I keep in mind your idea of using nodes in case of my approach doesn't work for the whole project. Thanks again for your advices.
– F...
Apr 28, 2018 at 20:02
• @F... No worries. (But note that, unlike tikzpictures, you can nest pspictures, i.e. have pictures inside pictures. That is, you could put, say, one of the tables in, say, some \rnode of a bigger psicture...)
– user121799
Apr 28, 2018 at 20:07
• Oh, I didn't know that. Great feature ! Many ideas come to me now for the next steps...
– F...
Apr 28, 2018 at 20:12