/**
* Copyright (c) 2009-2011, chunquedong(YangJiandong)
*
* This file is part of ChunMap project
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
*
* History:
* 2010-05-05 Jed Young Creation
*/
package chunmap.data.index;
import java.util.ArrayList;
import java.util.List;
import chunmap.model.elem.Envelope;
import chunmap.model.geom.Geometry;
/**
* 窗口过滤索引
*
* @author chunquedong
*
*/
public class Filter3window {
private Filter3window right;
private Filter3window middle;
private Filter3window left;
private final Envelope window;
private final List<Geometry> geometrys;
private final int nowDeep;
private final int maxDeep;
private final boolean isVertical;
public Filter3window(int nowDeep, int maxDeep, Envelope window,
boolean direction) {
this.nowDeep = nowDeep;
this.maxDeep = maxDeep;
this.window = window;
this.isVertical = direction;
geometrys = new ArrayList<Geometry>();
}
public void put(Geometry g) {
if (nowDeep == maxDeep) {
geometrys.add(g);
} else {
if (!putSubWindow(g)) {
geometrys.add(g);
}
}
}
private boolean putSubWindow(Geometry g) {
insureInit();
if (middle.getEnvelop().contain(g.getEnvelop())) {
middle.put(g);
return true;
} else if (right.getEnvelop().contain(g.getEnvelop())) {
right.put(g);
return true;
} else if (left.getEnvelop().contain(g.getEnvelop())) {
left.put(g);
return true;
}
return false;
}
private void insureInit() {
boolean b = !isVertical;
if (middle == null) {
middle = new Filter3window(nowDeep + 1, maxDeep, mEnv(), b);
right = new Filter3window(nowDeep + 1, maxDeep, rEnv(), b);
left = new Filter3window(nowDeep + 1, maxDeep, lEnv(), b);
}
}
private Envelope mEnv() {
if (isVertical) {
double oneFour = (window.getMaxX() - window.getMinX()) / 4d;
double maxX = window.getMaxX() - oneFour;
double minX = window.getMinX() + oneFour;
return new Envelope(minX, window.getMinY(), maxX, window.getMaxY());
} else {
double oneFour = (window.getMaxY() - window.getMinY()) / 4d;
double maxY = window.getMaxY() - oneFour;
double minY = window.getMinY() + oneFour;
return new Envelope(window.getMinX(), window.getMaxX(), minY, maxY);
}
}
private Envelope rEnv() {
if (isVertical) {
double oneTwo = (window.getMaxX() - window.getMinX()) / 2d;
double maxX = window.getMaxX() - oneTwo;
double minX = window.getMinX();
return new Envelope(minX, window.getMinY(), maxX, window.getMaxY());
} else {
double oneTwo = (window.getMaxX() - window.getMinX()) / 2d;
double maxY = window.getMaxY() - oneTwo;
double minY = window.getMinY();
return new Envelope(window.getMinX(), window.getMaxX(), minY, maxY);
}
}
private Envelope lEnv() {
if (isVertical) {
double oneTwo = (window.getMaxX() - window.getMinX()) / 2d;
double maxX = window.getMaxX();
double minX = window.getMinX() + oneTwo;
return new Envelope(minX, window.getMinY(), maxX, window.getMaxY());
} else {
double oneTwo = (window.getMaxX() - window.getMinX()) / 2d;
double maxY = window.getMaxY();
double minY = window.getMinY() + oneTwo;
return new Envelope(window.getMinX(), window.getMaxX(), minY, maxY);
}
}
public Envelope getEnvelop() {
return window;
}
public List<Geometry> search(Envelope env) {
List<Geometry> geos = new ArrayList<Geometry>();
geos.addAll(geometrys);
if (middle != null) {
if (middle.getEnvelop().hasIntersect(env)) {
geos.addAll(middle.search(env));
} else if (right.getEnvelop().hasIntersect(env)) {
geos.addAll(right.search(env));
} else if (left.getEnvelop().hasIntersect(env)) {
geos.addAll(left.search(env));
}
}
return geos;
}
}