Solved Scanning edges of a cube

Discussion in 'Plugin Development' started by Googlelover1234, Jun 18, 2016.

Thread Status:
Not open for further replies.
  1. Offline

    Googlelover1234

    Hi there folks! I am currently attempting to make a method to find the edges of a cube (between two vectors). I have just edited the code that @desht posted a while back, and while my code works on a few conditions (Y has to be even, X&Z must be odd), it still does not always stay true to that.

    Code:
    PHP:
        // Base code modified by me, thanks desht on Bukkit forums.
       
        
    public List<VectorgetEdges() {
           
            List<
    Vectorresult = new ArrayList<Vector>();
           
            
    int spacesToFix 0;
           
            for (
    int y min.getBlockY() + 1max.getBlockY(); y++, spacesToFix++) {
                
    result.add(new Vector(min.getBlockX(), ymin.getBlockZ()));
                
    result.add(new Vector(min.getBlockX(), ymax.getBlockZ()));
                
    result.add(new Vector(max.getBlockX(), ymin.getBlockZ()));
                
    result.add(new Vector(max.getBlockX(), ymax.getBlockZ()));
               
                
    result.add(new Vector(min.getBlockX(), ymin.getBlockZ()));
                
    result.add(new Vector(max.getBlockX(), ymin.getBlockZ()));
                
    result.add(new Vector(min.getBlockX(), ymax.getBlockZ()));
                
    result.add(new Vector(max.getBlockX(), ymax.getBlockZ()));
               
            }
           
            
    Bukkit.broadcastMessage("SpacesToFix: " +spacesToFix);
           
            for (
    int x min.getBlockX(); <= max.getBlockX(); x++) {
               
                
    result.add(new Vector(xmin.getBlockY(), min.getBlockZ()));
                
    result.add(new Vector(xmin.getBlockY(), max.getBlockZ()));
                
    result.add(new Vector(xmax.getBlockY(), min.getBlockZ()));
                
    result.add(new Vector(xmax.getBlockY(), max.getBlockZ()));
               
                
    result.add(new Vector(xmin.getBlockY() + spacesToFixmin.getBlockZ()));
                
    result.add(new Vector(xmax.getBlockY() - spacesToFixmin.getBlockZ()));
                
    result.add(new Vector(xmin.getBlockY() + spacesToFixmax.getBlockZ()));
                
    result.add(new Vector(xmax.getBlockY() - spacesToFixmax.getBlockZ()));
               
            }
           
            for (
    int z min.getBlockZ() + 1max.getBlockZ(); z++) {
               
                
    result.add(new Vector(min.getBlockX(), min.getBlockY(), z));
                
    result.add(new Vector(max.getBlockX(), min.getBlockY(), z));
                
    result.add(new Vector(min.getBlockX(), max.getBlockY(), z));
                
    result.add(new Vector(max.getBlockX(), max.getBlockY(), z));
               
                
    result.add(new Vector(min.getBlockX(), min.getBlockY() + spacesToFixz));
                
    result.add(new Vector(min.getBlockX(), max.getBlockY() - spacesToFixz));
                
    result.add(new Vector(max.getBlockX(), min.getBlockY() + spacesToFixz));
                
    result.add(new Vector(max.getBlockX(), max.getBlockY() - spacesToFixz));
            }
           
            return 
    result;
        }
    First, a few things to explain about the code:
    This method is inside of my custom "Bounds" class, which represents the bounds in a cube. min is obviously the smaller vector, while max is the bigger one (I have ensured this, so there should be no issue there). The method that desht posted works great the the OP's problem, but doesn't fit mine quite as well (I don't want there to be spaces on the sides, only on the floor and ceiling).

    Screenshots:

    [​IMG]
    ^ Works fine, has no holes in the sides of the cube, only on floor and ceiling. It is 4 (even) blocks high, and 5 (odd) blocks wide.

    [​IMG]
    ^ Doesn't work like I want it to (if it's too hard to see, there's a strip of blocks there aren't placed on each side right in the middle. It is 5 (odd) blocks high, and 7 (odd) blocks wide.

    If there is anything else you need (screenshots, code, etc), please feel free to ask me.
     
  2. Offline

    I Al Istannen

    @Googlelover1234
    I didn't really understand his code, so I made my own. It is easier than you might think. The basic principle is the following:
    Principle.png

    If you can't fix your code above, I would encourage you to write your own. Without code from anybody else. It will give you a much better understanding of what does what.

    The picture above should help you to find a small algorithm to do it on your own. Every color is made by a nested for loop and you are looking from the top.

    If you have any questions regarding making your own, feel free to ask them!

    If you want to have the code you copied (and slightly adjusted) fixed, I won't help you. I didn't and won't take the time to understand his code and this is one of the tasks you can do yourself :)
     
    Googlelover1234 likes this.
  3. Offline

    Googlelover1234

    @I Al Istannen
    The reason I wanted to use his code was because I figured it would be more efficient than what I had in mind. I would be drawing these cubes quite frequently. Anyway, I am assuming that you are hinting that I should create two walls each loop (which is what I was already doing anyway). But I suppose I could try to recreate the method and can report back to you.
     
  4. Offline

    I Al Istannen

    @Googlelover1234
    Well, I can't think of a more efficient solution than checking every block exactly once. Which the method in the picture above does, if you implement it like you see there.
    I mean, you need to check every block once, there is no smaller way. The arithmetic between each block is addition and subtraction, which is totally negligible.

    I use a 2D for-loop to draw each wall, packed in another for-loop which just supplies the values for the last remaining axis. The outer loop (supplying the last axis) is therefore run twice.
     
    Googlelover1234 likes this.
  5. Offline

    Googlelover1234

    @I Al Istannen
    Could you elaborate more on what you mean by the last axis? I'm assuming you pack two loops for X and Z into a big loop for Y?

    @I Al Istannen
    Actually, thank you very much. You made me think a lot more... outside the box... get it? Anyway: here's what I found to be a good solution:

    PHP:
        public List<VectorgetEdges() {
         
            List<
    Vectorresult = new ArrayList<Vector>();
         
            for (
    int y min.getBlockY(); <= max.getBlockY(); y++) {
             
                for (
    int x min.getBlockX(); <= max.getBlockX(); x++) {
                 
                    
    result.add(new Vector(xymin.getBlockZ()));
                    
    result.add(new Vector(xymax.getBlockZ()));
                 
                }
             
                for (
    int z min.getBlockZ(); <= max.getBlockZ(); z++) {
                 
                    
    result.add(new Vector(min.getBlockX(), yz));
                    
    result.add(new Vector(max.getBlockX(), yz));
                 
                }
             
            }
         
            return 
    result;
         
        }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited: Jun 18, 2016
  6. Offline

    I Al Istannen

    @Googlelover1234
    You ended up doing it a bit different, but it looks beautiful ;)
    Last thing you could do is specify the size of the arraylist at creating time to speed it up (actually quite heavily if the cube is big). For me it could cut the needed time in half.
    I think you can calculate the needed size with:
    "(xMax - xMin) * (yMax - yMin) * 2 + (zMax - zMin) * (yMax - yMin) * 2", but there surely is a better formula on the internet :p

    ArrayList uses an array internal. If the amount of items is bigger than the array size, it needs to create a new array, copy the data and delete the old one. This takes some time.

    So, I would either specify the size (probably the fastest option, as you know it beforehand.) or use a HashSet (constant add, remove, contains and a few others time, but needs to calculate the hash. Will be slower than an ArrayList with the right size).

    You can further speed it up by saving the "min.getBlockX()" and so on in variables. Accessing these variables will be faster than invoking the method everytime. This may fall under premature optimization, but I would specify the arraylist capacity. It should really speed it up, without you really changing anything.
     
    Last edited: Jun 18, 2016
  7. Offline

    Googlelover1234

    @I Al Istannen
    I agree with setting the arraylist size beforehand, thank you for the suggestion.

    PHP:
        public List<VectorgetEdges() {
           
            
    int minX min.getBlockX();
            
    int maxX max.getBlockX();
           
            
    int minY min.getBlockY();
            
    int maxY max.getBlockY();
           
            
    int minZ min.getBlockZ();
            
    int maxZ max.getBlockZ();
           
            
    int amountOfBlocks = (((maxX minX) * (maxY minY)) * 2) + (((maxZ minZ) * (maxY minY)) * 2);
           
            List<
    Vectorresult = new ArrayList<Vector>(amountOfBlocks);
           
            for (
    int y minY<= maxYy++) {
               
                for (
    int x minX<= maxXx++) {
                   
                    
    result.add(new Vector(xyminZ));
                    
    result.add(new Vector(xymaxZ));
                   
                }
               
                for (
    int z minZ<= maxZz++) {
                   
                    
    result.add(new Vector(minXyz));
                    
    result.add(new Vector(maxXyz));
                   
                }
               
            }
           
            return 
    result;
           
        }
     
  8. Offline

    I Al Istannen

    @Googlelover1234
    Yea, looks good ;)

    Good luck with your plugin and have a nice day!
     
  9. Offline

    Googlelover1234

    @I Al Istannen
    Thank you for your help, enjoy the rest of your day too.
     
    I Al Istannen likes this.
Thread Status:
Not open for further replies.

Share This Page