Boost logo

Boost :

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk