Package org.matheusdev.util.collections

Source Code of org.matheusdev.util.collections.GridCollection

/*
* Copyright (c) 2012 matheusdev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.matheusdev.util.collections;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import org.matheusdev.util.collision.Rect;
import org.matheusdev.util.vecs.Vec2i;

/**
* @author matheusdev
*
*/
public class GridCollection<E extends CollectionEntity> {

  protected final HashMap<Vec2i, ArrayList<E>> map;
  protected final ArrayList<E> queryList;
  protected int width;
  protected int height;

  public GridCollection(int elementWidth, int elementHeight) {
    this.width = elementWidth;
    this.height = elementHeight;
    this.map = new HashMap<>();
    this.queryList = new ArrayList<>();
  }

  public void add(E e) {
    Rect rect = e.getAABB();

    int beginx = ((int) rect.x) / width;
    int beginy = ((int) rect.y) / height;
    int endx = ((int) (rect.x + rect.w)) / width;
    int endy = ((int) (rect.y + rect.h)) / height;

    Vec2i pos = new Vec2i(0, 0);
    for (int y = beginy; y <= endy; y++) {
      for (int x = beginx; x <= endx; x++) {
        pos.set(x, y);

        ArrayList<E> mapList = map.get(pos);

        if (mapList == null) {
          ArrayList<E> list = new ArrayList<E>();
          list.add(e);
          map.put(new Vec2i(x, y), list);
        } else {
          mapList.add(e);
        }
      }
    }
  }

  public void query(CollectionTraverser<E> callback, Rect region) {
    int beginx = ((int) region.x) / width;
    int beginy = ((int) region.y) / height;
    int endx = ((int) (region.x + region.w)) / width;
    int endy = ((int) (region.y + region.h)) / height;

    for (int y = beginy; y <= endy; y++) {
      for (int x = beginx; x <= endx; x++) {
        Vec2i pos = Vec2i.get(x, y);
        ArrayList<E> elements = map.get(pos);

        if (elements != null) {
          for (int i = 0; i < elements.size(); i++) {
            boolean continueSearching = callback.handleElement(x, y, elements.get(i));

            if (!continueSearching) {
              return;
            }
          }
        }
      }
    }
  }

  public List<E> query(Rect region) {
    queryList.clear();

    int beginx = ((int) region.x) / width;
    int beginy = ((int) region.y) / height;
    int endx = ((int) (region.x + region.w)) / width;
    int endy = ((int) (region.y + region.h)) / height;

    for (int y = beginy; y <= endy; y++) {
      for (int x = beginx; x <= endx; x++) {
        Vec2i pos = Vec2i.get(x, y);
        ArrayList<E> elements = map.get(pos);

        if (elements != null) {
          queryList.addAll(elements);
        }
      }
    }
    return queryList;
  }

  public void update() {
    update(width, height);
  }

  /**
   * <p>Use this only in case you want to change the
   * width and height according to latest statistics
   * or something like that.</p>
   * @param newWidth
   * @param newHeight
   */
  public void update(int newWidth, int newHeight) {
    this.width = newWidth;
    this.height = newHeight;

    Iterator<Entry<Vec2i, ArrayList<E>>> itr = map.entrySet().iterator();

    while (itr.hasNext()) {
      Entry<Vec2i, ArrayList<E>> entry = itr.next();
      ArrayList<E> list = entry.getValue();
      // So this part is basically "Garbage-Collection"...
      //
      // The lists, which are empty, haven't got any
      // element inside them since they were created,
      // which means they aren't used, and probably
      // won't be used later.
      // Because of that we just let the GC Kill
      // those ArrayLists...
      if (list.isEmpty()) {
        // This comment is somehow famous...
        // (For reference, see source code from "ArrayList#clear()"...)
        // Let gc do its work
        map.put(entry.getKey(), null);
      } else {
        list.clear();
      }
    }
  }

}
TOP

Related Classes of org.matheusdev.util.collections.GridCollection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.