From 34631fb66f1b44c654043d1c9e8dfa8150d287c0 Mon Sep 17 00:00:00 2001 From: kriegerj Date: Fri, 21 Aug 2015 13:49:11 +0200 Subject: [PATCH] JKQTPbarVerticalGraph and JKQTPbarHoricontalGraph now draw bars with the proper width, even if data is not sorted --- jkqtpdatastorage.cpp | 104 ++++++++++++---- jkqtpdatastorage.h | 16 ++- jkqtpelements.cpp | 113 +++++++++++++----- .../jkqtplotter_simpletest_barchart.cpp | 6 +- 4 files changed, 182 insertions(+), 57 deletions(-) diff --git a/jkqtpdatastorage.cpp b/jkqtpdatastorage.cpp index efc91d2b12..745e7c692d 100644 --- a/jkqtpdatastorage.cpp +++ b/jkqtpdatastorage.cpp @@ -57,14 +57,10 @@ QVector JKQTPcolumn::copyData() QVector 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)=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)getColumn("<getItem(datastoreItem); } diff --git a/jkqtpelements.cpp b/jkqtpelements.cpp index 85b4e8bed5..6d1c11b940 100644 --- a/jkqtpelements.cpp +++ b/jkqtpelements.cpp @@ -23,6 +23,7 @@ #include "jkqtpbaseplotter.h" #include #include +#include #include "jkqtptools.h" #include "jkqtpimageelements.h" #include "jkqtpbaseelements.h" @@ -4311,18 +4312,32 @@ void JKQTPbarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) { for (int iii=imin; iiiget(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<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; iget(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) ) { diff --git a/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp b/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp index ade90f09c1..a85dd90fd0 100644 --- a/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp +++ b/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp @@ -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};