225 lines
4.2 KiB
C++
225 lines
4.2 KiB
C++
#include "Canvas.h"
|
|
|
|
static double dist_P2P(QPointF p1, QPointF p2) {
|
|
return sqrt(pow(p2.x() - p1.x(), 2) + pow(p2.y() - p1.y(), 2));
|
|
}
|
|
|
|
void Canvas::changeMode(Mode _mode)
|
|
{
|
|
mode = _mode;
|
|
}
|
|
|
|
// TODO
|
|
Line* Canvas::findAt(QPointF& pos)
|
|
{
|
|
for (Line* line : lines) {
|
|
if (line->contains(pos)) {
|
|
return line;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Point* Canvas::findPointAt(QPointF pos, qreal tolerance)
|
|
{
|
|
for (Line* line : lines) {
|
|
QPointF p1(*line->p1.x, *line->p1.y);
|
|
QPointF p2(*line->p2.x, *line->p2.y);
|
|
|
|
if (dist_P2P(p1, pos) <= tolerance)
|
|
return &line->p1;
|
|
else if (dist_P2P(p2, pos) <= tolerance)
|
|
return &line->p2;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
LinePair Canvas::makeOrderedPair(Line* l1, Line* l2)
|
|
{
|
|
return (l1 < l2) ? std::make_pair(l1, l2) : std::make_pair(l2, l1);
|
|
}
|
|
|
|
bool Canvas::areAlreadyParallel(Line* l1, Line* l2)
|
|
{
|
|
return parallelPairs.count(makeOrderedPair(l1, l2)) > 0;
|
|
}
|
|
|
|
void Canvas::mousePressEvent(QMouseEvent* event)
|
|
{
|
|
QPointF scene = event->pos();
|
|
|
|
#ifdef _DEBUG
|
|
qDebug() << "Scene point in" << scene.x() << scene.y();
|
|
#endif
|
|
|
|
if (mode == Mode::DrawingLine) {
|
|
if (!current_line) {
|
|
current_line = new Line();
|
|
current_line->set_tag(obj_count);
|
|
double* x1 = new double(scene.x());
|
|
double* y1 = new double(scene.y());
|
|
|
|
double* x2 = new double(scene.x());
|
|
double* y2 = new double(scene.y());
|
|
|
|
params.push_back(x1);
|
|
params.push_back(y1);
|
|
|
|
points.push_back(Point(x1, y1, obj_count));
|
|
points.push_back(Point(x2, y2, obj_count));
|
|
|
|
current_line->p1.x = x1;
|
|
current_line->p1.y = y1;
|
|
current_line->p2.x = x2;
|
|
current_line->p2.y = y2;
|
|
}
|
|
else {
|
|
*current_line->p2.x = scene.x();
|
|
*current_line->p2.y = scene.y();
|
|
|
|
params.push_back(current_line->p2.x);
|
|
params.push_back(current_line->p2.y);
|
|
|
|
lines.append(current_line);
|
|
current_line = nullptr;
|
|
mode = Mode::None;
|
|
obj_count++;
|
|
update();
|
|
return;
|
|
}
|
|
}
|
|
|
|
else if (mode == Mode::Parallel) {
|
|
static Line* first = nullptr;
|
|
Line* found = findAt(scene);
|
|
|
|
if (!found) {
|
|
first = nullptr;
|
|
return;
|
|
}
|
|
|
|
if (!first) {
|
|
first = found;
|
|
return;
|
|
}
|
|
|
|
if (found == first){
|
|
first = nullptr;
|
|
return;
|
|
}
|
|
|
|
if (!areAlreadyParallel(found, first)) {
|
|
sys.addConstraintParallel(*found, *first, constraints_count++);
|
|
parallelPairs.insert(makeOrderedPair(found, first));
|
|
first = nullptr;
|
|
mode = Mode::None;
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef _DEBUG
|
|
qDebug() << "Line" << first << "and" << found << "are parallel. Abort!";
|
|
#endif
|
|
QMessageBox::warning(this,
|
|
QString("Wrong"),
|
|
QString("Parallel lines can not be more parallel!"),
|
|
QMessageBox::Ok
|
|
);
|
|
first = nullptr;
|
|
return;
|
|
}
|
|
|
|
update();
|
|
}
|
|
|
|
else if (mode == Mode::Coincedent) {
|
|
Point* clickedPoint = findPointAt(scene);
|
|
|
|
if (!clickedPoint) {
|
|
firstPoint = nullptr;
|
|
return;
|
|
}
|
|
|
|
if (!firstPoint) {
|
|
firstPoint = clickedPoint;
|
|
return;
|
|
}
|
|
|
|
if (clickedPoint == firstPoint) {
|
|
firstPoint = nullptr;
|
|
return;
|
|
}
|
|
|
|
Line *l1 = nullptr, *l2 = nullptr;
|
|
for (Line* l : lines) {
|
|
if (&l->p1 == firstPoint || &l->p2 == firstPoint) l1 = l;
|
|
if (&l->p1 == clickedPoint || &l->p2 == clickedPoint) l2 = l;
|
|
}
|
|
|
|
if (l1 == l2) {
|
|
QMessageBox::warning(this, QString("NO!"), QString("P2P failed"));
|
|
firstPoint = nullptr;
|
|
return;
|
|
}
|
|
|
|
sys.addConstraintP2PCoincident(*firstPoint, *clickedPoint, constraints_count++);
|
|
firstPoint = nullptr;
|
|
mode = Mode::None;
|
|
update();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Canvas::paintEvent(QPaintEvent*)
|
|
{
|
|
QPainter p(this);
|
|
p.setRenderHint(QPainter::Antialiasing);
|
|
if (!params.empty()) {
|
|
int res = sys.solve(params);
|
|
if (res == SolveStatus::Success) {
|
|
sys.applySolution();
|
|
}
|
|
else {
|
|
#ifdef _DEBUG
|
|
qDebug() << "INVAILD LAST CONSTRAINT. REMOVE HIM";
|
|
#endif
|
|
sys.removeConstraint(sys.get_last_constraint());
|
|
}
|
|
}
|
|
for (Line* line : lines) {
|
|
line->draw(p);
|
|
}
|
|
return;
|
|
}
|
|
|
|
Canvas::Canvas(QWidget *parent)
|
|
: QWidget(parent)
|
|
{
|
|
sys = System();
|
|
current_line = nullptr;
|
|
setMouseTracking(true);
|
|
setBackgroundRole(QPalette::Base);
|
|
setAutoFillBackground(true);
|
|
}
|
|
|
|
Canvas::~Canvas()
|
|
{
|
|
for (Line* line : lines) {
|
|
delete line;
|
|
}
|
|
|
|
for (double* param : params) {
|
|
delete param;
|
|
}
|
|
|
|
lines.clear();
|
|
params.clear();
|
|
points.clear();
|
|
|
|
if (current_line)
|
|
delete current_line;
|
|
if (firstPoint)
|
|
delete firstPoint;
|
|
}
|
|
|