summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/pst-intersect
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-02-21 00:22:39 +0000
committerKarl Berry <karl@freefriends.org>2014-02-21 00:22:39 +0000
commita5737bc6edabf060276b0476fcbe35e3088a5e24 (patch)
tree574ccf5c3926bfb1a0c1f2e5200e7b5e9f5fdf1a /Master/texmf-dist/source/latex/pst-intersect
parentaf161732d0da218229ae153646c74621e65a75a8 (diff)
pst-intersect (19feb14)
git-svn-id: svn://tug.org/texlive/trunk@33014 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/pst-intersect')
-rw-r--r--Master/texmf-dist/source/latex/pst-intersect/Makefile74
-rw-r--r--Master/texmf-dist/source/latex/pst-intersect/pst-intersect.dtx3094
-rw-r--r--Master/texmf-dist/source/latex/pst-intersect/pst-intersect.ins98
3 files changed, 3266 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/pst-intersect/Makefile b/Master/texmf-dist/source/latex/pst-intersect/Makefile
new file mode 100644
index 00000000000..43463f8ada8
--- /dev/null
+++ b/Master/texmf-dist/source/latex/pst-intersect/Makefile
@@ -0,0 +1,74 @@
+.SUFFIXES : .tex .ltx .dvi .ps .pdf .eps
+
+PACKAGE = pst-intersect
+
+LATEX = latex
+
+ARCHNAME = $(PACKAGE)-$(shell date +"%y%m%d")
+ARCHNAME_TDS = $(PACKAGE).tds
+
+ARCHFILES = $(PACKAGE).dtx $(PACKAGE).ins Makefile \
+ README Changes $(PACKAGE).pdf $(PACKAGE)-DE.pdf
+
+PS2PDF = GS_OPTIONS=-dPDFSETTINGS=/prepress ps2pdf
+
+all : doc doc-DE
+
+doc : $(PACKAGE).pdf
+doc-DE : $(PACKAGE)-DE.pdf
+
+dist : doc Changes
+ mkdir -p $(PACKAGE)
+ cp $(ARCHFILES) $(PACKAGE)
+ tar chvzf $(ARCHNAME).tar.gz $(PACKAGE)
+ rm -rf $(PACKAGE)
+ @ echo
+ @ echo $(ARCHNAME).tar.gz
+
+$(PACKAGE).dvi: L = english
+$(PACKAGE)-DE.dvi: L = ngerman
+%.dvi: $(PACKAGE).dtx $(PACKAGE).sty $(PACKAGE).tex $(PACKAGE).pro
+ $(LATEX) -jobname=$(basename $@) '\newcommand*{\mainlang}{$(L)}\input{$(PACKAGE).dtx}'
+ $(LATEX) -jobname=$(basename $@) '\newcommand*{\mainlang}{$(L)}\input{$(PACKAGE).dtx}'
+
+%.ps: %.dvi
+ dvips $<
+%.pdf: %.ps
+ $(PS2PDF) $< $@
+
+$(PACKAGE).sty $(PACKAGE).pro $(PACKAGE).tex: $(PACKAGE).ins $(PACKAGE).dtx
+ tex $<
+
+Changes: Changes.py $(PACKAGE).dtx
+ python $<
+
+arch : Changes
+ zip $(ARCHNAME).zip $(ARCHFILES)
+
+arch-tds : Changes
+ $(RM) $(ARCHNAME_TDS).zip
+ mkdir -p tds/tex/latex/$(PACKAGE)
+ mkdir -p tds/tex/generic/$(PACKAGE)
+ mkdir -p tds/doc/latex/$(PACKAGE)
+ mkdir -p tds/source/latex/$(PACKAGE)
+ mkdir -p tds/dvips/$(PACKAGE)
+ cp $(PACKAGE).sty tds/tex/latex/$(PACKAGE)/
+ cp $(PACKAGE).tex tds/tex/generic/$(PACKAGE)/
+ cp $(PACKAGE).pro tds/dvips/$(PACKAGE)/
+ cp Changes $(PACKAGE).pdf $(PACKAGE)-DE.pdf README tds/doc/latex/$(PACKAGE)/
+ cp $(PACKAGE).dtx $(PACKAGE).ins Makefile \
+ tds/source/latex/$(PACKAGE)/
+ cd tds ; zip -r ../$(ARCHNAME_TDS).zip tex doc source dvips
+ cd ..
+ rm -rf tds
+
+ctan : dist arch-tds
+ tar cf $(PACKAGE).tar $(ARCHNAME_TDS).zip $(ARCHNAME).tar.gz
+
+clean :
+ $(RM) $(foreach prefix, $(PACKAGE) $(PACKAGE)-DE, \
+ $(addprefix $(prefix), .dvi .ps .log .aux .bbl .blg .out .tmp \
+ .toc .hd))
+
+veryclean : clean
+ $(RM) $(addprefix $(PACKAGE), .pdf .tex .sty .pro) $(PACKAGE)-DE.pdf Changes
diff --git a/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.dtx b/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.dtx
new file mode 100644
index 00000000000..7bc9b753edb
--- /dev/null
+++ b/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.dtx
@@ -0,0 +1,3094 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2014 by Christoph Bersch <usenet@bersch.net>
+%
+% 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
+%<*driver>
+\ProvidesFile{pst-intersect.dtx}
+%</driver>
+%<stylefile>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<stylefile>\ProvidesPackage{pst-intersect}
+%<*stylefile>
+ [2014/02/19 v0.1 package wrapper for pst-intersect.tex]
+%</stylefile>
+%
+%<*driver>
+\documentclass[a4paper, DIV=9, oneside, toc=index, parskip=half-]{scrreprt}
+\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{array,booktabs,paralist,tabularx}
+\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{nicefrac, multido}
+\usepackage{pst-intersect}
+\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}
+\colorlet{DGreen}{green!90!black}
+\usepackage{showexpl}
+\makeatletter\renewcommand*\SX@Info{}\makeatother
+\usepackage{etoolbox}
+\undef{\cs}\undef{\cmd}
+\usepackage{ltxdockit}
+\newcommand{\poeTR}[1]{\TR{\ttfamily\color{DOrange}#1}}
+\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>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<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>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}
+%</driver>
+% \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 \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> 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}}
+% \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}}
+% \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-optexp}\\ 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.
+% \fi
+% \ifENGLISH
+% \section{About the package}
+% \LPack{pst-intersect} is a PSTricks package to calculate
+% the intersections of Bezier curves and arbitrary Postscript paths.
+% \fi
+%
+% \ifGERMAN
+% \section{Anforderungen}
+% \LPack{pst-intersect} benötigt aktuelle Versionen der
+% Pakete \LPack{pstricks}, \LPack{pst-node} 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}, 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
+%<*ignore>
+%\fi
+\begin{LTXexample}
+\begin{pspicture}(3,2)
+ \pssavepath[linecolor=DOrange]{MyPath}{%
+ \pscurve(0,2)(0,0.5)(3,1)
+ }%
+\end{pspicture}
+\end{LTXexample}
+%\iffalse
+%</ignore>
+%\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
+%<*ignore>
+%\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
+%</ignore>
+%\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
+%<*ignore>
+%\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
+%</ignore>
+%\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
+%<*ignore>
+%\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
+%</ignore>
+%\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
+%<*ignore>
+%\fi
+\begin{LTXexample}
+\begin{pspicture}(2,2)
+ \pssavepath{Circle}{\pscircle(1,1){1}}
+ \pstracecurve[linestyle=dashed, linecolor=green]{Circle}
+\end{pspicture}
+\end{LTXexample}
+%\iffalse
+%</ignore>
+%\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
+%<*ignore>
+%\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
+%</ignore>
+%\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
+%<*ignore>
+%\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
+%</ignore>
+%\fi
+%
+% \end{optionlist}
+%
+% \ifGERMAN
+% Beachten Sie, dass in der Version 0.1 die Reihenfolge von
+% \Lkeyword{tstart} und \Lkeyword{tstop} noch keine Rolle spielt. Für
+% kommende Versionen ist geplant, dass bei \Lkeyword{tstart}
+% \textgreater{} \Lkeyword{tstop} die Pfadrichtung umgekehrt wird. Zur
+% Zeit werden auch noch keine Pfeile für \Lcs{pstracecurve} unterstützt.
+% \fi
+% \ifENGLISH
+% Please note, that as of version 0.1 the order of \Lkeyword{tstart} and
+% \Lkeyword{tstop} doesn't play a role. But for upcoming versions it is
+% planned that \Lkeyword{tstart} \textgreater{} \Lkeyword{tstop}
+% reverses the path direction. At the moment arrows aren't supported
+% either.
+% \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
+%<*ignore>
+%\fi
+\begin{LTXexample}
+\begin{pspicture}(5.2,5.2)
+\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=->]{A}(0,0)(0,5)(5,2)(5,5)
+\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=->]{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
+%</ignore>
+%\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
+%<*ignore>
+%\fi
+\begin{LTXexample}
+\begin{pspicture}(5.2,5.2)
+\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=->]{A}(0,0)(0,5)(5,2)(5,5)
+\pssavebezier[linewidth=0.5\pslinewidth, linestyle=dashed, arrows=->]{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
+%</ignore>
+%\fi
+%
+% \ifGERMAN
+% \chapter{Beispiele}
+% \fi
+% \ifENGLISH
+% \chapter{Examples}
+% \fi
+%\iffalse
+%<*ignore>
+%\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
+%</ignore>
+%\fi
+%
+%\iffalse
+%<*ignore>
+%\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+2,\ii=2+2}{5}{\uput[120](C\i){\i}\uput[60](C\ii){\ii}}
+\end{pspicture}
+\end{LTXexample}
+\endgroup
+%\iffalse
+%</ignore>
+%\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.1}{2014-02-19}
+% \item First CTAN version
+% \end{release}
+% \end{changelog}
+%
+% \StopEventually{}
+%
+% \begin{otherlanguage}{english}
+% \printindex[idx]
+% \end{otherlanguage}
+%
+% \chapter{The \LaTeX\ wrapper}
+%<*stylefile>
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+\ProvidesPackage{pst-intersect}%
+ [2014/02/06 v0.1alpha package wrapper for pst-intersect.tex]
+\RequirePackage{pstricks}
+\RequirePackage{pst-xkey}
+\RequirePackage{pst-node}
+\RequirePackage{multido}
+\RequirePackage{pst-func}
+\input{pst-intersect.tex}
+\IfFileExists{pst-intersect.pro}{%
+ \ProvidesFile{pst-intersect.pro}
+ [2014/02/06 PostScript prologue file]
+ \@addtofilelist{pst-intersect.pro}}{}%
+% \end{macrocode}
+%</stylefile>
+%
+% \chapter{The \TeX\ implementation}
+%
+%<*texfile>
+% \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} }}%
+
+\def\pssavebezier{\pst@object{pssavebezier}}
+\def\pssavebezier@i#1{%
+ \begin@OpenObj
+ \PIT@checkname{#1}%
+ \addto@pscode{ /\PIT@name{#1} }%
+ \pst@getcoors[\pssavebezier@ii%]
+}%
+\def\pssavebezier@ii{%
+ \addto@pscode{%
+ % only 10 points allowed, remove the rest
+ counttomark 20 gt { counttomark 20 sub { pop } repeat } if
+ % reverse the point order
+ counttomark -2 4 { 2 roll } for
+ %\addto@pscode{%
+ %counttomark 2 add -1 roll pop % remove the path name
+ counttomark 2 idiv 1 sub dup 9 gt { pop 9 } if
+ \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}%
+\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]{}
+\psset[intersect]{%
+ tstart=-1,
+ tstop=-1,
+ istart=-1,
+ istop=-1,
+ name={},
+ saveintersections
+}%
+\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{}%
+}%
+\let\PIT@pst@stroke@orig\pst@stroke
+\def\PIT@save@path{%
+ \PIT@pst@stroke@orig
+ \addto@pscode{%
+ clear mark
+ { /movetype counttomark 3 roll }
+ { /linetype counttomark 3 roll }
+ { /curvetype counttomark 7 roll }{} pathforall
+ counttomark 1 add -1 roll pop count }%
+}%
+\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
+}%
+\def\pssavepath{\pst@object{pssavepath}}%
+\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
+}%
+\def\pstracecurve{\pst@object{pstracecurve}}%
+\def\pstracecurve@i#1{%
+ \addbefore@par{plotpoints=200}%
+ \begin@OpenObj
+ \@ifnextchar\bgroup
+ {\PIT@traceintersection{#1}}%
+ {\PIT@tracecurve{#1}}%
+}%
+\def\PIT@tracecurve#1{%
+ \PIT@checkname{#1}%
+ \addto@pscode{%
+ \pst@intersectdict
+ \PIT@name{#1} dup IsPath {
+ \PIT@key@tstart\space\PIT@key@tstop\space
+ ShowPathPortion
+ }{
+ [exch dup
+ \PIT@key@tstart\space\PIT@key@tstop\space
+ dup 0 lt { pop 1 } if
+ ToUnitInterval Portion
+ { aload pop } forall
+ counttomark 2 sub 2 idiv
+ \psk@plotpoints
+ exch
+ \txFunc@BezierCurve
+ \ifshowpoints \txFunc@BezierShowPoints \else pop \fi
+ } ifelse
+ end
+ }%
+ \end@OpenObj
+}%
+\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
+ 2 copy 2 copy gt 3 1 roll -1 gt exch -1 gt and and { exch } if
+ 3 -1 roll dup
+ IsPath {
+ 3 1 roll
+ ShowPathPortion
+ }{
+ [ exch dup 5 -2 roll
+ dup 0 lt { pop 1 } if
+ ToUnitInterval Portion
+ { aload pop } forall
+ counttomark 2 sub 2 idiv
+ \psk@plotpoints
+ exch
+ \txFunc@BezierCurve
+ \ifshowpoints \txFunc@BezierShowPoints \else pop \fi
+ } ifelse
+ end
+ }%
+ \end@OpenObj
+}%
+%
+% \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\space /\PIT@name{#1} /\PIT@name{#2} 8 3 roll
+ SaveIntersection
+ }%
+ \ifPIT@saveintersections
+ \pst@Verb{%
+ \pst@intersectdict
+ \PIT@@name\space /Points get
+ ArrayToPointArray
+ end
+ tx@NodeDict begin
+ dup length 1 1 3 -1 roll {
+ 2 copy 1 sub get cvx
+ false 3 -1 roll (N@\PIT@key@name) exch 20 string cvs
+ \pst@intersectdict strcat end cvn
+ 10 {InitPnode} /NodeScale {} def NewNode
+ } for
+ end
+ 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{macrocode}
+\catcode`\@=\PstAtCode\relax
+% \end{macrocode}
+%</texfile>
+%
+% \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
+%
+%<*prolog>
+% \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}{ToVec}
+% 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{ToVec} \PSarray{X Y}
+% \end{pssyntax}
+% \begin{macrocode}
+/ToVec {
+ [ 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 {
+ IntersectLines
+ }{
+ 2 copy [0 1] [0 1] IterateIntersection
+ } ifelse
+ 3 -1 roll exch
+} bind def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{IntersectLines}
+%
+% \begin{pssyntax}
+% \PSarray{lineA} \PSarray{lineB} \PSop{IntersectLines}
+% \PSarray{lineA} \PSarray{tA} \PSarray{lineB} \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 % X3-X4 Y3-Y4 X2-X1 Y2-Y1 X3-X1 Y3-Y1 % b1 b2 a1 a2 c1 c2
+ 6 copy 12 -4 roll
+ neg 4 -1 roll mul 3 1 roll mul add
+ dup 0 eq {
+ % no intersections
+ 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
+ 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
+ } ifelse
+ DebugEnd
+} 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
+ % [intersections] [pathA] [tA] [pathB] [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
+ { % [curveA] [Bi]
+ /n n 1 sub def
+ exch dup 3 -1 roll % [curveA] [curveA] [Bi]
+ IntersectBeziers
+ 4 copy LoadIntersectionPoints % [curveA] [tA] [curveB] [tB]
+ [ 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 % remove [curveA]
+ [ isect { aload pop } forall ] 3 1 roll tA exch tB
+ % [intersections] [curveA] [tA] [pathB] [tB]
+ end
+ DebugEnd
+} bind def
+/IntersectPathCurve {
+ exch IntersectCurvePath 4 2 roll
+} bind def
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{SaveIntersection}
+% \begin{pssyntax}
+% \PSname{isectname} \PSname{nameA} \PSname{nameB}
+% \PSarray{intersectionpoints} \PSarray{A} \PSarray{tA} \PSarray{B} \PSarray{tB}
+% \PSop{SaveIntersection}
+% \end{pssyntax}
+% \begin{macrocode}
+/SaveIntersection {
+ (SaveIntersection) DebugBegin
+ 4 dict dup 10 -1 roll exch def
+ begin %
+ /Points 6 -1 roll def
+ 5 -1 roll dup 4 -1 roll def % /curveA [curveA] [tA] [tB] /curveB /curveB [curveB] def
+ nametostr (@t) strcat cvn exch TArray def % /curveA [curveA] [tA] /curveB@t [tB] def
+ 3 -1 roll dup 4 -1 roll def
+ nametostr (@t) strcat cvn exch TArray def
+ end
+ 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 {
+ (TArray) DebugBegin
+ 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
+ DebugEnd %1 debug
+} 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}
+/movetype { /moveto load } bind def
+/linetype { /lineto load } bind def
+/curvetype { /curveto load } bind def
+% \end{macrocode}
+%
+% [ ... /movetype ... /linetype .../curvetype ]
+% \begin{macrocode}
+/PreparePath {
+ [ exch aload pop
+ {
+ dup type /nametype eq not { exit } if
+ dup /movetype eq {
+ pop ToVec /@mycp exch def
+ } {
+ dup /linetype eq {
+ pop [ @mycp 4 2 roll 2 copy ToVec /@mycp exch def ToVec ]
+ } {
+ pop [ @mycp 8 2 roll 2 copy ToVec /@mycp exch def
+ ToVec 5 1 roll ToVec 4 1 roll ToVec 3 1 roll ]
+ } ifelse
+ counttomark 1 roll
+ } ifelse
+ } loop ]
+} bind def
+% \end{macrocode}
+%
+% \begin{macro}{LoadLineIntersectionPoints}
+% Prepare \PSarray{Curve} for use with tx@Func
+% \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
+ % [A0.x A0.y ... AM.x AM.y] [tA0a tA0b ... tAMa tAMb] [tB0a tB0b ... tBNa tBNb] [B0.x B0.y ... BN.x BN.y]
+ 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
+ %2 debug
+ % [IB0.xa IB0.ya IB0.xb IB0.yb ... IBM.yb] [IA0.xa IA0.ya IA0.xb IA0.yb ... IAM.yb]
+ 2 {
+ [ exch aload length 4 idiv {
+ [ 5 1 roll ] counttomark 1 roll
+ } repeat ]
+ exch
+ } repeat
+ % [[IB0.xa ...] ... [... IBM.yb]] [[IA0.xa IA0.ya IA0.xb IA0.yb] ...[IAM.xa ... IAM.yb]]
+ 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
+ % merge near intersection points
+ %counttomark 2 idiv 1 1 3 -1 roll {
+ % pop
+ % counttomark 4 lt { exit } if
+ % 4 copy 4 2 roll ToVec 3 1 roll ToVec AreNear {
+
+ % }
+ %} 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
+ 11 dict begin
+ /precision MaxPrecision 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
+/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 {
+ (>> curve subdivision performed: dom(A) = ) domA CurveToString strcat
+ (, dom(B) = ) strcat domB CurveToString strcat ( <<) strcat ==
+ } if
+ CurveA IsConstant CurveB IsConstant and {
+ CurveA MiddlePoint ToVec
+ CurveB MiddlePoint ToVec 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 ToVec
+ CurveB MiddlePoint ToVec AreNear {
+ domA domB true
+ }{
+ false
+ } ifelse
+ } ifelse
+ exit
+ } if
+% \end{macrocode}
+% iter < 100 && (dompA.extent() >= precision || dompB.extent() >= 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] > dom[1], invalid.
+% \begin{macrocode}
+ dom aload pop 2 copy min 3 1 roll max gt {
+ CheckIT {
+ (dom[0] > 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 ToVec
+ CurveB MiddlePoint ToVec 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{pssyntx}
+% \PSarray{interval} \PSop{IsEmptyInterval} \PSvar{boolean}
+% \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
+ ToVec
+} 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}
+% \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 ToVec
+} 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 ToVec % [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
+ 4 copy abs 3 { exch abs max } repeat Epsilon mul
+ dup 6 2 roll VecSub abs 4 -1 roll lt exch abs 3 -1 roll 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 -> 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 -> 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}{ShowFullPath}
+% \begin{macrocode}
+/ShowFullPath {
+ 4 dict begin
+ /movetype /moveto load def
+ /linetype /lineto load def
+ /curvetype /curveto load def
+ mark exch aload pop
+ {
+ counttomark 0 eq { exit } if
+ load exec
+ } loop
+ pop
+ end
+} bind def
+/ShowPathPortion {
+ 6 dict begin
+ exch dup 0 lt { pop 0 } if /tstart exch def
+ % if tstart is < 0, use the array length
+ dup 0 lt { pop dup length } if /tstop exch def
+ tstop tstart gt {
+ /movetype /moveto load def
+ /linetype /lineto load def
+ /curvetype /curveto load def
+ /n 0 def
+ mark exch aload pop
+ {
+ counttomark 0 eq { pop exit } if
+ dup /movetype eq not { /n n 1 add def } if
+ % current section is after tstart
+ n tstop sub 1 ge { cleartomark exit } if
+
+ dup /movetype eq {
+ load exec
+ } {
+ tstart n gt {
+ % current path section is before tstart
+ /curvetype eq { 6 2 roll 4 { pop } repeat } if
+ movetype
+ } {
+ tstart n 1 sub gt tstop n lt or {
+ % draw a truncated section
+ tstart n sub 1 add tstop n sub 1 add
+ ToUnitInterval exch
+ /linetype eq {
+ 3 1 roll ToVec currentpoint ToVec exch ToVec
+ dup 3 -1 roll Portion
+ aload pop exch
+ tstart n 1 sub gt { aload pop moveto } { pop } ifelse
+ aload pop lineto
+ } {
+ 7 1 roll [ currentpoint 9 3 roll ] ArrayToPointArray
+ dup 3 -1 roll Portion
+ { aload pop } forall
+ 8 -2 roll
+ tstart n 1 sub gt { moveto } { pop pop } ifelse
+ curveto
+ } ifelse
+ }{
+ load exec
+ } ifelse
+ } ifelse
+ } ifelse
+ } loop
+ } if
+ end
+} 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 -> [[...] ... [...]]
+ %
+/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 < Q in lexicographic order
+ % i.e xP < xQ, or yP < 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 >= 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 >= 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 > 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 < 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 < 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}
+%</prolog>
+% \Finale
+% \endinput
diff --git a/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.ins b/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.ins
new file mode 100644
index 00000000000..936fc96b5e4
--- /dev/null
+++ b/Master/texmf-dist/source/latex/pst-intersect/pst-intersect.ins
@@ -0,0 +1,98 @@
+%%
+%% Copyright (C) 2014 by Christoph Bersch <usenet@bersch.net>
+%%
+%% 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.
+%%
+%% This work has the LPPL maintenance status "maintained".
+%%
+%% The current maintainer of this work is Christoph Bersch.
+%%
+%% This work consists of the files pst-intersect.dtx and pst-intersect.ins
+%% and the derived files
+%% pst-intersect.sty, pst-intersect.tex, pst-intersect.pro.
+%%
+%% Distribution:
+%% CTAN:graphics/pstricks/contrib/pst-intersect/README
+%% CTAN:graphics/pstricks/contrib/pst-intersect/Changes
+%% CTAN:graphics/pstricks/contrib/pst-intersect/pst-intersect.ins
+%% CTAN:graphics/pstricks/contrib/pst-intersect/pst-intersect.dtx
+%% CTAN:graphics/pstricks/contrib/pst-intersect/pst-intersect.pdf
+%%
+%% Unpacking:
+%% tex pst-intersect.ins
+%%
+%% Documentation:
+%% make doc
+%%
+%% Installation:
+%% TDS:tex/latex/pst-intersect/pst-intersect.sty
+%% TDS:tex/generic/pst-intersect/pst-intersect.tex
+%% TDS:dvips/pst-intersect/pst-intersect.pro
+%% TDS:doc/latex/pst-intersect/README
+%% TDS:doc/latex/pst-intersect/Changes
+%% TDS:doc/latex/pst-intersect/pst-intersect.pdf
+%% TDS:source/latex/pst-intersect/pst-intersect.ins
+%% TDS:source/latex/pst-intersect/pst-intersect.dtx
+%%
+\input docstrip.tex
+\keepsilent
+
+\preamble
+
+This is a generated file.
+
+Project: pst-intersect
+Version: 0.1 (2014/02/19)
+
+Copyright (C) 2007-2014 by Christoph Bersch <usenet@bersch.net>
+
+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.
+
+This work has the LPPL maintenance status "maintained".
+
+The current maintainer of this work is Christoph Bersch.
+
+This work consists of the files pst-intersect.dtx and pst-intersect.ins
+and the derived files
+ pst-intersect.sty, pst-intersect.tex, pst-intersect.pro.
+
+\endpreamble
+
+\askforoverwritefalse
+
+\generate{\file{pst-intersect.sty}{\from{pst-intersect.dtx}{stylefile}}
+ \file{pst-intersect.tex}{\from{pst-intersect.dtx}{texfile}}
+ \usepostamble\empty%
+ \file{pst-intersect.pro}{\from{pst-intersect.dtx}{prolog}}}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* pst-intersect.sty *}
+\Msg{* pst-intersect.tex *}
+\Msg{* pst-intersect.pro *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file *}
+\Msg{* pst-intersect.dtx through LaTeX, preferably using the *}
+\Msg{* Makefile. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile