implement new version of vector index
git-svn-id: https://osmand.googlecode.com/svn/trunk@592 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
2176d32a00
commit
45b8c23ee8
46 changed files with 11252 additions and 265 deletions
|
@ -146,6 +146,43 @@ public class Algoritms {
|
|||
bytes[offset + 3] = (byte) (l & 0xff);
|
||||
}
|
||||
|
||||
|
||||
public static void writeLongInt(OutputStream stream, long l) throws IOException {
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
l >>= 8;
|
||||
stream.write((int) (l & 0xff));
|
||||
}
|
||||
|
||||
public static void writeInt(OutputStream stream, int l) throws IOException {
|
||||
stream.write(l & 0xff);
|
||||
l >>= 8;
|
||||
stream.write(l & 0xff);
|
||||
l >>= 8;
|
||||
stream.write(l & 0xff);
|
||||
l >>= 8;
|
||||
stream.write(l & 0xff);
|
||||
}
|
||||
|
||||
|
||||
public static void writeSmallInt(OutputStream stream, int l) throws IOException {
|
||||
stream.write(l & 0xff);
|
||||
l >>= 8;
|
||||
stream.write(l & 0xff);
|
||||
l >>= 8;
|
||||
}
|
||||
|
||||
public static int parseSmallIntFromBytes(byte[] bytes, int offset) {
|
||||
int s = (0xff & bytes[offset + 1]) << 8;
|
||||
s |= (0xff & bytes[offset + 0]);
|
||||
|
|
155
DataExtractionOSM/src/net/osmand/binary/BinaryIndexWriter.java
Normal file
155
DataExtractionOSM/src/net/osmand/binary/BinaryIndexWriter.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package net.osmand.binary;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Stack;
|
||||
|
||||
import net.osmand.data.index.IndexConstants;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import com.google.protobuf.WireFormat;
|
||||
import com.google.protobuf.WireFormat.JavaType;
|
||||
|
||||
public class BinaryIndexWriter {
|
||||
|
||||
private final OutputStream out;
|
||||
private CodedOutputStream codedOutStream;
|
||||
|
||||
private static class Bounds {
|
||||
public Bounds(int leftX, int rightX, int topY, int bottomY) {
|
||||
super();
|
||||
this.bottomY = bottomY;
|
||||
this.leftX = leftX;
|
||||
this.rightX = rightX;
|
||||
this.topY = topY;
|
||||
}
|
||||
int leftX = 0;
|
||||
int rightX = 0;
|
||||
int topY = 0;
|
||||
int bottomY = 0;
|
||||
|
||||
|
||||
}
|
||||
private Stack<Bounds> stackBounds = new Stack<Bounds>();
|
||||
|
||||
// internal constants to track state of index writing
|
||||
private Stack<Integer> state = new Stack<Integer>();
|
||||
private final static int OSMAND_STRUCTURE_INIT = 1;
|
||||
private final static int MAP_INDEX_INIT = 2;
|
||||
private final static int MAP_ROOT_LEVEL_INIT = 3;
|
||||
private final static int MAP_TREE = 4;
|
||||
private final static int MAP_DATA = 5;
|
||||
|
||||
public BinaryIndexWriter(OutputStream out) throws IOException{
|
||||
this.out = out;
|
||||
codedOutStream = CodedOutputStream.newInstance(out);
|
||||
codedOutStream.writeInt32(OsmandOdb.OsmAndStructure.VERSION_FIELD_NUMBER, IndexConstants.BINARY_MAP_VERSION);
|
||||
state.push(OSMAND_STRUCTURE_INIT);
|
||||
}
|
||||
// message MapTree {
|
||||
// required sint32 left = 1; // delta encoded
|
||||
// required sint32 right = 2; // delta encoded
|
||||
// required sint32 top = 3; // delta encoded
|
||||
// required sint32 bottom = 4; // delta encoded
|
||||
//
|
||||
// optional StringTable stringTable = 5;
|
||||
// optional uint64 baseId = 6;
|
||||
//
|
||||
// repeated MapTree subtrees = 7;
|
||||
// repeated MapData leafs = 8;
|
||||
//
|
||||
// }
|
||||
// /// Simple messages
|
||||
// message MapData {
|
||||
// required bytes coordinates = 1; // array of delta x,y uin32 could be read by codedinputstream
|
||||
// repeated sint32 types = 2;
|
||||
//
|
||||
// required sint64 id = 3; // delta encoded
|
||||
// optional uint32 stringId = 4;
|
||||
//
|
||||
// repeated sint64 restrictions = 5; // delta encoded 3 bytes for type and other for id
|
||||
// }
|
||||
|
||||
public void startWriteMapIndex() throws IOException{
|
||||
assert state.peek() == OSMAND_STRUCTURE_INIT;
|
||||
state.push(MAP_INDEX_INIT);
|
||||
codedOutStream.writeTag(OsmandOdb.OsmAndStructure.MAPINDEX_FIELD_NUMBER, WireFormat.FieldType.MESSAGE.getWireType());
|
||||
// TODO write size of map index
|
||||
codedOutStream.writeFixed32NoTag(0);
|
||||
|
||||
}
|
||||
|
||||
public void endWriteMapIndex() throws IOException{
|
||||
Integer st = state.pop();
|
||||
assert st == MAP_INDEX_INIT;
|
||||
codedOutStream.writeRawVarint32(0);
|
||||
}
|
||||
|
||||
public void startWriteMapLevelIndex(int maxZoom, int minZoom, int leftX, int rightX, int topY, int bottomY) throws IOException{
|
||||
assert state.peek() == MAP_INDEX_INIT;
|
||||
state.push(MAP_ROOT_LEVEL_INIT);
|
||||
|
||||
codedOutStream.writeTag(OsmandOdb.OsmAndMapIndex.LEVELS_FIELD_NUMBER, WireFormat.FieldType.MESSAGE.getWireType());
|
||||
// TODO write size of level map index
|
||||
codedOutStream.writeFixed32NoTag(0);
|
||||
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.MAXZOOM_FIELD_NUMBER, maxZoom);
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.MINZOOM_FIELD_NUMBER, minZoom);
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.LEFT_FIELD_NUMBER, leftX);
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.RIGHT_FIELD_NUMBER, rightX);
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.TOP_FIELD_NUMBER, topY);
|
||||
codedOutStream.writeInt32(OsmandOdb.MapRootLevel.BOTTOM_FIELD_NUMBER, bottomY);
|
||||
|
||||
stackBounds.push(new Bounds(leftX, rightX, topY, bottomY));
|
||||
}
|
||||
|
||||
public void endWriteMapLevelIndex() throws IOException{
|
||||
assert state.peek() == MAP_ROOT_LEVEL_INIT;
|
||||
state.pop();
|
||||
|
||||
stackBounds.pop();
|
||||
codedOutStream.writeRawVarint32(0);
|
||||
}
|
||||
|
||||
public void startMapTreeElement(int leftX, int rightX, int topY, int bottomY) throws IOException{
|
||||
assert state.peek() == MAP_ROOT_LEVEL_INIT || state.peek() == MAP_TREE;
|
||||
if(state.peek() == MAP_ROOT_LEVEL_INIT){
|
||||
codedOutStream.writeTag(OsmandOdb.MapRootLevel.ROOT_FIELD_NUMBER, WireFormat.FieldType.MESSAGE.getWireType());
|
||||
} else {
|
||||
codedOutStream.writeTag(OsmandOdb.MapTree.SUBTREES_FIELD_NUMBER, WireFormat.FieldType.MESSAGE.getWireType());
|
||||
}
|
||||
// TODO write size of level map index
|
||||
codedOutStream.writeFixed32NoTag(0);
|
||||
state.push(MAP_TREE);
|
||||
|
||||
|
||||
Bounds bounds = stackBounds.peek();
|
||||
codedOutStream.writeSInt32(OsmandOdb.MapTree.LEFT_FIELD_NUMBER, leftX - bounds.leftX);
|
||||
codedOutStream.writeSInt32(OsmandOdb.MapTree.RIGHT_FIELD_NUMBER, rightX - bounds.rightX);
|
||||
codedOutStream.writeSInt32(OsmandOdb.MapTree.TOP_FIELD_NUMBER, topY - bounds.topY);
|
||||
codedOutStream.writeSInt32(OsmandOdb.MapTree.BOTTOM_FIELD_NUMBER, bottomY - bounds.bottomY);
|
||||
stackBounds.push(new Bounds(leftX, rightX, topY, bottomY));
|
||||
|
||||
}
|
||||
|
||||
public void endWriteMapTreeElement() throws IOException{
|
||||
assert state.peek() == MAP_TREE;
|
||||
state.pop();
|
||||
|
||||
stackBounds.pop();
|
||||
}
|
||||
|
||||
public void writeMapData(long id) throws IOException{
|
||||
assert state.peek() == MAP_TREE;
|
||||
// TODO
|
||||
codedOutStream.writeInt64NoTag(id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void close() throws IOException{
|
||||
assert state.peek() == OSMAND_STRUCTURE_INIT;
|
||||
codedOutStream.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
2928
DataExtractionOSM/src/net/osmand/binary/OsmandOdb.java
Normal file
2928
DataExtractionOSM/src/net/osmand/binary/OsmandOdb.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,6 @@
|
|||
package net.osmand.data.index;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
@ -19,6 +20,7 @@ import net.osmand.data.City;
|
|||
import net.osmand.data.TransportRoute;
|
||||
import net.osmand.data.TransportStop;
|
||||
import net.osmand.data.City.CityType;
|
||||
import net.osmand.data.index.IndexConstants.IndexBinaryMapRenderObject;
|
||||
import net.osmand.data.index.IndexConstants.IndexBuildingTable;
|
||||
import net.osmand.data.index.IndexConstants.IndexCityTable;
|
||||
import net.osmand.data.index.IndexConstants.IndexMapRenderObject;
|
||||
|
@ -34,6 +36,11 @@ import net.osmand.osm.MapUtils;
|
|||
import net.osmand.osm.Node;
|
||||
import net.osmand.osm.Relation;
|
||||
import net.osmand.osm.Way;
|
||||
import rtree.IllegalValueException;
|
||||
import rtree.LeafElement;
|
||||
import rtree.RTree;
|
||||
import rtree.RTreeInsertException;
|
||||
import rtree.Rect;
|
||||
|
||||
|
||||
|
||||
|
@ -185,6 +192,8 @@ public class DataIndexWriter {
|
|||
Statement stat = conn.createStatement();
|
||||
stat.execute(IndexConstants.generateCreateSQL(IndexMapRenderObject.values()));
|
||||
stat.execute(IndexConstants.generateCreateIndexSQL(IndexMapRenderObject.values()));
|
||||
stat.execute(IndexConstants.generateCreateSQL(IndexBinaryMapRenderObject.values()));
|
||||
stat.execute(IndexConstants.generateCreateIndexSQL(IndexBinaryMapRenderObject.values()));
|
||||
stat.execute("CREATE VIRTUAL TABLE "+IndexConstants.indexMapLocationsTable+" USING rtree (id, minLon, maxLon, minLat, maxLat);"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
stat.execute("CREATE VIRTUAL TABLE "+IndexConstants.indexMapLocationsTable2+" USING rtree (id, minLon, maxLon, minLat, maxLat);"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
stat.execute("CREATE VIRTUAL TABLE "+IndexConstants.indexMapLocationsTable3+" USING rtree (id, minLon, maxLon, minLat, maxLat);"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
@ -196,6 +205,11 @@ public class DataIndexWriter {
|
|||
assert IndexMapRenderObject.values().length == 4;
|
||||
return conn.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexMapRenderObject.getTable(), 4));
|
||||
}
|
||||
|
||||
public static PreparedStatement createStatementMapBinaryInsert(Connection conn) throws SQLException{
|
||||
assert IndexBinaryMapRenderObject.values().length == 5;
|
||||
return conn.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexBinaryMapRenderObject.getTable(), 5));
|
||||
}
|
||||
public static PreparedStatement createStatementMapWaysLocationsInsert(Connection conn) throws SQLException{
|
||||
return conn.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexConstants.indexMapLocationsTable, 5));
|
||||
}
|
||||
|
@ -207,8 +221,10 @@ public class DataIndexWriter {
|
|||
return conn.prepareStatement(IndexConstants.generatePrepareStatementToInsert(IndexConstants.indexMapLocationsTable3, 5));
|
||||
}
|
||||
|
||||
|
||||
public static void insertMapRenderObjectIndex(Map<PreparedStatement, Integer> statements,
|
||||
PreparedStatement mapStat, PreparedStatement mapWayLocationsStat, /*RTree mapTree, */Entity e, String name,
|
||||
PreparedStatement mapStat, PreparedStatement mapWayLocationsStat,
|
||||
RTree mapTree, Entity e, String name,
|
||||
long id, int type, List<Integer> typeUse, List<Long> restrictions, boolean writeRestrictions,
|
||||
boolean inversePath, boolean writeAsPoint, int batchSize) throws SQLException {
|
||||
assert IndexMapRenderObject.values().length == 4;
|
||||
|
@ -270,7 +286,9 @@ public class DataIndexWriter {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
ByteArrayOutputStream bnodes = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream btypes = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream brestrictions = new ByteArrayOutputStream();
|
||||
for (Node n : nodes) {
|
||||
if (n != null) {
|
||||
int y = MapUtils.get31TileNumberY(n.getLatitude());
|
||||
|
@ -288,25 +306,27 @@ public class DataIndexWriter {
|
|||
offset += 4;
|
||||
Algoritms.putIntToBytes(bytes, offset, x);
|
||||
offset += 4;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
if (init) {
|
||||
|
||||
|
||||
mapStat.setLong(IndexMapRenderObject.ID.ordinal() + 1, id);
|
||||
mapStat.setInt(IndexMapRenderObject.TYPE.ordinal() + 1, type);
|
||||
mapStat.setString(IndexMapRenderObject.NAME.ordinal() + 1, name);
|
||||
mapStat.setBytes(IndexMapRenderObject.NODES.ordinal() + 1, bytes);
|
||||
addBatch(statements, mapStat);
|
||||
|
||||
//
|
||||
// try {
|
||||
// mapTree.insert(new LeafElement(new Rect(minX, minY, maxX, maxY), id));
|
||||
// } catch (RTreeInsertException e1) {
|
||||
// // TODO
|
||||
// e1.printStackTrace();
|
||||
// } catch (IllegalValueException e1) {
|
||||
// // TODO
|
||||
// e1.printStackTrace();
|
||||
// }
|
||||
|
||||
try {
|
||||
mapTree.insert(new LeafElement(new Rect(minX, minY, maxX, maxY), id));
|
||||
} catch (RTreeInsertException e1) {
|
||||
throw new IllegalArgumentException(e1);
|
||||
} catch (IllegalValueException e1) {
|
||||
throw new IllegalArgumentException(e1);
|
||||
}
|
||||
|
||||
mapWayLocationsStat.setLong(1, id);
|
||||
mapWayLocationsStat.setFloat(2, (float) minLon);
|
||||
|
|
|
@ -8,6 +8,7 @@ public class IndexConstants {
|
|||
public final static int POI_TABLE_VERSION = 0;
|
||||
public final static int ADDRESS_TABLE_VERSION = 1;
|
||||
public final static int MAP_TABLE_VERSION = 0;
|
||||
public final static int BINARY_MAP_VERSION = 0;
|
||||
public final static int VOICE_VERSION = 0;
|
||||
|
||||
|
||||
|
@ -20,6 +21,7 @@ public class IndexConstants {
|
|||
public static final String ADDRESS_INDEX_EXT = ".addr.odb"; //$NON-NLS-1$
|
||||
public static final String TRANSPORT_INDEX_EXT = ".trans.odb"; //$NON-NLS-1$
|
||||
public static final String MAP_INDEX_EXT = ".map.odb"; //$NON-NLS-1$
|
||||
public static final String BINARY_MAP_INDEX_EXT = ".map.pbf"; //$NON-NLS-1$
|
||||
|
||||
public static final String POI_INDEX_EXT_ZIP = ".poi.zip"; //$NON-NLS-1$
|
||||
public static final String ADDRESS_INDEX_EXT_ZIP = ".addr.zip"; //$NON-NLS-1$
|
||||
|
@ -451,4 +453,41 @@ public class IndexConstants {
|
|||
}
|
||||
}
|
||||
|
||||
public enum IndexBinaryMapRenderObject implements IndexColumn {
|
||||
ID("long", true), NAME, TYPES("BLOB"), RESTRICTIONS("BLOB"), NODES("BLOB"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
boolean index = false;
|
||||
String type = null;
|
||||
|
||||
private IndexBinaryMapRenderObject() {
|
||||
}
|
||||
|
||||
private IndexBinaryMapRenderObject(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private IndexBinaryMapRenderObject(String type, boolean index) {
|
||||
this(type);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public static String getTable() {
|
||||
return "binary_map_objects"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return getTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.awt.geom.Line2D;
|
|||
import java.awt.geom.Point2D;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.Connection;
|
||||
|
@ -26,6 +27,7 @@ import java.util.Map.Entry;
|
|||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.binary.BinaryIndexWriter;
|
||||
import net.osmand.data.Amenity;
|
||||
import net.osmand.data.Building;
|
||||
import net.osmand.data.City;
|
||||
|
@ -64,6 +66,15 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.apache.tools.bzip2.CBZip2InputStream;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import rtree.Element;
|
||||
import rtree.IllegalValueException;
|
||||
import rtree.LeafElement;
|
||||
import rtree.NonLeafElement;
|
||||
import rtree.Pack;
|
||||
import rtree.RTree;
|
||||
import rtree.RTreeException;
|
||||
import rtree.Rect;
|
||||
|
||||
|
||||
/**
|
||||
* http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing#Is_inside.2Foutside
|
||||
|
@ -101,6 +112,7 @@ public class IndexCreator {
|
|||
private String poiFileName = null;
|
||||
private String addressFileName = null;
|
||||
private String mapFileName = null;
|
||||
private String binaryMapFileName = null;
|
||||
private Long lastModifiedDate = null;
|
||||
|
||||
|
||||
|
@ -139,7 +151,9 @@ public class IndexCreator {
|
|||
private PreparedStatement mapLocsStatLevel0;
|
||||
private PreparedStatement mapLocsStatLevel1;
|
||||
private PreparedStatement mapLocsStatLevel2;
|
||||
// private RTree mapTree;
|
||||
private RTree mapTree;
|
||||
|
||||
private File binaryMapFile;
|
||||
|
||||
// MEMORY map : save it in memory while that is allowed
|
||||
private Map<Long, Set<Integer>> multiPolygonsWays0 = new LinkedHashMap<Long, Set<Integer>>();
|
||||
|
@ -147,8 +161,6 @@ public class IndexCreator {
|
|||
private Map<Long, Set<Integer>> multiPolygonsWays2 = new LinkedHashMap<Long, Set<Integer>>();
|
||||
private Map<Long, String> multiPolygonsNames = new LinkedHashMap<Long, String>();
|
||||
private Map<Long, List<Long>> highwayRestrictions = new LinkedHashMap<Long, List<Long>>();
|
||||
private Map<Long, List<Way>> lowLevelWaysSt = new LinkedHashMap<Long, List<Way>>();
|
||||
private Map<Long, List<Way>> lowLevelWaysEnd = new LinkedHashMap<Long, List<Way>>();
|
||||
|
||||
|
||||
// MEMORY address : choose what to use ?
|
||||
|
@ -460,6 +472,16 @@ public class IndexCreator {
|
|||
return mapFileName;
|
||||
}
|
||||
|
||||
public void setBinaryMapFileName(String mapFileName) {
|
||||
this.binaryMapFileName = mapFileName;
|
||||
}
|
||||
public String getBinaryMapFileName(){
|
||||
if(binaryMapFileName == null){
|
||||
return getRegionName() + IndexConstants.BINARY_MAP_INDEX_EXT;
|
||||
}
|
||||
return binaryMapFileName;
|
||||
}
|
||||
|
||||
public String getTransportFileName() {
|
||||
if(transportFileName == null){
|
||||
return IndexConstants.TRANSPORT_INDEX_DIR + getRegionName() + IndexConstants.TRANSPORT_INDEX_EXT;
|
||||
|
@ -960,11 +982,9 @@ public class IndexCreator {
|
|||
// manipulate what kind of way to load
|
||||
loadEntityData(e, true);
|
||||
boolean inverse = "-1".equals(e.getTag(OSMTagKey.ONEWAY));
|
||||
writeEntityToMapDatabase(e, e.getId(), inverse, 0);
|
||||
writeEntityToMapDatabase(e, e.getId(), false, 1);
|
||||
writeEntityToMapDatabase(e, e.getId(), false, 2);
|
||||
// indexLowLevelMap(e, 1);
|
||||
// indexLowLevelMap(e, 2);
|
||||
writeBinaryEntityToMapDatabase(e, e.getId(), inverse, 0);
|
||||
writeBinaryEntityToMapDatabase(e, e.getId(), false, 1);
|
||||
writeBinaryEntityToMapDatabase(e, e.getId(), false, 2);
|
||||
}
|
||||
|
||||
if (indexAddress) {
|
||||
|
@ -1191,11 +1211,8 @@ public class IndexCreator {
|
|||
int t = MapRenderingTypes.encodeEntityWithType(e, level, true, typeUse);
|
||||
int mtType = 0;
|
||||
if (t != 0) {
|
||||
if (((t >> 1) & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
|
||||
// last bit is used for direction
|
||||
mtType = (t >> 1) & 0x7fff;
|
||||
} else if (((t >> 16) & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE && (t >> 16) != 0) {
|
||||
mtType = t >> 16;
|
||||
if ((t & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
|
||||
mtType = t;
|
||||
} else {
|
||||
for (Integer i : typeUse) {
|
||||
if ((i & 3) == MapRenderingTypes.MULTY_POLYGON_TYPE) {
|
||||
|
@ -1321,128 +1338,129 @@ public class IndexCreator {
|
|||
}
|
||||
|
||||
|
||||
private <T, R> void putIntoMap(Map<T, List<R>> map, T key, R value){
|
||||
if(!map.containsKey(key)){
|
||||
map.put(key, new ArrayList<R>());
|
||||
}
|
||||
map.get(key).add(value);
|
||||
}
|
||||
|
||||
private <T, R> void removeValueMap(Map<T, List<R>> map, T key, R value){
|
||||
boolean remove = map.get(key).remove(value);
|
||||
if(!remove){
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if(map.get(key).isEmpty()){
|
||||
map.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO do not use that method
|
||||
@SuppressWarnings("unused")
|
||||
private void indexLowLevelMap(Entity e, int level) throws SQLException{
|
||||
private void writeBinaryEntityToMapDatabase(Entity e, long baseId, boolean inverse, int level) throws SQLException {
|
||||
int type = MapRenderingTypes.encodeEntityWithType(e, level, false, typeUse);
|
||||
// TODO that is not correct because multiPolygonsWays contains types for level 0
|
||||
// TODO that method should be redesigned (!!!) to support multipolygon types and multipolygon names
|
||||
// if(type == 0 && multiPolygonsWays.containsKey(e.getId())){
|
||||
// type = multiPolygonsWays.get(e.getId()).iterator().next();
|
||||
// }
|
||||
if(type == 0){
|
||||
return;
|
||||
Map<Long, Set<Integer>> multiPolygonsWays;
|
||||
if (level == 0) {
|
||||
multiPolygonsWays = multiPolygonsWays0;
|
||||
} else if (level == 1) {
|
||||
multiPolygonsWays = multiPolygonsWays1;
|
||||
} else if (level == 2) {
|
||||
multiPolygonsWays = multiPolygonsWays2;
|
||||
} else {
|
||||
multiPolygonsWays = Collections.emptyMap();
|
||||
}
|
||||
boolean writeIntoDB = true;
|
||||
boolean ring = true;
|
||||
if(e instanceof Way && level > 0){
|
||||
List<Node> nodes = ((Way) e).getNodes();
|
||||
Node n = nodes.get(0);
|
||||
Node l = nodes.get(nodes.size() - 1);
|
||||
// ring
|
||||
ring = l.getId() == n.getId();
|
||||
if (!ring) {
|
||||
writeIntoDB = false;
|
||||
Way start = null;
|
||||
if (lowLevelWaysEnd.containsKey(n.getId())) {
|
||||
for (Way w : lowLevelWaysEnd.get(n.getId())) {
|
||||
int t = MapRenderingTypes.encodeEntityWithType(w, level, false, typeUse);
|
||||
if (t == type && Algoritms.objectEquals(MapRenderingTypes.getEntityName(w, t),
|
||||
MapRenderingTypes.getEntityName(e, t))) {
|
||||
start = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start != null) {
|
||||
ring = start.getNodeIds().get(0) == l.getId();
|
||||
if(ring){
|
||||
removeValueMap(lowLevelWaysEnd, n.getId(), start);
|
||||
removeValueMap(lowLevelWaysSt, l.getId(), start);
|
||||
} else {
|
||||
// add nodes to start
|
||||
for (int i = 1; i < nodes.size(); i++) {
|
||||
start.addNode(nodes.get(i));
|
||||
}
|
||||
removeValueMap(lowLevelWaysEnd, n.getId(), start);
|
||||
putIntoMap(lowLevelWaysEnd, l.getId(), start);
|
||||
}
|
||||
boolean hasMulti = e instanceof Way && multiPolygonsWays.containsKey(e.getId());
|
||||
if (hasMulti) {
|
||||
Set<Integer> set = multiPolygonsWays.get(e.getId());
|
||||
boolean first = true;
|
||||
for (Integer i : set) {
|
||||
if (first && type == 0) {
|
||||
type = i;
|
||||
first = false;
|
||||
} else {
|
||||
long tempId = (e.getId() << 2) | level;
|
||||
start = new Way(tempId);
|
||||
for(String t : e.getTagKeySet()){
|
||||
start.putTag(t, e.getTag(t));
|
||||
}
|
||||
// add nodes to start
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
start.addNode(nodes.get(i));
|
||||
}
|
||||
|
||||
putIntoMap(lowLevelWaysSt, n.getId(), start);
|
||||
putIntoMap(lowLevelWaysEnd, l.getId(), start);
|
||||
}
|
||||
|
||||
if (!ring) {
|
||||
Way end = null;
|
||||
if (lowLevelWaysSt.containsKey(l.getId())) {
|
||||
for (Way w : lowLevelWaysSt.get(l.getId())) {
|
||||
int t = MapRenderingTypes.encodeEntityWithType(w, level, false, typeUse);
|
||||
if (t == type && Algoritms.objectEquals(MapRenderingTypes.getEntityName(w, t),
|
||||
MapRenderingTypes.getEntityName(e, t))) {
|
||||
end = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end != null) {
|
||||
Long ll = end.getNodeIds().get(end.getNodeIds().size() - 1);
|
||||
// remove end line
|
||||
removeValueMap(lowLevelWaysSt, l.getId(), end);
|
||||
removeValueMap(lowLevelWaysEnd, ll, end);
|
||||
ring = ll == n.getId();
|
||||
|
||||
if (!ring) {
|
||||
|
||||
// add nodes to start
|
||||
for (int i = 1; i < end.getNodes().size(); i++) {
|
||||
start.addNode(end.getNodes().get(i));
|
||||
}
|
||||
|
||||
// remove end start
|
||||
removeValueMap(lowLevelWaysEnd, l.getId(), start);
|
||||
putIntoMap(lowLevelWaysEnd, ll, start);
|
||||
// do not compare direction
|
||||
int k = i & 0x7fff;
|
||||
int ks = k | MapRenderingTypes.POLYGON_TYPE;
|
||||
// turn of polygon type 3 ^ (suppose polygon = multipolygon)
|
||||
if (ks == type) {
|
||||
type = i;
|
||||
} else {
|
||||
int ind = typeUse.indexOf(ks);
|
||||
if (ind == -1) {
|
||||
typeUse.add(i);
|
||||
} else {
|
||||
typeUse.set(ind, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(writeIntoDB || ring){
|
||||
writeEntityToMapDatabase(e, e.getId(), false, level);
|
||||
if (type == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean useRestrictions = false;
|
||||
restrictionsUse.clear();
|
||||
if (MapRenderingTypes.isHighwayType(type >> 1)) {
|
||||
useRestrictions = true;
|
||||
// try to find restrictions only for max zoom level
|
||||
if (level == 0 && highwayRestrictions.containsKey(baseId)) {
|
||||
restrictionsUse.addAll(highwayRestrictions.get(baseId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean point = ((type >> 1) & 3) == MapRenderingTypes.POINT_TYPE;
|
||||
PreparedStatement mapLocations;
|
||||
int zoom;
|
||||
long id = baseId << 3;
|
||||
if (level == 1) {
|
||||
id |= 2;
|
||||
mapLocations = mapLocsStatLevel1;
|
||||
zoom = 12;
|
||||
} else if (level == 2) {
|
||||
id |= 4;
|
||||
zoom = 7;
|
||||
mapLocations = mapLocsStatLevel2;
|
||||
} else {
|
||||
zoom = 18;
|
||||
mapLocations = mapLocsStatLevel0;
|
||||
}
|
||||
boolean skip = false;
|
||||
if (e instanceof Way) {
|
||||
id |= 1;
|
||||
// simplify route
|
||||
if (level > 0) {
|
||||
List<Node> nodes = ((Way) e).getNodes();
|
||||
Way way = new Way(id);
|
||||
for (String t : e.getTagKeySet()) {
|
||||
way.putTag(t, e.getTag(t));
|
||||
}
|
||||
int prevX = 0;
|
||||
int prevY = 0;
|
||||
int len = 0;
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
// do not simplify last node it could be important node for multipolygon
|
||||
if (nodes.get(i) != null) {
|
||||
int r = i < nodes.size() - 1 ? 4 : 0;
|
||||
int x = (int) (MapUtils.getTileNumberX(zoom, nodes.get(i).getLongitude()) * 256d);
|
||||
int y = (int) (MapUtils.getTileNumberY(zoom, nodes.get(i).getLatitude()) * 256d);
|
||||
int dy = Math.abs(y - prevY);
|
||||
int dx = Math.abs(x - prevX);
|
||||
if (dx > r || dy > r) {
|
||||
way.addNode(nodes.get(i));
|
||||
len += (dx + dy);
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
e = way;
|
||||
skip = way.getNodes().size() < 2;
|
||||
if (!hasMulti && len < 8) {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
String eName = MapRenderingTypes.getEntityName(e, type);
|
||||
if (eName == null) {
|
||||
eName = multiPolygonsNames.get(baseId);
|
||||
}
|
||||
DataIndexWriter.insertMapRenderObjectIndex(pStatements, mapObjStat, mapLocations, mapTree, e, eName, id, type, typeUse,
|
||||
restrictionsUse, useRestrictions, inverse, point, BATCH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void writeEntityToMapDatabase(Entity e, long baseId, boolean inverse, int level) throws SQLException {
|
||||
|
||||
/*private void writeEntityToMapDatabase(Entity e, long baseId, boolean inverse, int level) throws SQLException {
|
||||
int type = MapRenderingTypes.encodeEntityWithType(e, level, false, typeUse);
|
||||
Map<Long, Set<Integer>> multiPolygonsWays;
|
||||
if(level == 0){
|
||||
|
@ -1569,12 +1587,69 @@ public class IndexCreator {
|
|||
if(eName == null ){
|
||||
eName = multiPolygonsNames.get(baseId);
|
||||
}
|
||||
DataIndexWriter.insertMapRenderObjectIndex(pStatements, mapObjStat, mapLocations, /*mapTree, */e,
|
||||
DataIndexWriter.insertMapRenderObjectIndex(pStatements, mapObjStat, mapLocations, mapTree, e,
|
||||
eName, id, type, typeUse, restrictionsUse, useRestrictions,
|
||||
inverse, point, BATCH_SIZE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public void writeBinaryData(RTree rtree) throws IOException {
|
||||
try {
|
||||
long rootIndex = rtree.getFileHdr().getRootIndex();
|
||||
binaryMapFile = new File(workingDir, getBinaryMapFileName());
|
||||
FileOutputStream fout = new FileOutputStream(binaryMapFile);
|
||||
BinaryIndexWriter writer = new BinaryIndexWriter(fout);
|
||||
writer.startWriteMapIndex();
|
||||
rtree.Node root = rtree.getReadNode(rootIndex);
|
||||
Rect rootBounds = calcBounds(root);
|
||||
writer.startWriteMapLevelIndex(6, 17, rootBounds.getMinX(), rootBounds.getMaxX(), rootBounds.getMinY(), rootBounds.getMaxY());
|
||||
|
||||
writeBinaryMapTree(root, rtree, writer);
|
||||
|
||||
writer.endWriteMapLevelIndex();
|
||||
writer.endWriteMapIndex();
|
||||
writer.close();
|
||||
} catch (RTreeException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeBinaryMapTree(rtree.Node parent, RTree r, BinaryIndexWriter writer) throws IOException, RTreeException {
|
||||
Element[] e = parent.getAllElements();
|
||||
for (int i = 0; i < parent.getTotalElements(); i++) {
|
||||
Rect re = e[i].getRect();
|
||||
if(e[i].getElementType() == rtree.Node.LEAF_NODE){
|
||||
// TODO
|
||||
long ptr = ((LeafElement) e[i]).getPtr();
|
||||
writer.writeMapData(ptr);
|
||||
} else {
|
||||
long ptr = ((NonLeafElement) e[i]).getPtr();
|
||||
writer.startMapTreeElement(re.getMinX(), re.getMaxX(), re.getMinY(), re.getMaxY());
|
||||
rtree.Node ns = r.getReadNode(ptr);
|
||||
writeBinaryMapTree(ns, r, writer);
|
||||
writer.endWriteMapTreeElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Rect calcBounds(rtree.Node n) {
|
||||
Rect r = null;
|
||||
Element[] e = n.getAllElements();
|
||||
for (int i = 0; i < n.getTotalElements(); i++) {
|
||||
Rect re = e[i].getRect();
|
||||
if (r == null) {
|
||||
try {
|
||||
r = new Rect(re.getMinX(), re.getMinY(), re.getMaxX(), re.getMaxY());
|
||||
} catch (IllegalValueException ex) {
|
||||
}
|
||||
} else {
|
||||
r.expandToInclude(re);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1585,6 +1660,15 @@ public class IndexCreator {
|
|||
}
|
||||
}
|
||||
|
||||
public String getRTreeMapIndexNonPackFileName(){
|
||||
return mapFile.getAbsolutePath()+".rtree";
|
||||
}
|
||||
|
||||
public String getRTreeMapIndexPackFileName(){
|
||||
return mapFile.getAbsolutePath()+".prtree";
|
||||
}
|
||||
|
||||
|
||||
public void generateIndexes(File readFile, IProgress progress, IOsmStorageFilter addFilter) throws IOException, SAXException,
|
||||
SQLException {
|
||||
if (readFile != null && regionName == null) {
|
||||
|
@ -1696,11 +1780,15 @@ public class IndexCreator {
|
|||
mapLocsStatLevel0 = DataIndexWriter.createStatementMapWaysLocationsInsert(mapConnection);
|
||||
mapLocsStatLevel1 = DataIndexWriter.createStatementMapWaysLocationsInsertLevel2(mapConnection);
|
||||
mapLocsStatLevel2 = DataIndexWriter.createStatementMapWaysLocationsInsertLevel3(mapConnection);
|
||||
// try {
|
||||
// mapTree = new RTree(mapFile.getAbsolutePath()+"_ind");
|
||||
// } catch (RTreeException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
try {
|
||||
File file = new File(getRTreeMapIndexNonPackFileName());
|
||||
if(file.exists()){
|
||||
file.delete();
|
||||
}
|
||||
mapTree = new RTree(getRTreeMapIndexNonPackFileName());
|
||||
} catch (RTreeException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
pStatements.put(mapObjStat, 0);
|
||||
pStatements.put(mapLocsStatLevel0, 0);
|
||||
pStatements.put(mapLocsStatLevel1, 0);
|
||||
|
@ -1856,19 +1944,29 @@ public class IndexCreator {
|
|||
}
|
||||
|
||||
}
|
||||
// 5. writing low level maps
|
||||
progress.setGeneralProgress("[95 of 100]");
|
||||
progress.startTask("Indexing low levels for map ...", -1);
|
||||
|
||||
// 5. writing map index
|
||||
if (indexMap) {
|
||||
for (Long l : lowLevelWaysSt.keySet()) {
|
||||
for (Way w : lowLevelWaysSt.get(l)) {
|
||||
int level = (int) (w.getId() & 3);
|
||||
writeEntityToMapDatabase(w, w.getId() >> 2, false, level);
|
||||
}
|
||||
progress.setGeneralProgress("[95 of 100]");
|
||||
progress.startTask("Serializing map data...", -1);
|
||||
try {
|
||||
mapTree.flush();
|
||||
} catch (RTreeException e) {
|
||||
log.error("Error flushing", e);
|
||||
}
|
||||
File file = new File(getRTreeMapIndexPackFileName());
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
new Pack().packTree(mapTree, getRTreeMapIndexPackFileName());
|
||||
mapTree = null;
|
||||
// TODO !!! create binary output stream in order to close it properly (finally)
|
||||
writeBinaryData(new RTree(getRTreeMapIndexPackFileName()));
|
||||
|
||||
}
|
||||
|
||||
} catch (RTreeException e) {
|
||||
throw new IOException(e);
|
||||
} finally {
|
||||
try {
|
||||
if (pselectNode != null) {
|
||||
|
@ -1911,17 +2009,17 @@ public class IndexCreator {
|
|||
mapConnection.commit();
|
||||
mapConnection.close();
|
||||
mapConnection = null;
|
||||
// try {
|
||||
// mapTree.flush();
|
||||
// } catch (RTreeException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
|
||||
if (lastModifiedDate != null) {
|
||||
mapFile.setLastModified(lastModifiedDate);
|
||||
}
|
||||
}
|
||||
if(mapTree != null){
|
||||
try {
|
||||
mapTree.flush();
|
||||
} catch (RTreeException e) {
|
||||
log.error("Error flushing", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (addressConnection != null) {
|
||||
addressConnection.commit();
|
||||
|
@ -1954,15 +2052,15 @@ public class IndexCreator {
|
|||
public static void main(String[] args) throws IOException, SAXException, SQLException {
|
||||
|
||||
IndexCreator creator = new IndexCreator(new File("e:/Information/OSM maps/osmand/"));
|
||||
// creator.setIndexMap(true);
|
||||
creator.setIndexMap(true);
|
||||
// creator.setIndexPOI(true);
|
||||
creator.setIndexTransport(true);
|
||||
// creator.setIndexTransport(true);
|
||||
|
||||
// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/minsk.tmp.odb"));
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/minsk.osm"), new ConsoleProgressImplementation(3), null);
|
||||
creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/minsk.tmp.odb"));
|
||||
creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/minsk.osm"), new ConsoleProgressImplementation(3), null);
|
||||
|
||||
creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/belarus_nodes.tmp.odb"));
|
||||
creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/belarus.osm.bz2"), new ConsoleProgressImplementation(3), null);
|
||||
// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/belarus_nodes.tmp.odb"));
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/belarus osm/belarus.osm.bz2"), new ConsoleProgressImplementation(3), null);
|
||||
|
||||
// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/ams.tmp.odb"));
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/ams_part_map.osm"), new ConsoleProgressImplementation(3), null);
|
||||
|
@ -1970,70 +2068,13 @@ public class IndexCreator {
|
|||
// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/den_haag.tmp.odb"));
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/den_haag.osm"), new ConsoleProgressImplementation(3), null);
|
||||
|
||||
// creator.setNodesDBFile(new File("e:/Information/OSM maps/osmand/netherlands.tmp.odb"));
|
||||
// creator.setNodesk(new File("e:/Information/OSM maps/osmand/netherlands.tmp.odb"));
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/netherlands.osm.bz2"), new ConsoleProgressImplementation(1), null);
|
||||
|
||||
// creator.generateIndexes(new File("e:/Information/OSM maps/osm_map/forest_complex.osm"), new ConsoleProgressImplementation(25), null);
|
||||
/*try {
|
||||
// RTree rtree = new RTree("e:/Information/OSM maps/osmand/Belarus_2010_09_03.map.odb_ind");
|
||||
// new Pack().packTree(rtree, "e:/Information/OSM maps/osmand/pack.ind");
|
||||
RTree rtree = new RTree("e:/Information/OSM maps/osmand/pack.ind");
|
||||
long rootIndex = rtree.getFileHdr().getRootIndex();
|
||||
int s = calculateSize(rtree.getReadNode(rootIndex), rtree, "!-");
|
||||
System.out.println(s);
|
||||
} catch (RTreeException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// download base
|
||||
/* MapTileDownloader instance = MapTileDownloader.getInstance();
|
||||
instance.addDownloaderCallback(new MapTileDownloader.IMapDownloaderCallback() {
|
||||
@Override
|
||||
public void tileDownloaded(DownloadRequest request) {
|
||||
System.out.println(request.url);
|
||||
}
|
||||
|
||||
});
|
||||
File baseDir = new File("e:/Information/OSM maps/planet_tiles");
|
||||
baseDir.mkdirs();
|
||||
TileSourceTemplate map = TileSourceManager.getMapnikSource();
|
||||
for (int zoom = 5; zoom <= 5; zoom++) {
|
||||
int length = 1 << zoom;
|
||||
for (int x = 0; x < length; x++) {
|
||||
for (int y = 0; y < length; y++) {
|
||||
String file = zoom + "/" + (x) + "/" + y + map.getTileFormat() + ".tile";
|
||||
DownloadRequest req = new DownloadRequest(map.getUrlToLoad(x, y, zoom), new File(baseDir, file), x, y, zoom);
|
||||
instance.requestToDownload(req);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
/*
|
||||
public static int calculateSize(rtree.Node n, RTree r, String level){
|
||||
Element[] e = n.getAllElements();
|
||||
int exc = 0; //20 + (169 - n.getTotalElements()) * 24;
|
||||
for(int i=0; i< n.getTotalElements(); i++){
|
||||
if(e[i].getElementType() == rtree.Node.LEAF_NODE){
|
||||
exc += 1;
|
||||
} else {
|
||||
// exc += 1;
|
||||
|
||||
long ptr = ((NonLeafElement) e[i]).getPtr();
|
||||
try {
|
||||
rtree.Node ns = r.getReadNode(ptr);
|
||||
System.out.println(level + " " + ns.getTotalElements());
|
||||
exc += calculateSize(ns, r, level +"-");
|
||||
} catch (RTreeException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return exc;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -14,20 +14,19 @@ import net.osmand.osm.OSMSettings.OSMTagKey;
|
|||
* SOURCE : http://wiki.openstreetmap.org/wiki/Map_Features
|
||||
*
|
||||
* Describing types of polygons :
|
||||
* 1. Last 3 bits define type of element : polygon, polyline, point
|
||||
* 1. Last 2 bits define type of element : polygon, polyline, point
|
||||
*/
|
||||
public class MapRenderingTypes {
|
||||
|
||||
// TODO Internet access bits for point, polygon
|
||||
/** standard schema :
|
||||
Last bit describe whether types additional exist (it is needed only for main type, other consists only from 15 bits)
|
||||
polygon : aaaaa ttttt 11 _ : 15 bits
|
||||
multi : aaaaa ttttt 00 _ : 15 bits
|
||||
polygon : ll aaaaa ttttt 11 : 14 bits
|
||||
multi : ll aaaaa ttttt 00 : 14 bits
|
||||
t - object type, a - area subtype,l - layer
|
||||
polyline : ll ppppp ttttt 10 _ : 15 bits + 2 bits for special info (+16)
|
||||
polyline : ll ppppp ttttt 10 : 14 bits
|
||||
t - object type, p - polyline object type, l - layer
|
||||
point : ssssssss ttttt 10 _ : 16 bits
|
||||
t - object type, a - subtype
|
||||
point : ssss ssss ttttt 10 : 15 bits
|
||||
t - object type, s - subtype
|
||||
*/
|
||||
|
||||
public final static int MULTY_POLYGON_TYPE = 0;
|
||||
|
@ -233,12 +232,12 @@ public class MapRenderingTypes {
|
|||
}
|
||||
|
||||
// if type equals 0 no need to save that point
|
||||
public static int encodeEntityWithType(Entity e, int level, boolean multipolygon, List<Integer> addTypes) {
|
||||
public static int encodeEntityWithType(Entity e, int level, boolean multipolygon, List<Integer> additionalTypes) {
|
||||
if (types == null) {
|
||||
types = new LinkedHashMap<String, MapRulType>();
|
||||
init(INIT_RULE_TYPES);
|
||||
}
|
||||
addTypes.clear();
|
||||
additionalTypes.clear();
|
||||
if("coastline".equals(e.getTag(OSMTagKey.NATURAL))){ //$NON-NLS-1$
|
||||
multipolygon = true;
|
||||
}
|
||||
|
@ -270,7 +269,7 @@ public class MapRenderingTypes {
|
|||
|
||||
// 2. 2 iterations first for exact tag=value match, second for any tag match
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (i == 1 && !addTypes.isEmpty()) {
|
||||
if (i == 1 && !additionalTypes.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
for (String tag : tagKeySet) {
|
||||
|
@ -284,63 +283,47 @@ public class MapRenderingTypes {
|
|||
int typeVal = rType.getType(val, MASK_13) << 2;
|
||||
if (pr == POINT_TYPE && pointType == 0) {
|
||||
pointType = POINT_TYPE | typeVal;
|
||||
addTypes.add(pointType);
|
||||
additionalTypes.add(pointType);
|
||||
} else if (!point && pr == POLYLINE_TYPE) {
|
||||
int attr = getLayerAttributes(e) << 12;
|
||||
boolean prevPoint = (polylineType == 0 && polygonType == 0);
|
||||
polylineType = POLYLINE_TYPE | (typeVal & MASK_12) | attr;
|
||||
if (((polylineType >> 2) & MASK_4) == HIGHWAY || prevPoint){
|
||||
addTypes.add(0, polylineType);
|
||||
additionalTypes.add(0, polylineType);
|
||||
} else {
|
||||
addTypes.add(polylineType);
|
||||
additionalTypes.add(polylineType);
|
||||
}
|
||||
} else if (polygon && (pr == POLYGON_WITH_CENTER_TYPE || pr == POLYGON_TYPE)) {
|
||||
boolean prevPoint = (polylineType == 0 && polygonType == 0);
|
||||
int attr = getLayerAttributes(e) << 12;
|
||||
polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (typeVal & MASK_12) | attr;
|
||||
if (prevPoint){
|
||||
addTypes.add(0, polygonType);
|
||||
additionalTypes.add(0, polygonType);
|
||||
} else {
|
||||
addTypes.add(polygonType);
|
||||
additionalTypes.add(polygonType);
|
||||
}
|
||||
if (pr == POLYGON_WITH_CENTER_TYPE) {
|
||||
pointType = POINT_TYPE | typeVal;
|
||||
addTypes.add(pointType);
|
||||
additionalTypes.add(pointType);
|
||||
}
|
||||
} else if (polygon && (pr == DEFAULT_POLYGON_BUILDING)) {
|
||||
if(polygonType == 0 && polylineType == 0){
|
||||
polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (((SUBTYPE_BUILDING << 5) | MAN_MADE) << 3);
|
||||
addTypes.add(0, polygonType);
|
||||
int attr = getLayerAttributes(e) << 12;
|
||||
polygonType = (multipolygon ? MULTY_POLYGON_TYPE : POLYGON_TYPE) | (((SUBTYPE_BUILDING << 5) | MAN_MADE) << 2) | attr;
|
||||
additionalTypes.add(0, polygonType);
|
||||
}
|
||||
pointType = POINT_TYPE | typeVal;
|
||||
addTypes.add(pointType);
|
||||
additionalTypes.add(pointType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int type = 0;
|
||||
if(addTypes.isEmpty()){
|
||||
return type;
|
||||
if(!additionalTypes.isEmpty()){
|
||||
type = additionalTypes.get(0);
|
||||
additionalTypes.remove(0);
|
||||
}
|
||||
boolean twoBytes = true;
|
||||
int first = addTypes.get(0);
|
||||
addTypes.remove(0);
|
||||
if(isHighwayType(first)){
|
||||
twoBytes = false;
|
||||
int attr = getHighwayAttributes(e) << 16;
|
||||
type = attr | (first << 1);
|
||||
} else {
|
||||
type = first << 1;
|
||||
}
|
||||
if(twoBytes && addTypes.size() > 0){
|
||||
type |= (addTypes.get(0) << 16);
|
||||
addTypes.remove(0);
|
||||
}
|
||||
if(!addTypes.isEmpty()){
|
||||
type |= 1;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -359,17 +342,15 @@ public class MapRenderingTypes {
|
|||
}
|
||||
|
||||
// HIGHWAY special attributes :
|
||||
// T/Type 5 bit
|
||||
// l/layer 2 bit
|
||||
// o/oneway 1 bit
|
||||
// f/free toll 1 bit
|
||||
// r/roundabout 1 bit (+ 1 bit direction)
|
||||
// r/roundabout 2 bit (+ 1 bit direction)
|
||||
// s/max speed 3 bit [0 - 30km/h, 1 - 50km/h, 2 - 70km/h, 3 - 90km/h, 4 - 110km/h, 5 - 130 km/h, 6 >]
|
||||
// a/vehicle access 4 bit (height, weight?) - one bit bicycle
|
||||
// p/parking 1 bit
|
||||
// c/cycle oneway 1 bit
|
||||
|
||||
// ENCODING : c|p|aaaa|sss|rr|f|o|ll|TTTTT|00001|01_ - 28 bit
|
||||
// ENCODING : c|p|aaaa|sss|rr|f|o - 13 bit
|
||||
|
||||
public static int getHighwayAttributes(Entity e){
|
||||
int attr = 0;
|
||||
|
@ -497,7 +478,6 @@ public class MapRenderingTypes {
|
|||
}
|
||||
|
||||
public static String getEntityName(Entity e, int mainType) {
|
||||
mainType >>= 1;
|
||||
if (e.getTag(OSMTagKey.REF) != null && getMainObjectType(mainType) == HIGHWAY) {
|
||||
String ref = e.getTag(OSMTagKey.REF);
|
||||
if (ref.length() > 5 && ref.indexOf('_') != -1) {
|
||||
|
|
103
DataExtractionOSM/src/rtree/ABL.java
Normal file
103
DataExtractionOSM/src/rtree/ABL.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
//ABL.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
/**Active Branch List
|
||||
This class will consist of the Elements and their MINDIST from the point of query.
|
||||
When the array of this object is returned by the 'nearestSearch' method,
|
||||
kindly type cast 'Elemen't to 'LeafElement' when necessary.
|
||||
This library should be considered as an open source library. Formal GNU licensing I will include later.
|
||||
*/
|
||||
public class ABL implements Cloneable
|
||||
{
|
||||
/**
|
||||
Please type cast it to LeafElement when used as a returned value of
|
||||
the 'nearestSearch' method.
|
||||
*/
|
||||
public Element element;
|
||||
/**By Definition - The distance of a point P in Euclidean space (E(n))
|
||||
from a rectangle R in the same space, denoted by MINDIST(P,R).<br>
|
||||
In English - This is the minimum distance between the query point P
|
||||
and the MBR of the object.
|
||||
<b>Note:-</b> The distance(minDist) is the square of the actual distance.
|
||||
To get the actual distance, call <b>Math.sqrt(minDist)</b> (cast minDist to
|
||||
Double).
|
||||
*/
|
||||
public long minDist;//MINDIST(P,this)
|
||||
public ABL(Element element,long minDist)
|
||||
{
|
||||
this.element = element;
|
||||
this.minDist = minDist;
|
||||
}
|
||||
//Uses Two-Way-Merge-Sort (Recursive)
|
||||
//Sorts an ABL array based on minDist. Make sure there are no null values.
|
||||
public void mergeSort(ABL[] arrABL)
|
||||
{
|
||||
twoWayMerge(arrABL,0,arrABL.length-1);
|
||||
}
|
||||
private void twoWayMerge(ABL[] arrABL,int start,int finish)
|
||||
{
|
||||
try{
|
||||
int size = finish - start+1;
|
||||
if(size <= 2){
|
||||
if(size < 2)
|
||||
return;
|
||||
ABL temp;
|
||||
if(arrABL[start].minDist > arrABL[finish].minDist){
|
||||
temp = arrABL[start];
|
||||
arrABL[start] = arrABL[finish];
|
||||
arrABL[finish] = temp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
Double middle = new Double(start+finish);
|
||||
middle = new Double(Math.ceil(middle.doubleValue()/2));
|
||||
twoWayMerge(arrABL,start,middle.intValue());
|
||||
twoWayMerge(arrABL,middle.intValue(),finish);
|
||||
simpleMerge(arrABL,start,middle.intValue(),finish);
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("rtree.ABL.twoWayMerge: most probably a null value in array");
|
||||
}
|
||||
}
|
||||
|
||||
//simple merge
|
||||
private void simpleMerge(ABL[] arrABL,int first,int second,int third)
|
||||
throws Exception
|
||||
{
|
||||
int i = first;
|
||||
int j = second;
|
||||
int l = 0;
|
||||
ABL[] temp = new ABL[third-first+1];
|
||||
while((i < second) && (j <= third)){//loop till one lasts
|
||||
if(arrABL[i].minDist <= arrABL[j].minDist)
|
||||
temp[l++] = arrABL[i++];
|
||||
else
|
||||
temp[l++] = arrABL[j++];
|
||||
}
|
||||
//copy the rest
|
||||
if(i >= second)//give second section
|
||||
while(j <= third)
|
||||
temp[l++] = arrABL[j++];
|
||||
else
|
||||
while(i < second)//give first section
|
||||
temp[l++] = arrABL[i++];
|
||||
System.arraycopy(temp,0,arrABL,first,temp.length);
|
||||
}
|
||||
public Object clone()
|
||||
{
|
||||
return new ABL(element,minDist);
|
||||
}
|
||||
|
||||
}//class ABL
|
||||
|
||||
|
409
DataExtractionOSM/src/rtree/CachedNodes.java
Normal file
409
DataExtractionOSM/src/rtree/CachedNodes.java
Normal file
|
@ -0,0 +1,409 @@
|
|||
//BufferHeader.java,CachedNodes.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import rtree.seeded.SdNode;
|
||||
/**
|
||||
<b>A circular linked list of cached nodes using hashtable ?!!</b>
|
||||
<p>This class will wrap a list of recently used nodes.
|
||||
If the requested node is in <tt>Hashtable</tt> of the class then the node would
|
||||
be returned from the <tt>Hashtable</tt>, else it would be read from the
|
||||
disk.
|
||||
<br>This will be a static object in the class RTree. Therefore no matter how
|
||||
many RTree objects you create they all would have one cache for all the files
|
||||
the object handles.
|
||||
TODO : keep a set that keeps all the nodes that are dirty. With each node registering themselves
|
||||
hara when thhey are dity, this is maageable.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
class BufferHeader
|
||||
{
|
||||
int recent;//the most recently inserted node
|
||||
int last;//the least recently inserted node
|
||||
int size;//max size of the link list
|
||||
Hashtable cache;
|
||||
BufferHeader(int size,Hashtable ch)
|
||||
{
|
||||
this.cache = ch;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
void flush()
|
||||
throws NodeWriteException
|
||||
{
|
||||
//if(!RTree.writeThr){
|
||||
for (Iterator it = cache.values().iterator(); it.hasNext();){
|
||||
NodeValue node = (NodeValue)it.next();
|
||||
node.node.flush();
|
||||
} // end of for (Iterator = .iterator(); .hasNext();)
|
||||
//}
|
||||
}
|
||||
/*for a fresh key when the array is not full.This will be called when the
|
||||
buffer is not fully warm*/
|
||||
void put(int key, Node node)
|
||||
{
|
||||
try{
|
||||
//the following two conditions happens in multithreaded programs
|
||||
if(cache.containsKey(new Integer(key))){
|
||||
update(key);
|
||||
return;
|
||||
}
|
||||
if(cache.size() == size){
|
||||
replace(key,node);
|
||||
return;
|
||||
}
|
||||
if(cache.size() == 0){
|
||||
last = key;
|
||||
cache.put(new Integer(key), new NodeValue(node,key,key));
|
||||
}else{
|
||||
//remove recent
|
||||
NodeValue tmpPrev = (NodeValue)(cache.remove(new Integer(recent)));
|
||||
if(last == recent){//there is only one node in cache
|
||||
cache.put(new Integer(key), new NodeValue(node,tmpPrev.next,tmpPrev.next));
|
||||
cache.put(new Integer(recent), new NodeValue(tmpPrev.node,key,key));
|
||||
}
|
||||
else{
|
||||
//remove next of previous
|
||||
NodeValue tmpPNext = (NodeValue)(cache.remove(new Integer(tmpPrev.next)));
|
||||
cache.put(new Integer(key), new NodeValue(node,tmpPrev.next,recent));
|
||||
cache.put(new Integer(tmpPrev.next), new NodeValue(tmpPNext.node,tmpPNext.next,key));
|
||||
cache.put(new Integer(recent), new NodeValue(tmpPrev.node,key,tmpPrev.prev));
|
||||
}
|
||||
}
|
||||
recent = key;
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/*a new key in a filled array*/
|
||||
void replace(int key,Node node)
|
||||
throws NodeWriteException
|
||||
{
|
||||
try{
|
||||
if(cache.containsKey(new Integer(key))){
|
||||
update(key);
|
||||
return;
|
||||
}
|
||||
if(cache.size() < size){
|
||||
put(key,node);
|
||||
return;
|
||||
}
|
||||
//remove the 'last' node
|
||||
NodeValue lastNode = (NodeValue)(cache.remove(new Integer(last)));
|
||||
lastNode.node.flush();
|
||||
NodeValue pNode = (NodeValue)(cache.remove(new Integer(lastNode.prev)));
|
||||
NodeValue nNode = (NodeValue)(cache.remove(new Integer(lastNode.next)));
|
||||
//put back the three nodes
|
||||
cache.put(new Integer(key), new NodeValue(node,lastNode.next, lastNode.prev));
|
||||
cache.put(new Integer(lastNode.prev), new NodeValue(pNode.node,key,pNode.prev));
|
||||
cache.put(new Integer(lastNode.next), new NodeValue(nNode.node,nNode.next,key));
|
||||
recent = key;//this is the latest node
|
||||
last = lastNode.next;//set the next in chain as the new 'last'
|
||||
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**make a node that is present as 'recent'*/
|
||||
void update(int key)
|
||||
{
|
||||
try{
|
||||
if(key != recent){
|
||||
NodeValue node,nextNode,prevNode,rcntNode,lastNode;//temp variables
|
||||
node = (NodeValue)(cache.remove(new Integer(key)));
|
||||
if(node == null){//will not happen
|
||||
System.out.println("CachedNodes.update: unlikely flow");
|
||||
return;
|
||||
}
|
||||
if(key == last){
|
||||
last = node.next;
|
||||
cache.put(new Integer(key), new NodeValue(node.node, node.next, node.prev));
|
||||
}
|
||||
else{
|
||||
//adjust next node and the recent node
|
||||
nextNode = (NodeValue)(cache.remove(new Integer(node.next)));
|
||||
if(recent != node.next){//if next node is not the recent node
|
||||
rcntNode = (NodeValue)(cache.remove(new Integer(recent)));
|
||||
rcntNode.next = key;
|
||||
cache.put(new Integer(recent), new NodeValue(rcntNode.node, rcntNode.next,rcntNode.prev));
|
||||
}
|
||||
else{//next node is the recent node
|
||||
nextNode.next = key;
|
||||
}
|
||||
cache.put(new Integer(node.next), new NodeValue(nextNode.node, nextNode.next,node.prev));
|
||||
|
||||
//adjust previous node and the last node - if unequal
|
||||
prevNode = (NodeValue)(cache.remove(new Integer(node.prev)));
|
||||
if(last != node.prev){//if last node is not the prev node
|
||||
lastNode = (NodeValue)(cache.remove(new Integer(last)));
|
||||
lastNode.prev = key;
|
||||
cache.put(new Integer(last),new NodeValue(lastNode.node, lastNode.next,lastNode.prev));
|
||||
}
|
||||
else{//if the last node is the prev node.
|
||||
prevNode.prev = key;
|
||||
}
|
||||
cache.put(new Integer(node.prev), new NodeValue(prevNode.node, node.next,prevNode.prev));
|
||||
|
||||
//put the new node
|
||||
cache.put(new Integer(key), new NodeValue(node.node,last,recent));
|
||||
}
|
||||
//update local variables
|
||||
}
|
||||
recent = key;
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
void remove(int key)
|
||||
throws NodeWriteException
|
||||
{
|
||||
try{
|
||||
NodeValue node = (NodeValue)(cache.remove(new Integer(key)));
|
||||
if((cache.size() != 0) && (node != null)){
|
||||
//if(!RTree.writeThr)
|
||||
node.node.flush();
|
||||
if(cache.size() == 1){
|
||||
NodeValue oNode = (NodeValue)(cache.remove(new Integer(node.prev)));
|
||||
cache.put(new Integer(node.prev), new NodeValue(oNode.node, node.prev,node.prev));
|
||||
recent = last = node.prev;
|
||||
}
|
||||
else{
|
||||
//if(!RTree.writeThr)
|
||||
node.node.flush();
|
||||
NodeValue pNode = (NodeValue)(cache.remove(new Integer(node.prev)));
|
||||
NodeValue nNode = (NodeValue)(cache.remove(new Integer(node.next)));
|
||||
cache.put(new Integer(node.prev), new NodeValue(pNode.node, node.next,pNode.prev));
|
||||
cache.put(new Integer(node.next), new NodeValue(nNode.node, nNode.next,node.prev));
|
||||
if(key == recent)
|
||||
recent = node.prev;
|
||||
if(key == last)
|
||||
last = node.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
void reset()
|
||||
throws NodeWriteException
|
||||
{
|
||||
//if(!RTree.writeThr)
|
||||
flush();
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
public class CachedNodes
|
||||
{
|
||||
private static final int NODE = 0;
|
||||
private static final int SDNODE = 1;
|
||||
Hashtable cache;
|
||||
BufferHeader buffHeader;
|
||||
int size = Node.CACHE_SIZE;
|
||||
CachedNodes()
|
||||
{
|
||||
//System.out.println("CachedNodes : cache called");
|
||||
cache = new Hashtable(Node.CACHE_SIZE+1,1);
|
||||
buffHeader = new BufferHeader(Node.CACHE_SIZE,cache);
|
||||
size = Node.CACHE_SIZE;
|
||||
}
|
||||
/**
|
||||
This one is still under construction.
|
||||
*/
|
||||
CachedNodes(int size)
|
||||
{
|
||||
if(size < 0)
|
||||
throw new IllegalArgumentException("CachedNodes:: size is less than zero");
|
||||
cache = new Hashtable(size+1,1);
|
||||
buffHeader = new BufferHeader(size, cache);
|
||||
this.size = size;
|
||||
}
|
||||
public synchronized void setCacheSize(int size)
|
||||
throws NodeWriteException
|
||||
{
|
||||
if(size < 0)
|
||||
throw new IllegalArgumentException("CachedNodes:: size is less than zero");
|
||||
removeAll();
|
||||
cache = new Hashtable(size+1,1);
|
||||
buffHeader = new BufferHeader(size, cache);
|
||||
this.size = size;
|
||||
}
|
||||
public synchronized int getSize()
|
||||
{
|
||||
return cache.size();
|
||||
}
|
||||
private Node getNode(RandomAccessFile file,String fileName,long lndIndex,FileHdr flHdr, int type)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
int ndIndex = (int)lndIndex;
|
||||
int key = calKey(fileName,ndIndex);
|
||||
NodeValue node = (NodeValue)(cache.get(new Integer(key)));
|
||||
Node nNode;
|
||||
if(node == null){//Node not in cache
|
||||
if(type == NODE){
|
||||
nNode = new Node(file, fileName, ndIndex, flHdr);
|
||||
}else{
|
||||
nNode = new SdNode(file, fileName, ndIndex, flHdr);
|
||||
}
|
||||
key = calKey(fileName, (int)nNode.getNodeIndex());//this is for the case where index is NOT_DEFINED
|
||||
nNode.sweepSort();
|
||||
//cache not full
|
||||
if(cache.size() < Node.CACHE_SIZE){
|
||||
buffHeader.put(key,nNode);//(Node)nNode.clone());
|
||||
}else if(cache.size() == Node.CACHE_SIZE){//cache Is full
|
||||
buffHeader.replace(key,nNode);//(Node)nNode.clone());
|
||||
}
|
||||
return nNode;
|
||||
}
|
||||
else{//node found in the cache
|
||||
buffHeader.update(key);
|
||||
node.node.sweepSort();
|
||||
return (node.node);
|
||||
}
|
||||
}
|
||||
private Node getNode(RandomAccessFile file,String fileName,long parentIndex, int elmtType, FileHdr flHdr,
|
||||
int type)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
Node nNode;
|
||||
if(type == NODE){
|
||||
nNode = new Node(file,fileName,parentIndex, elmtType, flHdr);
|
||||
}else{
|
||||
nNode = new SdNode(file,fileName,parentIndex, elmtType, flHdr);
|
||||
}
|
||||
int key = calKey(fileName, (int)nNode.getNodeIndex());
|
||||
nNode.sweepSort();
|
||||
//cache not full
|
||||
if(cache.size() < Node.CACHE_SIZE)
|
||||
buffHeader.put(key,nNode);
|
||||
//cache Is full
|
||||
else if(cache.size() == Node.CACHE_SIZE)
|
||||
buffHeader.replace(key,nNode);
|
||||
return nNode;
|
||||
}
|
||||
//-----------------------Methods for client to get Node they prefer------------
|
||||
/**
|
||||
This one returns an existing <code>SdNode</code>
|
||||
*/
|
||||
public synchronized SdNode getSdNode(RandomAccessFile file,String fileName,long lndIndex,FileHdr flHdr)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
return (SdNode)getNode(file,fileName,lndIndex,flHdr, SDNODE);
|
||||
}
|
||||
/**
|
||||
This one returns an existing <code>SdNode</code>.
|
||||
*/
|
||||
public synchronized SdNode getSdNode(RandomAccessFile file,String fileName,long parentIndex,
|
||||
int elmtType, FileHdr flHdr)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
return (SdNode)getNode(file,fileName,parentIndex, elmtType, flHdr, SDNODE);
|
||||
}
|
||||
/**
|
||||
This one returns an existing <code>Node</code>.
|
||||
*/
|
||||
public synchronized Node getNode(RandomAccessFile file,String fileName,long lndIndex,FileHdr flHdr)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
return getNode(file,fileName,lndIndex,flHdr, NODE);
|
||||
}
|
||||
/**
|
||||
This one returns an new <code>SdNode</code>.
|
||||
*/
|
||||
public synchronized Node getNode(RandomAccessFile file,String fileName,long parentIndex,
|
||||
int elmtType, FileHdr flHdr)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
return getNode(file,fileName,parentIndex, elmtType, flHdr, NODE);
|
||||
}
|
||||
/**
|
||||
This one returns an new <code>Node</code>.
|
||||
*/
|
||||
public synchronized Node getNode(RandomAccessFile file,String fileName,long parentIndex,
|
||||
int elmtType, FileHdr flHdr, Node type)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
if(type instanceof SdNode)
|
||||
return getNode(file,fileName,parentIndex, elmtType, flHdr, SDNODE);
|
||||
else
|
||||
return getNode(file,fileName,parentIndex, elmtType, flHdr, NODE);
|
||||
}
|
||||
/**
|
||||
This one return <code>ReadNode</code> a read only node.
|
||||
All clients that need only to query the rtree must at all cost call this method. This method will
|
||||
return a clones ReadNode, so that concurrent reads can take place (because none of the methods
|
||||
of <code>Node</code> are <code>synchronized</code>.
|
||||
*/
|
||||
public synchronized ReadNode getReadNode(RandomAccessFile file,String fileName,long lndIndex,FileHdr flHdr)
|
||||
throws IllegalValueException, NodeReadException, FileNotFoundException, IOException, NodeWriteException
|
||||
{
|
||||
return ReadNode.makeReadNode(getNode(file,fileName,lndIndex,flHdr));
|
||||
}
|
||||
/**
|
||||
Write all the diry nodes to the disc.
|
||||
*/
|
||||
synchronized void flush()
|
||||
throws NodeWriteException
|
||||
{
|
||||
//if(!RTree.writeThr)
|
||||
buffHeader.flush();
|
||||
}
|
||||
/**
|
||||
This method would be called only by those threads that need to modify the
|
||||
tree. Hence this method is automatically synchronized.
|
||||
*/
|
||||
synchronized void remove(String fileName,long ndIndex)
|
||||
throws NodeWriteException
|
||||
{
|
||||
int key = calKey(fileName,(int)ndIndex);
|
||||
buffHeader.remove(key);
|
||||
}
|
||||
|
||||
|
||||
synchronized void removeAll()
|
||||
throws NodeWriteException
|
||||
{
|
||||
buffHeader.reset();
|
||||
}
|
||||
|
||||
int calKey(String fileName,int idx)
|
||||
{
|
||||
if(fileName != null)
|
||||
return (idx + fileName.toLowerCase().hashCode());
|
||||
else{
|
||||
System.out.println("CachedNodes.calKey: fileName null");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
class NodeValue
|
||||
{
|
||||
Node node;
|
||||
int next;//the next node's key
|
||||
int prev;//the prev node's key
|
||||
NodeValue(Node node,int n,int p)
|
||||
{
|
||||
this.node = node;
|
||||
next = n;
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
/**
|
||||
TODO:
|
||||
2) A way to pin an node. Obviously the client must also unpinn the node.
|
||||
|
||||
*/
|
58
DataExtractionOSM/src/rtree/Element.java
Normal file
58
DataExtractionOSM/src/rtree/Element.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
//Element.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**baap of all elemetns
|
||||
@author Prachuryya Barua
|
||||
*
|
||||
**/
|
||||
public abstract class Element implements Cloneable, java.io.Serializable
|
||||
{
|
||||
Rect Rectangle;
|
||||
|
||||
Element(){};
|
||||
public Element( Rect Rectangle)
|
||||
{
|
||||
this.Rectangle = Rectangle;
|
||||
}
|
||||
private void overwriteRect( Rect Rectangle)
|
||||
{
|
||||
this.Rectangle = Rectangle;
|
||||
}
|
||||
public Rect getRect()
|
||||
{
|
||||
return(Rectangle);
|
||||
}
|
||||
/**
|
||||
This can be a child node pointer or a record pointer.
|
||||
*/
|
||||
//public abstract Object getPtr();//old
|
||||
public abstract long getPtr();
|
||||
/**
|
||||
Do not call this function, Node will call it.
|
||||
*/
|
||||
void setRect( Rect mbr)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(mbr == null)
|
||||
throw new IllegalValueException("Element.adjustMBR: Rect is null");
|
||||
overwriteRect(mbr);
|
||||
}
|
||||
//abstract void setPtr(Object ptr) //old
|
||||
//throws IllegalValueException;
|
||||
public abstract void setPtr(long ptr);
|
||||
public abstract int getElementType();
|
||||
public String toString()
|
||||
{
|
||||
return Rectangle.toString();
|
||||
}
|
||||
}
|
22
DataExtractionOSM/src/rtree/ElementNotFoundException.java
Normal file
22
DataExtractionOSM/src/rtree/ElementNotFoundException.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
//ElementNotFoundException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
/**When deleting node if the node is not found then the exception is thrown
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class ElementNotFoundException extends Exception
|
||||
{
|
||||
public ElementNotFoundException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
534
DataExtractionOSM/src/rtree/FileHdr.java
Normal file
534
DataExtractionOSM/src/rtree/FileHdr.java
Normal file
|
@ -0,0 +1,534 @@
|
|||
//FileHdr.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
import java.io.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
/**
|
||||
This class is the handler for the file.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class FileHdr
|
||||
{
|
||||
/**------------file header - will always take 1024 bytes------------*/
|
||||
/**total no. of nodes in the file*/
|
||||
int totalNodes;
|
||||
/**the index of the root*/
|
||||
long rootIndex;
|
||||
|
||||
/**------------local variables--------------------------------------*/
|
||||
protected boolean writeThr = false;//whether write dirt or write through
|
||||
/**Overflow limit*/
|
||||
int stkLimit;
|
||||
/**The stack data. Although the indices are <code>long</code> but they can be easily represented as
|
||||
<code>int</code>*/
|
||||
private int[] S;
|
||||
/**Index of the top most element*/
|
||||
private int topIdx;
|
||||
private RandomAccessFile file;
|
||||
private boolean dirty = false;/*Tells whethet this is a dirty filehdr or not*/
|
||||
/**If any write thread is interested then increment this. This variable
|
||||
results in the fact that writes will always have the preference.
|
||||
Even when the JVM chooses a READ thread to run, it would have to wait
|
||||
till <b>one</b> of all the waiting WRITE threads run. After one of the WRITE
|
||||
thread runs, the situation is open for all. Again, if any of the WRITE
|
||||
thread sets <tt>interested</tt>, then on next <tt>notifyAll</tt> it is
|
||||
gauranteed that one of the WRITE threads will run before any other READ.
|
||||
*/
|
||||
private boolean interested;
|
||||
/**The wait thread queue*/
|
||||
private Vector waiters;
|
||||
/**
|
||||
Although this 'stack' is part of the file header but it acts totally
|
||||
independently of the rest of the file header. All of the file reads and
|
||||
writes are handled by the 'Node' class but the free node list('stack') is
|
||||
maintained by this class independently. Therefore all the 'Node' class
|
||||
needs to do is call the 'push' and 'pop' method to read and write to the
|
||||
file regarding the free node list.<br>
|
||||
Note:- This class will work well with 150 element delets at one go but
|
||||
beyond that it will not maintain the list of nodes that have been
|
||||
deleted. This is not fatal but the size of the file will increase and the
|
||||
deleted nodes that did not register with the stack will be lost forever.
|
||||
This condition can be rectified by calling <tt>Pack.packTree</tt>.
|
||||
*/
|
||||
FileHdr(int stkLimit,String fileName)
|
||||
throws RTreeException
|
||||
{
|
||||
try{
|
||||
this.file = new RandomAccessFile(fileName,"rw");
|
||||
this.writeThr = false;
|
||||
this.stkLimit = stkLimit;
|
||||
waiters = new Vector();
|
||||
S = new int[this.stkLimit];
|
||||
topIdx = -1;
|
||||
int frNode;
|
||||
writeThr = false;
|
||||
//no nodes present
|
||||
//if(file.length() <= (Node.FILE_HDR_SIZE+1)){
|
||||
if(file.length() <= (Node.INTEGER_SIZE)){
|
||||
file.seek(0);
|
||||
file.writeInt(0);//total nodes
|
||||
file.writeLong(Node.NOT_DEFINED);//file.writeInt(Node.NOT_DEFINED);//original
|
||||
file.writeInt(Node.NOT_DEFINED);
|
||||
totalNodes = 0;
|
||||
rootIndex = Node.NOT_DEFINED;
|
||||
}
|
||||
//read stack from the file if stack exists
|
||||
else{
|
||||
file.seek(0);
|
||||
byte[] data = new byte[ Node.FILE_HDR_SIZE ];
|
||||
file.read(data);
|
||||
DataInputStream ds = new DataInputStream(new ByteArrayInputStream(data));
|
||||
totalNodes = ds.readInt();
|
||||
rootIndex = ds.readLong();//rootIndex = ds.readInt();
|
||||
while((topIdx<stkLimit) &&
|
||||
((frNode = ds.readInt()) != Node.NOT_DEFINED))
|
||||
S[++topIdx] = frNode;
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
throw new RTreeException("FileHdr.FileHdr: " +e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
This method at the moment is only for Pack. This one has potential!
|
||||
*/
|
||||
public void setBufferPolicy(boolean writeThr)
|
||||
throws IOException
|
||||
{
|
||||
flush();
|
||||
this.writeThr = writeThr;
|
||||
}
|
||||
|
||||
/**
|
||||
This method will be used by the Pack class to update this header from the file again. I assume that
|
||||
the object that called this method has write lock with it.
|
||||
*/
|
||||
void update(String fileName)
|
||||
throws RTreeException
|
||||
{
|
||||
try{
|
||||
file.close();
|
||||
this.file = new RandomAccessFile(fileName,"rw");
|
||||
//file.getFD().sync();
|
||||
S = new int[this.stkLimit];
|
||||
topIdx = -1;
|
||||
int frNode;
|
||||
dirty = false;
|
||||
//no nodes present
|
||||
//if(file.length() <= (Node.FILE_HDR_SIZE+1)){
|
||||
if(file.length() <= (Node.INTEGER_SIZE)){
|
||||
file.seek(0);
|
||||
file.writeInt(0);
|
||||
file.writeLong(Node.NOT_DEFINED);//file.writeInt(Node.NOT_DEFINED);
|
||||
file.writeInt(Node.NOT_DEFINED);
|
||||
totalNodes = 0;
|
||||
rootIndex = Node.NOT_DEFINED;
|
||||
}
|
||||
//read stack from the file if stack exists
|
||||
else{
|
||||
file.seek(0);
|
||||
byte[] data = new byte[Node.FILE_HDR_SIZE];
|
||||
file.read(data);
|
||||
DataInputStream ds = new DataInputStream(new ByteArrayInputStream(data));
|
||||
totalNodes = ds.readInt();
|
||||
rootIndex = ds.readLong();//rootIndex = ds.readInt();
|
||||
while((topIdx<stkLimit)
|
||||
&& ((frNode = ds.readInt()) != Node.NOT_DEFINED))
|
||||
S[++topIdx] = frNode;
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException("FileHdr.FileHdr: " +e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
Will set the file header size to zero and remake the file header.
|
||||
*/
|
||||
void resetHeader()
|
||||
throws Exception
|
||||
{
|
||||
S = new int[this.stkLimit];
|
||||
topIdx = -1;
|
||||
int frNode;
|
||||
file.setLength(1);
|
||||
file.seek(0);
|
||||
file.writeInt(0);
|
||||
file.writeLong(Node.NOT_DEFINED);
|
||||
file.writeInt(Node.NOT_DEFINED);
|
||||
totalNodes = 0;
|
||||
rootIndex = Node.NOT_DEFINED;
|
||||
dirty = false;
|
||||
}
|
||||
/**
|
||||
Pass the index of the node that needs to be pushed in the stack
|
||||
*/
|
||||
synchronized void push(long lval)
|
||||
throws StackOverflowException,IOException
|
||||
{
|
||||
int val = (int)lval;
|
||||
if(topIdx >= (stkLimit-1))
|
||||
throw new StackOverflowException("FileHdr.push: Overflow but not fatal");
|
||||
//System.out.println("Push called, pushing at S["+(topIdx+1)+"]:"+val);
|
||||
S[++topIdx] = val;
|
||||
dirty = true;
|
||||
if(writeThr){
|
||||
file.seek(( Node.INTEGER_SIZE + Node.LONG_SIZE)+( Node.INTEGER_SIZE*(topIdx)));
|
||||
file.writeInt(val);
|
||||
//signal end of free list
|
||||
if(topIdx < ( Node.FREE_LIST_LIMIT-1))
|
||||
file.writeInt( Node.NOT_DEFINED);
|
||||
}
|
||||
}
|
||||
synchronized int pop()
|
||||
throws StackUnderflowException,IOException
|
||||
{
|
||||
if(topIdx < 0)
|
||||
throw new StackUnderflowException("FileHdr.pop: Underflow");
|
||||
//System.out.println("Pop called, returning S["+topIdx+"]:"+S[topIdx]);
|
||||
if(writeThr){
|
||||
file.seek(( Node.INTEGER_SIZE + Node.LONG_SIZE) + ( Node.INTEGER_SIZE*topIdx));
|
||||
file.writeInt( Node.NOT_DEFINED);
|
||||
}
|
||||
dirty = true;
|
||||
return S[topIdx--];
|
||||
}
|
||||
/**
|
||||
returns the size of the stck of free nodes.
|
||||
*/
|
||||
int stackSize()
|
||||
{
|
||||
return topIdx + 1;
|
||||
}
|
||||
int peep(int index)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if((index > topIdx) || (index < 0))
|
||||
throw new IllegalValueException("FileHdr.peep: Index out of bound");
|
||||
return S[index];
|
||||
}
|
||||
|
||||
private synchronized void writeFileHeader()
|
||||
throws IOException
|
||||
{
|
||||
if(dirty){
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream(Node.FILE_HDR_SIZE);
|
||||
DataOutputStream ds = new DataOutputStream(bs);
|
||||
ds.writeInt(totalNodes);
|
||||
ds.writeLong(rootIndex);
|
||||
if(topIdx == -1)
|
||||
ds.writeInt(Node.NOT_DEFINED);
|
||||
else{//write the whole stack
|
||||
for(int i=0; i <= topIdx; i++)
|
||||
ds.writeInt(S[i]);
|
||||
ds.writeInt(Node.NOT_DEFINED);//indicate the end of list
|
||||
}//else
|
||||
bs.flush();
|
||||
ds.flush();
|
||||
file.seek(0);
|
||||
file.write(bs.toByteArray());
|
||||
}
|
||||
dirty = false;
|
||||
}
|
||||
/**this function writes to file header as well as to the local variables
|
||||
an atomic function.Does not concern itself with the stack info.
|
||||
*/
|
||||
synchronized void writeFileHeader(int totNodes,long rootIdx)
|
||||
throws IOException
|
||||
{
|
||||
if(writeThr){
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream(Node.INTEGER_SIZE + Node.LONG_SIZE);
|
||||
DataOutputStream ds = new DataOutputStream(bs);
|
||||
ds.writeInt(totNodes);
|
||||
ds.writeLong(rootIdx);
|
||||
bs.flush();
|
||||
ds.flush();
|
||||
file.seek(0);
|
||||
file.write(bs.toByteArray());
|
||||
dirty = false;
|
||||
}
|
||||
dirty = true;
|
||||
//update local variables
|
||||
totalNodes = totNodes;
|
||||
rootIndex = rootIdx;
|
||||
}
|
||||
/**
|
||||
This method does a file IO. Can we make another method which is not static.
|
||||
@return root index for any file.
|
||||
@deprecated Use the non static one.
|
||||
*/
|
||||
public static long getRootIndex(String fileName)
|
||||
throws FileNotFoundException
|
||||
{
|
||||
RandomAccessFile fl = new RandomAccessFile(fileName,"r");
|
||||
try{
|
||||
if (fl.length() == 0)//new file
|
||||
throw new FileNotFoundException("Node.getRootIndex : File not found");
|
||||
fl.seek( Node.INTEGER_SIZE );
|
||||
long rootIndx = fl.readLong();
|
||||
fl.close();
|
||||
return rootIndx;
|
||||
}
|
||||
catch(IOException e){
|
||||
System.out.println("Node.getRootIndex: Couldn't get root index");
|
||||
return Node.NOT_DEFINED;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Returns the <code>RandomAccessFile</code> object
|
||||
*/
|
||||
public RandomAccessFile getFile()
|
||||
{
|
||||
return this.file;
|
||||
}
|
||||
/**
|
||||
Will return the total nodes in the tree. This does not include the nodes that are deleted and are
|
||||
in the stack.
|
||||
*/
|
||||
public int getTotalNodes()
|
||||
{
|
||||
if(topIdx < 0)
|
||||
return totalNodes;
|
||||
else
|
||||
return totalNodes - topIdx;
|
||||
}
|
||||
public long getRootIndex()
|
||||
{
|
||||
return rootIndex;
|
||||
}
|
||||
protected void finalize() throws Throwable
|
||||
{
|
||||
try {
|
||||
flush();
|
||||
file.close();
|
||||
}catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
Will flush the file header if it is dirty. It will <b>not</b> flush the individual nodes at it it not
|
||||
its responsiblity.
|
||||
*/
|
||||
void flush()
|
||||
throws IOException
|
||||
{
|
||||
if(dirty && !writeThr){
|
||||
writeFileHeader();
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
public boolean isWriteThr()
|
||||
{
|
||||
return writeThr;
|
||||
}
|
||||
void setDirty(boolean val)
|
||||
{
|
||||
this.dirty = val;
|
||||
}
|
||||
//-------------The following code is added by Ketan ...replacing my code!!!!------------------
|
||||
|
||||
/**retuns the index of the first WRITE thread in the queue*/
|
||||
private int firstWriter()
|
||||
{
|
||||
Enumeration e=waiters.elements();
|
||||
|
||||
for(int index=0;e.hasMoreElements();index++)
|
||||
{
|
||||
ThreadInfo threadinfo = (ThreadInfo) e.nextElement();
|
||||
if(threadinfo.lockType == Node.WRITE)
|
||||
return index;
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
private int getIndex(Thread t)
|
||||
{
|
||||
Enumeration e=waiters.elements();
|
||||
|
||||
/** If thread is in the vector then
|
||||
* return it's index
|
||||
* else
|
||||
* return -1
|
||||
*/
|
||||
for(int index=0;e.hasMoreElements();index++)
|
||||
{
|
||||
ThreadInfo threadinfo = (ThreadInfo) e.nextElement();
|
||||
/** If Thread is already in the vector then
|
||||
* return it's Index
|
||||
*/
|
||||
if(threadinfo.t == t)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public synchronized void lockRead()
|
||||
{
|
||||
ThreadInfo threadinfo;
|
||||
Thread me = Thread.currentThread();
|
||||
int index = getIndex(me);
|
||||
/** if index = -1 then
|
||||
the thread is not in the Vector, so create a new ThreadInfo
|
||||
and add it to the vector
|
||||
else
|
||||
thread is in the queue and get the index of the thread
|
||||
*/
|
||||
if(index == -1)
|
||||
{
|
||||
threadinfo = new ThreadInfo(me,Node.READ);
|
||||
waiters.addElement(threadinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
threadinfo = (ThreadInfo) waiters.elementAt(index);
|
||||
}
|
||||
|
||||
/** If the currentThread has come after a Write Thread then
|
||||
* make it wait() until WRITE thread is serviced
|
||||
*/
|
||||
while(getIndex(me) >= firstWriter())
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}catch(Exception e){}
|
||||
}
|
||||
/**
|
||||
* increase the no. of locks the threadinfo has acquired
|
||||
*/
|
||||
threadinfo.nAcquired++;
|
||||
//System.out.println("FileHdr.lockRead : read locked for thread " + Thread.currentThread());
|
||||
//+" when "+this.toString());
|
||||
}
|
||||
|
||||
public synchronized void lockWrite() throws IllegalArgumentException
|
||||
{
|
||||
ThreadInfo threadinfo;
|
||||
Thread me= Thread.currentThread();
|
||||
int index = getIndex(me);
|
||||
/** If the thread is not in the Vector then
|
||||
create a new ThreadInfo with WRITE status and add it to the Vector
|
||||
else
|
||||
get the Index for the thread from the Vector
|
||||
*/
|
||||
if(index==-1)
|
||||
{
|
||||
threadinfo = new ThreadInfo(me,Node.WRITE);
|
||||
waiters.addElement(threadinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
//System.out.println("getIndex = " +getIndex(me));
|
||||
threadinfo = (ThreadInfo) waiters.elementAt(index);
|
||||
//if(threadinfo.lockType==Node.READ)
|
||||
//threadinfo.lockType = Node.WRITE;
|
||||
}
|
||||
while(getIndex(me)!=0)
|
||||
{
|
||||
try
|
||||
{
|
||||
wait();
|
||||
}catch(Exception e){}
|
||||
}
|
||||
threadinfo.nAcquired++;
|
||||
//System.out.println("FileHdr.lockWrite : write locked for thread " + Thread.currentThread());
|
||||
}
|
||||
public synchronized void unlock() throws IllegalArgumentException
|
||||
{
|
||||
ThreadInfo threadinfo;
|
||||
Thread me = Thread.currentThread();
|
||||
int index = getIndex(me);
|
||||
|
||||
/** if the index is greater than first WRITE thread then
|
||||
* lock is not held by the thread so throw Exception
|
||||
else
|
||||
|
||||
*/
|
||||
if(index > firstWriter())
|
||||
throw new IllegalArgumentException("FileHdr.unlock: Lock not Held for the thread");
|
||||
|
||||
threadinfo = (ThreadInfo) waiters.elementAt(index);
|
||||
threadinfo.nAcquired--;
|
||||
|
||||
if(threadinfo.nAcquired==0)
|
||||
{
|
||||
waiters.removeElementAt(index);
|
||||
if(waiters.size()>0){
|
||||
//System.out.println("FileHdr.unlock : notifiying");
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
//System.out.println("FileHdr.unlock : unlocking for thread " + Thread.currentThread());
|
||||
}
|
||||
/**
|
||||
This method will return only internal varaibles.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
try{
|
||||
String str = new String();
|
||||
str += "\nTotal Nodes " + totalNodes;
|
||||
str += "\nRoot Index " + rootIndex;
|
||||
str += "\nFile length " + file.length();
|
||||
if(waiters != null){
|
||||
str += "\nWaiters : total " + waiters.size();
|
||||
for(int i=0; i<waiters.size();i++)
|
||||
str += "\n" + i + " : " + waiters.get(i).toString();
|
||||
}
|
||||
return str;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Vector getWaiters()
|
||||
{
|
||||
return waiters;
|
||||
}
|
||||
synchronized void setWaiters(Vector wtrs)
|
||||
{
|
||||
waiters = wtrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The class helps to store the details of a thread, like lockType
|
||||
*/
|
||||
class ThreadInfo
|
||||
{
|
||||
int lockType;
|
||||
int nAcquired=0;
|
||||
Thread t;
|
||||
|
||||
ThreadInfo(Thread t,int lockType)
|
||||
{
|
||||
this.t = t;
|
||||
this.lockType = lockType;
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
String str = new String("\nThreadInfo");
|
||||
str += "\n lockType : "+ lockType;
|
||||
str += "\n nAcquired : "+ nAcquired;
|
||||
str += "\n Thread : "+ t;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
27
DataExtractionOSM/src/rtree/IllegalValueException.java
Normal file
27
DataExtractionOSM/src/rtree/IllegalValueException.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
//IllegalValueException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class IllegalValueException extends Exception
|
||||
{
|
||||
|
||||
public IllegalValueException (){
|
||||
super ();
|
||||
}
|
||||
|
||||
public IllegalValueException(String s){
|
||||
super(s);
|
||||
}
|
||||
}
|
109
DataExtractionOSM/src/rtree/LeafElement.java
Normal file
109
DataExtractionOSM/src/rtree/LeafElement.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
//LeafElement.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
This class represents database objects.
|
||||
It consist of a MBR and the PID of the object.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class LeafElement extends Element
|
||||
{
|
||||
/**
|
||||
for the time being it is 'int'.
|
||||
Changed to long
|
||||
*/
|
||||
long recordPtr;
|
||||
|
||||
public LeafElement( Rect minBndRect,long recordPtr)
|
||||
{
|
||||
super(minBndRect);
|
||||
this.recordPtr = recordPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
if possible make this function abstract and static in the parent class
|
||||
depends upon the size of the pointer
|
||||
*/
|
||||
public static int sizeInBytes()
|
||||
{
|
||||
return( Rect.sizeInBytes() + Node.LONG_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
The <tt>"Id"</tt> of the MBR in database.
|
||||
@return an Long type object
|
||||
*/
|
||||
// public Object getPtr()
|
||||
// {
|
||||
// return(new Long(recordPtr));
|
||||
// }
|
||||
public long getPtr()
|
||||
{
|
||||
return recordPtr;
|
||||
}
|
||||
public int getElementType()
|
||||
{
|
||||
return Node.LEAF_NODE;
|
||||
}
|
||||
// void setPtr(Object ptr)
|
||||
// throws IllegalValueException
|
||||
// {
|
||||
// if(!(ptr instanceof Long))
|
||||
// throw new IllegalValueException("rtree.LeafElement.setPtr: pointer shoild be Long");
|
||||
// recordPtr = ((Long)ptr).longValue();
|
||||
// }
|
||||
public void setPtr(long ptr)
|
||||
{
|
||||
recordPtr = ptr;
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
return (super.toString()+"\n\trecPointer: "+recordPtr);
|
||||
}
|
||||
public Object clone()
|
||||
{
|
||||
try{
|
||||
return new LeafElement(new Rect(Rectangle.getMinX(), Rectangle.getMinY(),
|
||||
Rectangle.getMaxX(), Rectangle.getMaxY()),recordPtr);
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This is a utility method that extracts record pointers(IDs) from a <code>LeafElement</code> vector.
|
||||
This method can be called after calling amy of the spatial calls to RTree.
|
||||
*/
|
||||
public synchronized static List extractPtrs(List elements)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if(elements == null)
|
||||
throw new IllegalArgumentException("RTree.LeafElement: Argument null");
|
||||
List result = new ArrayList();
|
||||
try{
|
||||
for (Iterator i = elements.iterator(); i.hasNext();)
|
||||
//result.addElement(new Long(((LeafElement)i.next()).getPtr()));
|
||||
result.add(new Integer((int)((LeafElement)i.next()).getPtr()));//temp
|
||||
//System.out.println("LeafElement.Extractptrs : time " + (System.currentTimeMillis() - time));
|
||||
return result;
|
||||
|
||||
}catch(ClassCastException e){
|
||||
throw new IllegalArgumentException("RTree.LeafElement: Type of vector is not LeafElement");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1480
DataExtractionOSM/src/rtree/Node.java
Normal file
1480
DataExtractionOSM/src/rtree/Node.java
Normal file
File diff suppressed because it is too large
Load diff
25
DataExtractionOSM/src/rtree/NodeEmptyException.java
Normal file
25
DataExtractionOSM/src/rtree/NodeEmptyException.java
Normal file
|
@ -0,0 +1,25 @@
|
|||
//NodeEmptyException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
import java.lang.Exception;
|
||||
|
||||
/**when a node is empty
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class NodeEmptyException extends Exception
|
||||
{
|
||||
NodeEmptyException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
27
DataExtractionOSM/src/rtree/NodeFullException.java
Normal file
27
DataExtractionOSM/src/rtree/NodeFullException.java
Normal file
|
@ -0,0 +1,27 @@
|
|||
//NodeFullException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
|
||||
import java.lang.Exception;
|
||||
|
||||
/**Exception when no. of elements increase, then the limited value, in a node.
|
||||
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class NodeFullException extends Exception
|
||||
{
|
||||
public NodeFullException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
26
DataExtractionOSM/src/rtree/NodeReadException.java
Normal file
26
DataExtractionOSM/src/rtree/NodeReadException.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
//NodeReadException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
|
||||
import java.lang.Exception;
|
||||
|
||||
/**When some error arises when reading a node
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class NodeReadException extends Exception
|
||||
{
|
||||
public NodeReadException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
26
DataExtractionOSM/src/rtree/NodeWriteException.java
Normal file
26
DataExtractionOSM/src/rtree/NodeWriteException.java
Normal file
|
@ -0,0 +1,26 @@
|
|||
//NodeWriteException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
//package rtree;
|
||||
|
||||
import java.lang.Exception;
|
||||
|
||||
/**for any error while writing to a node
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class NodeWriteException extends Exception
|
||||
{
|
||||
public NodeWriteException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
155
DataExtractionOSM/src/rtree/NonLeafElement.java
Normal file
155
DataExtractionOSM/src/rtree/NonLeafElement.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
//NonLeafElement.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**
|
||||
Anybody outside the package need not be concerned with this class.
|
||||
Element that will be in a non leaf node
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class NonLeafElement extends Element
|
||||
{
|
||||
/**will contain file pointer pointing to the child node*/
|
||||
long nodePtr;
|
||||
public NonLeafElement( Rect nodeRect,long nodePtr)
|
||||
{
|
||||
super(nodeRect);
|
||||
this.nodePtr = nodePtr;
|
||||
}
|
||||
/**if possible make this function abstract and static in the parent class
|
||||
depends upon the size of the pointer
|
||||
*/
|
||||
public static int sizeInBytes()
|
||||
{
|
||||
return( Rect.sizeInBytes() + Node.LONG_SIZE);
|
||||
}
|
||||
/**
|
||||
This can be the chile node pointer.
|
||||
*/
|
||||
// public Object getPtr()//this is an integer object
|
||||
// {
|
||||
// return(new Integer(nodePtr));
|
||||
// }
|
||||
public long getPtr()//this is an integer object
|
||||
{
|
||||
return nodePtr;
|
||||
}
|
||||
|
||||
public int getElementType()
|
||||
{
|
||||
return Node.NONLEAF_NODE;
|
||||
}
|
||||
// void setPtr(Object ptr)
|
||||
// throws IllegalValueException
|
||||
// {
|
||||
// if(!(ptr instanceof Integer))
|
||||
// throw new IllegalValueException("rtree.NonLeafElement.setPtr: pointer shoild be Integer");
|
||||
// nodePtr = ((Integer)ptr).intValue();
|
||||
// }
|
||||
public void setPtr(long ptr)
|
||||
{
|
||||
nodePtr = ptr;
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
return (super.toString()+"\n\tnodePointer: "+nodePtr);
|
||||
}
|
||||
/**
|
||||
A merge-sort routine for the Packing algo.
|
||||
@param rect the array to sort
|
||||
@param on if 0 then sort on X else on Y(i.e for 1)
|
||||
*/
|
||||
public static void sort( Element[] elmts,int on)
|
||||
{
|
||||
twoWayMerge(elmts,0,elmts.length-1,on);
|
||||
}
|
||||
|
||||
static void twoWayMerge(Element[] elmts,int start,int finish,int on)
|
||||
{
|
||||
try{
|
||||
int size = finish - start+1;
|
||||
if(size <= 2){//last two elements - simple swap
|
||||
if(size < 2)
|
||||
return;
|
||||
int midValI = getMid(elmts[start],on);
|
||||
int midValJ = getMid(elmts[finish],on);
|
||||
Element temp;
|
||||
if(midValI > midValJ){
|
||||
temp = elmts[start];
|
||||
elmts[start] = elmts[finish];
|
||||
elmts[finish] = temp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
Double middle = new Double(start+finish);
|
||||
middle = new Double(Math.ceil(middle.doubleValue()/2));
|
||||
twoWayMerge(elmts,start,middle.intValue(),on);
|
||||
twoWayMerge(elmts,middle.intValue(),finish,on);
|
||||
simpleMerge(elmts,start,middle.intValue(),finish,on);
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("rtree.Element.twoWayMerge: probably index out of bound");
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//simple merge
|
||||
private static void simpleMerge( Element[] elmts,int first,int second,int third,int on)
|
||||
throws Exception
|
||||
{
|
||||
int i = first;
|
||||
int j = second;
|
||||
int l = 0;
|
||||
int midValI;
|
||||
int midValJ;
|
||||
Element[] temp = new Element[third-first+1];
|
||||
while((i < second) && (j <= third)){//loop till one lasts
|
||||
//get the mid values in the given dimension
|
||||
midValI = getMid(elmts[i],on);
|
||||
midValJ = getMid(elmts[j],on);
|
||||
if(midValI <= midValJ)
|
||||
temp[l++] = elmts[i++];
|
||||
else
|
||||
temp[l++] = elmts[j++];
|
||||
}
|
||||
//copy the rest
|
||||
if(i >= second)//give second section
|
||||
while(j <= third)
|
||||
temp[l++] = elmts[j++];
|
||||
else
|
||||
while(i < second)//give first section
|
||||
temp[l++] = elmts[i++];
|
||||
System.arraycopy(temp,0,elmts,first,temp.length);
|
||||
}
|
||||
/**
|
||||
A private class to calculate the mid value in given dimension
|
||||
*/
|
||||
private static int getMid( Element elmt,int on)
|
||||
{
|
||||
if(on == 0)
|
||||
return ((elmt.getRect().getMaxX()
|
||||
+ elmt.getRect().getMinX())/2);
|
||||
else
|
||||
return ((elmt.getRect().getMaxY()
|
||||
+ elmt.getRect().getMinY())/2);
|
||||
}
|
||||
public Object clone()
|
||||
{
|
||||
try{
|
||||
return new NonLeafElement(new Rect(Rectangle.getMinX(), Rectangle.getMinY(),
|
||||
Rectangle.getMaxX(), Rectangle.getMaxY()), nodePtr);
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
248
DataExtractionOSM/src/rtree/Pack.java
Normal file
248
DataExtractionOSM/src/rtree/Pack.java
Normal file
|
@ -0,0 +1,248 @@
|
|||
//Pack.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
/**
|
||||
Modified again on 9/1/2003
|
||||
This class can now be used Pack rtrees at run time i.e an rtree object can now be packed and later used
|
||||
without recreating the rtree.
|
||||
<p>Original comments
|
||||
A utility class that packs a rtree.
|
||||
<br>Pack is a special utility class. This class can also be used to maintain
|
||||
a R-Tree after many insertions and deletions.(Just like defragmentation
|
||||
in windows).
|
||||
<p><b> Never create more than one instance of this class.
|
||||
<br>Never run the methods of this class in any other thread except the main
|
||||
thread and make sure it is the only thread running.
|
||||
<br>Positively remember to reinitialise all the rtree objects after you
|
||||
call <code>packTree</code>.</b>
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class Pack
|
||||
{
|
||||
public Pack(){};
|
||||
|
||||
/**
|
||||
Added this new method that takes a list of <code>Element</code>s and builds a
|
||||
*/
|
||||
public synchronized int packTree(List elmts, String newFile)
|
||||
{
|
||||
try{
|
||||
if(elmts.size() <= Node.MAX){
|
||||
RTree rtree = new RTree(newFile);
|
||||
for(int i=0; i<elmts.size(); i++)
|
||||
rtree.insert((LeafElement)elmts.get(i));
|
||||
rtree.flush();
|
||||
return 0;
|
||||
}
|
||||
return packTree((Element[])elmts.toArray(new Element[elmts.size()]), new RTree(newFile), newFile);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Sort-Tile-Recursive(STR) packing algo. by Leutenegger.
|
||||
<p><b>**FLUSH THE RTREE BEFORE CALLING**</b>
|
||||
<br>Prepocess the file and sort the rectangles
|
||||
<br>Load into file
|
||||
<br>Recursively pack above MBRs to nodes at the next level.
|
||||
<br>If you give the new file name same as the old one then the old would
|
||||
be overwritten. One word of caution, whichever new file name you give, it
|
||||
would be overwritten.
|
||||
@param rtree the rtree object to pack
|
||||
@param newFile the new rtree file after packing
|
||||
@return <b>0</b> if successfully created a new file,
|
||||
<br><b>1</b> if there is no need to pack the file, in this case a new
|
||||
file is not created and the old file is left untouched,
|
||||
<br> Greater than zero if all fail.
|
||||
*/
|
||||
public synchronized int packTree(RTree rtree,String newFile)
|
||||
{
|
||||
try{
|
||||
if(rtree == null)
|
||||
throw new IllegalArgumentException("PackTree.packTree: rtree null");
|
||||
List elmts = rtree.getAllElements();
|
||||
//RTree.chdNodes.removeAll();
|
||||
int ret = packTree((Element[])elmts.toArray(new Element[elmts.size()]), rtree, newFile);
|
||||
return ret;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
private int packTree(Element[] elmts, RTree rtree, String newFile)
|
||||
{
|
||||
try{
|
||||
//long t = System.currentTimeMillis();
|
||||
//rtree.flush();
|
||||
File tmpPckFile = File.createTempFile("pack",null);
|
||||
RandomAccessFile rFile = new RandomAccessFile(tmpPckFile.getAbsolutePath(),"rw");
|
||||
|
||||
if(newFile.equalsIgnoreCase(rtree.getFileName())){//we need a write lock
|
||||
rtree.getFileHdr().lockWrite();
|
||||
}
|
||||
/*the following is required as we may pack an existing tree.. until we find a way to remove nodes of
|
||||
a particular rtree*/
|
||||
RTree.chdNodes.removeAll();
|
||||
//rtree.getFileHdr().getFile().getFD().sync();
|
||||
if(elmts.length <= Node.MAX)//change this for the first method
|
||||
return(1);
|
||||
System.out.println("Pack.packTree : Size of elmts: "+ elmts.length);
|
||||
|
||||
packRec(rFile,tmpPckFile,elmts,elmts.length);
|
||||
|
||||
//craete the new file
|
||||
File fo = new File(newFile);
|
||||
//delete the new file if it exists !!
|
||||
if(fo.exists()){
|
||||
fo.delete();
|
||||
fo.createNewFile();
|
||||
}
|
||||
//overwrite the old rtree file with the temp file
|
||||
FileInputStream fis=new FileInputStream(tmpPckFile);
|
||||
FileOutputStream fos=new FileOutputStream(fo);
|
||||
int i=fis.available();
|
||||
byte b[]=new byte[i];
|
||||
while((i=fis.read(b))!=-1)
|
||||
fos.write(b);
|
||||
fos.close();
|
||||
fis.close();
|
||||
rFile.close();
|
||||
tmpPckFile.deleteOnExit();
|
||||
//System.out.println("Pack.packTree : packing took " + (System.currentTimeMillis() - t));
|
||||
return(0);
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
System.out.println("rtree.RTree.pack: Could not pack rtree, the destination file may be corrupted.");
|
||||
return(2);
|
||||
}
|
||||
finally{//delete the source file header
|
||||
synchronized(rtree){
|
||||
//Here we have the old and the new file as same.. so we update the header
|
||||
try{
|
||||
rtree.updateHdr();
|
||||
if(newFile.equalsIgnoreCase(rtree.getFileName())){//we need a write lock
|
||||
rtree.getFileHdr().unlock();//relaese this lock as this header will be lost for ever
|
||||
}
|
||||
}catch(Exception e){
|
||||
System.out.println("Pack.packTree : The pack tree is made but some other error hs occured. "
|
||||
+"It is recomended to restart the application");
|
||||
if(newFile.equalsIgnoreCase(rtree.getFileName()))//we need a write lock
|
||||
rtree.getFileHdr().unlock();//relaese this lock as this header will be lost for ever
|
||||
}
|
||||
}//synchronized
|
||||
}
|
||||
}
|
||||
private void packRec(RandomAccessFile rFile,File tmpPckFile, Element[] elmts,int length)
|
||||
throws Exception
|
||||
{
|
||||
//P the no. of leaf nodes - ceil(objects/max objects per node)
|
||||
Double temp = new Double(Node.MAX);//temp
|
||||
temp = new Double(Math.ceil(length/temp.doubleValue()));
|
||||
//int P = temp.intValue();//leaves
|
||||
//no. of vertical slices
|
||||
temp = new Double(Math.ceil(Math.sqrt(temp.doubleValue())));
|
||||
int S = temp.intValue();
|
||||
//System.out.println("total slices: "+S);
|
||||
Slice sls[] = new Slice[S];
|
||||
|
||||
//sort all the rectangles on X axis
|
||||
NonLeafElement.twoWayMerge(elmts,0,length-1,0);
|
||||
|
||||
//divide into slices
|
||||
int start = 0;
|
||||
int end;
|
||||
for(int i=0; i<S; i++){
|
||||
if((start + (S*Node.MAX)) <= length)
|
||||
end = start+((S*Node.MAX)-1);
|
||||
else
|
||||
end = length - 1;
|
||||
sls[i] = new Slice(start,end);
|
||||
start = end+1;
|
||||
}
|
||||
//sort each slice on Y axis and write to file
|
||||
for(int i=0; i<S; i++)
|
||||
NonLeafElement.twoWayMerge(elmts,sls[i].start,sls[i].end,1);
|
||||
int newLength = writePckFile(rFile,tmpPckFile,elmts,sls);
|
||||
if(newLength == 1)//last insertion was a root
|
||||
return;
|
||||
packRec(rFile,tmpPckFile,elmts,newLength);
|
||||
}
|
||||
/**
|
||||
Method that handles the low level details of nodes, leaves, file headers etc.
|
||||
It writes the details to the rtree file.
|
||||
@return the no. of new leaf elements created. The element themselves are in
|
||||
the 'elmts' array.
|
||||
*/
|
||||
private int writePckFile(RandomAccessFile rFile,File tmpPckFile,
|
||||
Element[] elmts,Slice[] sls)
|
||||
throws Exception
|
||||
{
|
||||
FileHdr hdr = new FileHdr(Node.FREE_LIST_LIMIT,tmpPckFile.getAbsolutePath());
|
||||
hdr.setBufferPolicy(true);
|
||||
int length;
|
||||
Double totNodes;//total nodes for the slice
|
||||
int netNodes = 0;// !?!!
|
||||
int l=0;//the position on to which the old elmt. would be replaced
|
||||
for(int i=0; i<sls.length; i++){//for each slice
|
||||
//cal. the length of this slice
|
||||
length = sls[i].end - sls[i].start + 1;
|
||||
//calculate the no. of new nodes for the slice
|
||||
totNodes = new Double(length);
|
||||
totNodes= new Double(Math.ceil(totNodes.doubleValue()/Node.MAX));
|
||||
netNodes += totNodes.intValue();
|
||||
//make nodes of the elements in the slice
|
||||
for(int j=0; j<totNodes.intValue(); j++){//loop for each new node
|
||||
Node node = new Node(rFile,tmpPckFile.getAbsolutePath(), Node.NOT_DEFINED,
|
||||
elmts[sls[i].start].getElementType(), hdr);
|
||||
//add elements to the node
|
||||
ArrayList list = new ArrayList(Node.MAX);
|
||||
for(int k=0; (k<Node.MAX) && (sls[i].start <= sls[i].end); k++){
|
||||
//node.insertElement(elmts[sls[i].start++]);
|
||||
list.add(elmts[sls[i].start++]);
|
||||
}
|
||||
node.insertElement((Element[])list.toArray(new Element[list.size()]), true);
|
||||
|
||||
//create the new nonleaf element - always nonleaf
|
||||
NonLeafElement nlf = new NonLeafElement(node.getNodeMBR(),node.getNodeIndex());
|
||||
|
||||
elmts[l++] = (NonLeafElement)nlf.clone();
|
||||
}
|
||||
}
|
||||
return netNodes;
|
||||
}
|
||||
/**An inner class for the packing method*/
|
||||
class Slice
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
Slice(int start,int stop)
|
||||
{
|
||||
this.start = start;
|
||||
this.end = stop;
|
||||
}
|
||||
}
|
||||
/**A wrapper class for int*/
|
||||
class Int
|
||||
{
|
||||
int val;
|
||||
Int(int val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
23
DataExtractionOSM/src/rtree/PageFaultException.java
Normal file
23
DataExtractionOSM/src/rtree/PageFaultException.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
//PageFaultException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**When a page fault occurs in the CachedNodes class
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
class PageFaultException extends Exception
|
||||
{
|
||||
PageFaultException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
47
DataExtractionOSM/src/rtree/Point.java
Normal file
47
DataExtractionOSM/src/rtree/Point.java
Normal file
|
@ -0,0 +1,47 @@
|
|||
//Point.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
//package rtree;
|
||||
/**
|
||||
A simple class used only in nearestNeighbour search.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class Point implements Cloneable
|
||||
{
|
||||
private int X=0,Y=0;
|
||||
public Point(int x,int y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
public int getX()
|
||||
{
|
||||
return X;
|
||||
}
|
||||
public int getY()
|
||||
{
|
||||
return Y;
|
||||
}
|
||||
public Object clone()
|
||||
{
|
||||
return new Point(X,Y);
|
||||
}
|
||||
public String toString()
|
||||
{
|
||||
String ret;
|
||||
ret = "\nThe Point:-";
|
||||
ret += "\n\tX: " + X;
|
||||
ret += "\n\tY: " + Y;
|
||||
return ret;
|
||||
}
|
||||
}
|
1199
DataExtractionOSM/src/rtree/RTree.java
Normal file
1199
DataExtractionOSM/src/rtree/RTree.java
Normal file
File diff suppressed because it is too large
Load diff
359
DataExtractionOSM/src/rtree/RTreeClient.java
Normal file
359
DataExtractionOSM/src/rtree/RTreeClient.java
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
PROGRAMME:
|
||||
PROGRAMMER:
|
||||
DATE:
|
||||
PROJECT:
|
||||
MODIFIED DATE:
|
||||
|
||||
*/
|
||||
package rtree;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
|
||||
public class RTreeClient
|
||||
{
|
||||
private Socket socket;
|
||||
public RTreeClient(String host,int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
socket=new Socket(host,port);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void insert(Element element) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="insert";
|
||||
Object obj[]={element};
|
||||
sendRequest(command,obj);
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public void delete(LeafElement element) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="delete";
|
||||
Object obj[]={element};
|
||||
sendRequest(command,obj);
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List overlaps(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="overlaps";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List nonDisjoint(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="nondisjoint";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List containedBy(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="containedby";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List equal(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="equal";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List meet(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="meet";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List contains(Rect rect) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="contains";
|
||||
Object obj[]={rect};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List getAllElements() throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="getallelements";
|
||||
Object[] response=sendRequest(command,null);
|
||||
//List v=(List)response[0];
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public Rect getTreeMBR() throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="gettreembr";
|
||||
Object[] response=sendRequest(command,null);
|
||||
return (Rect) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public ABL[] nearestSearch(Point pt,long ln,int in) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="nearest";
|
||||
Object obj[]={pt,new Long(ln),new Integer(in)};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
if(response!=null)
|
||||
{
|
||||
ABL abl[]=new ABL[response.length];
|
||||
for(int i=0;i<response.length;i++)
|
||||
{
|
||||
abl[i]=(ABL)response[i];
|
||||
}
|
||||
return abl;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
public List nearestSearch(Point pt,long ln) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
String command="nearestsearch";
|
||||
Object obj[]={pt,new Long(ln)};
|
||||
Object[] response=sendRequest(command,obj);
|
||||
return (List) response[0];
|
||||
}
|
||||
catch(RTreeException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
private Object[] sendRequest(String command,Object[] param) throws RTreeException
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream bout=new ByteArrayOutputStream ();
|
||||
ObjectOutputStream out=new ObjectOutputStream (bout);
|
||||
// ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());
|
||||
OutputStream fout=socket.getOutputStream ();
|
||||
out.writeObject(command);
|
||||
if(param!=null)
|
||||
{
|
||||
out.writeObject(new Integer (param.length));
|
||||
for(int i=0;i<param.length;i++)
|
||||
{
|
||||
out.writeObject(param[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.writeObject(new Integer(0));
|
||||
}
|
||||
// out.flush();
|
||||
out.close();
|
||||
//long time = System.currentTimeMillis();
|
||||
fout.write(bout.toByteArray());
|
||||
fout.flush();
|
||||
// InputStream in=socket.getInputStream();
|
||||
/*
|
||||
while(in.available()==0)
|
||||
{
|
||||
Thread.sleep(10);
|
||||
}
|
||||
int rTotal=in.available();
|
||||
System.out.println("RTotal..........."+rTotal);
|
||||
byte[] bb=new byte[in.available()];
|
||||
in.read(bb,0,in.available());
|
||||
byte ln[]=new byte[10];
|
||||
System.arraycopy(bb,0,ln,0,10);
|
||||
ByteArrayInputStream lin=new ByteArrayInputStream(ln);
|
||||
ObjectInputStream loin=new ObjectInputStream(lin);
|
||||
int total=loin.readInt();
|
||||
byte bbf[]=new byte[rTotal];
|
||||
System.out.println(total+"..."+bbf.length);
|
||||
System.arraycopy(bb,10,bbf,0,rTotal-10);
|
||||
int pos=bbf.length;
|
||||
System.out.println("Postion................."+pos);
|
||||
while(rTotal<total)
|
||||
{
|
||||
int avail=in.available();
|
||||
while(avail==0)
|
||||
{
|
||||
avail=in.available();
|
||||
}
|
||||
byte temp[]=new byte[avail];
|
||||
in.read(temp,0,avail);
|
||||
byte temp1[]=new byte[avail+bbf.length];
|
||||
System.arraycopy(bbf,0,temp1,0,bbf.length);
|
||||
System.arraycopy(temp,0,temp1,bbf.length,temp.length);
|
||||
bbf=temp1;
|
||||
rTotal+=avail;
|
||||
System.out.println(bbf.length+"______________________");
|
||||
System.arraycopy(temp,0,bbf,pos,temp.length);
|
||||
pos+=avail;
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
InputStream in=socket.getInputStream();
|
||||
//System.out.println("RTreeClient.sendRequest : time to receive response "
|
||||
//+ (System.currentTimeMillis() - time));
|
||||
//time = System.currentTimeMillis();
|
||||
|
||||
byte bbf[]=new byte[100];
|
||||
|
||||
int i=0;
|
||||
int total=-1;
|
||||
while(true)
|
||||
{
|
||||
int val=in.read(bbf,i,1);
|
||||
if(val==-1)
|
||||
break;
|
||||
i++;
|
||||
if(i==10)
|
||||
{
|
||||
byte ln[]=new byte[10];
|
||||
System.arraycopy(bbf,0,ln,0,10);
|
||||
ByteArrayInputStream lin=new ByteArrayInputStream(ln);
|
||||
ObjectInputStream loin=new ObjectInputStream(lin);
|
||||
total=loin.readInt();
|
||||
byte temp[]=new byte[total];
|
||||
System.arraycopy(bbf,0,temp,0,bbf.length);
|
||||
bbf=temp;
|
||||
}
|
||||
if(i>=total && total!=-1)
|
||||
{
|
||||
//System.out.println("read completed..."+bbf.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byte tby[]=new byte[bbf.length-10];
|
||||
System.arraycopy(bbf,10,tby,0,tby.length);
|
||||
ByteArrayInputStream bin=new ByteArrayInputStream(tby);
|
||||
ObjectInputStream oIn=new ObjectInputStream(bin);
|
||||
Boolean bool=(Boolean) oIn.readObject();
|
||||
//System.out.println("boolean.........."+bool);
|
||||
Integer count=(Integer) oIn.readObject();
|
||||
//System.out.println("count.........."+count);
|
||||
if(bool.booleanValue())
|
||||
{
|
||||
Object[] obj=new Object[count.intValue()];
|
||||
for(int j=0;j<count.intValue();j++)
|
||||
{
|
||||
obj[j]=oIn.readObject();
|
||||
}
|
||||
// oIn.close();
|
||||
//System.out.println("RTreeClient.sendRequest : time to process input data "
|
||||
// + (System.currentTimeMillis() - time));
|
||||
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (Exception) oIn.readObject();
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
public static void main(String args[])
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
RTreeClient cln=new RTreeClient("localhost",7001);
|
||||
System.out.println("Connection established1...");
|
||||
Rect rect=cln.getTreeMBR();
|
||||
System.out.println("........."+rect);
|
||||
List v=cln.getAllElements();//contains(new Rect(0,0,1000,1000));
|
||||
System.out.println(v.size());
|
||||
System.out.println(v.get(0));
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
} */
|
||||
}
|
23
DataExtractionOSM/src/rtree/RTreeException.java
Normal file
23
DataExtractionOSM/src/rtree/RTreeException.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
//RTreeException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
/**
|
||||
for any major RTree Exception
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class RTreeException extends Exception
|
||||
{
|
||||
public RTreeException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
22
DataExtractionOSM/src/rtree/RTreeInsertException.java
Normal file
22
DataExtractionOSM/src/rtree/RTreeInsertException.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
//RTreeInsertException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
/**When some error arises inserting an element
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class RTreeInsertException extends Exception
|
||||
{
|
||||
public RTreeInsertException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
247
DataExtractionOSM/src/rtree/ReadNode.java
Normal file
247
DataExtractionOSM/src/rtree/ReadNode.java
Normal file
|
@ -0,0 +1,247 @@
|
|||
//ReadNode.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/***********************************************************************************************************
|
||||
* * *
|
||||
* This is a special purpose class that is alowed read only operartion on tree. Any write operation *
|
||||
* would give error. *
|
||||
* This class was necessary to solve the following problem. Since none of the nodes are cloned when given *
|
||||
* to the clients, they can become problematic when multiple reads on the same node is going on. *
|
||||
* Because of the new buffer policy we do not clone node, it is like a single node in the whole system. *
|
||||
* But the obvious problem is multiple read threads when reading nodes. *
|
||||
* No though problem when writing as the whole tree is locked. What we can do is that clients themselves *
|
||||
* tell the cache that they need a cloned node and that it willnot be used for write purpose. *
|
||||
* This class does exactly that. *
|
||||
* @author Prachuryya Barua
|
||||
***********************************************************************************************************/
|
||||
|
||||
class ReadNode extends Node
|
||||
{
|
||||
ReadNode()
|
||||
{
|
||||
}
|
||||
public static ReadNode makeReadNode(Node node)
|
||||
{
|
||||
ReadNode rdNode = new ReadNode();
|
||||
try{
|
||||
//Integer intVal;
|
||||
rdNode.file = node.file;
|
||||
rdNode.dirty = node.dirty;
|
||||
rdNode.fileName = new String(node.fileName.toCharArray());
|
||||
rdNode.nodeIndex = node.nodeIndex;
|
||||
//rdNode.isNodeEmpty = node.isNodeEmpty;
|
||||
rdNode.sorted = node.sorted;
|
||||
rdNode.nodeMBR = new Rect(node.nodeMBR);//remove
|
||||
rdNode.elements = new Element[node.elements.length];
|
||||
if(node.elementType == LEAF_NODE){
|
||||
for(int i=0; i<node.totalElements; i++)
|
||||
rdNode.elements[i] = new LeafElement(new Rect(node.elements[i].getRect()),
|
||||
node.elements[i].getPtr());
|
||||
}else{
|
||||
for(int i=0; i<node.totalElements; i++)
|
||||
rdNode.elements[i] = new NonLeafElement(new Rect(node.elements[i].getRect()),
|
||||
node.elements[i].getPtr());
|
||||
}
|
||||
// for(int i=0; i<node.totalElements; i++){
|
||||
// if(node.elementType == LEAF_NODE)
|
||||
// rdNode.elements[i] = new LeafElement(new Rect(node.elements[i].getRect()),
|
||||
// node.elements[i].getPtr());
|
||||
// else
|
||||
// rdNode.elements[i] = new NonLeafElement(new Rect(node.elements[i].getRect()),
|
||||
// node.elements[i].getPtr());
|
||||
// }//if
|
||||
// }//for
|
||||
rdNode.fileHdr = node.fileHdr;
|
||||
rdNode.totalElements = node.totalElements;
|
||||
rdNode.parent = node.parent;
|
||||
rdNode.elementSize = node.elementSize;
|
||||
rdNode.elementType = node.elementType;
|
||||
return rdNode;
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
This method delets the element with the given index from the node.
|
||||
It rewrites the node.
|
||||
This method now also being used to write the whole node to the file.
|
||||
@param index The element to delete. Give -1 if the whole node is to be flushed.
|
||||
@param force Whether to force IO. As this method is also used to write the whole node, this was
|
||||
required.
|
||||
@return thengaa!
|
||||
XXX : This is till not correct.
|
||||
*/
|
||||
public void deleteElement(int index, boolean force)
|
||||
throws IllegalValueException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public void insertElement(Element elmt)
|
||||
throws NodeWriteException, NodeFullException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public void insertElement(Element[] elmts, boolean updateChldrn)
|
||||
throws NodeWriteException, NodeFullException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public int getElementType()
|
||||
{
|
||||
return super.getElementType();
|
||||
}
|
||||
public long getNodeIndex()//for new nodes
|
||||
{
|
||||
return super.getNodeIndex();
|
||||
}
|
||||
Rect[] getAllRectangles()
|
||||
throws IllegalValueException
|
||||
{
|
||||
return super.getAllRectangles();
|
||||
}
|
||||
public Element getLeastEnlargement(Element elmt)
|
||||
throws NodeEmptyException, IllegalValueException, NodeWriteException
|
||||
{
|
||||
return super.getLeastEnlargement(elmt);
|
||||
}
|
||||
boolean isInsertPossible()
|
||||
{
|
||||
return super.isInsertPossible();
|
||||
}
|
||||
|
||||
public Node[] splitNode(Element elmtM1, long slotIndex)
|
||||
throws RTreeException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public long getParent()
|
||||
{
|
||||
return super.getParent();
|
||||
}
|
||||
public int getElementIndex(long ptr/*Object ptr*/)
|
||||
{
|
||||
return super.getElementIndex(ptr);
|
||||
}
|
||||
/**
|
||||
Used to overwrite the old Element with the new one.
|
||||
It modifies the element in the disk as well as in the local variables.
|
||||
*/
|
||||
public void modifyElement(int index,Element elmt)
|
||||
throws IllegalValueException,IOException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
/**
|
||||
Overloaded
|
||||
*/
|
||||
public void modifyElement(int index,long pointer)
|
||||
throws IllegalValueException,IOException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
/**
|
||||
Overloaded
|
||||
*/
|
||||
public void modifyElement(int index,Rect rect)
|
||||
throws IllegalValueException,IOException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
/**
|
||||
This function runs a loop on the elements to calculate the total MBR.
|
||||
Therefore in case if you already have loop that runs through each of the entries,
|
||||
then it is better to calculate MBR in that loop without calling this method.
|
||||
@throws IllegalValueException When there are no elements in the node.
|
||||
*/
|
||||
public Rect getNodeMBR()
|
||||
throws IllegalValueException
|
||||
{
|
||||
return super.getNodeMBR();
|
||||
}
|
||||
/**
|
||||
No error echecking at all.
|
||||
*/
|
||||
public void setParent(long /*int*/ prnt)
|
||||
throws IOException, NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public int getTotalElements()
|
||||
{
|
||||
return super.getTotalElements();
|
||||
}
|
||||
/**
|
||||
Although it returns all the elements but the total elements will not be equal to the length of
|
||||
the returned array.Therefore <br><b>Never Use <code>.length</code> field With the Returned Array
|
||||
</b>. Instead use <code>getTotalElements()</code>.
|
||||
@return An element Array.
|
||||
*/
|
||||
public Element[] getAllElements()
|
||||
{
|
||||
return super.getAllElements();
|
||||
}
|
||||
Element getElement(int index)
|
||||
throws IllegalValueException
|
||||
{
|
||||
return super.getElement(index);
|
||||
}
|
||||
/**
|
||||
Adds the node to the free stack.
|
||||
Be very careful with this method because once called, this node may be
|
||||
given to any new node even when you have not destroyed its object.
|
||||
If the node is the only node then it updates the file header as well.
|
||||
</br><i><b>Once called, there is no turning back!</b></i>.
|
||||
*/
|
||||
public void deleteNode()
|
||||
throws NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
/**
|
||||
* This method is added to sort the elements in this node to help sweepline algorithm.
|
||||
*/
|
||||
void sweepSort()//check out for null elements
|
||||
{
|
||||
super.sweepSort();
|
||||
}//sweepSort
|
||||
/**
|
||||
This is a new methos that will help the phylosophy where one should write to tbe cache only when
|
||||
required.
|
||||
@return true if needed write and written or false (not dirty).
|
||||
*/
|
||||
public boolean flush()
|
||||
throws NodeWriteException
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
void setDirty(boolean val)
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
public boolean isDirty()
|
||||
{
|
||||
throw new UnsupportedOperationException("operation not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
562
DataExtractionOSM/src/rtree/Rect.java
Normal file
562
DataExtractionOSM/src/rtree/Rect.java
Normal file
|
@ -0,0 +1,562 @@
|
|||
//Rect.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**
|
||||
It is very easy to extend this program to n dimensions. Here every thing is
|
||||
hard coaded for 2 dim. To convert to more than 2 dim. :-
|
||||
<br>make the point class to hold the required dimensions.(keep an array of
|
||||
dimensions)
|
||||
<br>The rect class needs the four points directly, instead of that make it to
|
||||
accept Point as its argument in the constructor.
|
||||
<br>Then on deal with the point class directly instead of the four points
|
||||
directly.
|
||||
<p>The methods of relational topology(equals,contains etc.) are from various
|
||||
papers by <b>D. Papadias</b> and mainly from Modeling Topological Spatial
|
||||
Relation: Strategies for Query Processing.- <b>Egenhofer</b>
|
||||
<br>The methods are nothing but set theories.
|
||||
<p>In GIS there can be many types of combinations of the topological relations.
|
||||
The theories of these combinations are given in the above said papers. If
|
||||
required this class can be improved for those conditions.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
//TODO: Apply the isNull considerations.
|
||||
// Take the common procedures in overloaded methods to one method.
|
||||
public class Rect implements java.io.Serializable
|
||||
{
|
||||
private int minX=0,minY=0,maxX=0,maxY=0;
|
||||
boolean isNull = false;
|
||||
public Rect()
|
||||
{
|
||||
initNull();
|
||||
}
|
||||
|
||||
public Rect(int topX,int topY,int botX, int botY)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if((topX > botX) || (topY > botY)){
|
||||
System.out.println("\ttopX:"+topX+"\ttopY:"+topY+"\tbotX:"+botX+"\tbotY:"+botY);
|
||||
throw new IllegalValueException("rtree.Rect.Rect: wrong order of params.");
|
||||
}
|
||||
init(topX,topY,botX,botY);
|
||||
}
|
||||
Rect(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.Rect: Param is null.");
|
||||
if(rect.isNull()){
|
||||
initNull();
|
||||
}
|
||||
else
|
||||
init(rect.getMinX(), rect.getMinY(), rect.getMaxX(), rect.getMaxY());
|
||||
}
|
||||
private void initNull()
|
||||
{
|
||||
minX = 0;
|
||||
minY = 0;
|
||||
maxX = -1;
|
||||
maxY = -1;
|
||||
isNull = true;
|
||||
}
|
||||
private void init(int minX, int minY, int maxX, int maxY)
|
||||
{
|
||||
this.minX = minX;
|
||||
this.minY = minY;
|
||||
this.maxX = maxX;
|
||||
this.maxY = maxY;
|
||||
isNull = false;
|
||||
}
|
||||
/*
|
||||
If you want to make the constructor take Point, then....
|
||||
Point minP,maxP;
|
||||
Rect(int minX,int minY,int botX, int botY)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if((minX > maxX) || (minY > maxY))
|
||||
throw new IllegalValueException("rtree.Rect.Rect: "
|
||||
+"minP > maxP ?");
|
||||
minP = new Point(minX,minY);
|
||||
maxP = new Point(maxX,maxY);
|
||||
}
|
||||
Rect(Point minP,Point maxP)
|
||||
throws IllgalValueException
|
||||
{
|
||||
if((minP == null) || (maxP == null))
|
||||
throw new IllegalValueException("rtree.Rect.Rect: "
|
||||
+"Either of the point are null");
|
||||
if((minP.getX() > maxP.getX()) || (minP.getY() > maxP.getY()))
|
||||
throw new IllegalValueException("rtree.Rect.Rect: "
|
||||
+"minP > maxP?");
|
||||
this.minP = (Point)minP.clone();
|
||||
this.maxP = (Point)maxP.clone();
|
||||
}
|
||||
*/
|
||||
public boolean isNull()
|
||||
{
|
||||
return isNull;
|
||||
//if(minX == 0 && minY == 0 && maxX == -1 && maxY == -1)
|
||||
//return true;
|
||||
//else
|
||||
//return false;
|
||||
}
|
||||
public static int sizeInBytes()
|
||||
{
|
||||
return(Node.INTEGER_SIZE*4);//depends upon the points
|
||||
}
|
||||
public int getArea()
|
||||
{
|
||||
if(isNull())
|
||||
return 0;
|
||||
return((maxX-minX)*(maxY-minY));
|
||||
}
|
||||
public int getWidth()
|
||||
{
|
||||
if(isNull())
|
||||
return 0;
|
||||
return(Math.abs(maxX - minX));
|
||||
}
|
||||
public int getHeight()
|
||||
{
|
||||
if(isNull())
|
||||
return 0;
|
||||
return(Math.abs(maxY - minY));
|
||||
}
|
||||
public int getMinX()
|
||||
{
|
||||
return(minX);
|
||||
}
|
||||
public int getMinY()
|
||||
{
|
||||
return(minY);
|
||||
}
|
||||
public int getMaxX()
|
||||
{
|
||||
return(maxX);
|
||||
}
|
||||
public int getMaxY()
|
||||
{
|
||||
return(maxY);
|
||||
}
|
||||
/**
|
||||
Include the given Rectangle.
|
||||
*/
|
||||
public void expandToInclude(Rect rect)
|
||||
{
|
||||
if(rect == null || rect.isNull())
|
||||
return;
|
||||
|
||||
if(this.isNull()){
|
||||
init(rect.getMinX(),rect.getMinY(), rect.getMaxX(), rect.getMaxY());
|
||||
return;
|
||||
}
|
||||
minX = Math.min(rect.getMinX(),minX);//minX
|
||||
minY = Math.min(rect.getMinY(),minY);//minY
|
||||
maxX = Math.max(rect.getMaxX(),maxX);//maxX
|
||||
maxY = Math.max(rect.getMaxY(),maxY);//maxY
|
||||
}
|
||||
/**
|
||||
return the minimum bounding rectangle of this rectangle and the passed
|
||||
rectangle.
|
||||
*/
|
||||
public Rect getResultingMBR(Rect rectangle)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rectangle == null)
|
||||
throw new IllegalValueException("rtree.Rect.getResultingMBR : Rect is null");
|
||||
if(rectangle.isNull())
|
||||
if(this.isNull())
|
||||
return new Rect();
|
||||
else
|
||||
return new Rect(this);
|
||||
else//rectangle is not null
|
||||
if(this.isNull())
|
||||
return rectangle;
|
||||
//if nobody is "isNull"
|
||||
int topX,topY,botX,botY;
|
||||
topX = Math.min(rectangle.getMinX(),minX);//minX
|
||||
topY = Math.min(rectangle.getMinY(),minY);//minY
|
||||
botX = Math.max(rectangle.getMaxX(),maxX);//maxX
|
||||
botY = Math.max(rectangle.getMaxY(),maxY);//maxY
|
||||
return(new Rect(topX,topY,botX,botY));
|
||||
}
|
||||
/**
|
||||
Overloaded type of the previous function - but static
|
||||
*/
|
||||
public static Rect getResultingMBR(Rect source, Rect dest)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if((dest == null) || (source == null))
|
||||
throw new IllegalValueException("rtree.Rect.getResultingMBR : Rect is null");
|
||||
return source.getResultingMBR(dest);
|
||||
}
|
||||
/**
|
||||
Another overloaded version - but static
|
||||
*/
|
||||
public static Rect getResultingMBR(Rect[] rects)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rects.length <= 0)
|
||||
throw new IllegalValueException("rtree.Rect.getResultingMBR : "+
|
||||
"Array of rectangles are empty.");
|
||||
Rect result = rects[0];
|
||||
for(int i=1; i<rects.length; ++i)
|
||||
result = getResultingMBR(rects[i],result);
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
Another overloaded version - but static
|
||||
*/
|
||||
public static Rect getResultingMBR(Rect[] rects, Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
Rect result = getResultingMBR(rects);
|
||||
result = getResultingMBR(rect,result);
|
||||
return result;
|
||||
}
|
||||
//--------------------------Topological methods---------------------------
|
||||
/**
|
||||
Checks if this rectangle contains 'rect'.
|
||||
<br>Checks the two minimal conditions from 'contains' matrix(Egenhofer.)
|
||||
<br>Correct for Point as well.
|
||||
*/
|
||||
public boolean contains(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.contains: null argument");
|
||||
boolean ret = true;
|
||||
//m12 = true && m22 = false
|
||||
//X dim.
|
||||
if((minX >= rect.getMinX()) || (maxX <= rect.getMaxX()))
|
||||
return false;
|
||||
//Y dim.
|
||||
if((minY >= rect.getMinY()) || (maxY <= rect.getMaxY()))
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
The difference betn. this method and <code>contains</code> is that this method returns true
|
||||
even if the <code>covers</code> condition if true.
|
||||
@return true if this rectangle completely encloses 'rect'.
|
||||
*/
|
||||
|
||||
public boolean encloses(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.overlaps: null argument");
|
||||
boolean ret = true;
|
||||
//X dim.
|
||||
if((minX > rect.getMinX()) || (maxX < rect.getMaxX()))
|
||||
return false;
|
||||
//Y dim.
|
||||
if((minY > rect.getMinY()) || (maxY < rect.getMaxY()))
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if this rectangle is contained by 'rect'
|
||||
*/
|
||||
public boolean containedBy(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.containedBy:null argument");
|
||||
boolean ret = true;
|
||||
//m21 = true && m22 = false
|
||||
//X dim.
|
||||
if((rect.getMinX() >= minX) || (rect.getMaxX() <= maxX))
|
||||
return false;
|
||||
//Y dim.
|
||||
if((rect.getMinY() >= minY) || (rect.getMaxY() <= maxY))
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
This method also gives whether one point is over another, if you do not
|
||||
want that much precision then comment the line.This will improve performance.
|
||||
@return true if both the rectangle overlap/intresect else false.
|
||||
<br><b>Note:-</b>This method is not precisely according to Egenhofer.
|
||||
*/
|
||||
public boolean overlaps(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("Rect.overlaps: null argument");
|
||||
int rectMinX = rect.getMinX();
|
||||
int rectMinY = rect.getMinY();
|
||||
int rectMaxX = rect.getMaxX();
|
||||
int rectMaxY = rect.getMaxY();
|
||||
boolean ret = false;
|
||||
//if one point object is over another then.....
|
||||
if((minX == rectMinX) && (minY == rectMinY) && (maxX == rectMaxX) && (maxY == rectMaxY))
|
||||
return true;
|
||||
//if you do not want this much precision then comment above written line.
|
||||
|
||||
//X dim.
|
||||
if((minX < rectMaxX) && (maxX > rectMinX))
|
||||
ret = true;
|
||||
else
|
||||
return false;
|
||||
//Y dim.
|
||||
if((minY < rectMaxY) && (maxY > rectMinY))
|
||||
ret = true;
|
||||
else
|
||||
return false;
|
||||
|
||||
return ret;
|
||||
}//overlaps
|
||||
|
||||
/**
|
||||
Saperate or not(Egenhofer).
|
||||
<br>To check if two rectangles intersect in any way then call '!disjoint()'.
|
||||
*/
|
||||
public boolean disjoint(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.disjoint: null argument");
|
||||
boolean ret = true;
|
||||
//m12 = false && m22 = false
|
||||
//X dim.
|
||||
if((minX <= rect.getMaxX()) && (maxX >= rect.getMinX()))
|
||||
ret = false;
|
||||
else
|
||||
return ret;
|
||||
//Y dim.
|
||||
if((minY <= rect.getMaxY()) && (maxY >= rect.getMinY()))
|
||||
ret = false;
|
||||
else
|
||||
ret = true;
|
||||
return ret;
|
||||
|
||||
}//disjoint - over
|
||||
/**
|
||||
Checks if both the rectangles meet or not.
|
||||
*/
|
||||
public boolean meet(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.meet: null argument");
|
||||
boolean ret = true;
|
||||
//m11 = false
|
||||
if(disjoint(rect))
|
||||
return false;
|
||||
//if both have common area then exit with false.
|
||||
if((minX < rect.getMaxX()) && (maxX > rect.getMinX()))
|
||||
if((minY < rect.getMaxY()) && (maxY > rect.getMinY()))
|
||||
return false;
|
||||
System.out.println("Raj!");
|
||||
//m22 = true
|
||||
if((minX == rect.getMaxX()) || (maxX == rect.getMinX()))
|
||||
return true;
|
||||
else
|
||||
ret = false;
|
||||
if((minY == rect.getMaxY()) || (maxY == rect.getMinY()))
|
||||
ret = true;
|
||||
return ret;
|
||||
|
||||
}//meet
|
||||
/**
|
||||
Checks if this rectangle contains 'rect'. This method is incomplete. It can
|
||||
be finished if required.(Depends on query requirements)
|
||||
|
||||
<pre>
|
||||
---------------
|
||||
| |
|
||||
| |------|
|
||||
| |'rect'|
|
||||
| |------|
|
||||
| |
|
||||
---------------
|
||||
</pre>
|
||||
*/
|
||||
public boolean covers(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.covers: null argument");
|
||||
boolean ret = true;
|
||||
//m12 = true
|
||||
if((minX > rect.getMaxX()) || (maxX < rect.getMinX()))
|
||||
return false;
|
||||
if((minY > rect.getMaxY()) || (maxY < rect.getMinY()))
|
||||
return false;
|
||||
//m21 = false
|
||||
if((minX < rect.getMinX()) && (maxX < rect.getMaxX()))
|
||||
return false;
|
||||
if((minY < rect.getMinY()) && (maxY < rect.getMaxY()))
|
||||
return false;
|
||||
//m22 = true
|
||||
if((minX != rect.getMinX()) && (maxX != rect.getMaxX()))
|
||||
return false;
|
||||
if((minY != rect.getMinY()) && (maxY != rect.getMaxY()))
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
Checks if this rectangle is equal to 'rect'
|
||||
*/
|
||||
public boolean equals(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.equals: null argument");
|
||||
//m21=false && m23=false
|
||||
if((minX != rect.getMinX()) || (maxX != rect.getMaxX()))
|
||||
return false;
|
||||
if((minY != rect.getMinY()) || (maxY != rect.getMaxY()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String ret;
|
||||
ret = "\nThe Rectangle:-";
|
||||
ret += "\n\tminX: " + minX;
|
||||
ret += "\n\tminY: " + minY;
|
||||
ret += "\n\tmaxX: " + maxX;
|
||||
ret += "\n\tmaxY: " + maxY;
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
Calculate the Euclidean distance between the point and the MBR.
|
||||
To calculate the distance(MINDIST) betn. a Point and Rectangle in
|
||||
n dimension. In our case we consider only 2 dimensions.
|
||||
<br><b>Note:-</b> The distance is the square of the actual distance. To find the actual
|
||||
distance, square root the returned value.
|
||||
*/
|
||||
public static long minDist(Point p, Rect rect)
|
||||
{
|
||||
long minDist;
|
||||
int ri;//see Roussopoulos for notations
|
||||
int pX = p.getX();
|
||||
int pY = p.getY();
|
||||
int minX = rect.getMinX();
|
||||
int minY = rect.getMinY();
|
||||
int maxX = rect.getMaxX();
|
||||
int maxY = rect.getMaxY();
|
||||
//for X dim.
|
||||
if(pX < minX)
|
||||
ri = minX;
|
||||
else if(pX > maxX)
|
||||
ri = maxX;
|
||||
else
|
||||
ri = pX;
|
||||
Long temp = new Long(Math.abs(pX - ri));
|
||||
minDist = (new Double(Math.pow(temp.doubleValue(),2))).longValue();
|
||||
//for Y dim.
|
||||
if(pY < minY)
|
||||
ri = minY;
|
||||
else if(pY > maxY)
|
||||
ri = maxY;
|
||||
else
|
||||
ri = pY;
|
||||
temp = new Long(Math.abs(pY - ri));
|
||||
minDist += (new Double(Math.pow(temp.doubleValue(),2))).longValue();
|
||||
return minDist;
|
||||
}
|
||||
/**
|
||||
To find the minimum of the maximum distances from a point to a Rectangle
|
||||
<b>(Not implemeneted yet).</b>
|
||||
For further details see Roussopoulos.
|
||||
If we apply Cheung then it will not be used.
|
||||
*/
|
||||
public static int minMaxDist(Point p, Rect rect)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
/**
|
||||
* Will return the intersection of the <code>this</code> and <code>rect</code>.
|
||||
* @param rect The other <code>Rect</code>
|
||||
*/
|
||||
public Rect intersection(Rect rect)
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalArgumentException("Rect.instersection : Argument Rect is null");
|
||||
int x1;// = 0
|
||||
int y1;// = 0;
|
||||
int x2;// = -1;
|
||||
int y2;// = -1;
|
||||
//minX
|
||||
if(minX < rect.minX)
|
||||
x1 = rect.minX;
|
||||
else
|
||||
x1 = minX;
|
||||
//minY
|
||||
if(minY < rect.minY)
|
||||
y1 = rect.minY;
|
||||
else
|
||||
y1 = minY;
|
||||
//maxX
|
||||
if(maxX > rect.maxX)
|
||||
x2 = rect.maxX;
|
||||
else
|
||||
x2 = maxX;
|
||||
//maxY
|
||||
if(maxY > rect.maxY)
|
||||
y2 = rect.maxY;
|
||||
else
|
||||
y2 = maxY;
|
||||
try{
|
||||
if(x1 > x2 || y1 > y2)
|
||||
return new Rect();
|
||||
else
|
||||
return new Rect(x1, y1, x2, y2);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return new Rect();
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO
|
||||
/*
|
||||
New disjunctions of topological relations can be derived from the
|
||||
minimal subset algorithm(Egenhofer)
|
||||
<br> To do so first make a method for each of the matrix element. Then
|
||||
using the algo. find the conditions of the matrix to satisfy and call
|
||||
the desired methods.
|
||||
Although this is possible through the combinations of the eight methods
|
||||
directly but it would need a lot of processing.
|
||||
*/
|
||||
|
||||
/*
|
||||
The diif. bet. this function and 'overlap' is that the latter returns
|
||||
false if the two rects have only a side(s) in common but no area.
|
||||
This method returns true if both the rects have either or both
|
||||
area and side(s) common.
|
||||
<br><b>returns true if ((meet=true)||(overlap=true)||(covers=true)||
|
||||
(equal=true)) or it can be said not disjoint.
|
||||
@return true if this rect. touches or overlaps with 'rect'
|
||||
*/
|
||||
/*
|
||||
public boolean intersect(Rect rect)
|
||||
throws IllegalValueException
|
||||
{
|
||||
if(rect == null)
|
||||
throw new IllegalValueException("rtree.Rect.overlaps: null argument");
|
||||
boolean ret = true;
|
||||
//X dim.
|
||||
if((minX > rect.getMaxX()) || (maxX < rect.getMinX()))
|
||||
return false;
|
||||
//Y dim.
|
||||
if((minY > rect.getMaxY()) || (maxY < rect.getMinY()))
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*/
|
||||
|
24
DataExtractionOSM/src/rtree/StackOverflowException.java
Normal file
24
DataExtractionOSM/src/rtree/StackOverflowException.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
//StackOverflowException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
/**When the stack overflows
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
class StackOverflowException extends Exception
|
||||
{
|
||||
StackOverflowException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
24
DataExtractionOSM/src/rtree/StackUnderflowException.java
Normal file
24
DataExtractionOSM/src/rtree/StackUnderflowException.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
//StackUnderflowException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
|
||||
package rtree;
|
||||
|
||||
/**When the stack underflows
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
class StackUnderflowException extends Exception
|
||||
{
|
||||
StackUnderflowException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
52
DataExtractionOSM/src/rtree/join/CompElmtX.java
Normal file
52
DataExtractionOSM/src/rtree/join/CompElmtX.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
//CompElmtX.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import java.util.Comparator;
|
||||
import rtree.*;
|
||||
|
||||
/**
|
||||
An internal Comparable class to sort Element.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class CompElmtX implements Comparator
|
||||
{
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
if(o1 instanceof Element && o2 instanceof Element){
|
||||
Rect r1 = ((Element)o1).getRect();
|
||||
Rect r2 = ((Element)o2).getRect();
|
||||
return r1.getMinX() - r2.getMinX();
|
||||
//if(r1.getMinX() <= r2.getMinX())
|
||||
//return -1;
|
||||
//else if(r1.getMinX() == r2.getMinX())
|
||||
//return 0;
|
||||
//else
|
||||
//return 1;
|
||||
}
|
||||
// else if(o1 == null && o2 != null){
|
||||
// return -1;
|
||||
// }else if(o1 != null && o2 == null){
|
||||
// return 1;
|
||||
// }else if(o1 == null && o2 == null){
|
||||
// return Integer.MAX_VALUE;
|
||||
//}
|
||||
else{
|
||||
throw new ClassCastException("Rect.compareTo : wrong object(s) passed : "
|
||||
+o1.getClass().getName() + " o2 " + o2.getClass().getName());
|
||||
}
|
||||
}
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
67
DataExtractionOSM/src/rtree/join/ContainedByPred.java
Normal file
67
DataExtractionOSM/src/rtree/join/ContainedByPred.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
//ContainedByPred.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
The "intersects" binary predicate. This is only for the sweepline algo.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class ContainedByPred extends Predicate
|
||||
{
|
||||
public ContainedByPred(){}
|
||||
|
||||
public void relate(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
//System.out.println("SweepLine.internalLoop : before pairs size : " + pairs.size());
|
||||
if(evtSide == Join.RIGHT){
|
||||
for(int i=from;
|
||||
(i<others.length) && (others[i] != null) &&
|
||||
(others[i].getRect().getMaxX() < event.getRect().getMaxX());
|
||||
i++){//while others are still intersecting with the event
|
||||
if(event.getRect().getMinX() < others[i].getRect().getMinX() &&//check x as well
|
||||
event.getRect().getMinY() < others[i].getRect().getMinY() &&//check the y coordinate
|
||||
event.getRect().getMaxY() > others[i].getRect().getMaxY()){
|
||||
if(evtSide == Join.LEFT)
|
||||
pairs.add(p.paired(event, others[i]));
|
||||
else
|
||||
pairs.add(p.paired(others[i], event));
|
||||
}//if
|
||||
}//for
|
||||
//System.out.println("SweepLine.internalLoop : after pairs size : " + pairs.size());
|
||||
}else{
|
||||
//do nothing and see the comments in ContainsPredicate
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@param side The side of <code>elmt1</code>.
|
||||
*/
|
||||
public boolean relateMismatch(Element elmt1, Element elmt2, int side)
|
||||
{
|
||||
try{
|
||||
if(elmt1 instanceof NonLeafElement || elmt2 instanceof NonLeafElement)
|
||||
return elmt1.getRect().overlaps(elmt2.getRect());
|
||||
else{
|
||||
if(side == Join.LEFT)
|
||||
return elmt1.getRect().containedBy(elmt2.getRect());
|
||||
else
|
||||
return elmt2.getRect().containedBy(elmt1.getRect());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
72
DataExtractionOSM/src/rtree/join/ContainsPred.java
Normal file
72
DataExtractionOSM/src/rtree/join/ContainsPred.java
Normal file
|
@ -0,0 +1,72 @@
|
|||
//ContainsPred.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
The "intersects" binary predicate. This is only for the sweepline algo.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class ContainsPred extends Predicate
|
||||
{
|
||||
public ContainsPred(){}
|
||||
|
||||
|
||||
public void relate(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
//System.out.println("SweepLine.internalLoop : before pairs size : " + pairs.size());
|
||||
if(evtSide == Join.LEFT){
|
||||
for(int i=from;
|
||||
(i<others.length) && (others[i] != null) &&
|
||||
(others[i].getRect().getMaxX() < event.getRect().getMaxX());
|
||||
i++){//while others are still intersecting with the event
|
||||
if(event.getRect().getMinY() < others[i].getRect().getMinY() &&
|
||||
event.getRect().getMaxY() > others[i].getRect().getMaxY()){//check the y coordinate
|
||||
if(evtSide == Join.LEFT)
|
||||
pairs.add(p.paired(event, others[i]));
|
||||
else
|
||||
pairs.add(p.paired(others[i], event));
|
||||
}//if
|
||||
}//for
|
||||
}else{
|
||||
/*do nothing as, if left contains right then left must have appeared before at all cost
|
||||
.In other words, if the event took place at a right side then it is not supposed to contain anything.
|
||||
We need to concern overselves with events because of left tree only.
|
||||
*/
|
||||
}
|
||||
//System.out.println("SweepLine.internalLoop : after pairs size : " + pairs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
@param side The side of <code>elmt1</code>.
|
||||
*/
|
||||
public boolean relateMismatch(Element elmt1, Element elmt2, int side)
|
||||
{
|
||||
//System.out.println("ContainsPred.relateMismatch :");
|
||||
|
||||
try{
|
||||
if(elmt1 instanceof NonLeafElement || elmt2 instanceof NonLeafElement)
|
||||
return elmt1.getRect().overlaps(elmt2.getRect());
|
||||
else{
|
||||
if(side == Join.LEFT)
|
||||
return elmt1.getRect().contains(elmt2.getRect());
|
||||
else
|
||||
return elmt2.getRect().contains(elmt1.getRect());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
70
DataExtractionOSM/src/rtree/join/EqualsPred.java
Normal file
70
DataExtractionOSM/src/rtree/join/EqualsPred.java
Normal file
|
@ -0,0 +1,70 @@
|
|||
//EqualsPred.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
The "intersects" binary predicate. This is only for the sweepline algo.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class EqualsPred extends Predicate
|
||||
{
|
||||
public EqualsPred(){}
|
||||
// EqualsPred(Pair p)
|
||||
// {
|
||||
// super(p);
|
||||
// }
|
||||
public void relate(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
//System.out.println("SweepLine.internalLoop : before pairs size : " + pairs.size());
|
||||
for(int i=from;
|
||||
(i<others.length) && (others[i] != null) &&
|
||||
(others[i].getRect().getMinX() <= event.getRect().getMaxX());
|
||||
i++){//while others are still intersecting with the event
|
||||
if(event.getRect().getMinY() < others[i].getRect().getMaxY() &&
|
||||
event.getRect().getMaxY() > others[i].getRect().getMinY()){//check the y coordinate
|
||||
if(evtSide == Join.LEFT)
|
||||
pairs.add(p.paired(event, others[i]));
|
||||
else
|
||||
pairs.add(p.paired(others[i], event));
|
||||
}//if
|
||||
}//for
|
||||
//System.out.println("SweepLine.internalLoop : after pairs size : " + pairs.size());
|
||||
}
|
||||
// public boolean relateMismatch(Element nlElmt, Element lfElmt)
|
||||
// {
|
||||
// try{
|
||||
// if(nlElmt instanceof NonLeafElement || lfElmt instanceof NonLeafElement)
|
||||
// return nlElmt.getRect().overlaps(lfElmt.getRect());
|
||||
// else
|
||||
// return nlElmt.getRect().equals(lfElmt.getRect());
|
||||
// }catch(Exception e){
|
||||
// e.printStackTrace();
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
public boolean relateMismatch(Element elmt1, Element elmt2, int side)
|
||||
{
|
||||
try{
|
||||
if(elmt1 instanceof NonLeafElement || elmt2 instanceof NonLeafElement)
|
||||
return elmt1.getRect().overlaps(elmt2.getRect());
|
||||
else{
|
||||
return elmt1.getRect().equals(elmt2.getRect());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
50
DataExtractionOSM/src/rtree/join/IntersectPred.java
Normal file
50
DataExtractionOSM/src/rtree/join/IntersectPred.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
//IntersectPred.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
The "intersects" binary predicate. This is only for the sweepline algo.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class IntersectPred extends Predicate
|
||||
{
|
||||
public IntersectPred(){}
|
||||
public void relate(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
//System.out.println("SweepLine.internalLoop : before pairs size : " + pairs.size());
|
||||
for(int i=from;
|
||||
(i<others.length) && (others[i] != null) &&
|
||||
(others[i].getRect().getMinX() <= event.getRect().getMaxX());
|
||||
i++){//while others are still intersecting with the event
|
||||
if(event.getRect().getMinY() < others[i].getRect().getMaxY() &&
|
||||
event.getRect().getMaxY() > others[i].getRect().getMinY()){//check the y coordinate
|
||||
if(evtSide == Join.LEFT)
|
||||
pairs.add(p.paired(event, others[i]));
|
||||
else
|
||||
pairs.add(p.paired(others[i], event));
|
||||
}//if
|
||||
}//for
|
||||
//System.out.println("SweepLine.internalLoop : after pairs size : " + pairs.size());
|
||||
}
|
||||
public boolean relateMismatch(Element ltElmt, Element rtElmt, int side)
|
||||
{
|
||||
try{
|
||||
return ltElmt.getRect().overlaps(rtElmt.getRect());
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
211
DataExtractionOSM/src/rtree/join/Join.java
Normal file
211
DataExtractionOSM/src/rtree/join/Join.java
Normal file
|
@ -0,0 +1,211 @@
|
|||
//Join.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
A class to join two RTrees.
|
||||
TODO:
|
||||
Make another buffer just for this algorithm of 512 bytes (or should you?).
|
||||
It is best to have this method's own cache. Read the document well before deciding on it.
|
||||
FIXME:
|
||||
1) This thing goes out of memory for large randomly generated trees.
|
||||
2) The result for point objects are not correct. The extra check done at Rect class is not done at sweep line algorithm.
|
||||
3) Better documentation
|
||||
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class Join
|
||||
{
|
||||
public static final int LEFT = 0;
|
||||
public static final int RIGHT = 1;
|
||||
private RTree ltTree = null;
|
||||
private RTree rtTree = null;
|
||||
private Pair p = null;
|
||||
SweepLine spLine = new SweepLine();//our sweep line always return a pair of pointers
|
||||
|
||||
/**
|
||||
@param left The left tree.
|
||||
@param right The right tree.
|
||||
*/
|
||||
public Join(RTree left, RTree right, Pair p, Predicate pred)
|
||||
{
|
||||
if(left == null || right == null)
|
||||
throw new IllegalArgumentException("Join : Argument null");
|
||||
this.ltTree = left;
|
||||
this.rtTree = right;
|
||||
this.p = p;
|
||||
spLine.setPredicate(pred);
|
||||
//this.pred = pred;
|
||||
}
|
||||
|
||||
public void setPairType(Pair p)
|
||||
{
|
||||
if(p != null)
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
/**
|
||||
Will return all the record pointers of the left tree that intersects with the right tree.
|
||||
At the moment I assume that the heights of the trees are same.
|
||||
@return a <code>List</code> of <code>Pair</code>s of pointers that intersect.
|
||||
*/
|
||||
public List relate()
|
||||
throws JoinException
|
||||
{
|
||||
try{
|
||||
//lock the files
|
||||
ltTree.getFileHdr().lockRead();
|
||||
rtTree.getFileHdr().lockRead();
|
||||
List vct = new ArrayList();
|
||||
long ltRoot = ltTree.getFileHdr().getRootIndex();
|
||||
long rtRoot = rtTree.getFileHdr().getRootIndex();
|
||||
|
||||
/*We can't do anything when we do not have any mbrs in either of the trees*/
|
||||
if(ltRoot == Node.NOT_DEFINED || rtRoot == Node.NOT_DEFINED)
|
||||
return vct;
|
||||
|
||||
Node ltRootNd = ltTree.getReadNode(ltRoot);
|
||||
Node rtRootNd = rtTree.getReadNode(rtRoot);
|
||||
|
||||
relateRec(ltRootNd, rtRootNd, ltRootNd.getNodeMBR().intersection(rtRootNd.getNodeMBR()), vct);
|
||||
return vct;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new JoinException("Join.intersectsInt : " + e.getMessage());
|
||||
}finally{
|
||||
ltTree.getFileHdr().lockRead();
|
||||
rtTree.getFileHdr().lockRead();
|
||||
}
|
||||
}
|
||||
/**
|
||||
@param ltNode
|
||||
@param rtNode
|
||||
@param ret
|
||||
@param intsect The intersection between the two <code>Node</code>.
|
||||
@param ret A <code>List</code> that would be filled with the pairs that intersect.
|
||||
*/
|
||||
private void relateRec(Node ltNode, Node rtNode, Rect intsect, List ret)
|
||||
throws Exception
|
||||
{
|
||||
if(ltNode == null || rtNode == null)
|
||||
throw new IllegalValueException("Join.intersectRec : Argument(s) null");
|
||||
Element[] ltElmts = ltNode.getAllElements();
|
||||
Element[] rtElmts = rtNode.getAllElements();
|
||||
|
||||
if(ltNode.getElementType() == Node.NONLEAF_NODE &&
|
||||
rtNode.getElementType() == Node.LEAF_NODE){//both sides are of different types
|
||||
ret.addAll(joinMismatch(ltElmts, rtElmts, Join.LEFT));
|
||||
}else if(ltNode.getElementType() == Node.LEAF_NODE &&
|
||||
rtNode.getElementType() == Node.NONLEAF_NODE){//both sides are of different types
|
||||
ret.addAll(joinMismatch(rtElmts, ltElmts, Join.RIGHT));
|
||||
}else {//either both are leaf or both non-leaf
|
||||
//this is where I remove elemensts which do no intersect with the intersection rectangle
|
||||
ltElmts = filterRect(ltElmts, intsect);
|
||||
rtElmts = filterRect(rtElmts, intsect);
|
||||
List pairs = spLine.sortedIntersectionTest(ltElmts, rtElmts);//get the intersecting pairs
|
||||
for(int i=0; i<pairs.size(); i++){//for each pair
|
||||
PairElmt intPair = (PairElmt)pairs.get(i);//the intersecting pair at i
|
||||
if(intPair.getLtElmt() instanceof NonLeafElement &&
|
||||
intPair.getRtElmt() instanceof NonLeafElement){//both are non leaf elements
|
||||
Node newLtNode = ltTree.getReadNode(intPair.getLtPtr());
|
||||
Node newRtNode = rtTree.getReadNode(intPair.getRtPtr());
|
||||
relateRec(newLtNode, newRtNode, newLtNode.getNodeMBR().intersection(newRtNode.getNodeMBR()),
|
||||
ret);
|
||||
}else if(intPair.getLtElmt() instanceof LeafElement &&
|
||||
intPair.getRtElmt() instanceof LeafElement){//LeafElement
|
||||
ret.add(p.paired(intPair.getLtElmt(), intPair.getRtElmt()));
|
||||
//System.out.println("Join.intersectRec with size of ret - leaf " + ret.size());
|
||||
}
|
||||
}//for
|
||||
}
|
||||
}
|
||||
/**
|
||||
Joins two nodes of different types.
|
||||
@param nlElmts non-leaf elements
|
||||
@param lfElmts leaf elements
|
||||
@param side The side of <code>nlElmts</code>. (Join.LEFT or Join.RIGHT)
|
||||
@return Pair of joins between leaf and non leaf elements (after window query).
|
||||
*/
|
||||
private List joinMismatch(Element[] nlElmts, Element[] lfElmts, int side)
|
||||
throws Exception
|
||||
{
|
||||
List ret = new ArrayList();
|
||||
for(int i=0; (i<nlElmts.length) && (nlElmts[i] != null); i++){//for each elmt in non-leaf
|
||||
for(int j=0; (j<lfElmts.length) &&(lfElmts[j] != null); j++){
|
||||
if(nlElmts[i].getRect().overlaps(lfElmts[j].getRect())){
|
||||
if(side == Join.LEFT)
|
||||
ret.addAll(windowQuery(ltTree.getReadNode(nlElmts[i].getPtr()),
|
||||
(LeafElement)lfElmts[j], side ));
|
||||
else//non leaf is the right tree
|
||||
ret.addAll(windowQuery(rtTree.getReadNode(nlElmts[i].getPtr()),
|
||||
(LeafElement)lfElmts[j], side ));
|
||||
|
||||
}//if
|
||||
}//for leaf-elements - j
|
||||
}//for non-leaf-elements - i
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method actually performs a simple window query on <code>nlNode</code> (a non-leaf Node).
|
||||
* Will return a <code>List</code> of <code>Pair</code>. The pair is made accordingly <code>side</code>.
|
||||
* @param side The side of <code>nlNode</code>.
|
||||
*/
|
||||
private List windowQuery(Node nlNode, LeafElement lfElmt, int side)
|
||||
throws Exception
|
||||
{
|
||||
RTree nlTree = null;//the non leaf tree
|
||||
if(side == Join.LEFT)
|
||||
nlTree = ltTree;
|
||||
else
|
||||
nlTree = rtTree;
|
||||
List list = new ArrayList();
|
||||
Element[] elmts = nlNode.getAllElements();
|
||||
int totElements = nlNode.getTotalElements();
|
||||
for(int i=0; i<totElements; i++){//for every element; we can use sweepline algorithm here
|
||||
//if(elmts[i].getRect().overlaps(lfElmt.getRect())){ //select elements that overlap
|
||||
if(spLine.getPredicate().relateMismatch(elmts[i], lfElmt, side)){//select elements that overlap
|
||||
if(elmts[i].getElementType() == Node.NONLEAF_NODE){//non leaf
|
||||
list.addAll(windowQuery( nlTree.getReadNode(elmts[i].getPtr()), lfElmt, side));
|
||||
}
|
||||
else{//if leaf element
|
||||
if(side == Join.LEFT)//here we add another condiation of the specified predicate
|
||||
list.add(p.paired(elmts[i], lfElmt));
|
||||
else
|
||||
list.add(p.paired(lfElmt, elmts[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
This method removes those elements from <code>elmts</code> that do not intersect <code>rect</code>.
|
||||
The original elements, <code>elmts</code>, are not modified.
|
||||
*/
|
||||
private Element[] filterRect(Element[] elmts, Rect rect)
|
||||
throws Exception
|
||||
{
|
||||
Element[] ret = new Element[elmts.length];
|
||||
int j=0;
|
||||
for(int i=0; i<elmts.length && elmts[i] != null; i++)
|
||||
if(rect.overlaps(elmts[i].getRect()))
|
||||
//ret[j++] = (Element)elmts[i].clone();//i hope java does not remove columns
|
||||
ret[j++] = elmts[i];
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
24
DataExtractionOSM/src/rtree/join/JoinException.java
Normal file
24
DataExtractionOSM/src/rtree/join/JoinException.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
//JoinException.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
/**
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class JoinException extends Exception
|
||||
{
|
||||
public JoinException(){}
|
||||
public JoinException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
42
DataExtractionOSM/src/rtree/join/MeetPred.java
Normal file
42
DataExtractionOSM/src/rtree/join/MeetPred.java
Normal file
|
@ -0,0 +1,42 @@
|
|||
//MeetPred.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
The "intersects" binary predicate. This is only for the sweepline algo.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class MeetPred extends Predicate
|
||||
{
|
||||
public MeetPred(){}
|
||||
|
||||
public void relate(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
(new IntersectPred()).relate(event, from, others, pairs, evtSide);
|
||||
}
|
||||
|
||||
public boolean relateMismatch(Element nlElmt, Element lfElmt, int side)
|
||||
{
|
||||
try{
|
||||
//if(nlElmt instanceof NonLeafElement)
|
||||
return nlElmt.getRect().overlaps(lfElmt.getRect());
|
||||
//else
|
||||
//return nlElmt.getRect().meet(lfElmt.getRect());
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
50
DataExtractionOSM/src/rtree/join/Pair.java
Normal file
50
DataExtractionOSM/src/rtree/join/Pair.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
//Pair.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
|
||||
|
||||
/**
|
||||
* This keeps a pair of intersection between two trees.
|
||||
* Basically the purpose of <code>Pair</code> and <code>PairElmt</code> is that the caller can get
|
||||
* pairs of pointers or pairs elements from the join operations.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class Pair
|
||||
{
|
||||
protected long left;
|
||||
protected long right;
|
||||
private Pair(long left, long right)
|
||||
{
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public Pair(){}
|
||||
|
||||
public long getLtPtr()
|
||||
{
|
||||
return left;
|
||||
}
|
||||
public long getRtPtr()
|
||||
{
|
||||
return right;
|
||||
}
|
||||
/**
|
||||
Returns an object <code>this</code> type.
|
||||
*/
|
||||
public Pair paired(Element ltElmt, Element rtElmt)
|
||||
{
|
||||
return new Pair(ltElmt.getPtr(), rtElmt.getPtr());
|
||||
}
|
||||
}
|
57
DataExtractionOSM/src/rtree/join/PairElmt.java
Normal file
57
DataExtractionOSM/src/rtree/join/PairElmt.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
//PairEmlt.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
|
||||
/**
|
||||
* This class inherits Pair but represents the whole Element that intersect and not just the pointers.
|
||||
* Basically the purpose of <code>Pair</code> and <code>PairElmt</code> is that the caller can get
|
||||
* pairs of pointers or pairs elements from the join operations.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class PairElmt extends Pair
|
||||
{
|
||||
private Element ltElmt;
|
||||
private Element rtElmt;
|
||||
|
||||
public PairElmt(){}
|
||||
|
||||
private PairElmt(Element ltElmt, Element rtElmt)
|
||||
{
|
||||
this.ltElmt = ltElmt;
|
||||
this.rtElmt = rtElmt;
|
||||
}
|
||||
|
||||
public long getLtPtr()
|
||||
{
|
||||
return ltElmt.getPtr();
|
||||
}
|
||||
public long getRtPtr()
|
||||
{
|
||||
return rtElmt.getPtr();
|
||||
}
|
||||
public Element getLtElmt()
|
||||
{
|
||||
return ltElmt;
|
||||
}
|
||||
|
||||
public Element getRtElmt()
|
||||
{
|
||||
return rtElmt;
|
||||
}
|
||||
public Pair paired(Element ltElmt, Element rtElmt)
|
||||
{
|
||||
return new PairElmt(ltElmt, rtElmt);
|
||||
}
|
||||
|
||||
}
|
62
DataExtractionOSM/src/rtree/join/Predicate.java
Normal file
62
DataExtractionOSM/src/rtree/join/Predicate.java
Normal file
|
@ -0,0 +1,62 @@
|
|||
//Predicate.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import rtree.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
This class works with "sweepline" algo. For the actual binary predicate between MBRs, this interface
|
||||
should help. We will have an implementing class for "intersects","contains","meet".
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public abstract class Predicate
|
||||
{
|
||||
protected Pair p = new PairElmt();//this is always PairElmt
|
||||
|
||||
public Predicate(){}
|
||||
|
||||
// public Predicate(Pair p)
|
||||
// {
|
||||
// if(p == null)
|
||||
// throw new NullPointerException(" Argument null");
|
||||
// this.p = p;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Do the appropriate rtree operation.
|
||||
* @param event the <code>Element</code> at which the event took place.
|
||||
* @param from the index from which <code>others</code> start.
|
||||
* @param others the <code>Element[]</code> to compare with <code>event</code>
|
||||
* @param pairs a <code>List</code> value where the output pairs would put.
|
||||
* @param evtSide tells whether <code>event</code> is from left tree or right tree.
|
||||
* @param p a <code>Pair</code> value which specifies the kind of output required.
|
||||
*/
|
||||
public abstract void relate(Element event, int from, Element[] others, List pairs, int evtSide);
|
||||
|
||||
/**
|
||||
* This one is specifically for the case where one tree is longer then the other.
|
||||
* It may be noted that both the elements can be leaf as well.
|
||||
* @param nlElmt the non-leaf <code>Element</code>
|
||||
* @param lfElmt the leaf <code>Element</code>
|
||||
* @param side The side of <code>nlElmt</code> element.
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public abstract boolean relateMismatch(Element nlElmt, Element lfElmt, int side);
|
||||
/**
|
||||
Returns the <code>Pair</code> which tells the type of output required.
|
||||
*/
|
||||
public Pair getPair()
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
168
DataExtractionOSM/src/rtree/join/SweepLine.java
Normal file
168
DataExtractionOSM/src/rtree/join/SweepLine.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
//SweepLine.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.join;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import rtree.*;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class SweepLine
|
||||
{
|
||||
//Pair p = new Pair();
|
||||
IntersectPred intPred = new IntersectPred();
|
||||
Predicate pred = null;
|
||||
public SweepLine()
|
||||
{
|
||||
}
|
||||
|
||||
public SweepLine(Predicate pred)
|
||||
{
|
||||
//this.p = p;
|
||||
this.pred = pred;
|
||||
//intPred = new IntersectPred();
|
||||
}
|
||||
|
||||
public void setPredicate(Predicate pred)
|
||||
{
|
||||
this.pred = pred;
|
||||
}
|
||||
public Predicate getPredicate()
|
||||
{
|
||||
return pred;
|
||||
}
|
||||
public void sort(Rect[] rects)
|
||||
{
|
||||
Arrays.sort(rects, new CompRectX());
|
||||
}
|
||||
public void sort(Element[] elmts)
|
||||
{
|
||||
Arrays.sort(elmts, new CompElmtX());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will return all the pointers of <code>elmts</code> which intersect with
|
||||
* <code>rect</code>. It is expected that <code>elmts</code> are sorted acording to <code>minX</code>
|
||||
* @return either a <code>List</code> of eithers pointers or ehole elements depending upon <code>p</code>.
|
||||
*/
|
||||
public List intersects(Rect rect, Element[] elmts)
|
||||
{
|
||||
if(elmts == null || elmts.length < 1)
|
||||
return null;
|
||||
Element dummy;
|
||||
if(elmts[0] instanceof LeafElement)
|
||||
dummy = new LeafElement(rect, 128);
|
||||
else
|
||||
dummy = new NonLeafElement(rect, 128);
|
||||
Element[] dummyArr = new Element[1];
|
||||
dummyArr[0] = dummy;
|
||||
return sortedIntersectionTest(dummyArr, elmts);
|
||||
}
|
||||
/**
|
||||
* This method applies the sweep line algorithm to the two given set of elements.
|
||||
* It is not necessary to have the two arrays sorted (by minX).
|
||||
*/
|
||||
public List intersects(Element[] ltElmts,Element[] rtElmts)
|
||||
{
|
||||
sort(ltElmts);
|
||||
sort(rtElmts);
|
||||
return sortedIntersectionTest(ltElmts, rtElmts);
|
||||
}
|
||||
|
||||
/**
|
||||
Does the sweep sort on the two sets. Assumes that both the set of elements are of the same type.
|
||||
@param ltElmts The sorted elements(by minX) of the left node.
|
||||
@param rtElmts The sorted elements(by minX) of the right node.
|
||||
@return A <code>List</code> of <code>Pair</code> of elements
|
||||
*/
|
||||
public List sortedIntersectionTest(Element[] ltElmts, Element[] rtElmts)
|
||||
{
|
||||
int i = 0;//loop cntr for left
|
||||
int j = 0;//loop cntr for right
|
||||
List pairs = new ArrayList();
|
||||
while((i < ltElmts.length) && (ltElmts[i] != null) &&
|
||||
(j < rtElmts.length) && (rtElmts[j] != null)){
|
||||
if(ltElmts[i].getRect().getMinX() < rtElmts[j].getRect().getMinX()){//event at left
|
||||
|
||||
if(ltElmts[i] instanceof NonLeafElement){
|
||||
intPred.relate(ltElmts[i], j, rtElmts, pairs, Join.LEFT);
|
||||
}else{
|
||||
pred.relate(ltElmts[i], j, rtElmts, pairs, Join.LEFT);
|
||||
}
|
||||
//System.out.println("SweepLine.sortedIntersectionTest : total pairs " + pairs.size());
|
||||
i++;
|
||||
}else{
|
||||
if(rtElmts[j] instanceof NonLeafElement){
|
||||
intPred.relate(rtElmts[j], i, ltElmts, pairs, Join.RIGHT);
|
||||
}else{
|
||||
pred.relate(rtElmts[j], i, ltElmts, pairs, Join.RIGHT);
|
||||
}
|
||||
//System.out.println("SweepLine.sortedIntersectionTest : total pairs " + pairs.size());
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
@param evtSide tells whether <code>event</code> is from left tree or right tree.
|
||||
|
||||
private void internalLoop(Element event, int from, Element[] others, List pairs, int evtSide)
|
||||
{
|
||||
//System.out.println("SweepLine.internalLoop : before pairs size : " + pairs.size());
|
||||
for(int i=from;
|
||||
(i<others.length) && (others[i] != null) &&
|
||||
(others[i].getRect().getMinX() <= event.getRect().getMaxX());
|
||||
i++){//while others are still intersecting with the event
|
||||
if(event.getRect().getMinY() < others[i].getRect().getMaxY() &&
|
||||
event.getRect().getMaxY() > others[i].getRect().getMinY()){//check the y coordinate
|
||||
if(evtSide == Join.LEFT)
|
||||
pairs.add(p.paired(event, others[i]));
|
||||
else
|
||||
pairs.add(p.paired(others[i], event));
|
||||
}//if
|
||||
}//for
|
||||
//System.out.println("SweepLine.internalLoop : after pairs size : " + pairs.size());
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
An internal Comparable class to sort Rect.
|
||||
*/
|
||||
class CompRectX implements Comparator
|
||||
{
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
if(o1 instanceof Rect && o2 instanceof Rect){
|
||||
Rect r1 = (Rect)o1;
|
||||
Rect r2 = (Rect)o2;
|
||||
if(r1.getMinX() <= r2.getMinX())
|
||||
return -1;
|
||||
else if(r1.getMinX() == r2.getMinX())
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
throw new ClassCastException("Rect.compareTo : wrong object(s) passed");
|
||||
|
||||
}
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
650
DataExtractionOSM/src/rtree/rTreeDemo.java
Normal file
650
DataExtractionOSM/src/rtree/rTreeDemo.java
Normal file
|
@ -0,0 +1,650 @@
|
|||
//RTreeDemo.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree;
|
||||
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.Random;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import rtree.join.*;
|
||||
import rtree.seeded.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
One can look at this class to understand the usage of RTree.
|
||||
*/
|
||||
public class rTreeDemo
|
||||
{
|
||||
public static void main(String argv[])
|
||||
{
|
||||
//rTreeDemo rt = new rTreeDemo();
|
||||
new TreeThread();
|
||||
}
|
||||
public List tryJoin()
|
||||
{
|
||||
TreeThread tr = new TreeThread();
|
||||
return tr.tryJoin();
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
TreeThread.fileName = name;
|
||||
}
|
||||
}
|
||||
|
||||
class TreeThread implements Runnable
|
||||
{
|
||||
static String fileName = "c:\\temp\\temp.tree";
|
||||
static long seed = 1015395880;//1015395880431;
|
||||
static int h = 15000000;//2148460;//15000000;
|
||||
static int w = 6000000;//2757573;//6000000;
|
||||
Thread tree;
|
||||
//String tname;
|
||||
TreeThread()
|
||||
{
|
||||
for(int i=0; i<1; i++){
|
||||
tree = new Thread(this,Integer.toString(i));
|
||||
// try{Thread.currentThread().sleep(3000);}
|
||||
// catch(Exception e){System.out.println("shdb");}
|
||||
tree.start();
|
||||
}
|
||||
}
|
||||
public void run()
|
||||
{
|
||||
try{
|
||||
//RTree rt = new RTree(fileName);
|
||||
//rt.printTree();
|
||||
// entry(fileName);
|
||||
//entryRand(fileName);
|
||||
// rt.flush();
|
||||
|
||||
// HashSet set = new HashSet(list);
|
||||
// System.out.println("rTreeDemo.run : size of set " + set.size());
|
||||
|
||||
//rt.printTree();
|
||||
//overlapRR(fileName);
|
||||
|
||||
//Pack pck = new Pack();
|
||||
//System.out.println("rTreeDemo : rt has before " + rt.getAllElements().size());
|
||||
//pck.packTree(rt, fileName);
|
||||
//System.out.println("rTreeDemo : rt has after " + rt.getAllElements().size());
|
||||
//rt.printTree();
|
||||
//pck.packTree(rt, fileName);
|
||||
|
||||
//pck.packTree(new RTree(fileName+"2"), fileName+"2");
|
||||
//trySeed("/tmp/seed.dat", new RTree(fileName));
|
||||
//System.out.println("rTreeDemo : height " + rt.getHeight());
|
||||
|
||||
RTreeRead rd = new RTreeRead(fileName+"1");
|
||||
rd.readSeq();
|
||||
rd = new RTreeRead(fileName+"2");
|
||||
rd.readSeq();
|
||||
|
||||
//tryJoin();
|
||||
}
|
||||
catch(Exception e){
|
||||
try{
|
||||
e.printStackTrace();
|
||||
}catch(Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
//tryOverlap();
|
||||
//tryCvr();
|
||||
}
|
||||
/**
|
||||
Enter records within l - 15000000 and w - 6000000
|
||||
*/
|
||||
public void entryRand(String fileName)
|
||||
throws Exception
|
||||
{
|
||||
List vct = new ArrayList(0);
|
||||
int ix,iy,xx,xy;//mIn,maX
|
||||
RTree rt = new RTree(fileName);
|
||||
Random rnd = new Random(seed);
|
||||
long start = System.currentTimeMillis();
|
||||
Rect rect = new Rect();
|
||||
|
||||
//point data
|
||||
for(int i=0;i<2000; i++){
|
||||
iy = rnd.nextInt(h);//height
|
||||
ix = rnd.nextInt(w);//width
|
||||
LeafElement lf = new LeafElement(new Rect(ix,iy,ix,iy),218);
|
||||
rt.insert(lf);
|
||||
//rect.expandToInclude(lf.getRect());
|
||||
//vct.add((LeafElement)lf.clone());
|
||||
}
|
||||
|
||||
//rectangles
|
||||
for(int i=0;i<30000; i++){
|
||||
iy = rnd.nextInt(h-2);//height
|
||||
ix = rnd.nextInt(w-2);//width
|
||||
xy = rnd.nextInt(h - iy);
|
||||
xx = rnd.nextInt(w - ix);
|
||||
LeafElement lf = new LeafElement(new Rect(ix,iy,ix+xx,iy+xy),218);
|
||||
rt.insert(lf);
|
||||
//rect.expandToInclude(lf.getRect());
|
||||
//vct.add((LeafElement)lf.clone());
|
||||
}
|
||||
|
||||
for(int i=0;i<20000; i++){
|
||||
iy = rnd.nextInt(h);//height
|
||||
ix = rnd.nextInt(w);//width
|
||||
LeafElement lf = new LeafElement(new Rect(ix,iy,ix,iy),218);
|
||||
rt.insert(lf);
|
||||
//rect.expandToInclude(lf.getRect());
|
||||
//vct.add((LeafElement)lf.clone());
|
||||
}
|
||||
//rectangles
|
||||
for(int i=0;i<30000; i++){
|
||||
iy = rnd.nextInt(h-2);//height
|
||||
ix = rnd.nextInt(w-2);//width
|
||||
xy = rnd.nextInt(h - iy);
|
||||
xx = rnd.nextInt(w - ix);
|
||||
LeafElement lf = new LeafElement(new Rect(ix,iy,ix+xx,iy+xy),218);
|
||||
rt.insert(lf);
|
||||
rect.expandToInclude(lf.getRect());
|
||||
//vct.add((LeafElement)lf.clone());
|
||||
}
|
||||
//for(int i=0; i<vct.size(); i++){
|
||||
//System.out.println(i);
|
||||
//delete(fileName, (LeafElement)vct.get(i));
|
||||
//}
|
||||
// RTreeRead rd = new RTreeRead(fileName);
|
||||
// rd.readSeq();
|
||||
|
||||
System.out.println("Entry over in ms : " +(System.currentTimeMillis()-start)
|
||||
+ " for thread " + Thread.currentThread());
|
||||
}
|
||||
//public
|
||||
public void entry(String fileName)
|
||||
{
|
||||
try{
|
||||
//Point data
|
||||
/*
|
||||
RTree rtree = new RTree(fileName);
|
||||
LeafElement lf1 =
|
||||
new LeafElement(new Rect(4,3,4,3),218);
|
||||
LeafElement lf2 =
|
||||
new LeafElement(new Rect(6,5,6,5),218);
|
||||
LeafElement lf3 =
|
||||
new LeafElement(new Rect(5,6,5,6),218);
|
||||
LeafElement lf4 =
|
||||
new LeafElement(new Rect(7,2,7,2),218);
|
||||
rtree.insert(lf1);
|
||||
rtree.insert(lf2);
|
||||
rtree.insert(lf3);
|
||||
rtree.insert(lf4);
|
||||
*/
|
||||
//BOXES
|
||||
long start = System.currentTimeMillis();
|
||||
RTree rtree = new RTree(fileName);
|
||||
LeafElement lf1 = new LeafElement(new Rect(3,2,4,3),3243);//keep for join
|
||||
rtree.insert(lf1);
|
||||
rtree.delete(lf1);
|
||||
/*
|
||||
//getall(fileName);
|
||||
RTree rtree1 = new RTree(fileName);
|
||||
LeafElement lf2 = new LeafElement(new Rect(5,4,6,5),5465);
|
||||
//rtree1.insert(lf2);
|
||||
|
||||
RTree rtree2 = new RTree(fileName);
|
||||
LeafElement lf3 = new LeafElement(new Rect(9,6,10,7),96107);
|
||||
//rtree2.insert(lf3);
|
||||
|
||||
RTree rtree3 = new RTree(fileName);
|
||||
LeafElement lf4 = new LeafElement(new Rect(6,1,7,3),6173);//keep for join
|
||||
rtree3.insert(lf4);
|
||||
|
||||
RTree rtree4 = new RTree(fileName);
|
||||
LeafElement lf5 = new LeafElement(new Rect(6,2,8,3),6283);
|
||||
//rtree4.insert(lf5);
|
||||
|
||||
RTree rtree5 = new RTree(fileName);
|
||||
LeafElement lf6 = new LeafElement(new Rect(4,4,5,6),4456);
|
||||
//rtree5.insert(lf6);
|
||||
|
||||
RTree rtree6 = new RTree(fileName);
|
||||
LeafElement lf7 = new LeafElement(new Rect(5,3,7,4),5374);
|
||||
//rtree6.insert(lf7);
|
||||
|
||||
RTree rtree7 = new RTree(fileName);
|
||||
LeafElement lf8 = new LeafElement(new Rect(9,5,10,6),95106);//keep for join
|
||||
rtree2.insert(lf8);
|
||||
|
||||
LeafElement lf9 = new LeafElement(new Rect(1,2,2,3),1223);//keep for join
|
||||
rtree2.insert(lf9);
|
||||
*/
|
||||
System.out.println("Time in ms:" +(System.currentTimeMillis()-start));
|
||||
System.out.println("Entry over");
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
Random rect queries
|
||||
*/
|
||||
public void overlapRR(String name)
|
||||
throws Exception
|
||||
{
|
||||
RTree rt = new RTree(name);
|
||||
int ix,iy,xx,xy;
|
||||
Random rnd = new Random(System.currentTimeMillis());
|
||||
for(int i=0;i<1;i++){
|
||||
iy = rnd.nextInt(h-2);//height
|
||||
ix = rnd.nextInt(w-2);//width
|
||||
xy = rnd.nextInt(h - iy);
|
||||
xx = rnd.nextInt(w - ix);
|
||||
long start4 = System.currentTimeMillis();
|
||||
List elmts = null;
|
||||
// elmts = rt.overlaps(new Rect(ix,iy,ix+xx,iy+xy));
|
||||
// System.out.println("Time in ms:" + (System.currentTimeMillis()-start4));
|
||||
// System.out.println("Search result-Total elements:"+elmts.size());
|
||||
System.out.println("Sweep");
|
||||
start4 = System.currentTimeMillis();
|
||||
elmts = rt.overlapsSweep(new Rect(ix,iy,ix+xx,iy+xy));
|
||||
System.out.println("Time in ms:" + (System.currentTimeMillis()-start4));
|
||||
System.out.println("Search result-Total elements:"+elmts.size());
|
||||
}
|
||||
}
|
||||
/*
|
||||
Random point queries
|
||||
*/
|
||||
public void overlapRP(String name)
|
||||
throws Exception
|
||||
{
|
||||
RTree rt = new RTree(name);
|
||||
int ix,iy;
|
||||
Random rnd = new Random(System.currentTimeMillis());
|
||||
for(int i=0;i<10;i++){
|
||||
iy = rnd.nextInt(h);//height
|
||||
ix = rnd.nextInt(w);//width
|
||||
long start4 = System.currentTimeMillis();
|
||||
List elmts = rt.overlaps(new Rect(ix,iy,ix,iy));
|
||||
System.out.println("Time in ms:" +
|
||||
(System.currentTimeMillis()-start4));
|
||||
System.out.println("Search result-Total elements:"+elmts.size());
|
||||
/*
|
||||
start4 = System.currentTimeMillis();
|
||||
elmts = rt.overlaps(new Rect(ix,iy,ix,iy));
|
||||
System.out.println("Time in ms:" +
|
||||
(System.currentTimeMillis()-start4));
|
||||
System.out.println("Search result-Total elements:"+elmts.size());
|
||||
*/
|
||||
}
|
||||
}
|
||||
public void getall(String name)
|
||||
{
|
||||
try{
|
||||
//get All elements
|
||||
RTree rt = new RTree(name);
|
||||
|
||||
long start1 = System.currentTimeMillis();
|
||||
List elmts1 = rt.getAllElements();
|
||||
System.out.println("Time in ms:" +
|
||||
(System.currentTimeMillis()-start1));
|
||||
System.out.println("Record fetched by "+
|
||||
Thread.currentThread().getName()+
|
||||
": " + elmts1.size());
|
||||
/*
|
||||
start1 = System.currentTimeMillis();
|
||||
LinkedList elmts2 = rt.testgetAllElements();
|
||||
System.out.println("Time in ms:" +
|
||||
(System.currentTimeMillis()-start1));
|
||||
System.out.println("Record fetched: " + elmts2.size());
|
||||
*/
|
||||
//for(int i=0; i<elmts2.length; i++)
|
||||
//System.out.println(elmts2[i].toString());
|
||||
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void overlap(String name,Rect rect)
|
||||
{
|
||||
try{
|
||||
//Test overlap
|
||||
RTree rt = new RTree(name);
|
||||
long start4 = System.currentTimeMillis();
|
||||
List elmts = rt.nonDisjoint(rect);
|
||||
System.out.println("Time in ms:" +
|
||||
(System.currentTimeMillis()-start4));
|
||||
System.out.println("overlap Search -Total elements:"+elmts.size());
|
||||
//for(int i=0;i<elmts.size();i++)
|
||||
//System.out.println(((LeafElement)(elmts.elementAt(i))).toString());
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
public void search(String name)
|
||||
{
|
||||
try{
|
||||
//Search Nearest
|
||||
RTree rt = new RTree(name);
|
||||
int ix,iy;
|
||||
Random rnd = new Random(System.currentTimeMillis());
|
||||
//for(int i=0;i<10;i++){
|
||||
iy = rnd.nextInt(h);//height
|
||||
ix = rnd.nextInt(w);//width
|
||||
Point pt =
|
||||
new Point(ix,iy);
|
||||
//Point pt =
|
||||
//new Point(2618917,1264511);
|
||||
//limited number
|
||||
long start5 = System.currentTimeMillis();
|
||||
|
||||
ABL[] nrst = rt.nearestSearch(pt,50000000000L,10);
|
||||
System.out.println("Time in ms for NNSearch(Limited):"+ (System.currentTimeMillis()-start5));
|
||||
/*
|
||||
for(int i=0;i<nrst.length;i++)
|
||||
if(nrst[i] == null)
|
||||
System.out.println("Could not find anything!!");
|
||||
else
|
||||
System.out.println("Result" + nrst[i].element.toString()
|
||||
+"\tMINDIST:" + nrst[i].minDist);
|
||||
*/
|
||||
//unlimited
|
||||
|
||||
System.out.println("List");
|
||||
start5 = System.currentTimeMillis();
|
||||
List vec = rt.nearestSearch(pt,10000000000L);
|
||||
System.out.println("Time in ms for NNSearch(Unlimited):"+ (System.currentTimeMillis()-start5));
|
||||
System.out.println("Retrieved: "+vec.size());
|
||||
|
||||
//for(int i=0;i<vec.size();i++)
|
||||
// System.out.println("Result" + ((ABL)(vec.elementAt(i)))
|
||||
// .element.toString()
|
||||
// +"\tMINDIST:" + ((ABL)(vec.elementAt(i)))
|
||||
// .minDist);
|
||||
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
public void delete(String name,LeafElement element)
|
||||
{
|
||||
try{
|
||||
RTree rt = new RTree(fileName);
|
||||
rt.delete(element);
|
||||
//for(int i=0;i<150;i++)
|
||||
//rt.delete(element);
|
||||
|
||||
}
|
||||
catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void tryOverlap()
|
||||
{
|
||||
try{
|
||||
Rect rect1 = new Rect();
|
||||
//Rect rect1 = new Rect(3,2,5,4);
|
||||
//Rect rect2 = new Rect(3,2,5,4);
|
||||
//Rect rect2 = new Rect(4,3,4,3);//true
|
||||
//Rect rect2 = new Rect(5,2,7,4);//false
|
||||
//Rect rect2 = new Rect(3,4,5,5);//false
|
||||
//Rect rect2 = new Rect(3,1,5,2);//false
|
||||
//Rect rect2 = new Rect(3,1,5,3);//false
|
||||
//Rect rect2 = new Rect(4,3,4,3);//true
|
||||
//Rect rect2 = new Rect(5,3,5,3);//true
|
||||
//Rect rect2 = new Rect(6,2,6,2);//false
|
||||
//Rect rect2 = new Rect(2,1,6,5);//false
|
||||
Rect rect2 = new Rect(4,2,5,3);
|
||||
//Rect rect1 = new Rect(9,6,10,7);//true
|
||||
//Rect rect2 = new Rect(8,5,11,8);//true
|
||||
System.out.println(rect1.toString()+" \nand\n"+rect2.toString()
|
||||
+"\noverlap? \n\tAns- "+rect2.contains(rect1));
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Exception "+e.getMessage());
|
||||
}
|
||||
}
|
||||
public void tryIntersection()
|
||||
{
|
||||
try{
|
||||
//Rect rect1 = new Rect(3,2,5,4);
|
||||
//Rect rect2 = new Rect(3,2,5,4);//3 2 5 4
|
||||
//Rect rect2 = new Rect(4,3,4,3);//4 3 4 3
|
||||
//Rect rect2 = new Rect(5,2,7,4);//5 2 5 4 - not null but a single line
|
||||
//Rect rect2 = new Rect(3,4,5,5);//3 4 5 4
|
||||
//Rect rect2 = new Rect(3,1,5,2);//3 2 5 2
|
||||
//Rect rect2 = new Rect(3,1,5,3);//3 2 5 3
|
||||
//Rect rect2 = new Rect(4,3,4,3);//4 3 4 3
|
||||
//Rect rect2 = new Rect(5,3,5,3);//5 3 5 3
|
||||
//Rect rect2 = new Rect(6,2,6,2);//null
|
||||
//Rect rect2 = new Rect(2,1,6,5);//3 2 5 4
|
||||
//Rect rect2 = new Rect(4,2,5,3);//4 2 5 3
|
||||
Rect rect1 = new Rect(9,6,10,7);//null
|
||||
Rect rect2 = new Rect(8,5,11,8);//null - comp the two 9 6 10 7
|
||||
System.out.println(rect1.toString()+" \nand\n"+rect2.toString()
|
||||
+"\nIntersection \n\tAns- "+rect2.intersection(rect1));
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Exception "+e.getMessage());
|
||||
}
|
||||
}
|
||||
public void tryCvr()
|
||||
{
|
||||
try{
|
||||
Rect rect1 = new Rect(3,2,5,4);
|
||||
Rect rect2 = new Rect(3,2,4,4);//true
|
||||
//Rect rect2 = new Rect(6,2,6,2);//false
|
||||
System.out.println(rect1.toString()+" \nand\n"+rect2.toString()
|
||||
+"\nDoes first Eclose second? \n\tAns- "
|
||||
+rect1.covers(rect2));
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Exception "+e.getMessage());
|
||||
}
|
||||
}
|
||||
public void tryIntsct()
|
||||
{
|
||||
try{
|
||||
Rect rect1 = new Rect(3,2,5,4);
|
||||
//Rect rect2 = new Rect(3,2,3,2);//true
|
||||
//Rect rect2 = new Rect(5,2,7,4);//false
|
||||
//Rect rect2 = new Rect(3,2,3,2);//true
|
||||
//Rect rect2 = new Rect(3,4,5,5);//false
|
||||
//Rect rect2 = new Rect(3,1,5,2);//false
|
||||
//Rect rect2 = new Rect(3,1,5,3);//true
|
||||
//Rect rect2 = new Rect(4,3,4,3);//true - check
|
||||
Rect rect2 = new Rect(3,2,3,2);//true
|
||||
System.out.println(rect1.toString()+" \nand\n"+rect2.toString()
|
||||
+"\nDo Both Intersect? \n\tAns- "
|
||||
+rect1.meet(rect2));
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Exception "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void trySeed(String sdTree, RTree rtree)
|
||||
{
|
||||
try{
|
||||
//System.out.println("rTreeDemo.trySeed : height of rtree is " + rtree.getHeight());
|
||||
SdTree sdt = new SdTree(sdTree, rtree);
|
||||
//now grow
|
||||
int ix,iy,xx,xy;//mIn,maX
|
||||
Random rnd = new Random(seed);
|
||||
long start = System.currentTimeMillis();
|
||||
// LeafElement llf = new LeafElement(new Rect(1752, 2179, 5999888, 14999646),218);
|
||||
// sdt.growLeaf(llf);
|
||||
|
||||
for(int i=0;i<2000000; i++){
|
||||
iy = rnd.nextInt(h-2);//height
|
||||
ix = rnd.nextInt(w-2);//width
|
||||
xy = rnd.nextInt(h - iy);
|
||||
xx = rnd.nextInt(w - ix);
|
||||
LeafElement lf = new LeafElement(new Rect(ix,iy,ix+xx,iy+xy),218);
|
||||
sdt.growLeaf(lf);
|
||||
}
|
||||
sdt.cleanUp();
|
||||
(new RTree(sdTree)).flush();
|
||||
// RTreeRead rd = new RTreeRead(sdTree);
|
||||
// rd.readSeq();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public List tryJoin()
|
||||
{
|
||||
try{
|
||||
//String lt = new String("c:\\temp\temptree.dat");
|
||||
//String lt = new String("/mnt/projects/data/MUM4_78.idx");
|
||||
//String rt = new String("/mnt/projects/data/MUM4_118.idx");
|
||||
RTree ltTree = new RTree(/*lt*/fileName+"1");
|
||||
RTree rtTree = new RTree(/*rt*/fileName+"2");
|
||||
//System.out.println("rTreeDemo.tryJoin : lt size " + ltTree.getAllElements().size());
|
||||
|
||||
Join join = new Join(ltTree, rtTree, new Pair(), new IntersectPred());
|
||||
|
||||
System.out.println("rTreeDemo : left tree size " + ltTree.getAllElements().size()
|
||||
+"\nright tree size " + rtTree.getAllElements().size()
|
||||
+"\n join size " + join.relate().size());
|
||||
|
||||
long t = System.currentTimeMillis();
|
||||
List list = join.relate();
|
||||
System.out.println("Join returned " + list.size() + " pointers in "
|
||||
+ (System.currentTimeMillis() - t) + " ms" );
|
||||
return list;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RTreeRead
|
||||
{
|
||||
static int nleaf;
|
||||
static int leaf;
|
||||
static int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE,maxX = Integer.MIN_VALUE,
|
||||
maxY = Integer.MIN_VALUE;
|
||||
RandomAccessFile file;
|
||||
RTreeRead(String fileName)
|
||||
{
|
||||
nleaf = leaf = 0;
|
||||
try{
|
||||
file = new RandomAccessFile(fileName,"r");
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("RTreeRead "+e.getMessage());
|
||||
}
|
||||
}
|
||||
public void readSeq()
|
||||
{
|
||||
try{
|
||||
long length = file.length();
|
||||
if(length == 0)
|
||||
return;
|
||||
Integer ln = new Integer((new Long(file.length())).intValue());
|
||||
int kbytes = (new Double(Math.floor(ln.doubleValue()/4096))).intValue();
|
||||
file.seek(0);
|
||||
for(int i=0;i<kbytes+1;i++)
|
||||
{
|
||||
byte[] data = new byte[Node.NODE_SIZE];
|
||||
file.read(data);
|
||||
if(i==0)
|
||||
printFlHdr(data);
|
||||
else
|
||||
printNode(i-1,data);
|
||||
}
|
||||
System.out.println("Total Leaf:"+leaf+"\tNonLeaf:"+nleaf);
|
||||
System.out.println("MinX:"+minX+"\tMinY:"+minY+"\tMaxX:"+maxX+"\tMaxY:"+maxY);
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("RTreeRead"+e.getMessage());
|
||||
}
|
||||
}
|
||||
public void printFlHdr(byte[] data)
|
||||
{
|
||||
try{
|
||||
int frNode = 123;
|
||||
DataInputStream ds =
|
||||
new DataInputStream(new ByteArrayInputStream(data));
|
||||
System.out.println("\t***The File Header***");
|
||||
System.out.println("TotalNodes:(includes unused ones):"+ds.readInt());
|
||||
System.out.println("RootIndex: " + ds.readLong());
|
||||
System.out.println("The free nodes Stack");
|
||||
for(int topIdx=0;(topIdx<Node.FREE_LIST_LIMIT)&&
|
||||
((frNode = ds.readInt()) !=
|
||||
Node.NOT_DEFINED); topIdx++){
|
||||
System.out.println("At " + topIdx + ": "+ frNode);
|
||||
}
|
||||
//System.out.println(frNode);
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Error at printFlHdr");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
public void printNode(int index,byte[] data)
|
||||
{
|
||||
int mx,my,xx,xy;
|
||||
try{
|
||||
DataInputStream ds =
|
||||
new DataInputStream(new ByteArrayInputStream(data));
|
||||
System.out.println("\t***Node at Index: "+index+"***");
|
||||
System.out.println("Node Header");
|
||||
int totElmt = ds.readInt();
|
||||
System.out.println("TotalElements:"+totElmt);
|
||||
System.out.println("Parent:"+ds.readLong());
|
||||
System.out.println("Element Size:"+ds.readInt());
|
||||
int elmtType = ds.readInt();
|
||||
System.out.println("Element Types:"+elmtType);
|
||||
if(elmtType == Node.NONLEAF_NODE)
|
||||
nleaf++;
|
||||
else
|
||||
leaf++;
|
||||
for(int i=0;i<totElmt;i++){
|
||||
System.out.println("Elements...");
|
||||
|
||||
mx = ds.readInt();
|
||||
if(mx < minX)
|
||||
minX = mx;
|
||||
System.out.println("MinX: "+mx);
|
||||
|
||||
my = ds.readInt();
|
||||
if(my < minY)
|
||||
minY = my;
|
||||
System.out.println("MinY: "+my);
|
||||
|
||||
xx = ds.readInt();
|
||||
if(xx > maxX)
|
||||
maxX = xx;
|
||||
System.out.println("MaxX: "+xx);
|
||||
|
||||
xy = ds.readInt();
|
||||
if(xy > maxY)
|
||||
maxY = xy;
|
||||
System.out.println("MaxY: "+xy);
|
||||
System.out.println("Pointer: "+ds.readLong());
|
||||
}
|
||||
}
|
||||
catch(Exception e){
|
||||
System.out.println("Error");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
109
DataExtractionOSM/src/rtree/seeded/SdNode.java
Normal file
109
DataExtractionOSM/src/rtree/seeded/SdNode.java
Normal file
|
@ -0,0 +1,109 @@
|
|||
//SdNode.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.seeded;
|
||||
|
||||
import rtree.*;
|
||||
import java.io.*;
|
||||
import rtree.Node;
|
||||
import rtree.IllegalValueException;
|
||||
import rtree.NodeWriteException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
The seed node.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class SdNode extends Node
|
||||
{
|
||||
/**
|
||||
For a new node.
|
||||
*/
|
||||
public SdNode(RandomAccessFile file,String fileName, long prnt,int elmtType, FileHdr flHdr)
|
||||
throws IOException, NodeWriteException
|
||||
{
|
||||
super(file, fileName, prnt, elmtType, flHdr);
|
||||
}
|
||||
|
||||
public SdNode(RandomAccessFile file, String fileName, long ndIndex, FileHdr flHdr)
|
||||
throws FileNotFoundException,IOException, NodeReadException, NodeWriteException
|
||||
{
|
||||
super(file, fileName, ndIndex, flHdr);
|
||||
}
|
||||
|
||||
SdNode(Node node)
|
||||
{
|
||||
|
||||
}
|
||||
public int getElementIndex(long param1)
|
||||
{
|
||||
return super.getElementIndex(param1);
|
||||
}
|
||||
public void insertElement(Element[] elmts )
|
||||
throws NodeWriteException, NodeFullException
|
||||
{
|
||||
super.insertElement(elmts, false);
|
||||
}
|
||||
public void insertElement(Element elmt)
|
||||
throws NodeWriteException, NodeFullException
|
||||
{
|
||||
super.insertElement(elmt);
|
||||
}
|
||||
public Element getLeastEnlargement(Element elmt)
|
||||
throws NodeEmptyException, IllegalValueException, NodeWriteException
|
||||
{
|
||||
return super.getLeastEnlargement(elmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriden so that this package can use it.
|
||||
* @param param1 <description>
|
||||
* @return <description>
|
||||
* @exception RTreeException <description>
|
||||
*/
|
||||
public Node[] splitNode(Element param1, long slotIndex) throws RTreeException, NodeWriteException
|
||||
{
|
||||
Node[] nodes = super.splitNode(param1, slotIndex);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriden so that this package can use it.
|
||||
*/
|
||||
public void modifyElement(int index,long pointer)
|
||||
throws IllegalValueException, IOException, NodeWriteException
|
||||
{
|
||||
super.modifyElement(index, pointer);
|
||||
}
|
||||
|
||||
public void deleteNode() throws NodeWriteException
|
||||
{
|
||||
super.deleteNode();
|
||||
}
|
||||
|
||||
public void modifyElement(int param1, Rect param2)
|
||||
throws IllegalValueException, IOException, NodeWriteException
|
||||
{
|
||||
super.modifyElement(param1, param2);
|
||||
}
|
||||
|
||||
public void deleteElement(int param1) throws IllegalValueException, NodeWriteException
|
||||
{
|
||||
super.deleteElement(param1, false);
|
||||
}
|
||||
|
||||
public void setParent(long param1) throws IOException, NodeWriteException
|
||||
{
|
||||
super.setParent(param1);
|
||||
}
|
||||
|
||||
}
|
||||
|
324
DataExtractionOSM/src/rtree/seeded/SdTree.java
Normal file
324
DataExtractionOSM/src/rtree/seeded/SdTree.java
Normal file
|
@ -0,0 +1,324 @@
|
|||
//SdTree.java
|
||||
//
|
||||
//This library is free software; you can redistribute it and/or
|
||||
//modify it under the terms of the GNU Lesser General Public
|
||||
//License as published by the Free Software Foundation; either
|
||||
//version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
//This library is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
//Lesser General Public License for more details.
|
||||
package rtree.seeded;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import rtree.Element;
|
||||
import rtree.IllegalValueException;
|
||||
import rtree.Node;
|
||||
import rtree.NodeFullException;
|
||||
import rtree.NodeReadException;
|
||||
import rtree.NodeWriteException;
|
||||
import rtree.NonLeafElement;
|
||||
import rtree.RTree;
|
||||
import rtree.RTreeException;
|
||||
import rtree.Rect;
|
||||
|
||||
/**
|
||||
This is a seeded class is good only for joining with the seeding class and not for window
|
||||
queries.
|
||||
How to use:
|
||||
1) Call the constructor.
|
||||
2) For each element to be inserted call <code>growLeaf</code>
|
||||
3) Positively call cleanup
|
||||
4) If you want you can create another rtree object from this file then flush the seed tree. Remember if
|
||||
this tree is used for query purpose and not going to be used again, there is no need to flush.
|
||||
@author Prachuryya Barua
|
||||
*/
|
||||
public class SdTree extends RTree
|
||||
{
|
||||
private String seedName = null;
|
||||
private RTree sdingTree = null;
|
||||
private int slotLvl = 1;
|
||||
|
||||
/**
|
||||
@param fileName The rtree filr name of this seed tree.
|
||||
@param sdingTree The <code>RTree</code> from which to start seeding.
|
||||
*/
|
||||
public SdTree(String fileName, RTree sdingTree)
|
||||
throws RTreeException
|
||||
{
|
||||
super(fileName);//this method should do its own locking
|
||||
try{
|
||||
System.out.println("SdTree:: sedding height is " + sdingTree.getHeight());
|
||||
fileHdr.lockWrite();
|
||||
try{
|
||||
fileHdr.setBufferPolicy(false);
|
||||
if(sdingTree == null)
|
||||
throw new IllegalArgumentException("SdTree: Seeding tree is null");
|
||||
this.sdingTree = sdingTree;
|
||||
setSlot();
|
||||
if(slotLvl >= 1)
|
||||
seed();
|
||||
//growLeaf();
|
||||
}catch(Exception e){throw new RTreeException(e.getMessage());}
|
||||
}finally{
|
||||
fileHdr.unlock();
|
||||
}
|
||||
}
|
||||
private void setSlot()
|
||||
{
|
||||
int ht = sdingTree.getHeight();
|
||||
switch(ht){
|
||||
case 0 : slotLvl = Node.NOT_DEFINED;
|
||||
break;
|
||||
case 1 : slotLvl = Node.NOT_DEFINED;
|
||||
break;
|
||||
case 2 : slotLvl = Node.NOT_DEFINED;
|
||||
break;
|
||||
case 3 : slotLvl = 1;
|
||||
break;
|
||||
case 4 : slotLvl = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
Start seeding - take the root node, copy it to this tree, keep on copying until the slot level.
|
||||
This method overwrites the root irrespective of its existance or nonexistence.
|
||||
*/
|
||||
private void seed()
|
||||
throws RTreeException
|
||||
{
|
||||
try{
|
||||
long sdingRoot = sdingTree.getFileHdr().getRootIndex();
|
||||
//somehow remove all the nodes of this tree from the cache and since we have a write lock
|
||||
//nobody can get this tree's nodes on to the buufer if we don't
|
||||
|
||||
Node sdingNode = sdingTree.getReadNode(sdingRoot);
|
||||
seedRec(sdingNode, chdNodes.getNode(fileHdr.getFile(), fileName, Node.NOT_DEFINED,//sd
|
||||
sdingNode.getElementType(), fileHdr), 0);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
@param sdingNode The seeding node from which to copy (source).
|
||||
@param level The height at which this node falls in the tree.
|
||||
*/
|
||||
private void seedRec(Node sdingNode, Node sdNode, int level)//sd
|
||||
throws Exception
|
||||
{
|
||||
if(sdingNode.getElementType() == Node.LEAF_NODE)
|
||||
throw new IllegalArgumentException("SdTree.seedRec : Cannot seed a leaf node");
|
||||
|
||||
//make the child nodes before hand so that we know their indices in file
|
||||
Node[] chNodes = null;//sd
|
||||
if(level != slotLvl)//we do not need to alocate new nodes if we are at slot level
|
||||
chNodes = new Node[sdingNode.getTotalElements()];//sd
|
||||
|
||||
Element[] elmts = sdingNode.getAllElements();
|
||||
Element[] newElmts = null;//elements for non-slot levels
|
||||
|
||||
if(level != slotLvl)
|
||||
newElmts = new Element[sdingNode.getTotalElements()];//non slots have multiple elements
|
||||
else{
|
||||
newElmts = new Element[1];//slot has only one element
|
||||
newElmts[0] = new NonLeafElement(new Rect(), Node.NOT_DEFINED);//element for slot level
|
||||
}
|
||||
for(int i=0; i<sdingNode.getTotalElements(); i++){//for each element in the seeding node
|
||||
|
||||
if(level != slotLvl){
|
||||
newElmts[i] = (NonLeafElement)((NonLeafElement)elmts[i]).clone();//we do not seed leaf elements
|
||||
chNodes[i] = chdNodes.getNode(fileHdr.getFile(), fileName, sdNode.getNodeIndex(),//sd
|
||||
sdingNode.getElementType(), fileHdr);
|
||||
newElmts[i].setPtr(chNodes[i].getNodeIndex());//update the child pointers for new node
|
||||
seedRec(sdingTree.getReadNode(elmts[i].getPtr()), chNodes[i], level+1);
|
||||
}else{//this is the slot level
|
||||
/*What we do here is that we put only one element into the slot node instead of all the elements.
|
||||
This would result in a single element in the node which represents all the seding node elements
|
||||
with a null pointer.
|
||||
*/
|
||||
newElmts[0].getRect().expandToInclude(elmts[i].getRect());
|
||||
}//else
|
||||
}//for
|
||||
sdNode.insertElement(newElmts, false);//copy the non-slot elements now //sd
|
||||
}
|
||||
|
||||
public void growLeaf(Element elmt)
|
||||
throws RTreeException
|
||||
{
|
||||
if(slotLvl == Node.NOT_DEFINED){
|
||||
try{
|
||||
insert(elmt);
|
||||
}catch(Exception e){
|
||||
throw new RTreeException(e.getMessage());
|
||||
}
|
||||
}else{
|
||||
fileHdr.lockWrite();
|
||||
try{
|
||||
long root = fileHdr.getRootIndex();
|
||||
//Long slotIndex = null;
|
||||
LongWraper slotIndex = new LongWraper();
|
||||
Node node = this.chooseLeaf(elmt, slotIndex);//sd
|
||||
|
||||
if(slotIndex == null)
|
||||
throw new NullPointerException();
|
||||
long nodeParent = node.getParent();
|
||||
Node[] newNodes = new Node[2];
|
||||
try{
|
||||
node.insertElement(elmt);//if another insert is possible
|
||||
newNodes[0] = node;
|
||||
newNodes[1] = null;
|
||||
}catch(NodeFullException e){ //if another insert is not possible
|
||||
newNodes = node.splitNode(elmt, slotIndex.val);
|
||||
}
|
||||
Node newRoot = adjustTree(newNodes, slotIndex.val);
|
||||
//if we got a new root node then we have to set the slot's child to point to this new root
|
||||
if(newRoot != null){
|
||||
Node slot = chdNodes.getNode(fileHdr.getFile(), fileName, newRoot.getParent(), fileHdr);//sd
|
||||
slot.modifyElement(0, newRoot.getNodeIndex());
|
||||
}
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}finally{
|
||||
fileHdr.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
This method is a copy of <code>RTree.chooseLeaf</code> with minor modifications.
|
||||
In fact there are number of changes , most important is that this method will just not get the new
|
||||
Node, but also change the parent's (slot node) child pointer.
|
||||
Remeber that if there are no leaf node associated with a slot selected, this method creates one
|
||||
returns this new Node after doing the process described above.
|
||||
but if there is a leaf node present then that node is returned just as in simple rtrees.
|
||||
*/
|
||||
private Node chooseLeaf(Element elmt, LongWraper slotIndex)//sd
|
||||
throws RTreeException, IOException
|
||||
{
|
||||
/*TODO : we may also have to traverse non seed node, i.e grown nodes.*/
|
||||
try{
|
||||
//get the root node
|
||||
long root = fileHdr.getRootIndex();
|
||||
int level = 0;
|
||||
Node sltNode = chdNodes.getNode(fileHdr.getFile(), fileName, root, fileHdr);//sd
|
||||
//repeat till you reach a slot node
|
||||
while(sltNode.getElementType() != Node.LEAF_NODE){//(level != slotLvl){
|
||||
//get the best fitting rect from the node
|
||||
Element nextElmt = sltNode.getLeastEnlargement(elmt);
|
||||
if(level == slotLvl){
|
||||
slotIndex.val = sltNode.getNodeIndex();
|
||||
if(nextElmt.getPtr() == Node.NOT_DEFINED){//the first leaf node for this slot node
|
||||
Node rtNode = chdNodes.getNode(fileHdr.getFile(), fileName, sltNode.getNodeIndex(),//sd
|
||||
Node.LEAF_NODE, fileHdr);
|
||||
|
||||
sltNode.modifyElement(0, rtNode.getNodeIndex());
|
||||
nextElmt.setPtr(rtNode.getNodeIndex());
|
||||
return rtNode;
|
||||
}
|
||||
}
|
||||
//if are here then we are not at a slot that has no childs
|
||||
|
||||
sltNode = chdNodes.getNode(fileHdr.getFile(), fileName, nextElmt.getPtr(), fileHdr);//sd
|
||||
level++;
|
||||
}//while
|
||||
//if we are here then we reached a proper leaf node rather than a slot node
|
||||
return sltNode;
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This method will adjust the slot's only elements's child pointer.
|
||||
*/
|
||||
private void adjustSlot(Node node, long childIndex)//sd
|
||||
throws RTreeException
|
||||
{
|
||||
try{
|
||||
node.modifyElement(0, childIndex);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The clean up pahse is the last method that should be called after all the data have been grown.
|
||||
* This method basically adjusts all the slot nodes after all the insertions are made
|
||||
*/
|
||||
public void cleanUp()
|
||||
throws RTreeException
|
||||
{
|
||||
try{
|
||||
fileHdr.lockWrite();
|
||||
if(slotLvl == Node.NOT_DEFINED)
|
||||
return;
|
||||
long root = fileHdr.getRootIndex();
|
||||
Node node = chdNodes.getNode(fileHdr.getFile(), fileName, root, fileHdr);//sd
|
||||
cleanUpRec(node, 0);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
throw new RTreeException(e.getMessage());
|
||||
}finally{
|
||||
fileHdr.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adjusts all the seed node MBRs to the grown subtrees. It also delets the slot node and
|
||||
* makes the root node of the underneath substree as the slot node.
|
||||
*/
|
||||
private Rect cleanUpRec(Node node, int level)//sd
|
||||
throws NodeWriteException, FileNotFoundException, IllegalValueException, IOException, NodeReadException,
|
||||
RTreeException
|
||||
{
|
||||
Element[] elmts = node.getAllElements();
|
||||
if(level == slotLvl){//if level is the slot
|
||||
if(elmts[0].getPtr() == Node.NOT_DEFINED){//this slot was never supplied a child node
|
||||
node.deleteNode();
|
||||
return new Rect();//a null rect
|
||||
}else{//a slot that does have child node
|
||||
//remove this slot node and make the parent element point to the child of this slot node
|
||||
|
||||
Node parentNode = chdNodes.getNode(fileHdr.getFile(), fileName, node.getParent(), fileHdr);//sd
|
||||
int index = parentNode.getElementIndex(node.getNodeIndex());
|
||||
parentNode.modifyElement(index, elmts[0].getPtr());
|
||||
|
||||
Node subRoot = chdNodes.getNode(fileHdr.getFile(), fileName, elmts[0].getPtr(), fileHdr);//sd
|
||||
|
||||
subRoot.setParent(node.getParent());
|
||||
node.deleteNode();
|
||||
|
||||
return(subRoot.getNodeMBR());
|
||||
}//else
|
||||
}else{//it is not slot node but a seed node
|
||||
//remebeer we may have a situation where we do not get any Rect from down below this node...we delete
|
||||
//this node as well.
|
||||
Rect rect = new Rect();
|
||||
for(int i=node.getTotalElements()-1; i>-1; i--){//for each element in this seed node
|
||||
Node chNode = chdNodes.getNode(fileHdr.getFile(), fileName, elmts[i].getPtr(), fileHdr);//sd
|
||||
Rect chRect = cleanUpRec(chNode, level + 1);
|
||||
rect.expandToInclude(chRect);//get child node's rect
|
||||
if(chRect.isNull()){//situation where child node does not have grown subtrees underneath
|
||||
node.deleteElement(i, false);
|
||||
}else{//we do have a child Rect
|
||||
node.modifyElement(i, chRect);
|
||||
}//else
|
||||
}//for
|
||||
if(rect.isNull()){//situation where there are no grown subtrees underneath this node
|
||||
node.deleteNode();
|
||||
}
|
||||
return rect;
|
||||
}//else
|
||||
}
|
||||
class LongWraper
|
||||
{
|
||||
long val = Node.NOT_DEFINED;
|
||||
}
|
||||
}
|
||||
//(79 residential_1 conby 121 main_area ** select * from main_area where strName like 'andheri'**)
|
Loading…
Reference in a new issue