
I have been looking at the advance version of [boost][geometry]. I think it is very useful and very well worked out. 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). 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] ? 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 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 added 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. The starting point would be to allow a class representing the transform between the two frames of reference to be declared. This should attempt to define as much of the machinery as possible. It seems to me that these facilities have no impact on the existing design of [geometry], but concern an extension to allow reference frames to be defined and related.

hi Paul,
I have been looking at the advance version of [boost][geometry]. I think it is very useful and very well worked out.
Thanks.
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).
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 added 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. Boost.Geometry is built using tag dispatching; functions are not overloaded. When you (in your example) add a tag for reference frames, you get rid of the function overloads (convenient, because when using templates they will get the same signature). The implementation can be in different classes, called by one function. However, implicit conversions, if you want them, should be added in another way then.
The starting point would be to allow a class representing the transform between the two frames of reference to be declared. This should attempt to define as much of the machinery as possible. It seems to me that these facilities have no impact on the existing design of [geometry], but concern an extension to allow reference frames to be defined and related.
If you have everything outside yes, it might be an extension. However, I think you will not profit from it as much - you still get a success when calculating the distance between two points in two (externally declared) frames. But as said, it is already in the design, at least to some extent, if I understand you correctly, and I'm glad with your interest and we might think about it and discuss it further. Regards, Barend

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 added 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 (quadtree). Example usage shown below: Quadtree<WorldFrame> OccupancyGrid; 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). Quadtree<T>::add(T point); Quadtree<T>::forallPoints(Shape<T> &s, Functor &f); As long as all my functions and datastructures define the reference frame they use, many mistakes can be avoided by compiler. Not an important point but in the documentation I found the use of the word 'geometry' confusing. Geometry appears to refer to a geometric object such as a point, box, line segment etc. At first I expected it to mean something like your use of the term 'coordinate system'. i.e. a 'geometry' would be something like planar, spherical etc. many regards, Paul

hi Paul,
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.
Yes, the compiler would reject it.
If a strategy was defined then conversion (implicit or explicit ?) would be possible. That sounds great. I suspect this may be a common requirement.
Yes, explicit conversion is possible by calling transform.
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.
It is easy to define one, but not easy to let everything work with it... I added two samples, c10_custom_cs_example and c11_custom_cs_transform_example to the sandbox, which: c10: define a Martian coordinate system and calculate distance between two Martian points c11: define two Cartesian systems and transform a point between those two I didn't mention earlier, but "coordinate system" is not alone. They are also organized into families. Thus two Cartesian systems can get both the tag "cartesian". The distance function then automatically works for them, taking Pythagoras. It is also possible to add a new (or user-defined) coordinate system tag, of course. That is done in c10 but not in c11. Furthermore, the distance function between two points in mutually different Cartesian coordinate systems compiles. This should actually not be the case, and the answer is wrong, so I will solve this. Also, the system to register a strategy is slightly different for distance (the new system) and transform (the old system), this will be solved as well, hopefully very soon. It is just naming style and namespaces.
The idea of implementing a strategy defining how to go from one system to the other is just what the doctor ordered !
Good to hear ;-)
How do you register a strategy to transform between coordinate systems in [Boost][Geometry] ?
I processed that in the example. But as noted, it will (slightly) change (so "strategy_transform" will be called "strategy::transform::services::default_strategy")
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.
Exactly.
The library user can then define constructors as required to enable implit conversion between frames of reference.
If he wants, he can do this indeed. Until now I didn't. But yes, it should be possible and might be convenient. This is entirely up to the user, and not part of the library.
I find implicit conversions very handy.
I think they can be convenient in many cases, as long as the library user is aware of it and knows there is a transformations in between. If he calls it too much (e.g. in calculations etc), it can affect performance.
Not an important point but in the documentation I found the use of the word 'geometry' confusing. Geometry appears to refer to a geometric object such as a point, box, line segment etc. At first I expected it to mean something like your use of the term 'coordinate system'. i.e. a 'geometry' would be something like planar, spherical etc.
I see. Yes, geometry is the name of the library (Boost.Geometry), of the namespace, and we have several "geometry types" defined, calling them geometry (as parameter) and Geometry (as template parameter)... It is indeed good to mention something like this in the introduction of the documentation. Thanks. Regards, Barend
participants (2)
-
Barend Gehrels
-
Paul Blampspied