[/============================================================================
  Boost.Geometry (aka GGL, Generic Geometry Library)

  Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
  Copyright (c) 2009-2012 Bruno Lalande, Paris, France.

  Use, modification and distribution is subject to the Boost Software License,
  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  http://www.boost.org/LICENSE_1_0.txt)
=============================================================================/]

[section:concept_point Point Concept]

[heading Description]
[concept Point..point]

A point is ['an entity that has a location in space or on a plane, but has no extent] ([@http://en.wikipedia.org/wiki/Point_(geometry) wiki]).
The point is the most basic geometry of Boost.Geometry, most other geometries consist of points. 
['(Exceptions are box and segment, which might consist of two points but that is not necessarily the case.)]

[heading Concept Definition]

The Point Concept is defined as following:

* there must be a specialization of `traits::tag`, defining `point_tag` as type
* there must be a specialization of `traits::coordinate_type`, defining the type of its coordinates
* there must be a specialization of `traits::coordinate_system`, defining its coordinate system
	 (cartesian, spherical, etc)
* there must be a specialization of `traits::dimension`, defining its number of dimensions (2, 3, ...) 
	(hint: derive it conveniently from `boost::mpl::int_<X>` for X Dimensional)
* there must be a specialization of `traits::access`, per dimension, with two functions:
	* `get` to get a coordinate value
	* `set` to set a coordinate value (this one is not checked for ConstPoint)
	
[heading Example]

While you can `#include boost/geometry/geometries/adapted/std_array.hpp` to use `std::array<T, D>` to model the Point concept,
the following code spells it out in detail, as you might use for your own point types:
```
namespace boost { namespace geometry { namespace traits
{

template <typename T, std::size_t D> struct tag<std::array<T, D>> { using type = point_tag; };
template <typename T, std::size_t D> struct dimension<std::array<T, D>> : boost::mpl::int_<D> {};
template <typename T, std::size_t D> struct coordinate_type<std::array<T, D>> { using type = T; };
template <typename T, std::size_t D> struct coordinate_system<std::array<T, D>> { using type = boost::geometry::cs::cartesian; };

template <typename T, std::size_t D, std::size_t Index>
struct access<std::array<T, D>, Index> {
    static_assert(Index < D, "Out of range");
    using Point = std::array<T, D>;
    using CoordinateType = typename coordinate_type<Point>::type;
    static inline CoordinateType get(Point const& p) { return p[Index]; }
    static inline void set(Point& p, CoordinateType const& value) { p[Index] = value; }
};

}}} // namespace boost::geometry::traits
```

[heading Available Models]	
* [link geometry.reference.models.model_point model::point]
* [link geometry.reference.models.model_d2_point_xy model::d2::point_xy]
* a lat long point (currently in an extension)
* [link geometry.reference.adapted.c_array C array]
* [link geometry.reference.adapted.std_array C++ array container]
* [link geometry.reference.adapted.boost_array Boost.Array]
* [link geometry.reference.adapted.boost_fusion Boost.Fusion]
* [link geometry.reference.adapted.boost_polygon Boost.Polygon]
* [link geometry.reference.adapted.boost_tuple Boost.Tuple]
* other point types, adapted e.g. using one of the [link geometry.reference.adapted.register registration macros]

[endsect]


