From aa0868d50d4455970e0654b0d3c0da19df49a53a Mon Sep 17 00:00:00 2001 From: w-mj Date: Mon, 25 Dec 2017 15:25:45 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=9C=8B=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- car.cpp | 14 +++++++------- car.h | 3 +++ parkingLotManager.cpp | 17 +++++++++++++++-- parkingLotManager.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/car.cpp b/car.cpp index 8ba105d..910e53a 100644 --- a/car.cpp +++ b/car.cpp @@ -37,14 +37,8 @@ Car::Car(ParkingLotManager * manager, QGraphicsItem *parent, int dir, Car::Color 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); m_number = "1234"; - - // 测试:创建10s后离开 - QTimer *timer = new QTimer(this); - connect(timer, &QTimer::timeout, [this, manager](){emit manager->requestOut(this);}); - timer->setSingleShot(true); - timer->start(10000); } void Car::Forward(qreal vel) @@ -228,6 +222,12 @@ void Car::setStartTime(const QTime &value) startTime = value; } +void Car::leaveProbability(int p) +{ + if (rand() % 100 + 1 < p) + emit out(this, -1); +} + int Car::getTargetFloor() const { return targetFloor; diff --git a/car.h b/car.h index 58cc264..ad773b2 100644 --- a/car.h +++ b/car.h @@ -68,6 +68,8 @@ public: QTime getStartTime() const; void setStartTime(const QTime &value); + void leaveProbability(int p); + private: Status m_status; Color m_color; //车身颜色 N为0, 顺时针递增 @@ -89,6 +91,7 @@ signals: void stair(Car* car); void exit(Car* car); void queueHead(Car* car); + void out(Car *car ,int); }; #endif // CAR_H diff --git a/parkingLotManager.cpp b/parkingLotManager.cpp index e5362eb..f29fcdf 100644 --- a/parkingLotManager.cpp +++ b/parkingLotManager.cpp @@ -57,6 +57,10 @@ ParkingLotManager::ParkingLotManager(QObject* objectParent, QGraphicsScene* scen generatePool(true); Adapter *adapter = new Adapter(objectParent, &m_all_cars); // 注册model CarList::getInstance()->setAdapter(adapter); + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &ParkingLotManager::periodWork); + timer->start(1000); // 轮询 } void ParkingLotManager::showParkingLot(uint pos) @@ -227,8 +231,6 @@ void ParkingLotManager::addCar(int entry) if (entry == -1) entry = (rand() % m_num_of_entry); - entry = 0; - Car *car = new Car(this); car->setEntryNum(entry + 1); m_waitting[entry].append(car); @@ -281,3 +283,14 @@ void ParkingLotManager::generatePool(bool sequence) std::random_shuffle(m_pool.begin(), m_pool.end()); Log::i(QString("生成车位池成功,当前共有") + QString::number(m_pool.size()) + "个空车位"); } + +void ParkingLotManager::periodWork() +{ + int generateProbability = 80; + if (rand() % 100 + 1 < generateProbability) + addCar(); + for (auto c: m_all_cars) { + if (c->getStatus() == Car::parking) + c->leaveProbability(2); + } +} diff --git a/parkingLotManager.h b/parkingLotManager.h index 34e0119..339cf8f 100644 --- a/parkingLotManager.h +++ b/parkingLotManager.h @@ -64,6 +64,8 @@ private: void generatePool(bool sequence); + void periodWork(void); + signals: void enableUpButton(bool); void enableDownButton(bool); From af2a3938eca41eef4226b7f61d8c54a0ea517ab6 Mon Sep 17 00:00:00 2001 From: w-mj Date: Mon, 25 Dec 2017 20:18:43 +0800 Subject: [PATCH 2/2] =?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; };