Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Genesys PGR
Geo Tools
Commits
7cd5e683
Commit
7cd5e683
authored
May 01, 2018
by
Matija Obreza
Browse files
Calculate distance to closest point on country border
parent
f5469f9a
Changes
3
Hide whitespace changes
Inline
Side-by-side
genesys-geotools/src/main/java/org/genesys/geotools/service/CountryOfOriginService.java
View file @
7cd5e683
...
...
@@ -33,4 +33,15 @@ public interface CountryOfOriginService {
*/
String
getCountries
(
float
longitude
,
float
latitude
,
String
origCty
,
int
allowedDistanceMargin
)
throws
Exception
;
/**
* Get distance from georeference to closest point on border of specified country
*
* @param longitude the longitude
* @param latitude the latitude
* @param origCty the country ISO code
* @return distance to closest point on country border or -1 if not found
* @throws Exception
*/
double
distanceToBorder
(
float
longitude
,
float
latitude
,
String
origCty
)
throws
Exception
;
}
genesys-geotools/src/main/java/org/genesys/geotools/service/impl/CountryOfOriginServiceImpl.java
View file @
7cd5e683
...
...
@@ -31,8 +31,10 @@ import org.geotools.data.FeatureSource;
import
org.geotools.factory.CommonFactoryFinder
;
import
org.geotools.feature.FeatureCollection
;
import
org.geotools.feature.FeatureIterator
;
import
org.geotools.geometry.jts.JTS
;
import
org.geotools.geometry.jts.JTSFactoryFinder
;
import
org.geotools.geometry.jts.ReferencedEnvelope
;
import
org.geotools.referencing.GeodeticCalculator
;
import
org.geotools.referencing.crs.DefaultGeographicCRS
;
import
org.opengis.feature.simple.SimpleFeature
;
import
org.opengis.feature.simple.SimpleFeatureType
;
...
...
@@ -47,7 +49,9 @@ import com.google.common.cache.CacheStats;
import
com.google.common.cache.LoadingCache
;
import
com.vividsolutions.jts.geom.Coordinate
;
import
com.vividsolutions.jts.geom.GeometryFactory
;
import
com.vividsolutions.jts.geom.MultiPolygon
;
import
com.vividsolutions.jts.geom.Point
;
import
com.vividsolutions.jts.operation.distance.DistanceOp
;
/**
* Polygons used here are derived from OSM data, © OpenStreetMap contributors.
...
...
@@ -72,6 +76,9 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
/** The country cache. */
private
LoadingCache
<
LonLatCacheKey
,
String
>
countryCache
;
/** The country cache. */
private
LoadingCache
<
LonLatCacheKey
,
Double
>
countryDistanceCache
;
/** The debug. */
private
final
boolean
debug
=
false
;
...
...
@@ -80,7 +87,7 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
public
void
setDataFolderPath
(
String
dataFolderPath
)
{
this
.
dataFolderPath
=
dataFolderPath
;
}
static
{
try
{
// Initialize stuff
...
...
@@ -106,14 +113,21 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
sourceAdmin0
=
dataStoreAdm0
.
getFeatureSource
(
dataStoreAdm0
.
getTypeNames
()[
0
]);
sourceAdmin0X
=
dataStoreAdm0X
.
getFeatureSource
(
dataStoreAdm0X
.
getTypeNames
()[
0
]);
countryCache
=
CacheBuilder
.
newBuilder
().
maximumSize
(
5000
).
recordStats
().
expireAfterWrite
(
20
,
TimeUnit
.
SECONDS
).
build
(
new
CacheLoader
<
LonLatCacheKey
,
String
>()
{
@Override
public
String
load
(
final
LonLatCacheKey
key
)
throws
Exception
{
// LOG.debug("Loading");
return
_getCountry
(
key
.
getLongitude
(),
key
.
getLatitude
(),
key
.
getOrigCty
(),
key
.
getAllowedDistanceMargin
());
}
});
countryCache
=
CacheBuilder
.
newBuilder
().
maximumSize
(
5000
).
recordStats
().
expireAfterWrite
(
20
,
TimeUnit
.
SECONDS
).
build
(
new
CacheLoader
<
LonLatCacheKey
,
String
>()
{
@Override
public
String
load
(
final
LonLatCacheKey
key
)
throws
Exception
{
// LOG.debug("Loading");
return
_getCountry
(
key
.
getLongitude
(),
key
.
getLatitude
(),
key
.
getOrigCty
(),
key
.
getAllowedDistanceMargin
());
}
});
countryDistanceCache
=
CacheBuilder
.
newBuilder
().
maximumSize
(
5000
).
recordStats
().
expireAfterWrite
(
20
,
TimeUnit
.
SECONDS
).
build
(
new
CacheLoader
<
LonLatCacheKey
,
Double
>()
{
@Override
public
Double
load
(
final
LonLatCacheKey
key
)
throws
Exception
{
// LOG.debug("Loading");
return
_distanceToBorder
(
key
.
getLongitude
(),
key
.
getLatitude
(),
key
.
getOrigCty
());
}
});
}
/*
...
...
@@ -121,8 +135,7 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
* @see org.genesys.geotools.LandOrSeaService#isOnLand(float, float, int)
*/
@Override
public
String
getCountries
(
final
float
longitude
,
final
float
latitude
,
final
String
origCty
,
final
int
allowedDistanceMargin
)
throws
Exception
{
public
String
getCountries
(
final
float
longitude
,
final
float
latitude
,
final
String
origCty
,
final
int
allowedDistanceMargin
)
throws
Exception
{
// 1 geographical mile is 1855.3248 metres for WGS84
// 1855.3248m * 60 = 111319.488m
...
...
@@ -149,8 +162,7 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
* @return the string
* @throws Exception the exception
*/
private
String
_getCountry
(
final
float
longitude
,
final
float
latitude
,
final
String
origCtyISO
,
final
int
allowedDistanceMargin
)
throws
Exception
{
private
String
_getCountry
(
final
float
longitude
,
final
float
latitude
,
final
String
origCtyISO
,
final
int
allowedDistanceMargin
)
throws
Exception
{
// LOG.debug(longitude + ", " + latitude + " " + origCtyISO);
final
StopWatch
stopWatch
=
new
StopWatch
();
...
...
@@ -161,8 +173,7 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
// sourceAdmin0.getSchema().getGeometryDescriptor()
// .getCoordinateReferenceSystem();
final
ReferencedEnvelope
bbox
=
new
ReferencedEnvelope
(
longitude
-
30
,
longitude
+
30
,
latitude
-
30
,
latitude
+
30
,
DefaultGeographicCRS
.
WGS84
);
final
ReferencedEnvelope
bbox
=
new
ReferencedEnvelope
(
longitude
-
30
,
longitude
+
30
,
latitude
-
30
,
latitude
+
30
,
DefaultGeographicCRS
.
WGS84
);
final
Filter
filterExact
=
// ff.and(
...
...
@@ -233,14 +244,62 @@ public class CountryOfOriginServiceImpl implements CountryOfOriginService {
return
sb
.
toString
();
}
@Override
public
double
distanceToBorder
(
float
longitude
,
float
latitude
,
String
origCty
)
throws
Exception
{
try
{
return
countryDistanceCache
.
get
(
new
LonLatCacheKey
(
longitude
,
latitude
,
origCty
,
0
));
}
catch
(
final
ExecutionException
e
)
{
throw
new
Exception
(
e
.
getCause
());
}
}
private
double
_distanceToBorder
(
float
longitude
,
float
latitude
,
String
origCty
)
throws
Exception
{
Coordinate
coordinate
=
new
Coordinate
(
longitude
,
latitude
);
final
Point
point
=
geometryFactory
.
createPoint
(
coordinate
);
final
Filter
filterExact
=
ff
.
equal
(
ff
.
property
(
"ISO3"
),
ff
.
literal
(
origCty
),
false
);
try
{
final
FeatureCollection
<
SimpleFeatureType
,
SimpleFeature
>
matchingFeatures
=
sourceAdmin0
.
getFeatures
(
filterExact
);
if
(
matchingFeatures
.
size
()
>
0
)
{
if
(
LOG
.
isTraceEnabled
())
{
try
(
FeatureIterator
<
SimpleFeature
>
features
=
matchingFeatures
.
features
())
{
while
(
features
.
hasNext
())
{
final
SimpleFeature
feature
=
features
.
next
();
LOG
.
trace
(
"{}: {} Attrs={}"
,
feature
.
getID
(),
feature
.
getDefaultGeometryProperty
().
getValue
(),
feature
.
getAttributes
());
}
}
}
try
(
FeatureIterator
<
SimpleFeature
>
features
=
matchingFeatures
.
features
())
{
if
(
features
.
hasNext
())
{
final
SimpleFeature
feature
=
features
.
next
();
MultiPolygon
geometry
=
(
MultiPolygon
)
feature
.
getDefaultGeometry
();
GeodeticCalculator
gc
=
new
GeodeticCalculator
(
DefaultGeographicCRS
.
WGS84
);
gc
.
setStartingPosition
(
JTS
.
toDirectPosition
(
DistanceOp
.
nearestPoints
(
geometry
,
point
)[
0
],
DefaultGeographicCRS
.
WGS84
));
gc
.
setDestinationPosition
(
JTS
.
toDirectPosition
(
coordinate
,
DefaultGeographicCRS
.
WGS84
));
return
gc
.
getOrthodromicDistance
();
}
else
{
return
-
1.0d
;
}
}
}
else
{
LOG
.
debug
(
"No geometry with ISO={}"
,
origCty
);
return
-
1.0d
;
}
}
catch
(
IOException
e
)
{
throw
e
;
}
}
/**
* Prints the cache.
*/
public
void
printCache
()
{
final
CacheStats
stats
=
countryCache
.
stats
();
if
(
LOG
.
isInfoEnabled
())
{
LOG
.
info
(
"Hit count="
+
stats
.
hitCount
()
+
" rate="
+
stats
.
hitRate
()
+
" Miss count="
+
stats
.
missCount
()
+
" rate="
+
stats
.
missRate
());
LOG
.
info
(
"Hit count="
+
stats
.
hitCount
()
+
" rate="
+
stats
.
hitRate
()
+
" Miss count="
+
stats
.
missCount
()
+
" rate="
+
stats
.
missRate
());
}
}
}
geotools-cli/src/main/java/org/genesys/geotools/cli/CountryDistance.java
0 → 100644
View file @
7cd5e683
/*
* Copyright 2016 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.genesys.geotools.cli
;
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
org.genesys.geotools.service.impl.CountryOfOriginServiceImpl
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
public
class
CountryDistance
{
private
final
static
Logger
LOG
=
LoggerFactory
.
getLogger
(
CountryDistance
.
class
);
public
static
void
main
(
final
String
arg
[])
throws
Exception
{
if
(
arg
.
length
==
0
)
{
final
CountryOfOriginServiceImpl
countryOfOriginService
=
new
CountryOfOriginServiceImpl
();
countryOfOriginService
.
afterPropertiesSet
();
final
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
));
final
Pattern
pattern
=
Pattern
.
compile
(
"^(\\w{3})[\\s,]+(\\-?\\d*\\.?\\d*)[\\s,]+(\\-?\\d*\\.?\\d*)$"
);
LOG
.
info
(
"Expects input rows in format: ORIGCTY\tDECLONGITUDE\tDECLATITUDE"
);
LOG
.
info
(
"Enter 'q' to quit."
);
System
.
out
.
println
(
"ORIGCTY\tDECLONGITUDE\tDECLATITUDE\tRESULT"
);
String
input
=
null
;
do
{
input
=
br
.
readLine
();
if
((
input
==
null
)
||
"q"
.
equals
(
input
))
break
;
final
Matcher
matcher
=
pattern
.
matcher
(
input
);
if
(
matcher
.
find
())
{
final
String
origCty
=
matcher
.
group
(
1
).
trim
();
final
float
longitude
=
Float
.
parseFloat
(
matcher
.
group
(
2
).
replace
(
","
,
"."
));
final
float
latitude
=
Float
.
parseFloat
(
matcher
.
group
(
3
).
replace
(
","
,
"."
));
System
.
out
.
println
(
origCty
+
"\t"
+
longitude
+
"\t"
+
latitude
+
"\t"
+
countryOfOriginService
.
distanceToBorder
(
longitude
,
latitude
,
origCty
));
}
else
{
LOG
.
info
(
"Invalid format: "
+
input
);
}
}
while
((
input
!=
null
)
&&
!
"q"
.
equals
(
input
));
}
else
{
throw
new
RuntimeException
(
"Nono."
);
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment