cgal/Packages/PS_Stream/web/PS_Stream.fw

1574 lines
44 KiB
Plaintext

\documentclass[]{article}
\usepackage{amssymb}
\usepackage{fw-latex}
\usepackage{cgal}
\usepackage{epsf}
\textwidth=6in
\textheight=8.9in
\oddsidemargin=0.25in
\evensidemargin=0.25in
\topmargin=-0.5in
\begin{document}
@p typesetter = tex
@p no_doc_header
@p maximum_output_line_length = 120
@p maximum_input_line_length = 120
\title{\bf The CGAL PostScript Stream}
\author{Franck Descollonges \\ INRIA Sophia Antipolis}
\date{29/01/1997}
\maketitle
\section{Introduction}
{\it Postscript} is a page description language. It is a programming language
designed to convey a description of virtually any desired page to a printer.
We provide a Postscript output for all geometric classes
of \cgal. Thanks to this stream, you will be able to create file printable
or a file you will be able to insert in Latex documents. Indeed the generate
output file can be an EPSF file.
\section{The Postscript Stream Class}
This class is the Postscript Stream class. It is the one containing all
methods used to create, modify a Postscript output.
The following two macros contain the public and the private part
respectively.
@$@<class CGAL_PS_Stream@>+=@{@-
typedef const char *DashStyle;
class CGAL_PS_Stream {
public:
typedef CGAL_Bbox_2 PS_BBox;
static const DashStyle SOLID;
static const DashStyle DASH1;
static const DashStyle DASH2;
static const DashStyle DASH3;
static const DashStyle DASH4;
static const DashStyle DASH5;
static const DashStyle DASH6;
static const float CM;
static const float INCH;
static const float POINT;
enum OutputMode {READABLE, QUIET, READABLE_EPS, QUIET_EPS, GS_VIEW};
enum DotStyle {NONE, XCROSS, ICROSS, EDOT, FDOT, EBOX, FBOX};
@}
\subsection{The Graphical Environment : Auxiliary classes}
Before speacking about the Postscript stream, we have to introduce some auxiliary classes.
\subsubsection{The Axis Class }
If you want to represente axis on the postscript output,
you have to create an axis object.
You can set the step between two marks on the x-axis and the y-axis.
If the padx or the pady is 0 no mark are displayed on the axis.
The thick member contains thickness of the lines rrepresenting the axis.
You can insert only one axis object in a postscript stream.
@$@<class CGAL_PS_Stream@>+=@{@-
class Axis {
friend CGAL_PS_Stream;
friend CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const Axis &g);
public:
Axis(double x, double y, unsigned int t=0.0)
: _stepx(x), _stepy(y), _thick(t) {}
Axis(double xy, unsigned int t=0.0)
: _stepx(xy),_stepy(xy), _thick(t) {}
Axis(): _stepx(1.0), _stepy(1.0), _thick(0.0) {}
double stepx() const { return _stepx;}
double stepy() const { return _stepy;}
double thickness() const { return _thick;}
private:
double _stepx;
double _stepy;
bool _thick;
};
@}
\subsubsection{The Grid Class }
You can insert grids in a postscript stream. You have to create an object and select
the step beetween two line for the x-axis and the y-axis...
You can select the style of the mark and insert many grid of differents styles.
@$@<class CGAL_PS_Stream@>+=@{@-
class Grid {
friend CGAL_PS_Stream;
friend CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const Grid &g);
public:
Grid(double x, double y, DashStyle str="[1 5] 0")
: _stepx(x), _stepy(y) {_style=strdup(str);}
Grid(double xy, DashStyle str="[1 5] 0")
: _stepx(xy), _stepy(xy) {_style=strdup(str);}
Grid() : _stepx(1.0), _stepy(1.0), _style("[1 5] 0") {}
private:
double stepx() const { return _stepx;}
double stepy() const { return _stepy;}
DashStyle style() const { return _style;}
double _stepx;
double _stepy;
DashStyle _style;
};
@}
\subsubsection{The Label class}
The Label class is used to insert text in a postscript output.
You have just to define a Label object and insert it in the stream
to display the string in the postscript output. Default font and
size is used to display texts but you are able to change this using the
modifiers of the stream.
@$@<class CGAL_PS_Stream@>+=@{@-
class Label {
friend CGAL_PS_Stream;
friend CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const Label &txt);
public:
Label(const char* txt) { _text=strdup(txt);}
private:
Label() { _text="";}
const char* text() const { return _text;}
const char* _text;
};
@}
\subsubsection{The Latex label class}
These class is used to insert text which will be only display with Latex.
These labels used default latex font to be displayed. You can can change font and style
(for exemple math style) by using standart latex commands as string like :
\begin{verbatim}
{$\alpha^{y}_{i}$}
\end{verbatim}
These labels wont be displayed on a gs view but only with latex.
To include such a file you have to type ("toto.ps" is the file in which
the Postscript output of CGAL had been redirected) :
\begin{verbatim}
\documentclass[]{article}
\begin{document}
\def\Ipe#1{\def\IPEfile{#1}\input{#1}}
before.
\begin{figure*}[h]
\begin{center}
\Ipe{toto.ps}
\end{center}
\end{figure*}
after.
\end{document}
\end{verbatim}
@$@<class CGAL_PS_Stream@>+=@{@-
class Latex_Label {
friend CGAL_PS_Stream;
friend CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, Latex_Label &txt);
public:
// Only text can be define by user
Latex_Label(const char* txt) { _text=strdup(txt);posx=0;posy=0;}
Latex_Label() { _text="";posx=0;posy=0;}
private:
// These functions are private because the position of the string must never appears to the user
// Only stream modifiers will access these data
void setposition(float x, float y) { posx=x;posy=y;}
Latex_Label(const char* txt,float x, float y) {_text=strdup(txt);posx=x;posy=y;}
float xpos() const {return posx;};
float ypos() const {return posy;};
const char* text() const { return _text;};
// Slots
const char* _text;
float posx;
float posy;
};
@}
I need to insert all Latex labels at the same position (at the end of the file.)
So i need to save all data in a list. It is why i define a Lsit of latex label.
@$@<class CGAL_PS_Stream@>+=@{@-
typedef list<Latex_Label> List_Label;
@}
\subsubsection{The Border class}
The border class is used to insert a border in a stream.
Users just need to define a border, and to insert it in the stream.
The postscript output will display this border.
@$@<class CGAL_PS_Stream@>+=@{@-
class Border {
friend CGAL_PS_Stream;
friend CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const Border &b);
public:
Border(int s=0) { _size=s;}
private:
int size() const { return _size;}
int _size;
};
@}
\subsubsection{The Context class}
The Context class define a graphical context. It is used to select the style
of the drawing.
You can create a context (set to DEFAULT value) and copy the current context.
You only can change the current context of the postscript stream by inserting modifiers
in the stream. The context can be globaly set with a modifier in the Postscript stream thanks
to this class.
\begin{figure}[h]
\centerline{\epsffile{demo.ps}}
\end{figure}
The following two macros contain the public and the private part respectively.
\subsubsection*{The Public Interface of the Context class}
@$@<class CGAL_PS_Stream@>+=@{@-
class Context {
friend CGAL_PS_Stream;
public:
Context() : _border_color(CGAL_Color(0,0,0)),
_fill_color(CGAL_Color(0,0,0)),_dot_style(XCROSS),_dot_size(5),
_thickness(0),_line_style(SOLID),_fill(false),
_font("Helvetica"),_font_size(12), _anchor_point(CGAL_Point_2<CGAL_Cartesian <double> > (0,0))
{}
Context(const Context& c)
: _border_color(c.get_border_color()),_fill_color(c.get_fill_color()),
_dot_style(c.get_dot_style()), _dot_size(c.get_dot_size()),
_thickness(c.get_thickness()), _line_style(strdup(c.get_line_style())),
_fill(c.get_fill()), _font(strdup(c.get_font())), _font_size(c.get_font_size()),
_anchor_point(c.get_pos())
{};
// Accessor
CGAL_Color get_border_color() const {return _border_color;}
CGAL_Color get_fill_color() const {return _fill_color;}
DotStyle get_dot_style() const {return _dot_style;}
unsigned int get_dot_size() const {return _dot_size;}
unsigned int get_thickness() const {return _thickness;}
unsigned int get_font_size() const {return _font_size;}
DashStyle get_line_style() const {return _line_style;}
const char* get_font() const {return _font;}
bool get_fill() const {return _fill;}
CGAL_Point_2<CGAL_Cartesian <double> > get_pos() const {return _anchor_point;}
void set_border_color(CGAL_Color& c) {_border_color=c;}
void set_fill_color(CGAL_Color& c) {_fill_color=c;}
void set_dot_style(DotStyle& s) {_dot_style=s;}
void set_dot_size(unsigned int s) {_dot_size=s;}
void set_thickness(unsigned int t) {_thickness=t;}
void set_font_size(unsigned int s) {_font_size=s;}
void set_fill(bool&b) {_fill=b;}
void set_current_pos(const CGAL_Point_2<CGAL_Cartesian <double> >& p) {_anchor_point=p;}
void set_line_style(DashStyle style) {_line_style=strdup(style);}
void set_font(const char *font) {_font=strdup(font);}@}
\subsubsection*{The Private part of the Context class}
@$@<class CGAL_PS_Stream@>+=@{@-
private:
// Store the current border color
CGAL_Color _border_color;
// Store the current fill color
CGAL_Color _fill_color;
// Store the current dot style
enum DotStyle _dot_style;
// Store the current dot size
unsigned int _dot_size;
// Store the current line thickness
unsigned int _thickness;
// Store the current line style
DashStyle _line_style;
// Define if a polygone must be fill or not
bool _fill;
// Define if direction must be shown.
bool _dir;
// Store the name of the font to use. It is only used for standart Label, not for Latex Label.
const char* _font;
// Store the size of the font. It is only used for standart Label, not for Latex Label.
unsigned int _font_size;
//Anchor point:
CGAL_Point_2<CGAL_Cartesian <double> > _anchor_point;
};
@}
\subsection{Specification of the CGAL\_PS\_Stream class}
\subsubsection{The public part of CGAL\_PS\_Stream}
The different constructors of the Postscipt Stream allow a very easy definition
of the working area.
For all constructors, you need to define a bounding box. This is the maximum area
of real objects represented in the postscript view.
In this coonstructors, the whole page is used,
the bounding box is defined by bb.
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb, ostream &os,
OutputMode = QUIET);
@}
The same as above but the output stream will be a file which name is fname.
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb, const char *fname,
OutputMode = QUIET);
@}
These constructors specify the size of the postscript result.
(size is given in postscript dots.)
You can select the desired height of the output. The width of
the output will be calculated to keep circle round.
In an output stream :
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb,float H, ostream &os,
OutputMode = QUIET);
@}
In a file named fname :
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb,float H, const char *fname,
OutputMode = QUIET);
@}
These constructors specify the size of the postscript result in postscipt dots.
In an output stream :
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb,float L, float H, ostream &os,
OutputMode = QUIET);
@}
In a file named fname :
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb,float L, float H, const char *fname,
OutputMode = QUIET);
@}
Destructor :
@$@<class CGAL_PS_Stream@>+=@{@-
~CGAL_PS_Stream();
@}
//Manipulators
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream& _SetBorderColor(CGAL_Color &);
CGAL_PS_Stream& _SetFillColor(CGAL_Color &);
CGAL_PS_Stream& _SetPointSize(unsigned int);
CGAL_PS_Stream& _SetLineWidth(unsigned int);
CGAL_PS_Stream& _SetPointStyle(enum DotStyle);
CGAL_PS_Stream& _SetLineStyle(DashStyle);
CGAL_PS_Stream& _SetFill(bool);
CGAL_PS_Stream& _SetDefaultContext(void);
CGAL_PS_Stream& _SetCurrentContext(const Context &);
CGAL_PS_Stream& _ShowDirection(bool);
CGAL_PS_Stream& _MoveTo(CGAL_Point_2< CGAL_Cartesian <double> >);
CGAL_PS_Stream& _ShowAxis(Axis &);
CGAL_PS_Stream& _ShowGrid(Grid &);
CGAL_PS_Stream& _PutPsLabel(const char *);
CGAL_PS_Stream& _PutLatexLabel(const char *);
CGAL_PS_Stream& _PutBorder(unsigned int);
CGAL_PS_Stream& _SetFont(const char *);
CGAL_PS_Stream& _SetFontSize(unsigned int);
//Accessors
ostream& os() {return _os;}
List_Label& list() {return _ll;}
const Context context() const {return ctxt;}
bool gs_output() const {return (bool)(mode()==GS_VIEW);}
PS_BBox bbox() const {return _bbox;}
int width() const {return _width;}
int height() const {return _height;}
OutputMode mode() const {return _mode;}
// Utils
double xratio() { return _xratio;}
double yratio() { return _yratio;}
double x2ps(double x) {
return (x-_bbox.xmin())*xratio();
}
double y2ps(double y) {
return (y-_bbox.ymin())*yratio();
}
bool is_eps();
bool is_readable();
@}
\subsubsection{The Private Part of CGAL\_PS\_Stream}
@$@<class CGAL_PS_Stream@>+=@{@-
private:
@}
Constructors in a pipe :
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream(const PS_BBox &bb);
CGAL_PS_Stream(const PS_BBox &bb,float H);
CGAL_PS_Stream(const PS_BBox &bb,float L, float H);
@}
Default Constructor protected.
@$@<class CGAL_PS_Stream@>+=@{@-
CGAL_PS_Stream();
// Manipulation du contexte.
void setdefault();
void setcontext();
// Pour inserer l'entete
void insert_catalogue();
// Define the scale.
double _xratio;
double _yratio;
// Define the boounding box
PS_BBox _bbox;
// OutputMode
OutputMode _mode;
// Size of output.
int _width,_height;
// Graphical Context
Context ctxt;
// The Output stream
#ifdef CGAL_WORKAROUND_016
_IO_ostream_withassign &_os;
#else
ostream_withassign &_os;
#endif
//List of Latex Labels. They will be inserted at the end of the file.
List_Label _ll;
};
@}
Definition of external fonctions and variables
@$@<class CGAL_PS_Stream@>+=@{@-
extern const CGAL_PS_Stream::Context CGAL_CTXT_DEFAULT;
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Border &b);
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Axis &g);
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Grid &g);
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Label &txt);
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Latex_Label &txt);
extern CGAL_PS_Modifier_creator<CGAL_Color &> set_fill_color;
extern CGAL_PS_Modifier_creator<CGAL_Color &> set_border_color;
extern CGAL_PS_Modifier_creator<unsigned int> set_point_size;
extern CGAL_PS_Modifier_creator<CGAL_PS_Stream::DotStyle> set_point_style;
extern CGAL_PS_Modifier_creator<DashStyle> set_line_style;
extern CGAL_PS_Modifier_creator<unsigned int> set_line_width;
extern CGAL_PS_Modifier_creator<bool> set_fill;
extern CGAL_PS_Modifier_creator<const CGAL_PS_Stream::Context &> set_current_context;
extern CGAL_PS_Modifier_creator<bool> show_direction;
extern CGAL_PS_Modifier_creator<CGAL_Point_2< CGAL_Cartesian <double> > > move_to;
//extern CGAL_PS_Modifier_creator<CGAL_PS_Stream::Axis &> show_axis;
//extern CGAL_PS_Modifier_creator<CGAL_PS_Stream::Grid &> show_grid;
//extern CGAL_PS_Modifier_creator<const char *> put_ps_label;
//extern CGAL_PS_Modifier_creator<const char *> put_latex_label;
//extern CGAL_PS_Modifier_creator<unsigned int> put_border;
extern CGAL_PS_Modifier_creator<const char *> set_font;
extern CGAL_PS_Modifier_creator<unsigned int> set_font_size;
@}
\subsection{Implementation : Constructors and Destructors}
Definition of constants :
@$@<Constructors and Destructors@>+=@{@-
const float CGAL_PS_Stream::CM=28.4;
const float CGAL_PS_Stream::INCH=72.0;
const float CGAL_PS_Stream::POINT=1.0;
const DashStyle CGAL_PS_Stream::SOLID="[] 0 ";
const DashStyle CGAL_PS_Stream::DASH2="[5 5] 0 ";
const DashStyle CGAL_PS_Stream::DASH3="[10 10] 0 ";
const DashStyle CGAL_PS_Stream::DASH6="[10 6 4 6] 0 ";
const DashStyle CGAL_PS_Stream::DASH4="[10 5] 0 ";
const DashStyle CGAL_PS_Stream::DASH5="[5 10] 0 ";
const DashStyle CGAL_PS_Stream::DASH1="[2 2] 0 ";
extern const CGAL_PS_Stream::Context CGAL_CTXT_DEFAULT=CGAL_PS_Stream::Context();
@}
Constructors :
@$@<Constructors and Destructors@>+=@{@-
/*
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb)
: _bbox(bb), _os(cerr), _mode(GS_VIEW)
{
FILE *fp = popen("gs -","w");
if(!fp){
cerr << "Could not open pipe to gs" << endl ;
exit(-1);
}
os().attach(fileno(fp));
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb,float L, float H)
: _bbox(bb), _os(cerr), _mode(GS_VIEW), _width(L), _height(H)
{
insert_catalogue();
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
};
*/
@}
Alternatively you can pass an output stream as argument. The
formatted Postscript output goes to this stream then, which
typically will be {\tt cout} or a file (passing a {\tt fstream}).
@$@<Constructors and Destructors@>+=@{@-
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb, ostream &os,
OutputMode mode)
:_bbox(bb), _mode(mode),
_width((int)21*CM), _height((int)29.7*CM), _os(cerr)
{
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
_os=os;
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb, const char *fname,
OutputMode mode)
: _bbox(bb),_mode(mode),_width((int)21*CM), _height((int)29.7*CM),_os(cerr)
{
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
static ofstream os(fname);
_os=os;
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb,float H, ostream &os,
OutputMode mode)
: _bbox(bb), _mode(mode), _height(H), _os(cerr)
{
_width=(bb.xmax()-bb.xmin())*H/(bb.ymax()-bb.ymin());
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
_os=os;
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb,float H, const char *fname,
OutputMode m)
: _bbox(bb), _mode(m), _height(H), _os(cerr)
{
static ofstream os(fname);
_os=os;
_width=(bb.xmax()-bb.xmin())*H/(bb.ymax()-bb.ymin());
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb,float L, float H,
ostream &os, OutputMode mode)
: _bbox(bb), _mode(mode), _width(L), _height(H), _os(cerr)
{
_os=os;
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
insert_catalogue();
}
CGAL_PS_Stream::CGAL_PS_Stream(const PS_BBox &bb,float L, float H,
const char *fname, OutputMode mode)
: _bbox(bb), _mode(mode),_width(L),_height(H), _os(cerr)
{
static ofstream os(fname);
_os=os;
_xratio=_width/(_bbox.xmax()-_bbox.xmin());
_yratio=_height/(_bbox.ymax()-_bbox.ymin());
insert_catalogue();
}
@}
Destructor :
The destructor insert all the latex instruction if needed.
Then, it inserts all the latex labels, and finaly it closes the stream.
@$@<Constructors and Destructors@>+=@{@-
CGAL_PS_Stream::~CGAL_PS_Stream()
{
List_Label tmp=list();
if (!list().empty())
{
os() << "%%}\\makeatletter\\let\\@@notdefinable\\relax" <<endl;
os() << "%%\\def\\IPEc#1[#2]#3{\\newcommand{#1}[#2]{#3}\\ignorespaces}\\@@ifundefined" <<endl;
os() << "%%{selectfont}{\\let\\selectfont\\relax\\def\\fontsize#1#2{}}{}\\makeatother" <<endl;
os() << "%%\\IPEc\\IPEput[4]{\\put(0,0){\\special{psfile=\\IPEfile}}}" <<endl;
os() << "%%\\IPEc\\IPEmp[2]{\\minipage[t]{#1bp}#2\\special{color pop}\\endminipage}" <<endl;
os() << "%%\\IPEc\\IPEtext[1]{\\makebox(0,0)[lb]{#1\\special{color pop}}}" <<endl;
os() << "%%\\IPEc\\IPEfs[1]{\\IPEcolfs{0 0 0}{#1}}" <<endl;
os() << "%%\\IPEc\\IPEcolfs[2]{\\dimen0=#2pt\\fontsize{#2}{1.2\\dimen0}\\selectfont" <<endl;
os() << "%%\\special{color push rgb #1}}" <<endl;
os() << "%%\\IPEc\\IPEsize[2]{\\unitlength1bp\\ignorespaces}" <<endl;
os() << "%%\\IPEsize{" << width() << "}{"<< height() << "}" <<endl;
os() << "%%\\begin{picture}(" << width() << "," << height() << ")(0,0)" <<endl;
os() << "%%\\IPEput{0}{0}{" << width() << "}{" << height() << "}" <<endl;
while (!tmp.empty())
{
os() << "%%\\put(" << tmp.front().xpos()
<< "," <<tmp.front().ypos()
<<"){\\IPEtext{\\IPEfs{10}\\rm "<< tmp.front().text()
<<" }}" << endl;
tmp.pop_front();
}
os() << "%%\\end{picture}\\endinput}" <<endl;
}
os() << "showpage\nend" << endl ;
cout << flush;
}
@}
\subsection{Implementation : Modifying the State of the Stream}
Manipulators are functions inserted into Postscript Stream to
change the state of the stream.
The user will write streams like that :
{\tt ps << set\_line\_width(4) << segment;}
The construction of manipulators is :
@$@<Manipulators Constructors@>+=@{@-
#ifndef CGAL_PS_MANIP_DEF
#define CGAL_PS_MANIP_DEF
CGAL_PS_Modifier_creator<CGAL_Color &>
set_border_color(&CGAL_PS_Stream::_SetBorderColor);
CGAL_PS_Modifier_creator<CGAL_Color &>
set_fill_color(&CGAL_PS_Stream::_SetFillColor);
CGAL_PS_Modifier_creator<unsigned int>
set_point_size(&CGAL_PS_Stream::_SetPointSize);
CGAL_PS_Modifier_creator<CGAL_PS_Stream::DotStyle>
set_point_style(&CGAL_PS_Stream::_SetPointStyle);
CGAL_PS_Modifier_creator<DashStyle>
set_line_style(&CGAL_PS_Stream::_SetLineStyle);
CGAL_PS_Modifier_creator<unsigned int>
set_line_width(&CGAL_PS_Stream::_SetLineWidth);
CGAL_PS_Modifier_creator<bool>
set_fill(&CGAL_PS_Stream::_SetFill);
CGAL_PS_Modifier_creator<const CGAL_PS_Stream::Context &>
set_current_context(&CGAL_PS_Stream::_SetCurrentContext);
CGAL_PS_Modifier_creator<bool>
show_direction(&CGAL_PS_Stream::_ShowDirection);
CGAL_PS_Modifier_creator<CGAL_Point_2< CGAL_Cartesian <double> > >
move_to(&CGAL_PS_Stream::_MoveTo);
CGAL_PS_Modifier_creator<CGAL_PS_Stream::Axis &>
show_axis(&CGAL_PS_Stream::_ShowAxis);
CGAL_PS_Modifier_creator<CGAL_PS_Stream::Grid &>
show_grid(&CGAL_PS_Stream::_ShowGrid);
CGAL_PS_Modifier_creator<const char *>
put_ps_label(&CGAL_PS_Stream::_PutPsLabel);
CGAL_PS_Modifier_creator<const char *>
put_latex_label(&CGAL_PS_Stream::_PutLatexLabel);
CGAL_PS_Modifier_creator<unsigned int>
put_border(&CGAL_PS_Stream::_PutBorder);
CGAL_PS_Modifier_creator<const char *>
set_font(&CGAL_PS_Stream::_SetFont);
CGAL_PS_Modifier_creator<unsigned int>
set_font_size(&CGAL_PS_Stream::_SetFontSize);
#endif //CGAL_PS_MANIP_DEF
@}
This is the class that allows to use manipulators in streams.
It is define with a pointer on a function with only one parameter
and returning the same type of value. This class contains a field
named param that is the value of the modifier inserted in the stream.
We will see further the definitions off the functions called by this way.
@$@<Manipulators@>+=@{@-
#ifndef CGAL_PS_MANIP_H_
#define CGAL_PS_MANIP_H_
class CGAL_PS_Stream;
template <class T>
class CGAL_PS_Modifier {
friend CGAL_PS_Stream& operator<<(CGAL_PS_Stream& pss,
const CGAL_PS_Modifier<T> &);
public:
CGAL_PS_Modifier(CGAL_PS_Stream& (CGAL_PS_Stream::*f)(T),T v):
_PS_func(f), param(v) {}
private:
CGAL_PS_Stream& (CGAL_PS_Stream::*_PS_func)(T);
T param;
};
template <class T>
CGAL_PS_Stream& operator<<(CGAL_PS_Stream& pss, const CGAL_PS_Modifier<T> &m)
{
(pss.*m._PS_func)(m.param);
return pss;
};
template<class T>
class CGAL_PS_Modifier_creator {
public:
CGAL_PS_Modifier_creator(CGAL_PS_Stream& (CGAL_PS_Stream::*f)(T)):
_PS_func(f) {}
CGAL_PS_Modifier<T> operator() (T param)
{
return CGAL_PS_Modifier<T>(_PS_func,param);
}
private:
CGAL_PS_Stream& (CGAL_PS_Stream::*_PS_func)(T);
};
#endif //CGAL_PS_MANIP_H_
@}
\subsection{Implementation : The Catalogue}
This function set the default context in the postscript stream.
@$@<Non-Template Output Operators@>+=@{@-
void CGAL_PS_Stream::setdefault()
{
if (ctxt.get_border_color()!=CGAL_CTXT_DEFAULT.get_border_color())
os()<<"0 0 0 setrgbcolor"<<endl;
if (ctxt.get_line_style()!=CGAL_CTXT_DEFAULT.get_line_style())
os() << CGAL_PS_Stream::SOLID << " setdash"<<endl;
if (ctxt.get_thickness()!=CGAL_CTXT_DEFAULT.get_thickness())
os() << 0 << " setlinewidth"<<endl;
if (ctxt.get_font_size()!=CGAL_CTXT_DEFAULT.get_font_size() ||
strcmp(ctxt.get_font(),CGAL_CTXT_DEFAULT.get_font())!=0)
{
os() << "/Helvetica findfont" <<endl;
os() << "12 scalefont setfont" << endl;
}
ctxt=CGAL_CTXT_DEFAULT;
}
bool CGAL_PS_Stream::is_eps()
{
return (bool)(mode()==QUIET_EPS || mode()==READABLE_EPS);
}
bool CGAL_PS_Stream::is_readable()
{
return (bool)(mode()==READABLE || mode()==READABLE_EPS);
}
@}
These function insert the postscript catalogue in the file.
Thanks to this catalogue the size of the file is reduced.
@$@<Non-Template Output Operators@>+=@{@-
void CGAL_PS_Stream::insert_catalogue()
{
if (is_eps())
{
os() << "%!PS-Adobe-3.0 EPSF 3.0" << endl;
os() << "%%BoundingBox: " << "0 0 "
<< width() << " " << height()<< endl;
os() << "%%Creator: CGAL_PS_Stream" << endl;
os() << "%%Title: (CGAL Output)" << endl;
os() << "%%CreationDate:" << endl;
}
else
{
os() << "%!PS-Adobe-3.0" << endl;
}
os() << "%%EndComments" <<endl<<endl;
// The next line is used to include Latex commands in the file.
// Thanks to this, it is possible to insert labels in the latex style.
os() << "{\\catcode37=9\\def\\IPEdummy{({{)}} pop" <<endl;
os() << "%% Ipe postscript prologue" << endl<<endl;
os() << "/CGAL_PS_Dict 14 dict def" << endl;
os() << "CGAL_PS_Dict begin" << endl;
os() << "/lt {lineto} bind def" << endl;
os() << "/mt {moveto} bind def" << endl;
os() << "/st {stroke} bind def" << endl;
os() << "/slw {setlinewidth} bind def" << endl;
os() << "/box {/siz exch def /yy "
<< "exch def /xx exch def xx siz sub yy siz sub siz 2 mul dup} bind def" << endl;
os() << "/fb {box rectfill} bind def" << endl;
os() << "/eb {gsave box 4 copy gsave 1 setgray rectfill grestore "
<< "[] 0 setdash 0 setlinewidth rectstroke grestore} bind def" << endl;
os() << "/xc {gsave [] 0 setdash 0 setlinewidth "
<< "/siz exch def /yy exch def /xx exch def "
<< "xx siz sub yy siz sub mt xx siz add yy siz add lineto stroke "
<< "xx siz sub yy siz add mt xx siz add yy siz sub lineto "
<< "stroke grestore} bind def" << endl;
os() << "/ic {gsave [] 0 setdash 0 setlinewidth "
<< "/siz exch def /yy exch def /xx exch def "
<< "xx siz sub yy mt xx siz add yy lineto stroke "
<< "xx yy siz add mt xx yy siz sub "
<<"lineto stroke grestore} bind def" << endl;
os() << "/cir {0 360 arc} bind def" << endl;
os() << "/ec {gsave 3 copy gsave 1 setgray cir fill grestore "
<< "[] 0 setdash 0 setlinewidth cir stroke grestore} bind def" << endl;
os() << "/fc {cir fill} bind def" << endl;
os() << "/sc {setrgbcolor} bind def" << endl;
os() << "/tr {mt lt lt lt} bind def" << endl;
os() << "/re {mt lt lt lt lt} bind def" << endl;
os() << "0 0 0 setrgbcolor"<<endl;
os() << CGAL_PS_Stream::SOLID << " setdash"<<endl;
os() << 0 << " setlinewidth"<<endl;
os() << "/Helvetica findfont" <<endl;
os() << "12 scalefont setfont" << endl;
os() << "0 0 " << width() << " " << height() << " rectclip" << endl;
setdefault();
}
@}
\subsection{Implementation : Manipulators}
Manipulators allow to influence the state of the stream. They permit
to change the color, the line width, the line style, the size and the style
of the dot when we draw a point, to instert label in the stream,
to set the font of the text and its size.
From an implementation point of view there are different solutions.
We use a class defining pointers on member fonctions.
This is the definition of member function called when a modifier is
inserted in the stream.
@$@<Non-Template Output Modifiers@>+=@{@-
CGAL_PS_Stream& CGAL_PS_Stream::_SetBorderColor(CGAL_Color &color)
{
if (ctxt.get_border_color()!=color)
{
os() << color.r() << " " << color.g() << " " << color.b()
<< " setrgbcolor" <<endl;
ctxt.set_border_color(color);
}
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetFillColor(CGAL_Color &color)
{
ctxt.set_fill_color(color);
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetPointSize(unsigned int Size)
{
ctxt.set_dot_size(Size);
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetLineWidth(unsigned int Width)
{
if (ctxt.get_thickness()!=Width)
{
os()<< Width <<" setlinewidth" <<endl;
ctxt.set_thickness(Width);
}
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetPointStyle(DotStyle Style)
{
ctxt.set_dot_style(Style);
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetLineStyle(DashStyle style)
{
if (strcmp(ctxt.get_line_style(),style))
{
ctxt.set_line_style(style);
os() << style << " setdash" << endl;
}
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetFill(bool test)
{
ctxt.set_fill(test);
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetDefaultContext(void)
{
setdefault();
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetCurrentContext(const CGAL_PS_Stream::Context &c)
{
if (ctxt.get_border_color()!=c.get_border_color())
os()<< c.get_border_color().r() << " "
<< c.get_border_color().g() << " "
<< c.get_border_color().b() << " setrgbcolor"<<endl;
if (strcmp(ctxt.get_line_style(),c.get_line_style()))
os() << c.get_line_style() << " setdash"<<endl;
if (ctxt.get_thickness()!=c.get_thickness())
os() << c.get_thickness() << " setlinewidth"<<endl;
if (ctxt.get_font_size()!=c.get_font_size() ||
strcmp(ctxt.get_font(),c.get_font())!=0)
{
os() << "/" << c.get_font() << " findfont" <<endl;
os() << c.get_font_size() << " scalefont setfont" << endl;
}
ctxt=c;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_ShowDirection(bool choice)
{
if (choice){};
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_MoveTo(CGAL_Point_2< CGAL_Cartesian <double> > p)
{
ctxt.set_current_pos(p);
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_ShowAxis(Axis &g)
{
static bool test=false;
double x0=x2ps(0);
double y0=y2ps(0);
double i;
if (!test)
{
os() << "gsave 0 setgray " << g.thickness()
<< " setlinewidth" << endl;
os() << "[] 0 setdash" << endl;
os() << x0 << " " << 0 << " mt" <<endl;
os() << x0 << " " << height() << " lt st" << endl;
os() << 0 << " " << y0 << " mt" <<endl;
os() << width() << " " << y0 << " lt st" <<endl;
if (g.stepx())
{
for (i=((int) (bbox().xmin() / g.stepx())) *g.stepx();
i<= bbox().xmax();
i+=g.stepx()){
double x=x2ps(i);
os() << x << " " << y0 << " mt" <<endl;
os() << x << " " << y0+2 << " lt st" << endl;
}
}
if (g.stepy())
{
for (i=((int) (bbox().ymin() / g.stepy())) *g.stepy();
i<=bbox().ymax();
i+=g.stepy()){
double y=y2ps(i);
os() << x0 << " " << y << " mt" <<endl;
os() << x0+2 << " " << y << " lt st" << endl;
}
}
os() << "grestore" <<endl;
}
test=true;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_ShowGrid(Grid &g)
{
double i;
os() << "gsave 0 setgray 0 setlinewidth" << endl;
os() << g.style() << " setdash" << endl;
if (g.stepx())
{
for (i=((int) (bbox().xmin() / g.stepx())) *g.stepx();
i<=bbox().xmax();
i+=g.stepx()){
double x=x2ps(i);
os() << x << " 0 mt" <<endl;
os() << x << " " << height() << " lt st" << endl;
}
}
if (g.stepy())
{
for (i=((int) (bbox().ymin() / g.stepy())) *g.stepy();
i<=bbox().ymax();
i+=g.stepy()){
double y=y2ps(i);
os() << " 0 " << y << " mt" <<endl;
os() << width() << " " << y << " lt st" << endl;
}
}
os() << "grestore" <<endl;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_PutPsLabel(const char *ch)
{
os() << x2ps(context().get_pos().x()) << " "
<< y2ps(context().get_pos().y()) << " mt" <<endl;
os() << "(" << ch << ") show" << endl;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_PutLatexLabel(const char *ch)
{
//os() << "%% CGAL - LATEX : " << x2ps(context().get_pos().x()) << " "
// << y2ps(context().get_pos().y()) << " " << ch << endl;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_PutBorder(unsigned int i)
{
os() << "gsave" << endl;
os() << "0 setgray [] 0 setdash" << endl;
os() << i << " setlinewidth" << endl;
os() << "0 0 " << width() << " " << height() << " rectstroke" << endl;
os() << "grestore" << endl;
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetFont(const char *ch)
{
if (strcmp(ch,context().get_font())!=0)
{
os() << "/" << ch << " findfont" << endl;
os() << context().get_font_size() << " scalefont setfont" << endl;
ctxt.set_font(ch);
}
return *this;
}
CGAL_PS_Stream& CGAL_PS_Stream::_SetFontSize(unsigned int i)
{
if (context().get_font_size()!=i)
{
ctxt.set_font_size(i);
os() << "/" << context().get_font() << " findfont" << endl;
os() << i << " scalefont setfont" <<endl;
}
return *this;
}
@}
\subsection{Implementation : Output Operators}
Each geometric class of \cgal\ gets its own ouptput operator. We encapsulate
each definition in a {\tt \#ifdef/\#endif} pair so that a user
does not implicitely include all geometric header files by including the
Postscript stream.
@$@<Non-Template Output Operators@>+=@{@-
#ifndef _PS_LABEL_
#define _PS_LABEL_
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Border &b)
{
ps.os() << "gsave" << endl;
ps.os() << "0 setgray [] 0 setdash" << endl;
ps.os() << b.size() << " setlinewidth" << endl;
ps.os() << "0 0 " << ps.width() << " " << ps.height() << " rectstroke" << endl;
ps.os() << "grestore" << endl;
return ps;
}
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Label &txt)
{
ps.os() << ps.x2ps(ps.context().get_pos().x()) << " "
<< ps.y2ps(ps.context().get_pos().y()) << " mt" <<endl;
ps.os() << "(" << txt.text() << ") show" << endl;
return ps;
}
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, CGAL_PS_Stream::Latex_Label &txt)
{
txt.setposition(ps.x2ps(ps.context().get_pos().x()),
ps.y2ps(ps.context().get_pos().y()));
txt.text();
ps.list().push_front(txt);
return ps;
}
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Grid &g)
{
double i;
ps.os() << "gsave 0 setgray 0 setlinewidth" << endl;
ps.os() << g.style() << " setdash" << endl;
if (g.stepx())
{
for (i=((int) (ps.bbox().xmin() / g.stepx())) *g.stepx();
i<=ps.bbox().xmax();
i+=g.stepx()){
double x=ps.x2ps(i);
ps.os() << x << " 0 mt" <<endl;
ps.os() << x << " " << ps.height() << " lt st" << endl;
}
}
if (g.stepy())
{
for (i=((int) (ps.bbox().ymin() / g.stepy())) *g.stepy();
i<=ps.bbox().ymax();
i+=g.stepy()){
double y=ps.y2ps(i);
ps.os() << " 0 " << y << " mt" <<endl;
ps.os() << ps.width() << " " << y << " lt st" << endl;
}
}
ps.os() << "grestore" <<endl;
return ps;
}
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_PS_Stream::Axis &g)
{
static bool test=false;
double x0=ps.x2ps(0);
double y0=ps.y2ps(0);
double i;
if (!test)
{
ps.os() << "gsave 0 setgray " << g.thickness()
<< " setlinewidth" << endl;
ps.os() << "[] 0 setdash" << endl;
ps.os() << x0 << " " << 0 << " mt" <<endl;
ps.os() << x0 << " " << ps.height() << " lt st" << endl;
ps.os() << 0 << " " << y0 << " mt" <<endl;
ps.os() << ps.width() << " " << y0 << " lt st" <<endl;
if (g.stepx())
{
for (i=((int) (ps.bbox().xmin() / g.stepx())) *g.stepx();
i<= ps.bbox().xmax();
i+=g.stepx()){
double x=ps.x2ps(i);
ps.os() << x << " " << y0 << " mt" <<endl;
ps.os() << x << " " << y0+2 << " lt st" << endl;
}
}
if (g.stepy())
{
for (i=((int) (ps.bbox().ymin() / g.stepy())) *g.stepy();
i<=ps.bbox().ymax();
i+=g.stepy()){
double y=ps.y2ps(i);
ps.os() << x0 << " " << y << " mt" <<endl;
ps.os() << x0+2 << " " << y << " lt st" << endl;
}
}
ps.os() << "grestore" <<endl;
}
test=true;
return ps;
}
#endif
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_POINT_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_Point_2<R> &p)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Point" << endl;
ps.os() << "%CGAL% "<<p.x()<<" "<<p.y()<<endl;
}
if (ps.context().get_dot_style()!=CGAL_PS_Stream::NONE)
ps.os() << ps.x2ps(p.x()) << " "
<< ps.y2ps(p.y()) << " "
<< ps.context().get_dot_size() << " ";
switch (ps.context().get_dot_style())
{
case CGAL_PS_Stream::EBOX:
ps.os() << "eb" << endl;
break;
case CGAL_PS_Stream::FBOX:
ps.os() << "fb" << endl;
break;
case CGAL_PS_Stream::EDOT:
ps.os() << "ec" << endl;
break;
case CGAL_PS_Stream::FDOT:
ps.os() << "fc" << endl;
break;
case CGAL_PS_Stream::ICROSS:
ps.os() << "ic" << endl;
break;
case CGAL_PS_Stream::XCROSS:
ps.os() << "xc" << endl;
break;
}
return ps;
}
#endif // CGAL_POINT_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_SEGMENT_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_Segment_2<R> &s)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Segment" << endl;
ps.os() << "%CGAL% "<<s.source().x()<<" "<<s.source().y()<<" "
<<s.target().x()<<" "<<s.target().y()<<endl;
}
ps.os() << ps.x2ps(s.source().x()) << " "
<< ps.y2ps(s.source().y()) << " mt ";
ps.os() << ps.x2ps(s.target().x()) << " "
<< ps.y2ps(s.target().y())
<< " lt st" << endl;
return ps;
}
#endif // CGAL_SEGMENT_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_LINE_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_Line_2<R> &l)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Line" << endl;
ps.os() << "%CGAL% "<<l.a()<<" "<<l.b()<<" "<<l.c()<<endl;
}
if (!l.is_degenerate())
if (l.is_vertical())
{
double t=ps.x2ps(l.x_at_y(0));
ps.os()<< t;
ps.os()<< " 0 mt" << endl;
ps.os()<< t << " " << ps.height() << " lt st" <<endl;
}
else
{
ps.os() << "0 "
<< ps.y2ps(l.y_at_x(ps.bbox().xmin()))
<< " mt" << endl;
ps.os() << ps.width() << " "
<< ps.y2ps(l.y_at_x(ps.bbox().xmax()))
<< " lt st"<< endl;
}
return ps;
}
#endif // CGAL_LINE_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_RAY_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps, const CGAL_Ray_2<R> &r)
{
typedef CGAL_Direction_2<CGAL_Cartesian <double> > dir;
CGAL_Line_2<R> l=r.supporting_line();
dir haut(0,1);
dir bas(0,-1);
if (ps.is_readable())
{
ps.os() << "%CGAL% Ray" << endl;
ps.os() << "%CGAL% "<<r.source().x()<<" "<<r.source().y()<<" ";
ps.os() << r.second_point().x() << " " << r.second_point().y() <<endl;
}
if (!r.is_degenerate())
{
ps.os()<< ps.x2ps(r.source().x()) << " "
<< ps.y2ps(r.source().y()) << " mt" << endl;
if (r.is_vertical())
{
ps.os()<< ps.x2ps(r.source().x()) << " ";
if (r.direction()==haut)
ps.os() << ps.height();
else
ps.os() << "0 ";
ps.os() << " lt st" << endl;
}
else
if (r.direction()>bas || r.direction()<haut)
ps.os() << ps.width()
<< " "
<<ps.y2ps(l.y_at_x(ps.bbox().xmax()))
<< " lt st" << endl;
else
ps.os() << "0 "
<< ps.y2ps(l.y_at_x(ps.bbox().xmin()))
<< " lt st" << endl;
}
return ps;
}
#endif // CGAL_RAY_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_PARABOLA_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps,const CGAL_Parabola<R> &p)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Parabola" << endl;
ps.os() << "%CGAL% Base "<<p.base().x()<<" "<<p.base().y()<<endl;
ps.os() << "%CGAL% Vector "<<p.vertor().x()<<" "p.vector().y()<<endl;
ps.os() << "%CGAL% Curvature "<<p.curvature()<<endl;
}
return ps;
}X
#endif // CGAL_PARABOLA_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_TRIANGLE_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps,const CGAL_Triangle_2<R> &t)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Triangle" << endl;
for (int i=0;i<3;i++)
ps.os() << "%CGAL " << t[i].x() << " " << t[i].y() << endl;
}
for (int i=0;i<4;i++)
ps.os() << ps.x2ps(t[i].x())<< " " << ps.y2ps(t[i].y()) << " ";
ps.os() << "tr ";
if (ps.context().get_fill())
{
ps.os() << "gsave " << endl;
ps.os() << ps.context().get_fill_color().r() << " "
<< ps.context().get_fill_color().g() << " "
<< ps.context().get_fill_color().b()
<< " setcolor fill grestore " <<endl;
}
ps.os() << "st" <<endl;
return ps;
}
#endif // CGAL_TRIANGLE_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_ISO_RECTANGLE_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps,const CGAL_Iso_rectangle_2<R> &r)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Rectangle" << endl;
for (int i=0;i<4;i++)
ps.os() << "%CGAL " << r[i].x() << " " << r[i].y() << endl;
}
for (int i=0;i<5;i++)
ps.os() << ps.x2ps(r[i].x()) << " " << ps.y2ps(r[i].y()) << " ";
ps.os() << "re ";
if (ps.context().get_fill())
{
ps.os() << "gsave " << endl;
ps.os() << ps.context().get_fill_color().r() << " "
<< ps.context().get_fill_color().g() << " "
<< ps.context().get_fill_color().b()
<< " setcolor fill grestore " <<endl;
}
ps.os() << "st" <<endl;
return ps;
}
#endif // CGAL_ISO_RECTANGLE_2_H
@}
@$@<Output Operators@>+=@{@-
#ifdef CGAL_CIRCLE_2_H
template < class R >
CGAL_PS_Stream &operator<<(CGAL_PS_Stream &ps,
const CGAL_Circle_2<R> &c)
{
if (ps.is_readable())
{
ps.os() << "%CGAL% Circle" << endl;
ps.os() << "%CGAL " << c.center().x() << " " << c.center().y() << endl;
ps.os() << "%CGAL " << c.squared_radius() << endl;
}
double ratio=ps.yratio()/ps.xratio();
ps.os()<< "gsave 1 " << ratio << " scale" << endl;
ps.os()<< ps.x2ps(c.center().x()) << " " << ps.y2ps(c.center().y())/ratio
<< " " << c.squared_radius()*ps.xratio() << " 0 360 arc " << endl;
if (ps.context().get_fill())
{
ps.os() << "gsave " << endl;
ps.os() << ps.context().get_fill_color().r() << " "
<< ps.context().get_fill_color().g() << " "
<< ps.context().get_fill_color().b()
<< " setcolor fill grestore " <<endl;
}
ps.os() << "st grestore" <<endl;
return ps;
}
#endif // CGAL_CIRCLE_2_H
@}
\section{Output Files}
\subsection{The Source File}
@O@<../src/Postscript_stream.C@>==@{@-
#include <CGAL/IO/Postscript_stream.h>
@<Constructors and Destructors@>
@<Manipulators Constructors@>
@<Non-Template Output Modifiers@>
@<Non-Template Output Operators@>
@}
\subsection{The Header File}
@O@<../include/CGAL/IO/Postscript_stream.h@>==@{@-
#ifndef CGAL_Postscript_STREAM
#define CGAL_Postscript_STREAM
// For g++ compiler... //
#include <CGAL/Cartesian.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <iomanip.h>
#include <fcntl.h>
#include <fstream.h>
#include <strstream.h>
#include <list.h>
#include <LEDA/basic.h>
#include <CGAL/IO/Color.h>
#include <CGAL/Point_2.h>
#include <CGAL/Direction_2.h>
#include <CGAL/Bbox_2.h>
@<Manipulators@>
@<class CGAL_PS_Stream@>
@<Output Operators@>
#endif // CGAL_Postscript_STREAM
@}
\end{document}