mirror of https://github.com/CGAL/cgal
410 lines
12 KiB
C++
410 lines
12 KiB
C++
// Copyright (c) 2003 INRIA Sophia-Antipolis (France) and
|
|
// Max-Planck-Institute Saarbruecken (Germany).
|
|
// All rights reserved.
|
|
//
|
|
// Authors : Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
|
|
// Radu Ursu
|
|
//
|
|
// Partially supported by the IST Programme of the EU as a Shared-cost
|
|
// RTD (FET Open) Project under Contract No IST-2000-26473
|
|
// (CGAL - Effective Computational Geometry for Curves and Surfaces)
|
|
|
|
// file : include/CGAL/IO/Qt_widget_get_arc.h
|
|
|
|
#ifndef CGAL_QT_WIDGET_GET_ARC_H
|
|
#define CGAL_QT_WIDGET_GET_ARC_H
|
|
|
|
#include <cmath>
|
|
#include <CGAL/IO/Qt_widget.h>
|
|
#include <CGAL/IO/Qt_widget_layer.h>
|
|
#include <CGAL/squared_distance_2.h>
|
|
|
|
#ifndef CGAL_QT_WIDGET_GET_POINT_BUTTON
|
|
#define CGAL_QT_WIDGET_GET_POINT_BUTTON Qt::LeftButton
|
|
#endif
|
|
|
|
namespace CGAL {
|
|
|
|
namespace CGALi {
|
|
|
|
class Qt_widget_get_arc_helper
|
|
: public CGAL::Qt_widget_layer
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
Qt_widget_get_arc_helper(QObject* parent = 0, const char* name = 0)
|
|
: Qt_widget_layer(parent, name) {}
|
|
|
|
virtual void got_it() { emit new_object_time(); }
|
|
|
|
signals:
|
|
void new_object_time();
|
|
};
|
|
|
|
} // namespace CGALi
|
|
|
|
template <class R>
|
|
class Qt_widget_get_arc
|
|
: public CGALi::Qt_widget_get_arc_helper
|
|
{
|
|
typedef typename R::FT FT;
|
|
typedef typename R::Circle_2 Circle;
|
|
typedef typename R::Circular_arc_2 Circular_arc_2;
|
|
typedef typename R::Segment_2 Segment;
|
|
typedef typename R::Line_2 Line;
|
|
typedef typename R::Point_2 Point;
|
|
|
|
public:
|
|
|
|
Qt_widget_get_arc(const QCursor c=QCursor(Qt::crossCursor),
|
|
QObject* parent = 0, const char* name = 0)
|
|
: CGALi::Qt_widget_get_arc_helper(parent, name),
|
|
cursor(c), firstpoint(false),
|
|
firsttime(true), secondpoint(false), thirdpoint(false),
|
|
clockwise(false)
|
|
{}
|
|
|
|
void draw()
|
|
{
|
|
if (secondpoint) {
|
|
*widget << CGAL::GREEN << introduced_circle;
|
|
if (thirdpoint){
|
|
*widget << CGAL::BLUE << Segment(Point(x1, y1), first_point);
|
|
}
|
|
}
|
|
firsttime = true;
|
|
}
|
|
|
|
private:
|
|
|
|
bool is_pure(Qt::ButtonState s) {
|
|
return ! ((s & Qt::ControlButton) ||
|
|
(s & Qt::ShiftButton) ||
|
|
(s & Qt::AltButton));
|
|
}
|
|
|
|
void mousePressEvent(QMouseEvent *e)
|
|
{
|
|
if (e->button() == CGAL_QT_WIDGET_GET_POINT_BUTTON
|
|
&& !firstpoint
|
|
&& is_pure(e->state()))
|
|
{
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
x1 = x;
|
|
y1 = y;
|
|
x2 = x;
|
|
y2 = y;
|
|
firstpoint = true;
|
|
center = Point(x, y);
|
|
} else if (e->button() == CGAL_QT_WIDGET_GET_POINT_BUTTON
|
|
&& !secondpoint && is_pure(e->state()))
|
|
{
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
introduced_circle = Circle(Point(x1,y1),
|
|
squared_distance(Point(x1, y1), Point(x,y)));
|
|
secondpoint = true;
|
|
firsttime = true;
|
|
on_the_boundary = Point(x, y);
|
|
} else if (e->button() == CGAL_QT_WIDGET_GET_POINT_BUTTON
|
|
&& !thirdpoint && is_pure(e->state())){
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
first_point = Point(x, y);
|
|
thirdpoint = true;
|
|
firsttime = true;
|
|
} else if (e->button() == CGAL_QT_WIDGET_GET_POINT_BUTTON){
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
second_point = Point(x, y);
|
|
firstpoint = false; secondpoint = false; thirdpoint = false;
|
|
firsttime = true;
|
|
got_it();
|
|
}
|
|
}
|
|
|
|
void keyPressEvent(QKeyEvent *e)
|
|
{
|
|
switch ( e->key() ) {
|
|
case Key_Escape: // key_escape
|
|
if (firstpoint && !secondpoint)
|
|
{
|
|
firstpoint = false;
|
|
RasterOp old_raster = widget->rasterOp();
|
|
QColor old_color = widget->color();
|
|
widget->lock();
|
|
widget->setRasterOp(XorROP);
|
|
*widget << CGAL::GREEN;
|
|
*widget << Circle(Point(x1,y1),
|
|
squared_distance(Point(x1, y1), Point(x2,y2)));
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
widget->unlock();
|
|
firsttime = true;
|
|
}
|
|
break;
|
|
case Key_C:
|
|
if(thirdpoint){
|
|
clockwise = !clockwise;
|
|
if(!firsttime){
|
|
//draw the arc
|
|
QColor old_color = widget->color();
|
|
RasterOp old_raster = widget->rasterOp();
|
|
//save the initial raster mode
|
|
widget->setRasterOp(XorROP);
|
|
widget->lock();
|
|
*widget << CGAL::RED;
|
|
int x_screen = widget->x_pixel(CGAL::to_double(center.x()));
|
|
int y_screen = widget->y_pixel(CGAL::to_double(center.y()));
|
|
int x_screen_b = widget->x_pixel(CGAL::to_double(on_the_boundary.x()));
|
|
int y_screen_b = widget->y_pixel(CGAL::to_double(on_the_boundary.y()));
|
|
int radius = (int)sqrt(CGAL::to_double((x_screen_b - x_screen) *
|
|
(x_screen_b - x_screen) +
|
|
(y_screen_b - y_screen) *
|
|
(y_screen_b - y_screen)));
|
|
double diff = 180/3.1415926;
|
|
|
|
double a = atan2( to_double(first_point.y() - center.y()),
|
|
to_double(first_point.x() - center.x()));
|
|
double a2p = atan2( to_double(y2 - center.y()),
|
|
to_double(x2 - center.x()));
|
|
if(!clockwise){double tempa = a; a = a2p; a2p = tempa;}
|
|
|
|
double alen2;
|
|
if(a2p > a)
|
|
alen2 = a2p - a;
|
|
else
|
|
alen2 = 2 * 3.1415926 + a2p - a;
|
|
|
|
widget->get_painter().drawArc(x_screen - radius,
|
|
y_screen - radius,
|
|
2 * radius, 2 * radius,
|
|
(int)(a * diff * 16),
|
|
(int)(alen2 * diff * 16));
|
|
a = atan2( to_double(first_point.y() - center.y()),
|
|
to_double(first_point.x() - center.x()));
|
|
double a2 = atan2( to_double(y2 - center.y()),
|
|
to_double(x2 - center.x()));
|
|
if(clockwise){double tempa = a; a = a2; a2 = tempa;}
|
|
double alen;
|
|
if(a2 > a)
|
|
alen = a2 - a;
|
|
else
|
|
alen = 2 * 3.1415926 + a2 - a;
|
|
|
|
widget->get_painter().drawArc(x_screen - radius,
|
|
y_screen - radius,
|
|
2 * radius, 2 * radius,
|
|
(int)(a * diff * 16),
|
|
(int)(alen * diff * 16));
|
|
widget->unlock();
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
}
|
|
}
|
|
break;
|
|
}//endswitch
|
|
}
|
|
|
|
void leaveEvent(QEvent *)
|
|
{
|
|
if (firstpoint && !secondpoint)
|
|
{
|
|
QColor old_color = widget->color();
|
|
RasterOp old_raster = widget->rasterOp(); //save the initial raster mode
|
|
|
|
widget->lock();
|
|
widget->setRasterOp(XorROP);
|
|
*widget << CGAL::GREEN << Circle(Point(x1,y1),
|
|
squared_distance(Point(x1, y1),
|
|
Point(x2,y2)));
|
|
widget->unlock();
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
firsttime = true;
|
|
}
|
|
}
|
|
|
|
void mouseMoveEvent(QMouseEvent *e)
|
|
{
|
|
if (firstpoint==true && !secondpoint)
|
|
{
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
QColor old_color = widget->color();
|
|
RasterOp old_raster = widget->rasterOp();//save the initial raster mode
|
|
widget->setRasterOp(XorROP);
|
|
widget->lock();
|
|
*widget << CGAL::GREEN;
|
|
if(!firsttime)
|
|
*widget << Circle(Point(x1,y1),
|
|
squared_distance(Point(x1, y1), Point(x2,y2)));
|
|
*widget << Circle(Point(x1,y1),
|
|
squared_distance(Point(x1, y1), Point(x,y)));
|
|
widget->unlock();
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
|
|
//save the last coordinates to redraw the screen
|
|
x2 = x;
|
|
y2 = y;
|
|
firsttime = false;
|
|
} else if(secondpoint || thirdpoint){
|
|
FT x, y;
|
|
widget->x_real(e->x(), x);
|
|
widget->y_real(e->y(), y);
|
|
QColor old_color = widget->color();
|
|
RasterOp old_raster = widget->rasterOp();//save the initial raster mode
|
|
widget->setRasterOp(XorROP);
|
|
widget->lock();
|
|
*widget << CGAL::BLUE;
|
|
if(!firsttime)
|
|
*widget << Segment(Point(x1,y1),Point(x2,y2));
|
|
|
|
*widget << Segment(Point(x1,y1),Point(x,y));
|
|
widget->unlock();
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
//save the last coordinates to redraw the screen
|
|
|
|
if(thirdpoint){
|
|
//draw the arc
|
|
QColor old_color = widget->color();
|
|
RasterOp old_raster = widget->rasterOp();//save the initial raster mode
|
|
widget->setRasterOp(XorROP);
|
|
widget->lock();
|
|
*widget << CGAL::RED;
|
|
|
|
int x_screen = widget->x_pixel(CGAL::to_double(center.x()));
|
|
int y_screen = widget->y_pixel(CGAL::to_double(center.y()));
|
|
int x_screen_b = widget->x_pixel(CGAL::to_double(on_the_boundary.x()));
|
|
int y_screen_b = widget->y_pixel(CGAL::to_double(on_the_boundary.y()));
|
|
|
|
int radius = (int)sqrt(CGAL::to_double((x_screen_b - x_screen) *
|
|
(x_screen_b - x_screen) +
|
|
(y_screen_b - y_screen) *
|
|
(y_screen_b - y_screen)));
|
|
|
|
double diff = 180/3.1415926;
|
|
|
|
double a = atan2( to_double(first_point.y() - center.y()),
|
|
to_double(first_point.x() - center.x()));
|
|
|
|
double a2 = atan2( to_double(y - center.y()),
|
|
to_double(x - center.x()));
|
|
if(clockwise){double tempa = a; a = a2; a2 = tempa;}
|
|
double alen;
|
|
if(a2 > a)
|
|
alen = a2 - a;
|
|
else
|
|
alen = 2 * 3.1415926 + a2 - a;
|
|
|
|
if(!firsttime){
|
|
double a = atan2( to_double(first_point.y() - center.y()),
|
|
to_double(first_point.x() - center.x()));
|
|
double a2p = atan2( to_double(y2 - center.y()),
|
|
to_double(x2 - center.x()));
|
|
if(clockwise){double tempa = a; a = a2p; a2p = tempa;}
|
|
|
|
double alen2;
|
|
if(a2p > a)
|
|
alen2 = a2p - a;
|
|
else
|
|
alen2 = 2 * 3.1415926 + a2p - a;
|
|
|
|
widget->get_painter().drawArc(x_screen - radius,
|
|
y_screen - radius,
|
|
2 * radius, 2 * radius,
|
|
(int)(a * diff * 16),
|
|
(int)(alen2 * diff * 16));
|
|
}
|
|
|
|
widget->get_painter().drawArc(x_screen - radius,
|
|
y_screen - radius,
|
|
2 * radius, 2 * radius,
|
|
(int)(a * diff * 16),
|
|
(int)(alen * diff * 16));
|
|
widget->unlock();
|
|
widget->setRasterOp(old_raster);
|
|
widget->setColor(old_color);
|
|
}
|
|
x2 = x;
|
|
y2 = y;
|
|
firsttime = false;
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
Circular_arc_2 get_circular_arc() {
|
|
//Circle circ (introduced_circle.center(),
|
|
//introduced_circle.squared_radius());
|
|
Circle circ = introduced_circle;
|
|
|
|
if (clockwise)
|
|
std::swap(first_point, second_point);
|
|
|
|
Line l1 (first_point, center);
|
|
Line l2 (second_point, center);
|
|
|
|
return Circular_arc_2 (circ,
|
|
// FIXME which one is newer?
|
|
//l1, compare_lexicographically_xy(first_point, center) == CGAL::SMALLER,
|
|
//l2, compare_lexicographically_xy(second_point, center) == CGAL::SMALLER);
|
|
l1, CGAL::compare_xy(first_point, center) == CGAL::SMALLER,
|
|
l2, CGAL::compare_xy(second_point, center) == CGAL::SMALLER);
|
|
}
|
|
|
|
private:
|
|
|
|
void activating()
|
|
{
|
|
oldpolicy = widget->focusPolicy();
|
|
widget->setFocusPolicy(QWidget::StrongFocus);
|
|
oldcursor = widget->cursor();
|
|
widget->setCursor(cursor);
|
|
}
|
|
|
|
void deactivating()
|
|
{
|
|
widget->setFocusPolicy(oldpolicy);
|
|
widget->setCursor(oldcursor);
|
|
firstpoint = false;
|
|
}
|
|
|
|
QCursor cursor;
|
|
QCursor oldcursor;
|
|
|
|
FT x1, //the X of the first point
|
|
y1; //the Y of the first point
|
|
FT x2, //the old second point's X
|
|
y2; //the old second point's Y
|
|
bool firstpoint, //true if the user left clicked once
|
|
firsttime; //true if the line is not drawn
|
|
bool secondpoint;//true after the secons point
|
|
bool thirdpoint; //true after the third point
|
|
|
|
Circle introduced_circle;
|
|
Point center;
|
|
Point on_the_boundary;
|
|
|
|
Point first_point;
|
|
Point second_point;
|
|
|
|
bool clockwise;
|
|
|
|
QWidget::FocusPolicy oldpolicy;
|
|
};
|
|
|
|
} // namespace CGAL
|
|
|
|
#endif // CGAL_QT_WIDGET_GET_ARC_H
|