I have a vector of 3D coordinates:
vector<float64>contourdata;
contourdata={x0,y0,z0,x1,y1,z1,x2,y2,z2,...}
And I want to sort them by the vector of the z value. How can I do it in c ?
CodePudding user response:
Like this :
#include <algorithm>
#include <iostream>
#include <vector>
#include <format>
// 3d points have 3 coordinates and
// we need to move those 3 values together when sorting
// It is also good to use "concepts" from real world as
// names in code : so define a struct representing a 3d coordinate.
// (Or use a 3d coordinate type from an existing library)
struct vec_3d_t
{
double x;
double y;
double z;
};
// helper function for outputing the values of one 3d point
// not essential for your problem.
std::ostream& operator<<(std::ostream& os, const vec_3d_t& data_point)
{
os << std::format("({0},{1},{2})", data_point.x, data_point.y, data_point.z);
return os;
}
int main()
{
// std::vector is a (resizable) array
// in this case to hold 3d coordinates
// then initialize the data with some values
// (you will probably get them from somewhere else, e.g. a file)
std::vector<vec_3d_t> contour_data
{
{3.0,4.0,5.0}, // first coordinate
{1.0,2.0,3.0}, // second etc ...
{7.0,8.0,9.0}
};
// this calls the sort algorithm
// using a function to compare two 3d points
// to sort on z only compare z.
std::sort(contour_data.begin(), contour_data.end(), [](const vec_3d_t& lhs, const vec_3d_t& rhs)
{
return lhs.z < rhs.z;
});
// range based for loop over data points
for (const auto& data_point : contour_data)
{
std::cout << data_point << "\n";
}
return 0;
}
CodePudding user response:
I struggled to find a way to use std::sort
but you can always drop back the the C qsort
stdlib function:
#include <cstdlib>
int compare(const double *A, const double *B) {
return (A[2] <= B[2]) ? -1 : 1;
}
...
const size_t N = contourdata.size() / 3;
double *xyz = contourdata.data();
qsort(xyz, N, 3*sizeof(double),
(int (*)(const void *, const void*))compare);
CodePudding user response:
If your coords stored as a plain vector, you may use static_cast.
#include <iostream>
#include <cassert>
#include <algorithm>
#include <vector>
using float64 = float;
void Sort(std::vector<float64>& points) {
assert(points.size() % 3 == 0);
struct Point {
float64 X, Y, Z;
};
auto begin = static_cast<Point*>(static_cast<void*>(points.data()));
auto end = begin points.size() / 3;
std::sort(begin, end, [](const Point& ptLeft, const Point& ptRight){
return ptLeft.Z < ptRight.Z;
});
}
void printCoords (const std::vector<float64>& coords){
for(auto it = coords.begin(); it != coords.end();) {
for(int i = 0; i < 3; i) {
std::cout << " X=" << *it ;
std::cout << " Y=" << *it ;
std::cout << " Z=" << *it ;
std::cout << std::endl;
}
}
}
int main()
{
std::vector<float64> coords;
coords.insert(coords.end(), { 0.0F, 0.0F,0.0F});
coords.insert(coords.end(), { -1.0F, -1.0F, -1.0F});
coords.insert(coords.end(), { 1.0F, 1.0F, 1.0F});
std::cout << "Before sort\n";
printCoords(coords);
Sort(coords);
std::cout << "After sort\n";
printCoords(coords);
}
Output
Before sort
X=0 Y=0 Z=0
X=-1 Y=-1 Z=-1
X=1 Y=1 Z=1
After sort
X=-1 Y=-1 Z=-1
X=0 Y=0 Z=0
X=1 Y=1 Z=1