Estou tentando criar locais aleatórios próximos ao meu local. O que eu quero é criar pares aleatórios de latitude / longitude dentro de um círculo de 200 metros ao redor da minha localização.
Esta é a fórmula que eu criei (com a ajuda de pessoas no StackOverFlow): (Número aleatório entre -1 e 1) * raio + (longitude antiga) = nova longitude dentro do raio da longitude antiga
(Número aleatório entre -1 e 1) * raio + (latitude antiga) = nova latitude dentro do raio da latitude antiga
O problema é que algo estranho está acontecendo com minha implementação, porque todos os locais aleatórios estão muito próximos do meu centro de localização, parece que a fórmula não cobre todo o raio.
Alguma idéia do que poderia estar errado com a minha fórmula?
Editado para mostrar a implementação java atual:
public static Location getLocation(Location location, int radius) {
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / METERS_IN_DEGREES;
double x0 = location.getLongitude() * 1E6;
double y0 = location.getLatitude() * 1E6;
double u = random.nextInt(1001) / 1000;
double v = random.nextInt(1001) / 1000;
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
// Set the adjusted location
Location newLocation = new Location("Loc in radius");
newLocation.setLongitude(new_x + x0);
newLocation.setLatitude(y + y0);
return newLocation;
}
Não tenho certeza do que estou fazendo de errado, porque os novos locais são criados no meio do mar.
Qualquer ideia?
fonte
random.nextInt(1001)/1000
retornará um valor maior que 1 em cerca de 0,1% das vezes. Por que você não está usandorandom.nextDouble
ourandom.nextFloat
? (ii) Multiplicarx0
ey0
por1E6
é bastante misterioso; não parece produzir resultados corretos.Respostas:
Isso é complicado por duas razões: primeiro, limitando os pontos a um círculo, em vez de um quadrado; segundo, contabilizando distorções nos cálculos de distância.
Muitos GISs incluem recursos que lidam com ambas as complicações de forma automática e transparente. No entanto, as tags aqui sugerem que uma descrição independente de GIS de um algoritmo pode ser desejável.
Para gerar pontos de maneira uniforme, aleatória e independente dentro de um círculo de raio r em torno de um local (x0, y0), comece gerando dois valores aleatórios uniformes independentes u e v no intervalo [0, 1). (Isso é o que quase todo gerador de números aleatórios fornece.)
O ponto aleatório desejado está no local (x + x0, y + y0).
Ao usar coordenadas geográficas (lat, lon), x0 (longitude) e y0 (latitude) estarão em graus, mas r provavelmente estará em metros (ou pés ou milhas ou alguma outra medida linear). Primeiro, converta o raio r em graus como se estivesse localizado perto do equador. Aqui, existem cerca de 111.300 metros em um grau.
Em segundo lugar, após a geração de x e y , como no passo (1), ajustar a coordenada x para o encolhimento das distâncias leste-oeste:
O ponto aleatório desejado está no local (x '+ x0, y + y0). Este é um procedimento aproximado. Para raios pequenos (menos de algumas centenas de quilômetros) que não se estendem por nenhum dos pólos da Terra, geralmente será tão preciso que você não poderá detectar nenhum erro, mesmo ao gerar dezenas de milhares de pontos aleatórios ao redor de cada centro (x0, y0) .
fonte
Implementado para Javascript:
fonte
A implementação correta é:
Eu removi a dependência de bibliotecas externas para torná-lo mais acessível.
fonte
Resposta aceita e derivados não funcionaram para mim. Os resultados foram muito imprecisos.
Implementação correta em javascript:
Essência completa aqui
Na resposta aceita, descobri que os pontos são distribuídos em uma elipse com largura 1,5 vezes a altura (no Panamá) e 8 vezes a altura (no norte da Suécia). Se eu removi o ajuste x coord da resposta do @ whuber, a elipse é distorcida para o outro lado, 8 vezes maior que a sua largura.
O código na minha resposta foi baseado em algoritmos daqui
Abaixo, você pode ver dois jsfiddles que mostram o problema com a elipse de alongamento
Algoritmo correto
Algoritmo distorcido
fonte
whuberPointAtDistance()
:x1 = (w * Math.cos(t)) / Math.cos(y0 * (Math.PI / 180))
.Em Python
Saída
A distância entre os pontos é 0.288044147914 A distância entre os pontos é 0.409557451806 A distância entre os pontos é 0.368260305716 A distância entre os pontos é 0.340720560546 A distância entre os pontos é 0.453773334731 A distância entre os pontos é 0.460608754561 A distância entre os pontos é 0.497188825576 A distância entre os pontos é 0.497188825576 A distância entre pontos é 0.503691568896 A distância entre pontos é 0.175153349209 A distância entre pontos é 0.195149463735 A distância entre pontos é 0.424094009858 A distância entre pontos é 0.286807741494 A distância entre pontos é 0.558049206307 A distância entre pontos é 0.558049206307 A distância entre pontos é 0.498612171417 A distância entre pontos é 0.0473447471821532
fonte
Você pode verificar os resultados de seus cálculos aqui . Role para baixo até a seção chamada "Ponto de destino, dada a distância e o rumo do ponto inicial". Existe até uma fórmula JavaScript simples na parte inferior para implementar isso. Você ainda precisará gerar um rolamento aleatório de $ \ theta $ em radianos (medido no sentido horário a partir do norte), embora isso deva ser bastante direto. Essas fórmulas assumem uma terra esférica (embora seja elipsoidal), que é boa o suficiente, pois produz erros de até 0,3%.
fonte
Implementação para Swift
Obtendo o lat e o lng do geoencoder e passando para esta função
No meu exemplo acima, obtenho a latitude e longitude da codificação geográfica do nome do país, pois cada vez que o nome do país fornece a mesma latitude e longitude, também no meio do país, então eu precisava de aleatoriedade.
fonte
private void drawPolyline (duplo lat, duplo lng) {
fonte