annotate base/PointSeries.h @ 1612:23a29e5dc0e9 single-point

Start implementing & testing PointSeries
author Chris Cannam
date Wed, 06 Mar 2019 16:24:23 +0000
parents
children 2e14a7876945
rev   line source
Chris@1612 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1612 2
Chris@1612 3 /*
Chris@1612 4 Sonic Visualiser
Chris@1612 5 An audio file viewer and annotation editor.
Chris@1612 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1612 7
Chris@1612 8 This program is free software; you can redistribute it and/or
Chris@1612 9 modify it under the terms of the GNU General Public License as
Chris@1612 10 published by the Free Software Foundation; either version 2 of the
Chris@1612 11 License, or (at your option) any later version. See the file
Chris@1612 12 COPYING included with this distribution for more information.
Chris@1612 13 */
Chris@1612 14
Chris@1612 15 #ifndef SV_POINT_SERIES_H
Chris@1612 16 #define SV_POINT_SERIES_H
Chris@1612 17
Chris@1612 18 #include "Point.h"
Chris@1612 19
Chris@1612 20 #include <set>
Chris@1612 21
Chris@1612 22 class PointSeries
Chris@1612 23 {
Chris@1612 24 public:
Chris@1612 25 PointSeries() : m_count(0) { }
Chris@1612 26
Chris@1612 27 void add(const Point &p) {
Chris@1612 28
Chris@1612 29 m_points.insert(p);
Chris@1612 30 ++m_count;
Chris@1612 31
Chris@1612 32 if (p.haveDuration()) {
Chris@1612 33 sv_frame_t frame = p.getFrame();
Chris@1612 34 sv_frame_t endFrame = p.getFrame() + p.getDuration();
Chris@1612 35
Chris@1612 36 std::set<Point> active;
Chris@1612 37 auto itr = m_seams.lower_bound(frame);
Chris@1612 38 if (itr == m_seams.end() || itr->first > frame) {
Chris@1612 39 if (itr != m_seams.begin()) {
Chris@1612 40 --itr;
Chris@1612 41 }
Chris@1612 42 }
Chris@1612 43 if (itr != m_seams.end()) {
Chris@1612 44 active = itr->second;
Chris@1612 45 }
Chris@1612 46 active.insert(p);
Chris@1612 47 m_seams[frame] = active;
Chris@1612 48
Chris@1612 49 for (itr = m_seams.find(frame); itr->first < endFrame; ++itr) {
Chris@1612 50 active = itr->second;
Chris@1612 51 itr->second.insert(p);
Chris@1612 52 }
Chris@1612 53
Chris@1612 54 m_seams[endFrame] = active;
Chris@1612 55 }
Chris@1612 56 }
Chris@1612 57
Chris@1612 58 void remove(const Point &p) {
Chris@1612 59
Chris@1612 60 // erase first itr that matches p; if there is more than one
Chris@1612 61 // p, erase(p) would remove all of them, but we only want to
Chris@1612 62 // remove (any) one
Chris@1612 63 auto pitr = m_points.find(p);
Chris@1612 64 if (pitr == m_points.end()) {
Chris@1612 65 return; // we don't know this point
Chris@1612 66 } else {
Chris@1612 67 m_points.erase(pitr);
Chris@1612 68 --m_count;
Chris@1612 69 }
Chris@1612 70
Chris@1612 71 if (p.haveDuration()) {
Chris@1612 72 sv_frame_t frame = p.getFrame();
Chris@1612 73 sv_frame_t endFrame = p.getFrame() + p.getDuration();
Chris@1612 74
Chris@1612 75 auto itr = m_seams.find(frame);
Chris@1612 76 if (itr == m_seams.end()) {
Chris@1612 77 SVCERR << "WARNING: PointSeries::remove: frame " << frame
Chris@1612 78 << " for point not found in seam map: point is "
Chris@1612 79 << p.toXmlString() << endl;
Chris@1612 80 return;
Chris@1612 81 }
Chris@1612 82
Chris@1612 83 while (itr != m_seams.end() && itr->first <= endFrame) {
Chris@1612 84 itr->second.erase(p);
Chris@1612 85 ++itr;
Chris@1612 86 }
Chris@1612 87
Chris@1612 88 // Shall we "garbage-collect" here? We could be leaving
Chris@1612 89 // lots of empty point-sets, or consecutive identical
Chris@1612 90 // ones, which are a pure irrelevance that take space and
Chris@1612 91 // slow us down. But a lot depends on whether callers ever
Chris@1612 92 // really delete anything much.
Chris@1612 93 }
Chris@1612 94 }
Chris@1612 95
Chris@1612 96 bool contains(const Point &p) {
Chris@1612 97 return m_points.find(p) != m_points.end();
Chris@1612 98 }
Chris@1612 99
Chris@1612 100 int count() const {
Chris@1612 101 return m_count;
Chris@1612 102 }
Chris@1612 103
Chris@1612 104 bool isEmpty() const {
Chris@1612 105 return m_count == 0;
Chris@1612 106 }
Chris@1612 107
Chris@1612 108 void clear() {
Chris@1612 109 m_points.clear();
Chris@1612 110 m_seams.clear();
Chris@1612 111 m_count = 0;
Chris@1612 112 }
Chris@1612 113
Chris@1612 114 /**
Chris@1612 115 * Retrieve all points that span the given frame. A point without
Chris@1612 116 * duration spans a frame if its own frame is equal to it. A point
Chris@1612 117 * with duration spans a frame if its start frame is less than or
Chris@1612 118 * equal to it and its end frame (start + duration) is greater
Chris@1612 119 * than it.
Chris@1612 120 */
Chris@1612 121 PointVector getPointsSpanning(sv_frame_t frame) {
Chris@1612 122 return {};
Chris@1612 123 }
Chris@1612 124
Chris@1612 125 private:
Chris@1612 126 int m_count;
Chris@1612 127 std::multiset<Point> m_points;
Chris@1612 128 std::map<sv_frame_t, std::set<Point>> m_seams;
Chris@1612 129 };
Chris@1612 130
Chris@1612 131 #endif