mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Voronoi diagram on chart
.. The diagram now displays on a chart, but there are a few issues. Will work through them as more testing done.
This commit is contained in:
@@ -8,9 +8,21 @@
|
||||
Voronoi::Voronoi()
|
||||
{
|
||||
// old controls essentially in main.c
|
||||
triangulate = 0;
|
||||
plot = 0;
|
||||
debug = 0;
|
||||
//
|
||||
// the original source was written in such a way that you could
|
||||
// update the "plotting functions" (line, circle etc) with your
|
||||
// own code to implement a plot.
|
||||
//
|
||||
// we have adapted the "line" function to record lines in the
|
||||
// output vector, so we can draw them on a plot
|
||||
//
|
||||
// testing has suggested that these kinds of diagrams only work
|
||||
// well when there are lots of cells ie, running kmeans with
|
||||
// 30 or even 100 clusters.
|
||||
//
|
||||
triangulate = 0; // tesselate (we don't support this)
|
||||
plot = 1; // call "plotting functions" - we use this
|
||||
debug = 0; // set to 1 to get lots of debug
|
||||
|
||||
// malloc lists are maintained and zapped in constructors
|
||||
freeinit(&sfl, sizeof(Site));
|
||||
@@ -98,6 +110,7 @@ Voronoi::run(QRectF /* boundingRect */)
|
||||
|
||||
// was done in main.c previously
|
||||
geominit();
|
||||
plotinit();
|
||||
|
||||
// now into the original sources
|
||||
Site *newsite, * bot, * top, * temp, * p, * v ;
|
||||
@@ -755,11 +768,13 @@ Voronoi::myalloc(unsigned n)
|
||||
void
|
||||
Voronoi::openpl(void)
|
||||
{
|
||||
output.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Voronoi::line(float ax, float ay, float bx, float by)
|
||||
{
|
||||
output << QLineF(QPointF(ax,ay), QPointF(bx,by));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QList>
|
||||
#include <QRectF>
|
||||
#include <QPointF>
|
||||
#include <QLineF>
|
||||
|
||||
#ifndef __VDEFS_H
|
||||
#define __VDEFS_H 1
|
||||
@@ -76,6 +77,9 @@ class Voronoi {
|
||||
void addSite(QPointF point);
|
||||
void run(QRectF boundingRect);
|
||||
|
||||
// the output is a vector of lines to draw
|
||||
QList<QLineF> &lines() { return output; }
|
||||
|
||||
private:
|
||||
|
||||
// original global variables
|
||||
@@ -99,6 +103,7 @@ class Voronoi {
|
||||
// refactoring to Qt containers
|
||||
QList<void *> malloclist; // keep tabs on all the malloc'ed memory
|
||||
QList<Site*> sites;
|
||||
QList<QLineF> output;
|
||||
|
||||
/*** implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,
|
||||
: deltax, deltay (can all be estimates).
|
||||
|
||||
@@ -439,7 +439,7 @@ GenericChart::finaliseChart()
|
||||
}
|
||||
|
||||
// did we have a voronoi diagram?
|
||||
if (p.voronoix.count() >= 2) newPlots[i].plot->addVoronoi(p.voronoix, p.voronoiy);
|
||||
if (p.voronoix.count() >= 2) newPlots[i].plot->addVoronoi(p.name, p.voronoix, p.voronoiy);
|
||||
}
|
||||
|
||||
// set axis
|
||||
|
||||
56
src/Charts/GenericLines.cpp
Normal file
56
src/Charts/GenericLines.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Mark Liversedge (liversedge@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <QChart>
|
||||
#include "GenericLines.h"
|
||||
|
||||
GenericLines::GenericLines(GenericPlot *plot) : QGraphicsItem(NULL), plot(plot), curve(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
GenericLines::~GenericLines() {}
|
||||
|
||||
void
|
||||
GenericLines::paint(QPainter*painter, const QStyleOptionGraphicsItem *, QWidget*)
|
||||
{
|
||||
if (curve == NULL) return;
|
||||
|
||||
QPen pen(Qt::lightGray);
|
||||
painter->setPen(pen);
|
||||
|
||||
painter->setClipRect(plot->qchart->plotArea());
|
||||
|
||||
foreach(QLineF line, lines) {
|
||||
QPointF from = plot->qchart->mapToPosition(line.p1(), curve);
|
||||
QPointF to = plot->qchart->mapToPosition(line.p2(), curve);
|
||||
|
||||
painter->drawLine(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericLines::prepare()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
}
|
||||
|
||||
QRectF GenericLines::boundingRect() const
|
||||
{
|
||||
// we cover the entire plot area generally
|
||||
return plot->qchart->plotArea();
|
||||
}
|
||||
56
src/Charts/GenericLines.h
Normal file
56
src/Charts/GenericLines.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Mark Liversedge (liversedge@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _GC_GenericLines_h
|
||||
#define _GC_GenericLines_h 1
|
||||
|
||||
#include <QPointF>
|
||||
#include <QtCharts>
|
||||
#include <QGraphicsItem>
|
||||
|
||||
#include "GenericPlot.h"
|
||||
|
||||
// for painting lines on a chart
|
||||
class GenericLines : public QGraphicsItem
|
||||
{
|
||||
|
||||
Q_INTERFACES(QGraphicsItem)
|
||||
|
||||
public:
|
||||
|
||||
GenericLines(GenericPlot *);
|
||||
~GenericLines();
|
||||
|
||||
void setCurve(QAbstractSeries *curve) { this->curve=curve; }
|
||||
void setLines(QList<QLineF> lines) { this->lines = lines; update(); }
|
||||
|
||||
void paint(QPainter*, const QStyleOptionGraphicsItem *, QWidget*);
|
||||
QRectF boundingRect() const;
|
||||
|
||||
void prepare();
|
||||
private:
|
||||
|
||||
// lines to draw
|
||||
QList<QLineF> lines;
|
||||
GenericPlot *plot;
|
||||
|
||||
QAbstractSeries *curve;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,9 @@
|
||||
#include "ChartSpace.h"
|
||||
#include "UserChartOverviewItem.h"
|
||||
|
||||
#include "Voronoi.h"
|
||||
#include "GenericLines.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
// used to format dates/times on axes
|
||||
@@ -47,6 +50,7 @@ GenericPlot::GenericPlot(QWidget *parent, Context *context, QGraphicsItem *item)
|
||||
barseries=NULL;
|
||||
stackbarseries=NULL;
|
||||
percentbarseries=NULL;
|
||||
voronoidiagram=NULL;
|
||||
bottom=left=true;
|
||||
|
||||
mainLayout = new QVBoxLayout(this);
|
||||
@@ -316,12 +320,11 @@ GenericPlot::addAnnotation(AnnotationType, QString string, QColor color)
|
||||
}
|
||||
|
||||
void
|
||||
GenericPlot::addVoronoi(QVector<double>x, QVector<double>y)
|
||||
GenericPlot::addVoronoi(QString name, QVector<double>x, QVector<double>y)
|
||||
{
|
||||
vname = name;
|
||||
vx = x;
|
||||
vy = y;
|
||||
|
||||
fprintf(stderr, "generic plot: add voronoi diagram\n"); fflush(stderr);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -456,6 +459,8 @@ GenericPlot::plotAreaChanged()
|
||||
bool
|
||||
GenericPlot::initialiseChart(QString title, int type, bool animate, int legpos, double scale)
|
||||
{
|
||||
clearVoronoi();
|
||||
|
||||
// if we changed the type, all series must go
|
||||
if (charttype != type) {
|
||||
qchart->removeAllSeries();
|
||||
@@ -466,6 +471,7 @@ GenericPlot::initialiseChart(QString title, int type, bool animate, int legpos,
|
||||
percentbarseries=NULL;
|
||||
}
|
||||
|
||||
|
||||
foreach(QLabel *label, labels) delete label;
|
||||
labels.clear();
|
||||
|
||||
@@ -919,6 +925,9 @@ GenericPlot::finaliseChart()
|
||||
{
|
||||
if (!qchart) return;
|
||||
|
||||
// remove voronoix if present
|
||||
clearVoronoi();
|
||||
|
||||
// clear ALL axes
|
||||
foreach(QAbstractAxis *axis, qchart->axes(Qt::Vertical)) {
|
||||
qchart->removeAxis(axis);
|
||||
@@ -1246,6 +1255,9 @@ GenericPlot::finaliseChart()
|
||||
// add labels after legend items
|
||||
foreach(QLabel *label, labels) legend->addLabel(label);
|
||||
|
||||
// add voronoi if need to
|
||||
plotVoronoi();
|
||||
|
||||
plotAreaChanged(); // make sure get updated before paint
|
||||
}
|
||||
|
||||
@@ -1357,3 +1369,46 @@ GenericPlot::seriesColor(QAbstractSeries* series)
|
||||
default: return GColor(CPLOTMARKER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GenericPlot::plotVoronoi()
|
||||
{
|
||||
// if there is one there already, lets remove it
|
||||
clearVoronoi();
|
||||
|
||||
if (vx.count() < 2) return;
|
||||
|
||||
Voronoi v;
|
||||
for(int i=0; i<vx.count(); i++) v.addSite(QPointF(vx[i],vy[i]));
|
||||
v.run(QRectF());
|
||||
|
||||
#if 0
|
||||
// how many lines?
|
||||
fprintf(stderr, "voronoi diagram curve '%s' has %d lines\n", vname.toStdString().c_str(),v.lines().count()); fflush(stderr);
|
||||
|
||||
foreach(QLineF line, v.lines()) {
|
||||
fprintf(stderr, "from %f,%f to %f,%f\n", line.p1().x(), line.p1().y(), line.p2().x(), line.p2().y());
|
||||
}
|
||||
#endif
|
||||
|
||||
// create a new diagram
|
||||
voronoidiagram = new GenericLines(this);
|
||||
voronoidiagram->setCurve(curves.value(vname,NULL));
|
||||
voronoidiagram->setLines(v.lines());
|
||||
|
||||
chartview->scene()->addItem(voronoidiagram);
|
||||
voronoidiagram->update();
|
||||
}
|
||||
|
||||
void
|
||||
GenericPlot::clearVoronoi()
|
||||
{
|
||||
if (voronoidiagram) {
|
||||
voronoidiagram->setCurve(NULL);
|
||||
voronoidiagram->setLines(QList<QLineF>());
|
||||
voronoidiagram->prepare();
|
||||
chartview->scene()->removeItem(voronoidiagram);
|
||||
//delete voronoidiagram; // CRASH!
|
||||
voronoidiagram = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ class GenericPlot;
|
||||
class GenericLegend;
|
||||
class GenericSelectTool;
|
||||
class GenericAxisInfo;
|
||||
class GenericLines; // draw lines
|
||||
|
||||
// the chart
|
||||
class ChartSpace;
|
||||
@@ -72,6 +73,7 @@ class GenericPlot : public QWidget {
|
||||
static QString gl_timeformat;
|
||||
|
||||
friend class GenericSelectTool;
|
||||
friend class GenericLines;
|
||||
friend class GenericLegend;
|
||||
|
||||
GenericPlot(QWidget *parent, Context *context, QGraphicsItem *item);
|
||||
@@ -107,7 +109,7 @@ class GenericPlot : public QWidget {
|
||||
// adding annotations
|
||||
void addAnnotation(AnnotationType, QAbstractSeries*, double yvalue); // LINE
|
||||
void addAnnotation(AnnotationType, QString, QColor=QColor(Qt::gray)); // LABEL
|
||||
void addVoronoi(QVector<double>, QVector<double>); // VORONOI
|
||||
void addVoronoi(QString name, QVector<double>, QVector<double>); // VORONOI
|
||||
|
||||
// configure axis, after curves added
|
||||
bool configureAxis(QString name, bool visible, int align, double min, double max,
|
||||
@@ -119,6 +121,10 @@ class GenericPlot : public QWidget {
|
||||
// do we want to see this series?
|
||||
void setSeriesVisible(QString name, bool visible);
|
||||
|
||||
// adding and clearing a voronoi diagram from the chart
|
||||
void clearVoronoi();
|
||||
void plotVoronoi();
|
||||
|
||||
// watching scene events and managing interaction
|
||||
void seriesClicked(QAbstractSeries*series, GPointF point);
|
||||
bool eventHandler(int eventsource, void *obj, QEvent *event);
|
||||
@@ -126,6 +132,9 @@ class GenericPlot : public QWidget {
|
||||
void plotAreaChanged();
|
||||
void pieHover(QPieSlice *slice, bool state);
|
||||
|
||||
// access structures
|
||||
QAbstractSeries *curve(QString name) { return curves.value(name, NULL); }
|
||||
|
||||
protected:
|
||||
|
||||
// legend and selector need acces to these
|
||||
@@ -153,7 +162,10 @@ class GenericPlot : public QWidget {
|
||||
|
||||
// annotations
|
||||
QList<QLabel *> labels;
|
||||
|
||||
QString vname;
|
||||
QVector<double> vx, vy; //voronoi digram
|
||||
GenericLines *voronoidiagram; // draws the lines on the chart
|
||||
|
||||
private:
|
||||
Context *context;
|
||||
|
||||
@@ -180,6 +180,10 @@ UserChart::setRide(const RideItem *item)
|
||||
// clear old annotations for this series
|
||||
annotations.clear();
|
||||
|
||||
// any old voronoi diagram centers
|
||||
series.voronoix.clear();
|
||||
series.voronoiy.clear();
|
||||
|
||||
// re-create program (may be edited)
|
||||
if (series.user1 != NULL) delete static_cast<UserChartData*>(series.user1);
|
||||
series.user1 = new UserChartData(context, this, series.string1, rangemode);
|
||||
@@ -534,7 +538,7 @@ UserChart::annotateVoronoi(QVector<double>x, QVector<double>y)
|
||||
UserChartData *ucd = static_cast<UserChartData*>(seriesinfo[i].user1);
|
||||
if (ucd->program == from) {
|
||||
seriesinfo[i].voronoix = x;
|
||||
seriesinfo[i].voronoiy = x;
|
||||
seriesinfo[i].voronoiy = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,9 +655,9 @@ greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
# generic chart
|
||||
DEFINES += GC_HAVE_GENERIC
|
||||
HEADERS += Charts/UserChartWindow.h Charts/UserChartOverviewItem.h Charts/UserChart.h Charts/UserChartData.h \
|
||||
Charts/GenericChart.h Charts/GenericPlot.h Charts/GenericSelectTool.h Charts/GenericLegend.h
|
||||
Charts/GenericChart.h Charts/GenericPlot.h Charts/GenericSelectTool.h Charts/GenericLegend.h Charts/GenericLines.h
|
||||
SOURCES += Charts/UserChartWindow.cpp Charts/UserChartOverviewItem.cpp Charts/UserChart.cpp Charts/UserChartData.cpp \
|
||||
Charts/GenericChart.cpp Charts/GenericPlot.cpp Charts/GenericSelectTool.cpp Charts/GenericLegend.cpp
|
||||
Charts/GenericChart.cpp Charts/GenericPlot.cpp Charts/GenericSelectTool.cpp Charts/GenericLegend.cpp Charts/GenericLines.cpp
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user