Home > Software engineering >  sort vector of Coordinates(x,y,z) by vector of z value
sort vector of Coordinates(x,y,z) by vector of z value

Time:10-24

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

https://onlinegdb.com/rthoPhvuM

  •  Tags:  
  • c
  • Related