c++ - Best data structure for point traversal -
looking c++ solution.
i had thoughts whether ask question on here or mathexchange etc. since it's more of programming based question posting here.
real problem:
i have xml field as:
<part name='01' x='351' y='151'/>
where x , y, storing qpointf object. also, require name=01
value mapping qpointf
object create map.
now there operations need on map :
- first need points(qpointf) , draw on image.
- second, modify x , y value of points getting points gui.
- when points gui, need check x , y value in each qpointf inside map.
problem in simpler form:
i looking data structure such instead of having map of key
, qpointf
, makes parsing , looking x , y value of points(qpointf) easier. qpointf , key should form unique pair each other, parsing through entire list of points find (x,y)
, modifying faster , when x , y value of qpointf modified key attached same.
ps: hope clear problem, if there unclear please edit/comment question can improved.
my guess here important aspect finding set of x , y points when user uses ui. there many acceleration structures possible, recommend point index grid
. is, partition indices of points 2d buckets. when user chooses point in ui, can quick look-up on bucket point in, , can iterate on points present in bucket find actual point.
as data, store in array:
struct namepoint { int name, x, y; }; std::vector<namepoint> points;
now create point index grid refers points
array. implementing 1 might worthwhile, otherwise know there exists openvdb version works.
i made small dirty implementation can see principle. have no checks inputs, if you're not careful access out of bounds of vector (e.g., calling pointindexgrid.indicesforpoint(5, 5)
gives segmentation fault).
#include <iostream> #include <vector> #include <limits> struct namepoint { int name, x, y; }; template <typename t> // array type can work struct pointindexgrid { using arraytype = t; using size_type = typename arraytype::size_type; pointindexgrid(const arraytype& points, int gridsize) : mgridsize(gridsize) { // find domain. create 2d vector contain vector indices. maxx = maxy = std::numeric_limits<int>::min(); minx = miny = std::numeric_limits<int>::max(); (const auto& p : points) { maxx = p.x > maxx ? p.x : maxx; maxy = p.y > maxy ? p.y : maxy; minx = p.x < minx ? p.x : minx; miny = p.x < miny ? p.x : miny; } // create buckets int nbrxbuckets = (maxx - minx)/mgridsize + 1; // due integer arithmetics round down -- lets add 1 in case int nbrybuckets = (maxy - miny)/mgridsize + 1; (int n = 0; n < nbrxbuckets; ++n) { mbuckets.emplace_back(std::vector<std::vector<size_type>>(nbrybuckets)); } // partition points (size_type = 0; < points.size(); ++i) { int xbucket = (points[i].x - minx)/mgridsize; // method how calculate bucket. pure arithmetics -- goes fast int ybucket = (points[i].y - miny)/mgridsize; mbuckets[xbucket][ybucket].emplace_back(i); } } std::vector<size_type> indicesforpoint(int x, int y) { int xbucket = (x - minx)/mgridsize; // same above int ybucket = (y - miny)/mgridsize; return mbuckets[xbucket][ybucket]; } private: int mgridsize; int maxx, minx; int maxy, miny; std::vector<std::vector<std::vector<size_type>>> mbuckets; }; int main() { std::vector<namepoint> points; points.emplace_back(namepoint{1, 1, 1}); points.emplace_back(namepoint{2, 1, 2}); points.emplace_back(namepoint{3, 1, 2}); points.emplace_back(namepoint{4, 2, 2}); points.emplace_back(namepoint{5, 3, 3}); pointindexgrid<std::vector<namepoint>> pointindexgrid(points, 2); std::cout << "indices (1, 1): " << std::endl; (const auto& : pointindexgrid.indicesforpoint(1, 1)) { std::cout << " " << << std::endl; } std::cout << "indices (3, 3): " << std::endl; (const auto& : pointindexgrid.indicesforpoint(3, 3)) { std::cout << " " << << std::endl; } }
this prints out:
indices (1, 1): 0 1 2 3 indices (3, 3): 4
so find point @ specific (x, y)
:
- partition points using
pointindexgrid
. - use
pointindexgrid.indicesforpoint(x, y)
. - iterate through indices there (and points in
points
-array). - grab point want.
Comments
Post a Comment