Re: [boost] [GTL] - geometric template library - determining interest

In-Reply-To: <1191527843170@dmwebmail.japan.chezphil.org> spam_from_boost_dev@chezphil.org (Phil Endecott) wrote (abridged):
http://www.gamedev.net/community/forums/topic.asp?topic_id=261920
Yes, a very good page showing several solutions:
1. A vector of member pointers (may have some overhead). 2. Anonymous structs and unions (may be non-standard). 3. x, y and z implemented as references (makes object bigger). 4. Relying on (&x)[1] pointing to y.
It misses this one: template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } }; which in my view is the only way to fly. It has no run-time overhead (provided the trivial functions are inlined). It does not rely on non-standard or non-portable features. It's simple and easy to understand. It has the added benefit that the underlying representation is kept private, and all access done via member functions. The main drawback is the extra brackets. cout << p.x(); rather than: cout << p.x; Which is a pain, but I think the benefits are worth it. -- Dave Harris, Nottingham, UK.

On Sun, 7 Oct 2007, Dave Harris wrote:
It misses this one:
template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } };
which in my view is the only way to fly. It has no run-time overhead (provided the trivial functions are inlined). It does not rely on non-standard or non-portable features. It's simple and easy to understand. It has the added benefit that the underlying representation is kept private, and all access done via member functions.
The main drawback is the extra brackets. cout << p.x();
rather than: cout << p.x;
Which is a pain, but I think the benefits are worth it.
I was beginning to wonder when finally someone would bring this one. I totally agree that this is the best option, and I personnaly don't understand what is the big fuss about adding the extra parenthesis. Is something like p.x() * p.x() + p.y() * p.y() really that much worse than p.x * p.x + p.y * p.y ? Is it really such a pain to write? Is the latter really more readable than the former? When I write code using points, I actually seldom have to use directly those accessors. I am not talking about writing the point class, but using it. How often do we have to use something else than functions/operators (norm, +/-/*, etc.) on points in complex expressions? -- Francois Duranleau

François Duranleau wrote:
On Sun, 7 Oct 2007, Dave Harris wrote:
It misses this one:
template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } };
which in my view is the only way to fly. It has no run-time overhead (provided the trivial functions are inlined). It does not rely on non-standard or non-portable features. It's simple and easy to understand. It has the added benefit that the underlying representation is kept private, and all access done via member functions.
The main drawback is the extra brackets. cout << p.x();
rather than: cout << p.x;
Which is a pain, but I think the benefits are worth it.
I was beginning to wonder when finally someone would bring this one. I totally agree that this is the best option, and I personnaly don't understand what is the big fuss about adding the extra parenthesis.
FWIW I also totally agree with you both. On both accounts. Fernando Cacciola

François Duranleau wrote:
On Sun, 7 Oct 2007, Dave Harris wrote:
It misses this one:
template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } };
which in my view is the only way to fly. It has no run-time overhead (provided the trivial functions are inlined). It does not rely on non-standard or non-portable features. It's simple and easy to understand. It has the added benefit that the underlying representation is kept private, and all access done via member functions.
The main drawback is the extra brackets. cout << p.x();
rather than: cout << p.x;
Which is a pain, but I think the benefits are worth it.
I was beginning to wonder when finally someone would bring this one. I totally agree that this is the best option, and I personnaly don't understand what is the big fuss about adding the extra parenthesis.
FWIW I also totally agree with you both. On both accounts.
Fernando Cacciola
IF I was writing a 'point' class I certainly would have it work that way, but I am interested in notation that should support generic algorithms right? You can provide whatever additional syntax you like, but I want to know what is reasonable to _require_ of a point class. It seems clear that bracket (runtime indexed) syntax has problems for some folks, and that compile-time indices (get<0>) has problems in other cases, and that Boost.Fusion seems to provide a way to deal with both cases in generic code. The named access functions (x(), y(), z()) can be convenient except that they are not even indexed by a compile-time integer, if that matters. Which compilers still don't support the at_c<N> syntax? I have heard others say that was not portable before, but I have used libraries that used this syntax on g++ 3.4.2 and VC8. Basically after looking at Fusion a bit, I am satisfied with the folks who argue in favor of satisfying Fusion concepts for point coordinates. I am ready to worry about IF and how boost would accommodate the other semantics of a 'point' concept. As the GTL author seems to have pointed out in their explanation of "isotropic", a point is a point regardless of its coordinates, and perhaps a point concept should involve the coordinate-free operations that make sense on a point versus a vector etc., and another concept/term should be adopted for the set of coordinates. If the GTL authors have such concepts I am curious to see the interplay of point, vector, and coordinate_sets (or whatever they are called). -- John

François Duranleau wrote:
On Sun, 7 Oct 2007, Dave Harris wrote:
It misses this one:
template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } };
which in my view is the only way to fly. It has no run-time overhead (provided the trivial functions are inlined). It does not rely on non-standard or non-portable features. It's simple and easy to understand. It has the added benefit that the underlying representation is kept private, and all access done via member functions.
The main drawback is the extra brackets. cout << p.x();
rather than: cout << p.x;
Which is a pain, but I think the benefits are worth it.
I was beginning to wonder when finally someone would bring this one. I totally agree that this is the best option, and I personnaly don't understand what is the big fuss about adding the extra parenthesis.
Is something like
p.x() * p.x() + p.y() * p.y()
really that much worse than
p.x * p.x + p.y * p.y
? Is it really such a pain to write? Is the latter really more readable than the former?
When I write code using points, I actually seldom have to use directly those accessors. I am not talking about writing the point class, but using it. How often do we have to use something else than functions/operators (norm, +/-/*, etc.) on points in complex expressions?
The thing is, you can never have a one-size-fits-all point type. Some folks say they need heterogeneous dimension types. If you use arrays, then you can't have those. And how about legacy types, need for higher dimensions, Etc. So, again, use concepts! And use them all the way! Don't generalize on concrete point types like above! You can't. Use concepts. An elegant concept hierarchy for points should satisfy all the needs for all users. And, there can be interoperability between different models of the unified point concept. Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net

When I write code using points, I actually seldom have to use
[snip] directly
those accessors. I am not talking about writing the point class, but using it. How often do we have to use something else than functions/operators (norm, +/-/*, etc.) on points in complex expressions?
The thing is, you can never have a one-size-fits-all point type. Some folks say they need heterogeneous dimension types. If you use arrays, then you can't have those. And how about legacy types, need for higher dimensions, Etc.
So, again, use concepts! And use them all the way! Don't generalize on concrete point types like above! You can't. Use concepts. An elegant concept hierarchy for points should satisfy all the needs for all users. And, there can be interoperability between different models of the unified point concept.
Regards, -- Joel de Guzman
I would add that these concepts should NOT require coordinates for PointConcept or SpatialVectorConcept, there should be a separate CoordinatesConcept and RuntimeIndexedCoordinatesConcept (names may be changed :) ). I suspect most of this dialog would fall under what I just called the CoordinatesConcept and RuntimeIndexedCoordinatesConcept. For instance one can not add, multiply, or take the norm/length of points (you need spatial vectors for that). You can also measure distance between points, but not vectors. You can translate a point, but not a vector, and you can not scale a point but you can scale a vector. Since coordinates are free from interpretation you can do whatever you want to with them, but the result is coordinates, not a point or a vector. I think the concepts for a point would require a typedef for the vector type, and likewise a vector would require a typedef for the corresponding point type. Coordinates should probably satisfy both concepts for a point and for a vector. Again I do not know if these concepts or equivalents are part of GTL. Is it appropriate/possible to try to flesh out details like this on the boost wiki? Would folks be interested in starting up or helping with a googlecode project to flesh out these concepts for a possible boost submission at a later date? -- John

Hi John,
I am ready to worry about IF and how boost would accommodate the other semantics of a 'point' concept. As the GTL author seems to have pointed out in their explanation of "isotropic", a point is a point regardless of its coordinates, and perhaps a point concept should involve the coordinate-free operations that make sense on a point versus a vector etc., and another concept/term should be adopted for the set of coordinates. If the GTL authors have such concepts I am curious to see the interplay of point, vector, and coordinate_sets (or whatever they are called).
Exacty. A concept is just a set of minimal requirements. It is not a class, neither is an adapter (it seems this library somewhat mixes conepts with adapters). So, while we certainly would like one single point class, or at most a few of them, we don't need to use a monolithic super concept. We can use a set of concepts instead, each one capturing an ortoghonal aspect of the design. Off the top of my head: IndexableCartesian2 (provides indexed access: [0], [1]) IndexableHomogeneous2 (provides indexed access: [0], [1], [2]) Cartesian2 (provides named access: x(),y()) Homogeneous2 (provides named access: x(),y(),w()) Vector2 (provides coordinate-free vector-specifc operations) Point2 (provides coordinate-free point-specifc operations) .. and so on for 3 dimensions, for heteregeneous coordinates, etc. Notice that a point is a point regardless of its coordinates, and so is a vector. That is, Vector2/Point2 ARE NOT refinements of the concepts for coordinate sets. Best Fernando Cacciola

Dave Harris wrote:
In-Reply-To: <1191527843170@dmwebmail.japan.chezphil.org> spam_from_boost_dev@chezphil.org (Phil Endecott) wrote (abridged):
http://www.gamedev.net/community/forums/topic.asp?topic_id=261920 Yes, a very good page showing several solutions:
1. A vector of member pointers (may have some overhead). 2. Anonymous structs and unions (may be non-standard). 3. x, y and z implemented as references (makes object bigger). 4. Relying on (&x)[1] pointing to y.
It misses this one:
template <typename T> class Point3 { T v[3]; public: T &operator[]( size_t i ) { return v[i]; } T &x() { return v[0]; } T &y() { return v[1]; } T &z() { return v[2]; } };
Doesn't work for a T without a default constructor and likely inefficient for a T with a non-trivial default constructor. Concepts are the answer, let the user pick what type works best for them. Thanks, Michael Marcin
participants (6)
-
brangdon@cix.compulink.co.uk
-
Fernando Cacciola
-
François Duranleau
-
Joel de Guzman
-
John Femiani
-
Michael Marcin