Sites, psites and dpoints

Need for site

As we have seen before, an image is usually defined on a grid. It has associated data and a site set which defines the domain of the image on that grid. Usually, we need to access a value by its coordinates. With default images it can be done easily, at no cost.

Example with an image2d:

 c 0 1 2 3
0 | |x| | |
1 | | | | |

The site x is the point (0, 1). The image values are stored in a multi-dimensional array. The point coordinates can be used directly. The site (0, 1) is the point (0, 1) and the data is stored at row 0 and column 1.

Here we have:

I::site == I::psite == point2d

where, roughly, point2d = { row, column }.

Need for psite

Sometimes, accessing a value in constant-time complexity, O(1), is not possible with a site object.

Let’s have a small example. Define a function returning a value for a given point:

unsigned my_values(const mln::point2d& p)
  if (p.row() == 0)
    return 8;
  return 9;

So, for each point having (0, x) as coordinate, this function will return 8, otherwise it will be 9.

Then, define a p_array with few point2d:

  p_array<point2d> arr;
  arr.append(point2d(3, 6));
  arr.append(point2d(3, 7));
  arr.append(point2d(3, 8));
  arr.append(point2d(4, 8));
  arr.append(point2d(4, 9));

Now, create a point-wise image from this function and this p_array:

  mln_VAR(ima, my_values | arr);

ima is actually that image:

c  6 7 8 9
3  | |x| |
4      | | |

However, in memory, since it is based on a p_array, sites are stored in a vector.

The site x is the point (3, 7) which corresponds to the cell 1 in the p_array.

arr[] = 0 1 2 3 4
       | |x| | | |

Obviously, we cannot check in constant time whether the site x, point2d here, is part of that image or not: knowing the point coordinates is not enough. That’s why we need a different mechanism in order to access this information: the psites.

Here we have:

I::site == point2d but I::psite == pseudo_site<point2d>

where, roughly, pseudo_site<point2d> = { i_in_p_array, p_array_ptr }.

Psites contains all the needed information to access the values in constant-time.

From psite to site

In the last example there was an image of type I such as I::site != I::psite. In that case, an object of type I::psite is actually convertible towards an object of type I::site. Furthermore, a psite shall behave as if it was a site.

Design note: it seems impossible to offer through the interface of some psite what is expected from its corresponding site. For instance, when a site has a given feature, say a method "m", then this method has to appear in the psite interface. However, thanks to inheritance, we fetch an interface and an implementation that delegates to the site.

For instance, in the last example, I::psite has a method row() because I::site, point2d, provides such a method.

How it works: a psite inherits from internal::site_impl<site> which is specialized for every site type; for instance, internal::site_impl<point2d> owns the method “coord row() const” which is defined as “return exact(this)->to_site().row()”.


Dpoints are relative sites. They are usually used in window and neighborhood definitions. Since the central site is not constant, windows and neighborhoods must be recomputed and dpoints help in doing that.

  dpoint2d dp(-1,0);
  point2d p(1,1);

  std::cout << p + dp << std::endl;