// ===============================================================================
// Authors: AFRL/RQQA
// Organization: Air Force Research Laboratory, Aerospace Systems Directorate, Power and Control Division
// 
// Copyright (c) 2017 Government of the United State of America, as represented by
// the Secretary of the Air Force.  No copyright is claimed in the United States under
// Title 17, U.S. Code.  All Other Rights Reserved.
// ===============================================================================

/**
 * \file visilibity.hpp
 * \authors Karl J. Obermeyer
 * \date March 20, 2008
 *
VisiLibity:  A Floating-Point Visibility Algorithms Library,
Copyright (C) 2008  Karl J. Obermeyer (karl.obermeyer [ at ] gmail.com)

This file is part of VisiLibity.

VisiLibity is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.

VisiLibity is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.

You should have received a copy of the GNU Lesser General Public
License along with VisiLibity.  If not, see <http://www.gnu.org/licenses/>.
*/

/** 
 * \mainpage
 * <center> 
 * see also the <a href="../index.html">VisiLibity Project Page</a>
 * </center>
 * <b>Authors</b>:  Karl J. Obermeyer
 * <hr>
 * \section developers For Developers
 * <a href="../VisiLibity.coding_standards.html">Coding Standards</a>
 * <hr>
 * \section release_notes Release Notes
 * <b>Current Functionality</b>
 *   <ul>
 *      <li>visibility polygons in polygonal environments with holes</li>
 *      <li>visibility graphs</li>
 *      <li>shortest path planning for a point</li>
 *   </ul>
 */

#ifndef VISILIBITY_H
#define VISILIBITY_H

#include "boost/geometry.hpp"
#include "boost/geometry/geometries/point_xy.hpp"
#include "boost/geometry/geometries/polygon.hpp"

#ifndef NAN
#include <limits>
#define NAN std::numeric_limits<double>::quiet_NaN()
#endif

#ifndef INFINITY
#include <limits>
#define INFINITY std::numeric_limits<double>::infinity()
#endif

#ifndef M_PI
#define M_PI 3.141592653589793238462643
#endif

#include <iso646.h>   //aliases for boolean operators

#include <cmath>      //math functions in std namespace
#include <vector>
#include <queue>      //queue and priority_queue.
#include <set>        //priority queues with iteration, 
                      //integrated keys
#include <list>
#include <algorithm>  //sorting, min, max, reverse
#include <cstdlib>    //rand and srand
#include <ctime>      //Unix time
#include <fstream>    //file I/O
#include <iostream>
#include <cstring>    //C-string manipulation
#include <string>     //string class
#include <cassert>    //assertions

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif

#if (defined(__APPLE__) && defined(__MACH__))
#define OSX
#endif

/// VisiLibity's sole namespace
namespace VisiLibity
{

  //Fwd declaration of all classes and structs serves as index.
  struct Bounding_Box;
  class Point;
  class Line_Segment;
  class Angle;
  class Ray;
  class Polar_Point;
  class Polyline;
  class Polygon;
  class Environment;
  class Guards;
  class Visibility_Polygon;
  class Visibility_Graph;

  // 2-dimensional boost point
  typedef boost::geometry::model::d2::point_xy<double> boost_point;
  //boost polygon based on points, with counterclockwise orientation and not closed (ie last point != first point
  typedef boost::geometry::model::polygon<boost_point, false, false> boost_polygon;


  /** \brief  floating-point display precision.
   *
   * This is the default precision with which floating point
   * numbers are displayed or written to files for classes with a
   * write_to_file() method.
   */
  const int FIOS_PRECISION = 10;


  /** \brief  get a uniform random sample from an (inclusive) interval
   *          on the real line
   *
   * \author  Karl J. Obermeyer
   * \param lower_bound  lower bound of the real interval
   * \param upper_bound  upper bound of the real interval
   * \pre  \a lower_bound <= \a upper_bound 
   * \return  a random sample from a uniform probability distribution
   * on the real interval [\a lower_bound, \a upper_bound]
   * \remarks  Uses the Standard Library's rand() function. rand()
   * should be seeded (only necessary once at the beginning of the
   * program) using the command 
   * std::srand( std::time( NULL ) ); rand();
   * \warning  performance degrades as upper_bound - lower_bound
   * approaches RAND_MAX.
   */  
  double uniform_random_sample(double lower_bound, double upper_bound);

  /** \brief  rectangle with sides parallel to the x- and y-axes
   *
   * \author  Karl J. Obermeyer
   * Useful for enclosing other geometric objects.
   */
  struct Bounding_Box { double x_min, x_max, y_min, y_max; };

/** \brief  convert VisiLibity polygon to Boost polygon
 *
 * \author  Amanda Cinnamon
 * Written for use within Polygon union_ method
 */
  boost_polygon to_boost(std::vector<Polygon> x);

  /** \brief  convert VisilLibity polygon to Boost polygon
   *
   * \author  Amanda Cinnamon
   * Written for use within Polygon union_ method
   */
  std::vector<Polygon> to_visiLibity(boost_polygon x);

  /** \brief  convert VisiLibity polygon to Boost polygon
   *
   * \author  Amanda Cinnamon
   * Written for use within Polygon union_ method
   */
  boost_point to_boost(Point visPoint);

  /** \brief  convert VisilLibity polygon to Boost polygon
   *
   * \author  Amanda Cinnamon
   * Written for use within Polygon union_ method
   */
  Point to_visiLibity(boost_point x);

   /** \brief  search for polygons that are near (within epsilon) but not adjacent and force them to adjacent
   *
   * \author  Amanda Cinnamon
   * Written for use within Polygon union_ method
   */  
  void snap_near(std::vector<boost_polygon> &polygonList, double epsilon=0.0);

  /** \brief  identify pairs of boost polygons that overlap
   *
   * \author  Amanda Cinnamon
   * Written for use within Polygon union_ method
   */  
  std::vector<std::pair<int, int> > find_overlap(std::vector<boost_polygon> polygonList);

  /// Point in the plane represented by Cartesian coordinates
  class Point
  {
  public:
    //Constructors
    /** \brief  default
     *
     * \remarks Data defaults to NAN so that checking whether the
     * data are numbers can be used as a precondition in functions.
     */
    Point() : x_(NAN) , y_(NAN) { }
    /// construct from raw coordinates
    Point(double x_temp, double y_temp)
    { x_=x_temp; y_=y_temp; }
    //Accessors
    /// get x coordinate
    double x () const { return x_; }
    /// get y coordinate
    double y () const { return y_; }
    /** \brief closest Point on \a line_segment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers
     *       and \a line_segment_temp is nonempty
     * \return  the Point on \a line_segment_temp which is the smallest
     * Euclidean distance from the calling Point
     */
    Point projection_onto(const Line_Segment& line_segment_temp) const;
    /** \brief closest Point on \a ray_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point and \a ray_temp data are numbers
     * \return  the Point on \a ray_temp which is the smallest
     * Euclidean distance from the calling Point
     */
    Point projection_onto(const Ray& ray_temp) const;
    /** \brief  closest Point on \a polyline_temp
     *
     * \pre  the calling Point data are numbers and \a polyline_temp 
     * is nonempty
     * \return  the Point on \a polyline_temp which is the smallest
     * Euclidean distance from the calling Point
     */
    Point projection_onto(const Polyline& polyline_temp) const;
    /** \brief  closest vertex of \a polygon_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a polygon_temp
     * is nonempty
     * \return  the vertex of \a polygon_temp which is the
     * smallest Euclidean distance from the calling Point
     */
    Point projection_onto_vertices_of(const Polygon& polygon_temp) const;
    /** \brief  closest vertex of \a environment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a environment_temp
     * is nonempty
     * \return  the vertex of \a environment_temp which is
     * the smallest Euclidean distance from the calling Point
     */
    Point projection_onto_vertices_of(const Environment& 
                      enviroment_temp) const;
    /** \brief  closest Point on boundary of \a polygon_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a polygon_temp
     * is nonempty
     * \return  the Point on the boundary of \a polygon_temp which is the
     * smallest Euclidean distance from the calling Point
     */
    Point projection_onto_boundary_of(const Polygon& polygon_temp) const;
    /** \brief  closest Point on boundary of \a environment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a environment_temp
     * is nonempty
     * \return  the Point on the boundary of \a environment_temp which is
     * the smalles Euclidean distance from the calling Point
     */
    Point projection_onto_boundary_of(const Environment&
                      enviroment_temp) const;
    /** \brief  true iff w/in \a epsilon of boundary of \a polygon_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a polygon_temp
     * is nonempty
     * \return true iff the calling Point is within Euclidean distance 
     * \a epsilon of \a polygon_temp 's boundary
     * \remarks  O(n) time complexity, where n is the number
     * of vertices of \a polygon_temp
     */
    bool on_boundary_of(const Polygon& polygon_temp,
            double epsilon=0.0) const;
    /** \brief  true iff w/in \a epsilon of boundary of \a environment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a environment_temp
     * is nonempty
     * \return true iff the calling Point is within Euclidean distance 
     * \a epsilon of \a environment_temp 's boundary
     * \remarks  O(n) time complexity, where n is the number
     * of vertices of \a environment_temp
     */   
    bool on_boundary_of(const Environment& environment_temp,
            double epsilon=0.0) const;
    /** \brief true iff w/in \a epsilon of \a line_segment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a line_segment_temp
     * is nonempty
     * \return  true iff the calling Point is within distance 
     * \a epsilon of the (closed) Line_Segment \a line_segment_temp
     */
    bool in(const Line_Segment& line_segment_temp,
        double epsilon=0.0) const;
    /** \brief true iff w/in \a epsilon of interior but greater than 
     *         \a espilon away from endpoints of \a line_segment_temp
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a line_segment_temp 
     * is nonempty
     * \return  true iff the calling Point is within distance \a
     * epsilon of \line_segment_temp, but distance (strictly) greater
     * than epsilon from \a line_segment_temp 's endpoints.
     */
    bool in_relative_interior_of(const Line_Segment& line_segment_temp,
                 double epsilon=0.0) const;
    /** \brief  true iff w/in \a epsilon of \a polygon_temp
     *
     * \author  Karl J. Obermeyer
     *
     * \pre the calling Point data are numbers and \a polygon_temp is
     * \a epsilon -simple. Test simplicity with
     * Polygon::is_simple(epsilon)
     *
     * \return  true iff the calling Point is a Euclidean distance no greater
     * than \a epsilon from the (closed) Polygon (with vertices listed
     * either cw or ccw) \a polygon_temp.
     * \remarks  O(n) time complexity, where n is the number of vertices
     * in \a polygon_temp
     */
    bool in(const Polygon& polygon_temp,
        double epsilon=0.0) const;
    /** \brief  true iff w/in \a epsilon of \a environment_temp
     *
     * \author  Karl J. Obermeyer
     *
     * \pre the calling Point data are numbers and \a environment_temp
     * is nonempty and \a epsilon -valid. Test validity with
     * Enviroment::is_valid(epsilon)
     *
     * \return  true iff the calling Point is a Euclidean distance no greater
     * than \a epsilon from the in the (closed) Environment \a environment_temp
     * \remarks  O(n) time complexity, where n is the number of
     * vertices in \a environment_temp
     */
    bool in(const Environment& environment_temp,
        double epsilon=0.0) const;
    /** \brief  true iff w/in \a epsilon of some endpoint 
     *          of \a line_segment_temp
     *
     * \pre  the calling Point data are numbers and \a line_segment_temp
     * is nonempty
     * \return  true iff calling Point is a Euclidean distance no greater
     * than \a epsilon from some endpoint of \a line_segment_temp
     */
    bool is_endpoint_of(const Line_Segment& line_segment_temp,
            double epsilon=0.0) const;
    /** \brief  calculates the ccw oriented angle offset from the segment ab to the segment bc
     *
     * \author Derek Kingston
     * \remark Points a,b,c must be separated by epsilon > 0
     */
    static Angle angle_separation(const Point& a, const Point& b, const Point& c);
    /** \brief  calculates the point p rotated ccw around the origin by th
     *
     * \author Derek Kingston
     */
    static Point rotate(const Point& p, double th);
    /** \brief  returns a point in the same direction as the point p
     *          but with length 1.0
     *
     * \author Derek Kingston
     */
    static Point normalize(const Point& p);
    //Mutators
    /// change x coordinate
    void set_x(double x_temp) { x_ = x_temp;}
    /// change y coordinate
    void set_y(double y_temp) { y_ = y_temp;}
    /** \brief relocate to closest vertex if w/in \a epsilon of some
     *         vertex (of \a polygon_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a polygon_temp 
     * is nonempty
     * \post If the calling Point was a Euclidean distance no greater
     * than \a epsilon from any vertex of \a polygon_temp, then it
     * will be repositioned to coincide with the closest such vertex
     * \remarks O(n) time complexity, where n is the number of
     * vertices in \a polygon_temp.
     */
    void snap_to_vertices_of(const Polygon& polygon_temp,
                 double epsilon=0.0);
    /** \brief relocate to closest vertex if w/in \a epsilon of some
     *         vertex (of \a environment_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a environment_temp 
     * is nonempty
     * \post If the calling Point was a Euclidean distance no greater
     * than \a epsilon from any vertex of \a environment_temp, then it
     * will be repositioned to coincide with the closest such vertex
     * \remarks O(n) time complexity, where n is the number of
     * vertices in \a environment_temp.
     */
    void snap_to_vertices_of(const Environment& environment_temp,
                 double epsilon=0.0);
    /** \brief relocate to closest Point on boundary if w/in \a epsilon
     *           of the boundary (of \a polygon_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a polygon_temp 
     * is nonempty
     * \post if the calling Point was a Euclidean distance no greater
     * than \a epsilon from the boundary of \a polygon_temp, then it
     * will be repositioned to it's projection onto that boundary
     * \remarks O(n) time complexity, where n is the number of
     * vertices in \a polygon_temp.
     */
    void snap_to_boundary_of(const Polygon& polygon_temp,
                 double epsilon=0.0);
    /** \brief relocate to closest Point on boundary if w/in \a epsilon
     *           of the boundary (of \a environment_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the calling Point data are numbers and \a environment_temp
     * is nonempty
     * \post if the calling Point was a Euclidean distance no greater
     * than \a epsilon from the boundary of \a environment_temp, then it
     * will be repositioned to it's projection onto that boundary
     * \remarks O(n) time complexity, where n is the number of
     * vertices in \a environment_temp.
     */
    void snap_to_boundary_of(const Environment& environment_temp,
                 double epsilon=0.0);
  protected:
    double x_;
    double y_;
  };
  
  
  /** \brief True iff Points' coordinates are identical.
   *
   * \remarks  NAN==NAN returns false, so if either point has 
   * not been assigned real number coordinates, they will not be ==
   */
  bool  operator == (const Point& point1, const Point& point2);  
  /// True iff Points' coordinates are not identical.
  bool  operator != (const Point& point1, const Point& point2);
  
  
  /** \brief  compare lexicographic order of points
   *
   * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
   * p1.x()==p2.x() and p1.y()<p2.y().  False if any member data have
   * not been assigned (numbers).
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a line parallel to one of the axes
   */
  bool  operator <  (const Point& point1, const Point& point2);
  /** \brief  compare lexicographic order of points
   *
   * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
   * p1.x()==p2.x() and p1.y()<p2.y().  False if any member data have
   * not been assigned (numbers).
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a line parallel to one of the axes
   */
  bool  operator >  (const Point& point1, const Point& point2);
  /** \brief  compare lexicographic order of points
   *
   * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
   * p1.x()==p2.x() and p1.y()<p2.y().  False if any member data have
   * not been assigned (numbers).
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a line parallel to one of the axes
   */
  bool  operator >= (const Point& point1, const Point& point2);
  /** \brief  compare lexicographic order of points
   *
   * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
   * p1.x()==p2.x() and p1.y()<p2.y().  False if any member data have
   * not been assigned (numbers).
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a line parallel to one of the axes
   */
  bool  operator <= (const Point& point1, const Point& point2);


  /// vector addition of Points
  Point operator +  (const Point& point1, const Point& point2);
  /// vector subtraction of Points
  Point operator -  (const Point& point1, const Point& point2);


  //// dot (scalar) product treats the Points as vectors
  Point operator *  (const Point& point1, const Point& point2);
 

  /// simple scaling treats the Point as a vector
  Point operator *  (double scalar, const Point& point2); 
  /// simple scaling treats the Point as a vector
  Point operator *  (const Point&  point1, double scalar);


  /** \brief  cross product (signed) magnitude treats the Points as vectors
   *
   * \author  Karl J. Obermeyer
   * \pre  Points' data are numbers
   * \remarks This is equal to the (signed) area of the parallelogram created
   * by the Points viewed as vectors.
   */
  double cross(const Point& point1, const Point& point2);


  /** \brief  Euclidean distance between Points
   *
   * \pre  Points' data are numbers
   */
  double distance(const Point& point1, const Point& point2);


  /** \brief  Euclidean distance between a Point and a Line_Segment
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Line_Segment is nonempty
   */
  double distance(const Point& pointemp,
          const Line_Segment& line_segment_temp);
  /** \brief  Euclidean distance between a Point and a Line_Segment
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Line_Segment is nonempty
   */
  double distance(const Line_Segment& line_segment_temp,
          const Point& pointemp);


  /** \brief  Euclidean distance between a Point and a Ray
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's and Ray's data are numbers
   */
  double distance(const Point& pointemp,
          const Ray& ray_temp);
  /** \brief  Euclidean distance between a Point and a Ray
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's and Ray's data are numbers
   */
  double distance(const Ray& ray_temp,
          const Point& pointemp);


  /** \brief  Euclidean distance between a Point and a Polyline
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Polyline is nonempty
   */
  double distance(const Point& pointemp,
          const Polyline& polyline_temp);
  /** \brief  Euclidean distance between a Point and a Polyline
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Polyline is nonempty
   */
  double distance(const Polyline& polyline_temp,
          const Point& pointemp);


  /** \brief  Euclidean distance between a Point and a Polygon's boundary
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Polygon is nonempty
   */
  double boundary_distance(const Point& pointemp,
               const Polygon& polygon_temp);
  /** \brief  Euclidean distance between a Point and a Polygon's boundary
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Polygon is nonempty
   */
  double boundary_distance(const Polygon& polygon_temp,
               const Point& pointemp);


  /** \brief  Euclidean distance between a Point and a Environment's boundary
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Environment is nonempty
   */
  double boundary_distance(const Point& pointemp,
               const Environment& environment_temp);
  /** \brief  Euclidean distance between a Point and a Environment's boundary
   *
   * \author  Karl J. Obermeyer
   * \pre  Point's data are numbers and the Environment is nonempty
   */
  double boundary_distance(const Environment& environment_temp,
               const Point& pointemp);


  /// print a Point
  std::ostream& operator << (std::ostream& outs, const Point& pointemp);


  /** \brief line segment in the plane represented by its endpoints
   *
   * Closed and oriented line segment in the plane represented by its endpoints.
   * \remarks  may be degenerate (colocated endpoints) or empty
   */
  class Line_Segment
  {
  public:
    //Constructors
    /// default to empty
    Line_Segment();
    /// copy constructor
    Line_Segment(const Line_Segment& line_segment_temp);
    /// construct degenerate segment from a single Point
    Line_Segment(const Point& pointemp);
    /// Line_Segment pointing from first_pointemp to second_pointemp
    Line_Segment(const Point& first_pointemp,
         const Point& second_pointemp, double epsilon=0);
    //Accessors 
    /** \brief  first endpoint
     *
     * \pre size() > 0
     * \return  the first Point of the Line_Segment
     * \remarks  If size() == 1, then both first() and second() are valid 
     * and will return the same Point
     */
    Point first()  const;
    /** \brief  second endpoint
     *
     * \pre size() > 0
     * \return  the second Point of the Line_Segment
     * \remarks  If size() == 1, then both first() and second() are valid 
     * and will return the same Point
     */
    Point second() const;
    /** \brief  number of distinct endpoints
     *
     * \remarks
     * size 0 => empty line segment;
     * size 1 => degenerate (single point) line segment;
     * size 2 => full-fledged (bona fide) line segment
     */
    unsigned size() const { return size_; }
    /** \brief midpoint
     *
     * \pre size() > 0
     */
    Point midpoint() const;
    /** \brief Euclidean length
     *
     * \pre size() > 0
     */
    double length() const;
    /** \brief  true iff vertices in lex. order
     *
     * \pre  size() > 0
     * \return  true iff vertices are listed beginning with the vertex 
     * which is lexicographically smallest (lowest x, then lowest y)
     * \remarks  lex. comparison is very sensitive to perturbations if
     * two Points nearly define a line parallel to one of the axes
     */
    bool is_in_standard_form() const;
    //Mutators
    /// assignment operator
    Line_Segment& operator = (const Line_Segment& line_segment_temp);
    /** \brief set first endpoint
     *
     * \remarks  if \a pointemp is w/in a distance \a epsilon of an existing 
     * endpoint, the coordinates of \a pointemp are used and size is set to 
     * 1 as appropriate
     */
    void set_first(const Point& pointemp, double epsilon=0.0);
    /** \brief set second endpoint
     *
     * \remarks  if \a pointemp is w/in a distance \a epsilon of an existing 
     * endpoint, the coordinates of \a pointemp are used and size is set to 
     * 1 as appropriate
     */
    void set_second(const Point& pointemp, double epsilon=0.0);
    /** \brief  reverse order of endpoints
     *
     * \post order of endpoints is reversed.
     */
    void reverse();
    /** \brief  enforce that lex. smallest endpoint first
     *
     * \post the lexicographically smallest endpoint (lowest x, then lowest y)
     * is first
     * \remarks  lex. comparison is very sensitive to perturbations if
     * two Points nearly define a line parallel to one of the axes
     */
    void enforce_standard_form();
    /// erase both endpoints and set line segment empty (size 0)
    void clear();
    /// destructor
    virtual ~Line_Segment();
  protected:
    //Pointer to dynamic array of endpoints.
    Point *endpoints_;
    //See size() comments.
    unsigned    size_;
  };
  

  /** \brief  true iff endpoint coordinates are exactly equal, but
   *          false if either Line_Segment has size 0
   *
   * \remarks  respects ordering of vertices, i.e., even if the line segments 
   * overlap exactly, they are not considered == unless the orientations are 
   * the same
   */
  bool  operator == (const Line_Segment& line_segment1,
             const Line_Segment& line_segment2);
  /// true iff endpoint coordinates are not ==
  bool  operator != (const Line_Segment& line_segment1,
             const Line_Segment& line_segment2);
  

  /** \brief  true iff line segments' endpoints match up w/in a (closed)
   *          \a epsilon ball of each other, but false if either
   *          Line_Segment has size 0
   *
   * \author  Karl J. Obermeyer
   * \remarks  this function will return true even if it has to flip
   * the orientation of one of the segments to get the vertices to
   * match up
   */
  bool equivalent(Line_Segment line_segment1,
          Line_Segment line_segment2, double epsilon=0);


  /** \brief  Euclidean distance between Line_Segments
   *
   * \author  Karl J. Obermeyer
   * \pre  \a line_segment1.size() > 0 and \a line_segment2.size() > 0
   */
  double distance(const Line_Segment& line_segment1,
          const Line_Segment& line_segment2);


  /** \brief  Euclidean distance between a Line_Segment and the
   *          boundary of a Polygon
   *
   * \author  Karl J. Obermeyer
   * \pre  \a line_segment.size() > 0 and \a polygon.n() > 0
   */
  double boundary_distance(const Line_Segment& line_segment,
               const Polygon& polygon);


  /** \brief  Euclidean distance between a Line_Segment and the
   *          boundary of a Polygon
   *
   * \author  Karl J. Obermeyer
   * \pre  \a line_segment.size() > 0 and \a polygon.n() > 0
   */
  double boundary_distance(const Polygon& polygon,
               const Line_Segment& line_segment);


  /** \brief  true iff the Euclidean distance between Line_Segments is 
   *          no greater than \a epsilon, false if either line segment
   *          has size 0
   *
   * \author  Karl J. Obermeyer
   */
  bool intersect(const Line_Segment& line_segment1,
         const Line_Segment& line_segment2,
         double epsilon=0.0);


  /** \brief  true iff line segments intersect properly w/in epsilon,
   *          false if either line segment has size 0
   *
   * \author  Karl J. Obermeyer
   * \return true iff Line_Segments intersect exactly at a single
   * point in their relative interiors.  For robustness, here the
   * relative interior of a Line_Segment is consider to be any Point
   * in the Line_Segment which is a distance greater than \a epsilon
   * from both endpoints.
   */
  bool intersect_proper(const Line_Segment& line_segment1,
            const Line_Segment& line_segment2,
            double epsilon=0.0);


  /** \brief  intersection of Line_Segments
   *
   * \author  Karl J. Obermeyer
   * \return a Line_Segment of size 0, 1, or 2 
   * \remarks  size 0 results if the distance (or at least the
   * floating-point computed distance) between line_segment1 and
   * line_segment2 is (strictly) greater than epsilon. size 1 results
   * if the segments intersect poperly, form a T intersection, or --
   * intersection.  size 2 results when two or more endpoints are a
   * Euclidean distance no greater than \a epsilon from the opposite
   * segment, and the overlap of the segments has a length greater
   * than \a epsilon.
   */
  Line_Segment intersection(const Line_Segment& line_segment1,
                const Line_Segment& line_segment2,
                double epsilon=0.0);

  /** \brief  intersection of Line_Segments treated as infinitely long lines
   *
   * \author  Derek Kingston
   * \return a Line_Segment of size 0, 1, or 2 
   * \remarks  size 0 results if the lines are parallel or either line segment
   * has size less than 2. size 1 results otherwise. note, numerically unstable
   * when the lines are nearly parallel
   */
  Line_Segment intersection_infinite(const Line_Segment& line_segment1,
                const Line_Segment& line_segment2,
                double epsilon=0.0);


  /// print a Line_Segment
  std::ostream& operator << (std::ostream& outs, 
                 const Line_Segment& line_segment_temp);
  

  /** \brief  angle in radians represented by a value in 
   *          the interval [0,2*M_PI]
   *
   * \remarks  the intended interpretation is that angles 0 and 2*M_PI
   * correspond to the positive x-axis of the coordinate system
   */
  class Angle
  {
  public:
    //Constructors
    /** \brief  default
     *
     * \remarks  data defaults to NAN so that checking whether the
     * data are numbers can be used as a precondition in functions
     */
    Angle() : angle_radians_(NAN) { }
    /// construct from real value, mod into interval [0, 2*M_PI)
    Angle(double data_temp);
    /** \brief construct using 4 quadrant inverse tangent into [0, 2*M_PI),
     *         where 0 points along the x-axis
     */ 
    Angle(double rise_temp, double run_temp);
    //Accessors
    /// get radians
    double get() const { return angle_radians_; }
    //Mutators
    /// set angle, mod into interval [0, 2*PI)
    void set(double data_temp);
    /** \brief  set angle data to 2*M_PI
     *
     * \remarks  sometimes it is necessary to set the angle value to
     * 2*M_PI instead of 0, so that the lex. inequalities behave
     * appropriately during a radial line sweep
    */
    void set_to_2pi() { angle_radians_=2*M_PI; }
    /// set to new random angle in [0, 2*M_PI)
    void randomize();
  private:
    double angle_radians_;
  };


  /// compare angle radians
  bool operator  == (const Angle& angle1, const Angle& angle2);
  /// compare angle radians
  bool operator  != (const Angle& angle1, const Angle& angle2);


  /// compare angle radians
  bool operator  >  (const Angle& angle1, const Angle& angle2);
  /// compare angle radians
  bool operator  <  (const Angle& angle1, const Angle& angle2);
  /// compare angle radians
  bool operator  >= (const Angle& angle1, const Angle& angle2);
  /// compare angle radians
  bool operator  <= (const Angle& angle1, const Angle& angle2);


  /// add angles' radians and mod into [0, 2*M_PI)
  Angle operator +  (const Angle& angle1, const Angle& angle2);
  /// subtract angles' radians and mod into [0, 2*M_PI)
  Angle operator -  (const Angle& angle1, const Angle& angle2);


  /** \brief  geodesic distance in radians between Angles
   *
   * \author  Karl J. Obermeyer
   * \pre  \a angle1 and \a angle2 data are numbers
   */
  double geodesic_distance(const Angle& angle1, const Angle& angle2);


  /** \brief  1.0 => geodesic path from angle1 to angle2 
   *          is couterclockwise, -1.0 => clockwise
   *
   * \author  Karl J. Obermeyer
   * \pre  \a angle1 and \a angle2 data are numbers
   */
  double geodesic_direction(const Angle& angle1, const Angle& angle2); 


  /// print Angle
  std::ostream& operator << (std::ostream& outs, const Angle& angle_temp);


  /** \brief  Point in the plane packaged together with polar
   *          coordinates w.r.t. specified origin
   *
   * The origin of the polar coordinate system is stored with the
   * Polar_Point (in \a polar_origin_) and bearing is measured ccw from the
   * positive x-axis.
   * \remarks  used, e.g., for radial line sweeps
   */
  class Polar_Point : public Point
  {
  public:
    //Constructors
    /** \brief  default
     *
     * \remarks  Data defaults to NAN so that checking whether the
     * data are numbers can be used as a precondition in functions.
     */
    Polar_Point() : Point(), range_(NAN), bearing_(NAN) { }
    /** \brief  construct from (Cartesian) Points
     *
     * \pre  member data of \a polar_origin_temp and \a pointemp have
     * been assigned (numbers)
     * \param polar_origin_temp  the origin of the polar coordinate system
     * \param pointemp  the point to be represented
     * \remarks  if polar_origin_temp == pointemp, the default
     * bearing is Angle(0.0)
     */
    Polar_Point(const Point& polar_origin_temp,
        const Point& pointemp,
        double epsilon=0.0);
    //Accessors
    /** \brief  origin of the polar coordinate system in which the point is
     *          represented
     */
    Point polar_origin() const { return polar_origin_; }
    /// Euclidean distance from the point represented to the origin of
    /// the polar coordinate system
    double       range() const { return range_; }
    /// bearing from polar origin w.r.t. direction parallel to x-axis
    Angle      bearing() const { return bearing_; }
    //Mutators
    /** \brief  set the origin of the polar coordinate system
     *
     * \remarks x and y held constant, bearing and range modified
     * accordingly
     */
    void set_polar_origin(const Point& polar_origin_temp);
    /** \brief  set x
     *
     * \remarks  polar_origin held constant, bearing and range modified
     * accordingly
     */
    void set_x(double x_temp);
    /** \brief  set y
     *
     * \remarks  polar_origin held constant, bearing and range modified
     * accordingly
     */
    void set_y(double y_temp);
    /** \brief set range
     *
     * \remarks  polar_origin held constant, x and y modified
     * accordingly
     */
    void set_range(double range_temp);
    /** \brief set bearing
     *
     * \remarks  polar_origin and range held constant, x and y modified
     * accordingly
     */
    void set_bearing(const Angle& bearing_temp);
    /** \brief  set bearing Angle data to 2*M_PI
     *
     * \remarks  Special function for use in computations involving a
     * radial line sweep; sometimes it is necessary to set the angle
     * value to 2*PI instead of 0, so that the lex. inequalities
     * behave appropriately
     */
    void set_bearing_to_2pi() { bearing_.set_to_2pi(); }
  protected:
    //Origin of the polar coordinate system in world coordinates.
    Point  polar_origin_;
    //Polar coordinates where radius always positive, and angle
    //measured ccw from the world coordinate system's x-axis.
    double range_;
    Angle  bearing_;
  };


  /** \brief  compare member data
   *
   * \remarks  returns false if any member data are NaN
   */
  bool operator == (const Polar_Point& polar_point1,
            const Polar_Point& polar_point2);
  bool operator != (const Polar_Point& polar_point1,
            const Polar_Point& polar_point2);


  /** \brief  compare according to polar lexicographic order 
   *          (smaller bearing, then smaller range)
   *
   *  false if any member data have not been assigned (numbers)
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a radial line
   */
  bool operator >  (const Polar_Point& polar_point1,
               const Polar_Point& polar_point2);
  /** \brief  compare according to polar lexicographic order 
   *          (smaller bearing, then smaller range)
   *
   *  false if any member data have not been assigned (numbers)
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a radial line
   */ 
  bool operator <  (const Polar_Point& polar_point1,
               const Polar_Point& polar_point2);
  /** \brief  compare according to polar lexicographic order 
   *          (smaller bearing, then smaller range)
   *
   *  false if any member data have not been assigned (numbers)
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a radial line
   */ 
  bool operator >= (const Polar_Point& polar_point1,
               const Polar_Point& polar_point2);
  /** \brief  compare according to polar lexicographic order 
   *          (smaller bearing, then smaller range)
   *
   *  false if any member data have not been assigned (numbers)
   * \remarks  lex. comparison is very sensitive to perturbations if
   * two Points nearly define a radial line
   */ 
  bool operator <= (const Polar_Point& polar_point1,
               const Polar_Point& polar_point2);


  /// print Polar_Point
  std::ostream& operator << (std::ostream& outs,
                 const Polar_Point& polar_pointemp);


  /// ray in the plane represented by base Point and bearing Angle
  class Ray
  {
  public:
    //Constructors
    /** \brief  default
     *
     * \remarks data defaults to NAN so that checking whether the data
     * are numbers can be used as a precondition in functions
     */
    Ray() { }
    /// construct ray emanating from \a base_pointemp in the direction
    /// \a bearing_temp
    Ray(Point base_pointemp, Angle bearing_temp) : 
    base_point_(base_pointemp) , bearing_(bearing_temp) {}
    /// construct ray emanating from \a base_pointemp towards
    /// \a bearing_point
    Ray(Point base_pointemp, Point bearing_point);
    //Accessors
    /// get base point
    Point base_point() const { return base_point_; }
    /// get bearing
    Angle bearing() const { return bearing_; }
    //Mutators
    /// set base point
    void set_base_point(const Point& pointemp)
    { base_point_ = pointemp; }
    /// set bearing
    void set_bearing(const Angle& angle_temp)
    { bearing_ = angle_temp; } 
  private:
    Point base_point_;
    Angle bearing_;
  };


  /** \brief  compare member data
   *
   * \remarks  returns false if any member data are NaN
   */
  bool operator == (const Ray& ray1,
            const Ray& ray2);
  /** \brief  compare member data
   *
   * \remarks  negation of ==
   */
  bool operator != (const Ray& ray1,
            const Ray& ray2);


  /** \brief compute the intersection of a Line_Segment with a Ray
   *
   * \author  Karl J. Obermeyer
   * \pre  member data of \a ray_temp has been assigned (numbers) and
   * \a line_segment_temp has size greater than 0
   * \remarks  as a convention, if the intersection has positive
   * length, the Line_Segment returned has the first point closest to
   * the Ray's base point
   */
  Line_Segment intersection(const Ray ray_temp,
                const Line_Segment& line_segment_temp,
                double epsilon=0.0);
  /** \brief compute the intersection of a Line_Segment with a Ray
   *
   * \author  Karl J. Obermeyer
   * \pre  member data of \a ray_temp has been assigned (numbers) and
   * \a line_segment_temp has size greater than 0
   * \remarks  as a convention, if the intersection has positive
   * length, the Line_Segment returned has the first point closest to
   * the Ray's base point
   */
  Line_Segment intersection(const Line_Segment& line_segment_temp,
                const Ray& ray_temp,
                double epsilon=0.0);


  ///oriented polyline in the plane represented by list of vertices
  class Polyline
  {
  public:
    friend class Point;
    //Constructors
    /// default to empty
    Polyline() { }
    /// construct from vector of vertices
    Polyline(const std::vector<Point>& vertices_temp)
    { vertices_ = vertices_temp; }
    //Accessors
    /** \brief  raw access
     *
     * \remarks for efficiency, no bounds checks; usually trying to
     * access out of bounds causes a bus error
     */
    Point operator [] (unsigned i) const
    { return vertices_[i]; }
    /// vertex count
    unsigned size() const
    { return vertices_.size(); }
    /// Euclidean length of the Polyline
    double length() const;
    /** \brief  Euclidean diameter
     *
     * \pre  Polyline has greater than 0 vertices
     * \return  the maximum Euclidean distance between all pairs of
     * vertices
     * \remarks  time complexity O(n^2), where n is the number of
     * vertices representing the Polyline
     */
    double diameter() const;
    //a box which fits snugly around the Polyline
    Bounding_Box bbox() const;
    //Mutators
    /** \brief  raw access
     *
     * \remarks for efficiency, no bounds checks; usually trying to
     * access out of bounds causes a bus error
     */
    Point& operator [] (unsigned i)
    { return vertices_[i]; }
    /// erase all points
    void clear()
    { vertices_.clear(); }
    /// add a vertex to the back (end) of the list
    void push_back(const Point& pointemp)
    { vertices_.push_back(pointemp); }
    /// delete a vertex to the back (end) of the list
    void pop_back()
    { vertices_.pop_back(); }
    /// reset the whole list of vertices at once
    void set_vertices(const std::vector<Point>& vertices_temp)
    { vertices_ = vertices_temp; }
    /** \brief  eliminates vertices which are (\a epsilon) - colinear
     *          with their respective neighbors
     *
     * \author  Karl J. Obermeyer
     * \post  the Euclidean distance between each vertex and the line
     * segment connecting its neighbors is at least \a epsilon
     * \remarks time complexity O(n), where n is the number of
     * vertices representing the Polyline.  
     */
    void eliminate_redundant_vertices(double epsilon=0.0);
    //Reduce number of vertices in representation...
    //void smooth(double epsilon);
    /// reverse order of vertices
    void reverse();
    /// append the points from another polyline
    void append( const Polyline& polyline );
  private:
    std::vector<Point> vertices_;
  };


  //print Polyline
  std::ostream& operator << (std::ostream& outs,
                 const Polyline& polyline_temp);


  /** \brief simple polygon in the plane represented by list of vertices
   *
   * Simple here means non-self-intersecting.  More precisely, edges
   * should not (i) intersect with an edge not adjacent to it, nor
   * (ii) intersect at more than one Point with an adjacent edge.
   * \remarks  vertices may be listed cw or ccw
   */
  class Polygon
  {
  public:
    friend class Point;
    //Constructors
    ///default to empty
    Polygon() { }
    /** \brief  construct from *.polygon file
     *
     * \author  Karl J. Obermeyer
     * \remarks  for efficiency, simplicity check not called here
     */
    Polygon(const std::string& filename);
    /** \brief  construct from vector of vertices
     *
     * \remarks  for efficiency, simplicity check not called here
     */
    Polygon(const std::vector<Point>& vertices_temp);
    /** \brief  construct triangle from 3 Points
     *
     * \remarks  for efficiency, simplicity check not called here
     */
    Polygon(const Point& point0, const Point& point1, const Point& point2);
    //Accessors
    /** \brief  access with automatic wrap-around in forward direction
     *
     * \remarks  For efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    const Point& operator [] (unsigned i) const 
    { return vertices_[i % vertices_.size()]; }
    /** \brief  vertex count
     *
     * \remarks  O(1) time complexity
     */
    unsigned n() const { return vertices_.size(); }
    /** \brief  reflex vertex count (nonconvex vertices)
     *  
     * \author  Karl J. Obermeyer
     * \remarks  Works regardless of polygon orientation (ccw vs cw),
     * but assumes no redundant vertices.  Time complexity O(n), where
     * n is the number of vertices representing the Polygon
     */
    unsigned r() const;
    /** \brief  true iff Polygon is (\a epsilon) simple 
     *
     * \author  Karl J. Obermeyer
     *
     * \remarks A Polygon is considered \a epsilon -simple iff (i) the
     * Euclidean distance between nonadjacent edges is no greater than
     * \a epsilon, (ii) adjacent edges intersect only at their single
     * shared Point, (iii) and it has at least 3 vertices.  One
     * consequence of these conditions is that there can be no
     * redundant vertices.
     */
    bool is_simple(double epsilon=0.0) const;
    /** \brief true iff lexicographically smallest vertex is first in 
     *         the list of vertices representing the Polygon
     *
     * \author  Karl J. Obermeyer
     * \remarks  lex. comparison is very sensitive to perturbations if
     * two Points nearly define a line parallel to one of the axes
     */
    bool is_in_standard_form() const;
    /// perimeter length
    double boundary_length() const;
    /** oriented area of the Polygon
     *
     * \author  Karl J. Obermeyer
     * \pre Polygon is simple, but for efficiency simplicity is not asserted.
     * area > 0 => vertices listed ccw, 
     * area < 0 => cw
     * \remarks O(n) time complexity, where n is the number
     * of vertices representing the Polygon
     */
    double area() const;
    /** \brief  Polygon's centroid (center of mass)
     *
     * \author  Karl J. Obermeyer
     * \pre Polygon has greater than 0 vertices and is simple,
     * but for efficiency simplicity is not asserted
     */
    Point  centroid() const;
    /** \brief  Euclidean diameter
     *
     * \pre Polygon has greater than 0 vertices
     * \return  maximum Euclidean distance between all pairs of
     * vertices
     * \remarks  time complexity O(n^2), where n is the number of
     * vertices representing the Polygon
     */
    double diameter() const;
    /** \brief box which fits snugly around the Polygon
     *
     * \author  Karl J. Obermeyer
     * \pre Polygon has greater than 0 vertices
     */
    Bounding_Box bbox() const;
    // Returns a vector of n pts randomly situated in the polygon.
    std::vector<Point> random_points(const unsigned& count,
                     double epsilon=0.0) const;
    /** \brief  write list of vertices to *.polygon file 
     *
     * \author  Karl J. Obermeyer
     * Uses intuitive human and computer readable decimal format with
     * display precision \a fios_precision_temp.
     * \pre  \a fios_precision_temp >=1
     */
    void write_to_file(const std::string& filename,
               int fios_precision_temp=FIOS_PRECISION);
    /** \brief  offsets a list of simple ccw oriented polygons by a specified
     *          distance delta and then performs a union operation.
     *          Note that the offset distance can be positive (expansion)
     *          or negative (contraction). Corners are roughly mitered, but
     *          guaranteed that all points on the new polygon are at least
     *          delta from the original polygon. The rough mitering operation
     *          uses a threshold angle (45 degrees) above which the expanded
     *          vertex is replaced by two vertices. In the worst case, the
     *          number of vertices in the expanded polygon will be twice that
     *          of the original polygon.
     * 
     * \pre polygonList contains only simple ccw oriented polygons, but for
     *      efficiency, simplicity and orientation are not asserted
     * \author  Derek Kingston
     * \remarks Will return false if an error occurs (e.g. OpenGL tessellation errors).
     */
    static bool offset_polygons(std::vector<Polygon>& polygonList, std::vector<Polygon>& resultingPolygons, double delta, double epsilon=0.0);
    static bool offset_polygons(std::vector<Polygon>& polygonList, std::vector<Polygon>& resultingPolygons, std::vector<double>& delta, double epsilon=0.0);
    /** \brief  merges a list of simple polygons oriented ccw using boost union
     *
     * \pre polygonList contains only simple ccw oriented polygons
     * \author  Amanda Cinnamon
     * \remarks Will return false if an error occurs (e.g. XXX).
     */
    static bool boost_union(std::vector<Polygon>& polygonList, std::vector<Polygon>& resultingPolygons, double epsilon=0.0);
    //Mutators
    /** \brief  access with automatic wrap-around in forward direction
     *
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    Point& operator [] (unsigned i) { return vertices_[i % vertices_.size()]; }
    /// set vertices using STL vector of Points
    void set_vertices(const std::vector<Point>& vertices_temp)
    { vertices_ = vertices_temp; }
    /// push a Point onto the back of the vertex list
    void push_back(const Point& vertex_temp )
    { vertices_.push_back( vertex_temp ); }
    /// erase all vertices
    void clear()
    { vertices_.clear(); }
    /** \brief enforces that the lexicographically smallest vertex is first
     *         in the list of vertices representing the Polygon
     *
     * \author  Karl J. Obermeyer
     * \remarks  O(n) time complexity, where n is the number of
     * vertices representing the Polygon.  Lex. comparison is very
     * sensitive to perturbations if two Points nearly define a line
     * parallel to one of the axes
     */
    void enforce_standard_form();
    /** \brief  eliminates vertices which are (\a epsilon) - colinear
     *          with their respective neighbors
     *
     * \author  Karl J. Obermeyer
     * \post  the Euclidean distance between each vertex and the line
     * segment connecting its neighbors is at least \a epsilon, and the
     * Polygon is in standard form
     * \remarks  time complexity O(n), where n is the number of
     * vertices representing the the Polygon  
     */
    void eliminate_redundant_vertices(double epsilon=0.0);
    /** \brief  reverse (cyclic) order of vertices
     *
     * \remarks  vertex first in list is held first
     */
    void reverse();

  protected:
    std::vector<Point> vertices_;
//    static std::vector<Point> openGlVertices_;
//    static std::vector<Polygon> openGlPolygons_;
//    static std::vector< Point* > openGlScratchMemory_;
//    static bool openGlError_;
  };


  /** \brief  true iff vertex lists are identical, but false if either
   *          Polygon has size 0
   *
   * \remarks returns false if either Polygon has size 0
   * \remarks  O(n) time complexity
   */
  bool operator == (Polygon polygon1, Polygon polygon2);
  bool operator != (Polygon polygon1, Polygon polygon2);
  /** \brief true iff the Polygon's vertices match up w/in a (closed)
   *         epsilon ball of each other, but false if either Polygon
   *         has size 0
   *
   * Respects number, ordering, and orientation of vertices, i.e.,
   * even if the (conceptual) polygons represented by two Polygons are
   * identical, they are not considered \a epsilon - equivalent unless
   * the number of vertices is the same, the orientations are the same
   * (cw vs. ccw list), and the Points of the vertex lists match up
   * within epsilon.  This function does attempt to match the polygons
   * for all possible cyclic permutations, hence the quadratic time
   * complexity.
   * \author  Karl J. Obermeyer 
   * \remarks  O(n^2) time complexity, where n is the number of
   * vertices representing the polygon
   */
  bool equivalent(Polygon polygon1, Polygon polygon2,
          double epsilon=0.0);


  /** \brief  Euclidean distance between Polygons' boundaries
   *
   * \author  Karl J. Obermeyer
   * \pre  \a polygon1 and \a polygon2 each have greater than 0 vertices
   */
  double boundary_distance( const Polygon& polygon1,
                const Polygon& polygon2 );

  
  //print Polygon
  std::ostream& operator << (std::ostream& outs,
                 const Polygon& polygon_temp);

  
  /** \brief  environment represented by simple polygonal outer boundary
   *          with simple polygonal holes
   *
   * \remarks  For methods to work correctly, the outer boundary vertices must
   * be listed ccw and the hole vertices cw
   */
  class Environment
  {
  public:
    friend class Point;
    //Constructors
    /// default to empty
    Environment() { }
    /** \brief  construct Environment without holes
     *
     * \remarks  time complexity O(n), where n is the number of vertices
     * representing the Environment
     */
    Environment(const Polygon& polygon_temp)
    { outer_boundary_=polygon_temp; update_flattened_index_key(); }
    /** \brief  construct Environment with holes from STL vector of Polygons
     *
     *  the first Polygon in the vector becomes the outer boundary,
     *  the rest become the holes
     * \remarks  time complexity O(n), where n is the number of vertices
     * representing the Environment
     */
    Environment(const std::vector<Polygon>& polygons);
    /** construct from *.environment file.
     *
     * \author  Karl J. Obermeyer
     * \remarks  time complexity O(n), where n is the number of vertices
     * representing the Environment
     */
    Environment(const std::string& filename);
    //Accessors
    /** \brief  raw access to Polygons
     *
     * An argument of 0 accesses the outer boundary, 1 and above
     * access the holes.
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    const Polygon& operator [] (unsigned i) const
    { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
    /** \brief  raw access to vertices via flattened index
     *
     * By flattened index is intended the label given to a vertex if
     * you were to label all the vertices from 0 to n-1 (where n is
     * the number of vertices representing the Environment) starting
     * with the first vertex of the outer boundary and progressing in
     * order through all the remaining vertices of the outer boundary
     * and holes.
     *
     * \remarks  Time complexity O(1).  For efficiency, no bounds
     * check; usually trying to access out of bounds causes a bus
     * error.
     */
    const Point& operator () (unsigned k) const;
    /// hole count
    unsigned h() const { return holes_.size(); }
    /** \brief  vertex count
     *
     * \remarks  time complexity O(h)
     */
    unsigned n() const;
    /** \brief  total reflex vertex count (nonconvex vertices)
     *  
     * \author  Karl J. Obermeyer
     * \remarks  time complexity O(n), where n is the number of
     * vertices representing the Environment
     */
    unsigned r() const;
    /** \brief  true iff lexicographically smallest vertex is first in 
     *          each list of vertices representing a Polygon of the
     *          Environment
     *
     * \author  Karl J. Obermeyer
     * \remarks  lex. comparison is very sensitive to perturbations if
     * two Points nearly define a line parallel to one of the axes
     */    
    bool is_in_standard_form() const;
    /** \brief  true iff \a epsilon -valid
     *
     * \a epsilon -valid means (i) the outer boundary and holes are
     * pairwise \a epsilon -disjoint (no two features should come
     * within \a epsilon of each other) simple polygons, (ii) outer
     * boundary is oriented ccw, and (iii) holes are oriented cw.
     *
     * \author  Karl J. Obermeyer
     *
     * \pre  Environment has greater than 2 vertices
     * (otherwise it can't even have nonzero area)
     * \remarks time complexity O(h^2*n^2), where h is the number of
     * holes and n is the number of vertices representing the
     * Environment
     */
    bool is_valid(double epsilon=0.0) const;
    /** \brief  sum of perimeter lengths of outer boundary and holes
     *
     * \author  Karl J. Obermeyer
     * \remarks O(n) time complexity, where n is the number of
     * vertices representing the Environment
     */
    double boundary_length() const;
    /** \brief (obstacle/hole free) area of the Environment
     *
     * \author  Karl J. Obermeyer
     * \remarks  O(n) time complexity, where n is the number of
     * vertices representing the Environment
     */
    double area() const;
    /** \brief  Euclidean diameter
     *
     * \author  Karl J. Obermeyer
     * \pre Environment has greater than 0 vertices
     * \return  maximum Euclidean distance between all pairs of
     * vertices
     * \remarks  time complexity O(n^2), where n is the number of
     * vertices representing the Environment
     */
    double diameter() const { return outer_boundary_.diameter(); }
    /** \brief box which fits snugly around the Environment
     *
     * \author  Karl J. Obermeyer
     * \pre Environment has greater than 0 vertices
     */
    Bounding_Box bbox() const { return outer_boundary_.bbox(); }
    /** \brief get STL vector of \a count Points randomly situated
     *         within \a epsilon of the Environment
     *
     * \author  Karl J. Obermeyer
     * \pre  the Environment has positive area
     */
    std::vector<Point> random_points(const unsigned& count,
                     double epsilon=0.0) const;
    /** \brief  compute a shortest path between 2 Points
     *
     * Uses the classical visibility graph method as described, e.g.,
     * in ``Robot Motion Planning" (Ch. 4 Sec. 1) by J.C. Latombe.
     * Specifically, an A* search is performed on the visibility graph
     * using the Euclidean distance as the heuristic function.
     *
     * \author  Karl J. Obermeyer
     *
     * \pre \a start and \a finish must be in the environment.
     * Environment must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \remarks  If multiple shortest path queries are made for the
     * same Envrionment, it is better to precompute the
     * Visibility_Graph. For a precomputed Visibility_Graph, the time
     * complexity of a shortest_path() query is O(n^2), where n is the
     * number of vertices representing the Environment.
     *
     * \todo  return not just one, but all shortest paths (w/in
     * epsilon), e.g., returning a std::vector<Polyline>)
     */
    Polyline shortest_path(const Point& start,
               const Point& finish,
               const Visibility_Graph& visibility_graph,
               double epsilon=0.0);
    /** \brief  compute shortest path between 2 Points
     *
     * \author  Karl J. Obermeyer
     *
     * \pre \a start and \a finish must be in the environment.
     * Environment must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \remarks  For single shortest path query, visibility graph is
     * not precomputed.  Time complexity O(n^3), where n is the number
     * of vertices representing the Environment.
     */
    Polyline shortest_path(const Point& start,
               const Point& finish,
               double epsilon=0.0);
    /** \brief  compute the faces (partition cells) of an arrangement
     *          of Line_Segments inside the Environment
     *
     * \author  Karl J. Obermeyer
     * \todo  finish this
     */
    std::vector<Polygon> compute_partition_cells( std::vector<Line_Segment> 
                          partition_inducing_segments,
                          double epsilon=0.0 )
    {
      std::vector<Polygon> cells;
      return cells;
    }
    /** \brief  write lists of vertices to *.environment file 
     *
     * uses intuitive human and computer readable decimal format with
     * display precision \a fios_precision_temp
     * \author  Karl J. Obermeyer
     * \pre  \a fios_precision_temp >=1
     */
    void write_to_file(const std::string& filename,
               int fios_precision_temp=FIOS_PRECISION);
    //Mutators
    /** \brief  raw access to Polygons
     *
     * An argument of 0 accesses the outer boundary, 1 and above
     * access the holes.
     * \author  Karl J. Obermeyer
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    Polygon& operator [] (unsigned i) 
    { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
    //Mutators
    /** \brief  raw access to vertices via flattened index
     *
     * By flattened index is intended the label given to a vertex if
     * you were to label all the vertices from 0 to n-1 (where n is
     * the number of vertices representing the Environment) starting
     * with the first vertex of the outer boundary and progressing in
     * order through all the remaining vertices of the outer boundary
     * and holes.
     * \author  Karl J. Obermeyer
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error.
     */
    Point& operator () (unsigned k);
    /// set outer boundary
    void set_outer_boundary(const Polygon& polygon_temp)
    { outer_boundary_ = polygon_temp; update_flattened_index_key(); }
    /// add hole
    void add_hole(const Polygon& polygon_temp)
    { holes_.push_back(polygon_temp); update_flattened_index_key(); }
    /** \brief enforces outer boundary vertices are listed ccw and
     *         holes listed cw, and that these lists begin with respective
     *         lexicographically smallest vertex
     *
     * \author  Karl J. Obermeyer
     * \remarks  O(n) time complexity, where n is the number of
     * vertices representing the Environment.  Lex. comparison is very
     * sensitive to perturbations if two Points nearly define a line
     * parallel to one of the axes.
     */
    void enforce_standard_form();
    /** \brief eliminates vertices which are (\a epsilon) - colinear
     *         with their respective neighbors
     *
     * \author  Karl J. Obermeyer
     * \post  the Euclidean distance between each vertex and the line
     * segment connecting its neighbors is at least \a epsilon
     * \remarks time complexity O(n), where n is the number of
     * vertices representing the the Environment
     */
    void eliminate_redundant_vertices(double epsilon=0.0);
    /** \brief  reverse (cyclic) order of vertices belonging to holes
     *          only
     *
     * \remarks  vertex first in each hole's list is held first
     */
    void reverse_holes();
  private:    
    Polygon outer_boundary_;
    //obstacles
    std::vector<Polygon> holes_;
    //allows constant time access to vertices via operator () with
    //flattened index as argument
    std::vector< std::pair<unsigned,unsigned> > flattened_index_key_;
    //Must call if size of outer_boundary and/or holes_ changes.  Time
    //complexity O(n), where n is the number of vertices representing
    //the Environment.
    void update_flattened_index_key();
    //converts flattened index to index pair (hole #, vertex #) in
    //time O(n), where n is the number of vertices representing the
    //Environment
    std::pair<unsigned,unsigned> one_to_two(unsigned k) const;
    //node used for search tree of A* search in shortest_path() method
    class Shortest_Path_Node
    {
    public:
      //flattened index of corresponding Environment vertex
      //convention vertex_index = n() => corresponds to start Point
      //vertex_index = n() + 1 => corresponds to finish Point
      unsigned vertex_index;
      //pointer to self in search tree.
      std::list<Shortest_Path_Node>::iterator search_tree_location;
      //pointer to parent in search tree.
      std::list<Shortest_Path_Node>::iterator parent_search_tree_location;
      //Geodesic distance from start Point.
      double cost_to_come;
      //Euclidean distance to finish Point.
      double estimated_cost_to_go;
      //std::vector<Shortest_Path_Node> expand();
      bool operator < (const Shortest_Path_Node& spn2) const
      { 
    double f1 = this->cost_to_come + this->estimated_cost_to_go;
    double f2 = spn2.cost_to_come + spn2.estimated_cost_to_go;
    if( f1 < f2 )
      return true;
    else if( f2 < f1 )
      return false;
    else if( this->vertex_index < spn2.vertex_index )
      return true;
    else if( this->vertex_index > spn2.vertex_index )
      return false;
    else if( &(*(this->parent_search_tree_location)) 
         < &(*(spn2.parent_search_tree_location)) ) 
      return true;
    else
      return false;
      }
      // print member data for debugging
      void print() const
      {
    std::cout << "         vertex_index = " << vertex_index << std::endl
          << "parent's vertex_index = " 
          << parent_search_tree_location->vertex_index 
          << std::endl
          << "         cost_to_come = " << cost_to_come << std::endl
          << " estimated_cost_to_go = " 
          << estimated_cost_to_go << std::endl;      
      }
    };
  };
  
  
  /// printing Environment
  std::ostream& operator << (std::ostream& outs,
                 const Environment& environment_temp);


  /** \brief  set of Guards represented by a list of Points
   */
  class Guards
  {
  public:
    friend class Visibility_Graph;
    //Constructors
    /// default to empty
    Guards() { }
    /** \brief  construct from *.guards file
     *
     * \author  Karl J. Obermeyer
     */
    Guards(const std::string& filename);
    /// construct from STL vector of Points
    Guards(const std::vector<Point>& positions)
    { positions_ = positions; }
    //Accessors
    /** \brief  raw access to guard position Points
     *
     * \author  Karl J. Obermeyer
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    const Point& operator [] (unsigned i) const { return positions_[i]; }
    /// guard count
    unsigned N() const { return positions_.size(); }
    /// true iff positions are lexicographically ordered
    bool are_lex_ordered() const;
    /// true iff no two guards are w/in epsilon of each other
    bool noncolocated(double epsilon=0.0) const;
    /// true iff all guards are located in \a polygon_temp
    bool in(const Polygon& polygon_temp, double epsilon=0.0) const;
    /// true iff all guards are located in \a environment_temp
    bool in(const Environment& environment_temp, double epsilon=0.0) const;
    /** \brief  Euclidean diameter
     *
     * \author  Karl J. Obermeyer
     * \pre  greater than 0 guards
     * \return  maximum Euclidean distance between all pairs of
     * vertices
     * \remarks  time complexity O(N^2), where N is the number of
     * guards
     */
    double diameter() const;
    /** \brief box which fits snugly around the Guards
     *
     * \author  Karl J. Obermeyer
     * \pre  greater than 0 guards
     */
    Bounding_Box bbox() const;
    /** \brief  write list of positions to *.guards file 
     *
     * Uses intuitive human and computer readable decimal format with
     * display precision \a fios_precision_temp.
     * \author  Karl J. Obermeyer
     * \pre  \a fios_precision_temp >=1
     */
    void write_to_file(const std::string& filename,
               int fios_precision_temp=FIOS_PRECISION);
    //Mutators
    /** \brief  raw access to guard position Points
     *
     * \author  Karl J. Obermeyer
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    Point& operator [] (unsigned i) { return positions_[i]; }
    /// add a guard
    void push_back(const Point& pointemp)
    { positions_.push_back(pointemp); } 
    /// set positions with STL vector of Points
    void set_positions(const std::vector<Point>& positions_temp)
    { positions_ = positions_temp; }
    /** \brief sort positions in lexicographic order
     *
     * from (lowest x, then lowest y) to (highest x, then highest y)
     * \author  Karl J. Obermeyer
     * \remarks time complexity O(N logN), where N is the guard count.
     * Lex. comparison is very sensitive to perturbations if two
     * Points nearly define a line parallel to one of the axes.
     */
    void enforce_lex_order();
    /// reverse order of positions
    void reverse();
    /** \brief relocate each guard to closest vertex if within
     *         \a epsilon of some vertex (of \a environment_temp)
     *   
     * \author  Karl J. Obermeyer
     * \pre  the guards' position data are numbers and \a environment_temp 
     * is nonempty
     * \post if a guard was a Euclidean distance no greater
     * than \a epsilon from any vertex of \a environment_temp, then it
     * will be repositioned to coincide with the closest such vertex
     * \remarks O(N*n) time complexity, where N is the guard count
     * and n is the number of vertices in \a environment_temp.
     */
    void snap_to_vertices_of(const Environment& environment_temp,
                 double epsilon=0.0);

    /** \brief relocate each guard to closest vertex if within
     *         \a epsilon of some vertex (of \a environment_temp)
     *   
     * \author  Karl J. Obermeyer
     * \pre  the guards' position data are numbers and \a polygon_temp 
     * is nonempty
     * \post if a guard was a Euclidean distance no greater
     * than \a epsilon from any vertex of \a polygon_temp, then it
     * will be repositioned to coincide with the closest such vertex
     * \remarks O(N*n) time complexity, where N is the guard count
     * and n is the number of vertices in \a polygon_temp
     */
    void snap_to_vertices_of(const Polygon& polygon_temp,
                 double epsilon=0.0);
    /** \brief  relocate each guard to closest Point on boundary if
     *            within \a epsilon of the boundary (of \a environment_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the guards' position data are numbers and \a environment_temp
     * is nonempty
     * \post If the calling Point was a Euclidean distance no greater
     * than \a epsilon from the boundary of \a environment_temp, then it
     * will be repositioned to it's projection onto that boundary
     * \remarks O(N*n) time complexity, where N is the guard count and
     * n is the number of vertices in \a environment_temp
     */
    void snap_to_boundary_of(const Environment& environment_temp,
                 double epsilon=0.0);
    /** \brief  relocate each guard to closest Point on boundary if
     *            within \a epsilon of the boundary (of \a polygon_temp)
     *
     * \author  Karl J. Obermeyer
     * \pre  the guards' position data are numbers and \a polygon_temp
     * is nonempty
     * \post If the calling Point was a Euclidean distance no greater
     * than \a epsilon from the boundary of \a polygon_temp, then it
     * will be repositioned to it's projection onto that boundary
     * \remarks O(N*n) time complexity, where N is the guard count and
     * n is the number of vertices in \a polygon_temp
     */
    void snap_to_boundary_of(const Polygon& polygon_temp,
                 double epsilon=0.0);
  private:
    std::vector<Point> positions_;
  };


  /// print Guards
  std::ostream& operator << (std::ostream& outs,
                 const Guards& guards);


  /** \brief visibility polygon of a Point in an Environment or Polygon
   *
   * A Visibility_Polygon represents the closure of the set of all
   * points in an environment which are {\it clearly visible} from a
   * point (the observer).  Two Points p1 and p2 are (mutually) {\it
   * clearly visible} in an environment iff the relative interior of
   * the line segment connecting p1 and p2 does not intersect the
   * boundary of the environment.
   *
   * \remarks  average case time complexity O(n log(n)), where n is the
   * number of vertices in the Evironment (resp. Polygon).  Note the
   * Standard Library's sort() function performs O(n log(n))
   * comparisons (both average and worst-case) and the sort() member
   * function of an STL list performs "approximately O(n log(n))
   * comparisons".  For robustness, any Point (observer) should be \a
   * epsilon -snapped to the environment boundary and vertices before
   * computing its Visibility_Polygon (use the Point methods
   * snap_to_vertices_of(...) and snap_to_boundary_of(...) ).
   */
  class Visibility_Polygon : public Polygon
  {
  public:
    //Constructors
    /// default to empty
    Visibility_Polygon() { }
    //:TRICKY:
    /** \brief visibility set of a Point in an Environment
     *
     * \author  Karl J. Obermeyer
     *
     * \pre \a observer is in \a environment_temp (w/in \a epsilon )
     * and has been epsilon-snapped to the Environment using the
     * method Point::snap_to_boundary_of() followed by (order is
     * important) Point::snap_to_vertices_of(). \a environment_temp
     * must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \remarks  O(n log(n)) average case time complexity, where n is the
     * number of vertices in the Evironment (resp. Polygon).
     */
    Visibility_Polygon(const Point& observer,
               const Environment& environment_temp,
               double epsilon=0.0); 
    /** \brief visibility set of a Point in a Polygon
     *
     * \pre \a observer is in \a polygon_temp (w/in \a epsilon ) and
     * has been epsilon-snapped to the Polygon using the methods
     * Point::snap_to_vertices_of() and Point::snap_to_boundary_of().
     * \a environment_temp must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \remarks  less efficient because constructs an Environment from
     * a Polygon and then calls the other Visibility_Polygon constructor.
     * O(n log(n)) average case time complexity, where n is the
     * number of vertices in the Evironment (resp. Polygon).
     */
    Visibility_Polygon(const Point& observer, 
               const Polygon& polygon_temp,
               double epsilon=0.0); 
    //Accessors
    //std::vector<bool> get_gap_edges(double epsilon=0.0) { return gap_edges_; }
    /// location of observer which induced the visibility polygon
    Point observer() const
    { return observer_; }
    //Mutators 
  private:
    //ith entry of gap_edges is true iff the edge following ith vertex
    //is a gap edge (not solid).
    //std::vector<bool> gap_edges_;
    Point observer_;

    struct Polar_Edge
    {
      Polar_Point first;
      Polar_Point second;
      Polar_Edge() { }
      Polar_Edge(const Polar_Point& ppoint1,
         const Polar_Point& ppoint2) :
    first(ppoint1), second(ppoint2) {}
    };    
 
    class Polar_Point_With_Edge_Info : public Polar_Point
    {
    public:      
      std::list<Polar_Edge>::iterator incident_edge;
      bool is_first;  //True iff polar_point is the first_point of the
              //Polar_Edge pointed to by
              //incident_edge.      
      void set_polar_point(const Polar_Point& ppointemp)
      {
    set_polar_origin( ppointemp.polar_origin() );    
    set_x( ppointemp.x() );
    set_y( ppointemp.y() );
    set_range( ppointemp.range() );
    set_bearing( ppointemp.bearing() );
      }
      //The operator < is the same as for Polar_Point with one
      //exception.  If two vertices have equal coordinates, but one is
      //the first point of its respecitve edge and the other is the
      //second point of its respective edge, then the vertex which is
      //the second point of its respective edge is considered
      //lexicographically smaller.
      friend bool operator < (const Polar_Point_With_Edge_Info& ppwei1,
               const Polar_Point_With_Edge_Info& ppwei2)
      {
    if( Polar_Point(ppwei1) == Polar_Point(ppwei2) 
        and !ppwei1.is_first and ppwei2.is_first )
      return true;
    else
      return Polar_Point(ppwei1) < Polar_Point(ppwei2);
      }
    };

    //Strict weak ordering (acts like <) for pointers to Polar_Edges.
    //Used to sort the priority_queue q2 used in the radial line sweep
    //of Visibility_Polygon constructors.  Let p1 be a pointer to
    //Polar_Edge e1 and p2 be a pointer to Polar_Edge e2.  Then p1 is
    //considered greater (higher priority) than p2 if the distance
    //from the observer (pointed to by observer_pointer) to e1 along
    //the direction to current_vertex is smaller than the distance
    //from the observer to e2 along the direction to current_vertex.
    class Incident_Edge_Compare
    {
      const Point *const observer_pointer;
      const Polar_Point_With_Edge_Info *const current_vertex_pointer;
      double epsilon;
    public:
      Incident_Edge_Compare(const Point& observer,
                const Polar_Point_With_Edge_Info& current_vertex,
                double epsilon_temp) :
    observer_pointer(&observer), 
    current_vertex_pointer(&current_vertex),
    epsilon(epsilon_temp) { }
      bool operator () (std::list<Polar_Edge>::iterator e1,
            std::list<Polar_Edge>::iterator e2) const
      {
    Polar_Point k1, k2;
    Line_Segment xing1 = intersection( Ray(*observer_pointer, 
                       current_vertex_pointer->bearing()), 
                       Line_Segment(e1->first,
                            e1->second),
                       epsilon);
    Line_Segment xing2 = intersection( Ray(*observer_pointer, 
                       current_vertex_pointer->bearing()), 
                       Line_Segment(e2->first,
                            e2->second),
                       epsilon);
    if( xing1.size() > 0 and xing2.size() > 0 ){
      k1 = Polar_Point( *observer_pointer,
                xing1.first() );
      k2 = Polar_Point( *observer_pointer,
                xing2.first() );
      if( k1.range() <= k2.range() )
        return false;
      return true;
    }
    //Otherwise infeasible edges are given higher priority, so they
    //get pushed out the top of the priority_queue's (q2's)
    //heap.
    else if( xing1.size() == 0 and xing2.size() > 0 )
      return false;
    else if( xing1.size() > 0 and xing2.size() == 0 )
      return true;
    else
      return true;
      }
    };
    
    bool is_spike( const Point& observer,
           const Point& point1,
           const Point& point2,
           const Point& point3, 
           double epsilon=0.0 ) const;
    
    //For eliminating spikes as they appear.  In the
    //Visibility_Polygon constructors, these are checked every time a
    //Point is added to vertices.
    void chop_spikes_at_back(const Point& observer,
                 double epsilon);
    void chop_spikes_at_wrap_around(const Point& observer,
                    double epsilon);
    void chop_spikes(const Point& observer,
             double epsilon);
    //For debugging Visibility_Polygon constructors.
    //Prints current_vertex and active_edge data to screen.
    void print_cv_and_ae(const Polar_Point_With_Edge_Info& current_vertex,
             const std::list<Polar_Edge>::iterator&
             active_edge);
  };


  /** \brief  visibility graph of points in an Environment,
   *          represented by adjacency matrix
   *
   * \remarks  used for shortest path planning in the
   * Environment::shortest_path() method
   *
   * \todo Add method to prune edges for faster shortest path
   * calculation, e.g., exclude concave vertices and only include
   * tangent edges as described in ``Robot Motion Planning" (Ch. 4
   * Sec. 1) by J.C. Latombe.
   */
  class  Visibility_Graph
  {
  public:
    //Constructors
    /// default to empty 
    Visibility_Graph() { n_=0; adjacency_matrix_ = NULL; }
    /// copy 
    Visibility_Graph( const Visibility_Graph& vg2 );
    /** \brief  construct the visibility graph of Environment vertices
     *
     * \author  Karl J. Obermeyer
     *
     * \pre \a environment must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \remarks  Currently this constructor simply computes the
     * Visibility_Polygon of each vertex and checks inclusion of the
     * other vertices, taking time complexity O(n^3), where n is the
     * number of vertices representing the Environment.  This time
     * complexity is not optimal. As mentioned in ``Robot Motion
     * Planning" by J.C. Latombe p.157, there are algorithms able to
     * construct a visibility graph for a polygonal environment with
     * holes in time O(n^2).  The nonoptimal algorithm is being used
     * temporarily because of (1) its ease to implement using the
     * Visibility_Polygon class, and (2) its apparent robustness.
     * Implementing the optimal algorithm robustly is future work.
     */
    Visibility_Graph(const Environment& environment, double epsilon=0.0);
    //Constructors
    /** \brief  construct the visibility graph of Points in an Environment
     *
     * \pre \a environment must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \author Karl J. Obermeyer \remarks Currently this constructor
     * simply computes the Visibility_Polygon of each Point and checks
     * inclusion of the other Points, taking time complexity
     * O(N n log(n) + N^2 n), where N is the number of Points and n is
     * the number of vertices representing the Environment.  This time
     * complexity is not optimal, but has been used for
     * simplicity. More efficient algorithms are discussed in ``Robot
     * Motion Planning" by J.C. Latombe p.157.
     */
    Visibility_Graph(const std::vector<Point> points,
             const Environment& environment, double epsilon=0.0);
    //Constructors
    /** \brief  construct the visibility graph of Guards in an Environment
     *
     * \pre \a start and \a finish must be in the environment.
     * Environment must be \a epsilon -valid.  Test with
     * Environment::is_valid(epsilon).
     *
     * \author  Karl J. Obermeyer 
     * \remarks  Currently this constructor simply computes the
     * Visibility_Polygon of each guard and checks inclusion of the
     * other guards, taking time complexity O(N n log(n) + N^2 n),
     * where N is the number of guards and n is the number of vertices
     * representing the Environment.  This time complexity is not
     * optimal, but has been used for simplicity. More efficient
     * algorithms are discussed in ``Robot Motion Planning" by
     * J.C. Latombe p.157.
     */
    Visibility_Graph(const Guards& guards,
             const Environment& environment, double epsilon=0.0);
    //Accessors
    /** \brief  raw access to adjacency matrix data
     *
     * \author  Karl J. Obermeyer
     * \param i1  Polygon index of first vertex
     * \param j1  index of first vertex within its Polygon
     * \param i2  Polygon index of second vertex
     * \param j2  index of second vertex within its Polygon
     * \return  true iff first vertex is visible from second vertex
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    bool operator () (unsigned i1,
              unsigned j1,
              unsigned i2,
              unsigned j2) const;
    /** \brief  raw access to adjacency matrix data via flattened
     *          indices
     *
     * By flattened index is intended the label given to a vertex if
     * you were to label all the vertices from 0 to n-1 (where n is
     * the number of vertices representing the Environment) starting
     * with the first vertex of the outer boundary and progressing in
     * order through all the remaining vertices of the outer boundary
     * and holes.
     * \author  Karl J. Obermeyer
     * \param k1  flattened index of first vertex
     * \param k1  flattened index of second vertex
     * \return  true iff first vertex is visible from second vertex
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    bool operator () (unsigned k1,
              unsigned k2) const;
    /// \brief  total number of vertices in corresponding Environment
    unsigned n() const { return n_; }
    //Mutators
    /** \brief  raw access to adjacency matrix data
     *
     * \author  Karl J. Obermeyer
     * \param i1  Polygon index of first vertex
     * \param j1  index of first vertex within its Polygon
     * \param i2  Polygon index of second vertex
     * \param j2  index of second vertex within its Polygon
     * \return  true iff first vertex is visible from second vertex
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    bool& operator () (unsigned i1,
               unsigned j1,
               unsigned i2,
               unsigned j2);
    /** \brief  raw access to adjacency matrix data via flattened
     *          indices
     *
     * By flattened index is intended the label given to a vertex if
     * you were to label all the vertices from 0 to n-1 (where n is
     * the number of vertices representing the Environment) starting
     * with the first vertex of the outer boundary and progressing in
     * order through all the remaining vertices of the outer boundary
     * and holes.
     * \author  Karl J. Obermeyer
     * \param k1  flattened index of first vertex
     * \param k1  flattened index of second vertex
     * \return  true iff first vertex is visible from second vertex
     * \remarks  for efficiency, no bounds check; usually trying to
     * access out of bounds causes a bus error
     */
    bool& operator () (unsigned k1,
               unsigned k2);
    /// assignment operator
    Visibility_Graph& operator = 
    (const Visibility_Graph& visibility_graph_temp);
    /// destructor
    virtual ~Visibility_Graph();
  private:
    //total number of vertices of corresponding Environment
    unsigned n_;
    //the number of vertices in each Polygon of corresponding Environment
    std::vector<unsigned> vertex_counts_;
    // n_-by-n_ adjacency matrix data stored as 2D dynamic array
    bool **adjacency_matrix_;
    //converts vertex pairs (hole #, vertex #) to flattened index
    unsigned two_to_one(unsigned i,
            unsigned j) const;
  };


  /// print Visibility_Graph adjacency matrix
  std::ostream& operator << (std::ostream& outs,
                 const Visibility_Graph& visibility_graph);

    std::ostream& operator << (std::ostream& outs, const boost_polygon b_poly);
}
  
#endif //VISILIBITY_H
