Questions:
1 - Sort multiple float vectors in the same order (keeping correspondance)
2 - QCustomPlot (QCP) plots ONLY outer boundary of a scatter plot.
(answering either of these 2 questions would solve my problem)
Situation:
I have 3 vectors for plotting:
std::vector<float> x, y;
std::vector<int> hits;
The resulting plot is a hit or miss scatter plot. The resulting plot is used by QCustomPlot's curve, which ends up as a circular "scribble." It just needs to look similar to a circle with no "scribbling" inside. I need this plot to overlay over another plot.
I don't have much control over the initial order of x
, y
, or hits
.
x
and y
are sorted in a traditional grid indexing:
x = -8, -8, -8, -8, -8, -4, -4, -4, -4, -4, ... 8
y = -8, -4, 0, 4, 8, -8, -4, 0, 4, 8, ... 8
The hits
are based on wether (let's just say archer's arrow) a hit was successful based on a range and speed of a fast target (let's just say bird).
The resulting plot is the outer boudary of hits based on the bird as a center reference.
The data vectors can be very large.
Method 1: I can calculate range and angle. Then doing a sort on float vectors: Sort the angles in order, so that when QCustomPlot plots the outer boundary without 'scribbles' inside. However, I need to know how to keep the corresponding x
& y
values together based on sorting the angle
.
// Make range and angle vectors for sorting
std::vector<float> range, angle;
for(int i = 0; i < x.size(); ++i {
float r = sqrt(x[i]*x[i] + y[i]*y[i]);
range.push_back(r);
float a = 0;
if(y < 0)
a = -acos(x[i]/r);
else
a = acos(x[i]/r);
angle.push_back(a);
}
// Sort all vectors by ascending angle vector.
/* Do stuff here! */
// Set up boundary plot data
QVector<float> plot_x, plot_y;
for(int i = 0; i < x.size(); ++i {
if(hits[i]) {
plot_x.push_back(x[i]);
plot_y.push_back(y[i]);
}
}
// curve is a QCPCurve object already existing.
curve->addData(plot_x, plot_y); // Already sorted QVectors
Method 2: Get QCustomPlot
curve->addData(x, y)
member to only plot an "perimeter line" of the scatter plot's hits
. I have tried using QCPScatterStyle
, .setCustomPath
, but have not been successful.
Thank you in advance! -John
If you want to order several vectors using some criteria and all the indices correspond create a new vector that are the indices, and order it, then use those indices to create the new vectors:
#include <cmath>
#include <QDebug>
static float calc_angle(float x, float y){
float r = sqrt(x*x + y*y);
float angle = acos(x/r);
return y<0 ? -angle : angle;
}
int main(int argc, char *argv[])
{
std::vector<int> hits{0, 1, 2, 1, 0, 1, 2, 1, 0, 1};
std::vector<float> x{-8, -8, -8, -8, -8, -4, -4, -4, -4, -4};
std::vector<float> y{-8, -4, 0, 4, 8, -8, -4, 0, 4, 8};
Q_ASSERT(x.size() == y.size() && y.size() == hits.size());
std::vector<int> indexes(x.size());
std::iota(indexes.begin(), indexes.end(), 0);
std::sort(indexes.begin(), indexes.end(), [&](const int & i, const int & j) -> bool{
return calc_angle(x[i], y[i]) < calc_angle(x[j], y[i]);
});
QVector<float> plot_x, plot_y;
QVector<int> new_hits;
for(const int & index : indexes){
plot_x<<x[index];
plot_y<<y[index];
new_hits<<hits[index];
}
qDebug()<<indexes;
qDebug()<< plot_x;
qDebug()<<plot_y;
qDebug()<<new_hits;
return 0;//a.exec();
}
Output:
std::vector(8, 0, 1, 2, 3, 4, 5, 6, 7, 9)
QVector(-4, -8, -8, -8, -8, -8, -4, -4, -4, -4)
QVector(4, -8, -4, 0, 4, 8, -8, -4, 0, 8)
QVector(0, 0, 1, 2, 1, 0, 1, 2, 1, 1)