annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 319:3ff8f571da09

* Hoist alignment model set/query up to Model, so any models can be aligned * Add Model::aboutToDelete and aboutToBeDeleted for management of models that are contained by or referred to by other models instead of only the document
author Chris Cannam
date Wed, 24 Oct 2007 15:21:38 +0000
parents 7a4bd2c8585c
children 1afaf98dbf11
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #include "EditableDenseThreeDimensionalModel.h"
Chris@152 17
Chris@152 18 #include <QTextStream>
Chris@152 19
Chris@181 20 #include <iostream>
Chris@181 21
Chris@256 22 #include <cmath>
Chris@256 23
Chris@152 24 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 25 size_t resolution,
Chris@152 26 size_t yBinCount,
Chris@152 27 bool notifyOnAdd) :
Chris@152 28 m_sampleRate(sampleRate),
Chris@152 29 m_resolution(resolution),
Chris@152 30 m_yBinCount(yBinCount),
Chris@152 31 m_minimum(0.0),
Chris@152 32 m_maximum(0.0),
Chris@256 33 m_haveExtents(false),
Chris@152 34 m_notifyOnAdd(notifyOnAdd),
Chris@152 35 m_sinceLastNotifyMin(-1),
Chris@152 36 m_sinceLastNotifyMax(-1),
Chris@152 37 m_completion(100)
Chris@152 38 {
Chris@152 39 }
Chris@152 40
Chris@152 41 bool
Chris@152 42 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 43 {
Chris@152 44 return true;
Chris@152 45 }
Chris@152 46
Chris@152 47 size_t
Chris@152 48 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 49 {
Chris@152 50 return m_sampleRate;
Chris@152 51 }
Chris@152 52
Chris@152 53 size_t
Chris@152 54 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 55 {
Chris@152 56 return 0;
Chris@152 57 }
Chris@152 58
Chris@152 59 size_t
Chris@152 60 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 61 {
Chris@152 62 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 63 }
Chris@152 64
Chris@152 65 Model *
Chris@152 66 EditableDenseThreeDimensionalModel::clone() const
Chris@152 67 {
Chris@152 68 EditableDenseThreeDimensionalModel *model =
Chris@152 69 new EditableDenseThreeDimensionalModel
Chris@152 70 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 71
Chris@152 72 model->m_minimum = m_minimum;
Chris@152 73 model->m_maximum = m_maximum;
Chris@256 74 model->m_haveExtents = m_haveExtents;
Chris@152 75
Chris@152 76 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 77 model->setColumn(i, m_data[i]);
Chris@152 78 }
Chris@152 79
Chris@152 80 return model;
Chris@152 81 }
Chris@152 82
Chris@152 83 size_t
Chris@152 84 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 85 {
Chris@152 86 return m_resolution;
Chris@152 87 }
Chris@152 88
Chris@152 89 void
Chris@152 90 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 91 {
Chris@152 92 m_resolution = sz;
Chris@152 93 }
Chris@152 94
Chris@152 95 size_t
Chris@182 96 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 97 {
Chris@182 98 return m_data.size();
Chris@182 99 }
Chris@182 100
Chris@182 101 size_t
Chris@182 102 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 103 {
Chris@152 104 return m_yBinCount;
Chris@152 105 }
Chris@152 106
Chris@152 107 void
Chris@182 108 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 109 {
Chris@152 110 m_yBinCount = sz;
Chris@152 111 }
Chris@152 112
Chris@152 113 float
Chris@152 114 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 115 {
Chris@152 116 return m_minimum;
Chris@152 117 }
Chris@152 118
Chris@152 119 void
Chris@152 120 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 121 {
Chris@152 122 m_minimum = level;
Chris@152 123 }
Chris@152 124
Chris@152 125 float
Chris@152 126 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 127 {
Chris@152 128 return m_maximum;
Chris@152 129 }
Chris@152 130
Chris@152 131 void
Chris@152 132 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 133 {
Chris@152 134 m_maximum = level;
Chris@152 135 }
Chris@152 136
Chris@152 137 void
Chris@182 138 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 139 Column &result) const
Chris@152 140 {
Chris@152 141 QMutexLocker locker(&m_mutex);
Chris@152 142
Chris@182 143 if (index < m_data.size()) {
Chris@152 144 result = m_data[index];
Chris@152 145 } else {
Chris@152 146 result.clear();
Chris@152 147 }
Chris@152 148
Chris@152 149 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 150 }
Chris@152 151
Chris@152 152 float
Chris@182 153 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 154 {
Chris@152 155 QMutexLocker locker(&m_mutex);
Chris@152 156
Chris@182 157 if (index < m_data.size()) {
Chris@182 158 const Column &s = m_data[index];
Chris@256 159 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 160 // << std::endl;
Chris@152 161 if (n < s.size()) return s[n];
Chris@152 162 }
Chris@152 163
Chris@152 164 return m_minimum;
Chris@152 165 }
Chris@152 166
Chris@152 167 void
Chris@182 168 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 169 const Column &values)
Chris@152 170 {
Chris@152 171 QMutexLocker locker(&m_mutex);
Chris@152 172
Chris@182 173 while (index >= m_data.size()) {
Chris@182 174 m_data.push_back(Column());
Chris@152 175 }
Chris@152 176
Chris@152 177 bool allChange = false;
Chris@152 178
Chris@152 179 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 180 float value = values[i];
Chris@257 181 if (std::isnan(value) || std::isinf(value)) {
Chris@256 182 continue;
Chris@256 183 }
Chris@256 184 if (!m_haveExtents || value < m_minimum) {
Chris@256 185 m_minimum = value;
Chris@152 186 allChange = true;
Chris@152 187 }
Chris@256 188 if (!m_haveExtents || value > m_maximum) {
Chris@256 189 m_maximum = value;
Chris@152 190 allChange = true;
Chris@152 191 }
Chris@256 192 m_haveExtents = true;
Chris@152 193 }
Chris@152 194
Chris@152 195 m_data[index] = values;
Chris@152 196
Chris@182 197 long windowStart = index;
Chris@182 198 windowStart *= m_resolution;
Chris@182 199
Chris@152 200 if (m_notifyOnAdd) {
Chris@152 201 if (allChange) {
Chris@152 202 emit modelChanged();
Chris@152 203 } else {
Chris@152 204 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 205 }
Chris@152 206 } else {
Chris@152 207 if (allChange) {
Chris@152 208 m_sinceLastNotifyMin = -1;
Chris@152 209 m_sinceLastNotifyMax = -1;
Chris@152 210 emit modelChanged();
Chris@152 211 } else {
Chris@152 212 if (m_sinceLastNotifyMin == -1 ||
Chris@152 213 windowStart < m_sinceLastNotifyMin) {
Chris@152 214 m_sinceLastNotifyMin = windowStart;
Chris@152 215 }
Chris@152 216 if (m_sinceLastNotifyMax == -1 ||
Chris@152 217 windowStart > m_sinceLastNotifyMax) {
Chris@152 218 m_sinceLastNotifyMax = windowStart;
Chris@152 219 }
Chris@152 220 }
Chris@152 221 }
Chris@152 222 }
Chris@152 223
Chris@152 224 QString
Chris@152 225 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 226 {
Chris@152 227 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 228 else return "";
Chris@152 229 }
Chris@152 230
Chris@152 231 void
Chris@152 232 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 233 {
Chris@152 234 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 235 m_binNames[n] = name;
Chris@152 236 emit modelChanged();
Chris@152 237 }
Chris@152 238
Chris@152 239 void
Chris@152 240 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 241 {
Chris@152 242 m_binNames = names;
Chris@152 243 emit modelChanged();
Chris@152 244 }
Chris@152 245
Chris@152 246 void
Chris@152 247 EditableDenseThreeDimensionalModel::setCompletion(int completion)
Chris@152 248 {
Chris@152 249 if (m_completion != completion) {
Chris@152 250 m_completion = completion;
Chris@152 251
Chris@152 252 if (completion == 100) {
Chris@152 253
Chris@152 254 m_notifyOnAdd = true; // henceforth
Chris@152 255 emit modelChanged();
Chris@152 256
Chris@152 257 } else if (!m_notifyOnAdd) {
Chris@152 258
Chris@152 259 if (m_sinceLastNotifyMin >= 0 &&
Chris@152 260 m_sinceLastNotifyMax >= 0) {
Chris@152 261 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 262 m_sinceLastNotifyMax + m_resolution);
Chris@152 263 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 264 } else {
Chris@152 265 emit completionChanged();
Chris@152 266 }
Chris@152 267 } else {
Chris@152 268 emit completionChanged();
Chris@152 269 }
Chris@152 270 }
Chris@152 271 }
Chris@152 272
Chris@318 273 QString
Chris@318 274 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 275 {
Chris@318 276 QString s;
Chris@318 277 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 278 QStringList list;
Chris@318 279 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@318 280 list << QString("%1").arg(m_data[i][j]);
Chris@318 281 }
Chris@318 282 s += list.join(delimiter) + "\n";
Chris@318 283 }
Chris@318 284 return s;
Chris@318 285 }
Chris@318 286
Chris@152 287 void
Chris@152 288 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 289 QString indent,
Chris@314 290 QString extraAttributes) const
Chris@152 291 {
Chris@152 292 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 293
Chris@318 294 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 295
Chris@314 296 Model::toXml
Chris@314 297 (out, indent,
Chris@314 298 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 299 .arg(m_resolution)
Chris@152 300 .arg(m_yBinCount)
Chris@152 301 .arg(m_minimum)
Chris@152 302 .arg(m_maximum)
Chris@152 303 .arg(getObjectExportId(&m_data))
Chris@152 304 .arg(extraAttributes));
Chris@152 305
Chris@152 306 out << indent;
Chris@152 307 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 308 .arg(getObjectExportId(&m_data));
Chris@152 309
Chris@152 310 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 311 if (m_binNames[i] != "") {
Chris@152 312 out << indent + " ";
Chris@152 313 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 314 .arg(i).arg(m_binNames[i]);
Chris@152 315 }
Chris@152 316 }
Chris@152 317
Chris@152 318 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 319 out << indent + " ";
Chris@152 320 out << QString("<row n=\"%1\">").arg(i);
Chris@152 321 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 322 if (j > 0) out << " ";
Chris@152 323 out << m_data[i][j];
Chris@152 324 }
Chris@152 325 out << QString("</row>\n");
Chris@318 326 out.flush();
Chris@152 327 }
Chris@152 328
Chris@152 329 out << indent + "</dataset>\n";
Chris@152 330 }
Chris@152 331
Chris@152 332