How to get the intersecting points from shape in ElasticSearch - java

I have stored a route in ElasticSearch as a Polygon. Now I have a circle (A point and a radius), I'am able to check the circle points intersects the polygon or not (Below is the code I used).
Question: How can I get the points in the route which intersects the circle ?
public Boolean isMatchingDoc(Long elasticDocId, Double latitude, Double longitude, Long radius) {
Coordinate origin = new Coordinate(latitude, longitude);
ShapeBuilder circleShapeBuilder = ShapeBuilder.newCircleBuilder().center(origin).radius(radius,
DistanceUnit.METERS);
GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("route", circleShapeBuilder);
SearchRequestBuilder finalQuery = client.prepareSearch(INDEX).setTypes(TYPE)
.setQuery(QueryBuilders.termQuery("_id", elasticDocId)).setPostFilter(geoShapeQueryBuilder);
SearchResponse searchResponse = finalQuery.execute().actionGet();
SearchHits searchHits = searchResponse.getHits();
if (searchHits.getTotalHits() > 0) {
return true;
}
return false;
}

I guess you are aware that with elasticsearch, you can query for polygons that intersect a given circle? See https://www.elastic.co/guide/en/elasticsearch/guide/current/querying-geo-shapes.html.
There are two reasons why this may not help you:
Your routes are not polygons, but lines.
You want to know the exact points of the intersection, if I read your question correctly.
Elasticsearch probably cannot solve this problem for you conveniently. It might be possible to solve if you would store all of your line-segments separately instead of in one huge polygon per route. Each line-segment then would have to bear an attribute that references the route it belongs to. Does that approach sound feasible to you?
Anyways, I would recommend you to look into the topic of "spatial databases":
Spatial databases are optimized for indexing and searching in a geometric space. Well-know databases such as PostgreSQL and MongoDB feature plugins/extensions for spatial indexing. I'm not sure what to recommend, but the MongoDB geospatial API looks promising for example, as it allows querying for intersection - and it supports lines as well as polygons.

Related

ELKI get clustering data points

How do I get the data points and centroid that are in a kmeans (llyod) cluster when I use elki?
Also could I plug in those points into one of the distance functions and get the distance between any two of the points?
This question is different, because the main focus of my question is retrieving the data points, not custom data points. Also the answer on the other thread is currently incomplete, since it refers to a wiki that is not functioning at the moment. Additionally I would like to know specifically what needs to be done, because the documentation on all of the libraries is a bit like a wild goose chase and it would be greatly appreciated that if you know/understand the library that you would be direct with the answer so that others with the same problem could also have a good solid reference to refer to, instead of trying to figure out the library.
A Cluster (JavaDoc) in ELKI never stores the point data. It only stores point DBIDs (Wiki), which you can get using the getIDs() method. To get the original data, you need the Relation from your database. The method getModel() returns the cluster model, which for kmeans is a KMeansModel.
You can get the point data from the database Relation by their DBID,
or compute the distance based on two DBIDs.
The centroid of KMeans is special - it is not a database object, but always a numerical vector - the arithmetic mean of the cluster. When using KMeans, you should be using SquaredEuclideanDistanceFunction. This is a NumberVectorDistanceFunction, which has the method distance(NumberVector o1, NumberVector o2) (not all distances work on number vectors!).
Relation<? extends NumberVector> rel = ...;
NumberDistanceFunction df = SquaredEuclideanDistanceFunction.STATIC;
... run the algorithm, then iterate over each cluster: ...
Cluster<KMeansModel> cluster = ...;
Vector center = cluster.getModel().getMean();
double varsum = cluster.getModel().getVarianceContribution();
double sum = 0.;
// C++-style for loop, for efficiency:
for(DBIDRef id = cluster.getIDs().iterDBIDs(); id.valid(); id.advance()) {
double distance = df.distance(relation.get(id), center);
sum += distance;
}
System.out.println(varsum+" should be the same as "+sum);

Find if location is land or water in WorldWind

I know in WorldWind Java you can find out the elevation and a particular location with something like this:
public Double getPositionElevationMeters(Double lat, Double lon) {
double elevation = getWorldWindCanvas().getModel().getGlobe()
.getElevation(Angle.fromDegrees(lat), Angle.fromDegrees(lon));
return elevation;
}
Is there a way to figure out if that lat/lon is actually a major body of water or land pro-grammatically? I've taken a "blind" approach of just considering elevation less than 0 to be water, but that's obviously not ideal.
I'd even use another library that would give me this information; I just need it to work offline.
You could possibly use a data source such as this from which you should be able to determine the polygons for all countries on Earth. Antarctica has also been added to that data set. This would get you most of the way there, depending on what you define as a "major" body of water.
From there, you can use GeoTools to import the shape data and calculate which polygons a given lat/lon pair fall in to. If none, then it is probably an ocean.
The following pseudocode illustrates the logical flow:
// pseudocode, not the actual GeoTools API
boolean isWater(Coordinate point)
{
ShapeDataStore countryShapes = loadShapeData("world.shp");
GeoShape shape = countryShapes.findShapeByPoint(point);
if (shape == null)
return true // not a country or Antarctica, must be international waters.
else
return false;
}
edit
See this answer for an answer to a similar question that describes this process in a bit more detail.

How to triangulate/tesselate some shape in Java?

I want to tessellate country shape from GeoTools to display it in 3D on Earth surface. GeoTools use JTS topology suite inside which looks feature rich.
Does it contain utility to tessellate some shape? I see there is triangulation package, but can't figure out, how to use it for shapes with holes.
Also I with it not just connect existing vertices like here
it should fill shape with multiple vertices inside.
UPDATE
I found, that JTS contains class ConformingDelaunayTriangulationBuilder which allows to make wished tessellations somehow, but it works bad. First of all it allows only constraining, which means additional code is needed to remove triangles from concaved regions. And also it tries to conserve Delaunay nature of tessellation, which leads to creating many additional sections.
Finally it causes ConstraintEnforcementException for complex shapes like countries and unusable.
Also I found "triangle" package, which is written in C and implementing Chew's second algorithm and works well
Now I wonder, was it ported to Java or wrapped into it?
I know this post is relatively old, but I recently faced the same situation and needed some Java Library or similar tool to triangulate some complex Polygons (as I wanted to display them on OpenGL, which can only draw triangles as primitive operations).
After quite some search and testing, the library that worked for me was Poly2Tri from Orbgis. You can get that library from Maven here*.
This library has many features, including Polygons with holes, Steiner points to optimize your triangulation, and other stuff. A basic usage example would be the following (based from the example on the linked repo):
//Create the polygon passing a List of PolygonPoints
Polygon polygon = new Polygon(
Arrays.asList(
new PolygonPoint(0, 0, 0),
new PolygonPoint(10, 0, 1),
new PolygonPoint(10, 10, 2),
new PolygonPoint(0, 10, 3)));
//Here you could add holes as needed, passing them as Polygons
polygon.addHole(someHoleYouCreated);
//Next, proceed to calculate the triangulation of the polygon
Poly2Tri.triangulate(polygon);
//Finally, obtain the resulting triangles
List<DelaunayTriangle> triangles = polygon.getTriangles();
Edit: Don't know if you already tried, but JTS Topology Suite also has a DelaunayTriangulationBuilder class (that is without the Conforming part). It is found at org.locationtech.jts.triangulate.DelaunayTriangulationBuilder, and perhaps it works better than the other one you tried but performed badly.
*Note: careful not to use this one instead, as I did at first and found that it was not the correct dependency (wasn't the -core version)
Here's a quick and dirty way using JTS:
First:
Triangulate your geometry with JTS DelaunayTriangulationBuilder
Prepare a set of sites, sites; copy in vertex sites from the initial triangulation
Loop:
Iterate over triangle geometries of the triangulation, adding triangle centroids** to sites
Re-triangulate using sites(now comprised of the original sites and the new centroid sites)
Finally:
Intersect the triangulation with the original geometry to restore its concave hull and any holes
**For this dirty technique, I've found that using triangle centroids lead to better results than the triangle circumcenters even though the latter tends to be used in more formal refinements (Chew, Ruppert and so on..)).
Code
static Geometry refinedTriangulation(Geometry g, int nRefinements, double tolerance) {
DelaunayTriangulationBuilder builder = new DelaunayTriangulationBuilder();
builder.setSites(g); // set vertex sites
builder.setTolerance(tolerance); // set tolerance for initial triangulation only
Geometry triangulation = builder.getTriangles(geometryFactory); // initial triangulation
HashSet<Coordinate> sites = new HashSet<>();
for (int i = 0; i < triangulation.getCoordinates().length; i++) {
sites.add(triangulation.getCoordinates()[i]);
}
for (int refinement = 0; refinement < nRefinements; refinement++) {
for (int i = 0; i < triangulation.getNumGeometries(); i++) {
Polygon triangle = (Polygon) triangulation.getGeometryN(i);
if (triangle.getArea() > 50) { // skip small triangles
sites.add(new Coordinate(triangle.getCentroid().getX(), triangle.getCentroid().getY()));
}
}
builder = new DelaunayTriangulationBuilder();
builder.setSites(sites);
triangulation = builder.getTriangles(geometryFactory); // re-triangulate using new centroid sites
}
triangulation = triangulation.intersection(g); // restore concave hull and any holes
return triangulation;
}
You can use triangle.getExteriorRing().getLength() > N or triangle.getArea() > N to skip over refining already-small triangles.
Example
Raw shape
JTS triangulation
JTS triangulation w/ intersection
1 Refinement
3 Refinements

Calculate percentage similarity of two images using OpenCV

I am able to find matching features using bewlow shown code. I want to calculate percentage similarity between two images. I am new to OpenCV. Any kind of help will be highly appreciated.
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor extractor = DescriptorExtractor
.create(DescriptorExtractor.ORB);
detector.detect(image1, keypoints1);
detector.detect(image2, keypoints2);
extractor.compute(image1, keypoints1, descriptors1);
extractor.compute(image2, keypoints2, descriptors2);
DescriptorMatcher matcher = DescriptorMatcher
.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
Is there any other library available serving the same purpose?
I don't think you can compute a percentage per se by using feature points. But you can compute a "score of similarity".
First of all, you want to filter out the bad matches you have, in some way (I would use a homography transformation to geometrically validate the matches). Then, you can establish your own way of computing this "score of similarity".
For instance, you can simply sum the hamming distances between the matches you have. And you could also use the position of the feature points: Suppose a feature point Ai on image A has a correspondence Bi on image B. The coordinates of Ai are (Xa, Ya) and those of Bi are (Xb, Yb). For your images to be similar, you possibly want (Xa, Ya) to be as close as possible to (Xb, Yb). The score would then be something like:
Score = HammingDist / DistanceBetween(Point(Xa, Ya), Point(Xb, Yb))
And of course, you might want to put more weight on HammingDist or on DistanceBetween; you need to experiment.
I found two libraries pHash and pdiff offering what I am looking for. I'll evaluate their performance and as well as compatibility with my code and pick the best one.

Determining whether geographic point is within X meters of a state border (using shapefile for border data)

So I'm writing a Java app, and I've got an ESRI Shapefile which contains the borders of all the U.S. states. What I need is to be able to determine whether any given lat/lon point is within a specified distance from ANY state border line - i.e., I will not be specifying a particular border line, just need to see whether the point is close to any of them.
The solution does NOT have to be very precise at all; e.g. I don't need to be dealing with measuring perpendicular to the border, or whatever. Just checking to see if going X meters north, south, east or west would result in crossing a border would be more than sufficient. The solution DOES have to be computationally efficient, as I'll be performing a huge number of these calculations.
I'm planning to use the GeoTools library (though if there's a simpler option, I'm all for it) with the Shapefile plugin. What I don't really understand is: Once I've got the shapefile loaded into memory, how do I check to see whether I'm near a border?
Thanks!
-Dan
Assuming JTS for Geometry which is what is included in GeoTools:
public boolean pointIsClose( File file, Point targetPoint,double distance) {
boolean ret = false;
Map connect = new HashMap();
connect.put("url", file.toURL());
DataStore dataStore = DataStoreFinder.getDataStore(connect);
FeatureSource featureSource = dataStore.getFeatureSource(typeName);
FeatureCollection collection = featureSource.getFeatures();
FeatureIterator iterator = collection.features();
try {
while (iterator.hasNext()) {
Feature feature = iterator.next();
Geometry sourceGeometry = feature.getDefaultGeometry();
ret= sourceGeometry.isWithinDistance(targetPoint, distance );
}
} finally {
iterator.close();
}
return ret;
}
The double number will have to come from the CRS which will define the units in which the calculation will be performed.
These are the geotools imports:
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
If you just want to know if point A is within X meters of a state border and X is constant and you don't care which border it is, you can precompute the negative space as a series of boxes. Then all you have to do is a contains check for each of those boxes against the point. If none of them match, you're not in the negative space.
If you can somehow extract the shape for each state from the shapefile, create an envelope that is x meters on a side (with your point in the exact center) and see if those two shapes intersect, you'll be able to answer the question.
If I was using ESRI's ArcGIS Engine, I'd use an ISpatialFilter with the point defined in the geometry (possibly with a buffer) and query that against the States shapefile. Any result(s) returned would indicate that the point was near a state. I'm unfamiliar with GeoTools and, while browsing through their documentation, I didn't come across anything that looked like that type of functionality, but they must have it. You may want to look for examples of how to use GeoTools to perform spatial queries on shapefiles.

Categories