I have the following sql query, anyone can assist me converting it to NSPredicate to run through core data?
Can't figure it out...
SELECT title, address1, ( 6371 * acos( cos( radians(36.414376) )
* cos( radians( latitude ) ) * cos( radians( longitude ) - radians(28.155212) )
+ sin( radians(36.414376) ) * sin( radians( latitude ) ) ) )
AS distance
FROM main
HAVING distance < 0.5
ORDER BY distance
latitude and longitude are doubles in entity main,
many thanks for any help...
Short answer is you can't.
Core Data and NSPredicate do not allow you to perform math.
What you can do, however, is write a NSPredicate that returns every address within a box.
What you need to do is pre-calculate the minimum Latitude and Longitude as well as the maximum Latitude and Longitude.
Then your NSPredicate turns into:
CGFloat minLat = ...;
CGFloat maxLat = ...;
CGFloat minLong = ...;
CGFloat maxLong = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(latitude < %f AND latitude > %f) AND (longitude < %f AND longitude > %f)", minLat, maxLat, minLong, maxLong];
From the results of that query you can then narrow down to within a circle to remove the items in the corners. of the box.
Related
We will get streaming data of many cars on a particular Stream Analytics. Each row will have vehicleId, latitude and longitude of vehicle. I need to raise an alarm whenever distance between ANY two cars is less than suppose x meters.
Right now we can consider radial distance to keep it simple. Hence, we need to calculate distance of cars NOT from a fix point but from other cars ( near by cars can keep changing with time ). Hence, we cannot hard-code vehicle id in the query for sure.
We do have Geo-spatial functions support https://learn.microsoft.com/en-us/stream-analytics-query/geospatial-functions ..
I am not sure if this can even be done by Stream Analytics query directly.
I created a small example of the potential solution, not perfect one perhaps, but it resolves the problem in the ASA job.
Essentially I have re-used javascript function that expects simple latitude and longitude and gives the distance in meters. You can use potentially the geospatial embedded function - I haven't tried to play with that.
So, idea is to cross join input, for all input messages(unfortunately yes, you get duplicated result but it works), and then you apply distance function and filter to the output only those that have a distance less than a threshold value. The following example propagates to the output only if the distance is not zero(it means it compared with itself) and if it is less than 5 meters:
with inputData as (select * from input i1 inner join input i2 ON DATEDIFF(second,i1,i2) BETWEEN 0 AND 5),
distances as (select *, udf.getGeoDistance(i1.lat,i1.long,i2.lat,i2.long) as distance from inputData)
select *
into output
from distances
where distance <> 0 and distance < 5
UDF function:
// Sample UDF which returns sum of two values.
function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
'use strict';
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2 - lat1); // deg2rad below
var dLon = deg2rad(lon2 - lon1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c * 1000; // Distance in m
return d;
}
function deg2rad(deg) {
return deg * (Math.PI / 180);
}
Input:
[
{
"name" : "car1",
"lat" : 59.3293371,
"long" : 13.4877472
},
{
"name" : "car2",
"lat" : 59.293371,
"long" : 13.2619422
},
{
"name" : "car3",
"lat" : 59.3293371,
"long" : 13.4877040
}
]
And result(car1 and car3 are close to each other):
Follow your latest comment,you use tumbling-window and set 5 seconds timeunit to get slice of data.Per my knowledge, you still could not calculate distance of cars each other by sql and Geo-spatial functions directly.Not to mention a warning.
I came up with an idea that you may could use Azure Function as the output of ASA job.Collect the slice of data and send them into Azure Function as json parameter.Inside function,you could write code to calculate the distances between cars each other,even alert warnings to other destinations.
I'm attempting to find the longitude (east-west) angle of a new point given that latitude does not also change.
Given: Starting Latitude, Starting Longitude, distance of travel in miles.
Desired result: Maximum and Minimum Longitude and Latitude degrees that are "distance of travel" from starting point.
Code below:
Attempt 1: Use "close enough" constants:
function(longitude, latitude, travelRadius, next){
var milesPerDegreeOfLongitude = 69.172;
var milesPerDegreeOfLatitude = 69.2;
var location = { longitude : longitude, latitude : latitude };
var longitudeDelta = (travelRadius / milesPerDegreeOfLongitude);
location.maxLongitude = longitude + longitudeDelta;
location.minLongitude = longitude - longitudeDelta;
var latitudeDelta = (travelRadius / milesPerDegreeOfLatitude);
location.maxLatitude = latitude + latitudeDelta;
location.minLatiude = latitude - latitudeDelta;
next(location);
}
^ This yields very close latitude, for a distance of 5 miles. But longitude for the same is about 3.93 miles as measured by google maps, too high of a variance.
Attempt 2: One radian is the angle for a line 3,958.761 miles long (the Earth's radius) therefore the angle for a line X miles long is X/3,958.761 radians.
function(longitude, latitude, travelRadius, next){
var radiusOfEarth = 3959.761;
//... omitting latitude ...
var distanceInRadians = (travelRadius / radiusOfEarth);
var degrees = (180 / Math.PI) * distanceInRadians;
location.maxLongitude = longitude + degrees;
location.minLongitude = longitude - degrees;
next(location)
}
^ And again I end up with about 3.93 miles on longitude distance. What could I do to get this right or at least within .5 miles of error?
Edit: attempt 3 using Mbo's suggestion:
var latitude = 37.7118042;
var longitude = -122.4458397;
var travelradius = 5;
function(latitude, longitude, travelRadius){
var milesPerDegreeOfLatitude = 69.172;
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude)
var location = { longitude : longitude, latitude : latitude };
var latitudeDelta = (travelRadius / milesPerDegreeOfLatitude);
location.maxLatitude = latitude + latitudeDelta;
location.minLatiude = latitude - latitudeDelta;
var longitudeDelta = (travelRadius / milesPerDegreeOfLongitude);
location.maxLongitude = longitude + longitudeDelta;
location.minLongitude = longitude - longitudeDelta;
return location;
}
Outputs:
{
longitude: -122.4458397,
latitude: 37.7118042,
maxLongitude: -122.37355611704736,
minLongitude: -122.51812328295263,
maxLatitude: 37.784058535260115,
minLatiude: 37.63954986473989
}
Where Max longitude is ~3.85 miles from starting position. Still off, expecting something like: -122.3515 which is ~5 miles
milesPerDegreeOfLongitude is not constant value!
It depends on latitude. 69.172 is value for equator (zero latitude).
For other latitudes:
trueMilesPerDegreeOfLongitude = 69.172 * Cos(latitude)
Note that you code uses degrees, but Math.cos works with radians:
var latitude = 37.7118042;
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude)
try something like
var milesPerDegreeOfLongitude = 69.172 * Math.cos(latitude * Math.Pi / 180)
My approx. calculation gives 0.09 for latitudeDelta and 122.44+-0.09 = 122.35, 122.53
I have a cassandra table with user name, latitude and longitude. I would like to get a list of users who are inside the circle with a given latitude, longitude and distance.
For example: my input Lat= 78.3232 and Long = 65.3234 and distance = 30 miles.
I would like to get a list of users who are within 30 miles distance from the point 78.3232 and 65.3234. Is it possible to solve this with single CQL3 query? Or can anyone give me a hint start solving this query?
There was no geospatial support for cassandra so I found a way to Implement it mathematically to generate box coordinates around the point (That was good enough for my work) and use query to get coordinates within boundary.
I'll post the code for others reference.
public class GeoOperations {
public static final int UPPER_LATITUDE = 0;
public static final int LOWER_LATITUDE = 1;
public static final int UPPER_LONGITUDE = 2;
public static final int LOWER_LONGITUDE = 3;
private static final double KM_TO_MILES = 0.621371;
private final double Latitude;
private final double Longitude;
double Boundary[];
public GeoOperations(double init_latitude, double init_longitude) {
Latitude = init_latitude;
Longitude = init_longitude;
Boundary = new double[4];
}
public void GenerateBoxCoordinates(double Distance) {
Distance = Distance * KM_TO_MILES;
double Lat_Factor = (Distance) / 69;
Boundary[UPPER_LATITUDE] = Latitude + Lat_Factor;
Boundary[LOWER_LATITUDE] = Latitude - Lat_Factor;
double Long_Factor = (Distance) / (3960 * 2 * Math.PI / 360 * Math.cos(Latitude));
Boundary[UPPER_LONGITUDE] = Longitude + Long_Factor;
Boundary[LOWER_LONGITUDE] = Longitude - Long_Factor;
for (double x : Boundary) {
System.out.println(x);
}
}
}
And then Used Simple CQL to find coordinates within ranges
if values are like this
UPPER_LATITUDE = 60
LOWER_LATITUDE = 40
UPPER_LONGITUDE = 10
LOWER_LONGITUDE = 5
Query will be something like this (actually I used kundera with Hibernate and used a JPA query. So I havent tested it but it should work)
SELECT * FROM Points_Tablle
WHERE LATITUDE > 40
AND LATITUDE < 60
AND LONGITUDE > 5
AND LONGITUDE < 10;
If you're using DataStax enterprise, you get Geospatial out of the box. Check out Patrick's Demo:
https://github.com/PatrickCallaghan/datastax-geospatial-demo
I'm moving my SQLite database over to Core Data. My database table looks like this:
CREATE TABLE IF NOT EXISTS stops (id integer primary key autoincrement, type text, lat real, lon real, stop_id integer unique, stop_code integer, title text, subtitle text, url text, lastupdate text
My Entity looks like this:
I'm not worries about moving the data over, it's really just a local cache that gets updated from time to time. If its empty, it will just repopulate.
My issue is I have a SQLite custom function:
static void distanceFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
{
// check that we have four arguments (lat1, lon1, lat2, lon2)
assert(argc == 4);
// check that all four arguments are non-null
if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL || sqlite3_value_type(argv[3]) == SQLITE_NULL) {
sqlite3_result_null(context);
return;
}
// get the four argument values
double lat1 = sqlite3_value_double(argv[0]);
double lon1 = sqlite3_value_double(argv[1]);
double lat2 = sqlite3_value_double(argv[2]);
double lon2 = sqlite3_value_double(argv[3]);
// convert lat1 and lat2 into radians now, to avoid doing it twice below
double lat1rad = DEG2RAD(lat1);
double lat2rad = DEG2RAD(lat2);
// apply the spherical law of cosines to our latitudes and longitudes, and set the result appropriately
// 6378.1 is the approximate radius of the earth in kilometres
sqlite3_result_double(context, acos(sin(lat1rad) * sin(lat2rad) + cos(lat1rad) * cos(lat2rad) * cos(DEG2RAD(lon2) - DEG2RAD(lon1))) * 6378.1);
}
The function given a 2 latitudes and 2 longitudes would return the distance. This would let me do something like:
SELECT *, distance(lat, lon, %f, %f) as dist FROM stops WHERE dist < 1 ORDER BY dist
Now, I've got all my data in Core Data, but no idea how to do something like the SQL above with a NSFetchRequest. So how would I go about fetching entities in this manner?
I would like draw sphere in pure OpenGL ES 2.0 without any engines. I write next code:
int GenerateSphere (int Slices, float radius, GLfloat **vertices, GLfloat **colors) {
srand(time(NULL));
int i=0, j = 0;
int Parallels = Slices ;
float tempColor = 0.0f;
int VerticesCount = ( Parallels + 1 ) * ( Slices + 1 );
float angleStep = (2.0f * M_PI) / ((float) Slices);
// Allocate memory for buffers
if ( vertices != NULL ) {
*vertices = malloc ( sizeof(GLfloat) * 3 * VerticesCount );
}
if ( colors != NULL) {
*colors = malloc( sizeof(GLfloat) * 4 * VerticesCount);
}
for ( i = 0; i < Parallels+1; i++ ) {
for ( j = 0; j < Slices+1 ; j++ ) {
int vertex = ( i * (Slices + 1) + j ) * 3;
(*vertices)[vertex + 0] = radius * sinf ( angleStep * (float)i ) *
sinf ( angleStep * (float)j );
(*vertices)[vertex + 1] = radius * cosf ( angleStep * (float)i );
(*vertices)[vertex + 2] = radius * sinf ( angleStep * (float)i ) *
cosf ( angleStep * (float)j );
if ( colors ) {
int colorIndex = ( i * (Slices + 1) + j ) * 4;
tempColor = (float)(rand()%100)/100.0f;
(*colors)[colorIndex + 0] = 0.0f;
(*colors)[colorIndex + 1] = 0.0f;
(*colors)[colorIndex + 2] = 0.0f;
(*colors)[colorIndex + (rand()%4)] = tempColor;
(*colors)[colorIndex + 3] = 1.0f;
}
}
}
return VerticesCount;
}
I'm drawing it with using next code:
glDrawArrays(GL_TRIANGLE_STRIP, 0, userData->numVertices);
Where userData->numVertices - VerticesCount from function GenerateSphere.
But on screen draws series triangles, these aren't sphere approximation!
I think, I need to numerate vertices and use OpenGL ES 2.0 function glDrawElements() (with array, contained number vertices). But series of triangles drawn on the screen is not a sphere approximation.
How can I draw sphere approximation? How specify order vertices (indices in OpenGL ES 2.0 terms)?
Before you start with anything in OpenGL ES, here is some advice:
Avoid bloating CPU/GPU performance
Removing intense cycles of calculations by rendering the shapes offline using another program will surely help. These programs will provide additional details about the shapes/meshes apart from exporting the resultant collection of points [x,y,z] comprising the shapes etc.
I went through all this pain way back, because I kept trying to search for algorithms to render spheres etc and then trying to optimize them. I just wanted to save your time in the future. Just use Blender and then your favorite programming language to parse the obj files that are exported from Blender, I use Perl. Here are the steps to render sphere: (use glDrawElements because the obj file contains the array of indices)
1) Download and install Blender.
2) From the menu, add sphere and then reduce the number of rings and segments.
3) Select the entire shape and triangulate it.
4) Export an obj file and parse it for the meshes.
You should be able to grasp the logic to render sphere from this file: http://pastebin.com/4esQdVPP. It is for Android, but the concepts are same.
Hope this helps.
I struggled with spheres and other geometric shapes. I worked at it a while and created an Objective-C class to create coordinates, normals, and texture coordinates both using indexed and non-indexed mechanisms, the class is here:
http://www.whynotsometime.com/Why_Not_Sometime/Code_Snippets.html
What is interesting to see the resulting triangles representing the geometry is to reduce the resolution (set the resolution property before generating the coordinates). Also, you can use GL_LINE_STRIP instead of GL_TRIANGLES to see a bit more.
I agree with the comment from wimp that since calculating the coordinates generally happens once, not many CPU cycles are used. Also, sometimes one does want to draw only a ball or world or...