Message Boards Message Boards

1
|
4687 Views
|
5 Replies
|
9 Total Likes
View groups...
Share
Share this post:

Check cities contained within a circle

Hello,

I am exploring the function CityData[]. One of the properties available are the coordinates of the city center, given by latitude and longitude. However, I am struggling to perform a simple operation from this data, consisting in checking which cities of a list are inside a circle.

Let me use a simple example:

latlong = 
  CityData[#, "Coordinates"] & /@ 
   CityData /@ {{"Istanbul", "Istanbul", "Turkey"}, {"Moscow", 
      "Moscow", "Russia"}, {"London", "GreaterLondon", 
      "UnitedKingdom"}, {"Berlin", "Berlin", "Germany"}, {"Madrid", 
      "Madrid", "Spain"}}

Here are the coordinates of some cities. Imagine one wants to draw a circle with center in Madrid and radius defined by the distance between Madrid and Berlin. How can I check which ones of the list are inside and outside that circle?

I have been able to calculate the radius using the function GeoDistance[]:

r = GeoDistance[latlong[[4]], latlong[[5]]]

However, I haven't been able to complete this operation.

Thanks in advance for any help!

5 Replies

Hi Jose, thank you again for your response!

I will try to explain myself better. Having a list of cities and their populations, I have gotten a matrix of distances between them:

cities = Entity["City", #] & /@ {{"Istanbul", "Istanbul", 
     "Turkey"}, {"Moscow", "Moscow", "Russia"}, {"London", 
     "GreaterLondon", "UnitedKingdom"}, {"Berlin", "Berlin", 
     "Germany"}, {"Madrid", "Madrid", "Spain"}};

populations = QuantityMagnitude@EntityValue[cities, "Population"];

R = QuantityMagnitude@Table[GeoDistance[cities[[i]], cities[[j]]], {i, 1, 
     Length[cities]}, {j, 1, Length[cities]}];

What I want is to obtain a second matrix, where every element is given by the population contained within a circle, defined by center in city i, and radius R[[i,j]], excluding the populations of cities i and j. This is my own attempt, based on previous replies:

S = Table[Table[Boole[0 < R[[i, k]] < R[[i, j]]], {k, 1, 5}] . 
populations, {i, 1, 5}, {j, 1, 5}]

It may not be the most efficient solution, but it seems to work, at least for small cases. Any additional ideas would be much appreciated!

Thanks.

It's not clear to me what you mean by "total population inside the previous circle".

Given a list of cities (those in the circle or any other list), you can eliminate elements of the list using Delete.

For example take the list of populations of a given list of cities:

populations = EntityValue[cities, "Population"]

Then something like this will add all populations except those at positions i and j:

total[i_, j_] := Total[Delete[populations, {{i}, {j}}]]

(The need of using double lists is a detail of the syntax of Total, not relevant here.) If the list of cities has length n, then the population matrix you want is something like

Table[total[i, j], {i, n}, {j, n}]

Note that on the diagonal we are removing only the population of city i, and we are removing it once, not twice.

Thank you both @Jose M. Martin-Garcia and @Henrik Schachner, your replies have been very helpful!

I am trying now to construct a matrix S, where the element ij contains the total population inside the previous circle, excluding the ones of cities i and j.

I have found that the populations can be obtained by using:

population = CityData[#, "Population"] & /@ cities

But I am not sure how to construct that matrix. Any idea would be much appreciated.

David,

here is one way:

cities = Entity["City", #] & /@ {{"Istanbul", "Istanbul", 
     "Turkey"}, {"Moscow", "Moscow", "Russia"}, {"London", 
     "GreaterLondon", "UnitedKingdom"}, {"Berlin", "Berlin", 
     "Germany"}, {"Madrid", "Madrid", "Spain"}};
radius = GeoDistance[{Entity["City", {"Berlin", "Berlin", "Germany"}], Entity["City", {"Madrid", "Madrid", "Spain"}]}];
(*    Out:   1870.16 km  *)
Select[cities, GeoDistance[{Entity["City", {"Madrid", "Madrid", "Spain"}], #}] < radius &]

In principle you probably can do this without the conversion from city names into Entity, but then the result of your query would be just a list of coordinates instead of names.

Addendum: @Jose M. Martin-Garcia - sorry, I saw your post not before I had posted mine!

POSTED BY: Henrik Schachner

Hello David,

I'd suggest to use entities for the cities:

cities = {
   Entity["City", {"Istanbul", "Istanbul", "Turkey"}], 
   Entity["City", {"Moscow", "Moscow", "Russia"}], 
   Entity["City", {"London", "GreaterLondon", "UnitedKingdom"}], 
   Entity["City", {"Berlin", "Berlin", "Germany"}], 
   Entity["City", {"Madrid", "Madrid", "Spain"}]
}

Define also the two cities of reference:

madrid = Entity["City", {"Madrid", "Madrid", "Spain"}]
berlin = Entity["City", {"Berlin", "Berlin", "Germany"}]

Compute the distance between them (units depend on whether you are, so in the US we get miles):

In[]:= dist = GeoDistance[madrid, berlin]
Out[]= Quantity[1162.07, "Miles"]

Now you can query:

In[]:= Select[cities, GeoDistance[madrid, #] < dist &]
Out[]= {
   Entity["City", {"London", "GreaterLondon", "UnitedKingdom"}], 
   Entity["City", {"Madrid", "Madrid", "Spain"}]
}

This performs an independent call to WA per city, which will be slow for long lists. We can do better in those cases by fetching all positions at once in advance.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract