$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: John Femiani (JOHN.FEMIANI_at_[hidden])
Date: 2008-05-10 19:09:19
Luke wrote:
> 
> >> >yet. There are very valid reasons that the size of a 
> coordinate set 
> >> >should be specified at compile time for cases other than 2 or 3.
> >> 
> >> You would not be using my library with these types, ...
> >
> John wrote:
> >Well then maybe I should back out of this discussion, I am interested
> in
> >a generic geometry library that will provide me with a framework to 
> >write algorithms that work with any (or many) external opensource, 
> >commercial, or legacy geometry libraries.
> >
> >If that is not an aim of GTL then I appologize for the noise :-)
> 
> That is the aim.  I don't want you to back out of the discussion.
> Instead of an n-d point concept, which provides you 
> relatively little, why not extend the library to have 
> explicit quaternians and homogeneous point concepts and 
> algorithms specific to such geometry?  Wouldn't that serve 
> you better?  It isn't my aim to provide those, because they 
> are not used in my domain, but I do want to provide a 
> framework that can be extended to include geometry that I 
> don't personally need.
> 
So in my imagination, CoordinatesConcept and its refinements are what we
are 
talking about. There should be related concepts of PointConcept,
VectorConcept,
LineConcept, OrientationConcept,  RayConcept, IntervalConcept,
SegmentConcept 
and the _real_ killers are probably GeometryConcept and/or 
CoordinateSystemConcept.
Most of the discussion here has been about coordinates access etc. so
here is a
rough (uncompiled) sketch of how I think a CoordinatesConcept might
look.  I 
am under the gun at work so If you guys tear into this I may be slow to 
respond, but If this approach is appreciated I will eventually put it
into an 
svn repo and actually try to compile it :)
----------------------------------------------------------------
//coordinates_concept.hpp....
namespace geometry {
template<class Coord>
struct Coordinates {
    Coord   coord;
    
    typedef typename scalar_type<Coord>::type scalar;
    
    ////supporting checks I need to do... 
    //BOOST_CONCEPT_ASSERT((Addable<scalar, scalar>));
    //BOOST_CONCEPT_ASSERT((Multiplyable<scalar, scalar>));
    //BOOST_CONCEPT_ASSERT((Sunbtractable<scalar, scalar>));
    //BOOST_CONCEPT_ASSERT((Dividable<scalar, scalar>));
    
    BOOST_CONCEPT_USAGE(Coord) 
    {
        bool bval;
        bval = ::geometry::is_runtime_indexable<Coord>();
        bval = ::geometry::is_runtime_indexable<Coord>::value;
       
        size_t dim;
        dim = ::geometry::dimension<Coord>();
        dim = ::geometry::dimension<Coord>::value;
                
        
        static_at_checker< geometry::dimension<Coord> >::apply();
    }
    
    template<class Dim>
    struct static_at_checker {
        Coord coord;
        typedef void 
            result_type;
        typedef mpl::prior<Dim> 
            static_index;
        typedef typename coordinate_accessor<Coord, static_index >
            accessor_type;
        typedef typename accessor_type::result_type 
            raw_type;
    
        BOOST_CONCEPT_ASSERT((Convertable<raw_type, scalar>));
        BOOST_CONCEPT_ASSERT((UnaryFunction<accessor_type>));
        
        //BOOST_CONCEPT_ASSERT((Addable<scalar, raw_type>));
        //BOOST_CONCEPT_ASSERT((Multiplyable<scalar, raw_type>));
        //BOOST_CONCEPT_ASSERT((Sunbtractable<scalar, raw_type>));
        //BOOST_CONCEPT_ASSERT((Dividable<scalar,  raw_type>));
        //....
        
        static void apply() {           
            raw_type rt = at(coord, static_index());
            scalar   st = at(coord, static_index());
            
            raw_type rt = at<static_index>(coord);
            scalar   st = at<static_index>(coord);
            
            static_at_checker<static_index>::apply();
        }              
    };
        
    template<> struct static_at_checker <mpl::int_<0> > { 
        static void apply(){} 
    };
};
}//geometry
    
--------------------------------------------------------------
Actually I can already see some things to do better in there but that is
_close_ to how I would do it.
There would be another CoordinateArray concept probably.
In order to adapt I would do something like this perhaps:
--------------------------------------------------------------
namespace geometry{ 
    //named axises
    namespace axis {
        struct X : mpl::int_<0> {};
        struct Y : mpl::int_<1> {};
        struct Z : mpl::int_<2> {};
        struct W : mpl::int_<3> {};
    };
    
    //Namespace for  nonintrusive customization, not to be called
directly 
    namespace adapted {
    
        template<class Coord> struct is_runtime_indexable
            : Coord::is_runtime_indexable {};
        
        template<class Coord> struct dimension 
            : Coord::dimension {};
            
        template<class Coord> struct scalar_type 
            : Coord::scalar_type {};
          
        template<class Coord, class Index> struct coordinate_accessor 
            : Coord::coordinate_accessor<Index> {};
    }
    //Public interface
    template<class Coord> struct is_runtime_indexable
        : geometry::adapted::is_runtime_indexable<Coord> {};
    
    template<class Coord> struct dimension  
        : geometry::adapted::dimension<Coord> {};
    template<class Coord> struct scalar_type 
        : geometry::adapted::scalar_type<Coord> {};
   
    //Static or dynamic indexing
    template<class Index, class Coord>
            adapted::coordinate_accessor<Coord, Index>::result_type>::
    type at(Coord& coord, Index const& index)
    {
            return adapted::coordinate_accessor<Coord, Index>
                ::apply(coord, index);
    }
    //Static indexing
    template<class Index, class Coord>
    typename enable_if_c< less_<Index, dimension<Coord> >
                        , adapted::coordinate_accessor<Coord, Index>
                            ::result_type
                        >::
    type at(Coord& coord)
    {
            return adapted::coordinate_accessor<Coord,
Index>::apply(coord);
    }    
}
------------------------------------------------------------
I would also add some other functions (at_c, size, etc) but they would
be 
implimented in terms of what is here.
I think it is a lot like Fusion, but with a requirement that the element
types 
have to be convertable to a common scalar type that supports the right 
operations (+-*/=). And then there is the metafunction to determine
whether it 
is runtime indexable or not.
Since ::geometry::adapted is a namespace it is easy to add adapted
syntax for 
other concepts (like Fusion does).
Since the syntax uses free functions in the ::geometry namespace you can
include files with only the functions & metafunctions you need. (There
will be
 more files in the future, that is bound to happen so we should plan on
it).
Requiring adapted syntax in the ::geometry::adapted namespace is
intended to 
help avoid ADL issues etc.
MPL integral constants are used for coordinate access because they are a
convertable to integers, so static indexing should always work whenever
runtime
 indexing would.
To be complete there should be header files that adapt Fusion sequences,
tuples, c-arrays and boost arrays, and CGAL points. 
-- John