Hi Simon. See responses inline.
On 29 Apr, 2012, at 09:20, SimonS wrote:
> Daniel
>
> Just to say I'm new to this but have a useful application in mind and
> all help getting up the learning curve is greatly appreciated.
>
> Thanks for the series of articles it helps me get my head around what
> RGeo library offers, and how I might be able to leverage it.
>
> I have some questions on areas the articles and trawling though the
> docs did not uncover:
>
> 1) If one want to be able to return distances in differing units do I
> need to map the ordinates though different projections and do the
> distance on that projection ?
If you need to calculate true distances across the earth's surface, there are two ways you can go about doing it.
(a) If it's just point-to-point distance, and you're okay with assuming the earth is spherical, the formula is pretty easy. You can convert your coordinates to latitude and longitude, and either use the spherical factory to measure distance (it returns results in meters, which you can then convert to whatever units you want), or just implement the formula yourself (which is pretty easy-- you can look it up online).
# Where p1 and p2 are points created using RGeo::Geographic.spherical_factory
p1.distance(p2) # => distance in meters
(b) If you need to measure distance between more complex objects, and you're okay with some amount of approximation, you can use a simple projection such as Mercator. The simple_mercator_factory is a good one to use for this purpose. It returns magnitudes in meters, scaled according to the Mercator scaling (which is the secant of the latitude) so you'll need to scale them down to get actual distances. The caveat here is that it doesn't work well close to the poles, and it doesn't work well unless your distance is generally small relative to the size of the earth.
# Where g1 and g2 are geometric objects created using RGeo::Geographic.simple_mercator_factory
# and latitude is the approximate latitude of g1 and g2...
g1.distance(g2) * Math.cos(latitude) # => approx distance in meters
> 2) How do I determine headings between points ?
Again, two ways to do this.
(a) There is an exact formula, if you're given latitudes and longitudes and can assume a spherical earth. It's not built into RGeo but here's an implementation I did a while ago that you can borrow...
RADIANS_PER_DEGREE = ::Math::PI/180.0
DEGREES_PER_RADIAN = 180.0/::Math::PI
# Given two latitude/longitude pairs in degrees, find the heading between them.
# Heading is returned as an angle in degrees clockwise from north.
def heading(from_lat_, from_lon_, to_lat_, to_lon_)
from_lat_rad_ = RADIANS_PER_DEGREE * from_lat_
to_lat_rad_ = RADIANS_PER_DEGREE * to_lat_
delta_lon_rad_ = RADIANS_PER_DEGREE * (to_lon_ - from_lon_)
y_ = ::Math.sin(delta_lon_rad_) * ::Math.cos(to_lat_rad_)
x_ = ::Math.cos(from_lat_rad_) * ::Math.sin(to_lat_rad_) -
::Math.sin(from_lat_rad_) * ::Math.cos(to_lat_rad_) * ::Math.cos(delta_lon_rad_)
DEGREES_PER_RADIAN * ::Math.atan2(y_, x_)
end
(b) If the points are relatively close together compared to the size of the earth, and not too close to the poles, and you're okay with some amount of approximation... then you can also just use a conformal projection such as Mercator, and measure the slope of the line between the two points.
> 3) if I have a boundary of a complex object (linear ring) can I rotate
> it around a point and then see if it intersects with other similar
> objects.
I'm not sure what you mean by rotating it around a point. If you have a boundary as a linear ring, it's trivial to create a polygon from that, and then compute intersections between that polygon and other objects.
linear_ring = my_get_linear_ring()
polygon = linear_ring.factory.polygon(linear_ring)
polygon.intersects?(another_geomtry) # => true or false
> 4) if I have a boundary of a complex (linear ring) can I move the
> origin of that boundary based of a known point within that boundary ?
I'm not completely sure I understand this one either, but if you're looking for a point that is guaranteed to be within a linear ring boundary, you can create a polygon from it (as above) and then call point_on_surface() on the polygon to get a point that is guaranteed to be contained in that polygon. Then if you want to shift the origin, you can iterate over the vertices and shift them by the coordinates of that point.
> 5) Do all the manipulations (like overlaps etc.) need to happen in the
> database or can they also work in memory ?
The datatypes provided by RGeo provide many of the manipulations and predicates as Ruby methods, so you can do these things in memory. In fact, RGeo uses the same underlying C library, libgeos, that is used by some spatial databases such as PostGIS to perform these operations. For the most part, in Ruby they work only in flat coordinate systems (i.e. projections) and not in latitude/longitude. For documentation of the operations you can perform, look at the submodules of RGeo::Feature, such as, for example, RGeo::Feature::Geometry.
>
> Thanks
> Simon