/*******************************************************************************
+
+  LEDA 3.5
+
+  rat_polygon.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#ifndef LEDA_RAT_POLYGON_H
#define LEDA_RAT_POLYGON_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350111
#include <LEDA/REDEFINE_NAMES.h>
#endif


#include <LEDA/rat_point.h>
#include <LEDA/rat_segment.h>
#include <LEDA/rat_line.h>
#include <LEDA/list.h>
#include <LEDA/polygon.h>



class rat_polygon_rep : public handle_rep {

friend class rat_polygon;

  list<rat_point>   pt_list;
  list<rat_segment> seg_list;

public:

  rat_polygon_rep() {}
  rat_polygon_rep(const list<rat_segment>&);
 ~rat_polygon_rep() {}
   
};


/*{\Manpage {rat_polygon} {} {Rational Polygons} }*/

class list_rat_polygon_;

class rat_polygon   : public handle_base 
{
/*{\Mdefinition
An instance $P$ of the data type |rat_polygon| is a simple polygon
in the two-dimensional plane defined by the sequence of its vertices
in counter-clockwise order. Each vertex is represented by a
rational point. The number of vertices is called the size
of $P$. A rational polygon with empty vertex sequence is called empty.}*/

rat_polygon_rep* ptr() const { return (rat_polygon_rep*)PTR; }

rat_polygon(const list<rat_segment>& sl);

rational compute_area(const list<rat_segment>&) const;

public:

/*{\Mcreation P }*/

rat_polygon(const list<rat_point>& pl);
/*{\Mcreate 
introduces a variable |\Mvar| of type |\Mname|. |\Mvar| is initialized to the
rational polygon with vertex sequence $pl$.\\
\precond The vertices in $pl$ are given
in counter-clockwise order and define a simple polygon.}*/

rat_polygon() { PTR = new rat_polygon_rep; }
/*{\Mcreate 
introduces a variable |\Mvar| of type |\Mname|. |\Mvar| is initialized to the
empty polygon.}*/


 rat_polygon(const rat_polygon& P) : handle_base(P) {}
~rat_polygon() {}

 rat_polygon& operator=(const rat_polygon& P) 
 { handle_base::operator=(P); return *this;}


/*{\Moperations 3.5 4.6}*/

polygon     to_polygon() const;
/*{\Mop     returns a floating point approximation of the |\Mvar|. }*/

const list<rat_point>&   vertices() const  { return ptr()->pt_list; } 
/*{\Mop     returns the sequence of vertices of |\Mvar| in 
            counterclockwise ordering.  }*/

/*{\Moptions nextwarning=no}*/
const list<rat_segment>& segments() const { return ptr()->seg_list; }
const list<rat_segment>& edges() const { return ptr()->seg_list; }
/*{\Mop     returns the sequence of bounding segments 
	    of |\Mvar| in counterclockwise ordering. }*/

list<rat_point> intersection(const rat_segment& s) const;
/*{\Mopl    returns $P \cap s$ as a list of points.}*/

list<rat_point> intersection(const rat_line& l) const;
/*{\Mopl    returns $P \cap l$ as a list of points.}*/

/*{\Moptions nextwarning=no}*/
list_rat_polygon_ unite(const rat_polygon& Q) const;
/*
list<rat_polygon> unite(const rat_polygon& Q) const;
*/
/*{\Mopl    returns $P \cup Q$ as a list of polygons. The first polygon
            in the list gives the outer boundary of the contour of the union.
            Possibly following polygons define the inner boundaries (holes) 
            of the contour (holes). }*/

/*{\Moptions nextwarning=no}*/
list_rat_polygon_ intersection(const rat_polygon& Q) const;
/*
list<rat_polygon> intersection(const rat_polygon& Q) const;
*/
/*{\Mopl    returns $P \cap Q$ as a list of rational polygons.}*/

rat_polygon translate(rational dx, rational dy) const;
/*{\Mopl    returns |\Mvar| translated by vector $(dx,dy)$.}*/

rat_polygon translate(integer dx, integer dy, integer dw) const;
/*{\Mopl    returns |\Mvar| translated by vector $(dx/dw,dy/dw)$.}*/

rat_polygon translate(const rat_vector& v) const;
/*{\Mop     returns |\Mvar| translated by vector $v$.}*/

rat_polygon operator+(const rat_vector& v) const { return translate(v); }
/*{\Mbinop  returns |\Mvar| translated by vector $v$.}*/

rat_polygon operator-(const rat_vector& v) const { return translate(-v); }
/*{\Mbinop  returns |\Mvar| translated by vector $-v$.}*/


rat_polygon rotate90(const rat_point& q) const;
/*{\Mopl    returns |\Mvar| rotated by 90 degrees about $q$. }*/

rat_polygon reflect(const rat_point& p, const rat_point& q) const;
/*{\Mop     returns |\Mvar| reflected  across the straight line passing
            through $p$ and $q$.}*/

rat_polygon reflect(const rat_point& p) const;
/*{\Mop     returns |\Mvar| reflected  across point $p$.}*/


bool        inside(const rat_point& p) const;
/*{\Mop     returns true if $p$ lies inside of |\Mvar| and
	    false otherwise.}*/

bool        outside(const rat_point& p) const { return !inside(p); }
/*{\Mop     returns true if $p$ lies outside of |\Mvar| and
	    false otherwise.}*/

rational    area() const { return compute_area(ptr()->seg_list); }
/*{\Mop     returns the area of $P$.}*/

int         size()   const  { return ptr()->seg_list.size(); }
/*{\Mop     returns the size of |\Mvar|.}*/

bool        empty()  const  { return ptr()->seg_list.empty(); }
/*{\Mop     returns true if |\Mvar| is empty, false otherwise.}*/


bool    operator==(const rat_polygon& P1) const;

friend ostream& operator<<(ostream& out, const rat_polygon& p);
friend istream& operator>>(istream& in,  rat_polygon& p);

};



struct list_rat_polygon_: public list<rat_polygon>
{
  list_rat_polygon_(const list<rat_polygon>& L) : list<rat_polygon>(L) {}
  list_rat_polygon_() {}
 ~list_rat_polygon_() {}
};


inline char* leda_tname(const rat_polygon*) { return "rat_polygon"; }

/*{\Mtext
\bigskip
{\bf Iterations Macros}

{\bf forall\_vertices}($v,P$)       
$\{$ ``the vertices of $P$ are successively assigned to rat\_point $v$'' $\}$

{\bf forall\_segments}($s,P$)       
$\{$ ``the edges of $P$ are successively assigned to rat\_segment $s$'' $\}$ }*/

#if !defined(forall_vertices)
#define forall_vertices(v,P)  forall(v,P.vertices())
#endif

#if !defined(forall_segments)
#define forall_segments(s,P)  forall(s,P.segments())
#endif

#if LEDA_ROOT_INCL_ID == 350111
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif

#endif 
