
#include <CGAL/Cartesian.h>
#include <CGAL/Point_2.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/IO/Qt_widget_Delaunay_triangulation_2.h>
#include <CGAL/IO/Qt_widget.h>
#include <CGAL/IO/Qt_widget_layer.h>
#include <qapplication.h>

typedef CGAL::Cartesian<double>		    Rep;
typedef CGAL::Point_2<Rep>		    Point;
typedef CGAL::Delaunay_triangulation_2<Rep> Delaunay;


typedef CGAL::Circle_2<Rep>		    Circle;
typedef CGAL::Triangle_2<Rep>		    Triangle;
typedef CGAL::Vector_2<Rep>                 Vector;
typedef CGAL::Segment_2<Rep>                Segment;
typedef Delaunay::Vertex_handle             Vertex;
typedef Delaunay::Face_handle               Face;
typedef Delaunay::Finite_faces_iterator     Faces_it;
typedef Delaunay::Face_circulator           Faces_circ;
typedef Delaunay::Line_face_circulator      Line_face_circ;
typedef Delaunay::Vertex_circulator         Vertex_circ;
/////////////////////////////////////////////////////////
//  Les objets affiches sont declares ici en variable globales
//  l'affichage est fait dans la methode "draw" ci dessous

Delaunay dt;
Point    the_point = Point(-1,-1);
Vertex   voisin;
Face     face_trouvee;
Triangle triang, triang_incident;
Circle   cercle;

class My_layer : public CGAL::Qt_widget_layer{
  void draw(){

    //3. coloriage des faces
    Faces_it it= dt.finite_faces_begin();
    Faces_it fin= dt.finite_faces_end();
    for ( ; it != fin ; it++ ) {
      Triangle tt=dt.triangle(it);
      double ratio = tt.area(  )
	/ CGAL::squared_distance(dt.circumcenter(it),it->vertex(0)->point());
      if ( ratio > 0.3 )
	*widget << CGAL::FillColor( CGAL::Color(100,255,100) ) << tt;
      else
	*widget << CGAL::FillColor( CGAL::Color(255,100,100) ) << tt;
    }
    // affichage triangulation et point clique
    *widget << CGAL::LineWidth(3) << CGAL::noFill << CGAL::RED << dt 
	    << CGAL::PointSize(6) << CGAL::BLUE << the_point 
      ;
    //4. afficher en plus tous les triangles incidents
    //au plus proche voisin du point clique
    if ( voisin != Vertex() ) {   
      Faces_circ circ = dt.incident_faces(voisin), done=circ;
      do {
	if (!dt.is_infinite(circ)){
	  triang_incident = dt.triangle(circ); 
	  *widget << CGAL::BLUE	  << triang_incident;
	}
      } while (++circ != done); 
    }
     //2. affichage face et cercle circonscrit
    if (face_trouvee != Face() &&   ! dt.is_infinite(face_trouvee) )
      *widget << CGAL::LineWidth(4) << CGAL::BLACK << cercle
	      <<                       CGAL::ORANGE << triang
	;
    //1. affichage plus proche voisin
    if (voisin != Vertex() ) 
      *widget << CGAL::GREEN << voisin->point();
    //5. afficher tous les triangles traverse's par la droite
    //horizontale passant par le point clique
    if (dt.dimension()>1) {
      Vector v(1,0);
      Line_face_circ lfcirc = dt.line_walk(the_point, the_point + v),
	lfdone = lfcirc;
      if (lfcirc != 0)
      do {  
	if  (!dt.is_infinite(lfcirc))  {
	  triang = dt.triangle(lfcirc); 
	  *widget << CGAL::FillColor( CGAL::Color(0,0,255) ) 
		  << triang;
	}
      } while (++lfcirc != lfdone); 
    }
    //6. afficher l'enveloppe convexe
    Vertex_circ vcirc = dt.incident_vertices( dt.infinite_vertex() ),
      vdone = vcirc;
    Point p1, p2;
    if (vcirc != 0) {
      p1 = vcirc->point();
      do {
	p2 = (++vcirc)->point();
	*widget << CGAL::BLACK << Segment(p1,p2);
	p1 = p2;
      } while (vcirc != vdone);
    }
    
  }
};

class My_window : public CGAL::Qt_widget {
public:
  My_window(int x, int y)
  {
    resize(x,y);
    attach(&layer);
  };
private:
  //this method is called when the user presses the mouse
  void mousePressEvent(QMouseEvent *e)
  {
    Qt_widget::mousePressEvent(e);

    /////////////////////////////////////////////////////////////
    //  C'EST ICI QUE CA SE PASSE QUAND ON CLIQUE !
    //
    if (e->button() == Qt::LeftButton) {
      dt.insert(Point(x_real(e->x()), y_real(e->y())));
    }
    if (e->button() == Qt::MidButton) {
      face_trouvee = dt.locate(Point(x_real(e->x()), y_real(e->y())));
      cercle = Circle(face_trouvee->vertex(0)->point(),
		      face_trouvee->vertex(1)->point(),
		      face_trouvee->vertex(2)->point());
      triang = Triangle(face_trouvee->vertex(0)->point(),
		      face_trouvee->vertex(1)->point(),
		      face_trouvee->vertex(2)->point());
    }
    if (e->button() == Qt::RightButton) {
      the_point =  Point(x_real(e->x()), y_real(e->y()));
      voisin = dt.nearest_vertex( the_point) ;
    }
    /////////////////////////////////////////////////////////////

    redraw();
  }
  My_layer layer;
};

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
    My_window *W = new My_window(400,400);
    app.setMainWidget(W);
    W->show();
    W->set_window(0, 400, 0, 400);
    return app.exec();
}

