Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
September 2008
- 12 participants
- 359 discussions
03 Sep '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Add documentation about the image values.
* doc/tutorial/image_values.txt: New, doc file.
image_values.txt | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 234 insertions(+)
Index: doc/tutorial/image_values.txt
--- doc/tutorial/image_values.txt (revision 0)
+++ doc/tutorial/image_values.txt (revision 0)
@@ -0,0 +1,234 @@
+-*- outline -*-
+
+
+* Image Values
+
+An image is an application:
+ ima: Domain -> Destination
+ p -> ima(p)
+
+Domain is a set of the point, or more generally sites, that compose the
+image. Destination is a set containing the values of the image. Each value
+of the image belongs to the Destination set.
+
+Yet, Destination can have several definitions. In the following, we will
+details these definitions.
+
+
+
+** E: values space
+
+E is a mathematical set. It contains, at least, all the values that the image
+can possibly take. All the image values are in the value spaces E.
+So for all p, ima(p) belongs to E.
+For instance, the value space of an image can be the rgb set, the int_u8 set
+or the gl8 set(gray level coded on 8 bits)...
+
+All the image provide the method .destination() which returns E.
+However, E is not always iterable in Milena. For performance issues, E is
+iterable only if the value are coded on less than 24 bits.
+
+If E is iterable, the following code:
+
+Code A)
+ for all v in ima.destination()
+ print v;
+
+prints all the values contained in the values space.
+
+** V: eligible values set.
+
+Like E, V is a mathematical set. It contains all the values that the image can possibly take. So if v belongs to V, ima(p) <- v is possible without any
+conversions.
+
+For instance, consider the set S composed by the colors RED, BLUE, ORANGE.
+S = (RED, BLUE, ORANGE).
+
+S is a subset of the rgb set. Indeed, the colors RED, BLUE, ORANGE are members
+of the rgb set. So, consider ima, an image defined with S as eligible value
+set. ima admits the rgb set as values space (the rgb set is the superset of S).
+However, ima can take only value from the S set (and not from the rgb set). So,
+ima(p) <- WHITE will not work.
+
+All the image provide the method .values_eligible() which returns S.
+
+Why do we introduce the eligible value set, since its definition is close to
+the value space?
+In the previous example, we can't apply Code A on ima. For performance reasons,
+we don't want to iter on the rgb set. But, it is possible to iterate over the
+ima values; since the ima eligible values set is a restriction of the rgb set.
+
+If we apply the following code on ima,
+
+code B)
+ for all v in ima.values_eligible()
+ print v
+
+the result will be:
+ RED BLUE ORANGE
+
+V can also be the value spaces itself. An image cab have all the rgb colors as
+eligible values. In this case, we can't iterate over the image eligible values.
+
+
+** Vp: values taken set
+
+Vp is a mathematical set that contains the values currently taken by an image.
+So for all p in the image domain, ima(p) belongs to Vp.
+If an image provides the access to its Vp, the image interface has the
+method .values_taken() which returns its Vp.
+
+
+For instance consider the following 2d image:
+
+ -----
+| R | R stands for Red
+| BGB| B stands for Blue
+| OO | G stands for Green
+ ----- O stands for orange.
+
+
+The following code:
+
+code C)
+ for all v in ima.values_taken()
+ print v
+
+prints:
+
+RBGO
+
+If the image admits (RED, BLUE, GREEN, WHITE, ORANGE) as eligible values set,
+the code B results is:
+RBGWO (W stands for white).
+
+
+
+
+** C: value cells
+
+All the milena image types are composed by cell.
+A cell is a location in RAM or in a file that stores an image value.
+
+For instance consider the following 2d images:
+
+ 0 1 2 3 4
+ ----------
+0 | |
+1 | R G R |
+2 | |
+3 | O W|
+4 | |
+ ----------
+
+This image is composed by 5 cells: R, G, R, O, W.
+Each cell correspond to a point 2d (respectively (1, 1), (1, 2), (1, 3),
+(1, 4)).
+
+
+C is the list of cells that is currently composing the image.
+Some image types provide an access to the cells list through the method
+.values_cell() which returns C.
+
+For instance, if we apply the following code the the previous image:
+
+code D)
+ for all v in ima.values_cells()
+ print v
+
+the result will be:
+RGROW, we print the list of cells composing the image.
+
+C is not a mathematical set. Indeed, in cell list a member can be duplicate.
+In the previous example R is present twice in the cells list.
+
+* Example1
+
+Consider the following rle image:
+
+ima = -----
+ | R |
+ | BBB|
+ | OO |
+ | RR|
+ -----
+
+This image encoded by runs (a run is a succession of points).
+Furthermore, only one value is associated to each run.
+
+So, in memory, the image will be encoded this way:
+
+ima = ({p, {R, 1}}, {q, {B, 3}}, {r, {O, 2}}, {s, {R, 2}} )
+ ^^^ ^^^ ^^^
+ run start run value run len
+
+where p, q, r are point at the beginning of a run:
+ -----
+ | p |
+ | q |
+ | r |
+ | s |
+ -----
+
+The run values correspond to the image cells.
+So if we apply the code D to this image, the result will be:
+RBOR
+
+If we apply the code C to this image, the result will be:
+RBO
+
+* Example2
+
+Consider the following sparse image:
+
+ima = -----
+ | R |
+ | BGB|
+ | OG |
+ | RR|
+ -----
+
+This image is also encoded by runs.
+But here, several values can be associated to each run.
+
+So, in memory, the image will be encoded this way:
+
+ima = ({p, (R)}, {q, (B, G, B)}, {r, {O, G}}, {s, {R, R}} )
+ ^^^ ^^^ ^^^
+ run start run values
+
+where p, q, r are point at the beginning of a run.
+
+The different values in each run correspond to the image cells.
+So if we apply the code D to this image, the result will be:
+RBGBOGRR
+
+If we apply the code C to this image, the result will be:
+RGBO
+
+* Example3
+
+Consider the following 2d image:
+
+ima = -----
+ |GROOG|
+ |BRBGB|
+ -----
+
+Every pixel can have a different values, so all the pixels are stored in
+memory.Thus, a cell is associated to each pixel of the image.
+So if we apply the code D to this image, the result will be:
+GROOGBRBGB
+
+If we apply the code C to this image, the result will be:
+RGBO
+
+
+* Order relationship
+
+E <= V <= V = E*
+
+
+* Image properties related to the values
+
+FIXME
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add tour files from old projects.
* doc/oldies: New.
* doc/oldies/2007__tour.cc: New.
* doc/oldies/2008__tour1.cc: New.
* doc/oldies/2008__tour2.cc: New.
* doc/oldies/2008__tour3.cc: New.
* doc/oldies/2008__tour1_extra.cc: New.
* doc/oldies/2006__tour_1.txt: New.
* doc/oldies/2006__tour_2.txt: New.
2006__tour_1.txt | 671 +++++++++++++++++++++++++++++++++++++++++++++++++++
2006__tour_2.txt | 404 ++++++++++++++++++++++++++++++
2007__tour.cc | 395 ++++++++++++++++++++++++++++++
2008__tour1.cc | 322 ++++++++++++++++++++++++
2008__tour1_extra.cc | 214 ++++++++++++++++
2008__tour2.cc | 393 +++++++++++++++++++++++++++++
2008__tour3.cc | 331 +++++++++++++++++++++++++
7 files changed, 2730 insertions(+)
Index: doc/oldies/2007__tour.cc
--- doc/oldies/2007__tour.cc (revision 0)
+++ doc/oldies/2007__tour.cc (revision 0)
@@ -0,0 +1,395 @@
+/* This is a short tour of the basics of Olena. It isn't in any way
+ meant to cover all the features of Olena. Especially, some
+ important objects, such as the iterators, are NOT presented here.
+ */
+
+// We will run some example with 1D, and 2D, so we include these two
+// files.
+#include <oln/basics1d.hh>
+#include <oln/basics2d.hh>
+//#include <oln/basics3d.hh>
+
+// Let's include all types, for simplicity.
+#include <ntg/all.hh>
+
+// Some algorithms...
+#include <oln/morpho/erosion.hh>
+#include <oln/morpho/dilation.hh>
+#include <oln/morpho/opening.hh>
+#include <oln/morpho/closing.hh>
+#include <oln/morpho/watershed.hh>
+
+#include <oln/utils/stat.hh>
+
+// Basic conversion functions.
+#include <oln/convert/basics.hh>
+
+// Always include system headers after Olena.
+#include <iostream>
+#include <cmath>
+
+
+
+// Namespaces.
+// ===========
+// Olena is organized in a namespace hierarchy. Every thing is
+// declared by Olena under the 'oln::' namespace, and possibly un a
+// sub namespace such as 'oln::arith::' (arithmetic operations on
+// images), 'oln::morpho::' (morphological operations), etc.
+// For the sake of simplicity, we will neglect the 'oln::' prefix
+// in this file.
+using namespace oln;
+
+// Data types are defined in the Int�gre library, so they are
+// in the ntg namespace.
+// In this file, we will neglect the 'ntg::' prefix.
+using namespace ntg;
+
+int
+main (void)
+{
+ // Basic value types.
+ // ==================
+ // Olena ships with a set of basic value types such as
+ // int_u8, int_u16, int_u32, (common unsigned integer types)
+ // int_s8, int_s16, int_s32, (common signed integer types)
+ // float_s, float_d, (common float types)
+ // bin (binary type: false|true)
+ //
+ // These value are defined in the value/ subdirectory. Actually
+ // we defined all of them by including value/all.hh.
+ //
+ // You should use them instead of the standard C/C++ type, because
+ // Olena types are equipped with additional members required to
+ // write generic processings.
+
+ // For instance the max() and min() class methods
+ // will return the maximum value of a type.
+ std::cout << "ntg_max_val(int_u8) = "
+ << ntg_max_val(int_u8) << std::endl;
+
+ // You can combine these values with the standard operators
+ // as expected.
+ int_u8 a = 4;
+ int_u16 b = 1000;
+ std::cout << "a + b = " << a + b << std::endl;
+
+ // Sometime it's hard to figure which type a variable has, because
+ // Olena seems to behave surprisingly at a first glance.
+ // There are two convenient functions that you can use to
+ // inspect a type.
+ // typename_of<T>() returns a std::string describing T
+ // typename_of_var(V) returns a std::string describing the type of V
+ std::cout << typename_of<int_u8>()
+ << " + "
+ << typename_of_var(b)
+ << " = " << typename_of_var(a + b) << std::endl;
+ // The expression above will print
+ // "int_u<8> + int_u<16> = int_u<17>"
+ // This probably seems surprising for two reasons:
+ // 1) int_u8 is printed as int_u<8>
+ // this is because int_u8 is really just a short hand for int_u<8>,
+ // Olena allows you to declare unsigned integer on 13 bits, if
+ // you want (int_u<13>); but int_u<8>, int_u<16>, and int_u<32> are
+ // more common so they have their own typedef.
+ // 2) (a + b) has type int_u<17>, not int_u<16> as one would expect.
+ // The point is that one needs 17 bits to hold the result
+ // of an addition between a 8bit and a 16bit value without
+ // overflowing.
+
+ // Olena will also ensure that you don't such a large value to
+ // a variable with a smaller type:
+ // int_u16 c = a + b;
+ // would fail to compile because (a + b) has type int_u<17> which
+ // cannot fit in int_u<16>.
+ // If you *know* that the result of (a + b) fits in c, you
+ // should cast the value to int_u16 explicitly:
+ int_u16 c = a + b;
+ std::cout << "c = " << c << std::endl;
+ // Of course assigning a+b to a variable of type int_u<17> or
+ // greater is allowed and doesn't require a cast.
+
+
+ // Image types.
+ // ============
+ // There are three kind of images supported for the moment.
+ // image1d, image2d, and image3d: the names are self-explanatory.
+ // All are template, parametrized by the kind of value associated
+ // to each point (we call 'point' a position in the image).
+ //
+ // We will start to use the 1D images, because they are
+ // easier to fill manually (i.e. there are less value
+ // to assign), and easy to display.
+
+ // Here are two most basic way to build an image.
+ image1d<int_u8> img1a; // Build an empty image.
+ image1d<int_u8> img1b(20); // Build an image with 20 points.
+
+ // The empty image hasn't any data. It's really useful
+ // only as a placeholder for the result of some processing,
+ // or another image.
+
+ // Assigning an image to another one is not a costly operation.
+ // In fact, img1a behave like some pointers. After the following
+ // instruction
+ img1a = img1b;
+ // img1a and img1b can be used equivalently to access the
+ // same data (in other words, the point values are shared
+ // by img1a and img1b).
+ img1a(10) = 42; // Assign value 42 to the 11th point of img1a
+ std::cout << "img1b(10) ="
+ << img1b(10) << std::endl; // print 42, although we use img1b
+
+ // We call these assignments 'shallow copies', because they don't copy the
+ // data. If you want to make a deep copy of an image, then use
+ // the clone() method, as in Java.
+ img1a = img1b.clone ();
+ img1a(10) = 13;
+ std::cout << "img1b(10) ="
+ << img1b(10) << std::endl; // still print 42
+
+ // As show above, assignments can be made using the parenthesis
+ // operator, which takes to coordinates of the point you want to
+ // assign a value to in argument. (In 1D there is only one coordinate.)
+ // Let's fill our image with a saw-teeth signal.
+ // (coord is the type used for coordinates)
+ for (coord col = 0; col < img1a.ncols(); ++col)
+ img1a(col) = col % 5;
+
+ std::cout << "img1a:" << std::endl;
+ std::cout << img1a << std::endl;
+ // 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
+
+ // You can build image2d and image3d objects similarly, except
+ // you have to account for the extra coordinate.
+ image2d<bin> img2a(10, 10);
+ for (coord row = 0; row < img2a.nrows(); ++row)
+ for (coord col = 0; col < img2a.ncols(); ++col)
+ img2a(row, col) = (row >= 3 && col >= 3 && row < 7 && col < 7);
+ std::cout << "img2a:" << std::endl;
+ std::cout << img2a << std::endl;
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - | | | | - - -
+ // - - - | | | | - - -
+ // - - - | | | | - - -
+ // - - - | | | | - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+
+ // Point types
+ // ===========
+ // As said before, a point is a position in an image. Because
+ // Olena supports different dimension, it supports different
+ // types of points: point1d, point2d, point3d.
+
+ // You build a point by passing it as much coordinate as
+ // needed.
+ point1d p1(10);
+ point2d p2(5, 3);
+ // You can address the value associated to a particular point
+ // in a image by using the [] operator:
+ std::cout << "img1b[p1]" << img1b[p1] << std::endl; // print 42
+
+ img2a[p2] = false;
+ std::cout << "img2a:" << std::endl;
+ std::cout << img2a << std::endl;
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - | | | | - - -
+ // - - - | | | | - - -
+ // - - - - | | | - - -
+ // - - - | | | | - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+
+
+ // Delta Point types
+ // =================
+ // You can't add points together, this make no sense. However
+ // you can use a delta-point to record a displacement, and add
+ // this delta-point to a point (yielding a new point).
+ // The types for delta-points are dpoint1d, dpoint2d, and dpoint3d.
+ dpoint1d dp1(2);
+ std::cout << "p1 + dp1 = " << p1 + dp1 << std::endl;
+ dpoint2d dp2(-1, 2);
+ img2a[p2 + dp2] = false;
+ std::cout << "img2a:" << std::endl;
+ std::cout << img2a << std::endl;
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - | | | | - - -
+ // - - - | | - | - - -
+ // - - - - | | | - - -
+ // - - - | | | | - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+
+
+ // Windows
+ // =======
+ // Windows are sets of delta-points.
+ //
+ // There are some predefined windows.
+ // For instance here are two common window2d objects:
+ std::cout << "win_c4p() = " << win_c4p() << std::endl;
+ // [(-1,0)(0,-1)(0,0)(0,1)(1,0)]
+ std::cout << "win_c4_only() = " << win_c4_only() << std::endl;
+ // [(-1,0)(0,-1)(0,1)(1,0)]
+
+ // A window is commonly used to iterate around a fixed point.
+ // For instance
+ window2d w2 = win_c4_only();
+ for (unsigned i = 0; i < w2.card(); ++i)
+ std::cout << "img2a[p2 + w2[" << i << "]] = "
+ << "img2a[" << p2 + w2.dp(i) << "] = "
+ << img2a[p2 + w2.dp(i)] << std::endl;
+ // img2a[p2 + w2[0]] = img2a[(4,3)] = |
+ // img2a[p2 + w2[1]] = img2a[(5,2)] = -
+ // img2a[p2 + w2[2]] = img2a[(5,4)] = |
+ // img2a[p2 + w2[3]] = img2a[(6,3)] = |
+
+ // You can build you own window using by adding delta-points
+ // using the add() method.
+ window1d w1;
+ w1.add(-1).add(0).add(1);
+ std::cout << "w1 = " << w1 << std::endl; // [(-1)(0)(1)]
+
+ // Neighborhoods
+ // =============
+ // These objects are like Windows, except they have
+ // some additional properties (a point is not in its neighborhood,
+ // the neighbor of a point should have the point in its neighborhood).
+ // For this reason, they have types distinct from the windows:
+ // neighborhood1d, neighborhood2d, neighborhood3d.
+ // The interface is just the same as the windows.
+ neighborhood1d n1;
+ n1.add(1);
+ std::cout << "n1 = " << n1 << std::endl; // N[(-1)(1)]
+
+
+ // Processings.
+ // ============
+ // We have seen how to build images and windows, that's
+ // enough to call some morphological operator.
+ // Windows are used as structural elements, so we can
+ // apply some basic morphological operator on img1a
+ // (the saw) using w1 as structural element:
+ std::cout << "erosion" << std::endl;
+ std::cout << morpho::erosion(img1a, w1) << std::endl;
+ // 0 0 1 2 0 0 0 1 2 0 0 0 1 2 0 0 0 1 2 3
+ std::cout << "dilation" << std::endl;
+ std::cout << morpho::dilation(img1a, w1) << std::endl;
+ // 1 2 3 4 4 4 2 3 4 4 4 2 3 4 4 4 2 3 4 4
+ std::cout << "opening" << std::endl;
+ std::cout << morpho::opening(img1a, w1) << std::endl;
+ // 0 1 2 2 2 0 1 2 2 2 0 1 2 2 2 0 1 2 3 3
+ std::cout << "closing" << std::endl;
+ std::cout << morpho::closing(img1a, w1) << std::endl;
+ // 1 1 2 3 4 2 2 2 3 4 2 2 2 3 4 2 2 2 3 4
+
+ // Yet, remember that Olena is a *generic* image
+ // processing library, in which processing are meant
+ // to be written once but yet work on many kind of images.
+
+ // Let's close the small hole we have added to img2d (in the
+ // paragraph about delta points).
+ std::cout << morpho::closing(img2a, win_c4p()) << std::endl;
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - | | | | - - -
+ // - - - | | | | - - -
+ // - - - - | | | - - -
+ // - - - | | | | - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+ // - - - - - - - - - -
+
+
+ // The watershed algorithm takes a neighborhood (not a window) as
+ // argument, and a type as template parameter.
+
+ // The type parameter specifies the type of the output image value.
+ // Watershed are indicated with the max() of this type, other values
+ // are basin labels.
+ std::cout << "watershed" << std::endl;
+ std::cout << morpho::watershed_seg<int_u8>(img1a, n1) << std::endl;
+ // 4 4 4 4 255 3 3 3 3 255 2 2 2 2 255 1 1 1 1 1
+
+
+ // Reading and writing PNM files.
+ // // You can read image2d from pnm files. The kind
+ // of pnm format supported (1,2,3,4,5,6) is dependent on
+ // the type of the image you load/save. The extension
+ // is also used to guess the format to use.
+ image2d<int_u8> lena = load(IMGDIR "/lena.pgm");
+ if (!lena.has_impl())
+ {
+ std::cerr << "Could not load " << IMGDIR "/lena.pgm" << std::endl;
+ exit(1);
+ }
+ std::cout << "watershedling lena..." << std::endl;
+ save(morpho::watershed_seg<int_u8>(lena, neighb_c4()), "output.pgm");
+
+
+ // High order operators.
+ // // Olena offers a set of high order operators than can simplify
+ // the writing of simple algorithm.
+ // For instance `traverse(f, img)' will apply the function `f'
+ // to each point of `img'. Actually, `f' do not need to be a function,
+ // it just have to _behave_ like a function; it can be a functor, i.e.,
+ // an instance of a class that implements an `operator()' (this allows
+ // `f' to maintain a state without using a global variable).
+
+ // The header `utils/stat.hh' define some functor to compute
+ // statistical data. In the following example we instantiate
+ // an `f_moments' functor, have it traverse the saw-teeth image,
+ // and compute some moments from the data gathered during the traversal.
+ utils::f_moments<int_u8> f;
+ traverse(f, img1a);
+ std::cout << "f.mean() = " << f.mean() << std::endl;
+ std::cout << "f.variance() = " << f.variance() << std::endl;
+
+ // `apply' is an high order operator similar to `traverse', but
+ // it builds an image from the results of the function application.
+ //
+ // o = apply(f, i);
+ //
+ // is a short for
+ //
+ // for all point p in i: o[p] = f(i[p])
+ //
+ // The type of the output image may be different from the type
+ // of the input image, so `apply' need a little more help from
+ // `f' than `traverse' does. Basically, `f' should define
+ // a type member named `result_type' so that `apply' knows which
+ // type of output image it has to create.
+ //
+ // (NOTE: The `result_type' presence is part of the requirement of
+ // the `Adaptable Unary Function' concept in the STL. So if you
+ // have a model of `Adaptable Unary Function', you can safely pass
+ // it to `apply'.)
+ //
+ // Some conversion functions (those for which the output type is
+ // knonw) can be used this way. For instance the
+ // `convert::bound<T>' functor will convert any value to type `T'
+ // and saturate for out-of-bound values. See how the `4' are
+ // converted to `3' when the saw-teeth image is converted to an
+ // image2d<int_u<2> > image.
+ std::cout << apply(convert::bound<int_u<2> >(), img1a) << std::endl;
+ // 0 1 2 3 3 0 1 2 3 3 0 1 2 3 3 0 1 2 3 3
+
+ // Another usefull high order operator is `fold':
+ // - `fold(f, val, img)' computes `f(...f(f(val,i_0),i_1)...,i_n)',
+ // where i_0...i_n are the value associated to each image point.
+ // - `fold(f, img)' computes `f(...f(f(i_0,i_1),i_2)...,i_n)'.
+ // In both cases, `f' must be a model of the
+ // `Adaptable Binary Function' STL concept.
+}
Index: doc/oldies/2008__tour1.cc
--- doc/oldies/2008__tour1.cc (revision 0)
+++ doc/oldies/2008__tour1.cc (revision 0)
@@ -0,0 +1,322 @@
+// Copyright (C) 2001, 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// File: tour1.cc.
+
+#include <oln/core/1d/image1d.hh>
+
+#include <oln/arith/plus.hh> // arith
+
+#include <oln/level/fill.hh> // level
+#include <oln/level/paste.hh>
+
+#include <oln/debug/println.hh> // debug
+
+
+int main()
+{
+ // Olena is organized in a namespace hierarchy. Everything is
+ // declared by Olena within the 'oln::' namespace, and possibly a
+ // sub-namespace such as 'oln::arith::' (arithmetic operations on
+ // images), 'oln::morpho::' (morphological operations), etc. For
+ // the sake of simplicity, we will neglect the 'oln::' prefix in
+ // this file.
+
+ using namespace oln;
+
+ // There are three kinds of image dimensions supported for the
+ // moment: 1D, 2D, and 3D. The respective basic image types are
+ // respectively image1d, image2d, and image3d. All are template'd,
+ // parametrized by the kind of value associated to each point.
+ //
+ // We will start to use the 1D images, because there are less values
+ // to assign (!) and because they are easy to display. Although we
+ // will be in 1D, we will talk about "points" and "pixels", just
+ // like in the classical 2D world.
+
+ // Here are the two most basic ways to build an image:
+
+ image1d<int> img1a; // which builds an empty image;
+ image1d<int> img1b(20); // which builds an image with 20 pixels.
+
+ // The type of values enclosed in those images is 'int' for
+ // integers.
+
+ // The empty image has no data and its definition domain is still
+ // unset. We do not know yet the number of pixels it contains.
+ // However, it is really useful to have such an "empty image"
+ // because it is a placeholder for the result of some processing, or
+ // another image.
+
+ // Trying to access the pixel value from an empty image leads to an
+ // error at run-time.
+
+ // Assigning an image to another one is NOT a costly operation.
+ // Actually img1a behaves like some mathematical variable. Put
+ // differently it is just a name to designate an image. After the
+ // following instruction
+
+ img1a = img1b;
+
+ // Both variables img1a and img1b can be used equivalently to access
+ // the same data. Just like in maths we can state that "img1a IS
+ // img2b" and we only have ONE actual image in memory. The image
+ // definition---its domain and its pixel values--is shared by img1a
+ // AND img1b.
+
+
+ // Since an image is a function that maps values to points, to read
+ // or modify a pixel value, we just the same notation than the one
+ // of functions:
+
+ img1a.at(0) = 7; // Assign value 7 to the 1st pixel of img1a.
+ img1a.at(10) = 51; // Assign value 51 to the 11th pixel of img1a.
+
+ std::cout << "img1b.at(10) = " << img1b.at(10)
+ << std::endl; // Print 51 since img1b is img1a.
+
+ // As you can see, Olena provides a unique easy syntax to access an
+ // image value, whatever we want to read this value or to modify it:
+ // "ima(p)", where p is a variable that represents a point of the 1D
+ // domain. In "val = ima(p)" we read the pixel value, whereas in
+ // "ima(p) = new_val" we write in an image. For 1D images, a 1D
+ // point behaves just like an index so the user can write "ima(i)"
+ // with i being an integer.
+
+
+ // A single image variable can be used to designate one image and
+ // then another one.
+
+ image1d<int> img2a(20); // An image (not empty).
+ image1d<int> img2b(20); // Another one (not empty).
+ image1d<int> img; // A variable.
+
+ img = img2a; // img is img2a
+ img.at(5) = 19; // so img2a at index 5 is set to 19.
+
+ img = img2b; // img is NOW img2b
+ img.at(5) = 69; // so img2b at index 5 is set to 69.
+
+ std::cout << (100 * img2a.at(5) + img2b.at(5)) // Gives 1969.
+ << std::endl;
+
+
+
+ // In the Olena library, all image types behave like image1d:
+ //
+ // +-----------------------------------------------------------+
+ // | |
+ // | - an "empty" image actually is a mathematical variable |
+ // | |
+ // | => just think in a mathemetical way when dealing |
+ // | with images; |
+ // | |
+ // | |
+ // | - no dynamic memory allocation/deallocation is required |
+ // | |
+ // | the user never has to use "new / delete" (the C++ |
+ // | equivalent for the C "malloc / free") so she does |
+ // | not have to manipulate pointers or to directly |
+ // | access memory |
+ // | |
+ // | => Olena prevents the user from making mistakes; |
+ // | |
+ // | |
+ // | - image data/values can be shared between several |
+ // | variables and the memory used for image data is |
+ // | handled by the library |
+ // | |
+ // | => memory management is automatic. |
+ // | |
+ // | |
+ // +-----------------------------------------------------------+
+
+
+
+
+ image1d<char> img3a(0, 19); // These 1D image data go from the
+ // index 0 to the index 19; it thus has
+ // 20 points.
+
+ // Memory has been allocated so data can be stored but pixel values
+ // have not been initialized yet. So we fill img3a, that is, all
+ // pixels of img3a, with the value 'a':
+ level::fill(inplace(img3a), 'a');
+
+ // The "fill" algorithm is located in the sub-namespace "level"
+ // since this algorithm deals with the "level" of pixel values.
+
+ // Note that the term "level" refers to the fact that an
+ // image can be considered as a landscape where the
+ // elevation at a particular location/point is given by the
+ // corresponding pixel value.
+
+ // The full name of this routine is "oln::level::fill". To access
+ // to a particular algorithm, the proper file shall be included.
+ // The file names of algorithms strictly map their C++ name; so
+ // oln::level::fill is defined in the file "oln/level/fill.hh".
+
+ // Most algorithms in Olena are constructed following the classical
+ // scheme: "output algo(input)", where the input image is only read.
+ // However some few algorithms take an input image in order to
+ // modify it. To enforce this particular feature, the user shall
+ // explicitly state that the image is provided so that its data is
+ // modified "inplace".
+
+ // The algorithm call shall be "level::fill(inplace(ima), val)".
+ // When forgetting the "inplace(..)" statement it does not compile.
+
+
+ // We then define below a second image to play with. As you can see
+ // this image has data for the indices 5 to 14 (so it has 10
+ // points). The definition domain of a 1D image can start from
+ // any index, even a negative one.
+ image1d<char> img3b(5, 14);
+
+ // We initialize the image values.
+ level::fill(inplace(img3b), 'b');
+
+ // Last we now paste the contents of img3b in img3a...
+ level::paste(img3b, inplace(img3a));
+
+ // ...and print the result.
+ debug::println(img3a);
+
+ // Before pasting, the couple of images looked like:
+ //
+ // index = 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
+ //
+ // img3a = a a a a a a a a a a a a a a a a a a a a
+ // img3b = b b b b b b b b b b
+ //
+ // so after pasting we get:
+ // img3a = a a a a a b b b b b b b b b b a a a a a
+ //
+ // Just remember that a point is an absolute location on the
+ // discrete domain. For the 1D case, an index is thus NOT an
+ // offset. When we write "imgb(5)", we designate the first pixel of
+ // imgb since this image starts at index 5.
+
+
+ // With this simple example we can see that images defined on
+ // different domains (or set of points) can interoperate. The set
+ // of points an image is defined on can be accessed and printed.
+ // The following code:
+
+ std::cout << "img3a.points() = " << img3a.points() << std::endl
+ << "img3b.points() = " << img3b.points() << std::endl;
+
+ // gives:
+ // img3a.points() = { (0) .. (19) }
+ // img3b.points() = { (5) .. (14) }
+
+ // The notion of point sets plays an important role in Olena. Many
+ // tests are performed at run-time to ensure that the program is
+ // correct.
+
+ // For instance, the algorithm level::paste tests that the set of
+ // points of img3b (whose values are to be pasted) is a subset of
+ // the destination image. We can reproduce this same test:
+
+ std::cout << (img3b.points() <= img3a.points() ?
+ "true" :
+ "false") << std::endl; // which gives 'true'.
+
+ // Accessing the value of an image at a given point also performs a
+ // test to make sure that this point belongs to the image domain
+ // (and consequently that data access in memory is valid). For
+ // instance, calling "img3a(9)" actually runs a code equivalent to
+ // this test:
+
+ point1d p(9);
+ std::cout << (img3a.points().has(p) ?
+ "true" :
+ "false") << std::endl; // which gives 'true'.
+
+ // The type of 1D image points is "point1d". The 1D image type
+ // features the method "operator()(point1d p)"; when we write
+ // "img3a(9)" it is just a shortcut for "img3a( point1d(9) )".
+
+ // When having a point we can access its index following:
+ std::cout << p.ind() << std::endl; // which gives 9.
+
+ // To know if a point belongs to an image domain or not, we can run
+ // this shorter test:
+ std::cout << (img3a.has(p) ?
+ "true" :
+ "false") << std::endl; // which gives 'true'.
+
+
+ // Since the notion of point is independent from the image it
+ // applies on, we can form expressions where p is used on several
+ // images:
+
+ img3a(p) = 'M', img3b(p) = 'W'; // At index 9, both values change.
+ debug::println(img3a);
+ debug::println(img3b);
+ // we obtain:
+ // a a a a a b b b b M b b b b b a a a a a
+ // b b b b W b b b b b
+
+
+ // To modify all the values of an image we can iterate over its
+ // domain with an index i:
+
+ for (int i = 5; i <= 14; ++i)
+ img3b.at(i) = 'a' + i - 5;
+ debug::println(img3b);
+ // a b c d e f g h i j
+
+ // There is a safer way to iterate that prevents from providing a
+ // wrong value for the minimum or maximum index value:
+ for (int i = img3b.min_ind(); i <= img3b.max_ind(); ++i)
+ img3b.at(i) = 'b' + i - img3b.min_ind();
+ debug::println(img3b);
+ // b c d e f g h i j k
+
+
+ // The Olena library was built with the following rationale:
+ //
+ // +-----------------------------------------------------------+
+ // | |
+ // | If you do not want to be "generic", if you are used to |
+ // | the classical way of browsing pixel values, you can! |
+ // | |
+ // +-----------------------------------------------------------+
+
+
+ // Indeed, the loops above depict the "classical" way to iterate
+ // over the contents of a 1D image. The next tour file introduces
+ // the solution provided by Olena to write better loops...
+
+
+ // Jump to tour1_extra.cc if you want some more information about
+ // image data management.
+
+ // Jump to tour2.cc to continue the tour.
+}
Index: doc/oldies/2008__tour2.cc
--- doc/oldies/2008__tour2.cc (revision 0)
+++ doc/oldies/2008__tour2.cc (revision 0)
@@ -0,0 +1,393 @@
+// Copyright (C) 2001, 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// File: tour2.cc.
+
+#include <oln/core/2d/image2d.hh>
+#include <oln/core/2d/window2d.hh>
+#include <oln/debug/println.hh>
+
+
+
+// Note to the reader: If you do not have read the tour1.cc file, you
+// should have a quick look at it before proceeding with this present
+// file. Some important features and practices are described in the
+// former tour step that are here assumed to be known.
+
+
+
+int main()
+{
+ using namespace oln;
+
+ // As shown before, image data read access and pixel value
+ // assignments can be performed using:
+ // - either the parenthesis operator with takes a point as its
+ // argument,
+ // - or the ".at" method which requires the coordinates of the point
+ // you want to access to.
+
+ // ex: ima(p), with p a 1D point, or ima.at(i), ima being a 1D
+ // image and i an index---single coordinate.
+
+
+ // Objects from image2d and image3d types can be build and access to
+ // in a similar way than image1d, except you have to account for
+ // respectively one and two extra coordinates. Let us take an
+ // example.
+
+ image2d<bool> img(4, 5); // A 4x5 2D binary image.
+
+ for (unsigned row = 0; row < img.nrows(); ++row)
+ for (unsigned col = 0; col < img.ncols(); ++col)
+ img.at(row, col) =
+ (row > 0 and row < 3) and (col > 0 and col < 4);
+
+ debug::println(img); // Gives:
+ // - - - - -
+ // - | | | -
+ // - | | | -
+ // - - - - -
+
+ // When debug::print'ing binary images, the 'true' (object) and
+ // 'false' (background) values are respectively depicted by the '|'
+ // and '-' symbols.
+
+
+
+
+ // As said before, a point is a position in an image. Because
+ // Olena supports different dimensions, it supports different
+ // point types: point1d, point2d, and point3d.
+
+ // We build a point by passing it as much coordinates as
+ // needed:
+ point2d p(2, 0); // a 2D point so a couple of coordinates.
+
+ // Each point coordinate can be accessed separately...
+ std::cout << "row = " << p.row() << std::endl
+ << "col = " << p.col() << std::endl;
+
+ // ...and modified:
+ p.col() = 1;
+ std::cout << "col = " << p.col() << " (new value!)" << std::endl;
+
+ // So we have a way to access image data:
+ img(p) = false;
+ // which is shorter than the equivalent writing:
+ // ima2a.at(2, 1) = false;
+
+ debug::println(img);
+ // Gives (with hand-written coordinates):
+ // col 0 1 2 3 4
+ // row v
+ // 0 - - - - -
+ // 1 - | | | -
+ // 2 > - - | | -
+ // 3 - - - - -
+
+ // Points in Olena are not really like mathematical vectors. The
+ // reason is twofold. Some operations over vectors are meaningless
+ // with points; for instance adding points together makes no sense.
+ // Furthermore we want C++ expressions with points to be more
+ // strongly typed so that errors from the user can be more easily
+ // pointed out.
+
+ // To record a displacement from one point to another one, Olena
+ // introduces the notion of "delta-points". The types for
+ // delta-points are dpoint1d, dpoint2d, and dpoint3d. We have:
+
+ dpoint2d dp(-1, +2); // -1 applies to row, +2 applies to column.
+ img(p + dp) = false;
+ debug::println(img);
+ // Gives:
+ // col 0 1 2 3 4
+ // row . . v
+ // 0 - - - - -
+ // 1 > - | | - -
+ // 2 . - - | | -
+ // 3 - - - - -
+
+ // Let us verify:
+ point2d p2 = p + dp;
+ std::cout << "p2 " << p2
+ << " = p " << p
+ << " + dp " << dp << std::endl;
+ assert(p2 == point2d(1, 3)); // Right: p2 is (1, 3).
+
+ // Taking the difference between a couple of points gives a
+ // delta-point.
+ dpoint2d dp2 = p2 - p; // That should be equal to 'dp'.
+ assert(dp2 == dp); // Indeed.
+
+ // Delta-points (amongst them) feature the classical arithmetical
+ // operators:
+ dpoint2d dp3 = dp + dp2;
+ dp3 -= dp2;
+ assert(dp3 == dp);
+
+
+ // The notion of delta-point is at the base of the definitions of
+ // classical window and neighborhood.
+
+
+ // A window, or "sliding window", is a region defined around a
+ // point. In its most usual forms offered by Olena, for instance
+ // window2d for the 2D case, windows are internally defined by a set
+ // of delta-points.
+
+ window2d win; // Empty window.
+ win
+ .take(dpoint2d(-1, -1)) // Add a delta-point.
+ .take(dpoint2d( 0, 0))
+ .take(dpoint2d( 1, 1))
+ .take(dpoint2d( 1, 2));
+ std::cout << "win = " << win << std::endl;
+ // win = [ (-1, -1), (0, 0), (1, 1), (1, 2) ]
+
+ // A window is commonly used to iterate around a fixed point.
+ std::cout << "around " << p
+ << " window points are ";
+ for (unsigned i = 0; i < win.size(); ++i)
+ std::cout << (p + win[i]) // win[i] gives the ith element of the
+ << ' '; // window, i.e., a delta-point.
+ std::cout << std::endl;
+ // The code above outputs:
+ // around (2, 1) window points are (1, 0) (2, 1) (3, 2) (3, 3)
+
+
+ // If we try to generalize this kind of display to all image points,
+ // one straightforward code is the following:
+
+ {
+ // First version.
+
+ std::cout << std::endl
+ << "First version:" << std::endl
+ << std::endl;
+
+ for (unsigned row = 0; row < img.nrows(); ++row)
+ for (unsigned col = 0; col < img.ncols(); ++col)
+ {
+ point2d p(row, col);
+ std::cout << p << ": ";
+ for (unsigned i = 0; i < win.size(); ++i)
+ {
+ point2d q = p + win[i]; // q is a point around p;
+ // precisely, the ith point of
+ // the window win centered at
+ // point p
+ if (img.has(q)) // we only print q if it actually lies
+ // within the image
+ std::cout << q << ' ';
+ }
+ std::cout << std::endl;
+ }
+
+ } // End of 1st version.
+
+ // We obtain:
+ // (0, 0): (0, 0) (1, 1) (1, 2)
+ // (0, 1): (0, 1) (1, 2) (1, 3)
+ // (0, 2): (0, 2) (1, 3) (1, 4)
+ // (0, 3): (0, 3) (1, 4)
+ // (0, 4): (0, 4)
+ // (1, 0): (1, 0) (2, 1) (2, 2)
+ // (1, 1): (0, 0) (1, 1) (2, 2) (2, 3)
+ // (1, 2): (0, 1) (1, 2) (2, 3) (2, 4)
+ // (1, 3): (0, 2) (1, 3) (2, 4)
+ // (1, 4): (0, 3) (1, 4)
+ // (2, 0): (2, 0) (3, 1) (3, 2)
+ // (2, 1): (1, 0) (2, 1) (3, 2) (3, 3)
+ // (2, 2): (1, 1) (2, 2) (3, 3) (3, 4)
+ // (2, 3): (1, 2) (2, 3) (3, 4)
+ // (2, 4): (1, 3) (2, 4)
+ // (3, 0): (3, 0)
+ // (3, 1): (2, 0) (3, 1)
+ // (3, 2): (2, 1) (3, 2)
+ // (3, 3): (2, 2) (3, 3)
+ // (3, 4): (2, 3) (3, 4)
+
+
+ // An equivalent code, given here just for you to realize that you
+ // may continue to handle images and points with Olena just the way
+ // you are used to it:
+
+ /*
+
+ { // A variation.
+
+ int nrows = img.nrows(), ncols = img.ncols();
+ unsigned n = win.size();
+ for (int row = 0; row < nrows; ++row)
+ for (int col = 0; col < ncols; ++col)
+ {
+ std::cout << "(" << row << ", " << col << "): "; // print p
+ for (unsigned i = 0; i < n; ++i)
+ {
+ int // define q coordinates:
+ r = row + win[i].row(),
+ c = col + win[i].col();
+ if (r >= 0 and r < nrows and c >= 0 and c < ncols) // q is in img
+ std::cout << "(" << r << ", " << c << ") "; // print q
+ }
+ std::cout << std::endl;
+ }
+
+ } // End of a variation.
+
+ */
+
+
+ // Such samples of "classical" image processing code have 3 (three!)
+ // main drawbacks:
+
+ // - it is error-prone; note that there is rather a lot of code for
+ // a so simple algorithm;
+
+ // - the algorithm, that is, the most important part of this code, is
+ // totally drowned in the middle of implementation details;
+
+ // - this kind of writing only applies to a very special type of
+ // images (2D ones, rectangular, and starting at (0,0)) so it is
+ // not reusable.
+
+
+ // If we express the algorithm into natural language, we can say:
+ //
+ // p, a point of img
+ // q, a point of win centered at p
+ //
+ // for all p
+ // print p
+ // for all q
+ // if q is in img
+ // print q
+ // print end of line
+ // end for
+ // end for
+
+
+ // The Olena library has been designed so that you can easily
+ // translate your algorithms into code. With the running example we
+ // can write:
+
+ { // Second version.
+
+ std::cout << std::endl
+ << "Second version (same result):" << std::endl
+ << std::endl;
+
+ box2d::piter p (img.points());
+ window2d::qiter q (win, p);
+
+ for_all(p)
+ {
+ std::cout << p << ": ";
+ for_all(q)
+ if (img.has(q))
+ std::cout << q << ' ';
+ std::cout << std::endl;
+ }
+
+ } // End of 2nd version.
+
+ std::cout << std::endl;
+
+
+ // Above, p and q behave just like points; for instance, the
+ // following expressions are valid:
+
+ // int r = p.row();
+ // to get the current row value,
+
+ // bool b = img(p);
+ // to get the pixel value at the current point,
+
+ // or point2d pp = p + dp;
+ // where dp is a delta-point to get a point nearby p.
+
+ // Yet, p and q are "more than points" since they allow to
+ // browse/iterate over a set of points, respectivelly, the domain of
+ // 'img' and the window centered at p.
+
+
+ // The domain of 'img' is obtained with "img.points()" and is
+ // provided to the 'p' object so that it knows how to iterate.
+
+ // For a "basic" image, its set of points is an n-dimensional box.
+ // In the 2D space, the box type is called 'box2d'. We also have
+ // 'box1d' and 'box3d' for other dimensions.
+
+ box2d pts = img.points();
+ std::cout << "img points are " << pts << std::endl;
+ // Prints:
+ // img points are { (0, 0) .. (3, 4) }
+
+ // The type of iterators over a point set is obtained with the
+ // expression: "name_of_the_point_set_type::piter", where 'piter'
+ // means "point iterator" for short.
+
+ // The same construction is available for iterators on window
+ // points, whose types are obtained in a similar way with
+ // "name_of_the_window_type::qiter". Here the 'q' in 'qiter'
+ // emphases the fact that a window is not really a set of points but
+ // "a set of dpoints and a center point".
+
+
+
+ // The second version of our example contrasts with the more
+ // "classical" ones; it is:
+
+ // - shorter,
+ // so it is less error-prone for the developer;
+
+ // - easy to read,
+ // so the algorithm appears clearly from the code;
+
+ // - (almost) "generic",
+ // for instance, no details within the loops indicate that we are
+ // processing a 2D image, that this image is rectangular, etc.
+
+
+ // +-----------------------------------------------------------+
+ // | |
+ // | A major feature of Olena is to offer to its users a way |
+ // | to write GENERIC algorithms, that is, algorithms that |
+ // | accept different image types as input. |
+ // | |
+ // +-----------------------------------------------------------+
+
+
+ // The next files of the tour give many details about what you can
+ // expect from the notion of "genericity" applied to image
+ // processing.
+
+ // Now you can jump to tour3.cc
+
+
+}
Index: doc/oldies/2008__tour3.cc
--- doc/oldies/2008__tour3.cc (revision 0)
+++ doc/oldies/2008__tour3.cc (revision 0)
@@ -0,0 +1,331 @@
+// Copyright (C) 2001, 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// File: tour2.cc.
+
+#include <oln/core/2d/image2d.hh>
+#include <oln/core/2d/neighb2d.hh>
+
+#include <oln/core/gen/such_as.hh>
+#include <oln/core/gen/torus_image.hh>
+#include <oln/core/gen/pw_value.hh>
+#include <oln/core/gen/fun_ops.hh>
+
+#include <oln/level/fill.hh>
+#include <oln/debug/fill.hh>
+#include <oln/debug/println.hh>
+
+
+// Note to the reader: you should have read the files tour1.cc and
+// tour2.cc before starting with this present file.
+
+
+
+// We have encapsulated an algorithm into a procedure which is forward
+// declared below so that it can be used in the section 'main'.
+template <typename I> void algo(const I& img);
+
+
+// Some functions that will be useful in the following:
+bool chessboard(oln::point2d p)
+{
+ return (p.row() + p.col()) % 2;
+}
+
+
+
+int main()
+{
+ using namespace oln;
+
+ // First our domain is 2d box:
+ box2d b(point2d(0, 0), point2d(2, 2));
+ // ^^^^ ^^^^
+ // from to
+
+ // We define a binary image with values on that box.
+ image2d<bool> img(b);
+
+ // With an array of Booleans (1 means true, 0 means false)...
+ bool vals[] = { 1, 0, 0,
+ 0, 1, 0,
+ 0, 1, 1 };
+ // ...the debug::fill routine allows for manually initializing
+ // image data:
+ debug::fill(inplace(img), vals);
+ std::cout << "img = " << std::endl;
+ debug::println(img);
+ // img =
+ // | - -
+ // - | -
+ // - | |
+
+ image2d<int> ima(b); // An image of integers with the same
+ box2d::piter p(ima.points()); // domain as img...
+ int i = 0;
+ for_all(p)
+ ima(p) = i++; // ...and manually filled with values.
+
+ std::cout << "ima = " << std::endl;
+ debug::println(ima);
+ // ima =
+ // 0 1 2
+ // 3 4 5
+ // 6 7 8
+
+
+
+ // The algorithm defined at the end of this file is very close to
+ // the one of the tour former file. The major difference is that it
+ // does not rely on a window but on a neighborhood.
+
+ // In image processing, we usually say that "an image has a given
+ // neighborhood" or that "we associate/embed a neighborhood to/into
+ // an image". In Olena, that is really the case: the image can
+ // "have" a neighborhood, meaning that a neighborhood can be added
+ // to an image in order to obtain an "image with a neighborhood".
+
+ // Joining an image with a neighborhood is performed with the
+ // operator '+':
+ algo(ima + c4); // c4 is the 2D neighborhood corresponding to
+ // 4-connectivity; such as many classical
+ // neighborhoods it is provided by Olena.
+ // The result is given below.
+
+ // ---input:
+ // 0 1 2
+ // 1 2 3
+ // 2 3 4
+ // ---output:
+ // 0: 1 1
+ // 1: 0 2 2
+ // 2: 1 3
+ // 1: 0 2 2
+ // 2: 1 1 3 3
+ // 3: 2 2 4
+ // 2: 1 3
+ // 3: 2 2 4
+ // 4: 3 3
+
+ // That was expectable...
+
+
+ // And now for a little test: what is the result of this code?
+ {
+ image2d<int> test(ima.points());
+ level::fill(inplace(test), ima);
+ (test + c4).at(1, 1) = 9;
+ debug::println(test);
+ }
+ // and can you tell why?
+ // The answers are given in the file tour3-test.txt
+
+
+ // Now let us start experimenting the genericity of Olena!
+
+
+ // First, imagine that you want to restrict the domain of ima to a
+ // subset of points, a region or whatever. For instance, the
+ // chessboard function takes a point as argument and returns a
+ // Boolean so it is like a predicate. We can want to consider only
+ // the points of ima "such as" this predicate is verified. The
+ // "such as" mathematical symbol is '|' so let's rock:
+
+ algo((ima | chessboard) + c8);
+ // gives:
+
+ // ---input:
+ // 1
+ // 3 5
+ // 7
+ // ---output:
+ // 1: 3 5
+ // 3: 1 7
+ // 5: 1 7
+ // 7: 3 5
+
+ // where the blanks in printing the input image denote that the
+ // corresponding points do NOT belong to the image domain.
+
+ // Another similar example is based on the binary image created at
+ // the beginning of this tour:
+ algo((ima | img) + c8);
+ // which gives:
+
+ // ---input:
+ // 0
+ // 4
+ // 7 8
+ // ---output:
+ // 0: 4
+ // 4: 0 7 8
+ // 7: 4 8
+ // 8: 4 7
+
+
+
+ // Second, imagine that you want your initial image to get the
+ // geodesy of a torus, that is, a 2D image wrapped on a torus.
+ // Points located at the image boundary have neighbors; for
+ // instance, the point denoted by the 'x' cross below has for
+ // 4-connectivity neighbors: t, l, r, and b (respectively for top,
+ // left, right, and bottom):
+
+ // b o o o
+ // o o o o
+ // t o o o
+ // x r o l
+
+ // Let us try:
+ algo(torus(ima) + c8);
+ // gives:
+
+ // ---input:
+ // 0 1 2
+ // 3 4 5
+ // 6 7 8
+ // ---output:
+ // 0: 8 6 7 2 1 5 3 4
+ // 1: 6 7 8 0 2 3 4 5
+ // 2: 7 8 6 1 0 4 5 3
+ // 3: 2 0 1 5 4 8 6 7
+ // 4: 0 1 2 3 5 6 7 8
+ // 5: 1 2 0 4 3 7 8 6
+ // 6: 5 3 4 8 7 2 0 1
+ // 7: 3 4 5 6 8 0 1 2
+ // 8: 4 5 3 7 6 1 2 0
+
+
+
+ // We can have both the torus geodesy and a sub-domain:
+
+ algo(torus(ima | chessboard) + c8);
+ algo(torus(ima | img) + c8);
+
+ // which respectively give:
+
+ // ---input:
+ // 1
+ // 3 5
+ // 7
+ // ---output:
+ // 1: 7 3 5
+ // 3: 1 5 7
+ // 5: 1 3 7
+ // 7: 3 5 1
+
+ // and:
+
+ // ---input:
+ // 0
+ // 4
+ // 7 8
+ // ---output:
+ // 0: 8 7 4
+ // 4: 0 7 8
+ // 7: 4 8 0
+ // 8: 4 7 0
+
+
+
+
+ // Last, the way a predicate is defined can also rely on some image
+ // values. For that the user can on the fly provide an expression
+ // built with the "pw_value" facility, where "pw_" means
+ // "point-wise" for short:
+
+ algo((ima | (pw_value(ima) < 4)) + c4);
+
+ // In this example, "pw_value(ima)" is the function that represents
+ // the point-wise value of the 'ima' image, that is, the function
+ // "p -> ima(p)". This naturally leads to:
+
+ // ---input:
+ // 0 1 2
+ // 3
+ //
+ // ---output:
+ // 0: 1 3
+ // 1: 0 2
+ // 2: 1
+ // 3: 0
+
+
+
+ // From those examples, you should realize that:
+
+
+ // +-----------------------------------------------------------+
+ // | |
+ // | The level of "genericity" provided by Olena is rather |
+ // | high; it means: |
+ // | |
+ // | - taking the image dimension you work on; |
+ // | |
+ // | - having the type of pixel values you need; |
+ // | |
+ // | - choosing the neighborhood you want; |
+ // | |
+ // | - changing the geodesy if you need it; |
+ // | |
+ // | - being able to restrict the image domain; |
+ // | |
+ // | - and many other features that are addressed further |
+ // | in the tour... |
+ // | |
+ // +-----------------------------------------------------------+
+
+}
+
+
+
+
+
+// The algorithm 'algo':
+
+template <typename I>
+void algo(const I& img)
+{
+ std::cout << "---input:" << std::endl;
+ oln::debug::print(img);
+ std::cout << "---output:" << std::endl;
+
+ oln_piter(I) p(img.points()); // p iterates on img points
+ oln_niter(I) n(img, p); // n iterates in img on neighbors of p
+
+ for_all(p)
+ {
+ std::cout << oln::debug::format(img(p))
+ << ':';
+ for_all(n)
+ std::cout << ' '
+ << oln::debug::format(img(n));
+ std::cout << std::endl;
+ }
+
+ std::cout << std::endl;
+}
Index: doc/oldies/2008__tour1_extra.cc
--- doc/oldies/2008__tour1_extra.cc (revision 0)
+++ doc/oldies/2008__tour1_extra.cc (revision 0)
@@ -0,0 +1,214 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+// File: tour1_extra.cc.
+
+#include <oln/core/1d/image1d.hh>
+#include <oln/arith/plus.hh>
+#include <oln/debug/println.hh>
+
+
+
+int main()
+{
+ using namespace oln;
+
+
+ // Let us take a few examples to illustrate how images and data are
+ // managed. In these examples, we will use the notion of "block of
+ // instructions" from the C/C++ languages: "{" ... "}".
+
+
+
+
+ // Example 1:
+
+ { // A new block starts here.
+
+ image1d<float> local_ima(1000);
+ // A non-empty image is created; a memory buffer is automatically
+ // allocated to store image data. Some code using 'local_ima' can
+ // be inserted here...
+
+ } // The block ends and 'local_ima' is not more accessible.
+
+ // At the end of the block, since the user cannot use 'local_ima'
+ // anymore, the memory is automatically deallocated.
+
+
+
+
+ // Example 2:
+
+ image1d<float> ima; // An empty image---a variable.
+
+ { // A new block.
+
+ image1d<float> local_ima(1000); // A non-empty image.
+ // Some work is performed with 'local_ima' here.
+ // ...
+ ima = local_ima; // Last, we state that ima IS local_ima.
+
+ } // End of the block: 'local_ima' is no more accessible.
+
+ assert(not ima.is_empty()); // We test that 'ima' is no more empty.
+
+ // Since we state that "ima IS local_ima" and since 'ima' is still
+ // accessible by the user, the contents of 'local_ima' is preserved.
+
+ // Conversely to the example 1, the memory allocated for 'local_ima'
+ // is thus NOT deallocated: the data of 'local_ima' is "transfered"
+ // to 'ima'. There is NO data "copy" involved during this transfer
+ // so it is fast and it saves memory.
+
+
+
+
+ // Example 3:
+
+ {
+ image1d<int> orig(5); // An original image.
+ for (int i = 0; i < 5; ++i)
+ orig.at(i) = i;
+ debug::println(orig);
+ // 0 1 2 3 4
+
+ image1d<int> ima = orig; // 'ima' is 'orig'.
+ ima = ima + ima; // Point-wise sum of ima and itself.
+ debug::println(ima);
+ // 0 2 4 6 8
+
+ debug::println(orig);
+ // 0 1 2 3 4
+ }
+
+ // To explain this result, let us detail the point-wise sum line.
+ // The assignment "ima = ima + ima" is a two-step process: first
+ // "ima + ima" is computed, then the assignment is performed. This
+ // line can be rewritten as:
+
+ // image1d<int> anon = ima + ima; // line (a)
+ // ima = anon; // line (b)
+
+ // where 'anon' is the "anonymous" result of the sum. We can see
+ // that 'ima' is used in line (a) to compute a new image, namely
+ // 'anon'. At that precise line, 'ima' still designates 'orig'. At
+ // line (b) the definition of 'ima' changes: 'ima' was designating
+ // 'orig', now it designates 'anon', that is, the sum result.
+ // Eventually the data of 'orig' have never changed since it has
+ // been initialized.
+
+ // In this example, two images with effective data have been
+ // created: the sum result, which is accessible through 'ima', and
+ // 'orig'.
+
+ // The same explanation in pictures. When the sum "ima + ima" is
+ // computed, the images and their data look like:
+ //
+ // +-----------+
+ // orig --> | 0 1 2 3 4 |
+ // +-----------+
+ // ^
+ // ima ______|
+ //
+ // +-----------+
+ // anon --> | 0 2 4 6 8 |
+ // +-----------+
+ //
+ // Then the assignment modifies this scheme into:
+ //
+ // +-----------+
+ // orig --> | 0 1 2 3 4 |
+ // +-----------+
+ // ima ______
+ // |
+ // v
+ // +-----------+
+ // anon --> | 0 2 4 6 8 |
+ // +-----------+
+ //
+ // and the temporary 'anon' disappears.
+
+
+
+
+
+ // Example 4:
+
+ {
+ image1d<int> ima(5);
+ for (int i = 0; i < 5; ++i)
+ ima.at(i) = i;
+ debug::println(ima);
+ // 0 1 2 3 4
+
+ ima = ima + ima;
+ debug::println(ima);
+ // 0 2 4 6 8
+ }
+
+ // Let us re-write the assignment line:
+
+ // image1d<int> anon = ima + ima; // line (a)
+ // ima = anon; // line (b)
+
+ // A new image, 'anon', is created to store the sum result; this
+ // image is just like a temporary object since it is anonymous. In
+ // line (a) the definition of 'ima' changes: it was the original
+ // image with its data being "0 1 2 3 4" and it now designates the
+ // sum result. The original data becomes inaccessible by the user
+ // so it is automatically deallocated.
+
+ // The same explanation In pictures. After the sum is computed, we
+ // have:
+ // +-----------+
+ // ima ---> | 0 1 2 3 4 |
+ // +-----------+
+ //
+ // +-----------+
+ // anon --> | 0 2 4 6 8 |
+ // +-----------+
+ //
+ // and the assignment of 'ima' leads to:
+ //
+ // +-----------+
+ // ima | 0 1 2 3 4 |
+ // | +-----------+
+ // |_________
+ // |
+ // v
+ // +-----------+
+ // anon --> | 0 2 4 6 8 |
+ // +-----------+
+ //
+ // so the original data, unreachable, are deallocated and the
+ // temporary 'anon' disappears; we end up with:
+ //
+ // +-----------+
+ // ima ---> | 0 2 4 6 8 |
+ // +-----------+
+}
Index: doc/oldies/2006__tour_1.txt
--- doc/oldies/2006__tour_1.txt (revision 0)
+++ doc/oldies/2006__tour_1.txt (revision 0)
@@ -0,0 +1,671 @@
+ -*- outline -*-
+
+
+* primary image types
+
+
+** image2d<T>
+
+*** definition
+
+rectangular 2D image with a virtual border
+
+*** parameter
+
+T: value type
+
+*** related types
+
+image1d<T> and image3d<T> are similarly constructed
+
+*** sample code
+
+**** step 1
+
+char[] values = { 'a', 'b', 'c',
+ 'd', 'e', 'f' };
+image2d<char> ima(2, 3);
+level::fill(ima, values);
+debug::print(ima.bbox());
+
+// [(0, 0)..(1, 2)]
+
+debug::print(ima);
+
+// 0 1 2
+// - - -
+// 0| a b c
+// 1| d e f
+
+ima.set_name("ima");
+point2d p(0, 1);
+
+std::cout << ima(p) << std::endl;
+// b
+
+debug::print(ima, p);
+// ima.at(0, 1) == b
+
+ima.at(0, 1) = 'B';
+debug::print(ima, p);
+// ima.at(0, 1) == B
+
+
+bbox2d bb = set(from(1,5), to(2,7));
+image2d<char> ima2(bb);
+ima2.set_name("ima2");
+level::fill(ima2, values);
+debug::print(ima2);
+
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+**** step 2
+
+ima2.set_border_thickness(1);
+border::fill(ima2, '.');
+
+debug::print(ima2.bbox());
+// [(1, 5)..(2, 7)]
+
+debug::print(ima2);
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+debug::print(ima2.large_bbox());
+// [(0, 4)..(3, 8)]
+
+debug::print_large(ima2);
+// 4 5 6 7 8
+// - - - - -
+// 0| . . . . .
+// 1| . a b c .
+// 2| . d e f .
+// 3| . . . . .
+
+ima2.at( 0, 6) = 'x'; // OK
+ima2.at(-1, 6) = '?'; // error: out of bounds
+
+debug::print_large(ima2);
+// 4 5 6 7 8
+// - - - - -
+// 0| . . x . .
+// 1| . a b c .
+// 2| . d e f .
+// 3| . . . . .
+
+debug::print(ima2);
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+std::cout << ima2.npoints() << std::endl;
+// 6
+
+std::cout << ima2.bbox().npoints() << std::endl;
+// 6
+
+std::cout << ima2.large_bbox().npoints() << std::endl;
+// 20
+
+std::cout << ima2.n_value_cells() << std::endl;
+// 20
+
+**** step 3
+
+a virtual border (at the outer boundary of the domain) is provided so
+that there is no need for special code to handle pixels at the limit
+of the domain.
+
+int[] values = { 0, 1, 1, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0 };
+image2d<bool> ima(from(1,1), to(4,4));
+level::fill(ima, values);
+debug::print(ima);
+// 1 2 3 4 5
+// - - - - -
+// 1| 0 1 1 1 0
+// 2| 0 1 1 1 0
+// 3| 0 1 1 1 0
+// 4| 0 0 0 0 0
+
+image2d<bool> ima2 = morpho::e_erosion(ima + c4);
+debug::print(ima2);
+// 1 2 3 4 5
+// - - - - -
+// 1| 0 0 1 0 0
+// 2| 0 0 1 0 0
+// 3| 0 0 0 0 0
+// 4| 0 0 0 0 0
+
+actually, after level::fill we have:
+
+// 0 1 2 3 4 5 6
+// - - - - - - -
+// 0| ? ? ? ? ? ? ?
+// 1| ? 0 1 1 1 0 ?
+// 2| ? 0 1 1 1 0 ?
+// 3| ? 0 1 1 1 0 ?
+// 4| ? 0 0 0 0 0 ?
+// 5| ? ? ? ? ? ? ?
+
+in morpho::e_erosion, the border is initialized:
+// 0 1 2 3 4 5 6
+// - - - - - - -
+// 0| 1 1 1 1 1 1 1
+// 1| 1 0 1 1 1 0 1
+// 2| 1 0 1 1 1 0 1
+// 3| 1 0 1 1 1 0 1
+// 4| 1 0 0 0 0 0 1
+// 5| 1 1 1 1 1 1 1
+
+so we get the proper result:
+// 0 1 2 3 4 5 6
+// - - - - - - -
+// 0| 1 1 1 1 1 1 1
+// 1| 1 0 0 1 0 0 1
+// 2| 1 0 0 1 0 0 1
+// 3| 1 0 0 0 0 0 1
+// 4| 1 0 0 0 0 0 1
+// 5| 1 1 1 1 1 1 1
+
+
+
+
+** image_2dhex<T>
+
+*** definition
+
+image defined on a 2D triangular grid (hexagonal pixels)
+it is equipped with a virtual border
+
+*** parameter
+
+T: value type
+
+*** sample code
+
+FIXME
+
+
+
+** igraph<T>
+
+FIXME: ...
+
+
+
+** image2d_without_border<T>
+
+*** definition
+
+same type as image2d<T> but without border
+
+*** parameter
+
+T: value type
+
+*** sample code
+
+**** step 1
+
+image2d<char> ima = set(from(0,0), to(0,0));
+ima.at( 0, 0) = 'a'; // OK
+ima.at(-1, 0) = 'a': // error
+
+std::cout << ima.npoints() << std::endl;
+// 1
+std::cout << ima.n_value_cells() << std::endl;
+// 1
+
+**** step 2
+
+int[] values = { 0, 1, 1, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0 };
+image2d_without_border<bool> ima(from(1,1), to(4,4));
+level::fill(ima, values);
+debug::print(ima);
+// 1 2 3 4 5
+// - - - - -
+// 1| 0 1 1 1 0
+// 2| 0 1 1 1 0
+// 3| 0 1 1 1 0
+// 4| 0 0 0 0 0
+
+image2d<bool> ima2 = morpho::e_erosion(ima + c4);
+debug::print(ima2);
+// 1 2 3 4 5
+// - - - - -
+// 1| 0 0 0 0 0
+// 2| 0 0 1 0 0
+// 3| 0 0 0 0 0
+// 4| 0 0 0 0 0
+
+
+
+** one_value_image<S, T>
+
+*** definition
+
+image defined by a point-set and a (single) value
+this image has the same value for all pixels
+
+*** parameters
+
+S: point set type
+T: value type
+
+*** sample code
+
+bbox2d bb = set(from(1,4), to(2,6));
+one_value_image<bbox2d, char> ima(bb, 'a');
+debug::print(ima);
+
+// 4 5 6
+// - - -
+// 1| a a a
+// 2| a a a
+
+ima.value() = 'b';
+debug::print(ima);
+
+// 4 5 6
+// - - -
+// 1| b b b
+// 2| b b b
+
+std::cout << ima.npoints() << std::endl;
+// 6
+
+std::cout << ima.nvalues() << std::endl;
+// 1
+
+std::cout << ima.n_value_cells() << std::endl;
+// 1
+
+ima.change_value('b', 'c');
+// 4 5 6
+// - - -
+// 1| c c c
+// 2| c c c
+
+std::cout << ima.at(1, 5) << std::endl;
+// c
+
+ima.at(1, 5) = 'd'; // error
+
+ima.change_value('C', ' '); // error at run-time
+ // 'C' is not a value for this image
+
+
+
+** image_p2v<S, F>
+
+*** definition
+
+image defined by a point set and a function "point -> value"
+
+*** parameters
+
+S: point set type
+F: function type
+
+*** sample code
+
+**** step 1
+
+bool chess(point2d p)
+{
+ return (p.row() + p.col()) % 2;
+}
+
+bbox2d bb(from(0,0), to(3,3));
+image2d<bool> ima = image(bb, chess);
+debug::print(ima);
+// 0 1 2 3
+// - - - -
+// 0| 0 1 0 1
+// 1| 1 0 1 0
+// 2| 0 1 0 1
+// 3| 1 0 1 0
+
+or:
+
+image_p2v<bbox2d, bool(*)(point2d)> ima(bb, chess);
+
+std::cout << ima.at(2, 3) << std::endl; // OK: image readable
+// 1
+
+bool val;
+ima.at(2, 3) = val; // error: image not writable
+
+**** step 2
+
+Likewise but with a function-object:
+
+struct chess_t
+{
+ bool operator()(point2d p) const
+ {
+ return (p.row() + p.col()) % 2;
+ }
+};
+
+bbox2d bb(from(0,0), to(3,3));
+image_p2v<bbox2d, chess_t> ima(bb);
+debug::print(ima);
+// 0 1 2 3
+// - - - -
+// 0| 0 1 0 1
+// 1| 1 0 1 0
+// 2| 0 1 0 1
+// 3| 1 0 1 0
+
+**** step 3
+
+struct chess_t : oln::abstract::function_p2v<chess_t>
+{
+ bool value(point2d p) const
+ {
+ return (p.row() + p.col()) % 2;
+ }
+};
+static chess_t chess;
+
+// ...
+
+debug::options opt;
+opt.true_symbol('*').false_symbol(' ');
+debug::print( chess(from(0,0), to(3,3)), opt );
+// 0 1 2 3
+// - - - -
+// 0| * *
+// 1| * *
+// 2| * *
+// 3| * *
+
+
+
+** rle_image<P, T>
+
+*** definition
+
+image with run-length encoding
+
+*** parameters
+
+P: point type
+T: value type
+
+*** sample code
+
+**** step 1
+
+rle_image<point2d, int> ima;
+ima.
+ set_name("ima").
+ insert(from(2,1), len(3), val(6)).
+ insert(from(1,2), len(2), val(8));
+
+debug::print(ima);
+// { ([(1, 2)..(1, 3)], 8), ([(2, 1)..(2, 3)], 6) }
+
+std::cout << ima.n_value_cells() << std::endl;
+// 2
+
+debug::options opt;
+opt.no_symbol('x');
+debug::print( imagine(ima), opt );
+// 1 2 3
+// - - -
+// 1| x 8 8
+// 2| 6 6 6
+
+std::cout << ima.npoints() << std::endl;
+// 5
+
+image2d<int> ima2(from(1,1), to(2,3), val(4));
+debug::print(ima2);
+// 1 2 3
+// - - -
+// 1| 4 4 4
+// 2| 4 4 4
+
+level::assign(ima2, ima);
+debug::print(ima2);
+// 1 2 3
+// - - -
+// 1| 4 8 8
+// 2| 6 6 6
+
+**** step 2
+
+std::cout << ima.nrls() << std::endl;
+// 2
+
+debug::print(ima.rl(0));
+// ([(1, 2)..(1, 3)], 8)
+
+debug::print(ima.rl(1));
+// ([(2, 1)..(2, 3)], 6)
+
+std::cout << ima.rl(1).first_p() << std::endl;
+// (2, 1)
+
+std::cout << ima.rl(1).last_p() << std::endl;
+// (2, 3)
+
+std::cout << ima.rl(1).value() << std::endl;
+// 6
+
+std::cout << ima.rl(1).npoints() << std::endl;
+// 3
+
+FIXME:
+std::cout << ima.rl(1).point(0) << ' '
+ << ima.rl(1).point(1) << ' '
+ << ima.rl_point(1, 2) << std::endl;
+// (2, 1) (2, 2) (2, 3)
+
+**** step 3
+
+// remember that for ima, in the rl #1, the point #1 is (2, 2)
+
+point2d p(2, 2);
+std::cout << ima(p) << std::endl; // KO: does not compile
+
+std::cout << ima.rl_point(1, 1) << std::endl;
+// (2, 2)
+
+rle_psite<point2d> p_(1, 1);
+std::cout << ima(p_) << std::endl; // OK
+// 6
+
+debug::print(ima2);
+// 1 2 3
+// - - -
+// 1| 4 8 8
+// 2| 6 6 6
+rle_image<point2d, int> ima3 = rlencode(ima2);
+debug::print(ima3);
+// { ([(1, 1)..(1, 1)], 4), ([(1, 2)..(1, 3)], 8), ([(2, 1)..(2, 3)], 6) }
+level::in_place::inc(ima3);
+
+
+debug::print(ima3);
+// { ([(1, 1)..(1, 1)], 5), ([(1, 2)..(1, 3)], 9), ([(2, 1)..(2, 3)], 7) }
+
+debug::print( imagine(ima3) );
+// 1 2 3
+// - - -
+// 1| 5 9 9
+// 2| 7 7 7
+
+
+debug::print(ima);
+// { ([(1, 2)..(1, 3)], 8), ([(2, 1)..(2, 3)], 6) }
+
+debug::print( imagine(ima), opt );
+// 1 2 3
+// - - -
+// 1| x 8 8
+// 2| 6 6 6
+
+std::cout << ima.rl_point(1, 1) << std::endl;
+// (2, 2)
+
+
+rl_psite<point2d> p3(ima3, 1, 1); // p3 is not bound to ima3 but to its topology
+
+std::cout << ima3.rl_point(1, 1) << std::endl;
+// (1, 3)
+
+std::cout << ima3(p3) << std::endl; // OK
+// 9
+
+std::cout << ima(p3) << std::endl; // error at run-time
+
+// explanation:
+// 1) p3, when created, clearly designates the 2D point (1, 3) through
+// the couple (rl #1, pt #1)
+// 2) when writing "ima(p3)" we want to access the value of "ima" at point (1, 3)
+// 3) "ima" knows that the couple (rl #1, pt #1) does not designate the point (1, 3)
+// but (2, 2) instead
+// 4) this error is then identified at run-time
+
+
+ima3.remove_rl(0);
+
+debug::print(ima3);
+// { ([(1, 2)..(1, 3)], 9), ([(2, 1)..(2, 3)], 7) }
+
+debug::print( imagine(ima3), opt );
+// 1 2 3
+// - - -
+// 1| x 9 9
+// 2| 7 7 7
+
+rl_psite<point2d> p3_(ima3, 1, 1);
+std::cout << ima3.rl_point(1, 1) << std::endl; // now same as ima.rl_point(1, 1)
+// (2, 2)
+
+std::cout << ima(p3_) << std::endl; // now OK
+// 7
+
+
+
+
+** sparse_image<P, T>
+
+*** definition
+
+FIXME: HERE
+
+
+*** parameter
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+std::vector of couples (p_start, std::vector<T>)
+
+
+** image_vec<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+std::vector< std::pair<P, T> >
+
+
+** image_map<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+using std::map<P, T>
+
+*** related type
+
+slow::image_map<P, T>
+
+
+** slow::image_bbmap<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+point-wise accessible and mutable
+not value-wise accessible
+bounding-boxed
+
+*** data storage
+
+some values are set in a std::map<P, T>
+when not set, a default value is provided by an attribute
+
+*** related type
+
+image_map<P, T>
+
+
+
+** Morpher types
+
+** FIXME
+
+do (really!) nothing when writing at p when outside the image domain
+error when reading at p when outside the image domain
+
+** FIXME
+
+add a default value when p is outside the image domain
+
+** sequence<I>
+
+FIXME: ...
+
+
+
+Local Variables:
+mode: outline
+ispell-local-dictionary: "american"
+End:
Index: doc/oldies/2006__tour_2.txt
--- doc/oldies/2006__tour_2.txt (revision 0)
+++ doc/oldies/2006__tour_2.txt (revision 0)
@@ -0,0 +1,404 @@
+ -*- outline -*-
+
+* primary image types
+
+** image2d<T>
+
+*** parameter
+
+T: value type
+
+*** main features
+
+- debase type for a rectangular 2D image
+
+- a virtual border (at the outer boundary of the domain) is provided
+ so that there is no need for special code to handle pixels at the
+ limit of the domain.
+
+*** sample code
+
+int[] values = { 'a', 'b', 'c',
+ 'd', 'e', 'f' };
+image2d<char> ima(2, 3);
+level::fill(ima, values);
+debug::print(ima.bbox());
+
+// [(0, 0)..(1, 2)]
+
+debug::print(ima);
+
+// 0 1 2
+// - - -
+// 0| a b c
+// 1| d e f
+
+ima.set_name("ima");
+point2d p(0, 1);
+
+std::cout << ima(p) << std::endl;
+// b
+
+debug::print(ima, p);
+// ima.at(0, 1) == b
+
+ima.at(0, 1) = 'B';
+debug::print(ima, p);
+// ima.at(0, 1) == B
+
+
+
+bbox2d bb = set(from(1,5), to(2,7));
+image2d<char> ima2(bb);
+ima2.set_name("ima2");
+level::fill(ima2, values);
+debug::print(ima2);
+
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+
+ima2.border() = 1;
+border::fill(ima2, '.');
+
+debug::print(ima2.bbox());
+// [(1, 5)..(2, 7)]
+
+debug::print(ima2);
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+debug::print(ima2.large_bbox());
+// [(0, 4)..(3, 8)]
+
+debug::print_large(ima2);
+// 4 5 6 7 8
+// - - - - -
+// 0| . . . . .
+// 1| . a b c .
+// 2| . d e f .
+// 3| . . . . .
+
+ima2.at( 0, 6) = 'x'; // OK
+ima2.at(-1, 6) = '?'; // error: out of bounds
+
+debug::print_large(ima2);
+// 4 5 6 7 8
+// - - - - -
+// 0| . . x . .
+// 1| . a b c .
+// 2| . d e f .
+// 3| . . . . .
+
+debug::print(ima2);
+// 5 6 7
+// - - -
+// 1| a b c
+// 2| d e f
+
+std::cout << ima2.npoints() << std::endl;
+// 6
+
+std::cout << ima2.bbox().npoints() << std::endl;
+// 6
+
+std::cout << ima2.large_bbox().npoints() << std::endl;
+// 20
+
+std::cout << ima2.n_memory_cells() << std::endl;
+// 20
+
+
+FIXME: play with point2d and dpoint2d...
+
+
+*** related types
+
+image1d<T> and image3d<T> are similarly constructed
+
+
+*** level 2
+
+*** main features
+
+has a virtual border (same thickness for every axis)
+point-wise accessible and mutable
+not value-wise accessible
+
+*** data storage
+
+relies on array2d<T>
+
+*** to-do
+
+should rely on array2d< T::storage >
+add unambiguous ctors
+
+*** ideas
+
+point2d p(0, 1);
+point2d p = set(row(0), col(1));
+
+bbox2d bb = set(from(1,5), to(2,7));
+bbox2d bb = set(minrow(1), maxrow(2), mincol(5), maxcol(7));
+bbox2d bb = set(minrow(1), mincol(5), nrows(2), ncols(3));
+bbox2d bb = set(pmin(1,5), nrows(2), ncols(3));
+bbox2d bb = set(pmin(1,5), size(2,3));
+
+
+*** image_2dhex<T>
+
+on a 2D triangular grid (hexagonal pixels)
+FIXME: ...
+
+
+*** igraph<T>
+
+FIXME: ...
+
+
+** image2d_without_border<T>
+
+*** level 1
+
+*** main features
+
+same type as image2d<T> but without border
+
+*** sample code
+
+image2d<char> ima = set(from(0,0), to(0,0));
+ima.at( 0, 0) = 'a'; // OK
+ima.at(-1, 0) = 'a': // error
+
+std::cout << ima.npoints() << std::endl;
+// 1
+std::cout << ima.n_memory_cells() << std::endl;
+// 1
+
+** level 2
+
+*** status
+
+to-do
+
+*** main features
+
+same as image2d<T> but without virtual border
+
+*** data storage
+
+relies on array2d<T>
+
+
+
+** one_value_image<S, T>
+
+*** level 1
+
+*** main features
+
+image defined by a point-set and a (single) value
+this image has the same value for all pixels
+
+*** sample code
+
+bbox2d bb = set(from(1,4), to(2,6));
+one_value_image<bbox2d, char> ima(bb, 'a');
+debug::print(ima);
+
+// 4 5 6
+// - - -
+// 1| a a a
+// 2| a a a
+
+ima.value() = 'b';
+debug::print(ima);
+
+// 4 5 6
+// - - -
+// 1| b b b
+// 2| b b b
+
+std::cout << ima.npoints() << std::endl;
+// 6
+
+std::cout << ima.n_memory_cells() << std::endl;
+// 1
+
+ima.change_value('b', 'c');
+// 4 5 6
+// - - -
+// 1| c c c
+// 2| c c c
+
+std::cout << ima.at(1, 5) << std::endl;
+// c
+
+ima.at(1, 5) = 'd'; // error
+
+
+*** level 2
+
+*** parameters
+
+S: point set type
+T: type of the value
+
+*** main features
+
+point-wise accessible but not mutable
+value-wise accessible and mutable
+
+*** data storage
+
+a single attribute: the unique value
+
+
+** image_p2v<S, F>
+
+*** parameters
+
+S: point set type
+F: function point-site -> value
+
+*** main features
+
+point-wise accessible but not mutable
+not value-wise accessible
+
+*** data storage
+
+combines the point set and the function to produce values
+on the fly
+
+
+** rle_image<P, T>
+
+*** parameter
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+std::vector of triplets (p_start, length, value)
+
+*** related type
+
+sparse_image<T>
+
+
+** sparse_image<P, T>
+
+*** parameter
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+std::vector of couples (p_start, std::vector<T>)
+
+*** related type
+
+rle_image<P, T>
+
+
+** image_vec<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+std::vector< std::pair<P, T> >
+
+
+** image_map<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+not point-wise accessible
+not value-wise accessible
+
+*** data storage
+
+using std::map<P, T>
+
+*** related type
+
+slow::image_map<P, T>
+
+
+** slow::image_bbmap<P, T>
+
+*** parameters
+
+P: point type
+T: value type
+
+*** main features
+
+point-wise accessible and mutable
+not value-wise accessible
+bounding-boxed
+
+*** data storage
+
+some values are set in a std::map<P, T>
+when not set, a default value is provided by an attribute
+
+*** related type
+
+image_map<P, T>
+
+
+
+** Morpher types
+
+** FIXME
+
+do (really!) nothing when writing at p when outside the image domain
+error when reading at p when outside the image domain
+
+** FIXME
+
+add a default value when p is outside the image domain
+
+** sequence<I>
+
+FIXME: ...
+
+
+
+Local Variables:
+mode: outline
+ispell-local-dictionary: "american"
+End:
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2008-09-02 Matthieu Garrigues <garrigues(a)lrde.epita.fr>
* geraud/fllt/fllt.svg.7.hh: Add comments to the working version of
FLLT.
---
fllt.svg.7.hh | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 85 insertions(+), 11 deletions(-)
Index: trunk/milena/sandbox/geraud/fllt/fllt.svg.7.hh
===================================================================
--- trunk/milena/sandbox/geraud/fllt/fllt.svg.7.hh (revision 2163)
+++ trunk/milena/sandbox/geraud/fllt/fllt.svg.7.hh (revision 2164)
@@ -331,9 +331,6 @@
++label;
- // if (holes.size() == 2)
- // std::cout << holes[0] << holes[1] << std::endl;
- // std::cout << " <<<<<<<exiting blob." << std::endl;
}
template <typename P, typename V>
@@ -393,7 +390,8 @@
}
}
- // LOWER LEVEL SET : region = c4, border = c8
+ // LOWER LEVEL SET information to compute the max tree.
+ // -> region = c4, border = c8
template <typename V>
struct lower
{
@@ -421,7 +419,8 @@
};
- // UPPER LEVEL SET : region = c8, border = c4
+ // UPPER LEVEL SET information to compute the max tree.
+ // -> region = c8, border = c4
template <typename V>
struct upper
{
@@ -445,6 +444,14 @@
static const neighb2d& reg_nbh() { return c8(); }
};
+ /*! Fast computation of a min/max tree.
+ *
+ * \param[in] input_ An input image.
+ * \param[out] smallest_shapes We stock in this image, for each point, a pointer
+ * to the smallest shape containing it.
+ * \return The min/max tree built.
+ *
+ */
template <typename I, typename Set>
fllt_tree(mln_point(I), mln_value(I))&
level_set(const Image<I>& input_,
@@ -560,7 +567,7 @@
deja_vu(x) = in_N;
}
}
- // gN = min u(x) for all x in N
+ // gN <- min u(x) for all x in N
update_gN(N, gN, Set());
// FIXME: update the number of CC of the border of R
@@ -609,7 +616,6 @@
// c)
else
{
- // FIXME: IDEA: this change might be performed while R is constructed(?)
n_step_4c++;
mln_piter(I) r(N_box);
for_all(r)
@@ -627,6 +633,15 @@
return *new tree_type(current_cc);
}
+ /*! Get the hole of a shape which contains a given point.
+ *
+ * \param[in] node a shape.
+ * \param[in] p a point.
+ * \param[in] other_reg The map which associate a point with its smallest shape
+ * of the oposite tree.
+ * \return true if A is included in B.
+ *
+ */
// F is the set in which we get the node.
template <typename P, typename V, typename F>
fllt_node(P, V)*
@@ -636,6 +651,7 @@
{
fllt_node(P, V)* s = other_reg(p);
mln_assertion(s);
+ // Go up the tree.
while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value))
{
mln_assertion(s);
@@ -649,6 +665,14 @@
return s;
}
+ /*! Test the inclusion of two shapes of the same tree
+ *
+ * \param[in] A a shape.
+ * \param[in] B a shape.
+ * \return true if A is included in B.
+ *
+ * \pre The shapes have to come from the same tree.
+ */
template <typename P, typename V>
bool shape_is_included(fllt_node(P, V)* A,
fllt_node(P, V)* B)
@@ -656,6 +680,17 @@
return A->parent() == B || A == B;
}
+ /*! Associated the points of the holes of the min/max tree's shapes.
+ *
+ * \param[in] lower_tree The min tree.
+ * \param[in] upper_tree The max tree.
+ * \param[in] low_reg The map which associate a point with its smallest shape
+ * of the min tree.
+ * \param[in] upp_reg The map which associate a point with its smallest shape
+ * of the max tree.
+ * \return The merged tree.
+ *
+ */
template <typename P, typename V>
void find_all_holes(fllt_tree(P, V)& lower_tree,
fllt_tree(P, V)& upper_tree,
@@ -665,6 +700,7 @@
typedef p_array<P> arr_t;
typedef fllt_node(P, V) node_type;
+ // Get the holes of the min tree
{
fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
for_all(node_)
@@ -676,6 +712,7 @@
}
}
+ // Get the holes of the max tree
{
fllt_branch_iter_ind(P, V) node_(upper_tree.main_branch());
for_all(node_)
@@ -688,6 +725,17 @@
}
}
+ /*! Merge the Min and the max tree.
+ *
+ * \param[in] lower_tree The min tree.
+ * \param[in] upper_tree The max tree.
+ * \param[in] low_reg The map which associate a point with its smallest shape
+ * of the min tree.
+ * \param[in] upp_reg The map which associate a point with its smallest shape
+ * of the max tree.
+ * \return The merged tree.
+ *
+ */
template <typename I>
fllt_tree(mln_point(I), mln_value(I))
merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree,
@@ -706,17 +754,24 @@
typedef p_array<P> arr_t;
+ // Here, a hole of a shape of the max or min tree is represented
+ // by a point belonging to this hole. We need to associate each of
+ // these points with its shape in the oposite tree.
find_all_holes(lower_tree, upper_tree, low_reg, upp_reg);
std::vector<node_type*> to_fill;
fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch());
+ // Browse the shapes of the min_tree, in order to put as child of
+ // min tree's shapes the shapes of the max tree corresponding to
+ // their holes.
for_all(node_)
{
node_type& node = *node_;
+ // If the node was not in the min tree at the begining, we ignore it.
if (node.elt().set_id != lower<V>::id)
continue;
- // std::cout << "Fill " << &node << std::endl;
+ // Browse the holes of the shape.
typename std::vector<fllt_node(P, V)*>::iterator hole_;
for (hole_ = node.elt().hole_shapes.begin();
hole_ != node.elt().hole_shapes.end();
@@ -724,6 +779,7 @@
{
fllt_node(P, V)* hole = *hole_;
+ // Check if hole_ is contained by a hole of the children of node.
bool child_has_bigger_hole = false;
typename fllt_node(P, V)::children_t::iterator it;
for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++)
@@ -735,8 +791,6 @@
child_hole_++)
{
fllt_node(P, V)* child_hole = *child_hole_;
- // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl;
- // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl;
if (shape_is_included(hole, child_hole))
{
child_has_bigger_hole = true;
@@ -744,6 +798,9 @@
}
} // end of browsing child's holes.
} // end of browsing childs.
+
+ // If no, move the shape of the max tree previously associated to this hole.
+ // as child of node.
if (!child_has_bigger_hole)
{
// // std::cout << "move " << hole << " as child of " << &node << std::endl;
@@ -754,6 +811,12 @@
node.elt().holes.clear();
} // end of browsing lower_tree.
+ // At this step, we have filled all the holes of the min
+ // tree. But, by filling these holes, we introduced somes holes of
+ // the max tree in the result tree. We need to fill them.
+
+ // Thus, we browse the shapes of the max tree previously merged in
+ // the min tree, in order to check their holes.
for(typename std::vector<node_type*>::iterator node_ = to_fill.begin();
node_ != to_fill.end();
node_++)
@@ -767,6 +830,7 @@
if (node.elt().set_id != upper<V>::id)
continue;
+ // Check if hole_ is contained by a hole of the children of node.
typename std::vector<fllt_node(P, V)*>::iterator hole_;
for (hole_ = node.elt().hole_shapes.begin();
hole_ != node.elt().hole_shapes.end();
@@ -785,7 +849,6 @@
child_hole_++)
{
fllt_node(P, V)* child_hole = *child_hole_;
- //if (hole->elt().points <= child_hole->elt().points)
if (shape_is_included(hole, child_hole))
{
child_has_bigger_hole = true;
@@ -794,6 +857,8 @@
} // end of browsing child's holes.
} // end of browsing childs.
+ // If no, move the shape of the max tree previously associated to this hole.
+ // as child of node.
if (!child_has_bigger_hole)
node.add_child(hole);
@@ -806,6 +871,12 @@
return lower_tree;
}
+ /*! This function compute the fllt tree of an image.
+ *
+ * \param[in] input_ An input image.
+ * \return The computed tree.
+ *
+ */
template <typename I>
fllt_tree(mln_point(I), mln_value(I))
fllt(const Image<I>& input_)
@@ -820,12 +891,15 @@
image2d<fllt_node(P, V)*> low_reg(input.domain());
image2d<fllt_node(P, V)*> upp_reg(input.domain());
+ // Compute the Min tree.
std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl;
lower_tree = level_set<I, lower<V> >(input, low_reg);
+ // Compute the Max tree.
std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl;
upper_tree = level_set<I, upper<V> >(input, upp_reg);
+ // Merge the two trees.
std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl;
fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input);
1
0
URL: https://svn.lrde.epita.fr/svn/scool/branches/scool-ng
ChangeLog:
2008-09-02 Maxime van Noppen <yabo(a)lrde.epita.fr>
Add tests for scool's translator.
* config: Add test configuration for Scool's translator.
* check.sh: Various fixes to properly handle multiple tests.
---
check.sh | 28 +++++++++++++++++++++-------
config | 20 +++++++++++++++++++-
2 files changed, 40 insertions(+), 8 deletions(-)
Index: branches/scool-ng/tests/config
===================================================================
--- branches/scool-ng/tests/config (revision 69)
+++ branches/scool-ng/tests/config (revision 70)
@@ -1,13 +1,31 @@
-number_of_tests=1
+number_of_tests=2
test_1 ()
{
+ desc="Scool parser"
cmd='sglri -p ../../src/scl-syn/Scool.tbl -i $input_file'
cmp='diff -EwbB -u $ref $output'
print_input_cmd='cat $input_file'
print_output_cmd='pp-aterm -i $input_file'
input_files="scool_src/*.scl"
+ input_extension=".scl"
+
ref_dir="scool_ast"
ref_extension=".aterm"
}
+
+test_2 ()
+{
+ desc="Scool AST -> C++ AST"
+ cmd='../../src/scoolt/scoolt -i $input_file'
+ cmp='diff -EwbB -u $ref $output'
+ print_input_cmd='pp-aterm -i $input_file'
+ print_output_cmd='pp-aterm -i $input_file'
+
+ input_files="scool_ast/*.aterm"
+ input_extension=".aterm"
+
+ ref_dir="cxx_ast"
+ ref_extension=".aterm"
+}
Index: branches/scool-ng/tests/check.sh
===================================================================
--- branches/scool-ng/tests/check.sh (revision 69)
+++ branches/scool-ng/tests/check.sh (revision 70)
@@ -27,19 +27,19 @@
perform_test()
{
cexit_val=0
- test_name=`basename "$1" .scl`
+ test_name=`basename "$1" "$2"`
input_file="$1"
- ref=${2}/${test_name}${3}
+ ref=${3}/${test_name}${4}
cmd_log=`mktemp`
cmd_err=`mktemp`
cmp_log=`mktemp`
cmp_err=`mktemp`
- rcmd=`echo $4 | sed s#'$input_file'#$input_file#g`
+ rcmd=`echo $5 | sed s#'$input_file'#$input_file#g`
- rcmp=`echo $5 | sed s#'$ref'#$ref#g`
+ rcmp=`echo $6 | sed s#'$ref'#$ref#g`
rcmp=`echo $rcmp | sed s#'$output'#$cmd_log#g`
indent $utest_name_indent
@@ -91,7 +91,7 @@
else echo -ne "${byell}sk";
fi
- echo -e " $bblue]"
+ echo -n -e " $bblue]"
}
print_output()
@@ -129,9 +129,12 @@
test_config="test_$testnb"
eval $test_config
+ echo -e "${bgreen} Test $testnb : $desc"
+ if [ "`echo $input_files`" = "$input_files" ]; then echo ; cd ..; return; fi
+
for input_file in `ls $input_files`
do
- perform_test "$input_file" "$ref_dir" "$ref_extension" "$cmd" "$cmp"
+ perform_test "$input_file" "$input_extension" "$ref_dir" "$ref_extension" "$cmd" "$cmp"
exit_val=$?
indent $test_result_indent
@@ -146,6 +149,7 @@
print_test_result "ko"
if [ $print_diff -eq 1 ]; then
+ echo
if [ $exit_val -eq 2 ]; then
echo -ne $grey; cat $cmd_log $cmd_err
echo -n
@@ -155,6 +159,9 @@
fi
fi
+ if [ $print_cmd -eq 1 ]; then echo -n -e ${grey} "$rcmd"; fi
+ echo
+
# Print the input if the -p option was provided
if [ $print -eq 1 ]; then
if [ $flush_sk -eq 1 ]; then
@@ -176,6 +183,7 @@
print_output $cmd_log
fi
done
+ echo
done
cd ..
@@ -192,6 +200,7 @@
-sk | --flush-skip Print the command output (if any) on successful tests
-p | --print Print the input of the command
-pa | --print-all Print all inputs
+ -pc | --print-command Prints the command used for the test
-h | --help Print this help message
"
}
@@ -200,6 +209,7 @@
gen_ref=0
flush_sk=0
print_all=0
+print_cmd=0
print=0
# Parse command line options
while [ $# -gt 0 ]
@@ -221,10 +231,14 @@
print=1
;;
- -pa | --pall)
+ -pa | --print-all)
print_all=1
;;
+ -pc | --print-command)
+ print_cmd=1
+ ;;
+
-h | --help)
print_help
exit 0
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Sandbox: Update metal::array.
* jardonnet/array/array.cc: Update Test.
* jardonnet/array/array.hh: Add stc/dyn getters.
* jardonnet/array/Makefile: New.
* jardonnet/test/icp.cc: .
* jardonnet/registration/tools.hh: .
array/Makefile | 2
array/array.cc | 12 ++++
array/array.hh | 121 +++++++++++++++++++++++++++++++++++++++++++++++++-
array/old/1d.hh | 4 -
registration/tools.hh | 58 ++++++-----------------
test/icp.cc | 1
6 files changed, 151 insertions(+), 47 deletions(-)
Index: jardonnet/test/icp.cc
--- jardonnet/test/icp.cc (revision 2161)
+++ jardonnet/test/icp.cc (working copy)
@@ -3,6 +3,7 @@
#include <mln/io/pbm/load.hh>
#include <mln/io/pbm/save.hh>
#include <mln/io/ppm/save.hh>
+#include <mln/convert/to_p_array.hh>
#include <mln/norm/l2.hh>
#include <sandbox/jardonnet/registration/icp.hh>
Index: jardonnet/registration/tools.hh
--- jardonnet/registration/tools.hh (revision 2161)
+++ jardonnet/registration/tools.hh (working copy)
@@ -193,23 +193,23 @@
namespace convert
{
- // to_p_array
- template <typename I>
- inline
- p_array<mln_point(I)>
- to_p_array(const Image<I>& img_)
- {
- const I& img = exact(img_);
-
- p_array<mln_point(I)> a;
-
- mln_piter(I) p(img.domain());
- for_all(p)
- if (img(p))
- a.append(p);
+// // to_p_array
+// template <typename I>
+// inline
+// p_array<mln_point(I)>
+// to_p_array(const Image<I>& img_)
+// {
+// const I& img = exact(img_);
+
+// p_array<mln_point(I)> a;
+
+// mln_piter(I) p(img.domain());
+// for_all(p)
+// if (img(p))
+// a.append(p);
- return a;
- }
+// return a;
+// }
template < typename P >
@@ -316,32 +316,6 @@
} // end of namespace convert
- namespace algebra
- {
-
- // transpose
- template<unsigned n, unsigned m, typename T>
- mat<m,n,T>
- trans(const mat<n,m,T>& matrice)
- {
- mat<m,n,T> tmp;
- for (unsigned i = 0; i < n; ++i)
- for (unsigned j = 0; j < m; ++j)
- tmp(j,i) = matrice(i,j);
- return tmp;
- }
-
- // trace
- template<unsigned n, typename T> inline
- float tr(const mat<n,n,T>& m)
- {
- float f = 0.f;
- for (unsigned i = 0; i < n; ++i)
- f += m(i,i);
- return f;
- }
-
- } // end of namespace algebra
} // end of namespace mln
Index: jardonnet/array/array.cc
--- jardonnet/array/array.cc (revision 2161)
+++ jardonnet/array/array.cc (working copy)
@@ -1,6 +1,6 @@
#include <iostream>
-#include <mln/metal/array.hh>
+#include "array.hh"
int main(int, char **)
{
@@ -9,4 +9,14 @@
mln::metal::array1d<int, 5> c;
c = a + b;
+
+ a.get<0>() = 0;
+ a.get<1>() = 1;
+ a.get<2>() = 2;
+ a.get<3>() = 3;
+
+ for (int i = 0 ; i < a.length; i++)
+ std::cout << a[i] << " ";
+
+ std::cout << std::endl;
}
Index: jardonnet/array/array.hh
--- jardonnet/array/array.hh (revision 2161)
+++ jardonnet/array/array.hh (working copy)
@@ -28,16 +28,47 @@
#ifndef MLN_METAL_ARRAY1D_HH
# define MLN_METAL_ARRAY1D_HH
+# include <mln/core/concept/object.hh>
+
# include <mln/trait/all.hh>
+# include <mln/trait/value_.hh>
+
+# include <mln/value/ops.hh>
namespace mln
{
+ // Fwd decls.
+ namespace metal {
+ template <typename T, unsigned Size> struct array1d;
+ }
+
+ namespace trait
+ {
+
+ template <typename T, unsigned Size>
+ struct value_< mln::metal::array1d<T,Size> >
+ {
+ typedef trait::value::nature::vectorial nature;
+ typedef trait::value::kind::data kind;
+
+ enum {
+ nbits = Size * mln_nbits(T),
+ card = Size * mln_card(T)
+ };
+ typedef mln_value_quant_from_(card) quant;
+
+ typedef metal::array1d<mln_sum(T),Size> sum;
+ };
+
+ } // end of namespace mln::trait
+
+
namespace metal
{
template <typename T, unsigned Size>
- struct array1d
+ struct array1d : public Object< array1d<T,Size> >
{
//
@@ -72,11 +103,99 @@
array1d<T, Size>&
operator-=(const array1d<T, Size>& rhs);
+
+ // dynamic accessors:
+
+ T operator[](unsigned i) const
+ {
+ mln_precondition(i < Size);
+ return buffer_[i];
+ }
+ T& operator[](unsigned i)
+ {
+ mln_precondition(i < Size);
+ return buffer_[i];
+ }
+
+ // static accessor
+
+ template<unsigned i>
+ T get() const {
+ return *(buffer_ + i);
+ }
+ template<unsigned i>
+ T& get() {
+ return *(buffer_ + i);
+ }
+
+ enum { length = Size };
protected:
T buffer_[Size];
};
+ }
+
+ namespace trait
+ {
+
+ // For unary traits.
+
+ template < template <class> class Name,
+ unsigned n, typename T >
+ struct set_precise_unary_< Name, metal::array1d<T, n> >
+ {
+ typedef mln_trait_unary(Name, T) V;
+ typedef metal::array1d<V, n> ret;
+ };
+
+ // For binary traits.
+
+ template < template <class, class> class Name,
+ unsigned n, typename T,
+ typename U >
+ struct set_precise_binary_< Name,
+ metal::array1d<T, n>, metal::array1d<U, n> >
+ {
+ typedef mln_trait_binary(Name, T, U) V;
+ typedef metal::array1d<V, n> ret;
+ };
+
+ template < unsigned n, typename T,
+ typename U >
+ struct set_precise_binary_< op::times,
+ metal::array1d<T, n>, metal::array1d<U, n> >
+ {
+ typedef mln_sum_x(T,U) ret;
+ };
+
+ template < template <class, class> class Name,
+ unsigned n, typename T,
+ typename S >
+ struct set_precise_binary_< Name,
+ metal::array1d<T, n>, mln::value::scalar_<S> >
+ {
+ typedef mln_trait_binary(Name, T, S) V;
+ typedef metal::array1d<V, n> ret;
+ };
+
+ template < template<class, class> class Name,
+ unsigned n, typename T,
+ typename S >
+ struct set_binary_< Name,
+ mln::Object, metal::array1d<T, n>,
+ mln::value::Scalar, S >
+ {
+ typedef mln_trait_binary(Name, T, S) V;
+ typedef metal::array1d<T, n> ret;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace metal
+ {
+
//
// Constructors
//
Index: jardonnet/array/Makefile
--- jardonnet/array/Makefile (revision 0)
+++ jardonnet/array/Makefile (revision 0)
@@ -0,0 +1,2 @@
+all:
+ g++ array.cc -I../../..
\ No newline at end of file
Index: jardonnet/array/old/1d.hh
--- jardonnet/array/old/1d.hh (revision 2161)
+++ jardonnet/array/old/1d.hh (working copy)
@@ -236,9 +236,7 @@
template<int i>
T get_() const {
- lesseq<-Info_::center, i>::ensure();
- lesseq<i, Info_::card - Info_::center - 1>::ensure();
- return *(buffer_ + Info_::center + i);
+ return *(buffer_ + i);
}
protected:
1
0
Re: [Olena-patches] [Olena] #32: Improve the integration of Doxygen into the (autoconfiscated) package
by Olena 01 Sep '08
by Olena 01 Sep '08
01 Sep '08
#32: Improve the integration of Doxygen into the (autoconfiscated) package
--------------------------+-------------------------------------------------
Reporter: levill_r | Owner: levill_r
Type: enhancement | Status: new
Priority: trivial | Milestone: Back-to-School 2008
Component: other | Version: 1.0
Resolution: | Keywords:
--------------------------+-------------------------------------------------
Changes (by levill_r):
* milestone: Olena 1.0 => Back-to-School 2008
--
Ticket URL: <https://trac.lrde.org/olena/ticket/32#comment:2>
Olena <http://olena.lrde.epita.fr>
Olena, a generic and efficient C++ image processing library.
1
0
#81: Olena 1.0 Reference Documentation
-----------------------+----------------------------------------------------
Reporter: levill_r | Owner: Olena Team
Type: task | Status: new
Priority: minor | Milestone: Back-to-School 2008
Component: Milena | Version: 1.0
Resolution: | Keywords: doc
-----------------------+----------------------------------------------------
Changes (by levill_r):
* milestone: Olena 1.0 => Back-to-School 2008
--
Ticket URL: <https://trac.lrde.org/olena/ticket/81#comment:2>
Olena <http://olena.lrde.epita.fr>
Olena, a generic and efficient C++ image processing library.
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
Sandbox: Start working on metal::array.
metal::array:
* jardonnet/array: New.
* jardonnet/array/array.cc: Test.
* jardonnet/array/array.hh: metal::array base.
* jardonnet/array/old,
* jardonnet/array/old/nd.hh,
* jardonnet/array/old/1d.hh,
* jardonnet/array/old/2d.hh,
* jardonnet/array/old/3d.hh,
* jardonnet/array/old/all.hh,
* jardonnet/array/old/1d.hxx,
* jardonnet/array/old/objs.hh,
* jardonnet/array/old/2d.hxx,
* jardonnet/array/old/3d.hxx: Olena 0.11 array type.
Minor ICP updates (old):
* jardonnet/test/icp_ref.cc,
* jardonnet/test/icp.cc,
* jardonnet/registration/icp.hh: Fix plotting.
* jardonnet/test/img/c55.pbm: New test img.
* jardonnet/test/Makefile: Clean up.
array/array.cc | 12 +
array/array.hh | 181 ++++++++++++++++++++++++++++
array/old/1d.hh | 294 +++++++++++++++++++++++++++++++++++++++++++++
array/old/1d.hxx | 237 +++++++++++++++++++++++++++++++++++++
array/old/2d.hh | 326
++++++++++++++++++++++++++++++++++++++++++++++++++
array/old/2d.hxx | 283 ++++++++++++++++++++++++++++++++++++++++++++
array/old/3d.hh | 333
++++++++++++++++++++++++++++++++++++++++++++++++++++
array/old/3d.hxx | 293 +++++++++++++++++++++++++++++++++++++++++++++
array/old/all.hh | 35 +++++
array/old/nd.hh | 50 +++++++
array/old/objs.hh | 74 +++++++++++
registration/icp.hh | 6
test/Makefile | 7 -
test/icp.cc | 10 -
test/icp_ref.cc | 2
15 files changed, 2131 insertions(+), 12 deletions(-)
Index: jardonnet/test/icp_ref.cc
--- jardonnet/test/icp_ref.cc (revision 2160)
+++ jardonnet/test/icp_ref.cc (working copy)
@@ -77,6 +77,7 @@
image2d<value::rgb8> output(convert::to_box2d(working_box), 1);
level::fill(output, literal::white);
+/* FIXME: remove or plot mu_Ck and mu_Xk
//plot mu_Ck
point3df mu_Ck = registration::center(c, c.npoints());
draw::plot(output, point2d(mu_Ck[0], mu_Ck[1]), literal::green);
@@ -84,6 +85,7 @@
//plot mu_X
point3df mu_X = registration::center(x, x.npoints());
draw::plot(output, point2d(mu_X[0], mu_X[1]), literal::black);
+*/
//to 2d : projection (FIXME:if 3d)
for (unsigned i = 0; i < c.npoints(); i++)
Index: jardonnet/test/icp.cc
--- jardonnet/test/icp.cc (revision 2160)
+++ jardonnet/test/icp.cc (working copy)
@@ -77,7 +77,7 @@
// final transform
- quat7<3> fqk = registration::final_qk(c, map, 2*stddev);
+ quat7<3> fqk = registration::final_qk2(c, map, 2*stddev);
fqk.apply_on(c, c, c.npoints());
@@ -92,7 +92,7 @@
//Xk points
point2d px(x[i][0], x[i][1]);
if (output.has(px))
- output(px) = literal::green;
+ output(px) = literal::black;
}
@@ -105,13 +105,13 @@
{
algebra::vec<3,float> xki = map(c[i]);
algebra::vec<3,float> ci = c[i];
-
+ /*
if (length[i] > 2 * stddev)
output(p) = literal::red;
else if (length[i] > stddev)
output(p) = value::rgb8(255,200,0);
- else
- output(p) = literal::black;
+ else*/
+ output(p) = literal::green;
}
}
Index: jardonnet/test/img/c55.pbm
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: jardonnet/test/img/c55.pbm
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Index: jardonnet/test/Makefile
--- jardonnet/test/Makefile (revision 2160)
+++ jardonnet/test/Makefile (working copy)
@@ -16,8 +16,8 @@
icpD: icp.cc +depend
g++ icp.cc -I../../.. -g -o 'icpD'
-icp: icp.o +depend
- g++ icp.o -I../../.. -O3 -DNDEBUG -o 'icp'
+icp: +depend
+ g++ icp.cc -I../../.. -O3 -DNDEBUG -o 'icp'
icp_refD: icp_ref.cc ../registration/icp_ref.hh +depend
g++ -Wall -W icp_ref.cc -I../../.. -g -o 'icp_refD'
@@ -25,9 +25,6 @@
icp_ref: icp_ref.cc ../registration/icp_ref.hh +depend
g++ icp_ref.cc -I../../.. -O3 -DNDEBUG -o 'icp_ref'
-icp.o:
- g++ -c icp.cc -I../../.. -O3 -DNDEBUG
-
bench:
ruby bench.rb
Index: jardonnet/registration/icp.hh
--- jardonnet/registration/icp.hh (revision 2160)
+++ jardonnet/registration/icp.hh (working copy)
@@ -182,7 +182,8 @@
#ifndef NDEBUG // FIXME: theo
- image2d<value::rgb8> tmp(500,500); // FIXME :
+ const box_<P> working_box = enlarge(bigger(cloud.bbox(),x.bbox()),5);
+ image2d<value::rgb8> tmp(convert::to_box2d(working_box), 1);
level::fill(tmp, literal::black);
//write X
mln_piter(p_array<P>) p(x);
@@ -203,6 +204,7 @@
l = (l<1) ? 1 : l;
impl::icp_(cloud, map, qk, l, 1e-3);
+ /*
//remove points
p_array<P> tmp;
tmp.reserve(cloud.npoints());
@@ -216,7 +218,7 @@
if (norm::l2(qci - xi) < 2 * stddev)
cloud.hook_()[i] = cloud[(i+1) % cloud.npoints()];
}
-
+ */
#ifndef NDEBUG
{
value::rgb8 c;
Index: jardonnet/array/array.cc
--- jardonnet/array/array.cc (revision 0)
+++ jardonnet/array/array.cc (revision 0)
@@ -0,0 +1,12 @@
+#include <iostream>
+
+#include <mln/metal/array.hh>
+
+int main(int, char **)
+{
+ mln::metal::array1d<int, 5> a;
+ mln::metal::array1d<int, 5> b;
+ mln::metal::array1d<int, 5> c;
+
+ c = a + b;
+}
Index: jardonnet/array/array.hh
--- jardonnet/array/array.hh (revision 0)
+++ jardonnet/array/array.hh (revision 0)
@@ -0,0 +1,181 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_METAL_ARRAY1D_HH
+# define MLN_METAL_ARRAY1D_HH
+
+# include <mln/trait/all.hh>
+
+namespace mln
+{
+
+ namespace metal
+ {
+
+ template <typename T, unsigned Size>
+ struct array1d
+ {
+
+ //
+ // Constructors
+ //
+
+ array1d();
+ array1d(T* ptr);
+
+ // Copy
+
+ array1d(const array1d<T, Size>& rhs);
+ array1d<T, Size>& operator=(const array1d<T, Size>& rhs);
+
+ // Operators
+
+ template <class U>
+ array1d<T, Size> operator*(U w);
+
+ template <class U>
+ array1d<mln_trait_op_div(T,U), Size>
+ operator/(U w);
+
+ template <typename U>
+ array1d<mln_trait_op_plus(T,U), Size>
+ operator+(const array1d<U, Size>& rhs) const;
+ array1d<T, Size>& operator+=(const array1d<T, Size>& rhs);
+
+ template <typename U>
+ array1d<mln_trait_op_minus(T,U), Size>
+ operator-(const array1d<U, Size>& rhs) const;
+ array1d<T, Size>&
+ operator-=(const array1d<T, Size>& rhs);
+
+ protected:
+
+ T buffer_[Size];
+ };
+
+ //
+ // Constructors
+ //
+
+ template <typename T, unsigned Size>
+ array1d<T,Size>::array1d()
+ {
+ }
+
+ template <typename T, unsigned Size>
+ array1d<T,Size>::array1d(T* ptr)
+ {
+ for (unsigned i = 0; i < Size; ++i)
+ buffer_[i] = *ptr++;
+ }
+
+ // Copy
+
+ template <typename T, unsigned Size>
+ array1d<T,Size>::array1d(const array1d<T, Size>& rhs)
+ {
+ for (unsigned i = 0; i < Size; ++i)
+ buffer_[i] = rhs[i];
+ }
+ template <typename T, unsigned Size>
+ array1d<T, Size>&
+ array1d<T,Size>::operator=(const array1d<T, Size>& rhs)
+ {
+ for (unsigned i = 0; i < Size; ++i)
+ buffer_[i] = rhs[i];
+ return *this;
+ }
+
+ // Operators
+
+ template <typename T, unsigned Size>
+ template <class U>
+ array1d<T, Size>
+ array1d<T,Size>::operator*(U w)
+ {
+ //fixme mln_trait_op_mult<int,U>
+ array1d<T, Size> tmp;
+ for (unsigned i = 0; i < Size; ++i)
+ tmp[i] = this->buffer_[i] * w;
+ return tmp;
+ }
+
+ template <typename T, unsigned Size>
+ template <class U>
+ array1d<mln_trait_op_div(T,U), Size>
+ array1d<T,Size>::operator/(U w)
+ {
+ array1d<T, Size> tmp;
+ for (unsigned i = 0; i < Size; ++i)
+ tmp[i] = this->buffer_[i] / w;
+ return tmp;
+ }
+
+ template <typename T, unsigned Size>
+ template <typename U>
+ array1d<mln_trait_op_plus(T,U), Size>
+ array1d<T,Size>::operator+(const array1d<U, Size>& rhs) const
+ {
+ array1d<T, Size> tmp;
+ for (unsigned i = 0; i < Size; ++i)
+ tmp[i] = this->buffer_[i] + rhs.buffer_[i];
+ return tmp;
+ }
+ template <typename T, unsigned Size>
+ array1d<T, Size>&
+ array1d<T,Size>::operator+=(const array1d<T, Size>& rhs)
+ {
+ for (unsigned i = 0; i < Size; ++i)
+ this->buffer_[i] += rhs.buffer_[i];
+ return *this;
+ }
+
+ template <typename T, unsigned Size>
+ template <typename U>
+ array1d<mln_trait_op_minus(T,U), Size>
+ array1d<T,Size>::operator-(const array1d<U, Size>& rhs) const
+ {
+ array1d<T, Size> tmp;
+ for (unsigned i = 0; i < Size; ++i)
+ tmp[i] = this->buffer_[i] - rhs.buffer_[i];
+ return tmp;
+ }
+ template <typename T, unsigned Size>
+ array1d<T, Size>&
+ array1d<T,Size>::operator-=(const array1d<T, Size>& rhs)
+ {
+ for (unsigned i = 0; i < Size; ++i)
+ this->buffer_[i] -= rhs.buffer_[i];
+ return *this;
+ }
+
+ } // end of namespace metal
+
+} // end of namespace mln
+
+#endif /* MLN_METAL_ARRAY1D_HH */
+
Index: jardonnet/array/old/nd.hh
--- jardonnet/array/old/nd.hh (revision 0)
+++ jardonnet/array/old/nd.hh (revision 0)
@@ -0,0 +1,50 @@
+// Copyright (C) 2001, 2003 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_ND_HH
+# define METALIC_ARRAY_ND_HH
+
+
+namespace mlc
+{
+
+ namespace internal
+ {
+
+ //
+ // mlc::internal misc
+ //
+ ////////////////////////////////////////
+
+ static const unsigned max_card_ = 4096; // 64 x 64
+ static const unsigned unknown_ = max_card_ + 1;
+
+ } // end of internal
+
+} // end of namespace mlc
+
+#endif // ! METALIC_ARRAY_ND_HH
Index: jardonnet/array/old/1d.hh
--- jardonnet/array/old/1d.hh (revision 0)
+++ jardonnet/array/old/1d.hh (revision 0)
@@ -0,0 +1,294 @@
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_1D_HH
+# define METALIC_ARRAY_1D_HH
+
+# include <mlc/contract.hh>
+# include <mlc/cmp.hh>
+# include <mlc/array/objs.hh>
+# include <ntg/basics.hh>
+# include <iostream>
+
+
+// impl
+# include <mlc/array/1d.hxx>
+
+namespace mlc
+{
+
+ template<class Info_, class T_>
+ struct array1d
+ {
+ typedef array1d self;
+ typedef T_ T;
+ typedef Info_ Info;
+
+
+ //
+ // Constructors
+ //
+
+ array1d()
+ {
+ }
+
+ array1d(T* ptr)
+ {
+ less<0, Info_::card>::ensure();
+ less< Info_::card, internal::max_card_ >::ensure();
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = *ptr++;
+ }
+
+ // Copy
+
+ array1d(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ }
+ self& operator=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ return *this;
+ }
+
+
+ // Name
+
+ static std::string
+ name()
+ {
+ return std::string("array1d< Info, ") + ntg_name(T) + " >";
+ }
+
+
+
+ //
+ // Operations on array
+ //
+
+ // Normalize (absolute values -> relative values)
+
+ array1d<Info_, ntg::float_s>
+ normalize()
+ {
+ array1d<Info_, ntg::float_s> tmp;
+ ntg::float_s sum = 0.f;
+ const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be
global
+ unsigned i;
+ for (i = 0; i < Info_::card; ++i)
+ sum += this->buffer_[i];
+ for (i = 0; i < Info_::card; ++i)
+ tmp[i] = this->buffer_[i] / sum;
+ // security
+ sum = 0.f;
+ for (i = 0; i < Info_::card; ++i)
+ sum += tmp[i];
+ postcondition(std::abs(sum - 1) <= epsilon);
+ return tmp;
+ }
+
+ // Central symmetry
+
+ array1d<array1d_info<Info_::card,
+ Info_::card - Info_::center - 1,
+ Info_::i>, T>
+ operator-() const
+ {
+ enum { new_center = Info_::card - Info_::center - 1 };
+ array1d<array1d_info< Info_::card, new_center, Info_::i>,T> tmp;
+
+ for (unsigned i = 0; i < Info_::card; ++i)
+ tmp[Info_::card - i - 1] = this->operator[](i);
+ return tmp;
+ }
+
+
+ // Operators
+
+ // FIXME: This code should be factorized between 1d, 2d and 3d.
+ // Think of a mechanism similar to apply() and apply2().
+
+ template <class U>
+ array1d< Info, ntg_return_type(times, T, U) >
+ operator*(U w)
+ {
+ array1d< Info, ntg_return_type(times, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] * w;
+ return tmp;
+ }
+
+ template <class U>
+ array1d< Info, ntg_return_type(div, T, U) >
+ operator/(U w)
+ {
+ array1d< Info, ntg_return_type(div, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] / w;
+ return tmp;
+ }
+
+ self operator+(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] + rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator+=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] += rhs.buffer_[i];
+ return *this;
+ }
+
+ self operator-(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] - rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator-=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] -= rhs.buffer_[i];
+ return *this;
+ }
+
+
+ //
+ // Accessors
+ //
+
+ unsigned size() const
+ {
+ return Info_::card;
+ }
+
+ const T* buffer() const
+ {
+ return buffer_;
+ }
+
+ // dynamic accessors:
+
+ T operator[](unsigned i) const // Absolute position
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+ T& operator[](unsigned i)
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+
+ T operator()(int i) const // Relative position
+ {
+ precondition(-Info_::center <= i);
+ precondition(i <= Info_::card - Info_::center - 1);
+ return *(buffer_ + Info_::center + i);
+ }
+ T& operator()(int i)
+ {
+ precondition(-Info_::center <= i);
+ precondition(i <= Info_::card - Info_::center - 1);
+ return *(buffer_ + Info_::center + i);
+ }
+
+
+ // do not use these methods...
+
+ template<unsigned i>
+ T get_at_() const {
+ lesseq<i, Info_::card>::ensure();
+ return *(buffer_ + i);
+ }
+
+ template<int i>
+ T get_() const {
+ lesseq<-Info_::center, i>::ensure();
+ lesseq<i, Info_::card - Info_::center - 1>::ensure();
+ return *(buffer_ + Info_::center + i);
+ }
+
+ protected:
+
+ T buffer_[Info_::card];
+ };
+
+
+ // ...but these static accessors:
+
+ template<unsigned i, class Info, class T> inline
+ T get_at(const array1d<Info, T>& arr)
+ {
+ return arr.template get_at_<i>();
+ }
+
+ template<int i, class Info, class T> inline
+ T get(const array1d<Info, T>& arr)
+ {
+ return arr.template get_<i>();
+ }
+
+ // starter objects
+
+ // FIXME: what about other types? Replace this by a function
+ // returning a starter.
+
+# define array1d_starter(T) \
+ static internal::array1d_start_<T > T##s_1d =
internal::array1d_start_<T >()
+
+ array1d_starter(int); // ints_1d
+ array1d_starter(float); // floats_1d
+
+
+
+ // print
+
+ template<class Info, class T>
+ std::ostream& operator<<(std::ostream& ostr, const array1d<Info, T>& rhs)
+ {
+ for (int i = 0; i < Info::card; ++i)
+ if (i == Info::center)
+ ostr << "<" << rhs[i] << "> ";
+ else
+ ostr << rhs[i] << " ";
+ ostr << std::endl;
+
+ return ostr;
+ }
+
+} // end of mlc
+
+#endif // ! METALIC_ARRAY_1D_HH
Index: jardonnet/array/old/2d.hh
--- jardonnet/array/old/2d.hh (revision 0)
+++ jardonnet/array/old/2d.hh (revision 0)
@@ -0,0 +1,326 @@
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_2D_HH
+# define METALIC_ARRAY_2D_HH
+
+# include <mlc/array/objs.hh>
+# include <mlc/contract.hh>
+# include <mlc/cmp.hh>
+# include <ntg/basics.hh>
+
+# include <iostream>
+
+// impl
+# include <mlc/array/2d.hxx>
+
+namespace mlc
+{
+
+ template<class Info_, class T_>
+ struct array2d
+ {
+ typedef array2d self;
+ typedef T_ T;
+ typedef Info_ Info;
+
+ //
+ // Constructors
+ //
+
+ array2d()
+ {
+ }
+
+ array2d(T* ptr)
+ {
+ less< 0, Info_::nrows >::ensure();
+ less< 0, Info_::ncols >::ensure();
+ less< Info_::card, internal::max_card_ >::ensure();
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = *ptr++;
+ }
+
+ // Copy
+
+ array2d(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ }
+ self& operator=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ return *this;
+ }
+
+
+ // Name
+
+ static std::string
+ name()
+ {
+ return std::string("array2d< Info, ") + ntg_name(T) + " >";
+ }
+
+
+
+ //
+ // Operations on array
+ //
+
+
+ // Normalize (absolute values -> relative values)
+
+ array2d<Info_, ntg::float_s>
+ normalize()
+ {
+ array2d<Info_, ntg::float_s> tmp;
+ ntg::float_s sum = 0.f;
+ const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be
global
+ unsigned i;
+ for (i = 0; i < Info_::card; ++i)
+ sum += this->buffer_[i];
+ for (i = 0; i < Info_::card; ++i)
+ tmp[i] = this->buffer_[i] / sum;
+ // security
+ sum = 0.f;
+ for (i = 0; i < Info_::card; ++i)
+ sum += tmp[i];
+ postcondition(std::abs(sum - 1) <= epsilon);
+ return tmp;
+ }
+
+ // Central symmetry
+
+ array2d<array2d_info<Info_::nrows,
+ Info_::ncols,
+ Info_::card - Info_::center - 1,
+ Info_::i>, T>
+ operator-() const
+ {
+ enum { new_center = Info_::card - Info_::center - 1 };
+ array2d<array2d_info< Info_::nrows, Info_::ncols, new_center,
Info_::i>,T> tmp;
+
+ for (unsigned i = 0; i < Info_::card; ++i)
+ tmp[Info_::card - i - 1] = this->operator[](i);
+ return tmp;
+ }
+
+
+ // Transpose
+
+ typedef array2d<array2d_info<
+ Info_::ncols,
+ Info_::nrows,
+ (Info_::center * Info_::nrows + Info_::center / Info_::ncols) %
Info_::card,
+ Info_::i
+ >, T> transposed_array_t;
+
+ transposed_array_t transpose() const
+ {
+ transposed_array_t tmp;
+ for (int i = 0; i < Info::card; ++i)
+ tmp[i] = this->operator[]((i * Info_::ncols + i / Info_::nrows) %
Info_::card);
+ return tmp;
+ }
+
+ // Operators
+
+ // FIXME: This code should be factorized between 1d, 2d and 3d.
+ // Think of a mechanism similar to apply() and apply2().
+
+ template <class U>
+ array2d< Info, ntg_return_type(times, T, U) >
+ operator*(U w)
+ {
+ array2d< Info, ntg_return_type(times, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] * w;
+ return tmp;
+ }
+
+ template <class U>
+ array2d< Info, ntg_return_type(div, T, U) >
+ operator/(U w)
+ {
+ array2d< Info, ntg_return_type(div, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] / w;
+ return tmp;
+ }
+
+ self operator+(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] + rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator+=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] += rhs.buffer_[i];
+ return *this;
+ }
+
+ self operator-(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] - rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator-=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] -= rhs.buffer_[i];
+ return *this;
+ }
+
+
+ //
+ // Accessors
+ //
+
+ unsigned size() const
+ {
+ return Info_::card;
+ }
+
+ const T* buffer() const
+ {
+ return buffer_;
+ }
+
+ // dynamic accessors:
+
+ T operator[](unsigned i) const // Absolute position
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+ T& operator[](unsigned i)
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+
+
+ T operator()(int row, int col) const // Relative position
+ {
+ precondition(-Info_::center_row <= row);
+ precondition(row <= Info_::nrows - Info_::center_row - 1);
+ precondition(-Info_::center_col <= col);
+ precondition(col <= Info_::ncols - Info_::center_col - 1);
+
+ return *(buffer_ + Info_::center + (row * Info_::ncols) + col);
+ }
+ T& operator()(int row, int col)
+ {
+ precondition(-Info_::center_row <= row);
+ precondition(row <= Info_::nrows - Info_::center_row - 1);
+ precondition(-Info_::center_col <= col);
+ precondition(col <= Info_::ncols - Info_::center_col - 1);
+
+ return *(buffer_ + Info_::center + (row * Info_::ncols) + col);
+ }
+
+
+ // do not use these methods...
+
+ template<unsigned i>
+ T get_at_() const {
+ lesseq<i, Info_::card>::ensure();
+ return *(buffer_ + i);
+ }
+
+ template<int nrow, int ncol>
+ T get_() const {
+ lesseq< -Info_::center_row, nrow >::ensure();
+ lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure();
+ lesseq< -Info_::center_col, ncol >::ensure();
+ lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure();
+ return *(buffer_ + Info_::center + (nrow * Info_::ncols) + ncol);
+ }
+
+
+ protected:
+
+ T buffer_[internal::max_card_];
+ };
+
+
+ // ...but these static accessors:
+
+ template<unsigned i, class Info, class T> inline
+ T get_at(const array2d<Info, T>& arr)
+ {
+ return arr.template get_at_<i>();
+ }
+
+ template<int row, int col, class Info, class T> inline
+ T get(const array2d<Info, T>& arr)
+ {
+ return arr.template get_<row, col>();
+ }
+
+ // starter objects
+
+ // FIXME: what about other types? Replace this by a function
+ // returning a starter.
+
+# define array2d_starter(T) \
+ static internal::array2d_start_<T > T##s_2d =
internal::array2d_start_<T >()
+
+ array2d_starter(int); // ints_2d
+ array2d_starter(float); // floats_2d
+
+
+ // print
+
+ template<class Info, class T>
+ std::ostream& operator<<(std::ostream& ostr, const array2d<Info, T>& rhs)
+ {
+ for (int i = 0; i < Info::card; ++i)
+ {
+ if (i == Info::center)
+ ostr << "<" << rhs[i] << ">";
+ else
+ ostr << rhs[i];
+
+ ostr << ((i + 1) % Info::ncols == 0 ? "\n" : "\t");
+ }
+ ostr << std::flush;
+ return ostr;
+ }
+
+} // end of mlc
+
+
+#endif // ! METALIC_ARRAY_2D_HH
Index: jardonnet/array/old/3d.hh
--- jardonnet/array/old/3d.hh (revision 0)
+++ jardonnet/array/old/3d.hh (revision 0)
@@ -0,0 +1,333 @@
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_3D_HH
+# define METALIC_ARRAY_3D_HH
+
+# include <mlc/array/objs.hh>
+# include <mlc/contract.hh>
+# include <mlc/cmp.hh>
+# include <ntg/basics.hh>
+
+# include <iostream>
+
+// impl
+# include <mlc/array/3d.hxx>
+
+namespace mlc
+{
+
+ class not_implemented_yet{}; // FIXME
+
+ template<class Info_, class T_>
+ struct array3d
+ {
+ typedef array3d self;
+ typedef T_ T;
+ typedef Info_ Info;
+
+ //
+ // Constructors
+ //
+
+ array3d()
+ {
+ }
+
+ array3d(T* ptr)
+ {
+ less< 0, Info_::nplanes >::ensure();
+ less< 0, Info_::nrows >::ensure();
+ less< 0, Info_::ncols >::ensure();
+ less< Info_::card, internal::max_card_ >::ensure();
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = *ptr++;
+ }
+
+ // Copy
+
+ array3d(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ }
+ self& operator=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info_::card; ++i)
+ buffer_[i] = rhs[i];
+ return *this;
+ }
+
+
+ // Name
+
+ static std::string
+ name()
+ {
+ return std::string("array3d< Info, ") + ntg_name(T) + " >";
+ }
+
+
+
+ //
+ // Operations on array
+ //
+
+ // Normalize (absolute values -> relative values)
+
+ array3d<Info_, ntg::float_s>
+ normalize()
+ {
+ array3d<Info_, ntg::float_s> tmp;
+ ntg::float_s sum = 0.f;
+ const ntg::float_s epsilon = 0.01f; // FIXME : epsilon should be
global
+ unsigned i;
+ for (i = 0; i < Info_::card; ++i)
+ sum += this->buffer_[i];
+ for (i = 0; i < Info_::card; ++i)
+ tmp[i] = this->buffer_[i] / sum;
+ // security
+ sum = 0.f;
+ for (i = 0; i < Info_::card; ++i)
+ sum += tmp[i];
+ postcondition(std::abs(sum - 1) <= epsilon);
+ return tmp;
+ }
+
+ // Central symmetry
+
+ array3d<array3d_info<Info_::nplanes,
+ Info_::nrows,
+ Info_::ncols,
+ Info_::card - Info_::center - 1,
+ Info_::i>, T>
+ operator-() const
+ {
+ enum { new_center = Info_::card - Info_::center - 1 };
+ array3d<array3d_info< Info_::nplanes, Info_::nrows, Info_::ncols,
new_center, Info_::i>,T> tmp;
+
+ for (unsigned i = 0; i < Info_::card; ++i)
+ tmp[Info_::card - i - 1] = this->operator[](i);
+ return tmp;
+ }
+
+
+ // Transpose
+
+ array3d<Info, T> transpose() const // FIXME
+ {
+ std::cerr << "[31m===> 3D transposition not implemented yet.
<===[0m" << std::endl;
+ throw not_implemented_yet();
+ }
+
+
+ // Operators
+
+ // FIXME: This code should be factorized between 1d, 2d and 3d.
+ // Think of a mechanism similar to apply() and apply2().
+
+ template <class U>
+ array3d< Info, ntg_return_type(times, T, U) >
+ operator*(U w)
+ {
+ array3d< Info, ntg_return_type(times, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] * w;
+ return tmp;
+ }
+
+ template <class U>
+ array3d< Info, ntg_return_type(div, T, U) >
+ operator/(U w)
+ {
+ array3d< Info, ntg_return_type(div, T, U) > tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] / w;
+ return tmp;
+ }
+
+ self operator+(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] + rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator+=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] += rhs.buffer_[i];
+ return *this;
+ }
+
+ self operator-(const self& rhs) const
+ {
+ self tmp;
+ for (unsigned i = 0; i < Info::card; ++i)
+ tmp[i] = this->buffer_[i] - rhs.buffer_[i];
+ return tmp;
+ }
+ self& operator-=(const self& rhs)
+ {
+ for (unsigned i = 0; i < Info::card; ++i)
+ this->buffer_[i] -= rhs.buffer_[i];
+ return *this;
+ }
+
+
+
+ // template<class U> int operator,(U); // FIXME: why this?
+
+ //
+ // Accessors
+ //
+
+ unsigned size() const
+ {
+ return Info_::card;
+ }
+
+ const T* buffer() const
+ {
+ return buffer_;
+ }
+
+ // dynamic accessors:
+
+ T operator[](unsigned i) const // Absolute position
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+ T& operator[](unsigned i)
+ {
+ precondition(i < Info_::card);
+ return *(buffer_ + i);
+ }
+
+
+ T operator()(int plane, int row, int col) const // Relative position
+ {
+ precondition(-Info_::center_plane <= plane);
+ precondition(plane <= Info::nplanes - Info_::center_plane - 1);
+ precondition(-Info_::center_row <= row);
+ precondition(row <= Info_::nrows - Info_::center_row - 1);
+ precondition(-Info_::center_col <= col);
+ precondition(col <= Info_::ncols - Info_::center_col - 1);
+
+ return *(buffer_ + Info_::center + (plane * Info::nrows *
Info::ncols) + (row * Info::ncols) + col);
+ }
+
+ T& operator()(int plane, int row, int col)
+ {
+ precondition(-Info_::center_plane <= plane);
+ precondition(plane <= Info::nplanes - Info_::center_plane - 1);
+ precondition(-Info_::center_row <= row);
+ precondition(row <= Info_::nrows - Info_::center_row - 1);
+ precondition(-Info_::center_col <= col);
+ precondition(col <= Info_::ncols - Info_::center_col - 1);
+
+ return *(buffer_ + Info_::center + (plane * Info::nrows *
Info::ncols) + (row * Info::ncols) + col);
+ }
+
+
+ // do not use these methods...
+
+ template<unsigned i>
+ T get_at_() const {
+ lesseq<i, Info_::card>::ensure();
+ return *(buffer_ + i);
+ }
+
+ template<int nplane, int nrow, int ncol>
+ T get_() const {
+ lesseq< -Info_::center_plane, nplane >::ensure();
+ lesseq< nplane, Info::nplanes - Info_::center_plane - 1 >::ensure();
+ lesseq< -Info_::center_row, nrow >::ensure();
+ lesseq< nrow, Info_::nrows - Info_::center_row - 1 >::ensure();
+ lesseq< -Info_::center_col, ncol >::ensure();
+ lesseq< ncol, Info_::ncols - Info_::center_col - 1 >::ensure();
+ return *(buffer_ + Info_::center + (nplane * Info::nrows *
Info::ncols) + (nrow * Info::ncols) + ncol);
+ }
+
+
+ protected:
+
+ T buffer_[internal::max_card_];
+ };
+
+
+ // ...but these static accessors:
+
+ template<unsigned i, class Info, class T> inline
+ T get_at(const array3d<Info, T>& arr)
+ {
+ return arr.template get_at_<i>();
+ }
+
+ template<int plane, int row, int col, class Info, class T> inline
+ T get(const array3d<Info, T>& arr)
+ {
+ return arr.template get_<plane, row, col>();
+ }
+
+ // starter objects
+
+ // FIXME: what about other types? Replace this by a function
+ // returning a starter.
+
+# define array3d_starter(T) \
+ static internal::array3d_start_<T > T##s_3d =
internal::array3d_start_<T >()
+
+ array3d_starter(int); // ints_3d
+ array3d_starter(float); // floats_3d
+
+
+ // print
+
+ template<class Info, class T>
+ std::ostream& operator<<(std::ostream& ostr, const array3d<Info, T>& rhs)
+ {
+ for (int i = 0; i < Info::card; ++i)
+ {
+ if (i == Info::center)
+ ostr << "<" << rhs[i] << "> ";
+ else
+ ostr << rhs[i] << " ";
+
+ ostr << ((i + 1) % Info::ncols == 0 ? "\n" : "\t");
+ ostr << ((i + 1) % (Info::ncols * Info::nrows) == 0 ? "\n" : "");
+ }
+ ostr << std::flush;
+
+ return ostr;
+ }
+
+
+} // end of mlc
+
+#endif // ! METALIC_ARRAY_3D_HH
Index: jardonnet/array/old/all.hh
--- jardonnet/array/old/all.hh (revision 0)
+++ jardonnet/array/old/all.hh (revision 0)
@@ -0,0 +1,35 @@
+// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY__HH
+# define METALIC_ARRAY__HH
+
+# include <mlc/array/1d.hh>
+# include <mlc/array/2d.hh>
+# include <mlc/array/3d.hh>
+
+#endif // ! METALIC_ARRAY__HH
Index: jardonnet/array/old/1d.hxx
--- jardonnet/array/old/1d.hxx (revision 0)
+++ jardonnet/array/old/1d.hxx (revision 0)
@@ -0,0 +1,237 @@
+// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_1D_HXX
+# define METALIC_ARRAY_1D_HXX
+
+# include <mlc/array/nd.hh>
+
+namespace mlc
+{
+
+ //
+ // mlc::array1d_info
+ //
+ ////////////////////////////////////////
+
+
+ // card_ -> total number of elements (1-indexed)
+
+ // center_ -> position of the central element (0-indexed)
+ // domain : [ 0, card [
+
+ // i_ -> number of elements that have been eaten yet (0-indexed)
+ // domain : [ 0, card ] -> watch out !!
+
+
+ template < unsigned card_, unsigned center_ = card_ / 2, unsigned i_
= card_>
+ struct array1d_info
+ {
+ enum {
+ card = card_,
+ center = center_,
+ i = i_,
+ well_formed = true,
+ get_real_center = center_
+ };
+
+ typedef array1d_info< card_, center_, i + 1 > next_elt;
+
+ };
+
+ template < unsigned card_, unsigned i_ >
+ struct array1d_info <card_, internal::unknown_, i_ >
+ {
+ enum {
+ card = card_,
+ center = internal::unknown_,
+ i = i_,
+ well_formed = true,
+ get_real_center = i_ / 2
+ };
+
+ typedef array1d_info< card_, internal::unknown_, i + 1 > next_elt;
+
+ };
+
+ // fwd decl
+ template<class, class> struct array1d;
+
+
+ namespace internal
+ {
+
+ // fwd decl
+
+ template<class T, class Info>
+ struct array1d_elt_;
+
+ // for error messages
+
+ template<class U>
+ struct here_a_value_is_not_of_type_;
+
+
+ //
+ // mlc::internal::array1d_start_ decl
+ //
+ ////////////////////////////////////////
+
+ template<class T>
+ struct array1d_start_ {
+
+ array1d_elt_< T, array1d_info< unknown_, unknown_, 1 > >
operator=(T val);
+ array1d_elt_< T, array1d_info< unknown_, 0, 1 > > operator=(x_<T>
val);
+ array1d_elt_< T, array1d_info< unknown_, 0, 1 > >
operator=(x_<void> val);
+
+ T ptr[max_card_]; // could be static
+ };
+
+
+
+ //
+ // mlc::internal::array1d_elt_
+ //
+ ////////////////////////////////////////
+
+ template<class T, class Info>
+ struct array1d_elt_
+ {
+ typedef array1d_elt_<T, typename Info::next_elt> next_elt_t_;
+
+ typedef array1d_elt_< T, array1d_info< Info::card, Info::i,
Info::i + 1> > eat_center_t_;
+
+ typedef array1d< array1d_info< Info::i, Info::get_real_center,
Info::i > , T> array1d_t_;
+
+ public:
+
+ // Constructor
+
+ array1d_elt_(T* ptr, array1d_start_<T>* arr) : ptr(ptr), arr(arr)
+ {
+ }
+
+
+
+ //
+ // Overloading "operator,"
+ //
+
+
+ // elt, elt
+
+ next_elt_t_ operator,(T val)
+ {
+ is_true<Info::card == unknown_>::ensure();
+ *ptr = val;
+ return next_elt_t_(ptr + 1, arr);
+ }
+
+
+ // elt, x(elt) -> center
+
+ eat_center_t_ operator,(x_<T> val)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = val.ue; // FIXME : give a *name* to this variable !!
+ return eat_center_t_(ptr+1, arr);
+ }
+
+
+ // elt, x() -> center
+
+ eat_center_t_ operator,(x_<void>)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = T(0);
+ return eat_center_t_(ptr+1, arr);
+ }
+
+
+ // elt, end
+
+ array1d_t_ operator,(end_type)
+ {
+ // array is well-formed :
+ is_true<Info::well_formed>::ensure();
+ // centering is automatic or user-defined :
+ // (commented out to allow automatic centering on even sized arrays)
+ // mlc::logical_or< mlc::eq< Info::i % 2, 1 >::ret, mlc::neq<
Info::center, unknown_ >::ret >::ensure();
+ return array1d_t_(arr->ptr);
+ }
+
+
+ // else -> error
+
+ template<class U>
+ void operator,(array1d< Info, U >);
+
+ template<class U>
+ here_a_value_is_not_of_type_<T> operator,(U u) const;
+
+ T* ptr;
+ array1d_start_<T>* arr;
+ };
+
+
+
+ //
+ // mlc::internal::array1d_start_ impl
+ //
+ ////////////////////////////////////////
+
+ template<class T> inline
+ array1d_elt_< T, array1d_info< unknown_, unknown_, 1 > >
+ array1d_start_<T>::operator=(T val)
+ {
+ ptr[0] = val;
+ return array1d_elt_< T, array1d_info< unknown_, unknown_, 1 >
>(ptr+1, this);
+ }
+
+ template<class T> inline
+ array1d_elt_< T, array1d_info< unknown_, 0, 1 > >
+ array1d_start_<T>::operator=(x_<T> val)
+ {
+ ptr[0] = val.ue;
+ // center <- 0
+ return array1d_elt_< T, array1d_info< unknown_, 0, 1 > >(ptr+1,
this);
+ }
+
+ template<class T> inline
+ array1d_elt_< T, array1d_info< unknown_, 0, 1 > >
+ array1d_start_<T>::operator=(x_<void> val)
+ {
+ ptr[0] = T(0);
+ // center <- 0
+ return array1d_elt_< T, array1d_info< unknown_, 0, 1 > >(ptr+1,this);
+ }
+
+ } // end of internal
+
+} // end of mlc
+
+#endif // ! METALIC_ARRAY_1D_HXX
Index: jardonnet/array/old/objs.hh
--- jardonnet/array/old/objs.hh (revision 0)
+++ jardonnet/array/old/objs.hh (revision 0)
@@ -0,0 +1,74 @@
+// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_OBJS_HH
+# define METALIC_ARRAY_OBJS_HH
+
+// FIXME: rename, objs is not precise enough.
+
+//
+// Defines common objects useful for array declarations.
+//
+
+# include <mlc/objs.hh>
+
+namespace mlc
+{
+
+ namespace internal
+ {
+
+ class lbrk_ {};
+ class pbrk_ {};
+
+ template<class T>
+ struct x_ {
+ x_(T val) : ue(val) {}
+ T ue;
+ };
+ template<> struct x_<void> {};
+ template<> struct x_<lbrk_>;
+ template<> struct x_<end_type>;
+
+ } // end of internal
+
+ // cross means origin
+
+ template<class T> inline
+ internal::x_<T>
+ x(T val) { return internal::x_<T>(val); }
+
+ inline
+ internal::x_<void>
+ x() { return internal::x_<void>(); }
+
+ static const internal::lbrk_ lbrk = internal::lbrk_();
+ static const internal::pbrk_ pbrk = internal::pbrk_();
+
+} // end of mlc
+
+#endif // METALIC_ARRAY_OBJS_HH
Index: jardonnet/array/old/2d.hxx
--- jardonnet/array/old/2d.hxx (revision 0)
+++ jardonnet/array/old/2d.hxx (revision 0)
@@ -0,0 +1,283 @@
+// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_2D_HXX
+# define METALIC_ARRAY_2D_HXX
+
+# include <mlc/array/nd.hh>
+
+namespace mlc
+{
+
+ //
+ // mlc::array2d_info
+ //
+ ////////////////////////////////////////
+
+
+ // nrows_ -> total number of rows (1-indexed)
+ // ncols_ -> total number of columns (1-indexed)
+
+ // center_ -> position of the central element (0-indexed)
+ // domain : [ 0, card [
+
+ // i_ -> number of elements that have been eaten yet (0-indexed)
+ // domain : [ 0, card ] -> watch out !!
+
+
+
+ // Center is user-defined
+
+ template < unsigned nrows_,
+ unsigned ncols_,
+ unsigned center_ = ncols_ * (nrows_ / 2) + (ncols_ / 2),
+ unsigned i_ = nrows_ * ncols_>
+ struct array2d_info
+ {
+ enum {
+ nrows = nrows_,
+ ncols = ncols_,
+ center = center_,
+ center_row = center_ / ncols_,
+ center_col = center_ % ncols_,
+ card = nrows_ * ncols_,
+ i = i_,
+ well_formed = ((i_ % ncols_) == 0),
+ get_real_center = center_
+ };
+
+ typedef array2d_info< nrows_, ncols_, center_, i + 1 > next_elt;
+
+ };
+
+ // Center is defined automatically, if nrows and ncols are both odd
+
+ template < unsigned nrows_, unsigned ncols_, unsigned i_ >
+ struct array2d_info <nrows_, ncols_, internal::unknown_, i_ >
+ {
+ enum {
+ nrows = nrows_,
+ ncols = ncols_,
+ center = internal::unknown_,
+ i = i_,
+ card = nrows_ * ncols_,
+ well_formed = ((i_ % ncols_) == 0),
+ get_real_center = i_ / 2
+ };
+
+ typedef array2d_info< nrows_, ncols_, internal::unknown_, i + 1 >
next_elt;
+
+ };
+
+ // fwd decl
+ template<class, class> struct array2d;
+
+
+ namespace internal
+ {
+
+ // fwd decl
+
+ template<class T, class Info>
+ struct array2d_elt_;
+
+ // for error messages
+
+ template<class U>
+ struct here_a_value_is_not_of_type_;
+
+
+ //
+ // mlc::internal::array2d_start_ decl
+ //
+ ////////////////////////////////////////
+
+ template<class T>
+ struct array2d_start_ {
+
+ array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > >
+ operator=(T val);
+
+ array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
+ operator=(x_<T> val);
+
+ array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
+ operator=(x_<void> val);
+
+ T ptr[max_card_]; // could be static
+ };
+
+
+ //
+ // mlc::internal::array2d_elt_
+ //
+ ////////////////////////////////////////
+
+ template<class T, class Info>
+ struct array2d_elt_
+ {
+ typedef array2d_elt_< T, typename Info::next_elt >
+ next_elt_t_;
+
+ typedef array2d_elt_< T, array2d_info< Info::nrows, Info::ncols,
Info::i, Info::i + 1> >
+ eat_center_t_;
+
+ typedef array2d_elt_< T, array2d_info< Info::nrows, Info::i,
Info::center, Info::i > >
+ eat_lbrk_t_;
+
+ typedef array2d< array2d_info< Info::i / Info::ncols, Info::ncols,
Info::get_real_center, Info::i > , T>
+ array2d_t_;
+
+ public:
+
+ // Constructor
+
+ array2d_elt_(T* ptr, array2d_start_<T>* arr) : ptr(ptr), arr(arr)
+ {
+ }
+
+
+ //
+ // Overloading "operator,"
+ //
+
+
+ // elt, elt
+
+ next_elt_t_ operator,(T val)
+ {
+ is_true<Info::nrows == unknown_>::ensure();
+ *ptr = val;
+ return next_elt_t_(ptr + 1, arr);
+ }
+
+
+ // elt, x(elt) -> center
+
+ eat_center_t_ operator,(x_<T> val)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = val.ue; // FIXME : give a *name* to this variable !!
+ return eat_center_t_(ptr + 1, arr);
+ }
+
+
+ // elt, x() -> center
+
+ eat_center_t_ operator,(x_<void>)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = T(0);
+ return eat_center_t_(ptr + 1, arr);
+ }
+
+
+ // elt, lbrk
+
+ eat_lbrk_t_ operator,(lbrk_)
+ {
+ is_true<Info::ncols == unknown_>::ensure();
+ is_true<Info::ncols != 0>::ensure();
+ return eat_lbrk_t_(ptr, arr);
+ }
+
+
+ // elt, end
+
+ array2d_t_ operator,(end_type)
+ {
+ enum { nrows = Info::i / Info::ncols };
+
+ // array is well-formed :
+ is_true<Info::well_formed == true>::ensure();
+ // centering is automatic or user-defined :
+
+ is_true<Info::ncols != unknown_>::ensure();
+
+
+ // both nrows and ncols must be odd
+ // or the center must be user-defined
+
+ is_true<
+ ((Info::ncols % 2 == 1) && (nrows % 2 == 1))
+ || (Info::center != unknown_)
+ >::ensure();
+
+ return array2d_t_(arr->ptr);
+ }
+
+
+ // else -> error
+
+ template<class U>
+ void operator,(array2d< Info, U >);
+
+ template<class U>
+ here_a_value_is_not_of_type_<T> operator,(U u) const;
+
+ T* ptr;
+ array2d_start_<T>* arr;
+ };
+
+
+
+ //
+ // mlc::internal::array2d_start_ impl
+ //
+ ////////////////////////////////////////
+
+ template<class T> inline
+ array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1 > >
+ array2d_start_<T>::operator=(T val)
+ {
+ ptr[0] = val;
+ return array2d_elt_< T, array2d_info< unknown_, unknown_, unknown_, 1
> >(ptr+1,this);
+ }
+
+ template<class T> inline
+ array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
+ array2d_start_<T>::operator=(x_<T> val)
+ {
+ ptr[0] = val.ue;
+ // center <- 0
+ return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 >
>(ptr+1,this);
+ }
+
+ template<class T> inline
+ array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 > >
+ array2d_start_<T>::operator=(x_<void> val)
+ {
+ ptr[0] = T(0);
+ // center <- 0
+ return array2d_elt_< T, array2d_info< unknown_, unknown_, 0, 1 >
>(ptr+1,this);
+ }
+
+ } // end of internal
+
+} // end of mlc
+
+#endif // ! METALIC_ARRAY_2D_HXX
Index: jardonnet/array/old/3d.hxx
--- jardonnet/array/old/3d.hxx (revision 0)
+++ jardonnet/array/old/3d.hxx (revision 0)
@@ -0,0 +1,293 @@
+// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef METALIC_ARRAY_3D_HXX
+# define METALIC_ARRAY_3D_HXX
+
+# include <mlc/array/nd.hh>
+
+namespace mlc
+{
+
+ //
+ // mlc::array3d_info
+ //
+ ////////////////////////////////////////
+
+
+ // nrows_ -> total number of rows (1-indexed)
+ // ncols_ -> total number of columns (1-indexed)
+ // nplanes_ -> total number of planes (1-indexed)
+
+ // center_ -> position of the central element (0-indexed)
+ // domain : [ 0, card [
+
+ // i_ -> number of elements that have been eaten yet (0-indexed)
+ // domain : [ 0, card ] -> watch out !!
+
+ // Center is user-defined
+
+ template < unsigned nplanes_,
+ unsigned nrows_,
+ unsigned ncols_,
+ unsigned center_ = (ncols_ * nrows_) * (nplanes_ / 2) + ncols_ *
(nrows_ / 2) + (ncols_ / 2),
+ unsigned i_ = nplanes_ * nrows_ * ncols_>
+ struct array3d_info
+ {
+ enum {
+ nplanes = nplanes_,
+ nrows = nrows_,
+ ncols = ncols_,
+ center = center_,
+ center_plane = center_ / (nrows_ * ncols_),
+ center_row = (center_ % (nrows_ * ncols_)) / ncols_,
+ center_col = (center_ % (nrows_ * ncols_)) % ncols_,
+ i = i_,
+ card = nplanes_ * nrows_ * ncols_,
+ well_formed = (i_ % (ncols_ * nrows) == 0),
+ get_real_center = center_
+ };
+
+ typedef array3d_info< nplanes_, nrows_, ncols_, center_, i + 1 >
next_elt;
+
+ };
+
+ // Center is defined automatically, if nrows and ncols are both odd
+
+ template < unsigned nplanes_, unsigned nrows_, unsigned ncols_,
unsigned i_ >
+ struct array3d_info < nplanes_, nrows_, ncols_, internal::unknown_, i_ >
+ {
+ enum {
+ nplanes = nplanes_,
+ nrows = nrows_,
+ ncols = ncols_,
+ center = internal::unknown_,
+ i = i_,
+ card = nplanes_ * nrows_ * ncols_,
+ well_formed = (i_ % (ncols_ * nrows_) == 0),
+ get_real_center = i_ / 2
+ };
+
+ typedef array3d_info< nplanes_, nrows_, ncols_, internal::unknown_,
i + 1 > next_elt;
+
+ };
+
+ // fwd decl
+ template<class, class> struct array3d;
+
+ namespace internal
+ {
+
+ // fwd decl
+
+ template<class T, class Info>
+ struct array3d_elt_;
+
+ // for error messages
+
+ template<class U>
+ struct here_a_value_is_not_of_type_;
+
+
+ //
+ // mlc::internal::array3d_start_ decl
+ //
+ ////////////////////////////////////////
+
+ template<class T>
+ struct array3d_start_ {
+
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_,
unknown_, 1 > >
+ operator=(T val);
+
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1
> >
+ operator=(x_<T> val);
+
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1
> >
+ operator=(x_<void> val);
+
+ T ptr[max_card_]; // could be static
+ };
+
+ //
+ // mlc::internal::array3d_elt_
+ //
+ ////////////////////////////////////////
+
+ template<class T, class Info>
+ struct array3d_elt_
+ {
+ typedef array3d_elt_< T, typename Info::next_elt >
+ next_elt_t_;
+
+ typedef array3d_elt_< T, array3d_info< Info::nplanes,
Info::nrows, Info::ncols, Info::i, Info::i + 1> >
+ eat_center_t_;
+
+ typedef array3d_elt_< T, array3d_info< Info::nplanes,
Info::nrows, Info::i, Info::center, Info::i > >
+ eat_lbrk_t_;
+
+ typedef array3d_elt_< T, array3d_info< Info::nplanes, Info::i /
Info::ncols, Info::ncols, Info::center, Info::i > >
+ eat_pbrk_t_;
+
+ typedef array3d< array3d_info< Info::i / (Info::ncols *
Info::nrows), Info::nrows, Info::ncols, Info::get_real_center, Info::i >
, T>
+ array3d_t_;
+
+ public:
+
+ // Constructor
+
+ array3d_elt_(T* ptr, array3d_start_<T>* arr) : ptr(ptr), arr(arr)
+ {
+ }
+
+
+ //
+ // Overloading "operator,"
+ //
+
+
+ // elt, elt
+
+ next_elt_t_ operator,(T val)
+ {
+ is_true<Info::nplanes == unknown_>::ensure();
+ *ptr = val;
+ return next_elt_t_(ptr + 1, arr);
+ }
+
+
+ // elt, x(elt) -> center
+
+ eat_center_t_ operator,(x_<T> val)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = val.ue; // FIXME : give a *name* to this variable !!
+ return eat_center_t_(ptr + 1, arr);
+ }
+
+
+ // elt, x() -> center
+
+ eat_center_t_ operator,(x_<void>)
+ {
+ is_true<Info::center == unknown_>::ensure();
+ *ptr = T(0);
+ return eat_center_t_(ptr + 1, arr);
+ }
+
+
+ // elt, lbrk
+
+ eat_lbrk_t_ operator,(lbrk_)
+ {
+ is_true<Info::ncols == unknown_>::ensure();
+ return eat_lbrk_t_(ptr, arr);
+ }
+
+
+ // elt, pbrk
+ eat_pbrk_t_ operator,(pbrk_)
+ {
+ is_true<Info::nplanes == unknown_>::ensure();
+ return eat_pbrk_t_(ptr, arr);
+ }
+
+ // elt, end
+
+ array3d_t_ operator,(end_type)
+ {
+ enum { nplanes = (Info::i / (Info::ncols * Info::nrows)) };
+
+ // array is well-formed :
+ is_true<Info::well_formed>::ensure();
+ // centering is automatic or user-defined :
+
+ is_true<Info::ncols != unknown_>::ensure();
+ is_true<Info::nrows != unknown_>::ensure();
+
+ // all of nplanes, nrows and ncols are odd
+ // or the center is user-defined
+
+ is_true<
+ (Info::ncols % 2 == 1 && Info::nrows % 2 == 1 && nplanes % 2 == 1)
+ || (Info::center != unknown_)
+ >::ensure();
+
+ return array3d_t_(arr->ptr);
+ }
+
+
+ // else -> error
+
+ template<class U>
+ void operator,(array3d< Info, U >);
+
+ template<class U>
+ here_a_value_is_not_of_type_<T> operator,(U u) const;
+
+ T* ptr;
+ array3d_start_<T>* arr;
+ };
+
+
+ //
+ // mlc::internal::array3d_start_ impl
+ //
+ ////////////////////////////////////////
+
+ template<class T> inline
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_,
unknown_, 1 > >
+ array3d_start_<T>::operator=(T val)
+ {
+ ptr[0] = val;
+ return array3d_elt_< T, array3d_info< unknown_, unknown_,
unknown_, unknown_, 1 > >(ptr+1,this);
+ }
+
+ template<class T> inline
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > >
+ array3d_start_<T>::operator=(x_<T> val)
+ {
+ ptr[0] = val.ue;
+ // center <- 0
+ return array3d_elt_< T, array3d_info< unknown_, unknown_,
unknown_, 0, 1 > >(ptr+1,this);
+ }
+
+ template<class T> inline
+ array3d_elt_< T, array3d_info< unknown_, unknown_, unknown_, 0, 1 > >
+ array3d_start_<T>::operator=(x_<void> val)
+ {
+ ptr[0] = T(0);
+ // center <- 0
+ return array3d_elt_< T, array3d_info< unknown_, unknown_,
unknown_, 0, 1 > >(ptr+1,this);
+ }
+
+ } // end of internal
+
+} // end of mlc
+
+
+#endif // ! METALIC_ARRAY_3D_HXX
1
0
cleanup-2008 2160: Add image domain extension morphers plus the flat image.
by Thierry Geraud 01 Sep '08
by Thierry Geraud 01 Sep '08
01 Sep '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add image domain extension morphers plus the flat image.
Add image domain extension morphers.
* mln/core/image/extension_ima.hh: New.
* mln/trait/ch_value.hh (ch_value_): New overload to deal with
extension_ima.
* mln/core/image/extension_fun.hh: New.
* mln/core/image/extension_val.hh: New.
* mln/core/routine: New directory.
* mln/core/routine/all.hh: New.
* mln/core/routine/extend.hh: New.
* doc/tutorial/examples/image_if.cc: Augment to test extensions.
Add the flat image type.
* mln/core/image/flat_image.hh: New.
* doc/tutorial/examples/image_flat.cc: New.
* mln/core/image/status.txt: Update.
Enforce consistency for iterator naming.
* mln/core/macros.hh
(mln_iter, mln_fwd_iter, mln_bkd_iter): Rename as...
(mln_eiter, mln_fwd_eiter, mln_bkd_eiter): ...these.
* mln/core/site_set/p_key.hh,
* mln/core/site_set/p_mutable_array_of.hh,
* mln/core/site_set/p_set_of.hh,
* mln/core/p_runs.hh,
* mln/util/set.hh,
* mln/util/array.hh: Update.
Misc.
* mln/core/image/instant.hh (file): Fix.
* sandbox/geraud/p_runs__with_dedicated_piter.hh (todo): Remove;
obsolete.
* mln/core/internal/morpher_lvalue.hh
(mln_morpher_lvalue): New macro.
* mln/core/internal/image_identity.hh: Use the new macro.
* mln/core/safe.hh: Likewise.
doc/tutorial/examples/image_flat.cc | 12 +
doc/tutorial/examples/image_if.cc | 59 ++++-
mln/core/image/extension_fun.hh | 222 ++++++++++++++++++++
mln/core/image/extension_ima.hh | 254 +++++++++++++++++++++++
mln/core/image/extension_val.hh | 240 +++++++++++++++++++++
mln/core/image/flat_image.hh | 273 +++++++++++++++++++++++++
mln/core/image/instant.hh | 2
mln/core/image/status.txt | 4
mln/core/internal/image_identity.hh | 2
mln/core/internal/morpher_lvalue.hh | 4
mln/core/macros.hh | 26 +-
mln/core/p_runs.hh | 4
mln/core/routine/all.hh | 45 ++++
mln/core/routine/extend.hh | 157 ++++++++++++++
mln/core/safe.hh | 4
mln/core/site_set/p_key.hh | 8
mln/core/site_set/p_mutable_array_of.hh | 4
mln/core/site_set/p_set_of.hh | 4
mln/trait/ch_value.hh | 7
mln/util/array.hh | 6
mln/util/set.hh | 6
sandbox/geraud/p_runs__with_dedicated_piter.hh | 4
22 files changed, 1305 insertions(+), 42 deletions(-)
Index: doc/tutorial/examples/image_if.cc
--- doc/tutorial/examples/image_if.cc (revision 2159)
+++ doc/tutorial/examples/image_if.cc (working copy)
@@ -1,10 +1,16 @@
# include <mln/core/image2d.hh>
+# include <mln/core/neighb2d.hh>
# include <mln/core/image_if.hh>
# include <mln/debug/iota.hh>
# include <mln/debug/println.hh>
# include <mln/fun/p2b/chess.hh>
+# include <mln/border/fill.hh>
+# include <mln/core/var.hh>
+# include <mln/core/routine/extend.hh>
+# include <mln/pw/all.hh>
+
template <typename It, typename S>
void ch_target(It it, const S& s)
@@ -13,21 +19,64 @@
}
+template <typename I, typename N>
+void browse(const I& ima, const N& nbh)
+{
+ // Relies on "ima.has(p)".
+ mln_fwd_piter(I) p(ima.domain());
+ mln_fwd_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ std::cout << ima(p) << ": ";
+ for_all(n)
+ if (ima.has(n))
+ std::cout << ima(n) << ' ';
+ std::cout << std::endl;
+ }
+}
+
+template <typename I, typename N>
+void browse_domain(const I& ima, const N& nbh)
+{
+ // Relies on "ima.domain().has(p)".
+ mln_fwd_piter(I) p(ima.domain());
+ mln_fwd_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ std::cout << ima(p) << ": ";
+ for_all(n)
+ if (ima.domain().has(n))
+ std::cout << ima(n) << ' ';
+ std::cout << std::endl;
+ }
+}
+
+
+
+
int main()
{
using namespace mln;
typedef image2d<unsigned> I;
- I ima(3, 5);
+ I ima(3, 3, 1);
+ // FIXME: border::fill(ima, 0);
debug::iota(ima);
+ mln_VAR(ima_, ima | fun::p2b::chess);
+
debug::println(ima);
- debug::println(ima | fun::p2b::chess);
+ debug::println(ima_);
- trait::image::print(ima | fun::p2b::chess);
+ trait::image::print(ima_);
+ std::cout << std::endl;
typedef pset_if<box2d, fun::p2b::chess_t> S;
+ ch_target(mln_fwd_piter_(S)(), ima_.domain());
- ch_target(mln_fwd_piter_(S)(),
- (ima | fun::p2b::chess).domain());
+ // mln_VAR(ima_e, extend(ima_, pw::value(ima)));
+ // mln_VAR(ima_e, extend(ima_, 0));
+ mln_VAR(ima_e, extend(ima_, ima));
+ debug::println(ima_e);
+ browse(ima_e, c4());
}
Index: doc/tutorial/examples/image_flat.cc
--- doc/tutorial/examples/image_flat.cc (revision 0)
+++ doc/tutorial/examples/image_flat.cc (revision 0)
@@ -0,0 +1,12 @@
+# include <mln/core/image2d.hh>
+# include <mln/core/image/flat_image.hh>
+# include <mln/debug/println.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ flat_image<unsigned, box2d> ima(3, box2d(3,3));
+ debug::println(ima);
+}
Index: mln/trait/ch_value.hh
--- mln/trait/ch_value.hh (revision 2159)
+++ mln/trait/ch_value.hh (working copy)
@@ -98,6 +98,13 @@
typedef M< P, V > ret;
};
+ template < template <class, class> class M, typename I1, typename I2,
+ typename V >
+ struct ch_value_< M< tag::image_<I1>, tag::image_<I2> >, V >
+ {
+ typedef M< mln_ch_value(I1, V), mln_ch_value(I2, V) > ret;
+ };
+
// For mln::value::stack_image<n,I>.
template < template <unsigned, class> class M, unsigned n, typename I,
typename V >
Index: mln/core/macros.hh
--- mln/core/macros.hh (revision 2159)
+++ mln/core/macros.hh (working copy)
@@ -49,10 +49,11 @@
// b
-/// Shortcuts to access the bkd_iter type associated to T.
+/// Shortcuts to access the element-backward-iterator type associated
+/// to T.
/// \{
-# define mln_bkd_iter(T) typename T::bkd_iter
-# define mln_bkd_iter_(T) T::bkd_iter
+# define mln_bkd_eiter(T) typename T::bkd_eiter
+# define mln_bkd_eiter_(T) T::bkd_eiter
/// \}
/// Shortcuts to access the bkd_niter type associated to T.
@@ -118,6 +119,12 @@
// e
+/// Shortcuts to access the element-iterator type associated to T.
+/// \{
+# define mln_eiter(T) typename T::eiter
+# define mln_eiter_(T) T::eiter
+/// \}
+
/// Shortcuts to access the element type associated to T.
/// \{
# define mln_element(T) typename T::element
@@ -139,10 +146,11 @@
// f
-/// Shortcuts to access the fwd_iter type associated to T.
+/// Shortcuts to access the element-forward-iterator type associated
+/// to T.
/// \{
-# define mln_fwd_iter(T) typename T::fwd_iter
-# define mln_fwd_iter_(T) T::fwd_iter
+# define mln_fwd_eiter(T) typename T::fwd_eiter
+# define mln_fwd_eiter_(T) T::fwd_eiter
/// \}
/// Shortcuts to access the fwd_niter type associated to T.
@@ -199,12 +207,6 @@
# define mln_invert_(T) T::invert
/// \}
-/// Shortcuts to access the iterator type associated to T.
-/// \{
-# define mln_iter(T) typename T::iter
-# define mln_iter_(T) T::iter
-/// \}
-
// l
Index: mln/core/internal/morpher_lvalue.hh
--- mln/core/internal/morpher_lvalue.hh (revision 2159)
+++ mln/core/internal/morpher_lvalue.hh (working copy)
@@ -36,6 +36,10 @@
# include <mln/core/macros.hh>
+# define mln_morpher_lvalue(I) typename internal::morpher_lvalue_<I>::ret
+
+
+
namespace mln
{
Index: mln/core/internal/image_identity.hh
--- mln/core/internal/image_identity.hh (revision 2159)
+++ mln/core/internal/image_identity.hh (working copy)
@@ -143,7 +143,7 @@
typedef mln_rvalue(I) rvalue;
/// Return type of read-write access.
- typedef typename internal::morpher_lvalue_<I>::ret lvalue;
+ typedef mln_morpher_lvalue(I) lvalue;
/// Give the set of values.
Index: mln/core/image/extension_ima.hh
--- mln/core/image/extension_ima.hh (revision 0)
+++ mln/core/image/extension_ima.hh (revision 0)
@@ -0,0 +1,254 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_EXTENSION_IMA_HH
+# define MLN_CORE_IMAGE_EXTENSION_IMA_HH
+
+/*!
+ * \file mln/core/image/extension_ima.hh
+ *
+ * \brief Definition of a morpher that extends the domain of an image
+ * with a function.
+ *
+ * \todo Use the 'instant' mechanism.
+ */
+
+# include <mln/core/internal/image_identity.hh>
+# include <mln/metal/converts_to.hh>
+
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I, typename J> struct extension_ima;
+
+
+ namespace internal
+ {
+
+ /// \internal Data structure for \c mln::extension_ima<I, J>.
+ template <typename I, typename J>
+ struct data< extension_ima<I, J> >
+ {
+ data(I& ima, J& ext);
+
+ I ima_;
+ J ext_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I, typename J>
+ struct image_< extension_ima<I, J> > : image_< I > // Same as I except...
+ {
+ // ...these changes.
+ typedef trait::image::category::identity_morpher category;
+ typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
+
+ // extended domain
+ typedef trait::image::ext_domain::extendable ext_domain;
+ typedef trait::image::ext_value::multiple ext_value;
+ typedef mln_trait_image_value_io(J) ext_io;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename I, typename J>
+ class extension_ima
+
+ : public internal::image_identity< I, mln_pset(I), extension_ima<I, J> >,
+ private mlc_converts_to(mln_value(J), mln_value(I))::check_t
+ {
+ public:
+
+ /// Skeleton.
+ typedef extension_ima< tag::image_<I>, tag::image_<J> > skeleton;
+ // FIXME: OK when ch_value?
+
+
+ /// Return type of read-only access.
+ typedef mln_value(I) rvalue;
+
+
+ /// Constructor without argument.
+ extension_ima();
+
+ /// Constructor from an image \p ima and a function \p ext.
+ extension_ima(I& ima, J& ext);
+
+ /// Deferred initialization from an image \p ima and a function \p
+ /// ext.
+ void init(I& ima, J& ext);
+
+
+ /// Test if \p p is valid.
+ // Tech note: the 'template' allows for multiple input.
+ template <typename P>
+ bool has(const P& p) const;
+
+
+ /// Read-only access to the image value located at site \p p;
+ mln_value(I) operator()(const mln_psite(I)& p) const;
+
+ /// Read-write access to the image value located at site \p p.
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
+
+
+ /// Read-only access to the extension domain (image).
+ mlc_const(J)& extension() const;
+
+ /// Mutable access to the extension domain (image). This domain
+ /// can be modified if J a read-write image type.
+ J& extension();
+ };
+
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // internal::data< extension_ima<I,S> >
+
+ namespace internal
+ {
+
+ template <typename I, typename J>
+ inline
+ data< extension_ima<I, J> >::data(I& ima, J& ext)
+ : ima_(ima),
+ ext_(ext)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ // extension_ima<I, J>
+
+ template <typename I, typename J>
+ inline
+ extension_ima<I, J>::extension_ima()
+ {
+ }
+
+ template <typename I, typename J>
+ inline
+ extension_ima<I, J>::extension_ima(I& ima, J& ext)
+ {
+ init(ima, ext);
+ }
+
+ template <typename I, typename J>
+ inline
+ void
+ extension_ima<I, J>::init(I& ima, J& ext)
+ {
+ this->data_ = new internal::data< extension_ima<I, J> >(ima, ext);
+ }
+
+ template <typename I, typename J>
+ template <typename P>
+ inline
+ bool
+ extension_ima<I, J>::has(const P& p) const
+ {
+ mln_precondition(this->has_data());
+ mln_precondition(this->data_->ext_.has_data());
+ return
+ this->data_->ima_.domain().has(p)
+ || this->data_->ext_.has(p);
+ }
+
+ template <typename I, typename J>
+ inline
+ mln_value(I)
+ extension_ima<I, J>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->has_data());
+ mln_precondition(has(p));
+ // if-else is preferred to the ternary op to allow for the
+ // function result to convert towards the expected return type.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ return this->data_->ext_(p);
+ }
+
+ template <typename I, typename J>
+ inline
+ mln_morpher_lvalue(I)
+ extension_ima<I, J>::operator()(const mln_psite(I)& p)
+ {
+ static mln_value(I) cpy;
+ mln_precondition(this->has_data());
+ mln_precondition(has(p));
+ // See the above comment about if-else v. ternary.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ {
+ // This hack makes this signature valid both in the image
+ // domain and in its extension. It works even if
+ // mln_morpher_lvalue(I) is a mutable reference.
+ cpy = this->data_->ext_(p);
+ return cpy;
+ }
+ }
+
+ template <typename I, typename J>
+ inline
+ mlc_const(J)&
+ extension_ima<I, J>::extension() const
+ {
+ mln_precondition(this->has_data());
+ return this->data_->ext_;
+ }
+
+ template <typename I, typename J>
+ inline
+ J&
+ extension_ima<I, J>::extension()
+ {
+ mln_precondition(this->has_data());
+ return this->data_->ext_;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_EXTENSION_IMA_HH
Index: mln/core/image/status.txt
--- mln/core/image/status.txt (revision 2159)
+++ mln/core/image/status.txt (working copy)
@@ -57,6 +57,10 @@
** identity morpher
new instant
+new extension_ima
+new extension_fun
+new extension_val
+
ok plain
ok safe
Index: mln/core/image/extension_fun.hh
--- mln/core/image/extension_fun.hh (revision 0)
+++ mln/core/image/extension_fun.hh (revision 0)
@@ -0,0 +1,222 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_EXTENSION_FUN_HH
+# define MLN_CORE_IMAGE_EXTENSION_FUN_HH
+
+/*!
+ * \file mln/core/image/extension_fun.hh
+ *
+ * \brief Definition of a morpher that extends the domain of an image
+ * with a function.
+ *
+ * \todo Deal with two-ways functions...
+ */
+
+# include <mln/core/internal/image_identity.hh>
+# include <mln/metal/converts_to.hh>
+
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I, typename F> struct extension_fun;
+
+
+ namespace internal
+ {
+
+ /// \internal Data structure for \c mln::extension_fun<I, F>.
+ template <typename I, typename F>
+ struct data< extension_fun<I, F> >
+ {
+ data(I& ima, const F& fun);
+
+ I ima_;
+ const F fun_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I, typename F>
+ struct image_< extension_fun<I, F> > : image_< I > // Same as I except...
+ {
+ // ...these changes.
+ typedef trait::image::category::identity_morpher category;
+ typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
+
+ // extended domain
+ typedef trait::image::ext_domain::infinite ext_domain;
+ typedef trait::image::ext_value::multiple ext_value;
+ typedef trait::image::ext_io::read_only ext_io;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename I, typename F>
+ class extension_fun
+
+ : public internal::image_identity< I, mln_pset(I), extension_fun<I, F> >,
+ private mlc_converts_to(mln_result(F), mln_value(I))::check_t
+ {
+ public:
+
+ /// Skeleton.
+ typedef extension_fun< tag::image_<I>, tag::function_<F> > skeleton;
+ // FIXME: OK when ch_value?
+
+
+ /// Return type of read-only access.
+ typedef mln_value(I) rvalue;
+
+
+ /// Constructor without argument.
+ extension_fun();
+
+ /// Constructor from an image \p ima and a function \p fun.
+ extension_fun(I& ima, const F& fun);
+
+ /// Deferred initialization from an image \p ima and a function \p
+ /// fun.
+ void init(I& ima, const F& fun);
+
+
+ /// Test if \p p is valid. It returns always true.
+ // Tech note: the 'template' allows for multiple input.
+ template <typename P>
+ bool has(const P& p) const;
+
+
+ /// Read-only access to the image value located at site \p p;
+ mln_value(I) operator()(const mln_psite(I)& p) const;
+
+ /// Read-write access to the image value located at site \p p.
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
+ };
+
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // internal::data< extension_fun<I,S> >
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ data< extension_fun<I, F> >::data(I& ima, const F& fun)
+ : ima_(ima),
+ fun_(fun)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ // extension_fun<I, F>
+
+ template <typename I, typename F>
+ inline
+ extension_fun<I, F>::extension_fun()
+ {
+ }
+
+ template <typename I, typename F>
+ inline
+ extension_fun<I, F>::extension_fun(I& ima, const F& fun)
+ {
+ init(ima, fun);
+ }
+
+ template <typename I, typename F>
+ inline
+ void
+ extension_fun<I, F>::init(I& ima, const F& fun)
+ {
+ this->data_ = new internal::data< extension_fun<I, F> >(ima, fun);
+ }
+
+ template <typename I, typename F>
+ template <typename P>
+ inline
+ bool
+ extension_fun<I, F>::has(const P&) const
+ {
+ return true;
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_value(I)
+ extension_fun<I, F>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->has_data());
+ // if-else is preferred to the ternary op to allow for the
+ // function result to convert towards the expected return type.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ return this->data_->fun_(p);
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_morpher_lvalue(I)
+ extension_fun<I, F>::operator()(const mln_psite(I)& p)
+ {
+ static mln_value(I) cpy;
+ mln_precondition(this->has_data());
+ // See the above comment about if-else v. ternary.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ {
+ // This hack makes this signature valid both in the image
+ // domain and in its extension. It works even if
+ // mln_morpher_lvalue(I) is a mutable reference.
+ cpy = this->data_->fun_(p);
+ return cpy;
+ }
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_EXTENSION_FUN_HH
Index: mln/core/image/flat_image.hh
--- mln/core/image/flat_image.hh (revision 0)
+++ mln/core/image/flat_image.hh (revision 0)
@@ -0,0 +1,273 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_FLAT_IMAGE_HH
+# define MLN_CORE_FLAT_IMAGE_HH
+
+/*!
+ * \file mln/core/flat_image.hh
+ *
+ * \brief Definition of a image with a signle value.
+ *
+ * \todo Zed: Address the values v. destination issue.
+ */
+
+# include <mln/core/internal/image_primary.hh>
+
+
+namespace mln
+{
+
+
+ // Forward declaration.
+ template <typename T, typename S> class flat_image;
+
+
+ namespace internal
+ {
+
+ /// \internal Data structure for \c mln::flat_image<T,S>.
+ template <typename T, typename S>
+ struct data< flat_image<T,S> >
+ {
+ data(const T& val, const S& pset);
+
+ T val_;
+ S pset_;
+ };
+
+ } // end of namespace mln::internal
+
+
+
+ namespace trait
+ {
+
+ template <typename T, typename S>
+ struct image_< flat_image<T,S> > : default_image_< T, flat_image<T,S> >
+ {
+ // misc
+ typedef trait::image::category::primary category;
+ typedef trait::image::speed::fast speed;
+ typedef trait::image::size::regular size;
+
+ // value
+ typedef trait::image::value_access::direct value_access;
+ typedef trait::image::value_storage::one_block value_storage;
+ typedef trait::image::value_browsing::site_wise_only value_browsing;
+ typedef trait::image::value_io::read_only value_io;
+
+ // site / domain
+ typedef trait::image::localization::basic_grid localization; // FIXME
+ typedef trait::image::dimension::two_d dimension; // FIXME
+
+ // extended domain
+ typedef trait::image::ext_domain::infinite ext_domain;
+ typedef trait::image::ext_value::single ext_value;
+ typedef trait::image::ext_io::read_only ext_io;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename T, typename S>
+ struct flat_image : public internal::image_primary< S, flat_image<T,S> >
+ {
+ /// Skeleton.
+ typedef flat_image< tag::value_<T>, tag::pset_<S> > skeleton;
+
+
+ /// Value associated type.
+ typedef T value;
+
+ /// Return type of read-only access.
+ typedef const T& rvalue;
+
+ /// Return type of read-write access.
+ typedef const T& lvalue;
+
+
+ /// Constructor without argument.
+ flat_image();
+
+ /// Constructor.
+ flat_image(const T& val, const S& pset);
+
+ /// Initialization.
+ void init_(const T& val, const S& pset);
+
+ /// Give the definition domain.
+ const S& domain() const;
+
+ /// Test if \p p is valid: always return true.
+ bool has(const mln_psite(S)& p) const;
+
+
+ /// Read-only access to the image value located at point \p p.
+ const T& operator()(const mln_psite(S)& p) const;
+
+ /// Read-write access to the image value located at point \p p.
+ const T& operator()(const mln_psite(S)& p);
+
+
+ // FIXME: Weird...
+
+ /// Value_Set associated type.
+ typedef mln::value::set<T> vset;
+
+ /// Give the set of values of the image.
+ const mln::value::set<T>& values() const;
+
+ // end of FIXME
+
+
+ /// Change the image value.
+ void change_value(const T& val);
+ };
+
+
+
+ template <typename T, typename S, typename J>
+ void init_(tag::image_t, flat_image<T,S>& target, const J& model);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // init_
+
+ template <typename T, typename S, typename J>
+ inline
+ void init_(tag::image_t, flat_image<T,S>& target, const J& model)
+ {
+ S pset;
+ init_(tag::domain, pset, model);
+ T dummy;
+ target.init_(dummy, pset);
+ }
+
+
+ // internal::data< flat_image<T,S> >
+
+ namespace internal
+ {
+
+ template <typename T, typename S>
+ inline
+ data< flat_image<T,S> >::data(const T& val, const S& pset)
+ : val_(val),
+ pset_(pset)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+
+ // flat_image<T,S>
+
+ template <typename T, typename S>
+ inline
+ flat_image<T,S>::flat_image()
+ {
+ }
+
+ template <typename T, typename S>
+ inline
+ flat_image<T,S>::flat_image(const T& val, const S& pset)
+ {
+ init_(val, pset);
+ }
+
+ template <typename T, typename S>
+ inline
+ void
+ flat_image<T,S>::init_(const T& val, const S& pset)
+ {
+ mln_precondition(! this->has_data());
+ this->data_ = new internal::data< flat_image<T,S> >(val, pset);
+ }
+
+ template <typename T, typename S>
+ inline
+ const S&
+ flat_image<T,S>::domain() const
+ {
+ return this->data_->pset_;
+ }
+
+ template <typename T, typename S>
+ inline
+ bool
+ flat_image<T,S>::has(const mln_psite(S)&) const
+ {
+ return true;
+ }
+
+ template <typename T, typename S>
+ inline
+ const T&
+ flat_image<T,S>::operator()(const mln_psite(S)& p) const
+ {
+ mln_precondition(this->has_data());
+ return this->data_->val_;
+ }
+
+ template <typename T, typename S>
+ inline
+ const T&
+ flat_image<T,S>::operator()(const mln_psite(S)& p)
+ {
+ mln_precondition(this->has_data());
+ return this->data_->val_;
+ }
+
+ template <typename T, typename S>
+ inline
+ const mln::value::set<T>&
+ flat_image<T,S>::values() const
+ {
+ return vset::the();
+ }
+
+ template <typename T, typename S>
+ inline
+ void
+ flat_image<T,S>::change_value(const T& val)
+ {
+ mln_precondition(this->has_data());
+ this->data_->val_ = val;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_FLAT_IMAGE_HH
Index: mln/core/image/extension_val.hh
--- mln/core/image/extension_val.hh (revision 0)
+++ mln/core/image/extension_val.hh (revision 0)
@@ -0,0 +1,240 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_EXTENSION_VAL_HH
+# define MLN_CORE_IMAGE_EXTENSION_VAL_HH
+
+/*!
+ * \file mln/core/image/extension_val.hh
+ *
+ * \brief Definition of a morpher that extends the domain of an image.
+ *
+ * \todo Use the 'instant' mechanism.
+ */
+
+# include <mln/core/internal/image_identity.hh>
+# include <mln/metal/converts_to.hh>
+
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I> struct extension_val;
+
+
+ namespace internal
+ {
+
+ /// \internal Data structure for \c mln::extension_val<I>.
+ template <typename I>
+ struct data< extension_val<I> >
+ {
+ data(I& ima, const mln_value(I)& val_);
+
+ I ima_;
+ mln_value(I) val_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I>
+ struct image_< extension_val<I> > : image_< I > // Same as I except...
+ {
+ // ...these changes.
+ typedef trait::image::category::identity_morpher category;
+ typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest.
+
+ // extended domain
+ typedef trait::image::ext_domain::infinite ext_domain;
+ typedef trait::image::ext_value::single ext_value;
+ typedef trait::image::ext_io::read_write ext_io;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ // FIXME: Doc!
+
+ template <typename I>
+ class extension_val : public internal::image_identity< I, mln_pset(I), extension_val<I> >
+ {
+ public:
+
+ /// Skeleton.
+ typedef extension_val< tag::image_<I> > skeleton;
+ // FIXME: OK when ch_value?
+
+
+ /// Return type of read-only access.
+ typedef mln_value(I) rvalue;
+
+
+ /// Constructor without argument.
+ extension_val();
+
+ /// Constructor from an image \p ima and a value \p val.
+ extension_val(I& ima, const mln_value(I)& val);
+
+ /// Deferred initialization from an image \p ima and a value \p
+ /// val.
+ void init(I& ima, const mln_value(I)& val);
+
+
+ /// Test if \p p is valid. It returns always true.
+ // Tech note: the 'template' allows for multiple input.
+ template <typename P>
+ bool has(const P& p) const;
+
+
+ /// Read-only access to the image value located at site \p p;
+ mln_value(I) operator()(const mln_psite(I)& p) const;
+
+ /// Read-write access to the image value located at site \p p.
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
+
+
+ /// Read-only access to the value of the extension domain.
+ const mln_value(I)& extension_value() const;
+
+ /// Change the value of the extension domain.
+ void change_extension_value(const mln_value(I)& val);
+ };
+
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // internal::data< extension_val<I,S> >
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ data< extension_val<I> >::data(I& ima, const mln_value(I)& val)
+ : ima_(ima),
+ val_(val)
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ // extension_val<I>
+
+ template <typename I>
+ inline
+ extension_val<I>::extension_val()
+ {
+ }
+
+ template <typename I>
+ inline
+ extension_val<I>::extension_val(I& ima, const mln_value(I)& val)
+ {
+ init(ima, val);
+ }
+
+ template <typename I>
+ inline
+ void
+ extension_val<I>::init(I& ima, const mln_value(I)& val)
+ {
+ this->data_ = new internal::data< extension_val<I> >(ima, val);
+ }
+
+ template <typename I>
+ template <typename P>
+ inline
+ bool
+ extension_val<I>::has(const P&) const
+ {
+ return true;
+ }
+
+ template <typename I>
+ inline
+ mln_value(I)
+ extension_val<I>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->has_data());
+ // if-else is preferred to the ternary op to allow conversions.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ return this->data_->val_;
+ }
+
+ template <typename I>
+ inline
+ mln_morpher_lvalue(I)
+ extension_val<I>::operator()(const mln_psite(I)& p)
+ {
+ static mln_value(I) cpy;
+ mln_precondition(this->has_data());
+ // See the above comment about if-else v. ternary.
+ if (this->data_->ima_.domain().has(p))
+ return this->data_->ima_(p);
+ else
+ {
+ // This hack makes the extension value non-modifiable.
+ cpy = this->data_->val_;
+ return cpy;
+ }
+ }
+
+ template <typename I>
+ inline
+ const mln_value(I)&
+ extension_val<I>::extension_value() const
+ {
+ mln_precondition(this->has_data());
+ return this->data_->val_;
+ }
+
+ template <typename I>
+ inline
+ void
+ extension_val<I>::change_extension_value(const mln_value(I)& val)
+ {
+ mln_precondition(this->has_data());
+ this->data_->val_ = val;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_IMAGE_EXTENSION_VAL_HH
Index: mln/core/image/instant.hh
--- mln/core/image/instant.hh (revision 2159)
+++ mln/core/image/instant.hh (working copy)
@@ -28,7 +28,7 @@
#ifndef MLN_CORE_IMAGE_INSTANT_HH
# define MLN_CORE_IMAGE_INSTANT_HH
-/*! \file mln/core/instant.hh
+/*! \file mln/core/image/instant.hh
*
* \brief Definition of a morpher that prevent an image from sharing
* his data.
Index: mln/core/site_set/p_key.hh
--- mln/core/site_set/p_key.hh (revision 2159)
+++ mln/core/site_set/p_key.hh (working copy)
@@ -88,12 +88,12 @@
/// Forward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_fwd_iter(util::set<K>),
+ mln_fwd_eiter(util::set<K>),
mln_fwd_piter(p_set<P>)> fwd_piter;
/// Backward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_bkd_iter(util::set<K>),
+ mln_bkd_eiter(util::set<K>),
mln_bkd_piter(p_set<P>)> bkd_piter;
/// Site_Iterator associated type.
@@ -439,7 +439,7 @@
// Update b_.
{
util::set<K> new_b;
- mln_iter(util::set<K>) k(b_);
+ mln_eiter(util::set<K>) k(b_);
for_all(k)
new_b.insert(lut[k] = f(k));
b_ = new_b;
@@ -570,7 +570,7 @@
}
unsigned n = 0;
- mln_iter(util::set<K>) key(b_);
+ mln_eiter(util::set<K>) key(b_);
for_all(key)
{
typename s_t::const_iterator k_s = s_.find(key);
Index: mln/core/site_set/p_mutable_array_of.hh
--- mln/core/site_set/p_mutable_array_of.hh (revision 2159)
+++ mln/core/site_set/p_mutable_array_of.hh (working copy)
@@ -91,12 +91,12 @@
/// Forward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_fwd_iter(array_),
+ mln_fwd_eiter(array_),
mln_fwd_piter(S)> fwd_piter;
/// Backward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_bkd_iter(array_),
+ mln_bkd_eiter(array_),
mln_bkd_piter(S)> bkd_piter;
/// Site_Iterator associated type.
Index: mln/core/site_set/p_set_of.hh
--- mln/core/site_set/p_set_of.hh (revision 2159)
+++ mln/core/site_set/p_set_of.hh (working copy)
@@ -88,12 +88,12 @@
/// Forward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_fwd_iter(set_),
+ mln_fwd_eiter(set_),
mln_fwd_piter(S)> fwd_piter;
/// Backward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_bkd_iter(set_),
+ mln_bkd_eiter(set_),
mln_bkd_piter(S)> bkd_piter;
/// Site_Iterator associated type.
Index: mln/core/safe.hh
--- mln/core/safe.hh (revision 2159)
+++ mln/core/safe.hh (working copy)
@@ -84,7 +84,6 @@
template <typename I>
class safe_image : public internal::image_identity< I, mln_pset(I), safe_image<I> >
{
- typedef internal::image_identity< I, mln_pset(I), safe_image<I> > super_;
public:
/// Skeleton.
@@ -96,8 +95,7 @@
mln_rvalue(I) operator()(const mln_psite(I)& p) const;
- typedef typename super_::lvalue lvalue;
- lvalue operator()(const mln_psite(I)& p);
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
/// Const promotion via conversion.
operator safe_image<const I>() const;
Index: mln/core/routine/extend.hh
--- mln/core/routine/extend.hh (revision 0)
+++ mln/core/routine/extend.hh (revision 0)
@@ -0,0 +1,157 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_ROUTINE_EXTEND_HH
+# define MLN_CORE_ROUTINE_EXTEND_HH
+
+/*!
+ * \file mln/core/routine/extend.hh
+ *
+ * \brief Definition of a morpher that extends the domain of an image.
+ *
+ * \todo Use the 'instant' mechanism.
+ * \todo Deal with ambiguities.
+ */
+
+# include <mln/core/image/extension_ima.hh>
+# include <mln/core/image/extension_fun.hh>
+# include <mln/core/image/extension_val.hh>
+
+
+
+namespace mln
+{
+
+
+ /// Routines for domain extension with a function.
+
+ template <typename I, typename F>
+ extension_fun<const I, F>
+ extend(const Image<I>& ima, const Function_v2v<F>& fun);
+
+ template <typename I, typename F>
+ extension_fun<I, F>
+ extend(Image<I>& ima, const Function_v2v<F>& fun);
+
+
+ /// Routines for domain extension with an image.
+
+ template <typename I, typename J>
+ extension_ima<const I, const J>
+ extend(const Image<I>& ima, const Image<J>& ext);
+
+ template <typename I, typename J>
+ extension_ima<I, J>
+ extend(Image<I>& ima, Image<J>& ext);
+
+
+ /// Routines for domain extension with a value.
+
+ template <typename I>
+ extension_val<const I>
+ extend(const Image<I>& ima, const mln_value(I)& val);
+
+ template <typename I>
+ extension_val<I>
+ extend(Image<I>& ima, const mln_value(I)& val);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // With a function.
+
+ template <typename I, typename F>
+ inline
+ extension_fun<const I, F>
+ extend(const Image<I>& ima, const Function_v2v<F>& fun)
+ {
+ mlc_converts_to(mln_result(F), mln_value(I))::check();
+ extension_fun<const I, F> tmp(exact(ima), exact(fun));
+ return tmp;
+ }
+
+ template <typename I, typename F>
+ inline
+ extension_fun<I, F>
+ extend(Image<I>& ima, const Function_v2v<F>& fun)
+ {
+ mlc_converts_to(mln_result(F), mln_value(I))::check();
+ extension_fun<I, F> tmp(exact(ima), exact(fun));
+ return tmp;
+ }
+
+
+ // With an image.
+
+ template <typename I, typename J>
+ extension_ima<const I, const J>
+ extend(const Image<I>& ima, const Image<J>& ext)
+ {
+ mlc_converts_to(mln_value(J), mln_value(I))::check();
+ extension_ima<const I, const J> tmp(exact(ima), exact(ext));
+ return tmp;
+ }
+
+ template <typename I, typename J>
+ extension_ima<I, J>
+ extend(Image<I>& ima, Image<J>& ext)
+ {
+ mlc_converts_to(mln_value(J), mln_value(I))::check();
+ extension_ima<I, J> tmp(exact(ima), exact(ext));
+ return tmp;
+ }
+
+
+ // With a value.
+
+ template <typename I>
+ inline
+ extension_val<const I>
+ extend(const Image<I>& ima, const mln_value(I)& val)
+ {
+ extension_val<const I> tmp(exact(ima), val);
+ return tmp;
+ }
+
+ template <typename I>
+ inline
+ extension_val<I>
+ extend(Image<I>& ima, const mln_value(I)& val)
+ {
+ extension_val<I> tmp(exact(ima), val);
+ return tmp;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_ROUTINE_EXTEND_HH
Index: mln/core/routine/all.hh
--- mln/core/routine/all.hh (revision 0)
+++ mln/core/routine/all.hh (revision 0)
@@ -0,0 +1,45 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_ROUTINE_ALL_HH
+# define MLN_CORE_ROUTINE_ALL_HH
+
+/*! \file mln/core/routine/all.hh
+ *
+ * \brief File that includes all core routines.
+ *
+ * \todo Move files, update, and activate.
+ */
+
+
+// # include <mln/core/routine/clone.hh>
+// # include <mln/core/routine/exact.hh>
+# include <mln/core/routine/extend.hh>
+// # include <mln/core/routine/initialize.hh>
+
+
+#endif // ! MLN_CORE_ROUTINE_ALL_HH
Index: mln/core/p_runs.hh
--- mln/core/p_runs.hh (revision 2159)
+++ mln/core/p_runs.hh (working copy)
@@ -99,12 +99,12 @@
/// Forward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_fwd_iter(set_),
+ mln_fwd_eiter(set_),
mln_fwd_piter(p_run<P>)> fwd_piter;
/// Backward Site_Iterator associated type.
typedef p_double_piter<self_,
- mln_bkd_iter(set_),
+ mln_bkd_eiter(set_),
mln_bkd_piter(p_run<P>)> bkd_piter;
/// Site_Iterator associated type.
Index: mln/util/set.hh
--- mln/util/set.hh (revision 2159)
+++ mln/util/set.hh (working copy)
@@ -89,13 +89,13 @@
/// Forward iterator associated type.
- typedef set_fwd_iter<T> fwd_iter;
+ typedef set_fwd_iter<T> fwd_eiter;
/// Backward iterator associated type.
- typedef set_bkd_iter<T> bkd_iter;
+ typedef set_bkd_iter<T> bkd_eiter;
/// Iterator associated type.
- typedef fwd_iter iter;
+ typedef fwd_eiter eiter;
/*! \brief Insert an element \p elt into the set.
Index: mln/util/array.hh
--- mln/util/array.hh (revision 2159)
+++ mln/util/array.hh (working copy)
@@ -74,13 +74,13 @@
/// Forward iterator associated type.
- typedef array_fwd_iter<T> fwd_iter;
+ typedef array_fwd_iter<T> fwd_eiter;
/// Backward iterator associated type.
- typedef array_bkd_iter<T> bkd_iter;
+ typedef array_bkd_iter<T> bkd_eiter;
/// Iterator associated type.
- typedef fwd_iter iter;
+ typedef fwd_eiter eiter;
/// Constructor without arguments.
Index: sandbox/geraud/p_runs__with_dedicated_piter.hh
--- sandbox/geraud/p_runs__with_dedicated_piter.hh (revision 2159)
+++ sandbox/geraud/p_runs__with_dedicated_piter.hh (working copy)
@@ -31,10 +31,6 @@
/*! \file mln/core/p_runs.hh
*
* \brief Definition of a set of point runs.
- *
- * \todo Zed: Use p_double* stuff.
- *
- * \todo Zed: Test for unicity (see FIXMEs).
*/
# include <mln/accu/bbox.hh>
1
0