From af2a3938eca41eef4226b7f61d8c54a0ea517ab6 Mon Sep 17 00:00:00 2001 From: w-mj Date: Mon, 25 Dec 2017 20:18:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=BE=E5=BC=83=E7=AD=89=E5=BE=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- car.cpp | 21 +++++++++++++++------ car.h | 1 + parkingLotManager.cpp | 32 +++++++++++++++++++++++++++++++- parkingLotManager.h | 3 +++ parkinglotgraph.cpp | 30 +++++++++++++++++++++++++----- parkinglotgraph.h | 4 ++++ path.cpp | 23 +++++++++++++++++++++++ path.h | 5 +++++ 8 files changed, 107 insertions(+), 12 deletions(-) diff --git a/car.cpp b/car.cpp index 910e53a..160b983 100644 --- a/car.cpp +++ b/car.cpp @@ -33,11 +33,13 @@ Car::Car(ParkingLotManager * manager, QGraphicsItem *parent, int dir, Car::Color m_pic = m_pic.scaled(M_WID, M_LEN); this->setPixmap(m_pic); setTransformOriginPoint(M_WID/2, M_LEN/2); //设置旋转中心 - connect(posAni,QPropertyAnimation::finished,this,followPath); + connect(posAni,QPropertyAnimation::finished, this, followPath); connect(this, &Car::queueHead, manager, &ParkingLotManager::requestIn); connect(this, &Car::exit, manager, &ParkingLotManager::leave); connect(this, &Car::stair, manager, &ParkingLotManager::requestStair); connect(this, &Car::out, manager, &ParkingLotManager::requestOut); + connect(this, &Car::back, manager, &ParkingLotManager::requestBack); + // connect(this, &Car::entry, manager, &ParkingLotManager::leave); m_number = "1234"; } @@ -93,9 +95,10 @@ void Car::setPath(Path *path) { m_path = path; m_target = path->getNext(); + m_target.point = m_target.point - QPoint(20, 30); m_current = m_target; m_target.action = Road::none; - this->setPos(m_target.point - QPoint(20, 30)); + this->setPos(m_target.point); this->setRotation(m_target.dir+90); } @@ -115,8 +118,12 @@ void Car::moveTo(QPointF target) qreal dy = m_current.point.y()-m_target.point.y(); qreal dis = qSqrt(qPow(dx,2)+qPow(dy,2)); qreal dur = dis/0.3; - target.setX(target.x() - 20); - target.setY(target.y() - 30); + this->setPos(m_current.point); +// target.setX(target.x() - 20); +// target.setY(target.y() - 30); + Log::i(QString("从%1,%2到%3,%4").arg(m_current.point.x()).arg(m_current.point.y()).arg(target.x()).arg(target.y())); + // posAni->setStartValue(m_current.point); + setRotation(m_current.dir + 90); posAni->setDuration(dur); posAni->setEndValue(target); posAni->start(); @@ -141,15 +148,17 @@ void Car::followPath() break; case Road::queueHead: Log::i("发送请求车位信号"); - emit queueHead(this); + // emit queueHead(this); + emit back(this); break; case Road::none: break; } - if(!m_path->isEmpty()) + if(m_path && !m_path->isEmpty()) { m_current = m_target; m_target = m_path->getNext(); + m_target.point = m_target.point - QPoint(20, 30); moveTo(m_target.point); } else { delete m_path; diff --git a/car.h b/car.h index ad773b2..14d6df5 100644 --- a/car.h +++ b/car.h @@ -92,6 +92,7 @@ signals: void exit(Car* car); void queueHead(Car* car); void out(Car *car ,int); + void back(Car*); }; #endif // CAR_H diff --git a/parkingLotManager.cpp b/parkingLotManager.cpp index f29fcdf..bfda235 100644 --- a/parkingLotManager.cpp +++ b/parkingLotManager.cpp @@ -60,7 +60,7 @@ ParkingLotManager::ParkingLotManager(QObject* objectParent, QGraphicsScene* scen QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &ParkingLotManager::periodWork); - timer->start(1000); // 轮询 + // timer->start(1000); // 轮询 } void ParkingLotManager::showParkingLot(uint pos) @@ -126,6 +126,8 @@ ParkingLotGraph::Node::Type getType(int n) { void ParkingLotManager::drawPath(int n1, int n2) { + if (n1 < -8 || n1 > 104 || n2 < -8 || n2 > 104) + return ; QPen pen(QColor(242, 23, 242)); pen.setWidth(3); Path *p = m_graph[m_current_floor]->findPath(getType(n1), n1, getType(n2), n2); @@ -141,6 +143,22 @@ void ParkingLotManager::drawPath(int n1, int n2) } } +void ParkingLotManager::drawPath(Path* p) +{ + QPen pen(QColor(242, 23, 242)); + pen.setWidth(3); + for(int i = 1; i < p->pointsCount(); i++) { + QLineF line(p->getPoint(i-1).point, p->getPoint(i).point); + QPointF dir(qCos(qDegreesToRadians(p->getPoint(i-1).dir)) * 10, + qSin(qDegreesToRadians(p->getPoint(i-1).dir)) * 10); + QLineF dirLine(p->getPoint(i-1).point, p->getPoint(i-1).point + dir); + m_scene->addLine(line); + m_scene->addLine(dirLine, pen); + m_scene->addText(QString::number(p->getPoint(i-1).dir))->moveBy(p->getPoint(i-1).point.x(), + p->getPoint(i-1).point.y()); + } +} + QString ParkingLotManager::getParkingLotName(int pos) { return m_widgets.at(pos)->getName(); @@ -173,6 +191,7 @@ void ParkingLotManager::requestStair(Car *car) p = m_graph[l]->findPath(NODE_TYPE::stair, e, NODE_TYPE::space, n); else p = m_graph[l]->findPath(NODE_TYPE::stair, e, NODE_TYPE::exit, -n); + // drawPath(p); car->setPath(p); car->setCurrentFloor(l); if (l == static_cast(m_current_floor)) @@ -182,12 +201,22 @@ void ParkingLotManager::requestStair(Car *car) car->followPath(); } +void ParkingLotManager::requestBack(Car *car) +{ + Path* p = m_graph[1]->findPath(car, car->getEntryNum()); + car->setPath(p); + car->followPath(); + m_all_cars.removeOne(car); + m_waitting[car->getEntryNum() - 1].removeOne(car); +} + void ParkingLotManager::requestIn(Car* car) { int entry = car->getEntryNum(); if (!m_pool.empty()) { uint l = m_pool.first().first; int n = m_pool.first().second + 1; + l = 0; m_pool.removeAt(0); Log::i(QString("分配第%1层%2号车位,剩余%3个空车位").arg(l).arg(n).arg(m_pool.size())); Path* p; @@ -196,6 +225,7 @@ void ParkingLotManager::requestIn(Car* car) else { p = m_graph[1]->findPath(NODE_TYPE::queueHead, entry, NODE_TYPE::stair, entry); } + // drawPath(p); m_waitting[entry - 1].removeOne(car); // 移除等候 m_cars[l][n - 1] = car; car->setPath(p); diff --git a/parkingLotManager.h b/parkingLotManager.h index 339cf8f..72a9366 100644 --- a/parkingLotManager.h +++ b/parkingLotManager.h @@ -9,6 +9,7 @@ #include "ParkingLotWidget.h" #include "parkinglotgraph.h" +class ParkingLotGraph; class Car; class ParkingLotManager: public QObject @@ -30,6 +31,7 @@ public: void showDownStairFloor(void); void showUpStairFloor(void); void drawPath(int n1, int n2); + void drawPath(Path* p); QString getParkingLotName(int pos); @@ -37,6 +39,7 @@ public slots: void requestIn(Car* car); void requestOut(Car* car, int exit = -1); void requestStair(Car* car); + void requestBack(Car* car); void leave(Car* car); void addCar(int entry = -1); diff --git a/parkinglotgraph.cpp b/parkinglotgraph.cpp index 4b76a35..68da100 100644 --- a/parkinglotgraph.cpp +++ b/parkinglotgraph.cpp @@ -181,10 +181,12 @@ uint ParkingLotGraph::getNodeId(ParkingLotGraph::Node::Type t, int n) { return -1; } -qreal angle(const QPoint& p) { +qreal angle(const QPointF& p) { return qRadiansToDegrees(qAtan2(p.y(), p.x())); } + + // Dijkstra 求最短路径 Path *ParkingLotGraph::findPath(ParkingLotGraph::Node::Type t1, int n1, ParkingLotGraph::Node::Type t2, int n2) { @@ -227,13 +229,13 @@ Path *ParkingLotGraph::findPath(ParkingLotGraph::Node::Type t1, int n1, ParkingL } } Path* path = new Path(); - uint n = id2; - QPoint lastP; + uint n = id2, lastN;; + QPointF lastP; while (n != id1) { // 相邻两个点的xy都不相等,添加一个辅助顶点构成矩形 if (m_all[n]->data.x() != m_all[prev[n]]->data.x() && m_all[n]->data.y() != m_all[prev[n]]->data.y()) { - QPoint tp; + QPointF tp; if (m_all[n]->type == Node::Type::space) { ParkingSpaceWidget* space = pk->getSpaceList().at(m_all[n]->number - 1); switch (space->getDir()) { @@ -273,10 +275,28 @@ Path *ParkingLotGraph::findPath(ParkingLotGraph::Node::Type t1, int n1, ParkingL } else { qreal ang = angle(m_all[n]->data - m_all[prev[n]]->data); path->addPoint(0, PathPoint(QPointF(m_all[n]->data), ang, m_all[n]->action, m_all[n]->getId())); + lastP = QPointF(m_all[n]->data); } + lastN = n; n = prev[n]; } - path->addPoint(0, PathPoint(QPointF(m_all[n]->data), angle(lastP - m_all[n]->data), m_all[n]->action, m_all[n]->getId())); // 把第一个点也加进去 + if (!lastP.isNull()) + path->addPoint(0, PathPoint(QPointF(m_all[n]->data), + angle(lastP - m_all[n]->data), m_all[n]->action, m_all[n]->getId())); // 把第一个点也加进去 + else + path->addPoint(0, PathPoint(QPointF(m_all[n]->data), + angle(m_all[n]->data - m_all[lastN]->data), m_all[n]->action, m_all[n]->getId())); + path->regularize(); + return path; +} + +Path *ParkingLotGraph::findPath(Car *car, int entry) +{ + Path* path = new Path(); + int entry_id = getNodeId(Node::Type::entry, entry); + qreal ang = angle(QPointF(m_all[entry_id]->data) - car->getmPos()); + path->addPoint(PathPoint(car->getmPos() + QPoint(20, 30), ang)); + path->addPoint(PathPoint(m_all[entry_id]->data, ang, Road::Action::exit)); return path; } diff --git a/parkinglotgraph.h b/parkinglotgraph.h index a14fc00..5971619 100644 --- a/parkinglotgraph.h +++ b/parkinglotgraph.h @@ -10,7 +10,9 @@ #include #include #include "Road.h" +#include "car.h" +class Car; class ParkingLotGraph { public: @@ -41,6 +43,8 @@ public: void paint(QGraphicsScene* scene); Path* findPath(Node::Type t1, int n1, Node::Type t2, int n2); + + Path* findPath(Car* car, int entry); uint getNodeId(Node::Type t, int n); ~ParkingLotGraph(); QPixmap *getPixmap(); diff --git a/path.cpp b/path.cpp index 56a1d5b..24fe8bc 100644 --- a/path.cpp +++ b/path.cpp @@ -1,4 +1,5 @@ #include "path.h" +#include "logwindow.h" Path::Path() { @@ -46,9 +47,31 @@ PathPoint Path::getNext() { PathPoint tmp = path.first(); path.removeFirst(); + // Log::i(QString("(%1,%2)").arg(tmp.point.x()).arg(tmp.point.y())); return tmp; } +bool inl(const QPointF& p1, const QPointF& p2, const QPointF& p3) { + if (p3.x() == p2.x() && p2.x() == p1.x()) + return true; + else if (p3.x() == p2.x() || p2.x() == p1.x()) + return false; + float k1 = (p3.y() - p2.y()) / (p3.x() - p2.x()); + float k2 = (p2.y() - p1.y()) / (p2.x() - p1.x()); + return k2 == k1; +} + +void Path::regularize() +{ + QVector delist; + for (int n = 0; n < path.size() - 2; n++) { + if ( inl(path[n].point, path[n+1].point, path[n+2].point)) + delist.append(path[n + 1]); + } + for (auto n: delist) + path.removeOne(n); +} + void PathPoint::operator=(const PathPoint &another) { point = another.point; diff --git a/path.h b/path.h index 4b5ae8a..2cd278a 100644 --- a/path.h +++ b/path.h @@ -30,6 +30,9 @@ struct PathPoint action = another.action; } void operator=(const PathPoint& another); + bool operator==(const PathPoint& another) { + return (point == another.point && dir == another.dir); + } }; class Path @@ -45,6 +48,8 @@ public: int pointsCount(); PathPoint getNext(); + void regularize(); // 如果三点共线,移除中间那个点 + private: QList path; };