diff --git a/include/personStorage.h b/include/personStorage.h index f245d4d66d3e997394a46148d46443a4163f8d01..dd6d360a09dc319e2494697784c476c1b788963c 100644 --- a/include/personStorage.h +++ b/include/personStorage.h @@ -27,6 +27,11 @@ class Petrack; +struct PersonFrame +{ + int personID; + int frame; +}; class PersonStorage { @@ -76,6 +81,8 @@ public: int largestFirstFrame() const; int largestLastFrame() const; int smallestFirstFrame() const; + std::vector<PersonFrame> + getProximalPersons(const QPointF &pos, int frame, QSet<int> selected, int before, int after) const; void recalcHeight(float altitude); void clear() { mPersons.clear(); } diff --git a/include/petrack.h b/include/petrack.h index 1596a093e93eacc7744d9c7ef4686384528549de..7afa439b4eca3877309274b8b6dfd954b1bd3648 100644 --- a/include/petrack.h +++ b/include/petrack.h @@ -158,6 +158,7 @@ public slots: // void showContextMenu(QPointF pos); void updateSourceInOutFrames(); void skipToFrameWheel(int delta); + void skipToFrameFromTrajectory(QPointF pos); public: void updateControlWidget(); diff --git a/include/view.h b/include/view.h index db25f5437ff7e5d6f22197785a30d201e93b8672..9dac4763ce83dcb17c2ad02bcfe12ba8224b5937 100644 --- a/include/view.h +++ b/include/view.h @@ -52,6 +52,7 @@ public: signals: void mouseDoubleClick(); + void mouseAltDoubleClick(QPointF pos); void mouseShiftControlDoubleClick(QPointF pos); void mouseShiftDoubleClick(QPointF pos); void mouseControlDoubleClick(QPointF pos); diff --git a/src/personStorage.cpp b/src/personStorage.cpp index fcddca68135e579ae899ddda91e4d3c8e97bb619..385fc5bf9b083e04e633cb86748359b92bc4a359 100644 --- a/src/personStorage.cpp +++ b/src/personStorage.cpp @@ -675,6 +675,61 @@ int PersonStorage::smallestFirstFrame() const return minElement != mPersons.cend() ? (*minElement).firstFrame() : -1; } +/** + * @brief Get a list of all people near pos at a frame in the given interval + * + * This function returns a list of all people, which are near the + * position pos at some frame f in the interval + * frame - before <= f <= frame + after + * + * Near is, when the distance is less than half a headsize. When + * multiple points for the same person are possible, the point + * and frame at which the person is nearest to the pos is returned, + * i.e. each persons only occurs once in the resulting list. + * + * @param pos position near the persons to select + * @param frame current frame + * @param selected set of ids of selected persons; empty means everyone is selected + * @param before frames to include before the current frame + * @param after frames to include after the current frame + * @return list of the id of all proximal persons with the frame at which they are nearest to pos + */ +std::vector<PersonFrame> +PersonStorage::getProximalPersons(const QPointF &pos, int frame, QSet<int> selected, int before, int after) const +{ + std::vector<PersonFrame> result; + for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) + { + if(!selected.empty() && !selected.contains(i)) + { + continue; + } + + double minDist = std::numeric_limits<double>::max(); + int minFrame = -1; + for(int f = frame - before; f <= frame + after; ++f) + { + if(!mPersons[i].trackPointExist(f)) + { + continue; + } + auto dist = mPersons[i].trackPointAt(f).distanceToPoint(pos); + if(dist < minDist && dist < (mMainWindow.getHeadSize(nullptr, i, frame) / 2.)) + { + minDist = dist; + minFrame = f; + } + } + if(minFrame == -1) + { + continue; + } + result.push_back({i, minFrame}); + } + + return result; +} + /** * @brief Recalcs the height of all persons (used with stereo) diff --git a/src/petrack.cpp b/src/petrack.cpp index 2c1f7fdaf464c3cf6e71000b216827031a1ff327..23fb6c8095b250f8334546cfc3df028b2bfe7ff1 100644 --- a/src/petrack.cpp +++ b/src/petrack.cpp @@ -171,6 +171,7 @@ Petrack::Petrack() : connect(mView, &GraphicsView::mouseRightDoubleClick, this, &Petrack::deleteTrackPoint); connect(mView, &GraphicsView::mouseMiddleDoubleClick, this, &Petrack::deleteTrackPointAll); connect(mView, &GraphicsView::mouseShiftWheel, this, &Petrack::skipToFrameWheel); + connect(mView, &GraphicsView::mouseAltDoubleClick, this, &Petrack::skipToFrameFromTrajectory); mPlayerWidget = new Player(mAnimation, this); @@ -4194,6 +4195,28 @@ void Petrack::skipToFrameWheel(int delta) mPlayerWidget->skipToFrame(mPlayerWidget->getPos() + delta); } +void Petrack::skipToFrameFromTrajectory(QPointF pos) +{ + auto peds = getPedestrianUserSelection(); + const auto before = mControlWidget->trackShowBefore->value(); + const auto after = mControlWidget->trackShowAfter->value(); + const auto currFrame = mPlayerWidget->getPos(); + + auto res = mPersonStorage.getProximalPersons(pos, currFrame, peds, before, after); + + if(res.size() == 1) + { + mPlayerWidget->skipToFrame(res.front().frame); + } + else if(res.size() > 1) + { + PWarning( + this, + tr("Too many trajectories"), + tr("PeTrack can't determine which point you meant. Try selecting fewer trajectories first.")); + } +} + void Petrack::setPeTrackVersion(const std::string &petrackVersion) { mPetrackVersion = QString::fromStdString(petrackVersion); diff --git a/src/view.cpp b/src/view.cpp index 43cf0af26ea598c5902df239137421e3783cb134..841c10e78c9af67e84d3996b43fe03929b04c42a 100644 --- a/src/view.cpp +++ b/src/view.cpp @@ -87,6 +87,10 @@ void GraphicsView::mouseDoubleClickEvent(QMouseEvent *event) { emit mouseControlDoubleClick(mapToScene(event->pos())); // const QPoint & //const QPointF &pos } + else if(event->modifiers() & Qt::AltModifier) + { + emit mouseAltDoubleClick(mapToScene(event->pos())); + } else { emit mouseDoubleClick();