added GeoLocation / GeoPoint classes which uses less memory than

Location/Coordinates and has initializers with correct order of lat,lon
coordinates
pull/1/head
Michael Peter Christen 13 years ago
parent 62ae9bbfda
commit 96c8119b50

@ -55,7 +55,7 @@ import net.yacy.document.Condenser;
import net.yacy.document.Document; import net.yacy.document.Document;
import net.yacy.document.LibraryProvider; import net.yacy.document.LibraryProvider;
import net.yacy.document.Parser; import net.yacy.document.Parser;
import net.yacy.document.geolocalization.Location; import net.yacy.document.geolocalization.GeoLocation;
import net.yacy.kelondro.data.meta.DigestURI; import net.yacy.kelondro.data.meta.DigestURI;
import net.yacy.kelondro.data.meta.URIMetadataRow; import net.yacy.kelondro.data.meta.URIMetadataRow;
import net.yacy.kelondro.data.word.Word; import net.yacy.kelondro.data.word.Word;
@ -909,12 +909,12 @@ public class yacysearch {
} }
// find geographic info // find geographic info
final SortedSet<Location> coordinates = LibraryProvider.geoLoc.find(originalquerystring, false); final SortedSet<GeoLocation> coordinates = LibraryProvider.geoLoc.find(originalquerystring, false);
if ( coordinates == null || coordinates.isEmpty() || startRecord > 0 ) { if ( coordinates == null || coordinates.isEmpty() || startRecord > 0 ) {
prop.put("geoinfo", "0"); prop.put("geoinfo", "0");
} else { } else {
int i = 0; int i = 0;
for ( final Location c : coordinates ) { for ( final GeoLocation c : coordinates ) {
prop.put("geoinfo_loc_" + i + "_lon", Math.round(c.lon() * 10000.0f) / 10000.0f); prop.put("geoinfo_loc_" + i + "_lon", Math.round(c.lon() * 10000.0f) / 10000.0f);
prop.put("geoinfo_loc_" + i + "_lat", Math.round(c.lat() * 10000.0f) / 10000.0f); prop.put("geoinfo_loc_" + i + "_lat", Math.round(c.lat() * 10000.0f) / 10000.0f);
prop.put("geoinfo_loc_" + i + "_name", c.getName()); prop.put("geoinfo_loc_" + i + "_name", c.getName());

@ -28,7 +28,7 @@ import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.protocol.RequestHeader; import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.services.federated.opensearch.SRURSSConnector; import net.yacy.cora.services.federated.opensearch.SRURSSConnector;
import net.yacy.document.LibraryProvider; import net.yacy.document.LibraryProvider;
import net.yacy.document.geolocalization.Location; import net.yacy.document.geolocalization.GeoLocation;
import net.yacy.search.Switchboard; import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants; import net.yacy.search.SwitchboardConstants;
import de.anomic.server.serverCore; import de.anomic.server.serverCore;
@ -67,11 +67,11 @@ public class yacysearch_location {
int placemarkCounter = 0; int placemarkCounter = 0;
if (query.length() > 0 && search_query) { if (query.length() > 0 && search_query) {
final Set<Location> locations = LibraryProvider.geoLoc.find(query, true); final Set<GeoLocation> locations = LibraryProvider.geoLoc.find(query, true);
for (final String qp: query.split(" ")) { for (final String qp: query.split(" ")) {
locations.addAll(LibraryProvider.geoLoc.find(qp, true)); locations.addAll(LibraryProvider.geoLoc.find(qp, true));
} }
for (final Location location: locations) { for (final GeoLocation location: locations) {
// write for all locations a point to this message // write for all locations a point to this message
prop.put("kml_placemark_" + placemarkCounter + "_location", location.getName()); prop.put("kml_placemark_" + placemarkCounter + "_location", location.getName());
prop.put("kml_placemark_" + placemarkCounter + "_name", location.getName()); prop.put("kml_placemark_" + placemarkCounter + "_name", location.getName());

@ -1,73 +0,0 @@
/**
* Coordinates.java
* Copyright 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany
* first published 04.10.2009 on http://yacy.net
*
* This file is part of YaCy Content Integration
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.document.geolocalization;
public class Coordinates {
private static final double tenmeter = 90.0d / 1.0e6d;
private final double lon, lat;
public Coordinates(double lon, double lat) {
this.lon = lon;
this.lat = lat;
}
public double lon() {
return this.lon;
}
public double lat() {
return this.lat;
}
private static final double bits30 = new Double(1L << 30).doubleValue(); // this is about one billion (US)
private static final double upscale = bits30 / 360.0;
private static final int coord2int(double coord) {
return (int) ((180.0 - coord) * upscale);
}
/**
* compute the hash code of a coordinate
* this produces identical hash codes for locations that are close to each other
*/
public int hashCode() {
return coord2int(this.lon) + (coord2int(this.lat) >> 15);
}
/**
* equality test that is needed to use the class inside HashMap/HashSet
*/
public boolean equals(final Object o) {
if (!(o instanceof Coordinates)) return false;
Coordinates oo = (Coordinates) o;
if (this.lon == oo.lon && this.lat == oo.lat) return true;
// we access fuzzy values that are considered as equal if they are close to each other
return Math.abs(this.lon - oo.lon) < tenmeter && Math.abs(this.lat - oo.lat) < tenmeter;
}
public String toString() {
return "[" + this.lon + "," + this.lat + "]";
}
}

@ -1,5 +1,5 @@
/** /**
* Location.java * GeoLocation
* Copyright 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany * Copyright 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany
* first published 08.10.2009 on http://yacy.net * first published 08.10.2009 on http://yacy.net
* *
@ -25,19 +25,19 @@ package net.yacy.document.geolocalization;
import java.util.Comparator; import java.util.Comparator;
public class Location extends Coordinates implements Comparable<Location>, Comparator<Location> { public class GeoLocation extends GeoPoint implements Comparable<GeoLocation>, Comparator<GeoLocation> {
private String name; private String name;
private int population; private int population;
public Location(float lon, float lat) { public GeoLocation(double lat, double lon) {
super(lon, lat); super(lat, lon);
this.name = null; this.name = null;
this.population = 0; this.population = 0;
} }
public Location(float lon, float lat, String name) { public GeoLocation(double lat, double lon, String name) {
super(lon, lat); super(lat, lon);
this.name = name; this.name = name;
} }
@ -57,10 +57,11 @@ public class Location extends Coordinates implements Comparable<Location>, Compa
return this.population; return this.population;
} }
@Override
public boolean equals(Object loc) { public boolean equals(Object loc) {
if (!(loc instanceof Location)) return false; if (!(loc instanceof GeoLocation)) return false;
if (this.name == null || ((Location) loc).name == null) return super.equals(loc); if (this.name == null || ((GeoLocation) loc).name == null) return super.equals(loc);
return super.equals(loc) && this.name.toLowerCase().equals(((Location) loc).name.toLowerCase()); return super.equals(loc) && this.name.toLowerCase().equals(((GeoLocation) loc).name.toLowerCase());
} }
/** /**
@ -69,7 +70,8 @@ public class Location extends Coordinates implements Comparable<Location>, Compa
* this order is used to get sorted lists of locations where the first elements * this order is used to get sorted lists of locations where the first elements
* have the greatest population * have the greatest population
*/ */
public int compareTo(Location o) { @Override
public int compareTo(GeoLocation o) {
if (this.equals(o)) return 0; if (this.equals(o)) return 0;
long s = (ph(this.getPopulation()) << 30) + this.hashCode(); long s = (ph(this.getPopulation()) << 30) + this.hashCode();
long t = (ph(o.getPopulation()) << 30) + o.hashCode(); long t = (ph(o.getPopulation()) << 30) + o.hashCode();
@ -80,10 +82,11 @@ public class Location extends Coordinates implements Comparable<Location>, Compa
private long ph(int population) { private long ph(int population) {
if (population > 10000) population -= 10000; if (population > 10000) population -= 10000;
return (long) population; return population;
} }
public int compare(Location o1, Location o2) { @Override
public int compare(GeoLocation o1, GeoLocation o2) {
return o1.compareTo(o2); return o1.compareTo(o2);
} }

@ -0,0 +1,91 @@
/**
* GeoPoint
* Copyright 2009 by Michael Peter Christen; mc@yacy.net, Frankfurt a. M., Germany
* first published 08.10.2009 on http://yacy.net
*
* This file is part of YaCy Content Integration
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.document.geolocalization;
public class GeoPoint {
public static final double meter = 90.0d / 1.0e7d; // this is actually the definition of 'meter': 10 million meter shall be the distance from the equator to the pole
private final long latlon; // using one variable for the coordinate pair saves some space
public GeoPoint(double lat, double lon) {
this.latlon = (((long) coord2int(lat)) << 32) | (coord2int(lon));
}
public GeoPoint(int lat, int lon) {
this.latlon = (((long) coord2int(lat / 1e6d)) << 32) | (coord2int(lon / 1e6d));
}
public double lon() {
return int2coord((int) (this.latlon & (Integer.MAX_VALUE)));
}
public double lat() {
return int2coord((int) (this.latlon >>> 32));
}
private static final double maxint = new Double(Integer.MAX_VALUE).doubleValue();
private static final double upscale = maxint / 360.0;
private static final int coord2int(double coord) {
return (int) ((coord + 180.0) * upscale);
}
private static final double int2coord(int z) {
return (z / upscale) - 180.0;
}
/**
* compute the hash code of a coordinate
* this produces identical hash codes for locations that are close to each other
*/
@Override
public int hashCode() {
return (int) ((this.latlon & Integer.MAX_VALUE) >> 1) + (int) (this.latlon >> 33);
}
/**
* equality test that is needed to use the class inside HashMap/HashSet
*/
@Override
public boolean equals(final Object o) {
if (!(o instanceof GeoPoint)) return false;
GeoPoint oo = (GeoPoint) o;
return (this.latlon == oo.latlon);
}
@Override
public String toString() {
return "[" + this.lat() + "," + this.lon() + "]";
}
public static void main(String[] args) {
double lat = 13.419444d;
double lon = 52.548611d;
GeoPoint c = new GeoPoint(lat, lon);
System.out.println(c.toString() + " #" + c.hashCode());
System.out.println("error: lat: " + (Math.abs(c.lat() - lat) / meter) + " meter; lon: " + (Math.abs(c.lon() - lon) / meter) + " meter");
}
}

@ -69,7 +69,7 @@ public class GeonamesLocalization implements Localization
modification date : date of last modification in yyyy-MM-dd format modification date : date of last modification in yyyy-MM-dd format
*/ */
private final Map<Integer, Location> id2loc; private final Map<Integer, GeoLocation> id2loc;
private final TreeMap<StringBuilder, List<Integer>> name2ids; private final TreeMap<StringBuilder, List<Integer>> name2ids;
private final File file; private final File file;
@ -77,7 +77,7 @@ public class GeonamesLocalization implements Localization
// this is a processing of the cities1000.zip file from http://download.geonames.org/export/dump/ // this is a processing of the cities1000.zip file from http://download.geonames.org/export/dump/
this.file = file; this.file = file;
this.id2loc = new HashMap<Integer, Location>(); this.id2loc = new HashMap<Integer, GeoLocation>();
this.name2ids = this.name2ids =
new TreeMap<StringBuilder, List<Integer>>(StringBuilderComparator.CASE_INSENSITIVE_ORDER); new TreeMap<StringBuilder, List<Integer>>(StringBuilderComparator.CASE_INSENSITIVE_ORDER);
@ -112,8 +112,8 @@ public class GeonamesLocalization implements Localization
for ( final String s : fields[3].split(",") ) { for ( final String s : fields[3].split(",") ) {
locnames.add(new StringBuilder(s)); locnames.add(new StringBuilder(s));
} }
final Location c = final GeoLocation c =
new Location(Float.parseFloat(fields[5]), Float.parseFloat(fields[4]), fields[1]); new GeoLocation(Float.parseFloat(fields[4]), Float.parseFloat(fields[5]), fields[1]);
c.setPopulation((int) Long.parseLong(fields[14])); c.setPopulation((int) Long.parseLong(fields[14]));
this.id2loc.put(id, c); this.id2loc.put(id, c);
for ( final StringBuilder name : locnames ) { for ( final StringBuilder name : locnames ) {
@ -136,7 +136,7 @@ public class GeonamesLocalization implements Localization
} }
@Override @Override
public TreeSet<Location> find(final String anyname, final boolean locationexact) { public TreeSet<GeoLocation> find(final String anyname, final boolean locationexact) {
final Set<Integer> r = new HashSet<Integer>(); final Set<Integer> r = new HashSet<Integer>();
List<Integer> c; List<Integer> c;
final StringBuilder an = new StringBuilder(anyname); final StringBuilder an = new StringBuilder(anyname);
@ -155,9 +155,9 @@ public class GeonamesLocalization implements Localization
} }
} }
} }
final TreeSet<Location> a = new TreeSet<Location>(); final TreeSet<GeoLocation> a = new TreeSet<GeoLocation>();
for ( final Integer e : r ) { for ( final Integer e : r ) {
final Location w = this.id2loc.get(e); final GeoLocation w = this.id2loc.get(e);
if ( w != null ) { if ( w != null ) {
a.add(w); a.add(w);
} }

@ -45,7 +45,7 @@ public interface Localization {
* @param locationexact - if true, then only exact matched with the location are returned. if false also partially matching names * @param locationexact - if true, then only exact matched with the location are returned. if false also partially matching names
* @return a set of locations, ordered by population (if this information is given) * @return a set of locations, ordered by population (if this information is given)
*/ */
public TreeSet<Location> find(String anyname, boolean locationexact); public TreeSet<GeoLocation> find(String anyname, boolean locationexact);
/** /**
* produce a set of location names * produce a set of location names

@ -53,7 +53,7 @@ public class OpenGeoDBLocalization implements Localization
{ {
private final Map<Integer, String> locTypeHash2locType; private final Map<Integer, String> locTypeHash2locType;
private final Map<Integer, Location> id2loc; private final Map<Integer, GeoLocation> id2loc;
private final Map<Integer, Integer> id2locTypeHash; private final Map<Integer, Integer> id2locTypeHash;
private final TreeMap<StringBuilder, List<Integer>> name2ids; private final TreeMap<StringBuilder, List<Integer>> name2ids;
private final TreeMap<StringBuilder, List<Integer>> kfz2ids; private final TreeMap<StringBuilder, List<Integer>> kfz2ids;
@ -65,7 +65,7 @@ public class OpenGeoDBLocalization implements Localization
this.file = file; this.file = file;
this.locTypeHash2locType = new HashMap<Integer, String>(); this.locTypeHash2locType = new HashMap<Integer, String>();
this.id2loc = new HashMap<Integer, Location>(); this.id2loc = new HashMap<Integer, GeoLocation>();
this.id2locTypeHash = new HashMap<Integer, Integer>(); this.id2locTypeHash = new HashMap<Integer, Integer>();
this.name2ids = this.name2ids =
new TreeMap<StringBuilder, List<Integer>>(StringBuilderComparator.CASE_INSENSITIVE_ORDER); new TreeMap<StringBuilder, List<Integer>>(StringBuilderComparator.CASE_INSENSITIVE_ORDER);
@ -112,7 +112,7 @@ public class OpenGeoDBLocalization implements Localization
lat = Float.parseFloat(v[2]); lat = Float.parseFloat(v[2]);
lon = Float.parseFloat(v[3]); lon = Float.parseFloat(v[3]);
} }
this.id2loc.put(Integer.parseInt(v[0]), new Location(lon, lat)); this.id2loc.put(Integer.parseInt(v[0]), new GeoLocation(lat, lon));
} }
if ( line.startsWith("geodb_textdata ") ) { if ( line.startsWith("geodb_textdata ") ) {
line = line.substring(15 + 7); line = line.substring(15 + 7);
@ -126,7 +126,7 @@ public class OpenGeoDBLocalization implements Localization
} }
l.add(id); l.add(id);
this.name2ids.put(new StringBuilder(h), l); this.name2ids.put(new StringBuilder(h), l);
final Location loc = this.id2loc.get(id); final GeoLocation loc = this.id2loc.get(id);
if ( loc != null ) { if ( loc != null ) {
loc.setName(h); loc.setName(h);
} }
@ -200,7 +200,7 @@ public class OpenGeoDBLocalization implements Localization
* @return * @return
*/ */
@Override @Override
public TreeSet<Location> find(final String anyname, final boolean locationexact) { public TreeSet<GeoLocation> find(final String anyname, final boolean locationexact) {
final HashSet<Integer> r = new HashSet<Integer>(); final HashSet<Integer> r = new HashSet<Integer>();
List<Integer> c; List<Integer> c;
final StringBuilder an = new StringBuilder(anyname); final StringBuilder an = new StringBuilder(anyname);
@ -231,9 +231,9 @@ public class OpenGeoDBLocalization implements Localization
r.add(i); r.add(i);
} }
} }
final TreeSet<Location> a = new TreeSet<Location>(); final TreeSet<GeoLocation> a = new TreeSet<GeoLocation>();
for ( final Integer e : r ) { for ( final Integer e : r ) {
final Location w = this.id2loc.get(e); final GeoLocation w = this.id2loc.get(e);
if ( w != null ) { if ( w != null ) {
a.add(w); a.add(w);
} }

@ -76,8 +76,8 @@ public class OverarchingLocalization implements Localization {
* @return a set of locations, ordered by population (if this information is given) * @return a set of locations, ordered by population (if this information is given)
*/ */
@Override @Override
public TreeSet<Location> find(final String anyname, final boolean locationexact) { public TreeSet<GeoLocation> find(final String anyname, final boolean locationexact) {
final TreeSet<Location> locations = new TreeSet<Location>(); final TreeSet<GeoLocation> locations = new TreeSet<GeoLocation>();
for (final Localization service: this.services.values()) { for (final Localization service: this.services.values()) {
locations.addAll(service.find(anyname, locationexact)); locations.addAll(service.find(anyname, locationexact));
} }

Loading…
Cancel
Save