Ruby Geocoder how to set a minimum .near distance - ruby-on-rails

Using Alex Reisner's Ruby Geocoder and finding the .near method very useful. One question we have is how can we set it so that we can search for objects between distance x and distance y from the origin (at the moment the .near method only sets the max distance it seems):
documentation here
We're looking for something like:
places = Place.near("Washington", min_distance, max_distance).reorder("score")
or some way of modifying the query so that we get the same effect without using .reorder (which we're using to sort on another "score" field)
The end result we want is the ability to have places ordered by score which are between x and y miles from the origin.

AFAIK it is not natively implemented.
If using ActiveRecord, you can try to use Geocoder's private class methods (see from line 105 to 147) to roll your own "reverse" method, with an algorithm that should be more or less :
calculate bounding box for mininum distance query with Geocoder::Calculations#bounding_box
build SQL to find all records in bounding box AND with #distance_sql(lat,lon,options) >= min_distance
stuff this logic inside a where scope, chain it to near, and voilĂ ! If you feel lazy you can even just copy/paste the whole method and just change the <= predicate.
On a side note, it would be great to file a feature request at geocoder's github, as i think it would be quick to implement for them.

The query generated by Geocoder includes a distance column so all you need to do is add a condition for the minimum distance, for example:
Venue.near("Washington", max_distance).having("distance >= ?", min_distance)
Note that you need to use HAVING, not WHERE.

Related

Comsol: Infinite Element Domain module

I want to simulate a 2D heat transfer process in the subsurface on a region which is infinite on the r-direction. So, as you know, the very basic way to model this is to draw a geometry that is very long in the r direction. I have done this, and the results that I obtain is correct as in this case, the results are matched with the analytical solution. As you know, there is a capability in Comsol called infinite element domain which serves the purpose to the problem mentioned above. In this case, we need to define a limited geometry on which we want to solve the PDE, and also need to draw a small domain acting as the Infinite Element Domain. However, in this case, the results are not correct because they are not matched with the analytical solution. Is there anything that I am missing to correctly use Infinite Element Domain in comsol?
Any help or comment would be appreciated.
Edit:
I edited the post to be more specific.
Please consider the following figure where a fluid with high temperature is being injected into a region with lower temperature:
https://i.stack.imgur.com/BQycC.png
The equation to solve is:
https://i.stack.imgur.com/qrZcK.png
With the following initial and boundary conditions (note that the upper and lower boundary condition is no-flux):
https://i.stack.imgur.com/l7pHo.png
We want to obtain the temperature profile over the length of rw<r<140 m (rw is very small and is equal to 0.005 m here) at different times. One way to model this numerically in Comsol is to draw a rectangle that is 2000 m in the r-direction, and get results only in the span of r [rw,140] m:
https://i.stack.imgur.com/BKCOi.png
The results of this case is fine, because they are well-matched with the analytical solution.
Another way to model this is to replace the above geometry with a bounded one that is [rw, 140] m in the r-direction and then augment it with an Infinite Element domain that is meshed mapped, as follows:
https://i.stack.imgur.com/m9ksm.png
Here, I have set the thickness of Infinite Element to 10 m in the r-direction. However, the results in this case are not matched with the analytical solution (or the above case where Infinite Element domain was not used). Is there anything that I am missing in Comsol? I have also changed some variables with regard to Infinite Element in Comsol such as physical width or distance, but I didn't see any changes in the results.
BTW, here are the results:
https://i.stack.imgur.com/cdaPH.png

Finding a gps locations near another one based on a dynamic radius

I have aGpsLocation model, this model has a latitude, a longitude and a radius property.
I want to find a GpsLocation based on its latitude and longitude and radius.
So lets say i am on location [52, 4], i want to find a GpsLocation instance that has these exact coordinates or is radius meters away.
I am using the geocoder gem but the near function does not do the job. Also tried monkey patching the near function so i can use a database column instead of a variable inside the query but still no luck, there are some mechanics that transform the lat/long to a range when providing a radius parameter.
Any help is appreciated
Calculating the distance between two points on a sphere can be done using the Haversine formula. There is a gem called haversine that can help. Or, if you're using PostgreSQL, there is also the earthdistance module.
However, you may find it easier to relax your definition of "near" somewhat, as dealing with circles can be annoying. Instead, consider using squares or rectangles.
Say you define "near" as within 10 miles. If you treat that as a plus or minus factor around the latitude and longitude of a given point, then you can do a simple query to find all nearby points at once, rather than a series of Haversine calculations. You query might look something like this:
# Only accurate in the U.S.
MILES_PER_LATITUDE = 69.0
MILES_PER_LONGITUDE = 55.0
min_latitude = thisLocation.latitude - (10.0 / MILES_PER_LATITUDE)
max_latitude = thisLocation.latitude + (10.0 / MILES_PER_LATITUDE)
min_longitude = thisLocation.longitude - (10.0 / MILES_PER_LONGITUDE)
max_longitude = thisLocation.longitude + (10.0 / MILES_PER_LONGITUDE)
nearby_points = GpsLocation.where(latitude: min_latitude..max_latitude).where(longitude: min_longitude..max_longitude)

idea: getting locations nearby

currently, i have a table with locations (latitude, longitude). I calculate nearby calculations using sin, cos as described here
This seems rather slow. I am having the idea of pre-calculating the distance to a fixed point f and store it along the locations. When I now want to find locations nearby i just calculate distance to the same fix point and can then find them by doing some less or equal comparing.
Does my idea make sense? Is there a standard way to do that? I am in the thinking phase, so i do not have any code to show yet.
Your idea won't work unless all your locations are collinear, which most probably is not the case.
Are you using SQL to do the calculations? Are you properly using indexes? Maybe you could share a bit of your code with us.

How do I calculate the nearest country on a given heading?

I'd like to calculate the closest country (as viewed on a world map) in a given direction (provided in degrees) from a user's current location.
I realize one way of doing this is to use the formula provided here to step in, for example, 5-mile increments from point to point until I finally reach a country that is not the user's starting country. However, that seems horribly inefficient with regard to use of geocoding resources.
Do any of you know of a better algorithm I could use for this?
Thanks in advance.
One way to reduce the amount of reverse geocoding operations is to treat this problem as a search for the border. If you use a binary search algorithm, and reverse geocode each point, you find where the country changes from your current country to the adjacent country with a minimum number of reverse geocode operations.
In the binary search, your heading is constant, and you have a minimum range (5 miles) and a maximum range (12,000 miles), you are searching for the range at which the border lies. Then you reverse geocode a position just beyond the border to find out what country is there. One problem is that just beyond the border might be ocean.
I would use MKReverseGeocoding. Check this SO question for code examples.

Calculating a lot of Lat/Lngs to a set of 2000 Lat/Lngs in Ruby

I am trying to find the best way to solve the problem below:
Problem
I have (up to) 100,000 Lat/Lng points in Set A
I have (up to) 2000 Lat/Lng points in Set B
I need to find the nearest neighbour of points in set B to points in Set A.
Once they have been paired - I then need to calculate their distance which will be:
2000 Set A points to 2000 Set B Points.
These points are "in memory" they do not come from a database - they are the result of other calculations done the in the system.
Current Solution
Using a KDTree implementation in Ruby I can create a KDTree lookup that will match the points I have. I then use a haversine method in Ruby to calculate the distance of the points when they are paired.
KDtree code: Ruby KDTree Code
haversine Code: Haversine Code
Platform
I am running jruby - with rails as the web framework.
Issue
Its slow! Like 30 to 40 seconds slow... I think the main bottle neck is in the KDtree, but the point look up takes a long time too (i think). At smaller numbers in Set B its quick but the higher the number of points in Set B it gets a lot quicker.
The Question
Would anyone think of doing this differently? Is there something I am missing. I think a Java library might be a lot quicker, but how would I implement this, and which one would I use (Not strong in Java - I use Jruby for multithreading ruby code in the JVM)
Is it possible to persist the information to a database? Because then you can use GeoKit, which leverages a geo-aware database (MySQL, Postgres > 8.1, etc) so that you can do this:
Location.find(:all, :origin =>[37.792,-122.393], :within=>10, :order=>"distance asc")
Also, you can find the distance between two points, etc. The response time will be more on par with a DB query, and much faster than what you're seeing.
Just an idea in my mind. If you round your lat/long's to two decimal places then all the points with-in 1.11 km's will be the same. See this for more details. I'm not 100% sure about it but may be it works for you. Off-course for areas near the pols, this will not work as longitude shrinks there.
To speed up the distance calculation between two lat/long's, you can calculate euclidean distance by using simple distance formula rather than geographical distance. This distance will not be accurate off-course but will speed up your process.

Resources