0

I am dividing a part of a 3D space into a series of 1x1x1 cubes, and that part may have a volume of 100^3 up to 1000^3, however, the cubes/cells I am really interested in rarely exceed 5000-20000 in their numbers.

What I am trying to do is to find all the cells/cubes which satisfy my criteria, adjacent to the chosen one. However, I am not sure what algorithm is the best for such a task. First thing which comes to my mind is to use a regular flood fill algorithm, but the following problem arises: I have to store information about all of the cells in the working area, which as I said may have up to 1000^3 elements, but the ones I need are barely 5000-20000.

So said my questions are:

  1. If I should use flood fill, is there any data structure which can be used in my case?
  2. If I shouldn't use flood fill, what should I?
help-info.de
  • 6,695
  • 16
  • 39
  • 41
R. Noe
  • 3
  • 3
  • 1
    I would guess that whatever works best will depend on the actual criteria for selecting which cells are included. What is the criteria? – Galik Jul 16 '16 at 10:47
  • Well... The criteria is gas density, however the specific of my task require me to choice cells adjacent by their facets. – R. Noe Jul 16 '16 at 10:50
  • If your criteria can be calculated on each visited cell independently and efficiently then you can use whatever structure you liek for the cells of interest (e.g. `vector`). However - do you have any specific order in which you would liek to later on process the cells of interest? If so - you just need to make sure you load the cells of interest in the container in the expected order from the very beginning – Boris Strandjev Jul 16 '16 at 16:04
  • Nope, the order doesn't matter at all and yes, I can calculate the criteria independently. However, the problem is that I have to keep track of all visited cells in order to prevent going back there again. My current implementation consists of vector in which each visited cell has been added and of a queue of cells, whose adjacent cells hasn't been added yet. And it works fine at first, but the performance downgrades with time as number of elements in vector increases, and so does the computing time to check whether the nearby elements from the queue have already been added. – R. Noe Jul 16 '16 at 16:42
  • You can store all visited cells in `set >` to speed up significantly the check whether the cell has been visited already. – Boris Strandjev Jul 16 '16 at 17:09
  • Could you please clarify that a bit? I am not particularly familiar with STL, but I've looked up information on those structures and I can't yet see how can it can help the case. – R. Noe Jul 16 '16 at 17:32

3 Answers3

0

I think this should illustrate my idea of how you can solve your problem. You can also consider transferring the set to a vector once you are done with the initial processing (though strictly speaking both structures are similar in resepct to full iteration amortised speed)

set<pair<int, int> > getAllPointsToProcess(const pair<int, int>& initialCell) {
    set<pair<int, int> > activatedCells; // these will be returned
    queue<pair<int, int> > toProcess;
    toProcess.push(initialCell);
    activatedCells.insert(initialCell);
    int adjacentOffsets[][] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    pair<int, int> currentlyProcessed;
    int neighbourCell;
    while (!toProcess.empty()) {
        currentlyProcessed = toProcess.front();
        toProcess.pop();
        for (int i = 0; i < 4; i++) {
             neighbourCell.first = currentlyProcessed.first + adjacentOffsets[i][0];
             neighbourCell.second = currentlyProcessed.second + adjacentOffsets[i][1];
             if (isActive(neighbourCell) && activatedCells.find(neighbourCell) == activatedCells.end()) {
                 toProcess.push(neighbourCell);
                 activatedCells.insert(neighbourCell);
             }
        }
    return activatedCells;
} 
Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135
0

As you pointed out, Flood-Fill algorithm seems relevant to this problem.The problem you are facing is storing information about all the cubes whether they have been visited or not.

You got two options :

  1. Keep Hash for each cubes , Space : O(1000^3) Time : O(1) : which u don't want
  2. Maintain a list of visited cubes , Space : O(10000) Time : O( 100002 ) : Everytime u need to check whether this cube has been visited just traverse the complete list of visited cubes.

That's just space-time trade off.

P.S : I hope I got your problem correctly !

pseudo_teetotaler
  • 1,485
  • 1
  • 15
  • 35
0

I'll try to rephrase the need: you want to store some data (bool visited) for every cell and for most of cells it will be the same (nor visited), so you want to save some memory.

Recently I heard about OpenVDB: http://www.openvdb.org/documentation/doxygen/

I haven't used it, but it looks like it matches the requirement - it stores sparse volumetric data and claims to be memory and time efficient.

maxim1000
  • 6,297
  • 1
  • 23
  • 19
  • Unfortunately their algorithms do not differ much from mine, however I indeed got a performance boost as their code is more optimized. I think I'll have to stick with it. – R. Noe Jul 17 '16 at 14:59