简体   繁体   中英

Highest values in vector< vector<Point3f> >

I know the how to find the highest values for the data types like int , float , double , etc. But here I am working with x , y , & z coordinates by using Point3f . So can anybody help to find the highest values of x , y or z from a std::vector of std::vector ?

std::vector< std::vector<Point3f> > cluster_points;

for simplicity lets say I want to find the highest values only for x axis among all.

I don't know opencv, so can be simpler solutions but...

What about a couple of std::for_each() with a couple of lambda functions?

std::vector<std::vector<Point3f>> vvp { /* some data */ };

auto mx = vvp[0][0].x;
auto my = vvp[0][0].y;
auto mz = vvp[0][0].z;

std::for_each(vvp.cbegin(), vvp.cend(),
   [&](std::vector<Point3f> const & vp)
       { std::for_each(vp.cbegin(), vp.cend(),
            [&](Point3f const & p)
               { mx = std::max(mx, p.x);
                 my = std::max(my, p.y);
                 mz = std::max(mz, p.z); }); });

If you can use C++14, so lambda functions with auto arguments, the double std::for_each() part can be simply written as

std::for_each(vvp.cbegin(), vvp.cend(), [&](auto const & vp)
 { std::for_each(vp.cbegin(), vp.cend(), [&](auto const & p)
    { mx = std::max(mx, p.x);
      my = std::max(my, p.y);
      mz = std::max(mz, p.z); }); });

so without expliciting Poinf3f and usable by other point-3d like types.

This is C++14.

This is a solution without explicit loops in client code.

template<class F>
auto foreacher(F&& f) {
  return [f=std::forward<F>(f)](auto&& r)mutable{
    for (auto&& e:decltype(r)(r))
      f(decltype(e)(e));
  };
}

std::vector<std::vector<Point3f>> data = {whatever};
auto mx = data[0][0].x;
auto task = foreacher(foreacher([&](Point3f const& e){
  mx = (std::max)(mx, e.x);
}));

task(data);

We take our lambda that solves the problem on an element, then we wrap it in two modifiers that make it iterate over the contents of the argument.

Live example .

You can use std::accumulate which maps to this task pretty well:

const auto min = std::numeric_limits<float>::min();
Point3f init( min, min, min );
std::vector< std::vector<Point3f> > cluster_points;
auto max = std::accumulate( cluster_points.begin(), cluster_points.end(), init, []( const Point3f &p, const std::vector<Point3f> &v ) {
    return std::accumulate( v.begin(), v.end(), p, []( const Point3f &p1, const Point3f &p2 ) {
       return Point3f( std::max( p1.x, p2.x ), std::max( p1.y, p2.y ), std::max( p1.z, p2.z ) );
   }
} ) );

And this requires only C++11, with C++14 it could be simplified by using auto arguments in lambdas

Although there are several great answers, I am just writing the one which is pure opencv , I leave the investigation upon the fastest way to you.

std::vector<Point3f> points;
// .. fill the array
Mat pointsMat = Mat(points).reshape(1); 

Quoting - As a result we get a 32FC1 matrix with 3 columns instead of 32FC3 matrix with 1 column. pointsMat uses data from points and will not deallocate the memory when destroyed. In this particular instance, however, developer has to make sure that lifetime of points is longer than of pointsMat.

Then, now that you have a Mat with all your Point3f , you could use the following:

minMaxLoc(pointsMat, &minVal, &maxVal);

If you wish to do this for std::vector<std::vector<Point3f>> All_points you can make a single channel Mat with number of columns = All_points.size() * 3 and use the same function minMaxLoc . This will give you minVal and maxVal along all point sets.

You can also get the location of the minVal and maxVal like:

minMaxLoc(pointsMat, &minVal, &maxVal, &minLoc, &maxLoc);

which is of course in the reshaped Mat .

Hope it helps!

PS Kudos to the C++11 and C++14 answers

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM