3

I'm using the packages

\usepackage{algpseudocode}
\usepackage{algorithm}

to produce a pseudocode of the following algorithm:

\begin{algorithm}
    \centering
    \caption{Octree based search algorithm}
    \label{alg:octree-search}
    {\small
      \begin{algorithmic}
\Function{octree-search}{node=root, point, squaredDistance, nearestPoint=distant point}
  \For{octants of node}
    \State get subNode
    \State pointSphere = sphere around point using squaredDistance 
    \If{subNode has child nodes}
      \State subNodeBox = Axis Aligned Bound Box (subNode)
      \If{subNodeBox overlaps with pointSphere} 
        \State \Call{octree-search}{subNode, point, squaredDistance, nearestPoint}
      \EndIf
    \ElsIf{subNode is a leaf node}
      \State leafNodeBox = Axis Aligned Bounding Box (node)
      \If{leafNodeBox overlaps with pointSphere} 
        \State minimalPoint = distant point 
        \For{shape in node shapes}
          \State distanceToShape, shapePoint = \Call{signed distance}{shape, point}
          \If{$\|\text{distanceToShape}\| < \|\text{minimalDistance}\|$}
            \State minimalPoint = shapePoint 
          \EndIf
        \EndFor
        \State nearestPoint = minimalPoint \Comment return point of the recursive search 
      \EndIf 
    \EndIf
  \EndFor
\EndFunction
      \end{algorithmic}
    }
\end{algorithm}

And I'm using \small as the algorithm font size. Unfortunately, the page width causes problems and introduces line breaks like this:

enter image description here

As the whole point of the pseudocode (and clean code in general) is to use sensible names (for example squaredDistance in stead of sqD), I would like to re-format the output generated by the algpseudocode, for the function declaration so that it looks like this:

function OCTREE-SEARCH(
     node = root, 
     point, 
     squaredDistance,
     nearestPoint = distant point
)

without the ugly looking line break.

Programming side-note

I'm aware that the functions should ideally be monadic/diadic, but I'm interfacing my code with legacy code at this point and I cannot change the function signature. Reducing the argument number is therefore not an option.

Edit

Also, can the large horizontal space that comes before the Comment be somehow shortened?

1

1 Answer 1

5
+50

The following example shows how to add line breaks to the function definition. This is done with a new pair of commands, \FunctionTwo and \EndFunctionTwo, analogous to \Function and \EndFunction, respectively. In this solution, each parameter must be preceded by a \State command which acts as a manual line break.

\documentclass{article}
\usepackage{algpseudocode}
\usepackage{algorithm}
\usepackage{amsmath}
\usepackage{calc}
\usepackage{suffix}
\algblockdefx[funcDef]{funcStart}{funcEnd}[1]{\algorithmicfunction\ \textproc{#1}(}{)}
\algblockdefx[funcStarDef]{funcStarStart}{funcStarEnd}[1]{\textproc{#1}(}{)}
\algblockdefx[funcTwo]{funcTwoStart}{EndFunctionTwo}{\vspace{-\baselineskip}}{\algorithmicend\ \algorithmicfunction}
\newcommand{\FunctionTwo}[2]{\funcStart{#1} #2 \funcEnd \funcTwoStart }
\newlength{\skipamount}
\newcommand{\CallTwo}[3][]{%
\setlength{\skipamount}{\widthof{#1\textproc{#2}(}}%
#1\textproc{#2}(#3)}
\newcommand{\StateTwo}{\State \hspace{\skipamount}}
\WithSuffix\newcommand\CallTwo*[2]{\funcStarStart{#1} #2 \funcStarEnd }
\WithSuffix\newcommand\FunctionTwo*[2]{\State \CallTwo[\algorithmicfunction\ ]{#1}{#2} \funcTwoStart }
\WithSuffix\newcommand\EndFunctionTwo*{\EndFunctionTwo}

\begin{document}
\begin{algorithm}
    \centering
    \caption{Octree based search algorithm}
    \label{alg:octree-search}
    {\small
      \begin{algorithmic}
\FunctionTwo{octree-search}{\State node=root, \State point, \State squaredDistance, \State nearestPoint=distant point}
  \For{octants of node}
    \State get subNode
    \State pointSphere = sphere around point using squaredDistance 
    \If{subNode has child nodes}
      \State subNodeBox = Axis Aligned Bound Box (subNode)
      \If{subNodeBox overlaps with pointSphere} 
        \State \Call{octree-search}{subNode, point, squaredDistance, nearestPoint}
      \EndIf
    \ElsIf{subNode is a leaf node}
      \State leafNodeBox = Axis Aligned Bounding Box (node)
      \If{leafNodeBox overlaps with pointSphere} 
        \State minimalPoint = distant point 
        \For{shape in node shapes}
          \State distanceToShape, shapePoint = \Call{signed distance}{shape, point}
          \If{$\|\text{distanceToShape}\| < \|\text{minimalDistance}\|$}
            \State minimalPoint = shapePoint 
          \EndIf
        \EndFor
        \State nearestPoint = minimalPoint \Comment return point of the recursive search 
      \EndIf 
    \EndIf
  \EndFor
\EndFunctionTwo
      \end{algorithmic}
    }
\end{algorithm}

\begin{algorithm}
    \centering
    \caption{Alternative formatting}
    \label{alg:octree-search2}
    {\small
      \begin{algorithmic}
\FunctionTwo*{octree-search}{node=root, \StateTwo point, \StateTwo squaredDistance, \StateTwo nearestPoint=distant point}
\State \CallTwo{octree-search}{subNode, point, \StateTwo squaredDistance, nearestPoint}
\State \CallTwo{octree-search}{subNode, \StateTwo point, \StateTwo squaredDistance, \StateTwo nearestPoint}
\CallTwo*{octree-search}{\State subNode, \State point, \State squaredDistance, \State nearestPoint}
\EndFunctionTwo*
      \end{algorithmic}
    }
\end{algorithm}

\end{document}

With the line breaks added to the function definition, the whole algorithm looks like this: Output of example code, part 1

The second picture shows alternative formatting choices for calls and function definitions. See the example code. Note that \CallTwo with \StateTwo cannot be nested in general. This is because only one variable, \skipamount, is used for the indentation level. This answer was a useful resource for me. Output of example code, part 2

Space before comment

The \Comment command seems to justify the comment text to the right. If there is a lot of space available and the comment text is short, this will leave a wide gap between the code line and the comment. One solution to reducing the gap is to pretend that the comment text requires more space than it actually does:

\State nearestPoint = minimalPoint \Comment \makebox[\width + 1cm][l]{return point of the recursive search}

This line would close the gap by one centimetre. Here one must experimentally find a suitable padding length. This answer by Werner is about length arithmetics with the calc package, as used in my example.

2
  • Thanks! I didnt' know that I have to explicitly klick on the bounty button. I did it just now. Thanks again for the nice answer!
    – tmaric
    Commented Jun 11, 2014 at 14:13
  • 1
    You're welcome. I think the bounty would have gone to me even without an explicit click, as you had already marked my answer as accepted. tex.stackexchange.com/help/bounty
    – mvkorpel
    Commented Jun 11, 2014 at 14:20

You must log in to answer this question.

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