// Copyright (c) 1997 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $Source: /CVSROOT/CGAL/Packages/Planar_map/demo/Planar_map/snapping_layer.h,v $
// $Revision: 1.2.6.1 $
// $Name: $
//
// author(s) : Radu Ursu
#ifndef CGAL_SNAPPING_LAYER_H
#define CGAL_SNAPPING_LAYER_H
#include "cgal_types.h"
#include <CGAL/IO/Qt_widget.h>
#include <CGAL/IO/Qt_widget_layer.h>
#include <qobject.h>
#include <qpopupmenu.h>
#include <qmessagebox.h>
#include <qcursor.h>
#include <CGAL/squared_distance_2.h>
template <class R>
class Snapping_layer : public CGAL::Qt_widget_layer
{
public:
typedef typename R::Point_2 Point;
typedef typename R::FT FT;
bool on_first, //true if the user selected the first vertex
wasrepainted;//true when the widget was repainted
Point old_point, //the last end point found
current_v; //the current point
QCursor cursor;
std::list<Curve> *curveslist;
Curve selected_curve, old_curve;
bool source, target;
Planar_map *pm;
//constructor
Snapping_layer(const QCursor c=QCursor(Qt::crossCursor)) :
on_first(false), cursor(c),
source(false), target(false) {};
void pass_the_structure(std::list<Curve>* l, Planar_map * p) {
curveslist = l;
pm = p;
}
private:
void draw(){
wasrepainted = true;
};
private:
QCursor oldcursor;
void mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::LeftButton && on_first)
{
curveslist->remove(selected_curve);
curveslist->push_back(old_curve);
Locate_type i;
Halfedge_handle hh;
if(source)
hh = pm->locate(selected_curve.source(), i);
else
hh = pm->locate(selected_curve.target(), i);
pm->remove_edge(hh);
pm->insert(old_curve);
on_first = false; source = false; target = false;
selected_curve = Curve();
widget->redraw();
}
if(e->button() == Qt::RightButton && !on_first)
{
if(curveslist->empty())
QMessageBox::warning( widget, "There are no segments in the list!",
"Input some segments before using this layer!");
else{
FT x, y;
widget->x_real(e->x(), x);
widget->y_real(e->y(), y);
Point p(x, y);
Point closest_p;
//this point is the closest one to the mouse coordinates
FT min_dist;
typename std::list<Curve>::const_iterator it = curveslist->begin();
min_dist = CGAL::squared_distance(p, (*it).source());
closest_p = (*it).source();
while(it!=curveslist->end())
{
if (min_dist > CGAL::squared_distance(p, (*it).source())) {
min_dist = CGAL::squared_distance(p, (*it).source());
closest_p = (*it).source();
selected_curve = (*it); old_curve = (*it);
source = true; target = false;
}
if (min_dist > CGAL::squared_distance(p, (*it).target())) {
min_dist = CGAL::squared_distance(p, (*it).target());
closest_p = (*it).target();
selected_curve = (*it); old_curve = (*it);
target = true; source = false;
}
it++;
}
RasterOp old = widget->rasterOp(); //save the initial raster mode
widget->setRasterOp(XorROP);
widget->lock();
*widget << CGAL::GREEN << CGAL::PointSize (5)
<< CGAL::PointStyle (CGAL::DISC);
*widget << closest_p;
widget->unlock();
widget->setRasterOp(old);
old_point = closest_p;
current_v = closest_p;
wasrepainted = false;
on_first = true;
}
}
};
void mouseMoveEvent(QMouseEvent *e)
{
if(on_first)
{
FT x, y;
widget->x_real(e->x(), x);
widget->y_real(e->y(), y);
RasterOp old = widget->rasterOp(); //save the initial raster mode
widget->setRasterOp(XorROP);
widget->lock();
*widget << CGAL::GREEN << CGAL::PointSize (5)
<< CGAL::PointStyle (CGAL::DISC);
if(!wasrepainted){
*widget << CGAL::RED << old_curve;
*widget << CGAL::GREEN << old_point;
}
Point p(x,y);
Point closest_p;
FT min_dist;
typename std::list<Curve>::const_iterator it = curveslist->begin();
min_dist = CGAL::squared_distance(p, (*it).source());
closest_p = (*it).source();
while(it!=curveslist->end())
{
if( (*it) == selected_curve){
it++;
continue;
}
if (min_dist > CGAL::squared_distance(p, (*it).source())) {
min_dist = CGAL::squared_distance(p, (*it).source());
closest_p = (*it).source();
}
if (min_dist > CGAL::squared_distance(p, (*it).target())) {
min_dist = CGAL::squared_distance(p, (*it).target());
closest_p = (*it).target();
}
it++;
}
if(target)
old_curve = Curve(old_curve.source(), closest_p);
else
old_curve = Curve(closest_p, old_curve.target());
*widget << CGAL::RED << old_curve;
*widget << CGAL::GREEN << closest_p;
widget->unlock();
widget->setRasterOp(old);
old_point = closest_p;
}
};
void activating()
{
oldcursor = widget->cursor();
widget->setCursor(cursor);
on_first = false; source = false;
target = false;
};
void deactivating()
{
widget->setCursor(oldcursor);
};
};
#endif // CGAL_SNAPPING_LAYER_H
syntax highlighted by Code2HTML, v. 0.9.1