Minimum distance to plot points on UIMapview - iphone

my query is whats the minimum distance required to plot point on a UIMAPVIEW, so that they could be shown as distinct points.
For e.g., suppose if there are users in same apartment, their would be hardly any distance between their latitude-longitude. So how do i differentiate them !

There are usually two ways - one is clustering, which means you use a marker with a number that indicates how many underlying markers there are. When tapping on that, the user is then shown the separate markers (or a recursive zoom-in that splits the markers up more and more). Superpin (www.getsuperpin.com) is one example, but there are others out there.
Another approach is to actually offset the marker from its real location. For this, you need some kind of distribution algorithm that offsets it just enough - that is, set the markers as close together as possible while still giving them enough surface area to be seen/touched. For this, we use Fibonacci's Sunflower patten. What you'd have to do is identify all the Annotations that have the same coordinate, group them, and then draw each group in a sequence while offsetting one from the other - for ex. have some code that iterates along a spiral shape and drops down markers along that spiral.
Can put up sample code etc to help if you're wanting to go with the second approach, let me know.
EDIT: I found some code we wrote for this, but it's not objective C. Can you read it?
class SunFlower
{
static $SEED_RADIUS = 2;
static $SCALE_FACTOR = 4;
static $PI2 = 6.28318531; // PI * 2
static $PHI = 1.61803399; // (sqrt(5)+1) / 2
public static function calcPos($xc, $yc, $factor, $i)
{
$theta = $i * SunFlower::$PI2 / SunFlower::$PHI;
$r = sqrt($i) * $factor;
$x = $xc + $r * cos($theta);
$y = $yc - $r * sin($theta);
if ($i == 1) {
$y += ($factor * 0.5);
}
return array($x, $y);
}
}

Related

How to measure distance in crs.simple?

I have a non-geographic map aka flat image using CRS.Simple extended by a custom transformation. Everything works fine so far, but now I want to add a distance measurement button. I'm confident I could implement a distance measurement between two markers myself, but the dynamic line drawing and measuring is still a bit above my skills, so I hoped I could use a plugin. None of the ones I found, did offer this though. After looking at the plugins page of leaflet, I tried this fork https://github.com/aprilandjan/leaflet.measure of leaflet.measure originally by https://github.com/jtreml/leaflet.measure as it seemed to offer the ability to add custom units - in my case pixels.
I added this:
L.control.measure({
// distance formatter, output mile instead of km
formatDistance: function (val) {
return Math.round(1000 * val / scaleFactor) / 1000 + 'mapUnits';
}
}).addTo(map)
Unfortunately, the result is a number far too big compared to the pixelsize of the map (4096x4096). distance() returns the expected 1414.213562373095 between a point 1000,1000 and one at 2000,2000. Calculating distanctTo returns 8009572.105082839 instead though. I use this at the beginning of my file
var yx = L.latLng;
var xy = function(x, y) {
if (L.Util.isArray(x)) { // When doing xy([x, y]);
return yx(x[1], x[0]);
}
return yx(y, x); // When doing xy(x, y);
};
If I log val to the console, I get things like this:
20411385.176805027
7118674.47741132
20409736.502863288
7117025.8034695815
20409186.004645467
20409736.502863288
That's likely some problem of the function trying to calculate latlng without a proper reference system.
Anyone got an idea how to solve this? I feel like it can't be overly difficult, but I don't know exactly where to start.
I found a way to do it, even though it feels a bit 'hacky':
I replaced the line
var distance = e.latlng.distanceTo(this._lastPoint)
in the _mouseMove and the _mouseClick events of leaflet.measure with
var currentPoint = e.latlng;
var lastPoint = this._lastPoint;
var distance = map.distance(currentPoint, lastPoint);
as the distance() method of the map returns meters, or in the case of a flat image, pixel values. And those we can translate in whatever unit we want in our flat image.
If anyone has a more elegant way, I'm all ears!

Label Routes based on GPS coordinates in R/MATLAB

I have three fixed points say A, B and C and several routes to commute between them, they can be in any order. Trip starts and ends at A. Image of routes, fixed points and reference points.
I have 1000s of GPS files in which I need to label the routes that were taken. The GPS files record Latitude, Longitude (in degrees), speed, distance traveled each second and cumulative distance.
I think of the following algorithm: Identify a reference point on each route at a fixed distance (say d) from each of point A, B and C. Now scan the GPS file for the first occurrence of either of Point A, B or C. Since its a GPS measurement, there may not be an exact point corresponding to A, B or C. So, we can find the first occurrence of a point within say 0.1 mile of either A, B or C.
Now start calculating the cumulative from Point A as we move towards B or C. when cumulative distance reaches close to d (again it may not be exactly d), we record coordinates of that point and find the reference point which is closest to it. The closest reference point will give me the route. I need to assign this route from start point to the second occurrence of either of A, B or C. For example, after traveling ‘d’ miles from either of A, B or C, we find that coordinate is closest to Point 3 in the Figure, we say that the route is BA. If the closest point is 2, then route is AB.
Now we go to second occurrence of A, B or C and then find a point after distance d and find a closest reference point to that point. Assign routes and so on.
Please help me with the code. Either R or MATLAB.
So, I wrote a code with a lot of for loops. It works well for me, no errors. Takes about 9 seconds to process a single file of 15000 rows and identify all 8 routes I need. So far so good. Just looking to find a more optimized program or a faster program. I am a beginner at programming.
gpsdata <- read.csv(file = filename, header = TRUE)
####lat and long of route start/end points
# Route Start Point: Routes A and C on Cates Avenue
cateslat = 35.781999
cateslon = -78.668252
#Route Mid: Intersection of AC13, Morning Dove Road
morlat = 35.882035
morlon = -78.645653
#Route End: RTP
rtplat = 35.895431
rtplon = -78.868958
}
#REFERENCE POINTS FOR ROUTE IDENTIFICATION ON EACH ROUTE
{
routea_lat = 35.795400
routea_lon = -78.641243
routec_lat = 35.821031
routec_lon = -78.687069
route1_lat = 35.913527
route1_lon = -78.714348
route3_lat = 35.922331
route3_lon = -78.842865
}
##### ROUTE START POINT TOLERANCE in miles
route_tol = 0.02
##### Reference POINT TOLERANCE for Identifying Routes (in miles)
ref_tol = 0.5
##Calculation Starts Here
n = length(gpsdata$Timestamp) ##File length
#Find point q where we first reach starting route (within 0.01 miles)
for (i in 1:n){
if((distm(c(gpsdata$Longitude[i], gpsdata$Latitude[i]),c(cateslon,
cateslat),fun = distHaversine)*0.000621371)<route_tol){
q=i
break
}
else
{
q=1
}
}
### First Route: Either A-Out or C-Out
for (i in q:n){
if((distm(c(gpsdata$Longitude[i], gpsdata$Latitude[i]),c(morlon, morlat),fun
= distHaversine)*0.000621371)<route_tol){
r=i
break
}
else
{
r=1
}
}
gpsdata1=gpsdata[(q+1):r,]
for (i in 1:length(gpsdata1$Timestamp)){
if((distm(c(gpsdata1$Longitude[i], gpsdata1$Latitude[i]),c(routea_lon,
routea_lat),fun = distHaversine)*0.000621371)<ref_tol){
gpsdata1$Route='A-Out'
break
} else if((distm(c(gpsdata1$Longitude[i],
gpsdata1$Latitude[i]),c(routec_lon, routec_lat),fun =
distHaversine)*0.000621371)<ref_tol){
gpsdata1$Route='C-Out'
break
} else{
gpsdata1$Route='Error-Check Data'
}
}
#Second Route: possibilities- 1-Out, 3-Out, A-In, C-In
#From Here we can either go back to Cates Avenue or go to RTP
for (i in r:n){
if((distm(c(gpsdata$Longitude[i], gpsdata$Latitude[i]),c(rtplon, rtplat),fun
= distHaversine)*0.000621371<route_tol) || +
(distm(c(gpsdata$Longitude[i], gpsdata$Latitude[i]),c(cateslon,
cateslat),fun = distHaversine)*0.000621371<route_tol)){
s=i
break
}
else
{
s=1
}
}
gpsdata2=gpsdata[(r+1):s,]
for (i in 1:length(gpsdata2$Timestamp)){
if((distm(c(gpsdata2$Longitude[i], gpsdata2$Latitude[i]),c(route1_lon,
route1_lat),fun = distHaversine)*0.000621371)<ref_tol){
gpsdata2$Route='1-Out'
break
} else if((distm(c(gpsdata2$Longitude[i],
gpsdata2$Latitude[i]),c(route3_lon, route3_lat),fun =
distHaversine)*0.000621371)<ref_tol){
gpsdata2$Route='3-Out'
break
} else if((distm(c(gpsdata2$Longitude[i],
gpsdata2$Latitude[i]),c(routea_lon, routea_lat),fun =
distHaversine)*0.000621371)<ref_tol){
gpsdata2$Route='A-In'
break
} else if((distm(c(gpsdata2$Longitude[i],
gpsdata2$Latitude[i]),c(routec_lon, routec_lat),fun =
distHaversine)*0.000621371)<ref_tol){
gpsdata2$Route='C-In'
break
} else{
gpsdata2$Route='Error-Check Data'
}
}

How to read elevation from USGS NED DEM GridFloat file in Perl

I have downloaded a large set of GridFloat (.flt, .hdr) DEM files from USGS NED (1") in order to implement my own elevation service on my website. I would like to be able to look up an elevation from this fileset, given latitude and longitude as inputs. I use Perl for my website development. The files have a conventional naming scheme, and I am able to get the appropriate tile filename using the lat/lng. Howevever, accessing the internals of the file is where I'm having an issue.
I know the file is in a fairly straightforward format (.flt, apparently called "Gridfloat"), but I could use some help figuring out the magic numbers for calculating where in the file I need to seek to for a given lat/lng, and how to handle byte order and so on so that I end up with an elevation. From what I understand, apparently row ordering can be an issue, as well as byte ordering. I am looking for a recipe that does not involve use of any third party libraries such as GDAL, which I think are overly complicated and slow for what I want to do. I think it should be possible to just open the file, seek to a position based on some calculation, read some bytes and then unpack them into the correct byte order. Here is an example .hdr file that accompanies floatn48w097_1.flt, I think it has the necessary info. There are a bunch of other files that come with the .zip, including .prj, but I believe those are for a commercial program like ArcInfo. I think everything I need should be in the following .hdr file.
ncols 3612
nrows 3612
xllcorner -97.00166666667
yllcorner 46.99833333333
cellsize 0.000277777777778
NODATA_value -9999
byteorder LSBFIRST
What I'm really hoping for is a formula for calculating the row and column from the lat/lng, then another formula for translating the row/column into a position for seek, how many bytes to read, and how to convert those raw bytes into an integer (or whatever it is these files contain). I feel that this could be a very fast operation, without all the overhead involved with the larger libraries which seem to be focused on doing a lot of stuff that I don't need.
I don't need Perl code, just pseudocode showing the calculations for row/col offsets etc would be more than enough. I believe the files are binary format, a straightforward grid of 4-byte numbers. The file example that goes with the .hdr file above has a size of 52186176, and when you multiply the ncols by nrows (from the .hdr), you get 13046544. which divides nicely into the file size by 4. So I assume it's just a matter of getting the right formula for row/col based on lat/lng, and then getting the bytes swizzled into the right order. I've just not done this much.
I found some reference to the Gridfloat format here: coolutils.com/formats/flt so apparently the file consists of a grid of 64-bit floating point values.
Thanks!
Ok, I think I have an answer. The following is Perl routine, which seems to give back reasonable looking elevation values when tested with the USGS NED1 .flt files. The script takes latitude and longitude as command line arguments, looks up the file and indexes into the grid.
#!/usr/bin/perl
use strict;
use POSIX;
use Math::Round;
sub get_elevation
{
my ($lat, $lng) = #_;
my $lat_degree = ceil ($lat);
my $lng_degree = floor ($lng);
my $lat_letter = ($lat >= 0) ? 'n' : 's';
my $lng_letter = ($lng >= 0) ? 'e' : 'w';
my $lng_tilenum = abs($lng_degree);
my $lat_tilenum = abs($lat_degree);
my $tilename = $lat_letter . sprintf('%02d', $lat_tilenum) . $lng_letter . sprintf('%03d',$lng_tilenum);
my $path = "/data/elevation/ned1/$tilename/float${tilename}_1.flt";
print "path = $path\n";
die "No such file" if (!-e($path));
my ($lat_fraction, $lat_integral) = modf (abs($lat));
my $row = floor ((1 - $lat_fraction) * 3600);
my ($lng_fraction, $lng_integral) = modf (abs($lng));
my $col = floor ((1 - $lng_fraction) * 3600);
open(FILE, "<$path");
my $pos = (3612 * 4 * 6) + (3612 * 4 * $row) + (4 * 6) + ($col * 4);
seek (FILE, $pos, SEEK_SET);
my $buffer;
read (FILE, $buffer, 4);
close (FILE);
my ($elevation) = unpack('f', $buffer);
if ($elevation == -9999)
{
return 'undefined';
}
return $elevation;
}
my $lat = $ARGV[0];
my $lng = $ARGV[1];
my $elevation = get_elevation ($lat, $lng);
print "Elevation for ($lat, $lng) = $elevation meters (", $elevation * 3.28084, " feet)\n";
Hope this might be useful to anyone else trying to do the same kind of thing... I've tested this method now and it seems to produce good looking elevation profiles which are smoother than those from the 3" SRTM data.
Neil put me on the right track but I think there's a few problems with his original answer. I've added some fixes and improvements including on-the-fly download of the needed tile from the 1/3 arc second (10 meter) dataset, proper parsing of the header file, and what I believe is corrected indexing.
This is still mostly illustrative and should be improved before production use, particularly, hanging on to the header information and the file handle for repeated queries.
https://gist.github.com/biomiker/32fe34e1fa1bb49ae1135ab6652f596d

Postgresql earth_box algorithm

I found this tutorial how to find something in specified the radius. My question is what algorithm was used to implement it?
If you mean the earth_box, the idea is to come up with a data type that can be useful with a GIST index (inverted search tree):
http://www.postgresql.org/docs/current/static/gist-intro.html
See in particular the links at the bottom of the maintainers' page:
http://www.sai.msu.su/~megera/postgres/gist/
One leads to:
The GiST is a balanced tree structure like a B-tree, containing pairs. But keys in the GiST are not integers like the keys in a B-tree. Instead, a GiST key is a member of a user-defined class, and represents some property that is true of all data items reachable from the pointer associated with the key. For example, keys in a B+-tree-like GiST are ranges of numbers ("all data items below this pointer are between 4 and 6"); keys in an R-tree-like GiST are bounding boxes, ("all data items below this pointer are in Calfornia"); keys in an RD-tree-like GiST are sets ("all data items below this pointer are subsets of {1,6,7,9,11,12,13,72}"); etc. To make a GiST work, you just have to figure out what to represent in the keys, and then write 4 methods for the key class that help the tree do insertion, deletion, and search.
http://gist.cs.berkeley.edu/gist1.html
If you mean the earth distance itself, the meaty part of source is:
/* compute difference in longitudes - want < 180 degrees */
longdiff = fabs(long1 - long2);
if (longdiff > M_PI)
longdiff = TWO_PI - longdiff;
sino = sqrt(sin(fabs(lat1 - lat2) / 2.) * sin(fabs(lat1 - lat2) / 2.) +
                cos(lat1) * cos(lat2) * sin(longdiff / 2.) * sin(longdiff / 2.));
if (sino > 1.)
        sino = 1.;
return 2. * EARTH_RADIUS * asin(sino);
https://github.com/postgres/postgres/blob/master/contrib/earthdistance/earthdistance.c#L50
My math is too rusty to be affirmative on what the above does exactly, but my guess would be that it's computing the distance between two points on the surface of a sphere (without considering the height of the two points). In other words, nautical miles.

Beat Detection on iPhone with wav files and openal

Using this website i have tried to make a beat detection engine. http://www.gamedev.net/reference/articles/article1952.asp
{
ALfloat energy = 0;
ALfloat aEnergy = 0;
ALint beats = 0;
bool init = false;
ALfloat Ei[42];
ALfloat V = 0;
ALfloat C = 0;
ALshort *hold;
hold = new ALshort[[myDat length]/2];
[myDat getBytes:hold length:[myDat length]];
ALuint uiNumSamples;
uiNumSamples = [myDat length]/4;
if(alDatal == NULL)
alDatal = (ALshort *) malloc(uiNumSamples*2);
if(alDatar == NULL)
alDatar = (ALshort *) malloc(uiNumSamples*2);
for (int i = 0; i < uiNumSamples; i++)
{
alDatal[i] = hold[i*2];
alDatar[i] = hold[i*2+1];
}
energy = 0;
for(int start = 0; start<(22050*10); start+=512){
for(int i = start; i<(start+512); i++){
energy+= ((alDatal[i]*alDatal[i]) + (alDatal[i]*alDatar[i]));
}
aEnergy = 0;
for(int i = 41; i>=0; i--){
if(i ==0){
Ei[0] = energy;
}
else {
Ei[i] = Ei[i-1];
}
if(start >= 21504){
aEnergy+=Ei[i];
}
}
aEnergy = aEnergy/43.f;
if (start >= 21504) {
for(int i = 0; i<42; i++){
V += (Ei[i]-aEnergy);
}
V = V/43.f;
C = (-0.0025714*V)+1.5142857;
init = true;
if(energy >(C*aEnergy)) beats++;
}
}
}
alDatal and alDatar are (short*) type;
myDat is NSdata that holds the actual audio data of a wav file formatted to
22050 khz and 16 bit stereo.
This doesn't seem to work correctly. If anyone could help me out that would be amazing. I've been stuck on this for 3 days.
The desired result is after the 10 seconds worth of data has been processed i should be able to multiply that by 6 and have an estimated beats per minute.
My current results are 389 beats every 10 seconds, 2334 BPM the song i know is right around 120 BPM.
That code really has been smacked about with the ugly stick. If you're going to ask other people to find your bugs for you, it's a good idea to make things presentable first. Strangely enough, this will often help you to find them for yourself too.
So, before I point out some of the more fundamental errors, I have to make a few schoolmarmly suggestions:
Don't sprinkle your code with magic numbers. Is it really that hard to type a few lines like const ALuint SAMPLE_RATE = 22050? Trust me, it makes life a lot easier.
Use variable names that you aren't going to mix up easily. One of your bugs is a substitution of alDatal for alDatar. That probably wouldn't have happened if they were called left and right. Similarly, what is the point of having a meaningful variable name like energy if you're just going to stick it alongside the meaningless but more or less identical aEnergy? Why not something informative like average?
Declare variables close to where you're going to use them and in the appropriate scope. Another of your bugs is that you don't reset your calculated energy sum when you move your averaging window, so the energy will just add up and up. But you don't need the energy outside that loop, and if you declared it inside the problem couldn't happen.
There are some other things I personally find a little irksome, like the random bracing and indentation, and mixing of C and C++ allocations, and odd inconsistent scraps of Hungarian prefixing, but at least some of those may be more a matter of taste so I won't go on.
Anyway, here are some reasons why your code doesn't work:
First up, look at the right hand side of this line:
energy+= ((alDatal[i]*alDatal[i]) + (alDatal[i]*alDatar[i]));
You want the square of each channel value, so it should really say:
energy+= ((alDatal[i]*alDatal[i]) + (alDatar[i]*alDatar[i]));
Spot the difference? Not easy with those names, is it?
Second, you should be computing the total energy over each window of samples, but you're only setting energy = 0 outside the outer loop. So the sum accumulates, and consequently the current window energy will always be the biggest you've ever encountered.
Third, your variance calculation is wrong. You have:
V += (Ei[i]-aEnergy);
But it should be the sum of the squares of the differences from the mean:
V += (Ei[i] - aEnergy) * (Ei[i] - aEnergy);
There may well be other errors as well. For instance, you don't allocate the data buffers if they're not NULL, but assume that they're the right length -- which you've only just calculated. You may justify that in terms of some consistent usage you've stuck to throughout your code, but from the perspective of what we can see here it looks like a pretty bad idea.