#include <iostream>
// if LEDA is not installed, a message will be issued in runtime.
#ifdef CGAL_USE_LEDA
#include <CGAL/basic.h>
#include <fstream>
#include <list>
#include "draw_map.h"
#include "read_inp.h"
/*=========================================================================
* Start of Code
\*=========================================================================*/
void MarkCcb (const Ccb_halfedge_circulator & b, std::list<Pm_curve>& l)
{
Ccb_halfedge_circulator first = b, iter = b;
do
{
l.push_back(iter->curve());
iter++;
}
while (iter != first);
}
void draw_arrow(Pm_point p1, Pm_point p2, bool black, CGAL::Window_stream & W)
{
if (black)
W << CGAL::BLACK;
else
W << CGAL::WHITE;
//float
number_type ar_size=(W.xmax()-W.xmin())/20 ;
W << Pm_curve (p1, p2);
#ifndef USE_LEDA_RAT_KERNEL
W << Pm_curve(p2, Pm_point (p2.x () - ar_size , p2.y () - ar_size));
W << Pm_curve(p2, Pm_point (p2.x () + ar_size , p2.y () - ar_size));
#else
W << Pm_curve(p2, Pm_point (p2.xcoord () - ar_size, p2.ycoord () - ar_size));
W << Pm_curve(p2, Pm_point (p2.xcoord () + ar_size, p2.ycoord () - ar_size));
#endif
}
void Draw (CGAL::Window_stream & W , Planar_map & pm)
{
W.set_flush( 0 );
Vertex_iterator vi;
for (vi = pm.vertices_begin (); vi != pm.vertices_end (); vi++)
{
W << CGAL::GREEN;
W << (*vi).point();
}
Halfedge_iterator ei;
for (ei = pm.halfedges_begin (); ei != pm.halfedges_end (); ei++)
{
W << CGAL::BLUE;
W << ((*ei).curve());
}
W.set_flush( 1 );
W.flush();
}
bool VerticalRayShoot (Pm_point p, Pm_point & q, bool up , Planar_map &pm)
{
Halfedge_handle e;
Planar_map::Locate_type lt;
number_type y_min, y_max, y_arrow_tip;
#ifdef CGAL_PM_TIMER
t_vertical.start();
#endif
e=pm.vertical_ray_shoot (p,lt, up);
#ifdef CGAL_PM_TIMER
t_vertical.stop();
n_vertical++;
#endif
if (lt!=Planar_map::UNBOUNDED_FACE)
{
Pm_point p1 = e->source()->point();
Pm_point p2 = e->target()->point();
// make the arrow point upwards and touch the found segment:
#ifndef USE_LEDA_RAT_KERNEL
if (p1.x() == p2.x())
{
// the found segment is vertical
y_min = std::min (p1.y(), p2.y());
y_max = std::max (p1.y(), p2.y());
y_arrow_tip = (p.y() < y_min) ? y_min : y_max;
q = Pm_point(p.x(), y_arrow_tip);
}
else
{
y_arrow_tip = p2.y()-
((p2.x()-p.x())*(p2.y()-p1.y()))/(p2.x()-p1.x());
q = Pm_point(p.x(), y_arrow_tip);
}
#else
if (p1.xcoord() == p2.xcoord())
{
// the found segment is vertical
y_min = std::min (p1.ycoord(), p2.ycoord());
y_max = std::max (p1.ycoord(), p2.ycoord());
y_arrow_tip = (p.ycoord() < y_min) ? y_min : y_max;
q = Pm_point(p.xcoord(), y_arrow_tip);
}
else
{
y_arrow_tip = p2.ycoord()-
((p2.xcoord()-p.xcoord())*(p2.ycoord()-p1.ycoord()))/
(p2.xcoord()-p1.xcoord());
q = Pm_point(p.xcoord(), y_arrow_tip);
}
#endif
return true;
}
else
{
return false;
}
}
void FindFace (const Pm_point& p , Planar_map &pm, std::list<Pm_curve>& l)
{
Planar_map::Locate_type lt;
#ifdef CGAL_PM_TIMER
t_vertical.start();
#endif
Halfedge_handle e = pm.vertical_ray_shoot (p, lt, true);
#ifdef CGAL_PM_TIMER
t_vertical.stop();
n_vertical++;
#endif
Face_handle f;
if (lt!=Planar_map::UNBOUNDED_FACE)
{
f = e->face ();
}
else
{
f = pm.unbounded_face ();
}
Ccb_halfedge_circulator ccb_circ;
if (f->does_outer_ccb_exist ())
{
ccb_circ = f->halfedge_on_outer_ccb()->ccb();
MarkCcb (ccb_circ,l);
}
Planar_map::Holes_iterator iccbit;
for (iccbit = f->holes_begin (); iccbit != f->holes_end (); ++iccbit)
{
MarkCcb (*iccbit,l);
}
}
int draw_pm (Planar_map & pm , CGAL::Window_stream & W)
{
std::list<Pm_curve> l;
Pm_point pnt (20, 20);
Pm_point ar1, ar2;
int mbutton = 0;
double x, y;
std::cerr << "Drawing the map:" << std::endl;
Draw (W,pm);
std::cerr << "1.Left button: vertical ray shooting." << std::endl;
std::cerr << "2.Middle button: point location." << std::endl;
std::cerr << "3.Right button: exit" << std::endl;
while (mbutton != 3)
{
int b=W.read_mouse(x,y);
if (b==10) return 0;
mbutton = -b;
// pnt = Pm_point (x, y);
#ifndef USE_LEDA_RAT_KERNEL
pnt = Pm_point(Rep::FT(x),
Rep::FT(y));
#else
pnt = Pm_point(leda_rational(x),leda_rational(y));
#endif
draw_arrow (ar1, ar2, false,W);
if (mbutton == 1)
{
ar1 = pnt;
if (VerticalRayShoot (ar1, ar2, true,pm))
draw_arrow (ar1, ar2, true,W);
}
if (mbutton == 2)
{
FindFace (pnt,pm,l);
}
if (mbutton != 0)
{
Draw (W,pm);
W << CGAL::RED;
for (std::list<Pm_curve>::iterator lit=l.begin(); lit!=l.end(); ++lit)
W << *lit;
l.erase(l.begin(),l.end());
}
}
return 0;
}
//-------------------------------------------------------------------
bool ReadFile(char *filename, int &num_points, Pm_point* &pnts,
int &num_curves, Pm_curve* &cvs )
{
int j, k;
std::ifstream is(filename);
if (is.bad()) return false;
PM_input<Traits> inp;
is >> inp;
is.close();
num_points = inp.get_num_pnts();
num_curves = inp.get_num_cvs();
pnts = new Pm_point[num_points];
cvs = new Pm_curve[num_curves];
int i;
for(i = 0; i < num_points; i++)
{
inp.get(i, pnts[i]);
}
for(i = 0; i < inp.get_num_cvs(); i++)
{
inp.get(i, k, j);
cvs[i] = Pm_curve(pnts[k], pnts[j]);
}
return true;
}
//----------------------------------------------------------------
void win_border( double &x0 , double &x1 , double &y0 ,Planar_map &pm)
{
Vertex_iterator vit = pm.vertices_begin();
#ifndef USE_LEDA_RAT_KERNEL
x0=x1=CGAL::to_double(( vit->point() ).x());
y0=CGAL::to_double(( vit->point() ).y());
#else
x0=x1=vit->point().xcoordD();
y0=vit->point().ycoordD();
#endif
while (vit!=pm.vertices_end())
{
#ifndef USE_LEDA_RAT_KERNEL
if ( ((*vit).point() ).x() < x0 )
x0 = CGAL::to_double(( (*vit).point() ).x()) ;
if ( ( (*vit).point() ).x() > x1 )
x1 = CGAL::to_double(( (*vit).point() ).x()) ;
if ( ( (*vit).point() ).y() < y0 )
y0 = CGAL::to_double(( (*vit).point() ).y()) ;
#else
if ( vit->point().xcoordD() < x0 )
x0 = vit->point().xcoordD() ;
if ( vit->point().xcoordD() > x1 )
x1 = vit->point().xcoordD() ;
if ( vit->point().ycoordD() < y0 )
y0 = vit->point().ycoordD() ;
#endif
vit++;
}
x0=x0-(x1-x0)/2;
x1=x1+(x1-x0)/3;
y0=y0-(x1-x0)/4;
if (x1<=x0)
std::cerr << "\nIf you are trying to read an input file "
<< "(e.g. from input_files directory),"
<< "\nmake sure to define the "
<< "USE_RATIONAL flag whenever you are reading exact input "
<< "\n(i.e. *.e files), otherwise avoid using this flag."
<< "\nexample: demo input_files\\window.f\n";
// CGAL_postcondition(x1>x0);
}
//DEBUG
//bool Init (char *filename , Planar_map & pm, CGAL::Window_stream& W)
bool Init (char *filename , Planar_map & pm)
{
int num_points, num_curves, i;
Pm_point *pnts;
Pm_curve *cvs;
#ifdef CGAL_PM_TIMER
// ReadFile shouldn't be included in construction time.
t_construction.stop();
#endif
if (!ReadFile (filename, num_points, pnts, num_curves, cvs ))
return false;
#ifdef CGAL_PM_TIMER
t_construction.start();
#endif
for (i = 0; i < num_curves; i++)
{
#ifdef CGAL_PM_DEBUG
std::cout << "inserting curve: i\n";
std::cout << cvs[i] << std::endl;
// W << cvs[i] ;
#endif
#ifdef CGAL_PM_TIMER
t_insert.start();
#endif
pm.insert (cvs[i]);
#ifdef CGAL_PM_TIMER
t_insert.stop();
n_insert++;
#endif
}
delete[] cvs;
delete[] pnts;
return true;
}
///////////////////////////////////////////////////////////////////////
CGAL::Window_stream& operator<<(CGAL::Window_stream& os, Planar_map &M)
{
Halfedge_iterator it = M.halfedges_begin();
while(it != M.halfedges_end()){
os << (*it).curve();
++it;
}
return os;
}
//function needed for window input
Vertex_handle closest_vertex(Planar_map &M, const Pm_point& p)
{
Vertex_handle v;
Vertex_iterator vi = M.vertices_begin();
if (vi==M.vertices_end())
return vi;
else v=vi;
#ifndef USE_LEDA_RAT_KERNEL
Rep::FT d = CGAL::squared_distance(p, (*vi).point());
for (; vi!=M.vertices_end(); ++vi)
{
Rep::FT d2 = CGAL::squared_distance(p, (*vi).point());
if(d2 < d){
d = d2;
v = vi;
}
}
#else
for (; vi!=M.vertices_end(); ++vi)
if(p.cmp_dist(vi->point(),v->point())<0){v = vi;}
#endif
return v;
}
void window_input(Planar_map & M, CGAL::Window_stream &W )
{
std::cerr << "1.Left button: start or end edge at mouse position."
<< std::endl;
std::cerr << "2.Middle button: start or end edge at closest vertex \
from mouse position"
<< std::endl;
std::cerr << "3.Right button: remove the edge directly above the mouse \
position"
<< std::endl;
Pm_point p;
Pm_point first_point;
// Vertex_handle last_vertex;
bool start_flag = true;
while(1) {
double x, y;
int b = W.get_mouse(x,y);
if (b==10) break;
#ifndef USE_LEDA_RAT_KERNEL
p = Pm_point(Rep::FT(x), Rep::FT(y));
#else
p = Pm_point(leda_rational(x),leda_rational(y));
#endif
if (b == MOUSE_BUTTON(1))
{
if (start_flag)
{
first_point=p;
start_flag=false;
}
else
{
start_flag=true;
#ifdef CGAL_PM_TIMER
t_insert.start();
#endif
#ifdef CGAL_PM_DEBUG
Halfedge_handle e=
#endif
M.insert(Pm_curve(first_point,p));
#ifdef CGAL_PM_TIMER
t_insert.stop();
n_insert++;
#endif
#ifdef CGAL_PM_DEBUG
Traits_wrap traits=M.get_traits();
CGAL_postcondition(traits.point_equal(e->source()->point(),
first_point));
CGAL_postcondition(traits.point_equal(e->target()->point(),p));
#endif
}
W << M;
}
else
if (b==MOUSE_BUTTON(2))
{
if (M.number_of_vertices()==0) { //an empty map do nothing
start_flag=true;
}
else {
Vertex_handle v=closest_vertex(M,p);
if (start_flag) {
first_point=v->point();
start_flag=false;
}
else //insert fromfirst_point to nearest
{
#ifdef CGAL_PM_TIMER
t_insert.start();
#endif
#ifdef CGAL_PM_DEBUG
Halfedge_handle e=
#endif
M.insert(Pm_curve(first_point,v->point()));
#ifdef CGAL_PM_TIMER
t_insert.stop();
n_insert++;
#endif
#ifdef CGAL_PM_DEBUG
Traits_wrap traits=M.get_traits();
CGAL_postcondition(traits.point_equal(e->source()->point(),
first_point));
CGAL_postcondition(traits.point_equal(e->target()->point(),
v->point()));
#endif
start_flag=true;
}
}
W << M;
}
else if(b == MOUSE_BUTTON(3))
{
start_flag=true;
Planar_map::Locate_type l;
Halfedge_handle e;
#ifdef CGAL_PM_TIMER
t_vertical.start();
#endif
e=M.vertical_ray_shoot(p,l,true);
#ifdef CGAL_PM_TIMER
t_vertical.stop();
n_vertical++;
#endif
if (l!=Planar_map::UNBOUNDED_FACE)
{
#ifdef CGAL_PM_TIMER
t_remove.start();
#endif
M.remove_edge(e);
#ifdef CGAL_PM_TIMER
t_remove.stop();
n_remove++;
#endif
W.clear();
W << M;
#ifdef CGAL_PM_DEBUG
std::cout << "\nremove()" << std::flush;
M.debug();
#endif
}
}
if (!M.is_valid()) {
std::cerr << "map is not valid - aborting" << std::endl;
exit(1);
}
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1