The fastest way to find if a 3D coordinate is already in use

Using C ++ (and Qt), I need to handle a large number of 3D coordinates.

In particular, when I get a three-dimensional coordinate (consisting of 3 doubles), I need to check the list if this coordinate has already been processed. If not, I process it and add it to the list (or container).

The number of coordinates can become very large, so I need to save the processed coordinates in the container, which will provide a quick check of the three-dimensional coordinate in the container.

I was thinking about using a map map map, keeping the x coordinate, then the y coordinate, then the z coordinate, but that makes it pretty tedious to use, so I really hope that there is a lot better way to do this that I can't think.

+3
source share
19 answers

Probably the easiest way to speed up this processing is to save the points that have already been processed in Octree . Verification of duplication will be close to logarithmic.

Also, make sure that you make rounding errors by checking the distance between the points, and not the equality of coordinates.

+7
source

You can easily use the kit as follows:

#include <set>
#include <cassert>

const double epsilon(1e-8);

class Coordinate {
public:
Coordinate(double x, double y, double z) :
  x_(x), y_(y), z_(z) {}

private:
double x_;
double y_;
double z_;

friend bool operator<(const Coordinate& cl, const Coordinate& cr);
};

bool operator<(const Coordinate& cl, const Coordinate& cr) {
  if (cl.x_ < cr.x_ - epsilon) return true;
  if (cl.x_ > cr.x_ + epsilon) return false;

  if (cl.y_ < cr.y_ - epsilon) return true;
  if (cl.y_ > cr.y_ + epsilon) return false;

  if (cl.z_ < cr.z_ - epsilon) return true;

  return false;

}

typedef std::set<Coordinate> Coordinates;

// Not thread safe!
// Return true if real processing is done
bool Process(const Coordinate& coordinate) {
  static Coordinates usedCoordinates;

  // Already processed?
  if (usedCoordinates.find(coordinate) != usedCoordinates.end()) {
    return false;
  }

  usedCoordinates.insert(coordinate);

  // Here goes your processing code



  return true;

}

// Test it
int main() {
  assert(Process(Coordinate(1, 2, 3)));
  assert(Process(Coordinate(1, 3, 3)));
  assert(!Process(Coordinate(1, 3, 3)));
  assert(!Process(Coordinate(1+epsilon/2, 2, 3)));
}
+4
source

. . , , , . , , .

. (, 1000 ), , 2 .

+3

, Coordinate, - hash_set . :

struct coord_eq
{
  bool operator()(const Coordinate &s1, const Coordinate &s2) const
  {
    return s1 == s2;
    // or: return s1.x() == s2.x() && s1.y() == s2.y() && s1.z() == s2.z();
  }
};

struct coord_hash
{
  size_t operator()(const Coordinate &s) const
  {
     union {double d, unsigned long ul} c[3];
     c[0].d = s.x();
     c[1].d = s.y();
     c[2].d = s.z();
     return static_cast<size_t> ((3 * c[0].ul) ^ (5 * c[1].ul) ^ (7 * c[2].ul));
  }
};

std::hash_map<Coordinate, coord_hash, coord_eq> existing_coords;
+2

, , ... , , ?

, .

, Octree .

, - (0, 0, 0,01) , (0, 0, 0.01000001)? , , , . , .

+1

/ ? . , (1.0, 1.0, 1.0), (0.9999999999999, 1.0, 1.0), ? , - , .

, : , , ( , , , ). , "(1.0,1.0,1.0)" . , ( ) . , , .

+1

boost:: ?

( divide-by-epsilon .)

+1

.

: md5 ('X, Y, Z') , .

- , . - , .

/

+1

std:: set. 3d- ( boost:: tuple), < . , , . ( ), .

, , , . IE, (1.0, 1.0, 1.0) , (1.0, 1.0, 1.000000001)?

+1

... , , .

, case less code , .

", " --- , typedefs - ( ).

3D- - ( , " X P" ), -... O (n) create, O (1) (, , ), .

, , . . , , .

... octree.

, , k-d tree. k-d ( , ). , Kd- Octrees, .

+1

, , 1 , 32- ; X, Y Z . - - ( , ).

, , , , .

0

, , , map<map<map<>>>. !

, -, . , . (, (1, 2, 3) (3, 2, 1) ..), - x, y, z, .

0

hash_set - , "(x, y, )". hash_set , .

0

, epsilon ( , ), epsilon, round .

0

- :

struct Coor {
    Coor(double x, double y, double z)
    : X(x), Y(y), Z(z) {}
    double X, Y, Z;
}

struct coords_thesame
{
  bool operator()(const Coor& c1, const Coor& c2) const {
    return c1.X == c2.X && c1.Y == c2.Y && c1.Z == c2.Z;
  }
};

std::hash_map<Coor, bool, hash<Coor>, coords_thesame> m_SeenCoordinates;

, :)

0

std::map, . . _Key template . .

:

#include <map>
#include <cassert>


struct Point {
  double x, y, z;
};

struct PointResult {
};

PointResult point_function( const Point& p ) { return PointResult(); }

// helper: binary function for comparison of two points
struct  point_compare {
  bool operator()( const Point& p1, const Point& p2 ) const {
    return p1.x < p2.x
      || ( p1.x == p2.x && ( p1.y < p2.y 
      || ( p1.y == p2.y && p1.z < p2.z ) 
      )
      );
  }
};

typedef std::map<Point, PointResult, point_compare> pointmap;

int _tmain(int argc, _TCHAR* argv[])
{

pointmap pm;

Point p1 = { 0.0, 0.0, 0.0 };
Point p2 = { 0.1, 1.0, 1.0 };

pm[ p1 ] = point_function( p1 );
pm[ p2 ] = point_function( p2 );
assert( pm.find( p2 ) != pm.end() );
    return 0;
}
0

, , .

, , , , , , (x, y, z) - , , (, ). / O (1).

, 3 , , (, OcTree, ), , O (logN) , , (, ..), , , .

0

std::set std::vector. . , .

0

? "" ? , , , -.

. , .

, , .

0

Source: https://habr.com/ru/post/1696956/


All Articles