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.LibraryProvider;
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.URIMetadataRow;
import net.yacy.kelondro.data.word.Word;
@ -909,12 +909,12 @@ public class yacysearch {
}
// 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 ) {
prop.put("geoinfo", "0");
} else {
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 + "_lat", Math.round(c.lat() * 10000.0f) / 10000.0f);
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.services.federated.opensearch.SRURSSConnector;
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.SwitchboardConstants;
import de.anomic.server.serverCore;
@ -67,11 +67,11 @@ public class yacysearch_location {
int placemarkCounter = 0;
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(" ")) {
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
prop.put("kml_placemark_" + placemarkCounter + "_location", 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,90 +1,93 @@
/**
* Location.java
* 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;
import java.util.Comparator;
public class Location extends Coordinates implements Comparable<Location>, Comparator<Location> {
private String name;
private int population;
public Location(float lon, float lat) {
super(lon, lat);
this.name = null;
this.population = 0;
}
public Location(float lon, float lat, String name) {
super(lon, lat);
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setPopulation(int population) {
this.population = population;
}
public int getPopulation() {
return this.population;
}
public boolean equals(Object loc) {
if (!(loc instanceof Location)) return false;
if (this.name == null || ((Location) loc).name == null) return super.equals(loc);
return super.equals(loc) && this.name.toLowerCase().equals(((Location) loc).name.toLowerCase());
}
/**
* comparator that is needed to use the object inside TreeMap/TreeSet
* a Location is smaller than another if it has a _greater_ population
* this order is used to get sorted lists of locations where the first elements
* have the greatest population
*/
public int compareTo(Location o) {
if (this.equals(o)) return 0;
long s = (ph(this.getPopulation()) << 30) + this.hashCode();
long t = (ph(o.getPopulation()) << 30) + o.hashCode();
if (s > t) return -1;
if (s < t) return 1;
return 0;
}
private long ph(int population) {
if (population > 10000) population -= 10000;
return (long) population;
}
public int compare(Location o1, Location o2) {
return o1.compareTo(o2);
}
}
/**
* GeoLocation
* 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;
import java.util.Comparator;
public class GeoLocation extends GeoPoint implements Comparable<GeoLocation>, Comparator<GeoLocation> {
private String name;
private int population;
public GeoLocation(double lat, double lon) {
super(lat, lon);
this.name = null;
this.population = 0;
}
public GeoLocation(double lat, double lon, String name) {
super(lat, lon);
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setPopulation(int population) {
this.population = population;
}
public int getPopulation() {
return this.population;
}
@Override
public boolean equals(Object loc) {
if (!(loc instanceof GeoLocation)) return false;
if (this.name == null || ((GeoLocation) loc).name == null) return super.equals(loc);
return super.equals(loc) && this.name.toLowerCase().equals(((GeoLocation) loc).name.toLowerCase());
}
/**
* comparator that is needed to use the object inside TreeMap/TreeSet
* a Location is smaller than another if it has a _greater_ population
* this order is used to get sorted lists of locations where the first elements
* have the greatest population
*/
@Override
public int compareTo(GeoLocation o) {
if (this.equals(o)) return 0;
long s = (ph(this.getPopulation()) << 30) + this.hashCode();
long t = (ph(o.getPopulation()) << 30) + o.hashCode();
if (s > t) return -1;
if (s < t) return 1;
return 0;
}
private long ph(int population) {
if (population > 10000) population -= 10000;
return population;
}
@Override
public int compare(GeoLocation o1, GeoLocation 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
*/
private final Map<Integer, Location> id2loc;
private final Map<Integer, GeoLocation> id2loc;
private final TreeMap<StringBuilder, List<Integer>> name2ids;
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.file = file;
this.id2loc = new HashMap<Integer, Location>();
this.id2loc = new HashMap<Integer, GeoLocation>();
this.name2ids =
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(",") ) {
locnames.add(new StringBuilder(s));
}
final Location c =
new Location(Float.parseFloat(fields[5]), Float.parseFloat(fields[4]), fields[1]);
final GeoLocation c =
new GeoLocation(Float.parseFloat(fields[4]), Float.parseFloat(fields[5]), fields[1]);
c.setPopulation((int) Long.parseLong(fields[14]));
this.id2loc.put(id, c);
for ( final StringBuilder name : locnames ) {
@ -136,7 +136,7 @@ public class GeonamesLocalization implements Localization
}
@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>();
List<Integer> c;
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 ) {
final Location w = this.id2loc.get(e);
final GeoLocation w = this.id2loc.get(e);
if ( w != null ) {
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
* @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

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

Loading…
Cancel
Save