//交差点削除、接続単路も削除、なしなら無視 void Map::deleteIntsec(int intsecId) { MAP_INTSECMAP_IT imi; Intsec* pIntsec; INTSEC_ROADMAP_IT irmi; Road* pRoad; vector<int> deleteRoadId; int i; // qDebug("Map::deleteIntsec %d", intsecId); imi = _intsecMap.find(intsecId); if (imi == _intsecMap.end()) return; pIntsec = imi->second; //単路削除時に接続情報を消すので後でまとめて実行 pRoad = pIntsec->nextRoad(&irmi, true); while (pRoad != NULL) { deleteRoadId.push_back(pRoad->getRoadId()); pRoad = pIntsec->nextRoad(&irmi); } for (i=0; i < (int)deleteRoadId.size(); i++) deleteRoad(deleteRoadId[i]); delete pIntsec; _intsecMap.erase(imi); }
//単路付け換え、付け換え後単路返却、構造的変換なので注意、既存単路不可 Road* Map::replaceRoad(Intsec* pIntsec, Intsec* pIntsecNew, Intsec* pIntsecCon) { bool already; Road* pRoad; Road* pRoadNew; pRoad = pIntsec->getRoad(pIntsecCon->getIntsecId()); Q_ASSERT(pRoad!=NULL); pRoadNew = createRoad(pIntsecCon, pIntsecNew, &already); Q_ASSERT(!already); pRoadNew->copyLane(pRoad); if (pIntsecCon->getFirstIntsecIdCon() == pIntsec->getIntsecId()) pIntsecCon->setFirstIntsecIdCon(pIntsecNew->getIntsecId()); deleteRoad(pRoad->getRoadId()); return pRoadNew; }
//ドロップイベント void MapFrame::dropEvent(QDropEvent *event) { Intsec* pIntsec; Intsec* pIntsecDrop; Intsec* pIntsecReplCon; Map* pMap = app.getMap(); double x, y; bool already; Road* pRoad; //自ドラッグ判定、ドラッグ開始で弾かれるようだが念のため if (!event->mimeData()->hasFormat(ITEM_MINETYPE) || (event->source() != this)) { event->ignore(); return; } //スクロール以外なら交差点取得、必ずあるはずだが念のため if (_dragType != scroll) { // qDebug("drop %d", _intsecIdDrag); pIntsec = pMap->getIntsec(_intsecIdDrag); if (pIntsec == NULL) { event->ignore(); return; } //単路ドラッグ位置設定 if (_dragType == intsec ||_dragType == road || _dragType == roadRepl) { _dragRoadX = event->pos().x() - _offsetDragX; _dragRoadY = event->pos().y() - _offsetDragY; } //交差点移動 if (_dragType == intsec) { x = getMapX(event->pos().x() - _offsetDragX); y = getMapY(event->pos().y() - _offsetDragY); if (x < APP_POS_MIN || y < APP_POS_MIN ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が小さすぎます。")); else if (x > APP_POS_MAX || y > APP_POS_MAX ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が大きすぎます。")); else pIntsec->setMapPos(x, y, pIntsec->getMapPosZ()); // pMap->debugTrace(); } //単路作成 else if (_dragType == road) { pIntsecDrop = getIntsecAt(_dragRoadX, _dragRoadY); if (pIntsecDrop != NULL && pIntsecDrop->getIntsecId() != _intsecIdDrag) { pRoad = pMap->createRoad(pIntsec, pIntsecDrop, &already); if (already) QMessageBox::warning(this, tr(TITLE), tr("既に単路があります。")); else { if (!app.getMainWindow()->isLane2()) pRoad->setLane4(); changeShowSelect(_intsecIdDrag, pIntsecDrop->getIntsecId(), pRoad->getRoadId()); } // pMap->debugTrace(); } } //単路入れ替え、先頭接続先交差点ID変更、タイミング注意 else if (_dragType == roadRepl) { pIntsecDrop = getIntsecAt(_dragRoadX, _dragRoadY); if (pIntsecDrop != NULL && pIntsecDrop->getIntsecId() != _intsecIdDrag && pIntsecDrop->getIntsecId() != _intsecIdReplCon) { pIntsecReplCon = pMap->getIntsec(_intsecIdReplCon); Q_ASSERT(pIntsecReplCon!=NULL); if (pMap->getRoad(_intsecIdReplCon, pIntsecDrop->getIntsecId()) != NULL) QMessageBox::warning(this, tr(TITLE), tr("既に単路があります。")); else { pRoad = pMap->replaceRoad(pIntsec, pIntsecDrop, pIntsecReplCon); if (_intsecIdDrag == _intsecIdSelect) changeShowSelect(pIntsecDrop->getIntsecId(), _intsecIdDest, pRoad->getRoadId()); else changeShowSelect(_intsecIdSelect, pIntsecDrop->getIntsecId(), pRoad->getRoadId()); } } } } //ドロップ終了、再描画はドラッグ処理で実行 event->accept(); }
//描画 void MapFrame::paint(QPainter* pp) { Map* pMap = app.getMap(); QRect rectSource, rectDest; double viewBackMagni; MAP_INTSECMAP_IT imi; Intsec* pIntsec; stringstream ss; int viewX, viewY; MAP_ROADMAP_IT rmi; Road* pRoad; DrawLineType drawLineType; //塗りつぶし、ドラッグ画面用 pp->fillRect(0, 0, width(), height(), Qt::gray); //背景描画 if (app.getBackImage() && !_backPixmap.isNull()) { viewBackMagni = app.getBackMagni() * app.getViewMagni(); // view / back rectDest.setCoords(0, 0, width(), height()); rectSource.setLeft( (int)((double)(app.getViewMapX() - app.getBackMapX()) / app.getBackMagni())); rectSource.setBottom(_backPixmap.size().height() - (int)((double)(app.getViewMapY() - app.getBackMapY()) / app.getBackMagni())); rectSource.setRight( rectSource.left() + (int)((double)width() / viewBackMagni)); rectSource.setTop( rectSource.bottom() - (int)((double)height() / viewBackMagni)); pp->drawPixmap(rectDest, _backPixmap, rectSource); } //全単路描画 pMap = app.getMap(); pRoad = pMap->nextRoad(&rmi, true); while (pRoad != NULL) { if (pRoad->getRoadId() == _roadIdSelect) { if (_dragType == roadRepl) { // qDebug("MapFrame::paint drag road replace selected"); drawLineType = selectedDark; } else drawLineType = selected; } else drawLineType = normal; if (_dragType == intsec) { // qDebug("MapFrame::paint drag intsec road"); if (pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId() == _intsecIdDrag || pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId() == _intsecIdDrag ) { // qDebug("MapFrame::paint drag intsec road selected"); drawLineType = selectedDark; } } // qDebug("MapFrame::paint road (%d,%d) drag %d lineType:%d", // pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId(), // pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId(), _intsecIdDrag, drawLineType); if (isViewArea(pRoad->getIntsec(ROAD_IT_SMALL)) || isViewArea(pRoad->getIntsec(ROAD_IT_LARGE))) drawLine(pp, getViewX(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_SMALL)->getMapPosY()), getViewX(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosX()), getViewY(pRoad->getIntsec(ROAD_IT_LARGE)->getMapPosY()), drawLineType, pRoad->isLaneOver4(), pRoad->isError()); pRoad = pMap->nextRoad(&rmi); } //交差点ID描画、広域表示では点描画 if (app.getShowId()) { pIntsec = pMap->nextIntsec(&imi, true); while (pIntsec != NULL) { if (isViewArea(pIntsec)) { if (app.getMainWindow()->getEditMode() != MainWindow::large) { ss.str(""); ss << pIntsec->getIntsecId(); viewX = getViewX(pIntsec->getMapPosX()) + INTSEC_LABELSIZE_H + 2; viewY = getViewY(pIntsec->getMapPosY()) + INTSEC_LABELSIZE_H + 2; pp->setPen(QColor("#FFFFFF")); pp->drawText(viewX - 1, viewY + 1, ss.str().c_str()); pp->drawText(viewX - 1, viewY - 1, ss.str().c_str()); pp->drawText(viewX + 1, viewY - 1, ss.str().c_str()); pp->drawText(viewX + 1, viewY + 1, ss.str().c_str()); pp->setPen(QColor("#0000FF")); pp->drawText(viewX, viewY, ss.str().c_str()); } else { viewX = getViewX(pIntsec->getMapPosX()) - 2; viewY = getViewY(pIntsec->getMapPosY()) - 2; QString colorName; if (pIntsec->getIntsecId() == _intsecIdSelect) { if (pIntsec->isError()) colorName = "#FF00FF"; else colorName = "#0000FF"; } else { if (pIntsec->isError()) colorName = "#FF0000"; else colorName = "#000000"; } //何故かこうしないと描けない QBrush brush(QColor(colorName.toStdString().c_str())); pp->setPen(QColor(colorName)); pp->fillRect(viewX, viewY, 4, 4, brush); pp->drawRect(viewX, viewY, 4, 4); } } pIntsec = pMap->nextIntsec(&imi); } } }
//マウス開放イベント void MapFrame::mouseReleaseEvent(QMouseEvent *event) { Map* pMap = app.getMap(); Intsec* pIntsec; Road* pRoad; bool roadSelected; int intsecIdSmall, intsecIdLarge, intsecIdNew; double x, y; //右ボタンクリック/ドラッグならクリック、このチェックはいらないようだが念のため // qDebug("MapFrame::mouseReleaseEvent"); if (event->button()!=Qt::LeftButton || !_clickDrag) return; // qDebug("MapFrame::mouseReleaseEvent click"); _clickDrag = false; //交差点選択あり、交差点以外は NULL pIntsec = getIntsecAt(_clickDragX, _clickDragY); if (pIntsec != NULL) { changeShowSelect(pIntsec->getIntsecId(), MAP_NOID, MAP_NOID); showStatus(event->pos().x(), event->pos().y(), pIntsec->getIntsecId()); //交差点モードなら編集画面 if (app.getMainWindow()->getEditMode() == MainWindow::intsec) { IntsecDialog id(this); // qDebug("MapFrame::mouseReleaseEvent intsec dialog (%d, %d)", _intsecDialogX, _intsecDialogY); id.init(pIntsec); if (_intsecDialogX != DIALOG_NOPOS) id.move(_intsecDialogX, _intsecDialogY); if (id.exec() == QDialog::Accepted) { if (id.isDelete()) { pMap->deleteIntsec(pIntsec->getIntsecId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } else { if (id.isCenter()) { app.setViewMap(app.getViewMapX() - pIntsec->getMapPosX(), app.getViewMapY() - pIntsec->getMapPosY()); if (app.getBackImage()) app.setBackMap(app.getBackMapX() - pIntsec->getMapPosX(), app.getBackMapY() - pIntsec->getMapPosY()); pMap->setCenter(pIntsec->getMapPosX(), pIntsec->getMapPosY(), 0); } //ID が変わったらマップで入れ替え、再選択 intsecIdNew = id.getIntsecId(); if (intsecIdNew != pIntsec->getIntsecId()) { pIntsec = pMap->changeIntsecId(pIntsec, intsecIdNew); changeShowSelect(intsecIdNew, MAP_NOID, MAP_NOID, true); } showIntsec(pIntsec); //全体再描画は遅いので先に書いとく } repaintAll(true); } // qDebug("MapFrame::mouseReleaseEvent intsec dialog (%d, %d)", id.x(), id.y()); _intsecDialogX = id.x(); _intsecDialogY = id.y(); } //単路/単路付け替えモードならモード切り替え(メインウィンドウから) else if (app.getMainWindow()->getEditMode() == MainWindow::road || app.getMainWindow()->getEditMode() == MainWindow::roadRepl) app.getMainWindow()->setEditMode(MainWindow::intsec); } //交差点選択なし else { //単路選択あり pRoad = getRoadAt(_clickDragX, _clickDragY); if (pRoad != NULL) { roadSelected = false; if (pRoad->getRoadId() == _roadIdSelect) roadSelected = true; intsecIdSmall = pRoad->getIntsec(ROAD_IT_SMALL)->getIntsecId(); intsecIdLarge = pRoad->getIntsec(ROAD_IT_LARGE)->getIntsecId(); if (intsecIdLarge == _intsecIdSelect) changeShowSelect(intsecIdLarge, intsecIdSmall, pRoad->getRoadId()); else changeShowSelect(intsecIdSmall, intsecIdLarge, pRoad->getRoadId()); showStatus(event->pos().x(), event->pos().y(), MAP_NOID); //交差点モードならモード切り替え(メインウィンドウから) if (app.getMainWindow()->getEditMode() == MainWindow::intsec) app.getMainWindow()->setEditMode(MainWindow::road); //単路モードなら編集画面、単路付け替えモードでも選択済みなら編集画面 else if (app.getMainWindow()->getEditMode() == MainWindow::road || (app.getMainWindow()->getEditMode() == MainWindow::roadRepl && roadSelected)) { RoadDialog rd(this); rd.init(pRoad); if (_roadDialogX != DIALOG_NOPOS) rd.move(_roadDialogX, _roadDialogY); if (rd.exec() == QDialog::Accepted) { if (rd.isDelete()) { pMap->deleteRoad(pRoad->getRoadId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } else if (rd.isDelIntsec()) { Intsec* intsec1 = pRoad->getIntsec(ROAD_IT_SMALL); Intsec* intsec2 = pRoad->getIntsec(ROAD_IT_LARGE); pMap->deleteRoad(pRoad->getRoadId()); pMap->deleteIntsec(intsec1->getIntsecId()); pMap->deleteIntsec(intsec2->getIntsecId()); changeShowSelect(MAP_NOID, MAP_NOID, MAP_NOID, true); } repaintAll(true); } _roadDialogX = rd.x(); _roadDialogY = rd.y(); } } //単路選択なし else { //交差点モードなら交差点新規作成、選択変更とエラーチェックと表示、ここは全体再描画なし if (app.getMainWindow()->getEditMode() == MainWindow::intsec) { pIntsec = pMap->createIntsec(); x = getMapX(_clickDragX); y = getMapY(_clickDragY); if (pIntsec == NULL) QMessageBox::critical(this, tr(TITLE), tr("最大交差点IDが大きすぎます。")); if (x < APP_POS_MIN || y < APP_POS_MIN ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が小さすぎます。")); else if (x > APP_POS_MAX || y > APP_POS_MAX ) QMessageBox::critical(this, tr(TITLE), tr("最大位置が大きすぎます。")); else { pIntsec->setMapPos(x, y, 0); changeShowSelect(pIntsec->getIntsecId(), _intsecIdDest, _roadIdSelect); // showStatus なしでも変わるが念のため showStatus(event->pos().x(), event->pos().y(), pIntsec->getIntsecId()); pIntsec->checkError(); showIntsec(pIntsec); // app.getMap()->debugTrace(); } } } } }