# Boost :

Subject: Re: [boost] [geometry]
From: Paul Blampspied (elpidiovaldez5_at_[hidden])
Date: 2010-10-11 14:32:17

>
>
>
>> I have a question. Does [geometry] support the idea of a frame of
>> reference
>> ? I believe not, but it may be that I have missed some way of achieving
>> this. By reference frame I mean that some points are not directly
>> comparable
>> if they are in different frames of reference. This is distinct from
>> different coordinate systems (I think).
>>
>>
>
> It is indeed not supported as a distinct feature, but in my opinion it is
> comparable to a coordinate system, the coordinate system concept covers (in
> most cases) these reference frames.
>
>
>
>> For example we could have two
>> geographic coordinate systems, one referring to lat./long. on earth and
>> another to Mars. the points on these two reference frames should not be
>> comparable and should give a compile error. Can this be done in
>> [geometry]
>> ?
>>
>>
>
> Nice example and yes, these reference frames (so coordinate systems in our
> terms) should not be comparable and give a compile error.
>
> The thing is that e.g. the distance function checks if the two input
> features (e.g. points) have the same coordinate system and calls the
> corresponding strategy. If they have a different coordinate system, it fails
> (or in some cases there may even be strategies that succeed, by first
> converting one of them to another coordinate system, or converting both to a
> common system).
>
> In this sense it has the properties of the reference system.
> This applies for two spherical or ellipsoidal systems, as you describe, but
> also for two different cartesian systems (e.g. two different map
> projections).
>

So you are saying that Mars and Earth would be different coordinate systems,
and in the absence of a strategy for transforming between them, the compiler
would reject an attempt to pass a point on one coordinate system to a
function requiring an argument from the other. If a strategy was defined
then conversion (implicit or explicit ?) would be possible. That sounds
great. I suspect this may be a common requirement. Is it easy to define a
new coordinate system, based on an existing system (and hence automatically
aquiring its strategies) ? How do you do it ? I could not find an example in
the documentation.

>
>
>> More interestingly we could use two distinct reference frames for
>> convenience, even though there is a known relation between them. It would
>> be nice if point conversions between the two frames could be carried out
>> (possibly implicitly). For example, I would like to do something like
>> this:
>>
>> ShiftAndRotateTransform<EgocentricFrame, WorldFrame>
>> EgoFrame_WorldFrame_Transform(10, 20, 90); //Shift by [10,20] and rotate
>> 90deg.
>>
>> WorldFrame Test() {
>>
>> WorldFrame p1 = EgoFrame(0,0);
>> EgocentricFrame p2 = WorldFrame(p1);
>> return p2; //IMPORTANT - p2 is implicitly transformed to
>> WorldFrame
>> when returned from Test function.
>> }
>>
>>
>
> I like this use case, and it might be implemented somehow. It more or less
> fits into the design. Suppose you will calculate the distance between two
> points of these two frames, a strategy can registered for this combination
> and can call this relation before calculating the distance.
>
>
>
>> I have managed to implement a very simple scheme which allows this to
>> compile and work successfully, but I am not completely satisfied with my
>> homebrew scheme. In particular, I am forced to declare the WorldFrame and
>> EgoFrame classes and provide all the constructors for them. It is
>> necessary
>> to explicitly provide constructors for all the reference frames which can
>> be
>> converted - implying that this is known at the time the class is written.
>> It is more flexible to use overloaded functions, because these can be
>> as required e.g.
>>
>> //The second argument is the output point which is modified.
>> ChangeReferenceFrame(WorldFrame&p1, EgocentricFrame&p2);
>> ChangeReferenceFrame(EgocentricFrame&p1, WorldFrame&p2);
>> ChangeReferenceFrame(EgocentricFrame&p1, SomeNewFrameType&p2);
>>
>> However the syntactic convenience and possibility of implicit conversion
>> is
>> lost. I wonder if some sleight of template magic could allow the
>> extensibility of the second approach with the usability of the first.
>>
>>
>
> Within the Boost.Geometry world, the transform function should do this.
> This function, boost::geometry::transform, transforms a geometry (point,
> polygon, etc) to another one, the other one being in another coordinate
> system, or in the same coordinate system but with another type (e.g. float
> to double). Internally, a strategy defining how to go from one to another
> system should be implemented for those systems.

The idea of implementing a strategy defining how to go from one system to
the other is just what the doctor ordered ! In the example from my
homebrewed system above, I was trying to achieve this idea by the statement:

ShiftAndRotateTransform<EgocentricFrame, WorldFrame>
EgoFrame_WorldFrame_Transform(10, 20, 90); //Shift by [10,20] and rotate
90deg.

This registers a transform, created from a template class, which connects
EgoFrame and WorldFrame point classes. I could not come up with an
automatic way to 'locate' this registration at the points in the code that
needed to transform the points. That is to say the constructor
WorldFrame(EgoFrame &) needed to explicitly name the transform. I need a
function that taps into the registrations,

> Transform *GetTheTransform(EgoFrame &, WorldFrame &)
>
How do you register a strategy to transform between coordinate systems in
[Boost][Geometry] ?

In order to use different reference frames, I think that the combination of
the following two steps will be common, and hence should be simple to code:

1. Define new coordinate systems for points on different frames of
reference, which use an existing coordinate system e.g. cartesian
2. Register/define the strategy for converting between these coordinate
systems.

The library user can then define constructors as required to enable implit
conversion between frames of reference.

e.g.

class WorldFrame : public point<double, 2,
cs::cartesian><http://geometrylibrary.geodan.nl/classboost_1_1geometry_1_1point.html>{

WorldFrame (EgoFrame &p) {

transform(p, *this, GetTheTransform(p, *this));

}

}

If the user does not want implicit conversions he/she can simply use the
'explicit' keyword to declare the constructor.

I find implicit conversions very handy. I have various functions which
locate points lying within a shaped region in a spatial data structure

EgoFrame p = Sensor1.obstacleLocation();
OccupancyGrid.add(p); //p implicitly converted to the reference frame of
OccupancyGrid.

GetRectangleInFrontOfRobot(p1,p2,p3,p4); //p1..p4 set to coordinates of a
region on egocentric ref frame.
OccupancyGrid.forAllPoints(Rectangle<WorldFrame>(p1,p2,p3,p4),
&PrintPoint); //p1..p4 put onto W.F.
OccupancyGrid.forAllPoints(Rectangle<WorldFrame>(p1,p2,p3,p4), &Count);

//Functions declared as follows in template class Quadtree (Hence they
expect WorldFrame points).