
https://svn.lrde.epita.fr/svn/oln/trunk/olena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Make 'inplace' mandatory and start a tour. * doc: New directory. * doc/tour: New sub-directory. * doc/tour/tour1_extra.cc: New. * doc/tour/tour1.cc: New. * tests/core/image1d.cc: Remove unused decl and update. * tests/core/image2d.cc: Use namespace. * tests/core/image3d.cc: Update. * tests/algorithms/basic_morpho.cc: Remove hack. Update includes. * oln/debug/print.hh (print_1D): New. * tests/core/stack.cc, * tests/algorithms/fill.cc, * oln/debug/iota.hh, * oln/draw/bresenham.hh, * oln/level/fill.hh, * oln/level/clone.hh, * oln/level/apply_inplace.hh: Update. * oln/core/1d/image1d.hh (prepare): New. * oln/core/1d/image1d_b.hh (prepare): New. * oln/core/internal/symmetrical_window.hh: New. * oln/core/internal/window.hh (impl_take): New. (take): Call impl_take. * oln/core/2d/vline2d.hh, * oln/core/2d/hline2d.hh, * oln/core/2d/rectangle2d.hh: Update. * oln/core/2d/neighb2d.hh: Add FIXMEs. * oln/core/gen/inplace.hh (inplace): New overload. * oln/core/concept/image.hh (is_empty): New in Image. (min_ind, max_ind, ninds): New in Image_1D. * oln/core/concept/function.hh: Remove obsolete commented code. * oln/core/concept/image_identity.hh: Cosmetic change. * oln/core/internal/image_selectors.hh (Image_dimension): Handle 1D and 3D cases. * oln/core/internal/image_base.hh (impl_is_empty): New. * oln/core/internal/op_image_extended_by_nbh.hh (init_): New overload. (init_): Unconst nbh in the Neighborhood version. * oln/core/internal/special_op.hh: Cosmetic change. * oln/morpho/cc_tarjan.hh: Fix. doc/tour/tour1.cc | 322 ++++++++++++++++++++++++++ doc/tour/tour1_extra.cc | 212 +++++++++++++++++ oln/core/1d/image1d.hh | 26 ++ oln/core/1d/image1d_b.hh | 17 + oln/core/2d/hline2d.hh | 14 - oln/core/2d/neighb2d.hh | 2 oln/core/2d/rectangle2d.hh | 15 - oln/core/2d/vline2d.hh | 14 - oln/core/concept/function.hh | 48 --- oln/core/concept/image.hh | 43 +++ oln/core/gen/inplace.hh | 14 + oln/core/internal/image_base.hh | 9 oln/core/internal/image_selectors.hh | 24 + oln/core/internal/op_image_extended_by_nbh.hh | 17 + oln/core/internal/special_op.hh | 4 oln/core/internal/symmetrical_window.hh | 111 ++++++++ oln/core/internal/window.hh | 17 + oln/debug/iota.hh | 19 + oln/debug/print.hh | 39 +++ oln/draw/bresenham.hh | 27 +- oln/level/apply_inplace.hh | 23 - oln/level/clone.hh | 4 oln/level/fill.hh | 68 +---- oln/morpho/cc_tarjan.hh | 8 tests/algorithms/basic_morpho.cc | 14 - tests/algorithms/fill.cc | 2 tests/core/image1d.cc | 5 tests/core/image2d.cc | 20 - tests/core/image3d.cc | 24 - tests/core/stack.cc | 3 30 files changed, 977 insertions(+), 188 deletions(-) Index: tests/core/stack.cc --- tests/core/stack.cc (revision 948) +++ tests/core/stack.cc (working copy) @@ -45,7 +45,8 @@ typedef image2d<int> I; I ima_0(3, 3), ima_1(3, 3); - level::fill(stack(ima_0, ima_1).inplace(), coords); + image_stack<2,I> ima = stack(ima_0, ima_1); + level::fill(inplace(ima), coords); { I::piter p(ima_0.points()); for_all(p) Index: tests/core/image1d.cc --- tests/core/image1d.cc (revision 948) +++ tests/core/image1d.cc (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2006 EPITA Research and Development Laboratory +// Copyright (C) 2006, 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 @@ -38,7 +38,6 @@ // Fill a 1D image using its iterator. image1d<char> ima1(3); - image1d<char>::box box1 = ima1.points(); image1d<char>::piter p1 (ima1.points()); for_all(p1) ima1(p1) = 1; @@ -50,7 +49,7 @@ // Fill a 1D image using the routine level::fill. image1d<long> ima3(ima1.points()); - level::fill(ima3, 3); + level::fill(inplace(ima3), 3); // Add the three images. Index: tests/core/image2d.cc --- tests/core/image2d.cc (revision 948) +++ tests/core/image2d.cc (working copy) @@ -28,34 +28,34 @@ /// Test oln::image2d. #include <cassert> -// FIXME: We should not include oln/basics2d.hh, but -// oln/core/2d/image2d.hh (and oln/core/2d/neigh2d.hh ?). #include <oln/core/2d/image2d.hh> #include <oln/level/fill.hh> int main() { + using namespace oln; + // Fill a 2D image using its iterator. - oln::image2d<char> ima1(3, 3); - oln::image2d<char>::piter p1(ima1.points()); + image2d<char> ima1(3, 3); + image2d<char>::piter p1(ima1.points()); for_all(p1) ima1(p1) = 1; // Fill a 2D image using a classic loop. - oln::image2d<int> ima2(ima1.points()); + image2d<int> ima2(ima1.points()); for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) ima2.at(i, j) = 2; - // Fill a 2D image using the routine oln::level::fill. - oln::image2d<long> ima3(ima1.points()); - oln::level::fill(ima3, 3); + // Fill a 2D image using the routine level::fill. + image2d<long> ima3(ima1.points()); + level::fill(inplace(ima3), 3); // Add the three images. - oln::image2d<long> sum(ima1.points()); - oln::image2d<long>::piter p(sum.points()); + image2d<long> sum(ima1.points()); + image2d<long>::piter p(sum.points()); for_all(p) sum(p) = ima1(p) + ima2(p) + ima3(p); // And check the sum. Index: tests/core/image3d.cc --- tests/core/image3d.cc (revision 948) +++ tests/core/image3d.cc (working copy) @@ -28,35 +28,35 @@ /// Test oln::image3d. #include <cassert> -// FIXME: We should not include oln/basics3d.hh, but -// oln/core/3d/image3d.hh (and oln/core/3d/neigh3d.hh ?). -#include <oln/basics3d.hh> +#include <oln/core/3d/image3d.hh> #include <oln/level/fill.hh> int main() { + using namespace oln; + // Fill a 3D image using its iterator. - oln::image3d<char> ima1(3, 3, 3); - oln_vtype_(oln::image3d<char>, piter) p1(ima1.topo()); + image3d<char> ima1(3, 3, 3); + image3d<char>::piter p1(ima1.points()); for_all(p1) ima1(p1) = 1; // Fill a 3D image using a classic loop. - oln::image3d<int> ima2(ima1.topo()); + image3d<int> ima2(ima1.points()); for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j < 3; ++j) for (unsigned k = 0; k < 3; ++k) - ima2(oln::point3d(i, j, k)) = 2; + ima2.at(i, j, k) = 2; - // Fill a 3D image using the routine oln::level::fill. - oln::image3d<long> ima3(ima1.topo()); - oln::level::fill(ima3, 3); + // Fill a 3D image using the routine level::fill. + image3d<long> ima3(ima1.points()); + level::fill(inplace(ima3), 3); // Add the three images. - oln::image3d<long> sum(ima1.topo()); - oln_vtype_(oln::image3d<long>, piter) p(sum.topo()); + image3d<long> sum(ima1.points()); + image3d<long>::piter p(sum.points()); for_all(p) sum(p) = ima1(p) + ima2(p) + ima3(p); // And check the sum. Index: tests/algorithms/basic_morpho.cc --- tests/algorithms/basic_morpho.cc (revision 948) +++ tests/algorithms/basic_morpho.cc (working copy) @@ -1,8 +1,12 @@ #include <oln/core/2d/image2d.hh> -#include <oln/core/2d/window2d.hh> #include <oln/core/2d/neighb2d.hh> +#include <oln/core/2d/window2d.hh> +#include <oln/core/2d/rectangle2d.hh> +#include <oln/core/2d/hline2d.hh> +#include <oln/core/2d/vline2d.hh> + #include <oln/morpho/elementary_dilation.hh> #include <oln/morpho/elementary_erosion.hh> @@ -40,13 +44,13 @@ for_all(p1) ima(p1) = i++ % 2; - my_test( (morpho::elementary_erosion(ima + c4)).image(), 0); + my_test( morpho::elementary_erosion(ima + c4), 0); - my_test( (morpho::elementary_dilation(ima + c4)).image(), 1 ); + my_test( morpho::elementary_dilation(ima + c4), 1 ); - my_test( (morpho::elementary_opening(ima + c4)).image(), 0); + my_test( morpho::elementary_opening(ima + c4), 0); - my_test( (morpho::elementary_closing(ima + c4)).image(), 1); + my_test( morpho::elementary_closing(ima + c4), 1); my_test( morpho::erosion(ima, win3x3), 0); Index: tests/algorithms/fill.cc --- tests/algorithms/fill.cc (revision 948) +++ tests/algorithms/fill.cc (working copy) @@ -38,7 +38,7 @@ using namespace oln; typedef image2d<int> image_t; image_t ima(3, 3); - level::fill(ima, 51); + level::fill(inplace(ima), 51); image_t::piter p(ima.points()); for_all(p) assert(ima(p) = 51); Index: doc/tour/tour1_extra.cc --- doc/tour/tour1_extra.cc (revision 0) +++ doc/tour/tour1_extra.cc (revision 0) @@ -0,0 +1,212 @@ +// 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> + + +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 automatically is + // 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(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' disapears. + + + + + + // Example 4: + + { + image1d<int> ima(5); + for (int i = 0; i < 5; ++i) + ima(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, which is unreachable, are deallocated and + // the temporary 'anon' disappears; we end up with: + // + // +-----------+ + // ima ---> | 0 2 4 6 8 | + // +-----------+ +} Index: doc/tour/tour1.cc --- doc/tour/tour1.cc (revision 0) +++ doc/tour/tour1.cc (revision 0) @@ -0,0 +1,322 @@ +w// 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(0) = 7; // Assign value 7 to the 1st pixel of img1a. + img1a(10) = 51; // Assign value 51 to the 11th pixel of img1a. + + std::cout << "img1b(10) = " << img1b(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(5) = 19; // so img2a(5) is set to 19. + + img = img2b; // img is NOW img2b + img(5) = 69; // so img2b(5) is set to 69. + + std::cout << (100 * img2a(5) + img2b(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 inportant 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(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 avoids to provide a wrong + // value for the minimum or maximum index value: + for (int i = img3b.min_ind(); i <= img3b.max_ind(); ++i) + img3b(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 explains + // 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: oln/debug/print.hh --- oln/debug/print.hh (revision 948) +++ oln/debug/print.hh (working copy) @@ -83,6 +83,44 @@ +# ifdef OLN_ENV_1D + + /// Default version. + + template <typename I> + void print_1D(const Image<I>&, const I& input, std::ostream& ostr) + { + print_Gen(input, ostr); + } + + /// Version for classical 1D images. + + template <typename I> + void print_1D(const Point_Wise_Accessible_Image<I>&, const I& input, + std::ostream& ostr) + { + const oln_coord(I) + imin = input.min_ind(), + imax = input.max_ind(); + for (oln_coord(I) i = imin; i <= imax; ++i) + { + if (input.has(i)) + ostr << format(input(i)); + else + ostr << '-'; + ostr << ' '; + } + } + + template <typename I> + void print(const Image_1D<I>& input, std::ostream& ostr) + { + impl::print_1D(exact(input), exact(input), ostr); + } + +# endif // OLN_ENV_1D + + # ifdef OLN_ENV_2D /// Default version. @@ -128,7 +166,6 @@ # endif // OLN_ENV_2D - } // end of namespace oln::debug::impl Index: oln/debug/iota.hh --- oln/debug/iota.hh (revision 948) +++ oln/debug/iota.hh (working copy) @@ -39,16 +39,16 @@ { template <typename I> - void iota(Mutable_Image<I>& in_out); - - template <typename I> void iota(inplace_<I> in_out); # ifndef OLN_INCLUDE_ONLY + namespace impl + { + template <typename I> - void iota(Mutable_Image<I>& in_out) + void iota_(Mutable_Image<I>& in_out) { oln_value(I) v = 0; oln_fwd_piter(I) p(in_out.points()); @@ -56,10 +56,19 @@ in_out(p) = v++; } + } // end of namespace oln::debug::impl + template <typename I> void iota(inplace_<I> in_out) { - iota(in_out.unwrap()); + impl::iota_(in_out.unwrap()); + } + + // guard + template <typename I> + void iota(const Image<I>&) + { + mlc::abort_<I>::check(); // FIXME: Add err msg. } # endif // ! OLN_INCLUDE_ONLY Index: oln/core/1d/image1d.hh --- oln/core/1d/image1d.hh (revision 948) +++ oln/core/1d/image1d.hh (working copy) @@ -85,6 +85,7 @@ image1d(); image1d(const box1d& b); + image1d(const point1d& pmin, const point1d& pmax); image1d(unsigned n); bool impl_owns_(const point1d& p) const; @@ -102,6 +103,9 @@ const box1d& impl_points() const; }; + template <typename T, typename D> + bool prepare(image1d<T>& target, with_t, const D& dat); + # ifndef OLN_INCLUDE_ONLY @@ -119,6 +123,15 @@ } template <typename T> + image1d<T>::image1d(const point1d& pmin, const point1d& pmax) + { + precondition(pmax >= pmin); + box1d b(pmin, pmax); + this->data_ = new data(new array_t(pmin.ind(), pmax.ind()), + b); + } + + template <typename T> image1d<T>::image1d(unsigned n) { precondition(n != 0); @@ -185,6 +198,19 @@ return this->data_->second; } + template <typename T, typename D> + bool prepare(image1d<T>& target, with_t, const D& dat) + { + precondition(not target.has_data()); + box1d b; + bool box_ok = init(b, with, dat); + postcondition(box_ok); + array1d_<T,int>* ptr = new array1d_<T,int>(b.pmin().ind(), + b.pmax().ind()); + target.data__() = new typename image1d<T>::data(ptr, b); + return box_ok; + } + # endif // ! OLN_INCLUDE_ONLY Index: oln/core/1d/image1d_b.hh --- oln/core/1d/image1d_b.hh (revision 948) +++ oln/core/1d/image1d_b.hh (working copy) @@ -107,6 +107,9 @@ unsigned impl_border() const; }; + template <typename T, typename D> + bool prepare(image1d_b<T>& target, with_t, const D& dat); + # ifndef OLN_INCLUDE_ONLY @@ -193,6 +196,20 @@ return this->data_->second; } + template <typename T, typename D> + bool prepare(image1d_b<T>& target, with_t, const D& dat) + { + precondition(not target.has_data()); + box1d b; + bool box_ok = init(b, with, dat); + postcondition(box_ok); + unsigned border = 2; // FIXME: Use init! + array1d_<T,int>* ptr = new array1d_<T,int>(b.pmin().ind() - border, + b.pmax().ind() + border); + target.data__() = new typename image1d_b<T>::data(ptr, border, b); + return box_ok; + } + # endif // ! OLN_INCLUDE_ONLY Index: oln/core/2d/neighb2d.hh --- oln/core/2d/neighb2d.hh (revision 948) +++ oln/core/2d/neighb2d.hh (working copy) @@ -52,6 +52,7 @@ namespace internal { + // FIXME: constify. neighb2d mk_c4(); neighb2d mk_c8(); neighb2d mk_c2_row(); @@ -101,6 +102,7 @@ } // end of namespace oln::internal + // FIXME: constify. extern neighb2d c4; extern neighb2d c8; extern neighb2d c2_row; Index: oln/core/2d/vline2d.hh --- oln/core/2d/vline2d.hh (revision 948) +++ oln/core/2d/vline2d.hh (working copy) @@ -28,7 +28,7 @@ #ifndef OLN_CORE_2D_VLINE2D_HH # define OLN_CORE_2D_VLINE2D_HH -# include <oln/core/internal/window.hh> +# include <oln/core/internal/symmetrical_window.hh> # include <oln/core/2d/dpoint2d.hh> @@ -39,11 +39,13 @@ class vline2d; +# define super internal::symmetrical_window_<vline2d> + // Super type. template <> struct super_trait_< vline2d > { - typedef internal::window_<vline2d> ret; + typedef super ret; }; @@ -57,7 +59,7 @@ /// 2D vertical line window. - class vline2d : public internal::window_< vline2d > + class vline2d : public super { public: @@ -66,7 +68,7 @@ private: void init_(int drow_min, int drow_max); - void take(); // safety; w/o impl, it provides from calling super::take(dp). + void impl_take(); // safety; w/o impl, it provides from calling take(dp). }; // end of class oln::vline2d @@ -90,11 +92,13 @@ vline2d::init_(int drow_min, int drow_max) { for (int drow = drow_min; drow <= drow_max; ++drow) - this->internal::window_<vline2d>::take(dpoint2d(drow, 0)); + this->super::impl_take(dpoint2d(drow, 0)); } # endif // ! OLN_INCLUDE_ONLY +#undef super + } // end of namespace oln Index: oln/core/2d/hline2d.hh --- oln/core/2d/hline2d.hh (revision 948) +++ oln/core/2d/hline2d.hh (working copy) @@ -28,7 +28,7 @@ #ifndef OLN_CORE_2D_HLINE2D_HH # define OLN_CORE_2D_HLINE2D_HH -# include <oln/core/internal/window.hh> +# include <oln/core/internal/symmetrical_window.hh> # include <oln/core/2d/dpoint2d.hh> @@ -39,11 +39,13 @@ class hline2d; +# define super internal::symmetrical_window_<hline2d> + // Super type. template <> struct super_trait_< hline2d > { - typedef internal::window_<hline2d> ret; + typedef super ret; }; @@ -57,7 +59,7 @@ /// 2D horizontal line window. - class hline2d : public internal::window_< hline2d > + class hline2d : public super { public: @@ -65,7 +67,7 @@ private: void init_(int dcol_min, int dcol_max); - void take(); // safety; w/o impl, it provides from calling super::take(dp). + void impl_take(); // safety; w/o impl, it prevents from calling take(dp). }; // end of class oln::hline2d @@ -83,11 +85,13 @@ hline2d::init_(int dcol_min, int dcol_max) { for (int dcol = dcol_min; dcol <= dcol_max; ++dcol) - this->internal::window_<hline2d>::take(dpoint2d(0, dcol)); + this->super::impl_take(dpoint2d(0, dcol)); } # endif // ! OLN_INCLUDE_ONLY +# undef super + } // end of namespace oln Index: oln/core/2d/rectangle2d.hh --- oln/core/2d/rectangle2d.hh (revision 948) +++ oln/core/2d/rectangle2d.hh (working copy) @@ -28,7 +28,7 @@ #ifndef OLN_CORE_2D_RECTANGLE2D_HH # define OLN_CORE_2D_RECTANGLE2D_HH -# include <oln/core/internal/window.hh> +# include <oln/core/internal/symmetrical_window.hh> # include <oln/core/2d/dpoint2d.hh> @@ -39,11 +39,13 @@ class rectangle2d; +# define super internal::symmetrical_window_<rectangle2d> + // Super type. template <> struct super_trait_< rectangle2d > { - typedef internal::window_<rectangle2d> ret; + typedef super ret; }; @@ -57,7 +59,7 @@ /// 2D rectangular window. - class rectangle2d : public internal::window_< rectangle2d > + class rectangle2d : public super { public: @@ -70,10 +72,11 @@ private: void init_(int drow_min, int dcol_min, int drow_max, int dcol_max); - void take(); // safety; w/o impl, it provides from calling super::take(dp). unsigned half_height_, half_width_; + void impl_take(); // safety; w/o impl, it prevents from calling take(dp). + }; // end of class oln::rectangle2d @@ -105,11 +108,13 @@ { for (int drow = drow_min; drow <= drow_max; ++drow) for (int dcol = dcol_min; dcol <= dcol_max; ++dcol) - this->internal::window_<rectangle2d>::take(dpoint2d(drow, dcol)); + this->super::impl_take(dpoint2d(drow, dcol)); } # endif // ! OLN_INCLUDE_ONLY +# undef super + } // end of namespace oln Index: oln/core/gen/inplace.hh --- oln/core/gen/inplace.hh (revision 948) +++ oln/core/gen/inplace.hh (working copy) @@ -57,6 +57,11 @@ inplace(Mutable_Image<I>& ima); + template <typename I> + inplace_<I> + inplace(inplace_<I> ima); + + # ifndef OLN_INCLUDE_ONLY @@ -80,6 +85,8 @@ return this->unwrap(); } + // inplace + template <typename I> inplace_<I> inplace(Mutable_Image<I>& ima) @@ -88,6 +95,13 @@ return tmp; } + template <typename I> + inplace_<I> + inplace(inplace_<I> ima) + { + return ima; + } + # endif // ! OLN_INCLUDE_ONLY } // end of namespace oln Index: oln/core/concept/image.hh --- oln/core/concept/image.hh (revision 948) +++ oln/core/concept/image.hh (working copy) @@ -131,7 +131,9 @@ // stc_typename(output); // FIXME: Uncomment! stc_typename(plain); + bool is_empty() const; // Not subject to delegation. bool owns_(const psite& p) const; + rvalue operator()(const psite& p) const; rvalue read_(const psite& p) const; @@ -209,11 +211,16 @@ stc_using_from(Mutable_Image, lvalue); stc_typename(index); + // FIXME: Confusing! We already have indices for 1D images... + // FIXME: Use "offset" instead! rvalue operator[](index i) const; lvalue operator[](index i); std::size_t npoints() const; - // FIXME: ... + + // FIXME: Add: + // point point_at_offset(o) const + // std::size_t offset_from_point(point p) const protected: Fast_Image(); @@ -275,6 +282,11 @@ { stc_typename(coord); + // final + coord min_ind() const; + coord max_ind() const; + unsigned ninds() const; + protected: Image_1D(); }; @@ -443,8 +455,16 @@ template <typename Exact> bool + Image<Exact>::is_empty() const + { + return exact(this)->impl_is_empty(); + } + + template <typename Exact> + bool Image<Exact>::owns_(const typename Image<Exact>::psite& p) const { + precondition(not this->is_empty()); return exact(this)->impl_owns_(p); } @@ -626,6 +646,27 @@ { } + template <typename Exact> + typename Image_1D<Exact>::coord + Image_1D<Exact>::min_ind() const + { + return this->bbox().pmin().ind(); + } + + template <typename Exact> + typename Image_1D<Exact>::coord + Image_1D<Exact>::max_ind() const + { + return this->bbox().pmax().ind(); + } + + template <typename Exact> + unsigned + Image_1D<Exact>::ninds() const + { + return this->bbox().pmax().ind() - this->bbox().pmin().ind() + 1; + } + // ----------------------------------- Image_2D<Exact> template <typename Exact> Index: oln/core/concept/function.hh --- oln/core/concept/function.hh (revision 948) +++ oln/core/concept/function.hh (working copy) @@ -37,18 +37,6 @@ { - /* - - // Fwd decl. - namespace morpher { - template <typename I, typename F> class two_way; - template <typename I, typename F> class two_way_rw; - } - namespace value { template <typename I, typename F> class two_way; } - - */ - - template <typename Exact> struct Function : public Any<Exact> { @@ -90,42 +78,17 @@ }; - /* - // Value1 -> Value2 *and* Value2 -> Value1. template <typename Exact> struct Function_v2w2v : public Function<Exact> { - public: - - template <typename I> - oln::morpher::two_way<I, Exact> - operator()(oln::abstract::mutable_image<I>& input) const; - + typedef Function_v2w2v<void> category; protected: Function_v2w2v(); }; - // (Image, Point) -> Value2 *and* (Image, Point, Value2) -> Value1. - - template <typename Exact> - struct Function_rw : public Function<Exact> - { - public: - - template <typename I> - oln::morpher::two_way_rw<I, Exact> - operator()(oln::abstract::mutable_image<I>& input) const; - - protected: - Function_rw(); - }; - - */ - - // Point -> Point. template <typename Exact> @@ -159,21 +122,12 @@ { } - /* - template <typename Exact> Function_v2w2v<Exact>::Function_v2w2v() { } template <typename Exact> - Function_rw<Exact>::Function_rw() - { - } - - */ - - template <typename Exact> Function_p2p<Exact>::Function_p2p() { } Index: oln/core/concept/image_identity.hh Index: oln/core/internal/image_selectors.hh --- oln/core/internal/image_selectors.hh (revision 948) +++ oln/core/internal/image_selectors.hh (working copy) @@ -28,9 +28,15 @@ #ifndef OLN_CORE_INTERNAL_IMAGE_SELECTORS_HH # define OLN_CORE_INTERNAL_IMAGE_SELECTORS_HH +# include <oln/core/concept/grid.hh> # include <oln/core/concept/image.hh> + +// FIXME: Bad! Move Grid_*D into concept/grid.hh... +# include <oln/core/1d/grid1d.hh> # include <oln/core/2d/grid2d.hh> -# include <oln/value/tags.hh> +# include <oln/core/3d/grid3d.hh> + +# include <oln/value/tags.hh> // FIXME: Bad! namespace oln @@ -69,11 +75,27 @@ template <typename Exact> struct case_< Image_dimension, Exact, 1 > : + where_< stc_is_a(grid, Grid_1D) > + { + typedef Image_1D<Exact> ret; + }; + + template <typename Exact> + struct case_< Image_dimension, Exact, 2 > + : where_< stc_is_a(grid, Grid_2D) > { typedef Image_2D<Exact> ret; }; + template <typename Exact> + struct case_< Image_dimension, Exact, 3 > + : + where_< stc_is_a(grid, Grid_3D) > + { + typedef Image_3D<Exact> ret; + }; + // FIXME: ... Index: oln/core/internal/window.hh --- oln/core/internal/window.hh (revision 948) +++ oln/core/internal/window.hh (working copy) @@ -72,12 +72,16 @@ public: stc_using(point); - typedef typename point::dpoint dpoint; + typedef oln_dpoint(point) dpoint; - window_(); Exact& take(const dpoint& dp); + Exact& impl_take(const dpoint& dp); + Exact impl_op_unary_minus_() const; + protected: + window_(); + }; // end of class oln::internal::window_<Exact> @@ -92,7 +96,14 @@ Exact& window_<Exact>::take(const typename window_<Exact>::dpoint& dp) { - this->take_( dp); + return exact(this)->impl_take(dp); + } + + template <typename Exact> + Exact& + window_<Exact>::impl_take(const typename window_<Exact>::dpoint& dp) + { + this->take_(dp); // from dpoints_impl_. return exact(*this); } Index: oln/core/internal/image_base.hh --- oln/core/internal/image_base.hh (revision 948) +++ oln/core/internal/image_base.hh (working copy) @@ -238,6 +238,7 @@ stc_typename(data); + bool impl_is_empty() const; bool has_data() const; // pseudo-private: @@ -360,9 +361,15 @@ /// image_base_<Exact> template <typename Exact> + bool image_base_<Exact>::impl_is_empty() const + { + return this->data_ = 0; // FIXME: This is not sufficient... + } + + template <typename Exact> bool image_base_<Exact>::has_data() const { - return this->data_ != 0; + return this->data_ != 0; // FIXME: redundant with is_empty? (no) } template <typename Exact> Index: oln/core/internal/op_image_extended_by_nbh.hh --- oln/core/internal/op_image_extended_by_nbh.hh (revision 948) +++ oln/core/internal/op_image_extended_by_nbh.hh (working copy) @@ -28,6 +28,7 @@ #ifndef OLN_CORE_INTERNAL_OP_IMAGE_EXTENDED_BY_NBH_HH # define OLN_CORE_INTERNAL_OP_IMAGE_EXTENDED_BY_NBH_HH +# include <mlc/unconst.hh> # include <oln/core/concept/neighborhood.hh> # include <oln/core/internal/image_base.hh> # include <oln/core/gen/op.hh> @@ -123,10 +124,14 @@ template <typename N, typename I> bool init_(Neighborhood<N>* this_, + const internal::single_image_morpher_<I>& dat); + + template <typename N, typename I> + bool init_(Neighborhood<N>* this_, const internal::current& dat); template <typename I, typename N> - bool init_(Image<I>* this_, + bool init_(Image<I>* this_, // FIXME: Pb with I being "const J"... const internal::current& dat); @@ -186,6 +191,14 @@ template <typename N, typename I> bool init_(Neighborhood<N>* this_, + const internal::single_image_morpher_<I>& data) + { + exact(*this_) = data.nbhood(); + return true; + } + + template <typename N, typename I> + bool init_(Neighborhood<N>* this_, const internal::current& data) { exact(*this_) = data.nbhood(); @@ -220,7 +233,7 @@ precondition(not target.has_data()); target.data__() = new typename op_<I, extended_by, N>::data; bool ima_ok = prepare(target.data__()->first, with, dat); - bool nbh_ok = init(target.data__()->second, with, dat); + bool nbh_ok = init(mlc::unconst_cast(target.data__()->second), with, dat); postcondition(ima_ok); postcondition(nbh_ok); return ima_ok and nbh_ok; Index: oln/core/internal/special_op.hh --- oln/core/internal/special_op.hh (revision 948) +++ oln/core/internal/special_op.hh (working copy) @@ -41,14 +41,14 @@ template <typename L, typename OpName, typename R> class op_; - /// Virtual types. + // Virtual types. template <typename Lcat, typename L, typename OpName, typename Rcat, typename R> struct vtypes< internal::special_op_<Lcat, L, OpName, Rcat, R> > /* undefined; to be specialized... */ ; - /// Super type. + // Super type. template <typename Lcat, typename L, typename OpName, typename Rcat, typename R> struct super_trait_< internal::special_op_<Lcat, L, OpName, Rcat, R> > /* undefined; to be specialized... */ Index: oln/core/internal/symmetrical_window.hh --- oln/core/internal/symmetrical_window.hh (revision 0) +++ oln/core/internal/symmetrical_window.hh (revision 0) @@ -0,0 +1,111 @@ +// 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. + +#ifndef OLN_CORE_INTERNAL_SYMMETRICAL_WINDOW_HH +# define OLN_CORE_INTERNAL_SYMMETRICAL_WINDOW_HH + +# include <oln/core/internal/window.hh> + + +namespace oln +{ + + + // Fwd decl. + namespace internal { template <typename Exact> class symmetrical_window_; } + +#define current symmetrical_window_<Exact> +#define super internal::window_<Exact> + + // Super type. + template <typename Exact> + struct super_trait_< internal::current > + { + typedef super ret; + }; + + + // Virtual types. + template <typename Exact> + struct vtypes< internal::current > + { + }; + + namespace internal + { + + /// Base implementation class for symmetrical window classes. + + template <typename Exact> + class symmetrical_window_ : public super + { + public: + stc_using(dpoint); + + const Exact& impl_op_unary_minus_() const; + Exact& impl_take(const dpoint& dp); + + protected: + symmetrical_window_(); + + }; // end of class oln::internal::symmetrical_window_<Exact> + + +# ifndef OLN_INCLUDE_ONLY + + template <typename Exact> + current::symmetrical_window_() + { + } + + template <typename Exact> + const Exact& + current::impl_op_unary_minus_() const + { + return exact(*this); + } + + template <typename Exact> + Exact& + current::impl_take(const typename current::dpoint& dp) + { + this->super::impl_take(dp); + this->super::impl_take(-dp); + return exact(*this); + } + + } // end of namespace oln::internal + +# endif // ! OLN_INCLUDE_ONLY + +# undef super +# undef current + +} // end of namespace oln + + +#endif // ! OLN_CORE_INTERNAL_SYMMETRICAL_WINDOW_HH Index: oln/draw/bresenham.hh --- oln/draw/bresenham.hh (revision 948) +++ oln/draw/bresenham.hh (working copy) @@ -46,11 +46,6 @@ // Fwd decl. template <typename I> - void bresenham(Mutable_Image<I>& in_out, - const oln_point(I)& begin, const oln_point(I)& end, - const oln_value(I)& value); - - template <typename I> void bresenham(inplace_<I> in_out, const oln_point(I)& begin, const oln_point(I)& end, const oln_value(I)& value); @@ -66,28 +61,32 @@ const oln_point(I)& begin, const oln_point(I)& end, const oln_value(I)& value) { - level::paste(literal(value) / line2d(begin, end), in_out); + level::paste(literal(value) / line2d(begin, end), + inplace(in_out)); } } // end of namespace oln::draw::impl - // Facades. + // Facade. template <typename I> - void bresenham(Mutable_Image<I>& in_out, + void bresenham(inplace_<I> in_out, const oln_point(I)& begin, const oln_point(I)& end, const oln_value(I)& value) { - impl::bresenham_(exact(in_out), begin, end, value); + impl::bresenham_(in_out.unwrap(), begin, end, value); } - template <typename I> - void bresenham(inplace_<I> in_out, - const oln_point(I)& begin, const oln_point(I)& end, - const oln_value(I)& value) + + // Guard. + + template <typename I, typename P, typename V> + void bresenham(const Image<I>&, + const P&, const P&, + const V&) { - bresenham(in_out.unwrap(), begin, end, value); + mlc::abort_<I>::check(); // FIXME: Add err msg. } # endif // ! OLN_INCLUDE_ONLY Index: oln/morpho/cc_tarjan.hh --- oln/morpho/cc_tarjan.hh (revision 948) +++ oln/morpho/cc_tarjan.hh (working copy) @@ -29,6 +29,8 @@ # define OLN_MORPHO_CC_TARJAN_HH # include <oln/core/concept/image.hh> +# include <oln/core/internal/f_ch_value.hh> +# include <oln/level/fill.hh> namespace oln { @@ -116,10 +118,10 @@ oln_plain_value(I, oln_point(I)) parent; prepare(parent, with, input); - oln_plain(I) is_processed; + // init. + oln_plain_value(I, bool) is_processed; prepare(is_processed, with, input); - oln_piter(I) p1(is_processed.points()); - is_processed(p1) = false; // FIXME : built with ?. + level::fill(inplace(is_processed), false); first_pass(input, parent, is_processed); second_pass(input, parent, output); Index: oln/level/fill.hh --- oln/level/fill.hh (revision 948) +++ oln/level/fill.hh (working copy) @@ -53,36 +53,22 @@ // Fwd decls. template <typename I> - void fill(Mutable_Image<I>& target, /* with */ const oln_value(I)& value); + void fill(inplace_<I> target, /* with */ const oln_value(I)& value); template <typename I, typename J> - void fill(Mutable_Image<I>& target, /* with */ const Image<J>& data); + void fill(inplace_<I> target, /* with */ const Image<J>& data); template <typename I, typename F> - void fill(Mutable_Image<I>& target, /* with */ const Function_p2v<F>& fun); + void fill(inplace_<I> target, /* with */ const Function_p2v<F>& fun); template <typename I, typename V, typename P> - void fill(Mutable_Image<I>& target, /* with */ V (*fun)(P)); + void fill(inplace_<I> target, /* with */ V (*f)(P)); // FIXME: Inactivated. // template <typename I> // void fill(Value_Wise_Mutable_Image<I>& target, const oln_value(I)& value); - // versions for temporary images - - template <typename I> - void fill(inplace_<I> target, /* with */ const oln_value(I)& value); - - template <typename I, typename J> - void fill(inplace_<I> target, /* with */ const Image<J>& data); - - template <typename I, typename F> - void fill(inplace_<I> target, /* with */ const Function_p2v<F>& fun); - - template <typename I, typename V, typename P> - void fill(inplace_<I> target, /* with */ V (*fun)(P)); - # ifndef OLN_INCLUDE_ONLY @@ -130,56 +116,44 @@ /// Facades. template <typename I> - void fill(Mutable_Image<I>& target, const oln_value(I)& value) + void fill(inplace_<I> target, const oln_value(I)& value) { - impl::fill_from_value_(exact(target), value); + impl::fill_from_value_(target.unwrap(), value); } template <typename I, typename J> - void fill(Mutable_Image<I>& target, const Image<J>& data) + void fill(inplace_<I> target, const Image<J>& data) { assert_same_grid_<I, J>::check(); - precondition(target.points() <= data.points()); - impl::fill_from_image_(exact(target), exact(data)); + precondition(target.unwrap().points() <= data.points()); + impl::fill_from_image_(target.unwrap(), exact(data)); } template <typename I, typename F> - void fill(Mutable_Image<I>& target, const Function_p2v<F>& fun) + void fill(inplace_<I> target, const Function_p2v<F>& fun) { - impl::fill_from_function_(exact(target), exact(fun)); + typedef mlc_basic(oln_argument(F)) P; + mlc::assert_< mlc_is_a(P, Point) >::check(); // FIXME: Add err msg. + // FIXME: Check also the value type. + impl::fill_from_function_(target.unwrap(), exact(fun)); } template <typename I, typename V, typename P> - void fill(Mutable_Image<I>& target, V (*f)(P)) + void fill(inplace_<I> target, V (*f)(P)) { mlc::assert_< mlc_is_a(P, Point) >::check(); // FIXME: Add err msg. - impl::fill_from_function_(exact(target), functorize_p2v(f)); + // FIXME: Check also the value type. + impl::fill_from_function_(target.unwrap(), functorize_p2v(f)); } - // with inplace_<I> - - template <typename I> - void fill(inplace_<I> target, const oln_value(I)& value) - { - fill(target.unwrap(), value); - } - template <typename I, typename J> - void fill(inplace_<I> target, const Image<J>& data) - { - fill(target.unwrap(), data); - } - template <typename I, typename F> - void fill(inplace_<I> target, const Function_p2v<F>& fun) - { - fill(target.unwrap(), fun); - } + /// Guard. - template <typename I, typename V, typename P> - void fill(inplace_<I> target, V (*fun)(P)) + template <typename I, typename T> + void fill(const Image<I>&, const T&) { - fill(target.unwrap(), fun); + mlc::abort_<I>::check(); // FIXME: Add err msg. } # endif // ! OLN_INCLUDE_ONLY Index: oln/level/clone.hh --- oln/level/clone.hh (revision 948) +++ oln/level/clone.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 EPITA Research and -// Development Laboratory +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 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 Index: oln/level/apply_inplace.hh --- oln/level/apply_inplace.hh (revision 948) +++ oln/level/apply_inplace.hh (working copy) @@ -80,27 +80,26 @@ /// Facades. template <typename F, typename I> - void apply_inplace(const Function_v2v<F>& f, Mutable_Image<I>& in_out) + void apply_inplace(const Function_v2v<F>& f, inplace_<I> in_out) { - impl::apply_inplace_(exact(f), exact(in_out)); + // FIXME: Add check. + impl::apply_inplace_(exact(f), in_out.unwrap()); } template <typename R, typename A, typename I> - void apply_inplace(R (*f)(A), Mutable_Image<I>& in_out) + void apply_inplace(R (*f)(A), inplace_<I> in_out) { - impl::apply_inplace_(functorize_v2v(f), exact(in_out)); + // FIXME: Add check. + impl::apply_inplace_(functorize_v2v(f), in_out.unwrap()); } - template <typename F, typename I> - void apply_inplace(const Function_v2v<F>& f, inplace_<I> in_out) - { - apply_inplace(f, in_out.unwrap()); - } - template <typename R, typename A, typename I> - void apply_inplace(R (*f)(A), inplace_<I> in_out) + /// Guard. + + template <typename T, typename I> + void apply_inplace(const T&, const Image<I>&) { - apply_inplace(f, in_out.unwrap()); + mlc::abort_<I>::check(); // FIXME: Add err msg. } # endif // ! OLN_INCLUDE_ONLY