<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">% \iffalse meta-comment
%
% Copyright (C) 2014 by Christoph Bersch &lt;usenet@bersch.net&gt;
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008/05/04 or later.
% \fi
%
% \iffalse
%&lt;*driver&gt;
\ProvidesFile{pst-intersect.dtx}
%&lt;/driver&gt;
%&lt;stylefile&gt;\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%&lt;stylefile&gt;\ProvidesPackage{pst-intersect}
%&lt;*stylefile&gt;
    [2014/03/16 v0.4 package wrapper for pst-intersect.tex]
%&lt;/stylefile&gt;
%
%&lt;*driver&gt;
\documentclass[a4paper, DIV=9, oneside, toc=index, parskip=half-]{scrreprt}
\usepackage{scrhack}
\usepackage{doc}
\setcounter{IndexColumns}{2}
\usepackage[utf8]{inputenc} 
\usepackage[T1]{fontenc}
\usepackage{lmodern} 
\usepackage{amsmath, marvosym} 
\usepackage{bera}
\providecommand*\mainlang{}
\usepackage[ngerman, english,\mainlang]{babel}
\usepackage{prettyref}
\usepackage[dvipsnames,x11names,svgnames]{xcolor}
\usepackage{ragged2e, calc}
\newlength{\PITcaptionmargin}
\newlength{\PITcaptionheight}
\usepackage[labelfont={color=DOrange}, 
            singlelinecheck=false, 
            justification=raggedright]{caption} 
\DeclareCaptionFormat{pitnocaption}{%
  \setlength{\PITcaptionmargin}{\widthof{#1}+7pt}%
  \setlength{\PITcaptionheight}{\heightof{#1}+3pt}%
  \hspace*{-\PITcaptionmargin}#1\par\vspace*{-\PITcaptionheight}%
}%
\DeclareCaptionFormat{pitcaption}{%
  \setlength{\PITcaptionmargin}{\widthof{#1}+7pt}%
  \hspace*{-\PITcaptionmargin}#1#2#3\par
}%
\captionsetup[lstlisting]{format=pitnocaption}
\usepackage{multido}
\usepackage{pst-intersect}
\usepackage[makeindex]{splitidx}
\usepackage{hypdoc}
\hypersetup{%
  colorlinks=true, 
  urlcolor=DOrange, 
  linkcolor=pdflinkcolor, 
  breaklinks,
  linktocpage=true} 
\usepackage{breakurl}
\definecolor{DOrange}{rgb}{1,.4,.2}%
\definecolor{DDOrange}{rgb}{0.7, 0.23, 0.07}%
\colorlet{pdflinkcolor}{DOrange}
\usepackage{showexpl}
\makeatletter\renewcommand*\SX@Info{}\makeatother
\usepackage{etoolbox}
\undef{\cs}\undef{\cmd}
\usepackage{ltxdockit}
\definecolor{colKeys}{rgb}{0,0,0}
\definecolor{colIdentifier}{rgb}{0,0,0}
\colorlet{colComments}{green!60!black}
\definecolor{colString}{rgb}{0,0.5,0}
\newlength{\codeoverhang}
\setlength{\codeoverhang}{0.5\marginparwidth+\marginparsep}
\lstset{%
  language=[LaTeX]TeX, identifierstyle=\color{colIdentifier},
  keywordstyle=\color{colKeys},
  keywordstyle = [21]\color{DOrange},
  keywordstyle = [22]\color{DOrange},
  stringstyle=\color{colString},
  commentstyle=\color{colComments},
  alsoletter={12},
  float=hbp,
  basicstyle=\ttfamily\small,
  columns=flexible,
  tabsize=4,
  showspaces=false,
  showstringspaces=false,
  breaklines=true,
  breakautoindent=true,
  breakatwhitespace=true,
  captionpos=t,
  belowcaptionskip=0pt,
  abovecaptionskip=0pt,
  xleftmargin=1em,
  prebreak = {\raisebox{-0.5ex}[\ht\strutbox]{\kern0.5ex\large\Righttorque}},
  rulecolor=\color{black!20}, 
  texcsstyle = [20]\color{DDOrange},
  moretexcs = [20]{pssavebezier, pssavepath, pstracecurve, psintersect},
  explpreset={%
    pos=l, width=-99pt, hsep=5mm, overhang=\codeoverhang, varwidth,
    vsep=\bigskipamount, rframe={}}, extendedchars=true
}%
\lstdefinestyle{example}{explpreset={%
    escapechar=*, pos=l, width=-99pt, hsep=5mm, overhang=\codeoverhang,
    varwidth, vsep=\bigskipamount, rframe={}}}
\makeatletter
\providecommand\ON{%
  \gdef\lst@alloverstyle##1{\textcolor{black!50}{\strut##1}%
}}
\providecommand\OFF{\xdef\lst@alloverstyle##1{##1}}
\makeatother
\colorlet{sectioncolor}{DOrange}
\addtokomafont{sectioning}{\color{sectioncolor}}
\usepackage[automark,nouppercase]{scrpage2}
\pagestyle{scrheadings}
\clearscrheadings
\clearscrplain
\ohead{\pagemark}
\ihead{\headmark}
\ofoot[\pagemark]{}
\automark[subsection]{section}
\setheadsepline{.4pt}[\color{DOrange}]
\setheadwidth[0pt]{text}
\setfootwidth[0pt]{text}
\makeatletter
\patchcmd{\l@chapter}{1.5em}{2em}{}{}
\renewcommand*\l@section{\bprot@dottedtocline{1}{1.5em}{3.0em}}
\renewcommand*\l@subsection{\bprot@dottedtocline{2}{3.8em}{4.0em}}
\newrobustcmd*{\fnurl}[1][]{\hyper@normalise\ltd@fnurl{#1}}
\def\ltd@fnurl#1#2{\footnote{#1\hyper@linkurl{\Hurl{#2}}{#2}}}
\newrobustcmd*{\arxivurl}[1]{\href{http://arxiv.org/abs/#1}{arXiv:#1}}
\newrobustcmd*{\doiurl}[1]{\href{http://dx.doi.org/#1}{DOI:#1}}
\makeatother
\usepackage{csquotes}
\MakeAutoQuote{Â«}{Â»}
%^^A spot is used in ltxdockit.sty
\colorlet{spot}{sectioncolor}
%^^A Fonts definitions used in ltxdockit.sty
\renewcommand*{\verbatimfont}{\ttfamily}
\renewcommand*{\displayverbfont}{\ttfamily}
\renewcommand*{\marglistfont}{\spotcolor\sffamily\small}
\renewcommand*{\margnotefont}{\sffamily\small}
\renewcommand*{\optionlistfont}{\spotcolor\sffamily\displayverbfont}
\renewcommand*{\ltxsyntaxfont}{\ttfamily}
\renewcommand*{\ltxsyntaxlabelfont}{\spotcolor\displayverbfont}
\renewcommand*{\changelogfont}{\normalfont}
\renewcommand*{\changeloglabelfont}{\spotcolor\sffamily\bfseries}

\makeatletter
\renewenvironment*{ltxsyntax}
  {\list{}{%
     \setlength{\labelwidth}{\marglistwidth}%
     \setlength{\labelsep}{0pt}%
     \setlength{\leftmargin}{0pt}%
     \renewcommand*{\makelabel}[1]{%
       \hss\ltxsyntaxfont\ltxsyntaxlabelfont##1}}%
   \let\cmditem\PIT@cmditem}
  {\endlist}

\def\ltd@optionlist{%
  \let\optitem\PIT@optitem
  \let\valitem\PIT@valitem
  \let\choitem\PIT@choitem
  \let\boolitem\PIT@boolitem
  \let\intitem\PIT@intitem
  \let\numitem\PIT@numitem
  \let\psnumitem\PIT@psnumitem
  \let\pititem\ltd@item
  \let\typeitem\PIT@typeitem}

\def\PIT@typeitem#1#2{%
  \item[{#1}]%
  \label{prm:#1}%
  \begingroup\raggedright
  #2%
  \settowidth\@tempdimb{\prm{psstyle}}%
  \settowidth\@tempdimc{#1}%
  \@tempdimc=\dimexpr\@tempdimc+\labelsep-\labelwidth\relax
  \ifdim\@tempdimc&gt;0pt%
    \@tempdima=\dimexpr\linewidth-\@tempdimb-\@tempdimc-1em\relax
  \else
    \@tempdima=\dimexpr\linewidth-\@tempdimb-1em\relax
  \fi
  \par\endgroup}

\def\PIT@option#1#2#3{%
  \item[#1]%
  \begingroup\raggedright
  \ltd@textverb{=}%
  \settowidth\@tempdimb{\ltd@textverb{=}}%
  \settowidth\@tempdimc{#1}%
  \@tempdimc=\dimexpr\labelwidth-\@tempdimc\relax
  \ifdim\@tempdimc&lt;0pt
    \@tempdima=\dimexpr\linewidth-\@tempdimb+\@tempdimc-2em\relax
  \else
    \@tempdima=\dimexpr\linewidth-\@tempdimb-2em\relax
  \fi
  \ifblank{#3}
    {}
    {\settowidth\@tempdimb{default: #3}%
     \@tempdima=\dimexpr\@tempdima-\@tempdimb-2em\relax}%
  \parbox[t]{\@tempdima}{\raggedright #2}%
  \ifblank{#3}
    {}
    {\hfill default:~#3}%
  \par\endgroup
  \nobreak\vspace{\itemsep}}

\def\PIT@optitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@optitem@i}
    {\booltrue{@tempswa}\PIT@optitem@i}}
\newcommand*{\PIT@optitem@i}[3][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{#3}{}}
    {\PIT@option{#2}{#3}{\ltd@textverb{#1}}}}%

\def\PIT@valitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@valitem@i}
    {\booltrue{@tempswa}\PIT@valitem@i}}
\newcommand*{\PIT@valitem@i}[3][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\prm{#3}}{}}
    {\PIT@option{#2}{\prm{#3}}{\ltd@textverb{#1}}}}%

\def\PIT@choitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@choitem@i}
    {\booltrue{@tempswa}\PIT@choitem@i}}
\newcommand*{\PIT@choitem@i}[3][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\ltd@verblist{#3}}{}}
    {\PIT@option{#2}{\ltd@verblist{#3}}{\ltd@textverb{#1}}}}%

\def\PIT@boolitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@boolitem@i}
    {\booltrue{@tempswa}\PIT@boolitem@i}}
\newcommand*{\PIT@boolitem@i}[2][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\ltd@verblist{true,false}}{}}
    {\PIT@option{#2}{\ltd@verblist{true,false}}{\ltd@textverb{#1}}}}%

\def\PIT@intitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@intitem@i}
    {\booltrue{@tempswa}\PIT@intitem@i}}
\newcommand*{\PIT@intitem@i}[2][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\prm{int}}{}}
    {\PIT@option{#2}{\prm{int}}{\ltd@textverb{#1}}}}%

\def\PIT@numitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@numitem@i}
    {\booltrue{@tempswa}\PIT@numitem@i}}
\newcommand*{\PIT@numitem@i}[2][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\prm{num}}{}}
    {\PIT@option{#2}{\prm{num}}{\ltd@textverb{#1}}}}%

\def\PIT@psnumitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@psnumitem@i}
    {\booltrue{@tempswa}\PIT@psnumitem@i}}
\newcommand*{\PIT@psnumitem@i}[2][]{%
  \ifbool{@tempswa}%
    {\label{prm:#2}\xdefLkeyword{#2}}%
    {\xLkeyword{#2}}%
  \ifblank{#1}
    {\PIT@option{#2}{\prm{psnum}}{}}
    {\PIT@option{#2}{\prm{psnum}}{\ltd@textverb{#1}}}}%

\def\ltd@csitem{%
  \@ifstar
    {\boolfalse{@tempswa}\ltd@csitem@i}
    {\booltrue{@tempswa}\ltd@csitem@i}}
\def\ltd@csitem@i#1{%
  \ifbool{@tempswa}
    {\ltd@item@ii{\textbackslash#1\hspace\marglistsep}{#1}}
    {\ltd@item@ii{\textbackslash#1\hspace\marglistsep}{}}}

\def\PIT@cmditem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@cmditem@i}
    {\booltrue{@tempswa}\PIT@cmditem@i}}
\def\PIT@cmditem@i#1{%
  \ifbool{@tempswa}
    {\PIT@cmditem@ii{\textbackslash#1}{cs:#1}}
    {\PIT@cmditem@ii{\textbackslash#1}{}}}
\def\PIT@compitem{%
  \@ifstar
    {\boolfalse{@tempswa}\PIT@compitem@i}
    {\booltrue{@tempswa}\PIT@compitem@i}}
\def\PIT@compitem@i#1{%
  \ifbool{@tempswa}
    {\PIT@cmditem@ii{\textbackslash#1}{comp:#1}}
    {\PIT@cmditem@ii{\textbackslash#1}{}}}
\def\PIT@cmditem@ii#1#2{%
  \ltd@itemsave
  \ifhmode
    \itemsep-\topsep
  \else
    \ltd@itembreak
  \fi
  \item[#1]%
  \ltd@itemrest
  \ifblank{#2}{}{\label{#2}}%
  \begingroup
  \ltd@syntaxsetup
  \ltxsyntaxfont
  \let\@tempa\@empty
  \ltd@parseargs}

\def\ltd@csitem@ii#1#2{%
  \ltd@itemsave
  \ifhmode
    \itemsep-\topsep
  \else
    \ltd@itembreak
  \fi
  \item[#1]%
  \ltd@itemrest
  \ifblank{#2}{}{\label{cs:#2}}%
  \begingroup
  \ltd@syntaxsetup
  \ltxsyntaxfont
  \let\@tempa\@empty
  \ltd@parseargs}


\let\plainllap\llap
\newrobustcmd\macro@llap[1]{{\global\let\llap\plainllap
 \setbox0=\hbox\bgroup \macro@font\small\saved@macroname\egroup
 \ifdim\wd0&gt;30mm
    \hbox to\z@ \bgroup\hss \hbox to30mm{\unhcopy0\hss}\egroup
    \edef\@tempa{\hskip\dimexpr\the\wd0-30mm}\global\everypar\expandafter{\the\expandafter\everypar
                                                                           \@tempa \global\everypar{}}%
 \else \llap{\unhbox0}\fi}}
 \AtBeginEnvironment{macro}{\let\llap\macro@llap}
\makeatother

\newcommand*{\PSstring}[1]{{\normalfont\small\ttfamily(#1)}}
\newcommand*{\PSarray}[1]{{\normalfont\small\ttfamily[#1]}}
\newcommand*{\PSname}[1]{{\normalfont\small\ttfamily/#1}}
\newcommand*{\PSproc}[1]{{\normalfont\small\ttfamily\textbraceleft #1\textbraceright}}
\newcommand*{\PSvar}[1]{{\normalfont\small\ttfamily #1}}
\newcommand*{\PSop}[1]{{\normalfont\small\ttfamily\color{DOrange}\hskip 3pt #1\hskip 3pt}}

\newcommand*{\compref}[1]{\ref{comp:#1}}
\newcommand*{\hyperpagedef}[1]{\textbf{\hyperpage{#1}}}
\newcommand*{\nodename}[1]{\emph{#1}}
\newcommand*{\param}[1]{\normalfont\texttt{#1}}
\newcommand*{\paramvalue}[1]{\texttt{#1}}
\newcommand*{\styleshape}[1]{\texttt{#1}}
\newcommand{\docindex}[1]{\sindex[doc]{#1|hyperpage}}
\newcommand{\docindexdef}[1]{\sindex[doc]{#1|hyperpagedef}}
\makeatletter
\def\Lcs{\@ifstar{\Lcs@nobm}{\Lcs@bm}}
\def\Lcs@nobm#1{\nxLcs{#1}\xLcs{#1}}
\def\Lcs@bm#1{\hyperref[cs:#1]{\Lcs@nobm{#1}}}
\def\xLcs#1{}
\def\nxLcs#1{\texttt{\textbackslash#1}}

\def\Lcomp{\@ifstar{\Lcomp@nobm}{\Lcomp@bm}}
\def\Lcomp@nobm#1{\nxLcomp{#1}\xLcomp{#1}}
\def\Lcomp@bm#1{\hyperref[comp:#1]{\Lcomp@nobm{#1}}}
\def\xLcomp#1{}
\def\nxLcomp#1{\texttt{\textbackslash#1}}

\def\LPack#1{\nxLPack{#1}}
\def\nxLPack#1{\texttt{#1}}

\def\Lenv{\@ifstar{\Lenv@nobm}{\Lenv@bm}}
\def\Lenv@nobm#1{\nxLenv{#1}\xLenv{#1}}
\def\Lenv@bm#1{\hyperref[env:#1]{\Lenv@nobm{#1}}}
\def\xLenv#1{}
\def\nxLenv#1{\texttt{#1}}
\let\orig@ltd@envitem\ltd@envitem
\def\ltd@envitem#1{\orig@ltd@envitem{#1}\label{env:#1}\xLenv{#1}}

\def\Lkeyword{\@ifstar{\Lkeyword@nobm}{\Lkeyword@bm}}
\def\Lkeyword@nobm#1{\nxLkeyword{#1}\xLkeyword{#1}}
\def\Lkeyword@bm#1{\hyperref[prm:#1]{\Lkeyword@nobm{#1}}}
\def\xLkeyword#1{}
\def\xdefLkeyword#1{}
\def\nxLkeyword#1{\texttt{#1}}

\def\xLoption#1{}
\def\Loption#1{\texttt{#1}\xLoption{#1}}
\def\nxLoption#1{\texttt{#1}}

\def\Lstyle{\@ifstar{\Lstyle@nobm}{\Lstyle@bm}}
\def\Lstyle@nobm#1{\nxLstyle{#1}\xLstyle{#1}}
\def\Lstyle@bm#1{\hyperref[sty:#1]{\Lstyle@nobm{#1}}}
\def\xLstyle#1{}
\def\xdefLstyle#1{}
\def\nxLstyle#1{\texttt{#1}}

\makeatother

\newcommand{\dipoledesc}[1]{%
  \xLdipole{#1}%
  \compitem{#1}[options](in)(out){label}%
}
\newcommand{\tripoledesc}[1]{%
  \xLtripole{#1}%
  \compitem{#1}[options](in)(center)(out){label}%
}

\newcommand{\fiberdipoledesc}[1]{%
  \xLfdipole{#1}%
  \compitem{#1}[options](in)(out){label}%
}

\newenvironment*{pssyntax}
  {\list{}{\small
     \setlength{\labelsep}{0pt}%
     \setlength{\leftmargin}{10pt}%
     \item[]}}
  {\endlist}

\newcommand{\psarglistfont}{\small}
\newenvironment*{psarglist}
  {\list{}{%
     \setlength{\labelwidth}{10pt}%
     \setlength{\labelsep}{0pt}%
     \setlength{\leftmargin}{0pt}%
     \setlength{\itemsep}{\parsep}%
     \setlength{\parsep}{0pt}%
     \renewcommand*{\makelabel}[1]{\hss\psarglistfont##1}}}
  {\endlist}

\makeatletter
\renewenvironment{theglossary}{\GlossaryParms \let\item\@idxitem \ignorespaces}{}
\makeatother
\def\psargitem#1{\item[#1]\hfill\par\nobreak}

\addtopsstyle{Fiber}{linecolor=DOrange,linewidth=1.5\pslinewidth}
\addtopsstyle{Beam}{linewidth=1.5\pslinewidth}
\EnableCrossrefs
\CodelineIndex
\OnlyDescription
\begin{document}
  \DocInput{pst-intersect.dtx}
\end{document}
%&lt;/driver&gt;
% \fi
%
% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&amp;
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \&lt;
%   Equals        \=     Greater than  \&gt;     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \GetFileInfo{pst-intersect.dtx}
%
% \newif\ifGERMAN  \GERMANfalse
% \newif\ifENGLISH \ENGLISHfalse
% \iflanguage{ngerman}{\GERMANtrue}{%
%   \iflanguage{german}{\GERMANtrue}{\GERMANfalse}}
% \iflanguage{english}{\ENGLISHtrue}{\ENGLISHfalse}
%
% \ifGERMAN
%   \newrefformat{chap}{Kap.~\ref{#1}}
%   \newrefformat{sec}{Kap.~\ref{#1}}
%   \newrefformat{l}{Zeile~\ref{#1}}
%   \newrefformat{ex}{Bsp.~\ref{#1}}
%   \newrefformat{tab}{Tab.~\ref{#1}}
%   \newrefformat{fig}{Abb.~\ref{#1}}
%   \newindex[Quelltextindex]{idx}
%   \newcommand{\PITindexMacro}{Makros}
%   \newcommand{\PITindexKeyword}{Parameter}
%   \newcommand{\PITindexEnv}{Umgebungen}
%   \newcommand{\PITindexPack}{Pakete}
%   \renewcommand*\lstlistingname{Bsp.}
% \fi
% \ifENGLISH
%   \newrefformat{chap}{Sec.~\ref{#1}}
%   \newrefformat{sec}{Sec.~\ref{#1}} 
%   \newrefformat{l}{Line~\ref{#1}}
%   \newrefformat{ex}{Ex.~\ref{#1}}
%   \newrefformat{tab}{Tab.~\ref{#1}}
%   \newrefformat{fig}{Fig.~\ref{#1}}
%   \newindex[Code index]{idx}
%   \newcommand{\PITindexMacro}{macros}
%   \newcommand{\PITindexKeyword}{parameters}
%   \newcommand{\PITindexEnv}{environments}
%   \newcommand{\PITindexPack}{packages}
%   \renewcommand*\lstlistingname{Ex.}
% \fi
%
% \makeatletter
% \renewcommand\maketitle{^^A
% \thispagestyle{empty}^^A
% \begin{titlepage}
% \begin{pspicture}(1.6in,0.685in)(10,21.7)
%   \psframe[fillstyle=solid,linecolor=lightgray,fillcolor=lightgray,linestyle=solid](0,-5.75)(21.5,10)
%   \psframe[fillstyle=solid,linecolor=Orange!85!Red,fillcolor=Orange!85!Red,linestyle=solid](0,10)(21.5,10.5)
%   \psframe[fillstyle=solid,linecolor=Orange!85!Red,fillcolor=Orange!85!Red,linestyle=solid](0,21.1)(21.5,21.2)
%   \rput[lb](3,22){\Huge\sffamily\color{Orange!65!Red}\psscalebox{2}{\textbf{PSTricks}}}
%   \rput[lb](3,14.1){\parbox{15cm}{\sffamily\RaggedRight\bfseries\huge\@title}}
%   \rput[lb](3,7.6){\parbox{13cm}{\sffamily\@date}}
%   \rput[lb](3,-2.6){\parbox[b]{17cm}{\sffamily\RaggedRight 
%     ~\hfill\makebox[7cm][l]{\ifGERMAN Paketautor:\fi\ifENGLISH Package author:\fi}\\
%     ~\hfill\makebox[7cm][l]{^^A
%       \bfseries\tabular[t]{@{}l@{}}\@author\endtabular}}}
%  \rput[C](11,4){\bgImage}
%  \end{pspicture}^^A
% \end{titlepage}}
% \makeatother
% 
% \ifGERMAN
%   \title{\texttt{pst-intersect}\\ Berechnen der Schnittpunkte beliebiger Kurven\\[0.5ex] \small \fileversion}
%   \hypersetup{pdftitle={Berechnen der Schnittpunkte beliebiger Kurven}}
% \fi
% \ifENGLISH
%   \title{\texttt{pst-intersect}\\ Intersecting arbitrary curves\\[0.5ex] \small \fileversion}
%   \hypersetup{pdftitle={Intersecting arbitrary curves}}
% \fi
% \author{Christoph Bersch}
% \date{\filedate}
% \def\bgImage{}
%
% \maketitle
% 
% \clearpage
% \tableofcontents
% \clearpage
% 
% \ifGERMAN
%   \chapter{EinfÃ¼hrung}
% \fi
% \ifENGLISH
%   \chapter{Introduction}
% \fi
% 
% \ifGERMAN
%   \section{Ãœber das Paket}
%
%   \LPack{pst-intersect} ist ein PSTricks-Paket zur
%   Berechnung der Schnittpunkte von BÃ©zier-Kurven und beliebigen
%   Postscript-Pfaden.
%
%   Beachten Sie, dass die Paket-Versionen 0.x sich in einem
%   experimentellen Status befinden, und sich grundlegende Ã„nderungen
%   ergeben kÃ¶nnen, die zur VorgÃ¤ngerversion inkompatibel sind.
% \fi 
% \ifENGLISH
%   \section{About the package}
%   \LPack{pst-intersect} is a PSTricks package to calculate
%   the intersections of Bezier curves and arbitrary Postscript paths.
%
%   Please note, that package versions 0.x are experimental, and may be
%   subject to fundamental changes, which aren't backward compatible.
% \fi
%
% \ifGERMAN
%   \section{Anforderungen}
%   \LPack{pst-intersect} benÃ¶tigt aktuelle Versionen der Pakete
%   \LPack{pstricks}, \LPack{pst-node}, \LPack{pst-eucl} und
%   \LPack{pst-func}.
%
%   Alle PSTricks-Pakete machen regen Gebrauch von der Postscript-Sprache, so
%   dass der typische Arbeitsfluss \opt{latex}, \opt{dvips} und
%   ggf. \opt{ps2pdf} umfasst. Es gibt viele alternative Methoden um die
%   Dokumente zu
%   kompilieren.\fnurl{http://tug.org/PSTricks/main.cgi?file=pdf/pdfoutput}
% \fi
% \ifENGLISH
%   \section{Requirements}
%   \LPack{pst-intersect} requires recent versions of \LPack{pstricks},
%   \LPack{pst-node}, \LPack{pst-eucl} and \LPack{pst-func}.
%
%   All PSTricks package rely heavily on the Postscript language so that the
%   typical workflow involves \opt{latex}, \opt{dvips}, and \opt{ps2pdf}. Of
%   course there are several alternative ways to compile your
%   documents.\fnurl{http://tug.org/PSTricks/main.cgi?file=pdf/pdfoutput} 
% \fi
%
% \ifGERMAN
%   \section{Verbreitung und Installation}
%   Dieses Paket ist auf
%   CTAN\fnurl{http://mirror.ctan.org/help/Catalogue/entries/pst-intersect.html}
%   erhÃ¤ltlich.
% 
%   Das \LPack{pst-intersect}-Paket umfasst die zwei Hauptdateien
%   \texttt{pst-intersect.ins} und \texttt{pst-intersect.dtx}. Durch Aufrufen
%   von \texttt{tex pst-intersect.ins} werden die drei folgenden
%   Dateien erzeugt:
%   \begin{itemize}
%   \item \texttt{pst-intersect.pro}: die Postscript Prologdatei
%   \item \texttt{pst-intersect.sty}: die \LaTeX-Stildatei
%   \item \texttt{pst-intersect.tex}: die \TeX-Datei
%   \end{itemize}
%   Speichern Sie diese Dateien in einem Verzeichnis der Teil Ihres
%   lokalen \TeX-Baums ist.
% 
%   Vergessen Sie nicht \texttt{texhash} aufzurufen um den Baum zu
%   aktualisieren. MiK\TeX{}-Benutzer mÃ¼ssen die Dateinamen-Datenbank
%   (FNDB) aktualisieren.
% 
%   Detailliertere Information finden Sie in der Dokumentation Ihrer
%   \LaTeX-Distribution Ã¼ber die Installation in den lokalen
%   \TeX{}-Baum.
% \fi
% \ifENGLISH
%   \section{Distribution and installation}
%   This package is available on
%   CTAN\fnurl{http://mirror.ctan.org/help/Catalogue/entries/pst-intersect.html}.
% 
%   The \LPack{pst-intersect} package consists of the two main files
%   \texttt{pst-intersect.ins} and \texttt{pst-intersect.dtx}. By running \texttt{tex
%   pst-intersect.ins} the following derived files are generated:
%   \begin{itemize}
%   \item \texttt{pst-intersect.pro}: the Postscript prolog file
%   \item \texttt{pst-intersect.sty}: the \LaTeX{} style file
%   \item \texttt{pst-intersect.tex}: the \TeX{} file
%   \end{itemize}
%   Save the files in a directory which is part of your local \TeX{} tree.
% 
%   Do not forget to run \texttt{texhash} to update this tree. For MiK\TeX{}
%   users, do not forget to update the file name database (FNDB).
% 
%   For more detailed information see the documentation of your personal
%   \LaTeX{} distribution on installing packages to your local \TeX{}
%   system.
% \fi
%
% \ifGERMAN\section{Lizenz}\fi
% \ifENGLISH\section{License}\fi
% \ifGERMAN
% Es wird die Erlaubnis gewÃ¤hrt, dieses Dokument zu kopieren, zu verteilen
% und\slash oder zu modifizieren, unter den Bestimmungen der \LaTeX{} Project
% Public License, Version
% 1.3c.\fnurl{http://www.latex-project.org/lppl.txt}. Dieses
% Paket wird vom Autor betreut (author-maintained).
% \fi
% \ifENGLISH
% Permission is granted
% to copy, distribute and\slash or modify this software under the terms of the
% \LaTeX{} Project Public License, version
% 1.3c.\fnurl{http://www.latex-project.org/lppl.txt} This
% package is author-maintained.
% \fi
%
% \ifGERMAN
%   \section{Danksagung}
% \fi
% \ifENGLISH
%   \section{Acknowledgements}
% \fi
% \ifGERMAN
% Ich danke Marco Cecchetti, dessen
% \opt{lib2geom}-Bibliothek\fnurl{http://lib2geom.sourceforge.net/}
% mir als Vorlage fÃ¼r einen GroÃŸteil des Postscript-Kodes fÃ¼r den
% BÃ©zier-Clipping-Algorithmus diente. AuÃŸerdem gilt mein Dank William
% A. Casselman, fÃ¼r seine Erlaubnis, den Quicksort-Kode und den Kode zur
% Berechung der konvexen HÃ¼llen aus seinem Buch Â«Mathematical
% IllustrationÂ» verwenden zu
% dÃ¼rfen\fnurl{http://www.math.ubc.ca/~cass/graphics/text/www/}. Der
% Dokumentationsstil ist eine Mischung aus der \opt{pst-doc} Klasse
% (Herbert VoÃŸ) und dem \opt{ltxdockit} Paket fÃ¼r die \opt{biblatex}
% Dokumentation (Philipp Lehmann).
% \fi
% \ifENGLISH
% I thank Marco Cecchetti, for his
% \opt{lib2geom}-library\fnurl{http://lib2geom.sourceforge.net/} from
% which I derived great parts of the Postscript code for the BÃ©zier
% clipping algorithm. Also I want to thank William A. Casselman for the
% Postscript code of the quicksort procedure and the procedure for
% calculating the convex hull from his book Â«Mathematical
% IllustrationÂ»\fnurl{http://www.math.ubc.ca/~cass/graphics/text/www/},
% and the permission to use it. The documentation style is a mixture of
% the \opt{pst-doc} class (Herbert VoÃŸ) and the \opt{ltxdockit} package
% for the \opt{biblatex} documentation (Philipp Lehman).
% \fi
%
%
% \ifGERMAN
% \chapter{Benutzung}
% \fi
% \ifENGLISH
% \chapter{Usage}
% \fi
%
% \ifGERMAN
% Das \LPack{pst-intersect}-Paket kann Schnittpunkte von beliebigen
% Postscript-Pfaden berechnen. Diese setzen sich nur aus drei primitiven
% Operation zusammen: Linien (\opt{lineto}), BÃ©zier-Kurven dritter
% Ordnung (\opt{curveto}) und SprÃ¼ngen (\opt{moveto}). Speziellere
% Konstruktionen, wie z.B. Kreise werden intern zu
% \opt{curveto}-Anweisungen umgewandelt. Ãœber diese Kommandos hinaus
% kann \LPack{pst-intersect} auch BÃ©zier-Kurven bis neunter Ordnung
% verwenden. Das diese keine primitiven Postscript-Pfadelemente
% darstellen, mÃ¼ssen sie gesondert behandelt werden.
%
% Der allgemeine Arbeitsablauf besteht darin eine oder mehrere Kurven
% oder Pfade zu speichern, und danach die Schnittpunkte zu
% berechnen. AnschlieÃŸend kÃ¶nnen die Schnittpunkte als normale
% PSTricks-Knoten verwendet werden, oder Abschnitte der Kurven und Pfade
% nachgezogen werden (z.B. zwischen zwei Schnittpunkten). 
% \fi
% \ifENGLISH
% The \LPack{pst-intersect} package can compute the intersections of
% arbitrary Postscript paths. These are composed of three primitive
% operations: lines (\opt{lineto}), third order BÃ©zier curves
% (\opt{curveto}) and jumps (\opt{moveto}). More specialized
% constructions, like circles, are converted internally to \opt{curveto}
% operations. Besides these three path operations, the
% \LPack{pst-intersect} supports BÃ©zier curves up to nineth order. As
% these aren't primitive Postscript path elements, they require separate
% handling.
%
% The general workflow consists in defining and saving paths and curves,
% and then compute the intersections between them. Following, those
% intersection points can be used as normal PSTricks nodes, or portions
% of the curves and paths can be retraced (e.g. between two
% intersections).
% \fi
%
% \ifGERMAN
% \section{Speichern von Pfaden und Kurven}
% \fi
% \ifENGLISH
% \section{Saving paths and curves}
% \fi
%
% \ifGERMAN
% 
% \fi
%
% \begin{ltxsyntax}
%   \cmditem{pssavepath}[options]{curvename}{commands} 
%   
%   \ifGERMAN
%   Speichert den gesamten Pfad, der durch \prm{commands} erstellt wird,
%   unter Verwendung des Namens \prm{curvename}. Das Makro funktioniert
%   genauso wie \cs{pscustom}, und kann daher auch nur die darin
%   erlaubten Kommandos verarbeiten.
%
%   In den Standardeinstellungen wird der entsprechende Pfad auch gleich
%   gezeichnet, was mit \prm{options} beeinflusst werden kann. Mit
%   \opt{linestyle=none} wird das unterbunden.
%   \fi
%   \ifENGLISH
%   Saves the complete path, which is generated by \prm{commands}, under
%   the name \prm{curvename}. The macro is a modification of
%   \cs{pscustom}, and does, therefore, supports only the same commands.
%
%   By default, the path is also drawn, which can be changed over the
%   \prm{options}, e.g. with \opt{linestyle=none}.
%   \fi
% \end{ltxsyntax}
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(3,2)
  \pssavepath[linecolor=DOrange]{MyPath}{%
    \pscurve(0,2)(0,0.5)(3,1)
  }%
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \begin{ltxsyntax}
%   \cmditem{pssavebezier}[options]{curvename}($X_0$)\ldots(\prm{$X_n$})
%
%   \ifGERMAN 
%   Die Postscript-Sprache unterstÃ¼tzt nur BÃ©zier-Kurven dritter
%   Ordnung. Mit dem Makro \Lcs{pssavebezier} kÃ¶nnen BÃ©zier-Kurven
%   bis neunter Ordnung definiert werden. Die angegebenen Knoten sind die
%   Kontrollpunkte der Kurve, fÃ¼r eine Kurve $n$-ter Ordnung werden
%   $(n+1)$ Kontrollpunkte benÃ¶tigt. Die Darstellung der Kurve erfolgt
%   mit dem Makro \cs{psBezier} aus dem \LPack{pst-func}-Paket.
%   \fi
%   \ifENGLISH
%   The Postscript language supports only third-order BÃ©zier
%   curves. With the macro \Lcs{pssavebezier} you can define BÃ©zier
%   curves up to nineth order. The specified nodes are the control
%   points of the curve, for an $n$-th order curve $n+1$ control points
%   are required. The drawing of the curve is done with the
%   \cs{psBezier} macro from the \LPack{pst-func} package.
%   \fi
% \end{ltxsyntax}
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(3,2)
  \pssavebezier[showpoints]{MyBez}(0,0)(0,1)(1,2)(3,2)(1,0)(3,0)
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \ifGERMAN
% \section{Schnittpunkte berechnen}
% \fi
% \ifENGLISH
% \section{Calculating intersections}
% \fi
%
% \begin{ltxsyntax}
%   \cmditem{psintersect}{curveA}{curveB}
% 
%   \ifGERMAN
%   Nachdem Sie nun Pfade oder Kurven gespeichert haben, kÃ¶nnen Sie
%   deren Schnittpunkte berechnen. Das geschieht mit dem Makro
%   \Lcs{psintersect}. Dieses benÃ¶tigt als Argumente zwei Namen von
%   Pfaden oder Kurven (Das Argument \prm{curvename} der beiden
%   \cs{pssave*} Makros).
%   \fi
%   \ifENGLISH
%   After having saved some paths and curves, you can now calculate the
%   intersections. That is done with the \Lcs{psintersect} macro. This
%   needs as arguments two names of paths or curves (the \prm{curvename}
%   argument of the two \cs{pssave*} macros).
%   \fi
% \end{ltxsyntax}
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(3,2)
  \pssavepath[linecolor=DOrange]{MyPath}{\pscurve(0,2)(0,0.5)(3,1)}
  \pssavebezier{MyBez}(0,0)(0,1)(1,2)(3,2)(1,0)(3,0)
  \psintersect[showpoints]{MyPath}{MyBez}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \ifGERMAN
% Der PSTricks-Parameter \opt{showpoints} steuert dabei, ob die
% Schnittpunkte angezeigt werden.
% \fi
% \ifENGLISH
% The \opt{showpoints} PSTricks parameter determines, if the
% intersections are drawn directly. 
% \fi
%
% \begin{optionlist}
% \valitem[@tmp]{name}{string}
% \ifGERMAN
% Die berechneten Schnittpunkte kÃ¶nnen unter einem hier angegebenen
% Namen gespeichert und zu einem spÃ¤teren Zeitpunkt verwendet werden
% (siehe \prettyref{sec:pstracecurve-int}). 
% \fi
% \ifENGLISH
% The calculated intersections can be saved for later use under this
% name (see \prettyref{sec:pstracecurve-int}).
% \fi
%
% \boolitem[true]{saveintersections}
% \ifGERMAN
% Ist dieser Schalter gesetzt, dann werden die Schnittpunkte als
% PSTricks-Knoten unter den Namen \prm{name}1, \prm{name}2 \ldots
% gespeichert. Die Nummerierung erfolgt aufsteigend nach dem Wert der
% $x$-Koordinate.
% \fi
% \ifENGLISH
% If this option is set, the intersections are saved as PSTricks nodes
% with the names \prm{name}1, \prm{name}2 \ldots. The numbering is
% ascending according to the value of their $x$-coordinate.
% \fi
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(5,5)
  \pssavebezier[linecolor=DOrange]{A}%
             (0,0)(0,5)(5,5)(5,1)(1,1.5)
  \pssavebezier{B}(0,5)(0,0)(5,0)(5,5)(0,2)
  \psintersect[name=C, showpoints]{A}{B}
  \uput[150](C1){1}
  \uput[85](C2){2}
  \uput[90](C3){3}
  \uput[-20](C4){4}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
% \end{optionlist}
%
% \ifGERMAN
% \section{Darstellung gespeicherter Pfade}
% \fi
% \ifENGLISH
% \section{Visualization of saved paths}
% \fi
%
% \begin{ltxsyntax}
%   \cmditem{pstracecurve}[options]{curvename}
%
% \ifGERMAN
% Gespeicherte Pfade und Kurven kÃ¶nnen mit diesem Makro nachtrÃ¤glich
% gezeichnet werden.
% \fi
% \ifENGLISH
% Saved paths and curves can be drawn again with this macro.
% \fi
% \end{ltxsyntax}
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(2,2)
  \pssavepath{Circle}{\pscircle(1,1){1}}
  \pstracecurve[linestyle=dashed, linecolor=green]{Circle}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \begin{optionlist}
% \numitem{tstart}
% \numitem{tstop}
%
% \ifGERMAN Unter Verwendung dieser beiden Parameter kÃ¶nnen auch
% Abschnitte von Pfaden und Kurven gezeichnet werden. Bei BÃ©zier-Kurven
% ist der Parameterbereich $[0, 1]$, wobei $0$ dem Anfang der Kurve,
% also dem ersten bei \Lcs{pssavebezier} angegebenen Knoten entspricht.
% \fi
% \ifENGLISH
% With these parameters also parts of paths and curves can be drawn. For
% BÃ©zier curves the allowed range is $[0, 1]$, where $0$ corresponds to
% the start of the curve, which is given by the first node given to
% \Lcs{pssavebezier}.
% \fi
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(5,5)
  \psset{showpoints}
  \pssavebezier{B}(0,5)(0,0)(5,0)(5,5)(0,2)
  \pstracecurve[linestyle=dashed, linecolor=blue!50,
               tstart=0, tstop=0.5]{B}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \medskip
% \ifGERMAN 
% Pfaden kÃ¶nnen aus mehr als einem Abschnitt bestehen, der Bereich ist
% also $[0, n]$, wobei $n$ die Anzahl der Pfadabschnitte ist. Dabei ist
% zu beachten, dass z.B. \cs{pscurve}-Pfade oder auch Kreise und
% KreisbÃ¶gen aus mehreren Abschnitten bestehen.
% \fi
% \ifENGLISH
% Paths can be composed of more than one segmet, and the range is $[0,
% n]$, where $n$ is the number of path segments. For this you must keep
% in mind, that also e.g \cs{pscurve} paths, circles or arcs consist of
% several segments.
% \fi
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(2,2)
  \pssavepath[linestyle=none]{Circle}{\pscircle(1,1){1}}
  \pstracecurve[tstart=0, tstop=1, linecolor=green]{Circle}
  \pstracecurve[tstart=2, tstop=3, linecolor=red]{Circle}
  \pstracecurve[tstart=1.25, tstop=1.75, linecolor=blue]{Circle}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \end{optionlist}
%
% \ifGERMAN
% Beachten Sie, dass die Reihenfolge von \Lkeyword{tstart} und
% \Lkeyword{tstop} eine Rolle spielt. Ist \Lkeyword{tstart}
% \textgreater{} \Lkeyword{tstop} dann wird die Pfadrichtung umgekehrt.
% \fi
% \ifENGLISH
% Please note, that the order of \Lkeyword{tstart} and \Lkeyword{tstop}
% plays a role. For \Lkeyword{tstart} \textgreater{} \Lkeyword{tstop}
% the path direction is reversed.
% \fi
%
% \iffalse
%&lt;*ignore&gt;
% \fi
\begin{LTXexample}
\begin{pspicture}(2,2)
  \psset{arrows=-&gt;, arrowscale=1.5}
  \pssavepath[linestyle=dashed, linewidth=0.5\pslinewidth]{A}{\psline(0,0)(1,2)(2,0)}
  \pstracecurve[tstart=0.1, tstop=0.9]{A}
\end{pspicture}
\end{LTXexample}

\begin{LTXexample}
\begin{pspicture}(2,2)
  \psset{arrows=-&gt;, arrowscale=1.5}
  \pssavepath[linestyle=dashed, linewidth=0.5\pslinewidth]{A}{\psline(0,0)(1,2)(2,0)}
  \pstracecurve[tstart=0.9, tstop=0.1]{A}
\end{pspicture}
\end{LTXexample}
% \iffalse
%&lt;/ignore&gt;
% \fi
%
% \begin{ltxsyntax}
%   \cmditem{psGetCurvePoint}{curvename}{t}
%   
%   \ifGERMAN 
%   Speichert die Koordinaten der Kurve \prm{curvename} am Punkt \prm{t}.
%   \fi
%   \ifENGLISH
%   Save the coordinates of \prm{curvename} at the point \prm{t}.
%   \fi
% \end{ltxsyntax}
% \iffalse
%&lt;*ignore&gt;
% \fi
\begin{LTXexample}
\begin{pspicture}(3,3)
  \pssavebezier{A}(0,0)(0,3)(3,0)(3,3)
  \multido{\r=0+0.1}{11}{%
    \psdot(! \psGetCurvePoint{A}{\r} I-A.x I-A.y)}
\end{pspicture}
\end{LTXexample}
% \iffalse
%&lt;/ignore&gt;
% \fi
%
% \ifGERMAN
% \section{Darstellung gespeicherter Schnitte}
% \fi
% \ifENGLISH
% \section{Visualization of saved intersections}
% \fi
% \label{sec:pstracecurve-int}
%
% \begin{ltxsyntax}
% \cmditem*{pstracecurve}[options]{intersection}{curvename}
% \end{ltxsyntax}
% 
% \begin{optionlist}
% \numitem{istart}
% \numitem{istop}
%
% \ifGERMAN 
% Dieser beiden Parameter kÃ¶nnen auch verwendet werden um Abschnitte von
% Pfaden und Kurven zwischen Schnittpunkten zu zeichnen. Die
% Schnittpunkte werden dabei angefangen bei $1$ in aufsteigender
% Reihenfolge entlang der Kurve durchnummeriert.
% \fi
% \ifENGLISH
% These two parameters can be used to draw path or curve segments
% between intersections. The intersections are numbered starting at $1$
% in ascending order along the curve.
% \fi
% \end{optionlist}
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(5.2,5.2)
\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=-&gt;]{A}(0,0)(0,5)(5,2)(5,5)
\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=-&gt;]{B}(0,2.5)(2.5,2.5)(4.5, 3)(2,4)
\psintersect[linecolor=green!70!black, name=C]{A}{B}
\pstracecurve[linecolor=red, istart=1, istop=2]{C}{A}
\pstracecurve[linecolor=blue, istart=1, istop=2]{C}{B}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \ifGERMAN 
% Wird nur ein Wert angegeben, beispielsweise \Lkeyword{istop}, dann
% wird die Kurve vom Anfang bis zum entsprechenden Schnittpunkt
% gezeichnet. Wird nur \Lkeyword{istart} angegeben, dann endet die Kurve
% am Ende. Die Parameter \Lkeyword{istart} bzw. \Lkeyword{istop} kÃ¶nnen
% mit \Lkeyword{tstart} bzw. \Lkeyword{tstop} kombiniert werden.
% \fi
% \ifENGLISH
% If only one value is specified, e.g. \Lkeyword{istop}, the curve is
% drawn from the start to the respective intersection. If only
% \Lkeyword{istart} is given, the curve is drawn from this intersection
% to the curve end. The parameters \Lkeyword{istart} and
% \Lkeyword{istop} can be combined with \Lkeyword{tstart} and
% \Lkeyword{tstop}.
% \fi
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(5.2,5.2)
\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=-&gt;]{A}(0,0)(0,5)(5,2)(5,5)
\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=-&gt;]{B}(0,2.5)(2.5,2.5)(4.5, 3)(2,4)
\psintersect[linecolor=green!70!black, name=C]{A}{B}
\pstracecurve[linecolor=red, istop=2]{C}{A}
\pstracecurve[linecolor=blue, istart=1]{C}{B}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \begin{ltxsyntax}
%   \cmditem{psGetIsectCenter}{intersection}{curvename}{n}
%
%   \ifGERMAN 
%   LÃ¤dt die Koordinaten des $n$-ten Schnittpunkts des Pfades
%   \prm{curvename} in der Schnittmenge \prm{intersection}. Dabei
%   startet die Nummer der Schnittpunkte bei \prm{n}$=1$ und wird in
%   Pfadrichtung durchnummeriert.
%   \fi
%   \ifENGLISH
%   Loads the coordinates of the $n$-th intersection point of the path
%   \prm{curvename} in the intersection set \prm{intersection}. The
%   numbering of the intersections starts at \prm{n}$=1$ and the number
%   increases along the path in its original direction.
% \fi
% \end{ltxsyntax}
%
% \iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(4,5)
  \pssavebezier[linecolor=DOrange, arrows=-&gt;]{A}%
             (0,0)(0,5)(5,5)(5,1)(1,1.5)
  \pssavebezier[arrows=-&gt;]{B}(0,5)(0,0)(5,0)(5,5)(0,2)
  \psintersect[name=C, showpoints]{A}{B}
  \color{DOrange}
  \uput[150](!\psGetIsectCenter{C}{A}{1} I-C1.x I-C1.y){1}
  \uput[85](!\psGetIsectCenter{C}{A}{2} I-C2.x I-C2.y){2}
  \uput[-20](!\psGetIsectCenter{C}{A}{3} I-C3.x I-C3.y){3}
  \uput[90](!\psGetIsectCenter{C}{A}{4} I-C4.x I-C4.y){4}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
% 
% \ifGERMAN 
% Wenn kein Kurvenname \prm{curvename} angegeben wird, dann werden die
% Punkte nach aufsteigender $x$-Koordinate sortiert:
% \fi
% \ifENGLISH
% Without \prm{curvename} the points are sorted according to their
% $x$-coordinate:
% \fi
%
% \iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}
\begin{pspicture}(4,5)
  \pssavebezier[linecolor=DOrange, arrows=-&gt;]{A}%
             (0,0)(0,5)(5,5)(5,1)(1,1.5)
  \pssavebezier[arrows=-&gt;]{B}(0,5)(0,0)(5,0)(5,5)(0,2)
  \psintersect[name=C, showpoints]{A}{B}
  \uput[150](!\psGetIsectCenter{C}{}{1} I-C1.x I-C1.y){1}
  \uput[85](!\psGetIsectCenter{C}{}{2} I-C2.x I-C2.y){2}
  \uput[90](!\psGetIsectCenter{C}{}{3} I-C3.x I-C3.y){3}
  \uput[-20](!\psGetIsectCenter{C}{}{4} I-C4.x I-C4.y){4}
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi
%
% \ifGERMAN
% Die Schnittpunkte kÃ¶nnen auch mit \Lkeyword{saveintersections} und
% \opt{saveNodeCoors} geladen werden. Diese werden dann ebenfalls nach
% aufsteigender $x$-Koordinate nummeriert.
% \fi
% \ifENGLISH
% The intersection points can also be loaded with
% \Lkeyword{saveintersections} and \opt{saveNodeCoors}. In that case,
% the numbering of the intersection increases according to their $x$
% coordinate.
% \fi
%
% \ifGERMAN
% \chapter{Beispiele}
% \fi
% \ifENGLISH
% \chapter{Examples}
% \fi
%\iffalse
%&lt;*ignore&gt;
%\fi
\begin{LTXexample}[caption={caption}]
\begin{pspicture}(5,5)
  \pssavebezier{A}(0,0)(0,5)(5,5)(5,1)(1,1.5)
  \multido{\i=100+-20,\r=1+-0.2}{5}{%
    \pstracecurve[linecolor=red!\i, tstop=\r, arrows=-|, showpoints]{A}
  }%
\end{pspicture}
\end{LTXexample}
%\iffalse
%&lt;/ignore&gt;
%\fi 
%
%\iffalse
%&lt;*ignore&gt;
%\fi
\begingroup
\captionsetup[lstlisting]{format=pitcaption}
\begin{LTXexample}[pos=t, caption={%
\ifGERMAN Mit diesem Paket kÃ¶nnen auch die Schnittpunkte von
 Funktionen berechnet werden, die mit \cs{psplot} gezeichnet
 werden. Dabei ist zu beachten, dass beide einzelnen Kurven aus
 \opt{plotpoints} Abschnitten bestehen, von denen jeder mit jedem
 geschnitten wird, was zu langen Berechnungen fÃ¼hren kann.
 \fi
 \ifENGLISH
 The package can also calculate the intersections of functions which are
 drawn with \cs{psplot}. Here you must keep in mind, that such curves
 consists of \opt{plotpoints} segments, which must all be considered for
 intersections, what can result in long calculations.
 \fi}]
\begin{pspicture}(10,4.4)
  \pssavepath{A}{\psplot[plotpoints=200]{0}{10}{x 180 mul sin 1 add 2 mul}}
  \pssavepath{B}{\psplot[plotpoints=50]{0}{10}{2 x neg 0.5 mul exp 4 mul}}
  \psintersect[name=C, showpoints]{A}{B}
  \multido{\i=1+1}{5}{\uput[210](C\i){\i}}
  \multido{\i=6+2,\ii=7+2}{3}{\uput[225](C\i){\i}\uput[-45](C\ii){\ii}}
\end{pspicture}
\end{LTXexample}
\endgroup
%\iffalse
%&lt;/ignore&gt;
%\fi 
%
% \appendix
%
% \ifGERMAN
% \chapter{Versionsgeschichte}
%
% Diese Versionsgeschichte ist eine Liste von Ã„nderungen, die fÃ¼r den Nutzer des
% Pakets von Bedeutung sind. Ã„nderungen, die eher technischer Natur sind und fÃ¼r
% den Nutzer des Pakets nicht relevant sind und das Verhalten des Pakets nicht
% Ã¤ndern, werden nicht aufgefÃ¼hrt. Wenn ein Eintrag der Versionsgeschichte ein
% Feature als \emph{improved} oder \emph{extended} bekannt gibt, so bedeutet
% dies, dass eine Modifikation die Syntax und das Verhalten des Pakets nicht
% beeinflusst, oder das es fÃ¼r Ã¤ltere Versionen kompatibel ist. EintrÃ¤ge, die
% als \emph{deprecated}, \emph{modified}, \emph{renamed}, oder \emph{removed}
% deklariert sind, verlangen besondere Aufmerksamkeit. Diese bedeuten, dass eine
% Modifikation Ã„nderungen in existierenden Dokumenten mit sich ziehen kann. 
% \fi
% \ifENGLISH
% \chapter{Revision history}
%
% This revision history is a list of changes relevant to users of this
% package. Changes of a more technical nature which do not affect the
% user interface or the behavior of the package are not included in the
% list. If an entry in the revision history states that a feature has
% been \emph{improved} or \emph{extended}, this indicates a modification
% which either does not affect the syntax and behavior of the package or
% is syntactically backwards compatible (such as the addition of an
% optional argument to an existing command). Entries stating that a
% feature has been \emph{deprecated}, \emph{modified}, \emph{fixed},
% \emph{renamed}, or \emph{removed} demand attention. They indicate a
% modification which may require changes to existing documents.
% \fi
% 
% \begin{changelog}
%   \patchcmd{\release}{\setlength{\itemsep}{0pt}}{\setlength{\itemsep}{0pt}\setlength{\parsep}{0pt}}{}{}
%   \begin{release}{0.4}{2014-03-16}
%   \item Added \cs{psGetCurvePoint}.
%   \item Fixed \cs{pstracecurve} for use with \cs{pscustom}.
%   \item Fixed arrow behavior.
%   \end{release}
%   \begin{release}{0.3}{2014-03-04}
%   \item Fixed \cs{psGetIsectNode} to work with more than one segment.
%   \item Modified \cs{psGetIsectNode} and the naming conventions of the
%     variables.
%   \item Fixed missing support for \opt{pst-node}'s \opt{saveNodeCoors}
%     parameter to \opt{saveintersections}.
%   \end{release}
%   \begin{release}{0.2}{2014-02-26}
%   \item Added support for \opt{arrows} parameter to \cs{pstracecurve}.
%   \item Modified parameters \opt{tstart}, \opt{tstop}, \opt{istart}
%     and \opt{istop} to respect different directions.
%   \item Added \cs{psGetIsectCenter}
%   \item Fixed a bug in the termination of the iteration procedure.
%   \item Fixed a bug in the point order of BÃ©zier curves, which was
%     related to a now fixed bug in \opt{pst-func}.
%   \item Several other improvements.
%   \end{release}
%   \begin{release}{0.1}{2014-02-19}
%   \item First CTAN version
%   \end{release}
% \end{changelog}
% 
% \StopEventually{}
%
%   \begin{otherlanguage}{english}
%    \printindex[idx]
%  \end{otherlanguage}
%
% \chapter{The \LaTeX\ wrapper}
%&lt;*stylefile&gt;
%    \begin{macrocode}
\RequirePackage{pstricks}
\RequirePackage{pst-xkey}
\RequirePackage{pst-node}
\RequirePackage{pst-func}
\input{pst-intersect.tex}
\IfFileExists{pst-intersect.pro}{%
    \ProvidesFile{pst-intersect.pro}
      [2014/03/16 PostScript prologue file]
      \@addtofilelist{pst-intersect.pro}}{}%
%    \end{macrocode}
%&lt;/stylefile&gt;
%
% \chapter{The \TeX\ implementation}
%
%&lt;*texfile&gt;
%    \begin{macrocode}
\csname PSTintersectLoaded\endcsname
\let\PSTintersectLoaded\endinput

\ifx\PSTricksLoaded\endinput\else\input pstricks.tex \fi
\ifx\PSTXKeyLoaded\endinput\else \input pst-xkey.tex \fi
\ifx\PSTnodesLoaded\endinput\else\input pst-node.tex \fi
\ifx\PSTfuncLoaded\endinput\else \input pst-func.tex \fi

\edef\PstAtCode{\the\catcode`\@} \catcode`\@=11\relax

\pst@addfams{intersect}
\pstheader{pst-intersect.pro}

\def\pst@intersectdict{tx@IntersectDict begin }
\def\PIT@dict#1{\pst@intersectdict #1 end}
\def\PIT@Verb#1{\pst@Verb{\PIT@dict{#1} }}%
%    \end{macrocode}
% \section{The parameter definitions}
%    \begin{macrocode}
\define@key[psset]{intersect}{tstart}{%
  \pst@checknum{#1}\PIT@key@tstart
}
\define@key[psset]{intersect}{tstop}{%
  \pst@checknum{#1}\PIT@key@tstop
}
\define@key[psset]{intersect}{istart}{%
  \pst@checknum{#1}\PIT@key@istart
}
\define@key[psset]{intersect}{istop}{%
  \pst@checknum{#1}\PIT@key@istop
}
\define@key[psset]{intersect}{name}{%
  \def\PIT@key@name{#1}%
}%
\newif\PIT@saveintersections
\define@boolkey[psset]{intersect}[PIT@]{saveintersections}[true]{}
\newif\PIT@addintersections
\define@boolkey[psset]{intersect}[PIT@]{addintersections}[true]{}

\psset[intersect]{%
  tstart=-1,
  tstop=-1,
  istart=-1,
  istop=-1,
  name={},
  saveintersections,
  addintersections=false
}%
%    \end{macrocode}
% 
% \begin{macro}{\PIT@use@pscode}
%   This is a modified version of the \cs{use@pscode} core macro. It
%   explicitely allows the content of the stack to be moved outside the
%   local Postscript-scope created by the \cs{pstverb} macro. This
%   allows to save these values on the global level for later
%   use. Beware, that you cannot leave arrays or marks on the stack.
%    \begin{macrocode}
\def\PIT@use@pscode{%
  \pstverb{%
    \pst@dict
    \tx@STP
    \pst@newpath
    \psk@origin
    \psk@swapaxes
    \pst@code
    end
    count /ocount exch def
  }%
  \gdef\pst@code{}%
}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\PIT@save@path}
%   Modified version of the \cs{pst@stroke} core macro, which puts the
%   whole current path on the stack.
%    \begin{macrocode}
\let\PIT@pst@stroke@orig\pst@stroke
\def\PIT@save@path{%
  \PIT@pst@stroke@orig
  \addto@pscode{%
    clear mark
    \pst@intersectdict GetFullPath end
    counttomark 1 add -1 roll pop count }%
}%
%    \end{macrocode}
% \end{macro}
% 
%    \begin{macrocode}
\def\PIT@name@default{@tmp}%
\def\PIT@name#1{PIT@#1}%
\def\PIT@checkname#1{%
  \ifx\@empty#1\@empty
    \@pstrickserr{Unexpected empty argument!}\@ehpb
  \fi
}%
%    \end{macrocode}
%
% \begin{macro}{\pssavebezier}
%    \begin{macrocode}
\def\pssavebezier{\pst@object{pssavebezier}}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pssavebezier@i}
% Process all nodes following the \cs{pssavebezier} macro call.
%    \begin{macrocode}
\def\pssavebezier@i#1{%
  \begin@OpenObj
    \PIT@checkname{#1}%
    \addto@pscode{ /\PIT@name{#1} }%
    \pst@getcoors[\pssavebezier@ii%]
}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pssavebezier@ii}
% This does the whole actual work.
%    \begin{macrocode}
\def\pssavebezier@ii{%
  \addto@pscode{%
%    \end{macrocode}
% only 10 points allowed, remove the rest
%    \begin{macrocode}
    counttomark 20 gt { counttomark 20 sub { pop } repeat } if
    counttomark 2 idiv 1 sub
    \psk@plotpoints\space exch
    \txFunc@BezierCurve
    \ifshowpoints \txFunc@BezierShowPoints \else pop \fi
    tx@FuncDict begin Points aload pop end
  }%
  \let\use@pscode\PIT@use@pscode
  \end@OpenObj
  \PIT@Verb{%
    [ count 1 sub 1 roll ] ArrayToPointArray def 
  }%
\ignorespaces}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pssavepath}
%    \begin{macrocode}
\def\pssavepath{\pst@object{pssavepath}}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pssavepath@i}
%    \begin{macrocode}
\long\def\pssavepath@i#1#2{%
  \begin@SpecialObj
    \PIT@checkname{#1}%
    \let\pst@stroke\PIT@save@path
    \let\use@pscode\PIT@use@pscode
    \pscustom{#2}%
    \PIT@Verb{%
      /\PIT@name{#1}
      [ 3 -1 roll 2 add 2 roll ] def }%
  \end@SpecialObj
}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pstracecurve}
%    \begin{macrocode}
\def\pstracecurve{\pst@object{pstracecurve}}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\pstracecurve@i}
%    \begin{macrocode}
\def\pstracecurve@i#1{%
  \addbefore@par{plotpoints=200}%
  \begin@OpenObj
   \@ifnextchar\bgroup
     {\PIT@traceintersection{#1}}%
     {\PIT@tracecurve{#1}}%
}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\PIT@tracecurve}
%    \begin{macrocode}
\def\PIT@tracecurve#1{%
  \PIT@checkname{#1}%
  \addto@pscode{%
    \pst@intersectdict
    /\PIT@name{#1} currentdict exch known not {
      (You haven't defined the curve '#1') ==
    } if
    \PIT@name{#1} \PIT@key@tstart\space\PIT@key@tstop\space % [curve] tstart tstop
    {\psk@plotpoints exch
      \txFunc@BezierCurve
      \ifshowpoints \txFunc@BezierShowPoints \else pop \fi
    }
    TraceCurveOrPath
    end
  }%
  %\showpointsfalse
  \end@OpenObj
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{PIT@traceintersection}
%    \begin{macrocode}
\def\PIT@traceintersection#1#2{%
  \PIT@checkname{#2}%
  \addto@pscode{%
    \pst@intersectdict
    \ifx\\#1\\%
    /\PIT@name{\PIT@name@default}
    \else
    /\PIT@name{#1}
    \fi
    dup currentdict exch known not {
      \ifx\\#1\\%
      (You haven't defined an intersection!) ==
      \else
      (You haven't defined the intersection '#1') ==
      \fi
    } if 
    load
    dup dup type /dicttype eq exch /\PIT@name{#2} known and not {
      (You haven't defined the intersection '#2') ==
    } if
    dup /\PIT@name{#2} get
    exch /\PIT@name{#2}@t get
    dup length \PIT@key@istart\space ge 0 \PIT@key@istart\space lt and {
      dup \PIT@key@istart\space cvi 1 sub get
    } {
      \PIT@key@tstart
    } ifelse
    exch % [curve] t_istart|tstart [ts]
    dup length \PIT@key@istop\space ge 0 \PIT@key@istop\space lt and {
      \PIT@key@istop\space cvi 1 sub get
    } {
      pop \PIT@key@tstop
    } ifelse % [curve] tstart tstop
    {\psk@plotpoints exch
      \txFunc@BezierCurve
      \ifshowpoints \txFunc@BezierShowPoints \else pop \fi
    }
    TraceCurveOrPath
    end
  }%
  %\showpointsfalse
  \end@OpenObj
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psintersect}
%    \begin{macrocode}
\def\psintersect{\pst@object{psintersect}}
\def\psintersect@i#1#2{%
  \PIT@checkname{#1}%
  \PIT@checkname{#2}%
  \begin@SpecialObj
  \def\PIT@@name{%
    \ifx\PIT@key@name\@empty
      \PIT@name{\PIT@name@default}
    \else
      \PIT@name{\PIT@key@name} 
    \fi}%
  \PIT@Verb{%
    currentdict /\PIT@name{#1} known not {
      (You haven't defined the curve or path '#1') ==
    } if
    currentdict /\PIT@name{#2} known not {
      (You haven't defined the curve or path '#2') ==
    } if
    \PIT@name{#1} \PIT@name{#2}
    \PIT@name{#1} IsPath {
      \PIT@name{#2} IsPath {
        IntersectPaths
      }{
        IntersectPathCurve
      } ifelse
    }{
      \PIT@name{#2} IsPath {
        IntersectCurvePath
      }{
        IntersectBeziers
        4 copy LoadIntersectionPoints 5 1 roll
      } ifelse
    } ifelse
    /\PIT@name{#1} /\PIT@name{#2} /\PIT@@name
    \ifPIT@addintersections true \else false \fi
    SaveIntersection
  }%
  \ifPIT@saveintersections
    \pst@Verb{%
      \pst@intersectdict 
        \PIT@@name\space /Points get 
        ArrayToPointArray
      end
      dup length 1 1 3 -1 roll {
        2 copy 1 sub get 
        \ifPst@saveNodeCoors
          \pst@intersectdict 
          2 copy aload pop \tx@UserCoor 3 -1 roll 
          20 string cvs (N-\PIT@key@name) exch strcat dup 
          (.y) strcat cvn exch (.x) strcat cvn
          end
          4 -1 roll def exch def
        \fi
        cvx
        false 3 -1 roll (N@\PIT@key@name) exch 20 string cvs 
        \pst@intersectdict strcat end cvn
        tx@NodeDict begin 
          10 {InitPnode} /NodeScale {} def NewNode
        end
      } for
      pop
    }%
  \fi
  \ifshowpoints
    \addto@pscode{%
      \pst@intersectdict
        [ \PIT@@name\space /Points get aload pop 
      end 
    }%
    \psdots@ii
  \else
    \end@SpecialObj
  \fi
}%
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\psGetIsectCenter}
%    \begin{macrocode}
\def\psGetIsectCenter#1#2#3{%
  \pst@intersectdict
  \ifx\\#2\\%
    \PIT@name{#1} /Points get dup #3 1 sub 2 mul get exch #3 2 mul 1 sub get
  \else
    \PIT@name{#1} /\PIT@name{#2@t} get #3 1 sub get 
    \PIT@name{#1} /\PIT@name{#2} get 
    dup IsPath {
      PreparePath dup length 1 sub 
      3 -1 roll dup dup
      cvi sub 4 1 roll
      cvi sub get
    } if
    PointArrayToArray
    tx@FuncDict begin 2 dict begin
      dup length 2 idiv 1 sub /BezierType exch def /Points exch def GetBezierCoor
    end end
  \fi
  end
  \tx@UserCoor /I-#1#3.y exch def /I-#1#3.x exch def
}%
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\psGetCurvePoint}
%    \begin{macrocode}
\def\psGetCurvePoint#1#2{%
  \pst@intersectdict
  currentdict /\PIT@name{#1} known not {
    (You haven't defined the curve or path '#1') ==
  } if
  #2 \PIT@name{#1} GetCurvePoint \tx@UserCoor
  end
  /I-#1.y exch def /I-#1.x exch def
}%
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
\catcode`\@=\PstAtCode\relax
%    \end{macrocode}
%&lt;/texfile&gt; 
%
% \chapter{The Postscript header file}
% \makeatletter
%^^A Copied this definition from doc.sty and changed it not to add a
%^^A backslash to the Postscript procedure name in the index.
% \def\SpecialIndex@#1#2{%
%    \@SpecialIndexHelper@#1\@nil
%    \def\@tempb{ }%
%    \ifcat \@tempb\@gtempa
%       \special@index{\quotechar\space\actualchar
%                      \string\verb\quotechar*\verbatimchar
%                      \quotechar\space\verbatimchar#2}%
%    \else
%      \def\@tempb##1##2\relax{\ifx\relax##2\relax
%           \def\@tempc{\special@index{\quotechar##1\actualchar
%                       \string\verb\quotechar*\verbatimchar
%                       \quotechar##1\verbatimchar#2}}%
%         \else
%           \def\@tempc{\special@index{##1##2\actualchar
%                        \string\verb\quotechar*\verbatimchar##1##2\verbatimchar#2}}%
%         \fi}%
%      \expandafter\@tempb\@gtempa\relax
%      \@tempc
%    \fi}
% \makeatother
%
%&lt;*prolog&gt;
%    \begin{macrocode}
/tx@IntersectDict 200 dict def
tx@IntersectDict begin
%    \end{macrocode}
% These are some helper procedures for vector operations.
%
% \begin{macro}{VecAdd}
% Addition of two vectors.
% \begin{pssyntax}
%   \PSvar{Xa Ya Xb Yb} \PSop{VecAdd} \PSvar{Xa+Xb Ya+Yb}
% \end{pssyntax}
%    \begin{macrocode}
/VecAdd {
    3 -1 roll add 3 1 roll add exch
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{VecSub}
% Subtraction of two vectors.
% \begin{pssyntax}
%   \PSvar{Xa Ya Xb Yb} \PSop{VecSub} \PSvar{Xa-Xb Ya-Yb}
% \end{pssyntax}
%    \begin{macrocode}
/VecSub {
    neg 3 -1 roll add 3 1 roll neg add exch
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{VecScale}
% Scale a vector by a factor \PSvar{fac}.
% \begin{pssyntax}
%   \PSvar{Xa Ya fac} \PSop{VecScale} \PSvar{fac}$\cdot$\PSvar{Xa} \PSvar{fac}$\cdot$\PSvar{Ya}
% \end{pssyntax}
%    \begin{macrocode}
/VecScale {
  dup 4 -1 roll mul 3 1 roll mul
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ToPnt}
%   Convert two numbers to a procedure holding the two values. This
%   representation is used to save coordinate values of nodes and vectors.
%   \begin{pssyntax}
%     \PSvar{X Y} \PSop{ToPnt} \PSarray{X Y}
%   \end{pssyntax}
%    \begin{macrocode}
/ToPnt {
    [ 3 1 roll ]
} bind def
%    \end{macrocode}
% \end{macro}
%
% \PSvar{MaxPrecision} gives the precision of the curve parameter t for the
% intersection. This shouldn't be lower than $10^{-6}$, because
% PostScript uses single precision.
%    \begin{macrocode}
/MaxPrecision 1e-6 def
%    \end{macrocode}
%
% \PSvar{Epsilon} gives the allowed relative error of the intersection point. 
%    \begin{macrocode}
/Epsilon 1e-4 def
%    \end{macrocode}
% 
% The threshold for curve subdivision, see below.
%    \begin{macrocode}
/MinClippedSizeThreshold 0.8 def
%    \end{macrocode}
%
% The predefined intervals for the subdivision of the curves.
%    \begin{macrocode}
/H1Interval [0 0.5] def
/H2Interval [0.5 MaxPrecision add 1] def
%    \end{macrocode}
% 
% \begin{macro}{IntersectBeziers}
%   The main procedure, which computes the intersection of two bezier
%   curves of arbitrary order.  This, and most of the following
%   procedures operate on curves, which are stored as arrays of points,
%   the points are also arrays with two elements -- \PSvar{X} and
%   \PSvar{Y}. A Bezier curve of $n$-th order is then givesn by
%   \PSarray{\PSarray{X0 Y0} \PSarray{X1 Y1} \ldots \PSarray{XN YN}}.
%
% \begin{pssyntax}
%   \PSarray{curveA} \PSarray{curveB} \PSop{IntersectBeziers} 
%   \PSarray{curveA} \PSarray{tA} \PSarray{curveB} \PSarray{tB}
% \end{pssyntax}
%    \begin{macrocode}
/IntersectBeziers {
  2 copy length 2 eq exch length 2 eq and {
    IntersectLineSegms
  }{ 
    2 copy [0 1] [0 1] IterateIntersection
  } ifelse
  3 -1 roll exch
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{IntersectLines}
% Intersect two lines.
%   \begin{pssyntax}
%     \PSarray{lineA} \PSarray{lineB} \PSop{IntersectLines}
%     \PSarray{lineA} \PSarray{lineB} \PSarray{tA} \PSarray{tB}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectLines {
  (IntersectLines) DebugBegin
  2 copy
  exch { aload pop } forall 5 -1 roll { aload pop } forall
  8 -2 roll 2 copy 10 4 roll 4 2 roll 2 copy 6 2 roll 10 2 roll
  VecSub
  6 2 roll 4 2 roll VecSub
  8 4 roll 4 2 roll VecSub 
%    \end{macrocode}
% X3-X4 Y3-Y4 X2-X1 Y2-Y1 X3-X1 Y3-Y1 % b1 b2 a1 a2 c1 c2
%    \begin{macrocode}
  6 copy 12 -4 roll 
  neg 4 -1 roll mul 3 1 roll mul add
  dup 0 eq {
%    \end{macrocode}
% no intersections
%    \begin{macrocode}
    9 { pop } repeat [] []
  } {
    dup 10 1 roll 5 1 roll
     4 -1 roll mul 3 1 roll mul sub exch div
     6 1 roll 4 -1 roll mul 3 1 roll mul sub exch div 
     [ exch ] exch [ exch ]
   } ifelse
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{IntersectLineSegms}
%   Intersect two line segments. This uses the output of
%   \PSop{IntersectLines} and checks if both line parameters are in the
%   range [0,1].
%   \begin{pssyntax}
%     \PSarray{lineA} \PSarray{lineB} \PSop{IntersectLineSegms}
%     \PSarray{lineA} \PSarray{lineB} \PSarray{tA} \PSarray{tB}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectLineSegms {
  IntersectLines
  dup length 0 eq not {
%    \end{macrocode}
% IntersectLines has found an intersection
%    \begin{macrocode}
    0 get exch 0 get
    2 copy 2 copy 0 ge exch 0 ge and 3 1 roll 1 le exch 1 le and and {
      [ exch ] exch [ exch ]
    } {
      pop pop [] []
    } ifelse
  } if
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{IntersectLineSegmLine}
%   Intersect a line segment with a line. This uses
%   \PSop{IntersectLines} and checks if the line parameter of the line
%   segment is in the range [0,1].
%   \begin{pssyntax}
%     \PSarray{lineA} \PSarray{lineSegmB} \PSop{IntersectLineLineSegm}
%     \PSarray{lineA} \PSarray{tA} \PSarray{lineSegmB} \PSarray{tB}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectLineLineSegm {
  tx@IntersectDict begin IntersectLines end
  dup length 0 eq not {
%    \end{macrocode}
% IntersectLines has found an intersection
%    \begin{macrocode}
    0 get dup dup 0 ge exch 1 le and {
      [ exch ]
    } {
      pop pop [] []
    } ifelse
  } if 
  3 -1 roll exch
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{IntersectLinePath}
%   Compute the first intersection of a line with a path. If an intersection was
%   found, also the respective path segment remains on the stack for
%   later computations.
%   \begin{pssyntax}
%     \PSarray{lineA} \PSarray{pathB} \PSop{IntersectLinePath}
%     \PSarray{segment} \PSvar{t} \PSarray{intersection}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectLinePath {
  (IntersectLinePath) DebugBegin
  3 dict begin
    PreparePath
%    \end{macrocode}
% First elongate lineA such, that it could intersect with any segment in pathB
%    \begin{macrocode}
    2 copy ElongateLine exch 3 -1 roll pop
    /isect [] def
    /t -1 def
    /n -1 def
    {
      /n n 1 add def
      2 copy IntersectBeziers
      dup 5 1 roll LoadIntersectionPoints
      dup length 0 gt {
%    \end{macrocode}
% one intersection found, clean up and exit
%    \begin{macrocode}
        /isect exch def
        0 get aload pop add 0.5 mul n add /t exch def
        exch pop
        exit
      } {
        pop pop pop
      } ifelse
    } forall
    t isect
  end
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ElongateLine}
%   Elongate \PSarray{line} to potentially intersect with every segment
%   in \PSarray{path}.
%   \begin{pssyntax}
%     \PSarray{lineA} \PSarray{path} \PSop{ElongateLine} \PSarray{lineA'}
%   \end{pssyntax}
%    \begin{macrocode}
/ElongateLine {
  exch { aload pop } forall
  4 2 roll 2 copy 6 2 roll
  VecSub 0 5 1 roll
  6 -1 roll {
%    \end{macrocode}
% 0 x0 y0 dx dy [segm\_i]
%    \begin{macrocode}
    {
      aload pop 
%    \end{macrocode}
% max x0 y0 dx dy P\_ij.x P\_ij.y
%    \begin{macrocode}
      6 2 roll 4 copy 10 4 roll
      6 2 roll VecSub 4 2 roll 
      tx@EcldDict begin Project end
      tx@Dict begin Pyth end
      6 -1 roll 2 copy
      gt { pop } { exch pop } ifelse
      5 1 roll
    } forall
  } forall
%    \end{macrocode}
% dmax x0 y0 dx dy
%    \begin{macrocode}
  % for a line
  5 -1 roll VecScale 4 copy VecSub ToPnt 5 1 roll VecAdd ToPnt ToPnt
  % for a ray
  %4 2 roll 2 copy ToPnt 6 1 roll 4 2 roll 5 -1 roll 1.1 mul VecScale VecAdd ToPnt ToPnt
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{IntersectPaths}
%   \begin{pssyntax}
%     \PSarray{pathA} \PSarray{pathB} \PSop{IntersectPaths}
%     \PSarray{intersections} \PSarray{pathA} \PSarray{tA} \PSarray{pathB} \PSarray{tB}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectPaths {
  (IntersectPaths) DebugBegin
  6 dict begin 
    2 copy exch PreparePath dup length /nA exch def 
    exch PreparePath dup length /nB exch def
    /isect [] def
    /tA [] def /tB [] def
    { % [pathA] [Bi]
      /nB nB 1 sub def
      exch dup 3 1 roll % [pathA] [Bi] [pathA]
      {
        /nA nA 1 sub def
        exch dup 3 1 roll % [pathA] [Bi] [Aj] [Bi]
        IntersectBeziers % [curveA] [tA] [curveB] [tB]
        4 copy LoadIntersectionPoints
        [ exch isect aload pop ] /isect exch def
        exch pop 3 -1 roll pop
        [ tB aload length 2 add -1 roll TArray { nB add } forall ] /tB exch def
        [ tA aload length 2 add -1 roll TArray { nA add } forall ] /tA exch def
      } forall
      pop % remove [Bi]
      dup length /nA exch def
    } forall
    pop % remove [pathA]
    [ isect { aload pop } forall ] 3 1 roll tA exch tB
  end
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{IntersectCurvePath}
%   \begin{pssyntax}
%     \PSarray{curveA} \PSarray{pathB} \PSop{IntersectCurvePath}
%     \PSarray{intersections} \PSarray{curveA} \PSarray{tA} \PSarray{pathB} \PSarray{tB}
%   \end{pssyntax}
%    \begin{macrocode}
/IntersectCurvePath {
  (IntersectCurvePath) DebugBegin
  6 dict begin 
    2 copy PreparePath dup length /n exch def
    /isect [] def
    /tA [] def /tB [] def
    {
      /n n 1 sub def
      exch dup 3 -1 roll
      IntersectBeziers 
      4 copy LoadIntersectionPoints
      [ exch isect aload pop ] /isect exch def
      pop 3 -1 roll pop
      [ tB aload length 2 add -1 roll TArray { n add } forall ] /tB exch def
      [ tA aload length 2 add -1 roll TArray aload pop ] /tA exch def
    } forall
    pop
    [ isect { aload pop } forall ] 3 1 roll tA exch tB
  end
  DebugEnd
} bind def
/IntersectPathCurve {
  exch IntersectCurvePath 4 2 roll
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{MergeAndSort}
%   Merge and sort two arrays. That may be point arrays or simple
%   arrays. Both arrays must be of the same type, but that is not
%   checked.
%    \begin{macrocode}
/MergeAndSortArrays {
  [ 3 1 roll aload pop counttomark -1 roll aload pop ]
  dup length 0 gt {
    dup dup 0 get type /arraytype eq {
      hulldict /comp get
    } {
      /lt
    } ifelse
    exch quicksort
  } if
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{SaveIntersection}
%   \begin{pssyntax}
%     \PSarray{intersectionpoints} \PSarray{A} \PSarray{tA} \PSarray{B} \PSarray{tB} 
%     \PSname{nameA} \PSname{nameB} \PSname{isectname} \PSvar{add?}
%     \PSop{SaveIntersection}
%   \end{pssyntax}
%    \begin{macrocode}
/SaveIntersection {
  (SaveIntersection) DebugBegin
  exch dup 3 1 roll % isectname add? isectname
  currentdict exch known and {
%    \end{macrocode}
% Want to add the new intersections to an existing intersection. Merge
% the new arrays with the existing ones and resort the \PSvar{Points}
% and \PSvar{\ldots @t} arrays.
%    \begin{macrocode}
    load begin % pnts A tA B tB /A /B
      dup currentdict exch known { % /nameB already saved.
        4 -1 roll pop % pnts A tA tB /A /B
        nametostr (@t) strcat cvn dup load 4 -1 roll 
        MergeAndSortArrays def
      } {
        dup 5 -1 roll def % pnts A tA B tB /A /B
        nametostr (@t) strcat cvn 3 -1 roll TArray def
      } ifelse % pnts A tA /A
      dup currentdict exch known { % /nameB already saved.
        3 -1 roll pop
        nametostr (@t) strcat cvn dup load 3 -1 roll 
        MergeAndSortArrays def
      } {
        dup 4 -1 roll def
        nametostr (@t) strcat cvn exch TArray def
      } ifelse
      /Points exch ArrayToPointArray Points ArrayToPointArray 
      MergeAndSortArrays PointArrayToArray def
    end
  } {
    4 dict dup 3 1 roll def
    begin
      dup 5 -1 roll def
      nametostr (@t) strcat cvn 3 -1 roll TArray def
      dup 4 -1 roll def
      nametostr (@t) strcat cvn exch TArray def
      /Points exch def
    end
  } ifelse
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{TArray}
%   The curve parameters \PSvar{t} as determined by
%   \PSvar{IntersectBeziers} are given in a special array
%   construct. \PSvar{TArray} creates a simple array with the
%   \PSvar{t}-values given in ascending order.
%
% \begin{pssyntax}
% \PSarray{\PSarray{t0a t0b} \ldots \PSvar{null}\ldots \PSvar{integer}}
% \PSop{TArray} \PSarray{t0 t1 \ldots tN}
% \end{pssyntax}
%    \begin{macrocode}
/TArray {
  dup length 0 gt {
    dup 0 get type /arraytype eq {
      [ exch
      { %dup type /nulltype eq { pop exit } if
  	aload pop add 0.5 mul
      } forall ]
    } if
    dup /lt exch quicksort
  } if
} bind def
%    \end{macrocode}
% \end{macro} 
% 
% We can save arbitrary paths using \PSvar{pathforall}. The saved path
% contains the commands \PSname{movetype}, \PSname{linetype} and
% \PSname{curvetype}. By default, these are defined as the respective
% original procedures.
%    \begin{macrocode}
/InitTracing {
  /movetype /moveto load def
  /linetype /lineto load def
  /curvetype /curveto load def
} bind def
%^^AInitTracing
/GetFullPath {
  (GetFullPath) DebugBegin
  { /movetype counttomark 3 roll }
  { /linetype counttomark 3 roll }
  { /curvetype counttomark 7 roll }{} pathforall 
  DebugEnd
} bind def
%    \end{macrocode}
% 
% \begin{macro}{ReversePath}
%    \begin{macrocode}
/ReversePath {
  gsave newpath
    [ exch aload pop InitTracing
    { counttomark 0 eq { exit } if
      load exec
    } loop
    reversepath
    GetFullPath ]         
  grestore
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ReverseCurve}
% Reverse direction of a bezier curve.
%   \begin{pssyntax}
%     \PSarray{\PSarray{X0 Y0} \ldots \PSarray{XN YN}}
%     \PSop{ReverseCurve} \PSarray{\PSarray{XN YN} \ldots \PSarray{X0 Y0}}
%   \end{pssyntax}
%    \begin{macrocode}
/ReverseCurve {
  PointArrayToArray aload pop % [ tstart tstop [ X0 Y0 X1 Y1...
  counttomark -2 4 { 2 roll } for ] ArrayToPointArray
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ReverseInterval}
%   \begin{pssyntax}
%     \PSarray{path} \PSvar{tstart} \PSvar{tstop} \PSop{ReverseInterval}
%     \PSarray{path} \PSvar{L-tstop} \PSvar{L-tstart}
%   \end{pssyntax}
%    \begin{macrocode}
/ReverseInterval {
  3 -1 roll dup 4 1 roll GetSegmentCount
  dup 4 1 roll exch sub 3 1 roll sub exch
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{UnifyInterval}
%   Unifies the interval \PSarray{tstart tstop}. If \PSvar{tstart} is
%   negative, 0 is used. If \PSvar{tstop} is negative, the curve length
%   is used. A too large \PSvar{tstop} is also truncated to the curve
%   length.
%   \begin{pssyntax}
%     \PSarray{curve} \PSvar{tstart tstop} \PSop{UnifyInterval}
%     \PSarray{curve} \PSvar{tstart' tstop}
%   \end{pssyntax}
%    \begin{macrocode}
/UnifyInterval {
  exch dup 0 lt { pop 0 } if exch
  3 -1 roll dup 4 1 roll GetSegmentCount
  2 copy exch dup 3 1 roll % [curve] tstart tstop cnt tstop cnt tstop 
  lt exch 0 lt or { exch } if pop % (tstop &lt; 0 | cnt &lt; tstop)
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{PreparePath}
% [ ... /movetype ... /linetype .../curvetype ]
%    \begin{macrocode}
/PreparePath {
  (PreparePath) DebugBegin
  [ exch aload pop
  {
    dup type /nametype eq not { exit } if
    dup /movetype eq {
      pop ToPnt /@mycp exch def
    } {
      dup /linetype eq {
        pop [ @mycp 4 2 roll 2 copy ToPnt /@mycp exch def ToPnt ]
      } {
        pop [ @mycp 8 2 roll 2 copy ToPnt /@mycp exch def
        ToPnt 5 1 roll ToPnt 4 1 roll ToPnt 3 1 roll ]
      } ifelse
      counttomark 1 roll	
    } ifelse
  } loop ]
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{GetSegmentCount}
%   Count the number of path or bezier curve segments. Bezier curves
%   always have the length 1, independent of their order. For paths,
%   only the \PSname{linetype} and \PSname{curvetype} segments are
%   counted.
%   \begin{pssyntax}
%     \PSarray{CurveOrPath} \PSop{GetSegmentCount} \PSvar{cnt}
%   \end{pssyntax}
% 
%    \begin{macrocode}
/GetSegmentCount {
  (GetSegmentCount) DebugBegin
  dup IsPath {
    [ exch aload pop 0
    {
      counttomark 1 eq { exit } if
      exch 
      dup /movetype eq {
        pop 3 1 roll pop pop
      }{
        dup /linetype eq {
          pop 1 add 3 1 roll pop pop
        }{
          pop 1 add 7 1 roll 6 { pop } repeat
        } ifelse
      } ifelse
    } loop
    exch pop
  } {
    % a Bezier curve is a single segment
    length 0 gt { 1 } { 0 } ifelse
  } ifelse
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{LoadLineIntersectionPoints}
% \begin{pssyntax}
% \PSarray{curve} \PSarray{t} \PSop{LoadLineIntersectionPoints}
% \PSarray{I0.x I0.y \ldots IN.x YN.x}
% \end{pssyntax}
%    \begin{macrocode}
/LoadLineIntersectionPoints {
  (LoadLineIntersectionPoints) DebugBegin
  exch [ exch { aload pop } forall ]
  tx@Dict begin tx@FuncDict begin 2 dict begin
    dup length 2 idiv 1 sub /BezierType exch def /Points exch def
    [ exch { GetBezierCoor } forall ]
  end end end
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{LoadCurveIntersectionPoints}
%   Load the intersection points. This loads the same intersection point
%   from both curves, and chooses the one with the lowest error.
% \begin{pssyntax}
% \PSarray{curveA} \PSarray{tA} \PSarray{curveB} \PSarray{tB} 
%  \PSop{LoadCurveIntersectionPoints}
% \PSarray{I0.x I0.y \ldots IN.x YN.x}
% \end{pssyntax}
%    \begin{macrocode}
/LoadCurveIntersectionPoints {
  (LoadCurveIntersectionPoints) DebugBegin
  2 {
    4 2 roll
    [ exch { aload pop } forall ]
    exch [ exch { aload pop } forall ]
  } repeat
%    \end{macrocode}
% [A0.x A0.y ... AM.x AM.y] [tA0a tA0b ... tAMa tAMb] [tB0a tB0b ... tBNa tBNb] [B0.x B0.y ... BN.x BN.y]
%    \begin{macrocode}
  tx@Dict begin tx@FuncDict begin 2 dict begin
    dup length 2 idiv 1 sub /BezierType exch def /Points exch def
      [ exch { GetBezierCoor } forall ]
    3 1 roll 
    dup length 2 idiv 1 sub /BezierType exch def /Points exch def
      [ exch { GetBezierCoor } forall ]
    end
%    \end{macrocode}
% [IB0.xa IB0.ya IB0.xb IB0.yb ... IBM.yb] [IA0.xa IA0.ya IA0.xb IA0.yb ... IAM.yb]
%    \begin{macrocode}
    2 {
      [ exch aload length 4 idiv {
        [ 5 1 roll ] counttomark 1 roll
      } repeat ]
      exch 
    } repeat
%    \end{macrocode}
% [[IB0.xa ...] ... [... IBM.yb]] [[IA0.xa IA0.ya IA0.xb IA0.yb] ...[IAM.xa ... IAM.yb]]
%    \begin{macrocode}
    2 {
      dup hulldict /comp get exch quicksort exch
    } repeat
    2 dict begin
      /B exch def /A exch def
      [ 0 1 A length 1 sub {
        dup A exch get exch B exch get % [IAi] [IBi]
        2 copy aload pop VecSub Pyth exch 
        aload pop VecSub Pyth lt { exch } if pop
        aload pop VecAdd 0.5 VecScale
      } for ]
    end
  end end
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{LoadIntersectionPoints}
%    \begin{macrocode}
/LoadIntersectionPoints {
  (LoadIntersectionPoints) DebugBegin
  4 copy pop exch pop length 2 eq exch length 2 eq and {
    pop pop LoadLineIntersectionPoints
  }{
    LoadCurveIntersectionPoints
  } ifelse
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{IterateIntersection}
% Iteration procedure to compute all intersections of CurveA and CurveB.
% This contains the
% 
% \begin{pssyntax}
% \PSarray{CurveA} \PSarray{CurveB} \PSarray{intervalA} \PSarray{intervalB}
% \PSop{IterateIntersection} \PSarray{domsA} \PSarray{domsB}
% \end{pssyntax}
%    \begin{macrocode}
/IterateIntersection {
    (IterateIntersection) DebugBegin
    12 dict begin
	/precision MaxPrecision def
        4 2 roll 2 copy 6 2 roll
        dup IsPath not { PointArrayToArray } if
        0 exch { dup type /nametype eq { pop }{ abs max} ifelse } forall
        exch dup IsPath not { PointArrayToArray } if
        { dup type /nametype eq { pop }{ abs max} ifelse } forall
        Epsilon mul /epsilon exch def
%    \end{macrocode}
% in order to limit recursion
%    \begin{macrocode}
        /counter 0 def
	/depth 0 def
	/domsA [] def
	/domsB [] def
	/domsA /domsB 6 2 roll _IterateIntersection
	domsB domsA
    end
    dup length 0 gt {
      TArraysRemoveDup
    } if
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{TArraysRemoveDup}
%    \begin{macrocode}
/TArraysRemoveDup {
  4 dict begin
    /tB exch def
    /tA exch def
    /j 0 def
    [ tA 0 get tB 0 get
    1 1 tA length 1 sub {
      /i exch def
      tA j get aload pop tA i get aload pop tx@Dict begin Pyth2 end MaxPrecision gt
      tB j get aload pop tB i get aload pop tx@Dict begin Pyth2 end MaxPrecision gt and {
        % keep the current parameter point
        /j i def
        tB i get tA i get
        counttomark 2 idiv 1 add 1 roll 
      } if
    } for
    counttomark 2 idiv 1 add [ exch 1 roll ] % [ ... [tB]
    counttomark 1 add 1 roll ] exch % [tA] [tB]
  end 
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{_IterateIntersection}
% This is the iteration part which is called recursively.
%
% \begin{pssyntax}
%   \PSname{domsA} \PSname{domsB} \PSarray{CurveA} \PSarray{CurveB}
%   \PSarray{domA} \PSarray{domB} \PSop{\_IterateIntersection}
% \end{pssyntax}
%    \begin{macrocode}
/_IterateIntersection {
    (_IterateIntersection) DebugBegin
    CloneVec /domB exch def
    CloneVec /domA exch def
    CloneCurve /CurveB exch def
    CloneCurve /CurveA exch def
    /iter 0 def
    /depth depth 1 add def
    /dom null def
    /counter counter 1 add def
    CheckIT {
	(&gt;&gt; curve subdivision performed: dom(A) = ) domA CurveToString strcat
	(, dom(B) = ) strcat domB CurveToString strcat ( &lt;&lt;) strcat ==
    } if
    CurveA IsConstant CurveB IsConstant and {
	CurveA MiddlePoint ToPnt
	CurveB MiddlePoint ToPnt AreNear {
	    domA domB 4 -1 roll exch PutInterval PutInterval
	} {
	    pop pop
	} ifelse
    }{
	counter 100 lt {
%    \end{macrocode}
% Use a loop to simulate some kind of return to exit at different positions.
%    \begin{macrocode}
	    {
		/iter iter 1 add def
		iter 100 lt
		domA Extent precision ge
		domB Extent precision ge or and not {
		    iter 100 ge {
			false 
		    } {
			CurveA MiddlePoint ToPnt
			CurveB MiddlePoint ToPnt AreNear {
			    domA domB true
			}{
			    false
			} ifelse
		    } ifelse
		    exit
		} if
%    \end{macrocode}
% iter &lt; 100 \&amp;\&amp; (dompA.extent() &gt;= precision || dompB.extent() &gt;= precision)
%    \begin{macrocode}
		CheckIT {
		    (counter: ) counter 20 string cvs strcat
		    (, iter: ) iter 20 string cvs strcat strcat
		    (, depth: ) depth 20 string cvs strcat strcat ==
		} if
		CurveA CurveB ClipCurve /dom exch def
	
		CheckIT {(dom : ) dom CurveToString strcat == } if		
		dom IsEmptyInterval {
		    CheckIT { (empty interval, exit) == } if
		    false exit
		} if
%    \end{macrocode}
% dom[0] &gt; dom[1], invalid.
%    \begin{macrocode}
		dom aload pop 2 copy min 3 1 roll max gt {
		    CheckIT {
			(dom[0] &gt; dom[1], invalid!) ==
		    } if
		    false exit
		} if

		domB dom MapTo /domB exch def
		CurveB dom Portion

		CurveB IsConstant CurveA IsConstant and {
		    CheckIT {
          		(both curves are constant: ) ==	
			(C1: [ ) CurveA { CurveToString ( ) strcat strcat } forall (]) strcat ==
			(C2: [ ) CurveB { CurveToString ( ) strcat strcat } forall (]) strcat ==
		    } if
		    CurveA MiddlePoint ToPnt
		    CurveB MiddlePoint ToPnt AreNear {
			domA domB true
		    } {
			false
		    } ifelse
		    exit
		} if
%    \end{macrocode}
% If we have clipped less than 20%, we need to subdivide the
% curve with the largest domain into two sub-curves.
%    \begin{macrocode} 
		dom Extent MinClippedSizeThreshold gt {
		    CheckIT {
			(clipped less than 20% : ) ==
			(angle(A) = ) CurveA dup length 1 sub get aload pop
				      CurveA 0 get aload pop VecSub
   				      exch 2 copy 0 eq exch 0 eq and {
					  pop pop (NaN)
				      } {
					  atan 20 string cvs
				      } ifelse strcat ==
		        (angle(B) = ) CurveB dup length 1 sub get aload pop
		                      CurveB 0 get aload pop VecSub
				      exch 2 copy 0 eq exch 0 eq and {
					  pop pop (NaN)
				      } {
					  atan 20 string cvs
				      } ifelse strcat ==
		        (dom : ) == dom == (domB :) == domB ==
		    } if
%    \end{macrocode}
% Leave those five values on the stack to revert to the current state after the recursive calls.
%    \begin{macrocode}
		    CurveA CurveB domA domB iter
     		    7 -2 roll 2 copy 9 2 roll 2 copy 
%    \end{macrocode}
% On the stack: /domsA /domsB CurveA CurveB domA domB iter /domsA /domsB /domsA /domsB
%    \begin{macrocode}
		    domA Extent domB Extent gt {
			CurveA CloneCurve dup H1Interval Portion % pC1
			CurveA CloneCurve dup H2Interval Portion % pC2
			domA H1Interval MapTo                    % dompC1
			domA H2Interval MapTo                    % dompC2
%    \end{macrocode}
% Need on the stack: /domsA /domsB pC2 CurveB dompC2 domB   /domsA /domsB pC1 CurveB dompC1 domB
%    \begin{macrocode}
			3 -1 roll exch % /domsA /domsB /domsA /domsB pC1 dompC1 pC2 dompC2
			CurveB exch domB 8 4 roll % /domsA /domsB pC2 CurveB dompC2 domB /domsA /domsB pC1 dompC1
			CurveB exch domB % /domsA /domsB pC2 CurveB dompC2 domB /domsA /domsB pC1 CurveB dompC1 domB
		    } {
			CurveB CloneCurve dup H1Interval Portion % pC1
			CurveB CloneCurve dup H2Interval Portion % pC2
			domB H1Interval MapTo                    % dompC1
			domB H2Interval MapTo                    % dompC2
%    \end{macrocode}
% Need on the stack: /domsB /domsA pC2 CurveA dompC2 domA   /domsB /domsA pC1 CurveA dompC1 domA
%    \begin{macrocode}
			8 -2 roll exch 8 2 roll 6 -2 roll exch 6 2 roll % /domsB /domsA /domsB /domsA pC1 pC2 dompC1 dompC2
			3 -1 roll exch % /domsB /domsA /domsB /domsA pC1 dompC1 pC2 dompC2
			CurveA exch domA 8 4 roll % /domsB /domsA pC2 CurveA dompC2 domA /domsB /domsA pC1 dompC1
			CurveA exch domA          % /domsB /domsA pC2 CurveA dompC2 domA /domsB /domsA pC1 CurveA dompC1 domA
		    } ifelse

		    _IterateIntersection
		    _IterateIntersection
%    \end{macrocode}		    
% Restore the state before the recursive calls.
%    \begin{macrocode}
		    /iter exch def
		    /domB exch def
		    /domA exch def
		    /CurveB exch def
		    /CurveA exch def
		    false exit
		} if
		CurveA CurveB /CurveA exch def /CurveB exch def
		domA domB /domA exch def /domB exch def
%    \end{macrocode}
% exchange /domsA and /domsB on the stack!
%    \begin{macrocode}
		exch
	    } loop	
%    \end{macrocode}
% boolean on stack
%    \begin{macrocode}
	    {
		4 -1 roll exch PutInterval PutInterval
		CheckIT {
		    (found an intersection ============================) ==
		} if
	    } { pop pop } ifelse
	} {
	    pop pop
	} ifelse
    } ifelse
    /depth depth 1 sub def
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{PutInterval}
%   Add a new interval \PSarray{newinterval} to the array stored in
%   \PSname{/Intervals}. The new interval is "cloned" before storing it.
% \begin{pssyntax}
% \PSname{Intervals} \PSarray{newinterval} \PSop{PutInterval}
% \end{pssyntax}
%    \begin{macrocode}
/PutInterval {
    CloneVec [ exch 3 -1 roll dup 4 1 roll load aload pop ] def
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{IsEmptyInterval}
% Check if an interval is empty, which is represented by a [1 0] interval.
% \begin{pssyntax}
% \PSarray{interval} \PSop{IsEmptyInterval} \PSvar{boolean}
% \end{pssyntax}
%    \begin{macrocode}
/IsEmptyInterval {
    aload pop 0 eq exch 1 eq and
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ToUnitInterval}
% Limit an interval \PSvar{a b} to the unit interval \PSarray{0 1}.
% \begin{pssyntax}
% \PSvar{a b} \PSop{ToUnitInterval} \PSarray{a|0 b|1}
% \end{pssyntax}
%    \begin{macrocode}
/ToUnitInterval {
    ToUnitRange exch ToUnitRange 2 copy gt {
	exch
    } if
    ToPnt
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{ToUnitRange}
% Limit a number to the range \PSarray{0 1}.
%    \begin{macrocode}
/ToUnitRange {
    dup 0 lt {
	pop 0
    }{
	dup 1 gt {
	    pop 1
	} if
    } ifelse
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{CloneCurve}
% Does a deep copy of the array \PSarray{Curve}. This also involved deep copies of the contained point arrays.
% \begin{pssyntax}
% \PSarray{Curve} \PSop{CloneCurve} \PSarray{newCurve}
% \end{pssyntax}
%    \begin{macrocode}
/CloneCurve {
    [ exch {
	CloneVec
    } forall ]
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{CloneVec}
% Does a deep copy of the vector \PSarray{X Y}
% \begin{pssyntax}
% \PSarray{X Y} \PSop{CloneVec} \PSarray{Xnew Ynew}
% \end{pssyntax}
%    \begin{macrocode}
/CloneVec {
    aload pop ToPnt
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{MapTo}
% Map the sub-interval \PSarray{I} in \PSarray{0 1} into the interval \PSarray{J}. Returns a new array.
% \begin{pssyntax}
% \PSarray{J} \PSarray{I} \PSop{MapTo} \PSarray{Jnew}
% \end{pssyntax}
%    \begin{macrocode}
/MapTo {
    (MapTo) DebugBegin
    exch aload 0 get 3 1 roll exch sub 2 copy % [I] J0 Jextent J0 Jextent
    5 -1 roll aload aload pop % J0 Jextent J0 Jextent I0 I1 I0 I1
    min 4 -1 roll mul % J0 Jextent J0 I0 I1 min(I0,I1)*Jextent
    4 -1 roll add [ exch % J0 Jextent I0 I1 [ J0new
    6 2 roll max mul add ]
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{Portion}
% Compute the portion of the Bezier curve \PSarray{CurveB} wrt the interval \PSarray{I}.
% \begin{pssyntax}
% \PSarray{CurveB} \PSarray{I} \PSop{Portion} \PSarray{CurvePartB}
% \end{pssyntax}
%    \begin{macrocode}
/Portion {
    (Portion) DebugBegin
    dup Min 0 eq { % [CurveB] [I]
	% I.min() == 0
	Max dup 1 eq {% [CurveB] I.max()
	    % I.max() == 1
	    pop pop	    
	} { % [CurveB] I.max()
	    LeftPortion
	} ifelse
    } { % [CurveB] [I]
	2 copy Min % [CurveB] [I] [CurveB] I.min()
	RightPortion
	dup Max 1 eq {
	    % I.max() == 1
	    pop pop
	} {% [CurveB] [I]
	    dup aload pop exch sub 1 3 -1 roll Min sub div % [CurveB] (I1-I0)/(1-I.min())
	    LeftPortion
	} ifelse
    } ifelse
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{LeftPortion}
%   Compute the portion of the Bezier curve \PSarray{CurveB} wrt the
%   interval \PSarray{0 t}.
% \begin{pssyntax}
% \PSarray{CurveB} \PSvar{t} \PSop{LeftPortion} \PSarray{CurvePartB}
% \end{pssyntax}
%    \begin{macrocode}
/LeftPortion {
    (LeftPortion) DebugBegin
    exch dup length 1 sub dup 4 1 roll % L-1 t [CurveB] L-1
    1 1 3 -1 roll { % L-1 t [CurveB] i
	4 -1 roll dup 5 1 roll % L-1 t [CurveB] i L-1
	-1 3 -1 roll % L-1 t [CurveB] L-1 -1 i
	{ % L-1 t [CurveB] j
	    2 copy 5 copy % L-1 t [CurveB] j [CurveB] j t [CurveB] j [CurveB] j 
	    1 sub get 3 1 roll get % L-1 t [CurveB] j [CurveB] j t B[j-1] B[j]
	    Lerp put pop % L-1 t [CurveB]
	} for
    } for
    pop pop pop
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{RightPortion}
%   Compute the portion of the Bezier curve \PSarray{CurveB} wrt the
%   interval \PSarray{t 1}.
% \begin{pssyntax}
% \PSarray{CurveB} \PSvar{t} \PSop{RightPortion} \PSarray{CurvePartB}
% \end{pssyntax}
%    \begin{macrocode}
/RightPortion {
    (RightPortion) DebugBegin
    exch dup length 1 sub dup 4 1 roll % L-1 t [CurveB] L-1
    1 1 3 -1 roll {% L-1 t [CurveB] i
	4 -1 roll dup 5 1 roll % L-1 t [CurveB] i L-1
	exch sub 0 1 3 -1 roll  % L-1 t [CurveB] 0 1 L-i-1
	{% L-1 t [CurveB] j
	    2 copy 5 copy
	    get 3 1 roll 1 add get Lerp put pop
	} for
    } for
    pop pop pop
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{Lerp}
% Given two points and a parameter \PSvar{t} $\in$ \PSarray{0 1}, return a point
% proportionally from \PSarray{A} to \PSarray{B} by \PSvar{t}. Akin to 1 degree Bezier.
% \begin{pssyntax}
% \PSvar{t} \PSarray{A} \PSarray{B} \PSop{Lerp} \PSarray{newpoint}
% \end{pssyntax}
%    \begin{macrocode}
/Lerp {
    (Lerp) DebugBegin
    3 -1 roll dup 1 exch sub 3 1 roll % [A] (1-t) [B] t
    exch aload pop 3 -1 roll VecScale % [A] (1-t) B.x*t B.y*t
    4 2 roll
    exch aload pop 3 -1 roll VecScale VecAdd ToPnt % [A.x*(1-t)+B.x*t A.y*(1-t)+B.y*t]
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{IsConstant}
% Test if all points of a curve are near to each other. This is used as termination criterium for the intersection procedure.
% \begin{pssyntax}
% \PSarray{Curve} \PSop{IsConstant} \PSvar{boolean}
% \end{pssyntax}
%    \begin{macrocode}
/IsConstant {
    aload length [ exch 1 roll ] true 3 1 roll
    {
	exch dup 4 1 roll
	AreNear and exch
    } forall
    pop
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{AreNear}
% Test if two points are near to each other.
% \begin{pssyntax}
% \PSarray{P1} \PSarray{P2} \PSop{AreNear} \PSvar{boolean}
% \end{pssyntax}
%    \begin{macrocode}
/AreNear {
    (AreNear) DebugBegin
    aload pop 3 -1 roll aload pop
    VecSub abs epsilon lt exch abs epsilon lt and
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{Min}
% Get the minimum value of the vector \PSarray{P}.
% \begin{pssyntax}
% \PSarray{P} \PSop{Min} \PSvar{minimum}
% \end{pssyntax}
%    \begin{macrocode}
/Min {
    aload pop min
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{Min}
% Get the maximum value of the vector \PSarray{P}.
% \begin{pssyntax}
% \PSarray{P} \PSop{Max} \PSvar{maximum}
% \end{pssyntax}
%    \begin{macrocode}
/Max {
    aload pop max
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{Min}
% Get the extent of the interval \PSarray{I}.
% \begin{pssyntax}
% \PSarray{I} \PSop{Extent} \PSvar{I1-I0}
% \end{pssyntax}
%    \begin{macrocode}
/Extent {
    aload pop exch sub
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{MiddlePoint}
% Compute the middle point of the first and last point of \PSarray{Curve}.
% \begin{pssyntax}
% \PSarray{Curve} \PSop{MiddlePoint} \PSvar{X Y}
% \end{pssyntax}
%    \begin{macrocode}
/MiddlePoint {
    dup dup length 1 sub get aload pop
    3 -1 roll 0 get aload pop
    VecAdd 0.5 VecScale
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{OrthogonalOrientationLine}
% \begin{pssyntax}
% \PSvar{MiddlePointA} \PSarray{CurveB} \PSop{OrthogonalOrientationLine} \PSvar{A B C}
% \end{pssyntax}
%    \begin{macrocode}
/OrthogonalOrientationLine {
    (OrthogonalOrientationLine) DebugBegin
    dup dup length 1 sub get aload pop 3 -1 roll 0 get aload pop VecSub
%    \end{macrocode}
% rotate by +90 degrees
%    \begin{macrocode}
    neg exch
    4 2 roll 2 copy 6 2 roll VecAdd
    ImplicitLine
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{PickOrientationLine}
%   Pick an orientation line for a Bezier curve. This uses the first
%   point and the lastmost point, which is not near to it.
% \begin{pssyntax}
% \PSarray{Curve} \PSop{PickOrientationLine} \PSvar{A B C}
% \end{pssyntax}
%    \begin{macrocode}
/PickOrientationLine {
    (PickOrientationLine) DebugBegin
    dup dup length 1 sub exch 0 get% [Curve] L-1 P0
    exch -1 1 {% [Curve] P0 i
	3 -1 roll dup 4 1 roll exch get % [Curve] P0 Pi
	2 copy AreNear {
	    pop
	} {
	    exit
	} ifelse
    } for
    3 -1 roll pop
    exch aload pop 3 -1 roll aload pop ImplicitLine
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{ImplicitLine}
% Compute the coefficients \PSvar{A}, \PSvar{B}, \PSvar{C} of the normalized implicit equation
% of the line which goes through the points \PSarray{Xi Yi} and \PSarray{Xj Yj}.
%
% \begin{pssyntax}
% \PSvar{Xi Yi Xj Yj} \PSop{ImplicitLine} \PSvar{A B C}
% \end{pssyntax}
%    \begin{macrocode}
/ImplicitLine {
    4 copy % Xi Yi Xj Yj Xi Yi Xj Yj
    3 -1 roll sub 7 1 roll sub 5 1 roll % Yj-Yi Xi-Xj Xi Yi Xj Yj
    % Yi*Xj - Xi*Yj
    4 -1 roll mul neg % Yj-Yi Xi-Xj Yi Xj -Yj*Xi
    3 1 roll mul add % Yj-Yi Xi-Xj Yi*Xj-Yj*Xi | l0 l1 l2
    3 1 roll 2 copy tx@Dict begin Pyth end dup dup % l2 l0 l1 L L L
    5 -1 roll exch % l2 l1 L L l0 L
    div 5 1 roll % l0/L l2 l1 L L
    3 1 roll div % l0/L l2 L l1/L
    3 1 roll div % l0/L l1/L l2/L
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{distance}
% Compute the distance of point \PSarray{X Y} from the implicit line given
% by $Ax + By + C = 0,\quad (A^2+B^2 = 1)$.
% \begin{pssyntax}
% \PSvar{X Y A B C} \PSop{distance} \PSvar{d}
% \end{pssyntax}
%    \begin{macrocode}
/distance {
    5 1 roll 3 -1 roll mul 3 1 roll mul add add
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ArrayToPointArray}
% \begin{pssyntax}
% \PSarray{A.x A.y ... N.x N.y} \PSop{ArrayToPointArray} \PSarray{\PSarray{A.x A.y} \ldots \PSarray{N.x N.y}}
% \end{pssyntax}
%    \begin{macrocode}
/ArrayToPointArray {
    aload length dup 2 idiv {
	3 1 roll [ 3 1 roll ] exch
	dup 1 sub 3 1 roll 1 roll
    } repeat 1 add [ exch 1 roll ]
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{PointArrayToArray}
% \begin{pssyntax}
% \PSarray{\PSarray{A.x A.y} \ldots \PSarray{N.x N.y}} \PSop{PointArrayToArray} \PSarray{A.x A.y ... N.x N.y}
% \end{pssyntax}
%    \begin{macrocode}
/PointArrayToArray {
    aload length dup {
	1 add dup 3 -1 roll aload pop 4 -1 roll 1 add 2 roll
    } repeat 1 add [ exch 1 roll ]
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{ClipCurve}
% Clip the Bezier curve B with respect to the Bezier curve A for
% individuating intersection points. The new parameter interval for the
% clipped curve is pushed on the stack.
% \begin{pssyntax}
% \PSarray{CurveA} \PSarray{CurveB} \PSop{ClipCurve} \PSarray{newinterval}
% \end{pssyntax}
%    \begin{macrocode}
/ClipCurve {
    (ClipCurve) DebugBegin
    4 dict begin 
    /CurveB exch def /CurveA exch def
    CurveA IsConstant {
    	CurveA MiddlePoint CurveB OrthogonalOrientationLine
    } {
	CurveA PickOrientationLine
    } ifelse
    CheckIT {
	3 copy exch 3 -1 roll (OrientationLine : )
	3 { exch 20 string cvs ( ) strcat strcat } repeat ==
    } if
    CurveA FatLineBounds
    CheckIT { dup (FatLineBounds : ) exch aload pop exch 20 string cvs (, ) strcat exch 20 string cvs strcat strcat == } if
    CurveB ClipCurveInterval
    end
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{FatLineBounds}
% Compute the boundary of the fat line given by \PSvar{A B C}
% \begin{pssyntax}
% \PSvar{A B C} \PSarray{Curve} \PSop{FatLineBounds} \PSvar{A B C} \PSarray{dmin dmax}
% \end{pssyntax}
%    \begin{macrocode}
/FatLineBounds {
    (FatLineBounds) DebugBegin
    /dmin 0 def /dmax 0 def
    { 
	4 copy aload pop 5 2 roll distance
	dup dmin lt { dup /dmin exch def } if
	dup dmax gt { dup /dmax exch def } if
	pop pop
    } forall
    [dmin dmax]
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{ClipCurveInterval}
%   Clip the Bezier curve wrt the fat line defined by the orientation
%   line (given by \PSvar{A B C}) and the interval range
%   \PSarray{bound}. The new parameter interval \PSarray{newinterval}
%   for the clipped curve is pushed on the stack.
% \begin{pssyntax}
% \PSvar{A B C} \PSarray{bound} \PSarray{curve} \PSop{ClipCurveInterval} \PSarray{newinterval}
% \end{pssyntax}
%    \begin{macrocode}
/ClipCurveInterval {
    (ClipCurveInterval) DebugBegin
    15 dict begin
    /curve exch def
    aload pop 2 copy min /boundMin exch def max /boundMax exch def
    [ 4 1 roll ] cvx /fatline exch def
    % number of sub-intervals
    /n curve length 1 sub def
    % distance curve control points
    /D n 1 add array def
    0 1 n { % i
	dup curve exch get aload pop % i Pi.x Pi.y
	fatline distance % distance d of Point i from the orientation line, on stack; i d
	exch dup n div % d i i/n
	[ exch 4 -1 roll ] % i [ i/n d ]
	D 3 1 roll put 
    } for
    D ConvexHull /D exch def
%    \end{macrocode}
% get the x-coordinate of the i-th point, i getX -&gt; D[i][X]
%    \begin{macrocode}
    /getX { D exch get 0 get } def
%    \end{macrocode}
% get the y-coordinate of the i-th point, i getY -&gt; D[i][Y]
%    \begin{macrocode}
    /getY { D exch get 1 get } def
    /tmin 1 def /tmax 0 def
    0 getY dup
    boundMin lt /plower exch def
    boundMax gt /phigher exch def
    plower phigher or not {
%    \end{macrocode}
% inside the fat line
%    \begin{macrocode}
	tmin 0 getX gt { /tmin 0 getX def } if
	tmax 0 getX lt { /tmax 0 getX def } if	
    } if
    1 1 D length 1 sub {
	/i exch def
	/clower i getY boundMin lt def
	/chigher i getY boundMax gt def
	clower chigher or not {
%    \end{macrocode}
% inside the fat line
%    \begin{macrocode}
	    tmin i getX gt { /tmin i getX def } if
	    tmax i getX lt { /tmax i getX def } if
	} if
	clower plower eq not {
%    \end{macrocode}
% cross the lower bound
%    \begin{macrocode}
	    boundMin i 1 sub i D Intersect % t on stack
	    dup tmin lt { dup /tmin exch def } if
	    dup tmax gt { dup /tmax exch def } if
	    pop 
	    /plower clower def
	} if
	chigher phigher eq not {
%    \end{macrocode}
% cross the upper bound
%    \begin{macrocode}
	    boundMax i 1 sub i D Intersect
	    dup tmin lt { dup /tmin exch def } if
	    dup tmax gt { dup /tmax exch def } if
	    pop 
	    /phigher chigher def
	} if
    } for
%    \end{macrocode}
% we have to test the closing segment for intersection
%    \begin{macrocode}
    /i D length 1 sub def
    /clower 0 getY boundMin lt def
    /chigher 0 getY boundMax gt def
    clower plower eq not {
%    \end{macrocode}
% cross the lower bound
%    \begin{macrocode}
	boundMin i 0 D Intersect
	dup tmin lt { dup /tmin exch def } if
	dup tmax gt { dup /tmax exch def } if
	pop
    } if
    chigher phigher eq not {
%    \end{macrocode}
% cross the lower bound
%    \begin{macrocode}
	boundMax i 0 D Intersect
	dup tmin lt { dup /tmin exch def } if
	dup tmax gt { dup /tmax exch def } if
	pop
    } if
    [tmin tmax]
    end
    DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{Intersect}
%   Get the x component of the intersection point between the line
%   passing through $i$-th and $j$-th points of \PSarray{Curve} and the
%   horizonal line through \PSvar{y}.
% \begin{pssyntax}
% \PSvar{y i j} \PSarray{Curve} \PSop{Intersect} \PSvar{Xisect}
% \end{pssyntax}
%    \begin{macrocode}
/Intersect {
    dup 4 -1 roll get aload pop
    4 2 roll exch get aload pop
%    \end{macrocode}
% On the stack: \PSvar{y Xi Yi Xj Yj}, Compute (Xj - Xi) * (y - Yi)/(Yj - Yi) + Xi
%
% We are sure, that Yi != Yj, because this procedure is called only
% when the lower or upper bound is crossed.
%    \begin{macrocode}
    4 2 roll 2 copy 6 2 roll VecSub
    5 2 roll
    neg 3 -1 roll add
    3 -1 roll div
    3 -1 roll mul add
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{IsPath}
%   Check if an array is a path. A path is represented as array, which
%   contains other arrays which represent native Postscript
%   operations. Those can be \PSarray{X Y /@m}, \PSarray{X Y /@l}, or
%   \PSarray{X1 Y1 X2 Y2 X3 Y3 /@c}.
%
%   \begin{pssyntax}
%     \PSarray{array} \PSop{IsPath} \PSvar{boolean}
%   \end{pssyntax}
%    \begin{macrocode}
/IsPath {
  dup length 1 sub get type /nametype eq { true } { false } ifelse
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{ShowPathPortion}
%   \begin{pssyntax}
%     \PSarray{path} \PSvar{tstart tstop} \PSop{ShowPathPortion}
%   \end{pssyntax}
%    \begin{macrocode}
/ShowPathPortion {
  (ShowPathPortion) DebugBegin
  8 dict begin
  /tstop exch def
  /tstart exch def
  /savecp { ToPnt cvx /@cp exch def } def
  InitTracing
  /n 0 def
  mark exch aload pop
  { 
    counttomark 0 eq n tstop ge or { cleartomark exit } if
    dup /movetype eq not { /n n 1 add def } if
    dup /movetype eq {
      pop savecp
    } {
      tstart n ge {
%    \end{macrocode}      
% current path section is before tstop
%    \begin{macrocode}
        /curvetype eq { 6 2 roll 4 { pop } repeat } if
        savecp
      } {
        tstart n 1 sub gt tstop n lt or {
%    \end{macrocode}
% draw a truncated segment
%    \begin{macrocode}
          tstart n sub 1 add tstop n sub 1 add
          ToUnitInterval exch
          /linetype eq {
            3 1 roll ToPnt 
            tstart n 1 sub gt { @cp ToPnt } { currentpoint ToPnt } ifelse exch ToPnt
            dup 3 -1 roll Portion
            aload pop exch 
            tstart n 1 sub gt { 
%    \end{macrocode}
% This is the start segment, move to the starting point, as it lies in the middle of the segment.
%    \begin{macrocode}
              exch aload pop 3 -1 roll aload pop ArrowA 
              tstop n le { 
%    \end{macrocode}
% only a single segment, draw also the ending arrow 
%    \begin{macrocode}
                currentpoint 4 2 roll ArrowB linetype pop pop
              } {
%    \end{macrocode}
% other segments to follow
%    \begin{macrocode}
                linetype
              } ifelse
            } { 
%    \end{macrocode}
% this is the last segment
%    \begin{macrocode}
              pop aload pop currentpoint 4 2 roll ArrowB linetype pop pop
            } ifelse
          } {
            7 1 roll
            [ tstart n 1 sub gt { @cp }{ currentpoint } ifelse
            9 3 roll ] ArrayToPointArray
            dup 3 -1 roll 
            Portion
            { aload pop } forall
            tstart n 1 sub gt {
              8 -4 roll 4 2 roll ArrowA 6 2 roll
            } {
              8 -2 roll pop pop
            } ifelse
            tstop n le { ArrowB } if
            curvetype
          } ifelse
        }{
%    \end{macrocode}
% full segment
%    \begin{macrocode}
          tstart n 1 sub eq {
%    \end{macrocode}
% the first segment
%    \begin{macrocode}
            /linetype eq {
              @cp ArrowA
              tstop n eq {
%    \end{macrocode}
% a single, full segment
%    \begin{macrocode}
                currentpoint 4 2 roll ArrowB linetype pop pop
              } {
%    \end{macrocode}
% not the last segment
%    \begin{macrocode}
                linetype
              } ifelse
            } {
              6 -2 roll @cp ArrowA 6 2 roll
              tstop n eq {
%    \end{macrocode}
% single, full curve segment
%   \begin{macrocode}
                ArrowB
              } if
              curvetype
            } ifelse
          } {
%    \end{macrocode}
% not the first segment
%    \begin{macrocode}
            /linetype eq {
              tstop n eq {
%    \end{macrocode}
% last segment but not a single one
%    \begin{macrocode}
                currentpoint 4 2 roll ArrowB linetype pop pop
              }{
%    \end{macrocode}
% full middle segment
%    \begin{macrocode}
                linetype 
              } ifelse
            } {
              tstop n eq {
%    \end{macrocode}
% last curveto segment, not a single one
%    \begin{macrocode}
                ArrowB
              } if
              curvetype
            } ifelse
          } ifelse
        } ifelse
      } ifelse
    } ifelse
  } loop
  end
  DebugEnd
} bind def
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{GetCurvePoint}
% Get the coordinates of the curve point at \PSvar{t}.
%   \begin{pssyntax}
%     \PSvar{t} \PSarray{curve} \PSop{GetCurvePoint} \PSvar{X Y}
%   \end{pssyntax}
%    \begin{macrocode}
/GetCurvePoint {
  dup IsPath {
    5 dict begin 
    exch dup /tstart exch def
    1 add cvi /tstop exch def
    /savecp { ToPnt cvx /@cp exch def } def
    /n 0 def
    mark exch aload pop
    { 
      counttomark 0 eq n tstop ge or { cleartomark exit } if
      dup /movetype eq not { /n n 1 add def } if
      dup /movetype eq {
        pop savecp
      } {
        tstart n ge {
%    \end{macrocode}      
% current path section is before tstop
%    \begin{macrocode}
          /curvetype eq { 6 2 roll 4 { pop } repeat } if
          savecp
        } {
          tstart n 1 sub gt {
            tstart n sub 1 add tstop n sub 1 add
            ToUnitInterval exch
            /linetype eq {
              3 1 roll ToPnt 
              tstart n 1 sub gt { @cp ToPnt } { currentpoint ToPnt } ifelse exch ToPnt
              dup 3 -1 roll Portion 
            } {
              7 1 roll
              [ @cp 9 3 roll ] ArrayToPointArray
              dup 3 -1 roll 
              Portion
            } ifelse
            0 get aload pop
          }{
%    \end{macrocode}
% full segment
%    \begin{macrocode}
            /curvetype eq {
              pop pop pop pop
            } if
          } ifelse
          counttomark 1 add 2 roll cleartomark exit
        } ifelse
      } ifelse
    } loop
    end
  } {
    exch dup 0 eq {
      pop 0 get aload pop
    } {
      0 exch ToUnitInterval exch dup 3 -1 roll Portion
      dup length 1 sub get aload pop
    } ifelse
  } ifelse
} bind def
%    \end{macrocode}
% \end{macro}
% \begin{macro}{TraceCurveOrPath}
%   \begin{pssyntax}
%     \PSarray{curve} \PSvar{tstart tstop} \PSproc{drawcurve}
%     \PSop{TraceCurveOrPath}
%   \end{pssyntax}
%    \begin{macrocode}
/TraceCurveOrPath {
  4 1 roll
  UnifyInterval
  3 -1 roll dup IsPath {
    4 -1 roll pop
    3 1 roll 2 copy gt {
%    \end{macrocode}
% reverse the path, draw everything and resave the path
%    \begin{macrocode}
      ReverseInterval
      3 -1 roll ReversePath 3 1 roll
    } if
    ShowPathPortion
  }{ % tstart tstop [curve]
    mark exch 4 2 roll % [ [curve] tstart tstop
      2 copy gt { % tstart &gt; tstop
%    \end{macrocode}
% Exchange tstart and tstop and reverse the curve array
%    \begin{macrocode}
        exch
        [ 4 -1 roll ReverseCurve 3 1 roll % [ [curve'] tstart tstop
      } if
      ToUnitInterval exch dup 3 -1 roll Portion
      { aload pop } forall
%    \end{macrocode}
% reverse the point order
%    \begin{macrocode}
      counttomark -2 4 { 2 roll } for
      counttomark 2 sub 2 idiv
      counttomark 2 add -1 roll exec
    } ifelse
} bind def
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
 % Graham Scal algorithm to compute the convex hull of a set of
 % points. Code written by Bill Casselman,
 %  http://www.math.ubc.ca/~cass/graphics/text/www/
 %
 % [[X1 Y1] [X2 Y2] ... [Xn Yn]] hull -&gt; [[...] ... [...]]
 %
/hulldict 32 dict def
hulldict begin

 % u - v 
/vsub { 2 dict begin
/v exch def
/u exch def
[ 
  u 0 get v 0 get sub
  u 1 get v 1 get sub
]
end } def

 % u - v rotated 90 degrees
/vperp { 2 dict begin
/v exch def
/u exch def
[ 
  v 1 get u 1 get sub
  u 0 get v 0 get sub
]
end } def

/dot { 2 dict begin
/v exch def
/u exch def
  v 0 get u 0 get mul
  v 1 get u 1 get mul
  add
end } def 

 % P Q
 % tests whether P &lt; Q in lexicographic order
 % i.e xP &lt; xQ, or yP &lt; yQ if xP = yP
/comp { 2 dict begin
/Q exch def
/P exch def
P 0 get Q 0 get lt 
  P 0 get Q 0 get eq
  P 1 get Q 1 get lt 
  and 
or 
end } def

end

 % args: an array of points C
 % effect: returns the array of points on the boundary of
 %     the convex hull of C, in clockwise order 

/ConvexHull {
(ConvexHull) DebugBegin
hulldict begin
/C exch def
/comp C quicksort
/n C length def
 % Q might circle around to the start
/Q n 1 add array def
Q 0 C 0 get put
Q 1 C 1 get put
/i 2 def
/k 2 def
 % i is next point in C to be looked at
 % k is next point in Q to be added
 % [ Q[0] Q[1] ... ]
 % scan the points to make the top hull
n 2 sub {
  % P is the current point at right
  /P C i get def
  /i i 1 add def
  {
    % if k = 1 then just add P 
    k 2 lt { exit } if
    % now k is 2 or more
    % look at Q[k-2] Q[k-1] P: a left turn (or in a line)?
    % yes if (P - Q[k-1])*(Q[k-1] - Q[k-2])^perp &gt;= 0
    P Q k 1 sub get vsub 
    Q k 1 sub get Q k 2 sub get vperp 
    dot 0 lt {
      % not a left turn
      exit
    } if
    /k k 1 sub def
  } loop
  Q k P put
  /k k 1 add def
} repeat

 % done with top half
 % K is where the right hand point is
/K k 1 sub def

/i n 2 sub def
Q k C i get put
/i i 1 sub def
/k k 1 add def
n 2 sub {
  % P is the current point at right
  /P C i get def
  /i i 1 sub def
  {
    % in this pass k is always 2 or more
    k K 2 add lt { exit } if
    % look at Q[k-2] Q[k-1] P: a left turn (or in a line)?
    % yes if (P - Q[k-1])*(Q[k-1] - Q[k-2])^perp &gt;= 0
    P Q k 1 sub get vsub 
    Q k 1 sub get Q k 2 sub get vperp 
    dot 0 lt {
      % not a left turn
      exit
    } if
    /k k 1 sub def
  } loop
  Q k P put
  /k k 1 add def
} repeat

 % strip Q down to [ Q[0] Q[1] ... Q[k-2] ]
 % excluding the doubled initial point
[ 0 1 k 2 sub {
  Q exch get
} for ] 
end
DebugEnd
} def

/qsortdict 8 dict def

qsortdict begin

 % args: /comp a L R x
 % effect: effects a partition into two pieces [L j] [i R]
 %     leaves i j on stack

/partition { 8 dict begin
/x exch def
/j exch def
/i exch def
/a exch def
dup type /nametype eq { load } if /comp exch def
{
  {
    a i get x comp exec not {
      exit
    } if
    /i i 1 add def
  } loop
  {
    x a j get comp exec not {
      exit
    } if
    /j j 1 sub def
  } loop
  
  i j le {
    % swap a[i] a[j]
    a j a i get
    a i a j get 
    put put
    /i i 1 add def
    /j j 1 sub def
  } if
  i j gt {
    exit
  } if
} loop
i j
end } def

 % args: /comp a L R
 % effect: sorts a[L .. R] according to comp
/subsort {
 % /c a L R
[ 3 1 roll ] 3 copy
 % /c a [L R] /c a [L R]
aload aload pop 
 % /c a [L R] /c a L R L R
add 2 idiv
 % /c a [L R] /c a L R (L+R)/2
3 index exch get
 % /c a [L R] /c a L R x
partition
 % /c a [L R] i j
 % if j &gt; L subsort(a, L, j)
dup 
 % /c a [L R] i j j
3 index 0 get gt {
  % /c a [L R] i j
  5 copy 
  % /c a [L R] i j /c a [L R] i j
  exch pop
  % /c a [L R] i j /c a [L R] j
  exch 0 get exch
  % ... /c a L j 
  subsort
} if
 % /c a [L R] i j
pop dup
 % /c a [L R] i i
 % if i &lt; R subsort(a, i, R)
2 index 1 get lt {
  % /c a [L R] i
  exch 1 get 
  % /c a i R
  subsort
}{
  4 { pop } repeat
} ifelse
} def

end % qsortdict

 % args: /comp a
 % effect: sorts the array a 
 % comp returns truth of x &lt; y for entries in a

/quicksort { qsortdict begin
dup length 1 gt {
 % /comp a
dup 
 % /comp a a 
length 1 sub 
 % /comp a n-1
0 exch subsort
} {
pop pop
} ifelse
end } def
%    \end{macrocode}
% 
% Debugging stuff
%    \begin{macrocode}
/debug {
    dup 1 add copy {==} repeat pop
} bind def
/DebugIT false def
/CheckIT false def
/DebugDepth 0 def
/DebugBegin {
  DebugIT {
    /DebugProcName exch def
    DebugDepth 2 mul string
    0 1 DebugDepth 2 mul 1 sub {
      dup 2 mod 0 eq { (|) }{( )} ifelse
      3 -1 roll dup 4 2 roll
      putinterval
    } for
    DebugProcName strcat ==
    /DebugDepth DebugDepth 1 add def
  }{
    pop
  } ifelse
} bind def
/DebugEnd {
  DebugIT {
    /DebugDepth DebugDepth 1 sub def
    DebugDepth 2 mul 2 add string
    0 1 DebugDepth 2 mul 1 sub {
      dup 2 mod 0 eq { (|) }{ ( ) } ifelse
      3 -1 roll dup 4 2 roll
      putinterval
    } for
    dup DebugDepth 2 mul (+-) putinterval
    ( done) strcat ==
  } if
} bind def
/strcat {
    exch 2 copy
    length exch length add
    string dup dup 5 2 roll
    copy length exch
    putinterval
} bind def
/nametostr {
    dup length string cvs
} bind def
/ShowCurve {
    { aload pop } forall
    8 -2 roll moveto curveto
} bind def
/CurveToString {
    (CurveToString) DebugBegin
    aload pop ([) 3 -1 roll 20 string cvs strcat (, ) strcat exch 20 string cvs strcat (]) strcat
    DebugEnd
} bind def
end % tx@IntersectDict
%    \end{macrocode}
%&lt;/prolog&gt; 
% \Finale
% \endinput
</pre></body></html>