https://svn.lrde.epita.fr/svn/oln/trunk/olena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)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