JKQTPbarVerticalGraph and JKQTPbarHoricontalGraph now draw bars with the proper width, even if data is not sorted

This commit is contained in:
kriegerj 2015-08-21 13:49:11 +02:00
parent 8dc6b57f9c
commit 34631fb66f
4 changed files with 182 additions and 57 deletions

View File

@ -57,14 +57,10 @@ QVector<double> JKQTPcolumn::copyData()
QVector<double> d;
copyData(d);
return d;
};
}
/** \brief reads the \a n'th value from the column
*
* This method accesses the datastore and returns the double value stored in the \a n'th row of the according
* column.
*/
double JKQTPcolumn::getValue(unsigned long long n) const {
double JKQTPcolumn::getValue(unsigned long long n) const
{
if (!datastore) return 0;
if (!datastore->getItem(datastoreItem)) return 0;
return datastore->getItem(datastoreItem)->get(datastoreOffset, n);
@ -75,19 +71,18 @@ double *JKQTPcolumn::getPointer(unsigned long long n) const
if (!datastore) return 0;
if (!datastore->getItem(datastoreItem)) return 0;
return datastore->getItem(datastoreItem)->getPointer(datastoreOffset, n);
};
}
/** \brief sets the \a n'th value from the column
*
* This method accesses the datastore and returns the double value stored in the \a n'th row of the according
* column.
*/
void JKQTPcolumn::setValue(unsigned long long n, double val) {
void JKQTPcolumn::setValue(unsigned long long n, double val)
{
if (!datastore) return ;
if (!datastore->getItem(datastoreItem)) return;
datastore->getItem(datastoreItem)->set(datastoreOffset, n, val);
};
void JKQTPcolumn::copy(double* data, unsigned long long N, unsigned long long offset) {
if (!datastore) return ;
JKQTPdatastoreItem* it=datastore->getItem(datastoreItem);
@ -308,6 +303,11 @@ size_t JKQTPdatastore::ensureColumnNum(QString name) {
return addColumn(0, name);
}
JKQTPcolumn JKQTPdatastore::getColumn(size_t i) const
{
return columns.value(i);
}
size_t JKQTPdatastore::addCopiedItem(JKQTPdatastoreItemFormat dataformat, double* data, size_t columnsnum, unsigned long long rows) {
JKQTPdatastoreItem* it=NULL;
if ((dataformat==JKQTPsingleColumn)||(columnsnum==1)) {
@ -1042,19 +1042,77 @@ size_t JKQTPdatastore::addLinearColumn(unsigned long long rows, double start, do
}
/** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
double JKQTPdatastore::get(size_t column, unsigned long long row) {
double JKQTPdatastore::get(size_t column, unsigned long long row) const {
return columns[column].getValue(row);
};
}
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
void JKQTPdatastore::set(size_t column, unsigned long long row, double value) {
long long JKQTPdatastore::getNextLowerIndex(size_t column, unsigned long long row, long long start, long long end) const
{
const JKQTPcolumn& col=columns[column];
if (start<0 && end>=0) return getNextLowerIndex(column, row, 0, end);
else if (start>=0 && end<0) return getNextLowerIndex(column, row, start, col.getRows()-1);
else if (start<0 && end<0) return getNextLowerIndex(column, row, 0, col.getRows()-1);
else {
double d=0;
const double v=col.getValue(row);
long long res=-1;
for ( long long i=start; i<=end; i++) {
if (i!=(long long)row) {
const double v1=col.getValue(i);
const double dd=v1-v;
if ((dd<0) && ((fabs(dd)<d)||(d==0.0))) {
res=i;
d=fabs(dd);
//std::cout<<" getNextLowerIndex("<<column<<", "<<row<<", "<<start<<", "<<end<<"): i="<<i<<": OK res="<<res<<" d="<<d<<"\n";
} /*else {
std::cout<<" getNextLowerIndex("<<column<<", "<<row<<", "<<start<<", "<<end<<"): i="<<i<<": FAIL res="<<res<<" dd="<<dd<<" v1="<<v1<<" v="<<v<<"\n";
}*/
}
}
return res;
}
}
long long JKQTPdatastore::getNextLowerIndex(size_t column, unsigned long long row) const
{
return getNextLowerIndex(column, row, 0, columns[column].getRows()-1);
}
long long JKQTPdatastore::getNextHigherIndex(size_t column, unsigned long long row, long long start, long long end) const
{
const JKQTPcolumn& col=columns[column];
if (start<0 && end>=0) return getNextHigherIndex(column, row, 0, end);
else if (start>=0 && end<0) return getNextHigherIndex(column, row, start, col.getRows()-1);
else if (start<0 && end<0) return getNextHigherIndex(column, row, 0, col.getRows()-1);
else {
double d=0;
const double v=col.getValue(row);
long long res=-1;
for ( long long i=start; i<=end; i++) {
if (i!=(long long)row) {
const double v1=col.getValue(i);
const double dd=v1-v;
if ((dd>0) && ((fabs(dd)<d)||(d==0.0))) {
res=i;
d=fabs(dd);
}
}
}
return res;
}
}
long long JKQTPdatastore::getNextHigherIndex(size_t column, unsigned long long row) const
{
return getNextHigherIndex(column, row, 0, columns[column].getRows()-1);
}
void JKQTPdatastore::set(size_t column, unsigned long long row, double value)
{
columns[column].setValue(row, value);
};
}
JKQTPcolumn JKQTPdatastore::getColumn(size_t i) {
//std::cout<<"datastore->getColumn("<<i<<")\n";
return columns.value(i);
};
unsigned long long JKQTPdatastore::getMaxRows() {
unsigned long long res=0;

View File

@ -204,7 +204,15 @@ class LIB_EXPORT JKQTPdatastore{
/** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
double get(size_t column, unsigned long long row);
double get(size_t column, unsigned long long row) const;
/** \brief gets the of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/
long long getNextLowerIndex(size_t column, unsigned long long row, long long start, long long end) const;
/** \brief gets the of the datapoint with the nearest, but lower value in the column */
long long getNextLowerIndex(size_t column, unsigned long long row) const;
/** \brief gets the index of the datapoint with the nearest, but higher value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column) */
long long getNextHigherIndex(size_t column, unsigned long long row, long long start, long long end) const;
/** \brief gets the index of the datapoint with the nearest, but higher value in the column */
long long getNextHigherIndex(size_t column, unsigned long long row) const;
/** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
void set(size_t column, unsigned long long row, double value);
@ -772,7 +780,7 @@ class LIB_EXPORT JKQTPdatastore{
size_t ensureColumnNum(QString name);
/** \brief returns the JKQTPcolumn object for the \a i -th column in the store */
JKQTPcolumn getColumn(size_t i);
JKQTPcolumn getColumn(size_t i) const;
/** \brief returns the maximum number of rows in all columns */
unsigned long long getMaxRows();
@ -918,14 +926,14 @@ class LIB_EXPORT JKQTPcolumn {
double getValue(unsigned long long n) const;
/** \brief gets a pointer to the n-th value in the column
*/
double* getPointer(unsigned long long n=0) const;
double* getPointer(unsigned long long n=0) const ;
/** \brief sets the \a n'th value from the column
*
* This method accesses the datastore and returns the double value stored in the \a n'th row of the according
* column.
*/
void setValue(unsigned long long n, double val);
void setValue(unsigned long long n, double val) ;
/** \brief returns a pointer to the datastore item representing this column */
inline JKQTPdatastoreItem* getDatastoreItem() const { return datastore->getItem(datastoreItem); }

View File

@ -23,6 +23,7 @@
#include "jkqtpbaseplotter.h"
#include <stdlib.h>
#include <QDebug>
#include <iostream>
#include "jkqtptools.h"
#include "jkqtpimageelements.h"
#include "jkqtpbaseelements.h"
@ -4311,18 +4312,32 @@ void JKQTPbarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
for (int iii=imin; iii<imax; iii++) {
int i=qBound(imin, getDataIndex(iii), imax);
double xv=datastore->get(xColumn,i);
long long sr=datastore->getNextLowerIndex(xColumn, i, datarange_start, datarange_end);
long long lr=datastore->getNextHigherIndex(xColumn, i, datarange_start, datarange_end);
double yv=datastore->get(yColumn,i);
if (imin==imax) { // only one x-value
// if (imin==imax) { // only one x-value
// deltam=0.5;
// deltap=0.5;
// } else if (i==imax-1) { // the right-most x-value
// deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
// } else if (i==imin) { // the left-most x-value
// deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
// } else {
// deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
// deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
// }
if (sr<0 && lr<0) { // only one x-value
deltam=0.5;
deltap=0.5;
} else if (i==imax-1) { // the right-most x-value
deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
} else if (i==imin) { // the left-most x-value
deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
} else if (lr<0) { // the right-most x-value
deltap=deltam=fabs(xv-datastore->get(xColumn,sr))/2.0;
} else if (sr<0) { // the left-most x-value
deltam=deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0;
} else {
deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
deltam=fabs(xv-datastore->get(xColumn,sr))/2.0;
deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0;
}
//std::cout<<iii<<", \t"<<i<<", \t"<<sr<<", \t"<<lr<<", \t"<<deltam<<", \t"<<deltap<<"\n\n";
delta=deltap+deltam;
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
@ -4375,17 +4390,31 @@ bool JKQTPbarHorizontalGraph::getXMinMax(double& minx, double& maxx, double& sma
for (int i=imin; i<imax; i++) {
double xv=datastore->get(xColumn,i);
long long sr=datastore->getNextLowerIndex(xColumn, i, datarange_start, datarange_end);
long long lr=datastore->getNextHigherIndex(xColumn, i, datarange_start, datarange_end);
double delta, deltap, deltam;
if (imin==imax) { // only one x-value
// if (imin==imax) { // only one x-value
// deltam=0.5;
// deltap=0.5;
// } else if (i==imax-1) { // the right-most x-value
// deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
// } else if (i==imin) { // the left-most x-value
// deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
// } else {
// deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
// deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
// }
if (sr<0 && lr<0) { // only one x-value
deltam=0.5;
deltap=0.5;
} else if (i==imax-1) { // the right-most x-value
deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
} else if (i==imin) { // the left-most x-value
deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
} else if (lr<0) { // the right-most x-value
deltap=deltam=fabs(xv-datastore->get(xColumn,sr))/2.0;
} else if (sr<0) { // the left-most x-value
deltam=deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0;
} else {
deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0;
deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0;
deltam=fabs(xv-datastore->get(xColumn,sr))/2.0;
deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0;
}
delta=deltap+deltam;
@ -4546,16 +4575,30 @@ void JKQTPbarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
int i=qBound(imin, getDataIndex(iii), imax);
double xv=datastore->get(xColumn,i);
double yv=datastore->get(yColumn,i);
if (imin==imax) { // only one x-value
long long sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end);
long long lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end);
// if (imin==imax) { // only one x-value
// deltam=0.5;
// deltap=0.5;
// } else if (i==imax-1) { // the right-most x-value
// deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
// } else if (i==imin) { // the left-most x-value
// deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
// } else {
// deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
// deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
// }
if (sr<0 && lr<0) { // only one y-value
deltam=0.5;
deltap=0.5;
} else if (i==imax-1) { // the right-most x-value
deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
} else if (i==imin) { // the left-most x-value
deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
} else if (lr<0) { // the right-most y-value
deltap=deltam=fabs(yv-datastore->get(yColumn,sr))/2.0;
} else if (sr<0) { // the left-most y-value
deltam=deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0;
} else {
deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
deltam=fabs(yv-datastore->get(yColumn,sr))/2.0;
deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0;
}
delta=deltap+deltam;
@ -4659,16 +4702,30 @@ bool JKQTPbarVerticalGraph::getYMinMax(double& miny, double& maxy, double& small
for (int i=imin; i<imax; i++) {
double yv=datastore->get(yColumn,i);
double delta, deltap, deltam;
if (imin==imax) { // only one x-value
long long sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end);
long long lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end);
// if (imin==imax) { // only one x-value
// deltam=0.5;
// deltap=0.5;
// } else if (i==imax-1) { // the right-most x-value
// deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
// } else if (i==imin) { // the left-most x-value
// deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
// } else {
// deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
// deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
// }
if (sr<0 && lr<0) { // only one y-value
deltam=0.5;
deltap=0.5;
} else if (i==imax-1) { // the right-most x-value
deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
} else if (i==imin) { // the left-most x-value
deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
} else if (lr<0) { // the right-most y-value
deltap=deltam=fabs(yv-datastore->get(yColumn,sr))/2.0;
} else if (sr<0) { // the left-most y-value
deltam=deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0;
} else {
deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0;
deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0;
deltam=fabs(yv-datastore->get(yColumn,sr))/2.0;
deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0;
}
delta=deltap+deltam;
if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(delta) ) {

View File

@ -14,8 +14,10 @@ int main(int argc, char* argv[])
JKQTPdatastore* ds=plot.getDatastore();
// 2. now we create data for three simple barchart
QString L[Ndata]={ "cat. A", "cat. B", "cat. C", "cat. D", "other"};
double X[Ndata]={ 1, 2, 3, 4, 5};
QString L[Ndata]={ "cat. A", "cat. C", "cat. B", "cat. D", "other"};
double X[Ndata]={ 1, 3, 2, 4, 5};
//QString L[Ndata]={ "cat. A", "cat. B", "cat. C", "cat. D", "other"}; // correctly sorted data!
//double X[Ndata]={ 1, 2, 3, 4, 5};
double Y1[Ndata]={ 5, 4, 3, 4, 5};
double Y2[Ndata]={ -5, -3, 1, 3, 6};
double Y3[Ndata]={ 6, 2, 5, 3, 6};